@ahsankhanamu/json-transformer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/ast.d.ts +259 -0
  2. package/dist/ast.d.ts.map +1 -0
  3. package/dist/ast.js +12 -0
  4. package/dist/ast.js.map +1 -0
  5. package/dist/codegen/base.d.ts +83 -0
  6. package/dist/codegen/base.d.ts.map +1 -0
  7. package/dist/codegen/base.js +494 -0
  8. package/dist/codegen/base.js.map +1 -0
  9. package/dist/codegen/index.d.ts +35 -0
  10. package/dist/codegen/index.d.ts.map +1 -0
  11. package/dist/codegen/index.js +42 -0
  12. package/dist/codegen/index.js.map +1 -0
  13. package/dist/codegen/library.d.ts +42 -0
  14. package/dist/codegen/library.d.ts.map +1 -0
  15. package/dist/codegen/library.js +406 -0
  16. package/dist/codegen/library.js.map +1 -0
  17. package/dist/codegen/native.d.ts +33 -0
  18. package/dist/codegen/native.d.ts.map +1 -0
  19. package/dist/codegen/native.js +452 -0
  20. package/dist/codegen/native.js.map +1 -0
  21. package/dist/codegen.d.ts +13 -0
  22. package/dist/codegen.d.ts.map +1 -0
  23. package/dist/codegen.js +12 -0
  24. package/dist/codegen.js.map +1 -0
  25. package/dist/index.d.ts +257 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +231 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/lexer.d.ts +37 -0
  30. package/dist/lexer.d.ts.map +1 -0
  31. package/dist/lexer.js +499 -0
  32. package/dist/lexer.js.map +1 -0
  33. package/dist/parser.d.ts +63 -0
  34. package/dist/parser.d.ts.map +1 -0
  35. package/dist/parser.js +1045 -0
  36. package/dist/parser.js.map +1 -0
  37. package/dist/playground.d.ts +6 -0
  38. package/dist/playground.d.ts.map +1 -0
  39. package/dist/playground.js +216 -0
  40. package/dist/playground.js.map +1 -0
  41. package/dist/runtime.d.ts +229 -0
  42. package/dist/runtime.d.ts.map +1 -0
  43. package/dist/runtime.js +933 -0
  44. package/dist/runtime.js.map +1 -0
  45. package/dist/tokens.d.ts +80 -0
  46. package/dist/tokens.d.ts.map +1 -0
  47. package/dist/tokens.js +88 -0
  48. package/dist/tokens.js.map +1 -0
  49. package/package.json +30 -0
