Skip to content

Commit 181cf10

Browse files
committed
wip
1 parent 38ab317 commit 181cf10

7 files changed

Lines changed: 436 additions & 302 deletions

File tree

apps/dashboard/public/rayforce.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/dashboard/public/rayforce.umd.js

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* </script>
1414
*/
1515

16-
(function(root, factory) {
16+
(function (root, factory) {
1717
if (typeof define === 'function' && define.amd) {
1818
// AMD
1919
define([], factory);
@@ -24,7 +24,7 @@
2424
// Browser global
2525
root.Rayforce = factory();
2626
}
27-
}(typeof self !== 'undefined' ? self : this, function() {
27+
}(typeof self !== 'undefined' ? self : this, function () {
2828
'use strict';
2929

3030
// ============================================================================
@@ -229,12 +229,12 @@
229229
if (this._typedArray === null) {
230230
const ArrayType = TYPED_ARRAY_MAP[this._elementType];
231231
if (!ArrayType) throw new Error(`No TypedArray for type ${this._elementType}`);
232-
232+
233233
const dataPtr = this._sdk._getDataPtr(this._ptr);
234234
const byteSize = this._sdk._getDataByteSize(this._ptr);
235235
const elementSize = ELEMENT_SIZES[this._elementType];
236236
const length = byteSize / elementSize;
237-
237+
238238
this._typedArray = new ArrayType(this._sdk._wasm.HEAPU8.buffer, dataPtr, length);
239239
}
240240
return this._typedArray;
@@ -326,12 +326,12 @@
326326
class Dict extends RayObject {
327327
keys() { return this._sdk._wrapPtr(this._sdk._dictKeys(this._ptr)); }
328328
values() { return this._sdk._wrapPtr(this._sdk._dictVals(this._ptr)); }
329-
329+
330330
get(key) {
331331
const keyObj = typeof key === 'string' ? this._sdk.symbol(key) : key;
332332
return this._sdk._wrapPtr(this._sdk._dictGet(this._ptr, keyObj._ptr));
333333
}
334-
334+
335335
has(key) { return !this.get(key).isNull; }
336336

337337
toJS() {
@@ -360,7 +360,7 @@
360360

361361
class Table extends RayObject {
362362
columns() { return this._sdk._wrapPtr(this._sdk._tableKeys(this._ptr)); }
363-
363+
364364
columnNames() {
365365
const cols = this.columns();
366366
const names = [];
@@ -450,11 +450,11 @@
450450
le(value) { return this._binOp('<=', value); }
451451
gt(value) { return this._binOp('>', value); }
452452
ge(value) { return this._binOp('>=', value); }
453-
453+
454454
and(other) { return this._logicOp('and', other); }
455455
or(other) { return this._logicOp('or', other); }
456456
not() { return new Expr(this._sdk, ['(not', ...this._parts, ')']); }
457-
457+
458458
sum() { return new Expr(this._sdk, ['(sum', ...this._parts, ')']); }
459459
avg() { return new Expr(this._sdk, ['(avg', ...this._parts, ')']); }
460460
min() { return new Expr(this._sdk, ['(min', ...this._parts, ')']); }
@@ -463,22 +463,22 @@
463463
first() { return new Expr(this._sdk, ['(first', ...this._parts, ')']); }
464464
last() { return new Expr(this._sdk, ['(last', ...this._parts, ')']); }
465465
distinct() { return new Expr(this._sdk, ['(distinct', ...this._parts, ')']); }
466-
466+
467467
_binOp(op, value) {
468468
const valStr = this._valueToStr(value);
469469
return new Expr(this._sdk, [`(${op}`, ...this._parts, valStr, ')']);
470470
}
471-
471+
472472
_logicOp(op, other) {
473473
return new Expr(this._sdk, [`(${op}`, ...this._parts, ...other._parts, ')']);
474474
}
475-
475+
476476
_valueToStr(value) {
477477
if (value instanceof Expr) return value.toString();
478478
if (typeof value === 'string') return `"${value}"`;
479479
return String(value);
480480
}
481-
481+
482482
toString() { return this._parts.join(' '); }
483483
}
484484

@@ -564,26 +564,26 @@
564564

565565
_setupBindings() {
566566
const w = this._wasm;
567-
567+
568568
this._evalCmd = w.cwrap('eval_cmd', 'number', ['string', 'string']);
569569
this._evalStr = w.cwrap('eval_str', 'number', ['string']);
570570
this._strOfObj = w.cwrap('strof_obj', 'string', ['number']);
571571
this._dropObj = w.cwrap('drop_obj', null, ['number']);
572572
this._cloneObj = w.cwrap('clone_obj', 'number', ['number']);
573573
this._versionStr = w.cwrap('version_str', 'string', []);
574-
574+
575575
this._getObjType = w.cwrap('get_obj_type', 'number', ['number']);
576576
this._getObjLen = w.cwrap('get_obj_len', 'number', ['number']);
577577
this._isObjAtom = w.cwrap('is_obj_atom', 'number', ['number']);
578578
this._isObjVector = w.cwrap('is_obj_vector', 'number', ['number']);
579579
this._isObjNull = w.cwrap('is_obj_null', 'number', ['number']);
580580
this._isObjError = w.cwrap('is_obj_error', 'number', ['number']);
581581
this._getObjRc = w.cwrap('get_obj_rc', 'number', ['number']);
582-
582+
583583
this._getDataPtr = w.cwrap('get_data_ptr', 'number', ['number']);
584584
this._getElementSize = w.cwrap('get_element_size', 'number', ['number']);
585585
this._getDataByteSize = w.cwrap('get_data_byte_size', 'number', ['number']);
586-
586+
587587
this._initB8 = w.cwrap('init_b8', 'number', ['number']);
588588
this._initU8 = w.cwrap('init_u8', 'number', ['number']);
589589
this._initC8 = w.cwrap('init_c8', 'number', ['number']);
@@ -596,7 +596,7 @@
596596
this._initTimestamp = w.cwrap('init_timestamp', 'number', ['number']);
597597
this._initSymbolStr = w.cwrap('init_symbol_str', 'number', ['string', 'number']);
598598
this._initStringStr = w.cwrap('init_string_str', 'number', ['string', 'number']);
599-
599+
600600
this._readB8 = w.cwrap('read_b8', 'number', ['number']);
601601
this._readU8 = w.cwrap('read_u8', 'number', ['number']);
602602
this._readC8 = w.cwrap('read_c8', 'number', ['number']);
@@ -609,32 +609,34 @@
609609
this._readTimestamp = w.cwrap('read_timestamp', 'number', ['number']);
610610
this._readSymbolId = w.cwrap('read_symbol_id', 'number', ['number']);
611611
this._symbolToStr = w.cwrap('symbol_to_str', 'string', ['number']);
612-
612+
// Change signature to number (ptr) to handle manual heap allocation
613+
this._readCSV = w.cwrap('read_csv', 'number', ['number', 'number']);
614+
613615
this._initVector = w.cwrap('init_vector', 'number', ['number', 'number']);
614616
this._initList = w.cwrap('init_list', 'number', ['number']);
615617
this._vecAtIdx = w.cwrap('vec_at_idx', 'number', ['number', 'number']);
616618
this._atIdx = w.cwrap('at_idx', 'number', ['number', 'number']);
617619
this._atObj = w.cwrap('at_obj', 'number', ['number', 'number']);
618620
this._pushObj = w.cwrap('push_obj', 'number', ['number', 'number']);
619621
this._insObj = w.cwrap('ins_obj', 'number', ['number', 'number', 'number']);
620-
622+
621623
this._initDict = w.cwrap('init_dict', 'number', ['number', 'number']);
622624
this._dictKeys = w.cwrap('dict_keys', 'number', ['number']);
623625
this._dictVals = w.cwrap('dict_vals', 'number', ['number']);
624626
this._dictGet = w.cwrap('dict_get', 'number', ['number', 'number']);
625-
627+
626628
this._initTable = w.cwrap('init_table', 'number', ['number', 'number']);
627629
this._tableKeys = w.cwrap('table_keys', 'number', ['number']);
628630
this._tableVals = w.cwrap('table_vals', 'number', ['number']);
629631
this._tableCol = w.cwrap('table_col', 'number', ['number', 'string', 'number']);
630632
this._tableRow = w.cwrap('table_row', 'number', ['number', 'number']);
631633
this._tableCount = w.cwrap('table_count', 'number', ['number']);
632-
634+
633635
this._querySelect = w.cwrap('query_select', 'number', ['number']);
634636
this._queryUpdate = w.cwrap('query_update', 'number', ['number']);
635637
this._tableInsert = w.cwrap('table_insert', 'number', ['number', 'number']);
636638
this._tableUpsert = w.cwrap('table_upsert', 'number', ['number', 'number', 'number']);
637-
639+
638640
this._internSymbol = w.cwrap('intern_symbol', 'number', ['string', 'number']);
639641
this._globalSet = w.cwrap('global_set', null, ['number', 'number']);
640642
this._quoteObj = w.cwrap('quote_obj', 'number', ['number']);
@@ -655,14 +657,14 @@
655657

656658
_wrapPtr(ptr) {
657659
if (ptr === 0) return new RayNull(this, 0);
658-
660+
659661
const type = this._getObjType(ptr);
660662
const isAtom = this._isObjAtom(ptr);
661663
const absType = type < 0 ? -type : type;
662-
664+
663665
if (type === Types.ERR) return new RayError(this, ptr);
664666
if (type === Types.NULL || this._isObjNull(ptr)) return new RayNull(this, ptr);
665-
667+
666668
if (isAtom) {
667669
switch (absType) {
668670
case Types.B8: return new B8(this, ptr);
@@ -680,7 +682,7 @@
680682
default: return new RayObject(this, ptr);
681683
}
682684
}
683-
685+
684686
switch (type) {
685687
case Types.C8: return new RayString(this, ptr);
686688
case Types.LIST: return new List(this, ptr);
@@ -701,7 +703,7 @@
701703
i32(value) { return new I32(this, this._initI32(value | 0)); }
702704
i64(value) { return new I64(this, this._initI64(Number(value))); }
703705
f64(value) { return new F64(this, this._initF64(value)); }
704-
706+
705707
date(value) {
706708
let days;
707709
if (value instanceof Date) {
@@ -712,18 +714,18 @@
712714
}
713715
return new RayDate(this, this._initDate(days));
714716
}
715-
717+
716718
time(value) {
717719
let ms;
718720
if (value instanceof Date) {
719-
ms = value.getHours() * 3600000 + value.getMinutes() * 60000 +
720-
value.getSeconds() * 1000 + value.getMilliseconds();
721+
ms = value.getHours() * 3600000 + value.getMinutes() * 60000 +
722+
value.getSeconds() * 1000 + value.getMilliseconds();
721723
} else {
722724
ms = value | 0;
723725
}
724726
return new RayTime(this, this._initTime(ms));
725727
}
726-
728+
727729
timestamp(value) {
728730
let ns;
729731
if (value instanceof Date) {
@@ -734,10 +736,10 @@
734736
}
735737
return new RayTimestamp(this, this._initTimestamp(ns));
736738
}
737-
739+
738740
symbol(value) { return new RaySymbol(this, this._initSymbolStr(value, value.length)); }
739741
string(value) { return new RayString(this, this._initStringStr(value, value.length)); }
740-
742+
741743
vector(type, lengthOrData) {
742744
if (Array.isArray(lengthOrData)) {
743745
const arr = lengthOrData;
@@ -754,7 +756,7 @@
754756
}
755757
return new Vector(this, this._initVector(type, lengthOrData), type);
756758
}
757-
759+
758760
list(items) {
759761
const len = items ? items.length : 0;
760762
const list = new List(this, this._initList(len));
@@ -765,7 +767,7 @@
765767
}
766768
return list;
767769
}
768-
770+
769771
dict(obj) {
770772
const keys = Object.keys(obj);
771773
const keyVec = this.vector(Types.SYMBOL, keys.length);
@@ -776,7 +778,7 @@
776778
const valList = this.list(Object.values(obj).map(v => this._toRayObject(v)));
777779
return new Dict(this, this._initDict(keyVec._ptr, valList._ptr));
778780
}
779-
781+
780782
table(columns) {
781783
const colNames = Object.keys(columns);
782784
const keyVec = this.vector(Types.SYMBOL, colNames.length);
@@ -790,23 +792,23 @@
790792
}
791793
return new Table(this, this._initTable(keyVec._ptr, valList._ptr));
792794
}
793-
795+
794796
_arrayToVector(arr) {
795797
if (arr.length === 0) return this.vector(Types.I64, 0);
796-
798+
797799
const first = arr[0];
798800
let type;
799-
801+
800802
if (typeof first === 'boolean') type = Types.B8;
801803
else if (typeof first === 'number') type = Number.isInteger(first) ? Types.I64 : Types.F64;
802804
else if (typeof first === 'bigint') type = Types.I64;
803805
else if (typeof first === 'string') type = Types.SYMBOL;
804806
else if (first instanceof Date) type = Types.TIMESTAMP;
805807
else return this.list(arr.map(v => this._toRayObject(v)));
806-
808+
807809
const vec = this.vector(type, arr.length);
808810
const view = vec.typedArray;
809-
811+
810812
for (let i = 0; i < arr.length; i++) {
811813
if (type === Types.SYMBOL) {
812814
view[i] = BigInt(this._internSymbol(arr[i], arr[i].length));
@@ -823,10 +825,10 @@
823825
view[i] = arr[i];
824826
}
825827
}
826-
828+
827829
return vec;
828830
}
829-
831+
830832
_toRayObject(value) {
831833
if (value instanceof RayObject) return value;
832834
if (value === null || value === undefined) return new RayNull(this, 0);
@@ -839,17 +841,33 @@
839841
if (typeof value === 'object') return this.dict(value);
840842
return new RayNull(this, 0);
841843
}
842-
844+
843845
set(name, value) {
844846
const sym = this.symbol(name);
845847
const val = value instanceof RayObject ? value : this._toRayObject(value);
846848
this._globalSet(sym._ptr, val._ptr);
847849
}
848-
850+
849851
get(name) { return this.eval(name); }
850852
typeName(typeCode) { return this._getTypeName(typeCode); }
851-
853+
852854
col(name) { return Expr.col(this, name); }
855+
856+
read_csv(content) {
857+
if (typeof content !== 'string') throw new Error('Content must be a string');
858+
859+
// Manually allocate memory on WASM heap to avoid stack overflow with large CSVs
860+
const lengthBytes = this._wasm.lengthBytesUTF8(content) + 1;
861+
const stringOnHeap = this._wasm._malloc(lengthBytes);
862+
863+
try {
864+
this._wasm.stringToUTF8(content, stringOnHeap, lengthBytes);
865+
// Pass pointer and length (excluding null terminator)
866+
return new Table(this, this._readCSV(stringOnHeap, lengthBytes - 1));
867+
} finally {
868+
this._wasm._free(stringOnHeap);
869+
}
870+
}
853871
}
854872

855873
// ============================================================================
@@ -869,7 +887,7 @@
869887
try {
870888
// For browser usage, we need to load the WASM module
871889
let createRayforce;
872-
890+
873891
if (typeof window !== 'undefined') {
874892
// Browser environment - expect global createRayforce or load via script
875893
if (typeof window.createRayforce === 'function') {
@@ -884,7 +902,7 @@
884902
const module = await import(wasmPath);
885903
createRayforce = module.default;
886904
}
887-
905+
888906
const wasm = await createRayforce({
889907
rayforce_ready: (msg) => { if (onReady) onReady(msg); }
890908
});
1.01 KB
Binary file not shown.

0 commit comments

Comments
 (0)