@@ -0,0 +1,933 @@
1
+ /**
2
+ * JSON Transformer Runtime Helpers
3
+ * These functions are available during expression evaluation
4
+ */
5
+ export class TransformError extends Error {
6
+ code;
7
+ path;
8
+ expected;
9
+ actual;
10
+ suggestions;
11
+ value;
12
+ constructor(message, details = 'TRANSFORM_ERROR') {
13
+ super(message);
14
+ this.name = 'TransformError';
15
+ if (typeof details === 'string') {
16
+ this.code = details;
17
+ }
18
+ else {
19
+ this.code = details.code;
20
+ this.path = details.path;
21
+ this.expected = details.expected;
22
+ this.actual = details.actual;
23
+ this.suggestions = details.suggestions;
24
+ this.value = details.value;
25
+ }
26
+ }
27
+ toString() {
28
+ let msg = `TransformError: ${this.message}`;
29
+ if (this.path)
30
+ msg += `\n Path: ${this.path}`;
31
+ if (this.suggestions?.length) {
32
+ msg += `\n Did you mean: ${this.suggestions.join(', ')}?`;
33
+ }
34
+ return msg;
35
+ }
36
+ }
37
+ // =============================================================================
38
+ // STRICT MODE HELPERS
39
+ // =============================================================================
40
+ /**
41
+ * Calculate Levenshtein distance between two strings
42
+ */
43
+ function levenshteinDistance(a, b) {
44
+ const matrix = [];
45
+ for (let i = 0; i <= b.length; i++) {
46
+ matrix[i] = [i];
47
+ }
48
+ for (let j = 0; j <= a.length; j++) {
49
+ matrix[0][j] = j;
50
+ }
51
+ for (let i = 1; i <= b.length; i++) {
52
+ for (let j = 1; j <= a.length; j++) {
53
+ if (b[i - 1] === a[j - 1]) {
54
+ matrix[i][j] = matrix[i - 1][j - 1];
55
+ }
56
+ else {
57
+ matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
58
+ }
59
+ }
60
+ }
61
+ return matrix[b.length][a.length];
62
+ }
63
+ /**
64
+ * Find similar keys in an object (for "did you mean?" suggestions)
65
+ */
66
+ function findSimilarKeys(target, keys, maxDistance = 3) {
67
+ return keys
68
+ .map((key) => ({ key, distance: levenshteinDistance(target.toLowerCase(), key.toLowerCase()) }))
69
+ .filter(({ distance }) => distance <= maxDistance && distance > 0)
70
+ .sort((a, b) => a.distance - b.distance)
71
+ .slice(0, 3)
72
+ .map(({ key }) => key);
73
+ }
74
+ /**
75
+ * Get a readable type name
76
+ */
77
+ function getTypeName(value) {
78
+ if (value === null)
79
+ return 'null';
80
+ if (value === undefined)
81
+ return 'undefined';
82
+ if (Array.isArray(value))
83
+ return 'array';
84
+ return typeof value;
85
+ }
86
+ /**
87
+ * Strict mode: Access a property with validation
88
+ */
89
+ export function strictGet(obj, property, path) {
90
+ // Check if object is null/undefined
91
+ if (obj === null) {
92
+ throw new TransformError(`Cannot access property '${property}' of null`, {
93
+ code: 'NULL_ACCESS',
94
+ path,
95
+ actual: 'null',
96
+ });
97
+ }
98
+ if (obj === undefined) {
99
+ throw new TransformError(`Cannot access property '${property}' of undefined`, {
100
+ code: 'UNDEFINED_ACCESS',
101
+ path,
102
+ actual: 'undefined',
103
+ });
104
+ }
105
+ // Check if object is actually an object
106
+ if (typeof obj !== 'object') {
107
+ throw new TransformError(`Cannot access property '${property}' of ${getTypeName(obj)}`, {
108
+ code: 'INVALID_ACCESS',
109
+ path,
110
+ expected: 'object',
111
+ actual: getTypeName(obj),
112
+ });
113
+ }
114
+ const record = obj;
115
+ // Check if property exists
116
+ if (!(property in record)) {
117
+ const availableKeys = Object.keys(record);
118
+ const suggestions = findSimilarKeys(property, availableKeys);
119
+ let message = `Property '${property}' does not exist`;
120
+ if (path)
121
+ message += ` at path '${path}'`;
122
+ throw new TransformError(message, {
123
+ code: 'MISSING_PROPERTY',
124
+ path: path ? `${path}.${property}` : property,
125
+ suggestions: suggestions.length > 0 ? suggestions : undefined,
126
+ });
127
+ }
128
+ return record[property];
129
+ }
130
+ /**
131
+ * Strict mode: Access an array index with validation
132
+ */
133
+ export function strictIndex(arr, index, path) {
134
+ if (arr === null || arr === undefined) {
135
+ throw new TransformError(`Cannot access index [${index}] of ${getTypeName(arr)}`, {
136
+ code: 'NULL_INDEX',
137
+ path,
138
+ actual: getTypeName(arr),
139
+ });
140
+ }
141
+ if (!Array.isArray(arr)) {
142
+ throw new TransformError(`Cannot access index [${index}] - value is not an array`, {
143
+ code: 'NOT_ARRAY',
144
+ path,
145
+ expected: 'array',
146
+ actual: getTypeName(arr),
147
+ });
148
+ }
149
+ // Handle negative indices
150
+ const actualIndex = index < 0 ? arr.length + index : index;
151
+ if (actualIndex < 0 || actualIndex >= arr.length) {
152
+ throw new TransformError(`Array index ${index} is out of bounds (array length: ${arr.length})`, {
153
+ code: 'INDEX_OUT_OF_BOUNDS',
154
+ path: `${path}[${index}]`,
155
+ value: arr.length,
156
+ });
157
+ }
158
+ return arr[actualIndex];
159
+ }
160
+ /**
161
+ * Strict mode: Ensure value is an array
162
+ */
163
+ export function strictArray(value, path) {
164
+ if (value === null || value === undefined) {
165
+ throw new TransformError(`Expected array but got ${getTypeName(value)}`, {
166
+ code: 'NULL_ARRAY',
167
+ path,
168
+ expected: 'array',
169
+ actual: getTypeName(value),
170
+ });
171
+ }
172
+ if (!Array.isArray(value)) {
173
+ throw new TransformError(`Expected array but got ${getTypeName(value)}`, {
174
+ code: 'NOT_ARRAY',
175
+ path,
176
+ expected: 'array',
177
+ actual: getTypeName(value),
178
+ });
179
+ }
180
+ return value;
181
+ }
182
+ /**
183
+ * Strict mode: Validate a value is not null/undefined
184
+ */
185
+ export function strictNonNull(value, path, message) {
186
+ if (value === null || value === undefined) {
187
+ throw new TransformError(message ?? `Value at '${path}' is ${getTypeName(value)}`, {
188
+ code: 'NULL_VALUE',
189
+ path,
190
+ actual: getTypeName(value),
191
+ });
192
+ }
193
+ return value;
194
+ }
195
+ /**
196
+ * Strict mode: Validate type
197
+ */
198
+ export function strictType(value, expectedType, path) {
199
+ const actualType = getTypeName(value);
200
+ if (expectedType === 'any')
201
+ return value;
202
+ if (actualType !== expectedType) {
203
+ throw new TransformError(`Type mismatch at '${path}': expected ${expectedType}, got ${actualType}`, { code: 'TYPE_MISMATCH', path, expected: expectedType, actual: actualType });
204
+ }
205
+ return value;
206
+ }
207
+ /**
208
+ * Strict mode: Safe filter with validation
209
+ */
210
+ export function strictFilter(arr, predicate, path) {
211
+ const validArray = strictArray(arr, path);
212
+ return validArray.filter(predicate);
213
+ }
214
+ /**
215
+ * Strict mode: Safe map with validation
216
+ */
217
+ export function strictMap(arr, mapper, path) {
218
+ const validArray = strictArray(arr, path);
219
+ return validArray.map(mapper);
220
+ }
221
+ // =============================================================================
222
+ // STRING FUNCTIONS
223
+ // =============================================================================
224
+ export function upper(s) {
225
+ if (s == null)
226
+ return '';
227
+ return String(s).toUpperCase();
228
+ }
229
+ export function lower(s) {
230
+ if (s == null)
231
+ return '';
232
+ return String(s).toLowerCase();
233
+ }
234
+ export function trim(s) {
235
+ if (s == null)
236
+ return '';
237
+ return String(s).trim();
238
+ }
239
+ export function split(s, delimiter = ',') {
240
+ if (s == null)
241
+ return [];
242
+ return String(s).split(delimiter);
243
+ }
244
+ export function join(arr, delimiter = ',') {
245
+ if (!Array.isArray(arr))
246
+ return '';
247
+ return arr.join(delimiter);
248
+ }
249
+ export function substring(s, start, end) {
250
+ if (s == null)
251
+ return '';
252
+ return String(s).substring(start, end);
253
+ }
254
+ export function replace(s, search, replacement) {
255
+ if (s == null)
256
+ return '';
257
+ return String(s).replace(search, replacement);
258
+ }
259
+ export function replaceAll(s, search, replacement) {
260
+ if (s == null)
261
+ return '';
262
+ return String(s).replaceAll(search, replacement);
263
+ }
264
+ export function matches(s, pattern) {
265
+ if (s == null)
266
+ return false;
267
+ return new RegExp(pattern).test(String(s));
268
+ }
269
+ export function startsWith(s, prefix) {
270
+ if (s == null)
271
+ return false;
272
+ return String(s).startsWith(prefix);
273
+ }
274
+ export function endsWith(s, suffix) {
275
+ if (s == null)
276
+ return false;
277
+ return String(s).endsWith(suffix);
278
+ }
279
+ export function contains(s, search) {
280
+ if (s == null)
281
+ return false;
282
+ return String(s).includes(search);
283
+ }
284
+ export function padStart(s, length, char = ' ') {
285
+ if (s == null)
286
+ return '';
287
+ return String(s).padStart(length, char);
288
+ }
289
+ export function padEnd(s, length, char = ' ') {
290
+ if (s == null)
291
+ return '';
292
+ return String(s).padEnd(length, char);
293
+ }
294
+ export function capitalize(s) {
295
+ if (s == null)
296
+ return '';
297
+ const str = String(s);
298
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
299
+ }
300
+ export function camelCase(s) {
301
+ if (s == null)
302
+ return '';
303
+ return String(s)
304
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
305
+ .replace(/^(.)/, (c) => c.toLowerCase());
306
+ }
307
+ export function snakeCase(s) {
308
+ if (s == null)
309
+ return '';
310
+ return String(s)
311
+ .replace(/([A-Z])/g, '_$1')
312
+ .replace(/[-\s]+/g, '_')
313
+ .toLowerCase()
314
+ .replace(/^_/, '');
315
+ }
316
+ export function kebabCase(s) {
317
+ if (s == null)
318
+ return '';
319
+ return String(s)
320
+ .replace(/([A-Z])/g, '-$1')
321
+ .replace(/[_\s]+/g, '-')
322
+ .toLowerCase()
323
+ .replace(/^-/, '');
324
+ }
325
+ // =============================================================================
326
+ // NUMBER FUNCTIONS
327
+ // =============================================================================
328
+ export function round(n, decimals = 0) {
329
+ if (n == null)
330
+ return 0;
331
+ const num = Number(n);
332
+ if (isNaN(num))
333
+ return 0;
334
+ const factor = Math.pow(10, decimals);
335
+ return Math.round(num * factor) / factor;
336
+ }
337
+ export function floor(n) {
338
+ if (n == null)
339
+ return 0;
340
+ const num = Number(n);
341
+ return isNaN(num) ? 0 : Math.floor(num);
342
+ }
343
+ export function ceil(n) {
344
+ if (n == null)
345
+ return 0;
346
+ const num = Number(n);
347
+ return isNaN(num) ? 0 : Math.ceil(num);
348
+ }
349
+ export function abs(n) {
350
+ if (n == null)
351
+ return 0;
352
+ const num = Number(n);
353
+ return isNaN(num) ? 0 : Math.abs(num);
354
+ }
355
+ export function min(...values) {
356
+ const nums = values
357
+ .flat()
358
+ .map(Number)
359
+ .filter((n) => !isNaN(n));
360
+ return nums.length ? Math.min(...nums) : 0;
361
+ }
362
+ export function max(...values) {
363
+ const nums = values
364
+ .flat()
365
+ .map(Number)
366
+ .filter((n) => !isNaN(n));
367
+ return nums.length ? Math.max(...nums) : 0;
368
+ }
369
+ export function clamp(n, minVal, maxVal) {
370
+ if (n == null)
371
+ return minVal;
372
+ const num = Number(n);
373
+ if (isNaN(num))
374
+ return minVal;
375
+ return Math.min(Math.max(num, minVal), maxVal);
376
+ }
377
+ export function random(min = 0, max = 1) {
378
+ return Math.random() * (max - min) + min;
379
+ }
380
+ export function randomInt(min = 0, max = 100) {
381
+ return Math.floor(Math.random() * (max - min + 1)) + min;
382
+ }
383
+ // =============================================================================
384
+ // ARRAY FUNCTIONS
385
+ // =============================================================================
386
+ export function sum(arr) {
387
+ if (!Array.isArray(arr))
388
+ return 0;
389
+ return arr.reduce((acc, val) => acc + (Number(val) || 0), 0);
390
+ }
391
+ export function avg(arr) {
392
+ if (!Array.isArray(arr) || arr.length === 0)
393
+ return 0;
394
+ return sum(arr) / arr.length;
395
+ }
396
+ export function count(arr) {
397
+ if (!Array.isArray(arr))
398
+ return 0;
399
+ return arr.length;
400
+ }
401
+ export function map(arr, fn) {
402
+ if (!Array.isArray(arr))
403
+ return [];
404
+ return arr.map(fn);
405
+ }
406
+ export function filter(arr, fn) {
407
+ if (!Array.isArray(arr))
408
+ return [];
409
+ return arr.filter(fn);
410
+ }
411
+ export function find(arr, fn) {
412
+ if (!Array.isArray(arr))
413
+ return undefined;
414
+ return arr.find(fn);
415
+ }
416
+ export function some(arr, fn) {
417
+ if (!Array.isArray(arr))
418
+ return false;
419
+ return arr.some(fn);
420
+ }
421
+ export function every(arr, fn) {
422
+ if (!Array.isArray(arr))
423
+ return true;
424
+ return arr.every(fn);
425
+ }
426
+ export function reduce(arr, fn, initial) {
427
+ if (!Array.isArray(arr))
428
+ return initial;
429
+ return arr.reduce(fn, initial);
430
+ }
431
+ export function first(arr) {
432
+ if (!Array.isArray(arr))
433
+ return undefined;
434
+ return arr[0];
435
+ }
436
+ export function last(arr) {
437
+ if (!Array.isArray(arr))
438
+ return undefined;
439
+ return arr[arr.length - 1];
440
+ }
441
+ export function unique(arr) {
442
+ if (!Array.isArray(arr))
443
+ return [];
444
+ return [...new Set(arr)];
445
+ }
446
+ export function flatten(arr) {
447
+ if (!Array.isArray(arr))
448
+ return [];
449
+ return arr.flat();
450
+ }
451
+ export function reverse(arr) {
452
+ if (!Array.isArray(arr))
453
+ return [];
454
+ return [...arr].reverse();
455
+ }
456
+ export function sort(arr, key) {
457
+ if (!Array.isArray(arr))
458
+ return [];
459
+ const sorted = [...arr];
460
+ if (key === undefined) {
461
+ return sorted.sort();
462
+ }
463
+ if (typeof key === 'string') {
464
+ // Support nested paths like "meta.priority"
465
+ const getNestedValue = (obj, path) => {
466
+ const keys = path.split('.');
467
+ let current = obj;
468
+ for (const k of keys) {
469
+ if (current == null || typeof current !== 'object')
470
+ return undefined;
471
+ current = current[k];
472
+ }
473
+ return current;
474
+ };
475
+ return sorted.sort((a, b) => {
476
+ const aVal = getNestedValue(a, key);
477
+ const bVal = getNestedValue(b, key);
478
+ if (aVal == null && bVal == null)
479
+ return 0;
480
+ if (aVal == null)
481
+ return 1;
482
+ if (bVal == null)
483
+ return -1;
484
+ if (aVal < bVal)
485
+ return -1;
486
+ if (aVal > bVal)
487
+ return 1;
488
+ return 0;
489
+ });
490
+ }
491
+ return sorted.sort((a, b) => {
492
+ const aVal = key(a);
493
+ const bVal = key(b);
494
+ if (aVal == null && bVal == null)
495
+ return 0;
496
+ if (aVal == null)
497
+ return 1;
498
+ if (bVal == null)
499
+ return -1;
500
+ if (aVal < bVal)
501
+ return -1;
502
+ if (aVal > bVal)
503
+ return 1;
504
+ return 0;
505
+ });
506
+ }
507
+ export function sortDesc(arr, key) {
508
+ return sort(arr, key).reverse();
509
+ }
510
+ export function groupBy(arr, key) {
511
+ if (!Array.isArray(arr))
512
+ return {};
513
+ // Support nested paths like "meta.priority"
514
+ const getValue = (obj, path) => {
515
+ const keys = path.split('.');
516
+ let current = obj;
517
+ for (const k of keys) {
518
+ if (current == null || typeof current !== 'object')
519
+ return undefined;
520
+ current = current[k];
521
+ }
522
+ return current;
523
+ };
524
+ return arr.reduce((acc, item) => {
525
+ const groupKey = typeof key === 'string' ? String(getValue(item, key)) : key(item);
526
+ if (!acc[groupKey])
527
+ acc[groupKey] = [];
528
+ acc[groupKey].push(item);
529
+ return acc;
530
+ }, {});
531
+ }
532
+ export function keyBy(arr, key) {
533
+ if (!Array.isArray(arr))
534
+ return {};
535
+ // Support nested paths like "meta.id"
536
+ const getValue = (obj, path) => {
537
+ const keys = path.split('.');
538
+ let current = obj;
539
+ for (const k of keys) {
540
+ if (current == null || typeof current !== 'object')
541
+ return undefined;
542
+ current = current[k];
543
+ }
544
+ return current;
545
+ };
546
+ return arr.reduce((acc, item) => {
547
+ const k = typeof key === 'string' ? String(getValue(item, key)) : key(item);
548
+ acc[k] = item;
549
+ return acc;
550
+ }, {});
551
+ }
552
+ export function zip(arr1, arr2) {
553
+ if (!Array.isArray(arr1) || !Array.isArray(arr2))
554
+ return [];
555
+ const len = Math.min(arr1.length, arr2.length);
556
+ const result = [];
557
+ for (let i = 0; i < len; i++) {
558
+ result.push([arr1[i], arr2[i]]);
559
+ }
560
+ return result;
561
+ }
562
+ export function compact(arr) {
563
+ if (!Array.isArray(arr))
564
+ return [];
565
+ return arr.filter((x) => x != null);
566
+ }
567
+ export function take(arr, n) {
568
+ if (!Array.isArray(arr))
569
+ return [];
570
+ return arr.slice(0, n);
571
+ }
572
+ export function drop(arr, n) {
573
+ if (!Array.isArray(arr))
574
+ return [];
575
+ return arr.slice(n);
576
+ }
577
+ export function range(start, end, step = 1) {
578
+ if (end === undefined) {
579
+ end = start;
580
+ start = 0;
581
+ }
582
+ const result = [];
583
+ for (let i = start; step > 0 ? i < end : i > end; i += step) {
584
+ result.push(i);
585
+ }
586
+ return result;
587
+ }
588
+ // =============================================================================
589
+ // OBJECT FUNCTIONS
590
+ // =============================================================================
591
+ export function keys(obj) {
592
+ if (obj == null || typeof obj !== 'object')
593
+ return [];
594
+ return Object.keys(obj);
595
+ }
596
+ export function values(obj) {
597
+ if (obj == null || typeof obj !== 'object')
598
+ return [];
599
+ return Object.values(obj);
600
+ }
601
+ export function entries(obj) {
602
+ if (obj == null || typeof obj !== 'object')
603
+ return [];
604
+ return Object.entries(obj);
605
+ }
606
+ export function merge(...objects) {
607
+ return Object.assign({}, ...objects.filter((o) => o != null && typeof o === 'object'));
608
+ }
609
+ export function pick(obj, ...keys) {
610
+ if (obj == null || typeof obj !== 'object')
611
+ return {};
612
+ const result = {};
613
+ for (const key of keys.flat()) {
614
+ if (key in obj) {
615
+ result[key] = obj[key];
616
+ }
617
+ }
618
+ return result;
619
+ }
620
+ export function omit(obj, ...keys) {
621
+ if (obj == null || typeof obj !== 'object')
622
+ return {};
623
+ const keySet = new Set(keys.flat());
624
+ const result = {};
625
+ for (const [key, value] of Object.entries(obj)) {
626
+ if (!keySet.has(key)) {
627
+ result[key] = value;
628
+ }
629
+ }
630
+ return result;
631
+ }
632
+ export function get(obj, path, defaultValue) {
633
+ if (obj == null)
634
+ return defaultValue;
635
+ const keys = path.split('.');
636
+ let current = obj;
637
+ for (const key of keys) {
638
+ if (current == null || typeof current !== 'object') {
639
+ return defaultValue;
640
+ }
641
+ current = current[key];
642
+ }
643
+ return current ?? defaultValue;
644
+ }
645
+ export function set(obj, path, value) {
646
+ if (obj == null || typeof obj !== 'object')
647
+ return {};
648
+ const result = { ...obj };
649
+ const keys = path.split('.');
650
+ let current = result;
651
+ for (let i = 0; i < keys.length - 1; i++) {
652
+ const key = keys[i];
653
+ if (!(key in current) || typeof current[key] !== 'object') {
654
+ current[key] = {};
655
+ }
656
+ else {
657
+ current[key] = { ...current[key] };
658
+ }
659
+ current = current[key];
660
+ }
661
+ current[keys[keys.length - 1]] = value;
662
+ return result;
663
+ }
664
+ // =============================================================================
665
+ // TYPE FUNCTIONS
666
+ // =============================================================================
667
+ export function type(value) {
668
+ if (value === null)
669
+ return 'null';
670
+ if (Array.isArray(value))
671
+ return 'array';
672
+ return typeof value;
673
+ }
674
+ export function isString(value) {
675
+ return typeof value === 'string';
676
+ }
677
+ export function isNumber(value) {
678
+ return typeof value === 'number' && !isNaN(value);
679
+ }
680
+ export function isBoolean(value) {
681
+ return typeof value === 'boolean';
682
+ }
683
+ export function isArray(value) {
684
+ return Array.isArray(value);
685
+ }
686
+ export function isObject(value) {
687
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
688
+ }
689
+ export function isNull(value) {
690
+ return value === null;
691
+ }
692
+ export function isUndefined(value) {
693
+ return value === undefined;
694
+ }
695
+ export function isEmpty(value) {
696
+ if (value == null)
697
+ return true;
698
+ if (typeof value === 'string')
699
+ return value.length === 0;
700
+ if (Array.isArray(value))
701
+ return value.length === 0;
702
+ if (typeof value === 'object')
703
+ return Object.keys(value).length === 0;
704
+ return false;
705
+ }
706
+ // =============================================================================
707
+ // CONVERSION FUNCTIONS
708
+ // =============================================================================
709
+ export function toString(value) {
710
+ if (value == null)
711
+ return '';
712
+ if (typeof value === 'object')
713
+ return JSON.stringify(value);
714
+ return String(value);
715
+ }
716
+ export function toNumber(value) {
717
+ if (value == null)
718
+ return 0;
719
+ const num = Number(value);
720
+ return isNaN(num) ? 0 : num;
721
+ }
722
+ export function toBoolean(value) {
723
+ return Boolean(value);
724
+ }
725
+ export function toArray(value) {
726
+ if (value == null)
727
+ return [];
728
+ if (Array.isArray(value))
729
+ return value;
730
+ return [value];
731
+ }
732
+ export function toJSON(value) {
733
+ return JSON.stringify(value);
734
+ }
735
+ export function fromJSON(value) {
736
+ try {
737
+ return JSON.parse(value);
738
+ }
739
+ catch {
740
+ return null;
741
+ }
742
+ }
743
+ // =============================================================================
744
+ // DATE FUNCTIONS
745
+ // =============================================================================
746
+ export function now() {
747
+ return new Date();
748
+ }
749
+ export function today() {
750
+ return new Date().toISOString().split('T')[0];
751
+ }
752
+ export function formatDate(date, format = 'YYYY-MM-DD') {
753
+ const d = date instanceof Date ? date : new Date(String(date));
754
+ if (isNaN(d.getTime()))
755
+ return '';
756
+ const year = d.getFullYear();
757
+ const month = String(d.getMonth() + 1).padStart(2, '0');
758
+ const day = String(d.getDate()).padStart(2, '0');
759
+ const hours = String(d.getHours()).padStart(2, '0');
760
+ const minutes = String(d.getMinutes()).padStart(2, '0');
761
+ const seconds = String(d.getSeconds()).padStart(2, '0');
762
+ return format
763
+ .replace('YYYY', String(year))
764
+ .replace('MM', month)
765
+ .replace('DD', day)
766
+ .replace('HH', hours)
767
+ .replace('mm', minutes)
768
+ .replace('ss', seconds);
769
+ }
770
+ export function parseDate(value) {
771
+ if (value == null)
772
+ return null;
773
+ const d = new Date(String(value));
774
+ return isNaN(d.getTime()) ? null : d;
775
+ }
776
+ // =============================================================================
777
+ // UTILITY FUNCTIONS
778
+ // =============================================================================
779
+ export function coalesce(...values) {
780
+ for (const value of values) {
781
+ if (value != null)
782
+ return value;
783
+ }
784
+ return undefined;
785
+ }
786
+ export function defaultValue(value, defaultVal) {
787
+ return value ?? defaultVal;
788
+ }
789
+ export function ifThen(condition, thenValue, elseValue) {
790
+ return condition ? thenValue : elseValue;
791
+ }
792
+ export function uuid() {
793
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
794
+ const r = (Math.random() * 16) | 0;
795
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
796
+ return v.toString(16);
797
+ });
798
+ }
799
+ // =============================================================================
800
+ // STRICT MODE ASSERTIONS
801
+ // =============================================================================
802
+ export function assertNonNull(value, message) {
803
+ if (value == null) {
804
+ throw new TransformError(message ?? 'Value is null or undefined', 'NULL_VALUE');
805
+ }
806
+ return value;
807
+ }
808
+ export function assertType(value, expectedType, nonNull = false) {
809
+ if (nonNull && value == null) {
810
+ throw new TransformError(`Expected non-null ${expectedType}, got ${value}`, 'NULL_VALUE');
811
+ }
812
+ if (value == null)
813
+ return value;
814
+ const actualType = type(value);
815
+ if (actualType !== expectedType && expectedType !== 'any') {
816
+ throw new TransformError(`Expected ${expectedType}, got ${actualType}`, 'TYPE_MISMATCH');
817
+ }
818
+ return value;
819
+ }
820
+ export function assertArray(value) {
821
+ if (!Array.isArray(value)) {
822
+ throw new TransformError(`Expected array, got ${type(value)}`, 'TYPE_MISMATCH');
823
+ }
824
+ return value;
825
+ }
826
+ // =============================================================================
827
+ // HELPERS BUNDLE
828
+ // =============================================================================
829
+ export const helpers = {
830
+ // String
831
+ upper,
832
+ lower,
833
+ trim,
834
+ split,
835
+ join,
836
+ substring,
837
+ replace,
838
+ replaceAll,
839
+ matches,
840
+ startsWith,
841
+ endsWith,
842
+ contains,
843
+ padStart,
844
+ padEnd,
845
+ capitalize,
846
+ camelCase,
847
+ snakeCase,
848
+ kebabCase,
849
+ // Number
850
+ round,
851
+ floor,
852
+ ceil,
853
+ abs,
854
+ min,
855
+ max,
856
+ clamp,
857
+ random,
858
+ randomInt,
859
+ // Array
860
+ map,
861
+ filter,
862
+ find,
863
+ some,
864
+ every,
865
+ reduce,
866
+ sum,
867
+ avg,
868
+ count,
869
+ first,
870
+ last,
871
+ unique,
872
+ flatten,
873
+ reverse,
874
+ sort,
875
+ sortDesc,
876
+ groupBy,
877
+ keyBy,
878
+ zip,
879
+ compact,
880
+ take,
881
+ drop,
882
+ range,
883
+ // Object
884
+ keys,
885
+ values,
886
+ entries,
887
+ merge,
888
+ pick,
889
+ omit,
890
+ get,
891
+ set,
892
+ // Type
893
+ type,
894
+ isString,
895
+ isNumber,
896
+ isBoolean,
897
+ isArray,
898
+ isObject,
899
+ isNull,
900
+ isUndefined,
901
+ isEmpty,
902
+ // Conversion
903
+ toString,
904
+ toNumber,
905
+ toBoolean,
906
+ toArray,
907
+ toJSON,
908
+ fromJSON,
909
+ // Date
910
+ now,
911
+ today,
912
+ formatDate,
913
+ parseDate,
914
+ // Utility
915
+ coalesce,
916
+ default: defaultValue,
917
+ if: ifThen,
918
+ uuid,
919
+ // Assertions (legacy)
920
+ assertNonNull,
921
+ assertType,
922
+ assertArray,
923
+ // Strict Mode Helpers
924
+ strictGet,
925
+ strictIndex,
926
+ strictArray,
927
+ strictNonNull,
928
+ strictType,
929
+ strictFilter,
930
+ strictMap,
931
+ };
932
+ export default helpers;
933
+ //# sourceMappingURL=runtime.js.map