starlight-cli 1.1.16 → 1.1.17

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.
package/dist/index.js CHANGED
@@ -10213,7 +10213,6 @@ const fs = __nccwpck_require__(896);
10213
10213
  const Lexer = __nccwpck_require__(211);
10214
10214
  const Parser = __nccwpck_require__(222);
10215
10215
  const path = __nccwpck_require__(928);
10216
-
10217
10216
  class ReturnValue {
10218
10217
  constructor(value) { this.value = value; }
10219
10218
  }
@@ -10414,7 +10413,51 @@ formatValue(value, seen = new Set()) {
10414
10413
  if (arg && typeof arg === 'object') return Object.keys(arg).length;
10415
10414
  return 0;
10416
10415
  });
10416
+ this.global.define('lower', arg => {
10417
+ if (typeof arg !== 'string') return String(arg).toLowerCase();
10418
+ return arg.toLowerCase();
10419
+ });
10420
+ this.global.define('toStr', arg => String(arg));
10421
+
10422
+ this.global.define('upper', arg => {
10423
+ if (typeof arg !== 'string') return String(arg).toUpperCase();
10424
+ return arg.toUpperCase();
10425
+ });
10426
+
10427
+ this.global.define('trim', arg => {
10428
+ if (typeof arg !== 'string') return String(arg).trim();
10429
+ return arg.trim();
10430
+ });
10431
+
10432
+ this.global.define('startsWith', (str, prefix) => {
10433
+ if (typeof str !== 'string') str = String(str);
10434
+ if (typeof prefix !== 'string') prefix = String(prefix);
10435
+ return str.startsWith(prefix);
10436
+ });
10417
10437
 
10438
+ this.global.define('endsWith', (str, suffix) => {
10439
+ if (typeof str !== 'string') str = String(str);
10440
+ if (typeof suffix !== 'string') suffix = String(suffix);
10441
+ return str.endsWith(suffix);
10442
+ });
10443
+
10444
+ this.global.define('includes', (str, substr) => {
10445
+ if (typeof str !== 'string') str = String(str);
10446
+ if (typeof substr !== 'string') substr = String(substr);
10447
+ return str.includes(substr);
10448
+ });
10449
+
10450
+ this.global.define('repeat', (str, times) => {
10451
+ if (typeof str !== 'string') str = String(str);
10452
+ return str.repeat(Number(times) || 0);
10453
+ });
10454
+
10455
+ this.global.define('replace', (str, search, replacement) => {
10456
+ if (typeof str !== 'string') str = String(str);
10457
+ if (typeof search !== 'string') search = String(search);
10458
+ if (typeof replacement !== 'string') replacement = String(replacement);
10459
+ return str.split(search).join(replacement);
10460
+ });
10418
10461
  this.global.define('print', arg => { console.log(arg); return null; });
10419
10462
  this.global.define('type', arg => {
10420
10463
  if (Array.isArray(arg)) return 'array';
@@ -10563,6 +10606,72 @@ this.global.define('range', (...args) => {
10563
10606
 
10564
10607
  return result;
10565
10608
  });
10609
+ this.global.define('floor', arg => Math.floor(Number(arg)));
10610
+ this.global.define('ceil', arg => Math.ceil(Number(arg)));
10611
+ this.global.define('round', arg => Math.round(Number(arg)));
10612
+ this.global.define('abs', arg => Math.abs(Number(arg)));
10613
+ this.global.define('pow', (base, exp) => Math.pow(Number(base), Number(exp)));
10614
+ this.global.define('sqrt', arg => Math.sqrt(Number(arg)));
10615
+ this.global.define('min', (...args) => Math.min(...args.map(Number)));
10616
+ this.global.define('max', (...args) => Math.max(...args.map(Number)));
10617
+ this.global.define('randomFloat', (min, max) => {
10618
+ min = Number(min); max = Number(max);
10619
+ if (isNaN(min) || isNaN(max)) return 0;
10620
+ return Math.random() * (max - min) + min;
10621
+ });
10622
+
10623
+ this.global.define('push', (arr, val) => {
10624
+ if (!Array.isArray(arr)) throw new RuntimeError('push() expects an array', null, this.source);
10625
+ arr.push(val); return arr.length;
10626
+ });
10627
+ this.global.define('pop', arr => {
10628
+ if (!Array.isArray(arr)) throw new RuntimeError('pop() expects an array', null, this.source);
10629
+ return arr.pop();
10630
+ });
10631
+ this.global.define('shift', arr => {
10632
+ if (!Array.isArray(arr)) throw new RuntimeError('shift() expects an array', null, this.source);
10633
+ return arr.shift();
10634
+ });
10635
+ this.global.define('unshift', (arr, val) => {
10636
+ if (!Array.isArray(arr)) throw new RuntimeError('unshift() expects an array', null, this.source);
10637
+ arr.unshift(val); return arr.length;
10638
+ });
10639
+ this.global.define('sort', (arr, fn) => {
10640
+ if (!Array.isArray(arr)) throw new RuntimeError('sort() expects an array', null, this.source);
10641
+ if (fn && typeof fn === 'function') return arr.sort(fn);
10642
+ return arr.sort();
10643
+ });
10644
+ this.global.define('reverse', arr => {
10645
+ if (!Array.isArray(arr)) throw new RuntimeError('reverse() expects an array', null, this.source);
10646
+ return arr.reverse();
10647
+ });
10648
+
10649
+ this.global.define('has', (obj, key) => obj && typeof obj === 'object' ? obj.hasOwnProperty(key) : false);
10650
+ this.global.define('merge', (obj1, obj2) => {
10651
+ if (!obj1 || typeof obj1 !== 'object') obj1 = {};
10652
+ if (!obj2 || typeof obj2 !== 'object') obj2 = {};
10653
+ return { ...obj1, ...obj2 };
10654
+ });
10655
+
10656
+ this.global.define('uuid', () => {
10657
+ // simple random UUID v4
10658
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
10659
+ const r = Math.random() * 16 | 0;
10660
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
10661
+ return v.toString(16);
10662
+ });
10663
+ });
10664
+ this.global.define('timestamp', () => Date.now());
10665
+ this.global.define('clone', arg => {
10666
+ if (Array.isArray(arg)) return [...arg];
10667
+ if (arg && typeof arg === 'object') return { ...arg };
10668
+ return arg; // primitive types
10669
+ });
10670
+ this.global.define('typeOf', arg => {
10671
+ if (arg === null) return 'null';
10672
+ if (Array.isArray(arg)) return 'array';
10673
+ return typeof arg;
10674
+ });
10566
10675
 
10567
10676
  this.global.define('ask', prompt => {
10568
10677
  const readlineSync = __nccwpck_require__(552);
@@ -10619,6 +10728,271 @@ this.global.define('sleep', async (ms) => {
10619
10728
  this.global.define('str', arg => {
10620
10729
  return String(arg);
10621
10730
  });
10731
+ this.global.define('now', () => Date.now());
10732
+ this.global.define('formatDate', (timestamp, locale = 'en-US', options = {}) => {
10733
+ if (timestamp === null || timestamp === undefined) timestamp = Date.now();
10734
+ const t = typeof timestamp === 'number' ? timestamp : Number(timestamp);
10735
+ if (isNaN(t)) t = Date.now();
10736
+ return new Date(t).toLocaleString(locale, options);
10737
+ });
10738
+
10739
+ this.global.define('readFile', path => {
10740
+ if (typeof path !== 'string') path = String(path);
10741
+ try {
10742
+ return fs.readFileSync(path, 'utf-8');
10743
+ } catch (e) {
10744
+ throw new RuntimeError('readFile error: ' + e.message, null, this.source);
10745
+ }
10746
+ });
10747
+ this.global.define('writeFile', (path, content) => {
10748
+ if (typeof path !== 'string') path = String(path);
10749
+ if (typeof content !== 'string') content = String(content);
10750
+ try {
10751
+ fs.writeFileSync(path, content, 'utf-8');
10752
+ return true;
10753
+ } catch (e) {
10754
+ throw new RuntimeError('writeFile error: ' + e.message, null, this.source);
10755
+ }
10756
+ });
10757
+
10758
+ this.global.define('split', (str, separator) => {
10759
+ if (typeof str !== 'string') str = String(str);
10760
+ if (separator === undefined) separator = '';
10761
+ return str.split(separator);
10762
+ });
10763
+
10764
+ this.global.define('join', (arr, separator = '') => {
10765
+ if (!Array.isArray(arr)) throw new RuntimeError('join() expects an array', null, this.source);
10766
+ return arr.join(separator);
10767
+ });
10768
+
10769
+ this.global.define('substring', (str, start, end) => {
10770
+ if (typeof str !== 'string') str = String(str);
10771
+ start = Number(start) || 0;
10772
+ end = end !== undefined ? Number(end) : undefined;
10773
+ return str.substring(start, end);
10774
+ });
10775
+
10776
+ this.global.define('padStart', (str, targetLength, padString = ' ') => {
10777
+ if (typeof str !== 'string') str = String(str);
10778
+ targetLength = Number(targetLength) || 0;
10779
+ return str.padStart(targetLength, padString);
10780
+ });
10781
+
10782
+ this.global.define('padEnd', (str, targetLength, padString = ' ') => {
10783
+ if (typeof str !== 'string') str = String(str);
10784
+ targetLength = Number(targetLength) || 0;
10785
+ return str.padEnd(targetLength, padString);
10786
+ });
10787
+ this.global.define('unique', arr => {
10788
+ if (!Array.isArray(arr)) throw new RuntimeError('unique() expects an array', null, this.source);
10789
+ return [...new Set(arr)];
10790
+ });
10791
+
10792
+ this.global.define('indexOf', (arr, val) => {
10793
+ if (!Array.isArray(arr)) throw new RuntimeError('indexOf() expects an array', null, this.source);
10794
+ return arr.indexOf(val);
10795
+ });
10796
+
10797
+ this.global.define('includesArr', (arr, val) => {
10798
+ if (!Array.isArray(arr)) throw new RuntimeError('includesArr() expects an array', null, this.source);
10799
+ return arr.includes(val);
10800
+ });
10801
+
10802
+ this.global.define('flatten', arr => {
10803
+ if (!Array.isArray(arr)) throw new RuntimeError('flatten() expects an array', null, this.source);
10804
+ return arr.flat(Infinity);
10805
+ });
10806
+
10807
+ this.global.define('randomChoice', arr => {
10808
+ if (!Array.isArray(arr)) throw new RuntimeError('randomChoice() expects an array', null, this.source);
10809
+ return arr[Math.floor(Math.random() * arr.length)];
10810
+ });
10811
+
10812
+ this.global.define('entries', obj => {
10813
+ if (!obj || typeof obj !== 'object') throw new RuntimeError('entries() expects an object', null, this.source);
10814
+ return Object.entries(obj);
10815
+ });
10816
+
10817
+ this.global.define('invert', obj => {
10818
+ if (!obj || typeof obj !== 'object') throw new RuntimeError('invert() expects an object', null, this.source);
10819
+ const result = {};
10820
+ for (const key in obj) result[obj[key]] = key;
10821
+ return result;
10822
+ });
10823
+
10824
+ this.global.define('isEmpty', arg => {
10825
+ if (arg == null) return true;
10826
+ if (Array.isArray(arg) || typeof arg === 'string') return arg.length === 0;
10827
+ if (typeof arg === 'object') return Object.keys(arg).length === 0;
10828
+ return false;
10829
+ });
10830
+
10831
+ this.global.define('deepClone', arg => {
10832
+ return JSON.parse(JSON.stringify(arg));
10833
+ });
10834
+
10835
+ this.global.define('capitalize', str => {
10836
+ if (typeof str !== 'string') str = String(str);
10837
+ if (str.length === 0) return '';
10838
+ return str[0].toUpperCase() + str.slice(1);
10839
+ });
10840
+
10841
+ this.global.define('reverseStr', str => {
10842
+ if (typeof str !== 'string') str = String(str);
10843
+ return str.split('').reverse().join('');
10844
+ });
10845
+
10846
+ this.global.define('trimStart', str => {
10847
+ if (typeof str !== 'string') str = String(str);
10848
+ return str.trimStart();
10849
+ });
10850
+
10851
+ this.global.define('trimEnd', str => {
10852
+ if (typeof str !== 'string') str = String(str);
10853
+ return str.trimEnd();
10854
+ });
10855
+
10856
+ this.global.define('clamp', (value, min, max) => {
10857
+ value = Number(value); min = Number(min); max = Number(max);
10858
+ return Math.min(Math.max(value, min), max);
10859
+ });
10860
+
10861
+ this.global.define('sign', value => {
10862
+ value = Number(value);
10863
+ return Math.sign(value);
10864
+ });
10865
+
10866
+ this.global.define('appendFile', (path, content) => {
10867
+ if (typeof path !== 'string') path = String(path);
10868
+ if (typeof content !== 'string') content = String(content);
10869
+ try {
10870
+ fs.appendFileSync(path, content, 'utf-8');
10871
+ return true;
10872
+ } catch (e) {
10873
+ throw new RuntimeError('appendFile error: ' + e.message, null, this.source);
10874
+ }
10875
+ });
10876
+
10877
+ this.global.define('exists', path => {
10878
+ if (typeof path !== 'string') path = String(path);
10879
+ return fs.existsSync(path);
10880
+ });
10881
+
10882
+ this.global.define('mkdir', path => {
10883
+ if (typeof path !== 'string') path = String(path);
10884
+ if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
10885
+ return true;
10886
+ });
10887
+ this.global.define('count', (arr, value) => {
10888
+ if (!Array.isArray(arr)) throw new RuntimeError('count() expects an array', null, this.source);
10889
+ return arr.filter(x => x === value).length;
10890
+ });
10891
+
10892
+ this.global.define('uniqueBy', (arr, fn) => {
10893
+ if (!Array.isArray(arr)) throw new RuntimeError('uniqueBy() expects an array', null, this.source);
10894
+ const seen = new Set();
10895
+ const result = [];
10896
+ for (const item of arr) {
10897
+ const key = fn ? fn(item) : item;
10898
+ if (!seen.has(key)) {
10899
+ seen.add(key);
10900
+ result.push(item);
10901
+ }
10902
+ }
10903
+ return result;
10904
+ });
10905
+ this.global.define('getProp', (obj, key, defaultValue = null) => {
10906
+ if (!obj || typeof obj !== 'object') return defaultValue;
10907
+ const keys = key.split('.');
10908
+ let current = obj;
10909
+ for (const k of keys) {
10910
+ if (current[k] === undefined) return defaultValue;
10911
+ current = current[k];
10912
+ }
10913
+ return current;
10914
+ });
10915
+
10916
+ this.global.define('setProp', (obj, key, value) => {
10917
+ if (!obj || typeof obj !== 'object') throw new RuntimeError('setProp() expects an object', null, this.source);
10918
+ const keys = key.split('.');
10919
+ let current = obj;
10920
+ for (let i = 0; i < keys.length - 1; i++) {
10921
+ if (!current[keys[i]] || typeof current[keys[i]] !== 'object') current[keys[i]] = {};
10922
+ current = current[keys[i]];
10923
+ }
10924
+ current[keys[keys.length - 1]] = value;
10925
+ return obj;
10926
+ });
10927
+
10928
+ this.global.define('mergeDeep', (obj1, obj2) => {
10929
+ const isObject = val => val && typeof val === 'object';
10930
+ const result = {...obj1};
10931
+ for (const key in obj2) {
10932
+ if (isObject(obj2[key]) && isObject(result[key])) {
10933
+ result[key] = this.global.get('mergeDeep')(result[key], obj2[key]);
10934
+ } else {
10935
+ result[key] = obj2[key];
10936
+ }
10937
+ }
10938
+ return result;
10939
+ });
10940
+ this.global.define('camelCase', str => {
10941
+ if (typeof str !== 'string') str = String(str);
10942
+ return str
10943
+ .replace(/[-_ ]+./g, s => s.charAt(s.length - 1).toUpperCase())
10944
+ .replace(/^[A-Z]/, s => s.toLowerCase());
10945
+ });
10946
+
10947
+ this.global.define('kebabCase', str => {
10948
+ if (typeof str !== 'string') str = String(str);
10949
+ return str
10950
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
10951
+ .replace(/\s+/g, '-')
10952
+ .replace(/_+/g, '-')
10953
+ .toLowerCase();
10954
+ });
10955
+
10956
+ this.global.define('repeatStr', (str, times) => {
10957
+ if (typeof str !== 'string') str = String(str);
10958
+ return str.repeat(Number(times) || 0);
10959
+ });
10960
+ this.global.define('randomInt', (min, max) => {
10961
+ min = Number(min); max = Number(max);
10962
+ if (isNaN(min) || isNaN(max)) return 0;
10963
+ return Math.floor(Math.random() * (max - min + 1)) + min;
10964
+ });
10965
+
10966
+ this.global.define('lerp', (a, b, t) => {
10967
+ a = Number(a); b = Number(b); t = Number(t);
10968
+ return a + (b - a) * t;
10969
+ });
10970
+
10971
+ this.global.define('degToRad', deg => Number(deg) * (Math.PI / 180));
10972
+ this.global.define('radToDeg', rad => Number(rad) * (180 / Math.PI));
10973
+ this.global.define('readJSON', path => {
10974
+ const content = this.global.get('readFile')(path);
10975
+ return JSON.parse(content);
10976
+ });
10977
+
10978
+ this.global.define('writeJSON', (path, obj) => {
10979
+ const content = JSON.stringify(obj, null, 2);
10980
+ return this.global.get('writeFile')(path, content);
10981
+ });
10982
+
10983
+ this.global.define('deleteFile', path => {
10984
+ if (typeof path !== 'string') path = String(path);
10985
+ if (!fs.existsSync(path)) return false;
10986
+ fs.unlinkSync(path);
10987
+ return true;
10988
+ });
10989
+
10990
+ this.global.define('rmdir', path => {
10991
+ if (typeof path !== 'string') path = String(path);
10992
+ if (!fs.existsSync(path)) return false;
10993
+ fs.rmSync(path, { recursive: true, force: true });
10994
+ return true;
10995
+ });
10622
10996
 
10623
10997
  }
10624
10998
 
@@ -13969,7 +14343,7 @@ const Lexer = __nccwpck_require__(211);
13969
14343
  const Parser = __nccwpck_require__(222);
13970
14344
  const Evaluator = __nccwpck_require__(112);
13971
14345
 
13972
- const VERSION = '1.1.16';
14346
+ const VERSION = '1.1.17';
13973
14347
 
13974
14348
  const COLOR = {
13975
14349
  reset: '\x1b[0m',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starlight-cli",
3
- "version": "1.1.16",
3
+ "version": "1.1.17",
4
4
  "description": "Starlight Programming Language CLI",
5
5
  "bin": {
6
6
  "starlight": "index.js"
package/src/evaluator.js CHANGED
@@ -3,7 +3,6 @@ const fs = require('fs');
3
3
  const Lexer = require('./lexer');
4
4
  const Parser = require('./parser');
5
5
  const path = require('path');
6
-
7
6
  class ReturnValue {
8
7
  constructor(value) { this.value = value; }
9
8
  }
@@ -204,7 +203,51 @@ formatValue(value, seen = new Set()) {
204
203
  if (arg && typeof arg === 'object') return Object.keys(arg).length;
205
204
  return 0;
206
205
  });
206
+ this.global.define('lower', arg => {
207
+ if (typeof arg !== 'string') return String(arg).toLowerCase();
208
+ return arg.toLowerCase();
209
+ });
210
+ this.global.define('toStr', arg => String(arg));
211
+
212
+ this.global.define('upper', arg => {
213
+ if (typeof arg !== 'string') return String(arg).toUpperCase();
214
+ return arg.toUpperCase();
215
+ });
216
+
217
+ this.global.define('trim', arg => {
218
+ if (typeof arg !== 'string') return String(arg).trim();
219
+ return arg.trim();
220
+ });
221
+
222
+ this.global.define('startsWith', (str, prefix) => {
223
+ if (typeof str !== 'string') str = String(str);
224
+ if (typeof prefix !== 'string') prefix = String(prefix);
225
+ return str.startsWith(prefix);
226
+ });
207
227
 
228
+ this.global.define('endsWith', (str, suffix) => {
229
+ if (typeof str !== 'string') str = String(str);
230
+ if (typeof suffix !== 'string') suffix = String(suffix);
231
+ return str.endsWith(suffix);
232
+ });
233
+
234
+ this.global.define('includes', (str, substr) => {
235
+ if (typeof str !== 'string') str = String(str);
236
+ if (typeof substr !== 'string') substr = String(substr);
237
+ return str.includes(substr);
238
+ });
239
+
240
+ this.global.define('repeat', (str, times) => {
241
+ if (typeof str !== 'string') str = String(str);
242
+ return str.repeat(Number(times) || 0);
243
+ });
244
+
245
+ this.global.define('replace', (str, search, replacement) => {
246
+ if (typeof str !== 'string') str = String(str);
247
+ if (typeof search !== 'string') search = String(search);
248
+ if (typeof replacement !== 'string') replacement = String(replacement);
249
+ return str.split(search).join(replacement);
250
+ });
208
251
  this.global.define('print', arg => { console.log(arg); return null; });
209
252
  this.global.define('type', arg => {
210
253
  if (Array.isArray(arg)) return 'array';
@@ -353,6 +396,72 @@ this.global.define('range', (...args) => {
353
396
 
354
397
  return result;
355
398
  });
399
+ this.global.define('floor', arg => Math.floor(Number(arg)));
400
+ this.global.define('ceil', arg => Math.ceil(Number(arg)));
401
+ this.global.define('round', arg => Math.round(Number(arg)));
402
+ this.global.define('abs', arg => Math.abs(Number(arg)));
403
+ this.global.define('pow', (base, exp) => Math.pow(Number(base), Number(exp)));
404
+ this.global.define('sqrt', arg => Math.sqrt(Number(arg)));
405
+ this.global.define('min', (...args) => Math.min(...args.map(Number)));
406
+ this.global.define('max', (...args) => Math.max(...args.map(Number)));
407
+ this.global.define('randomFloat', (min, max) => {
408
+ min = Number(min); max = Number(max);
409
+ if (isNaN(min) || isNaN(max)) return 0;
410
+ return Math.random() * (max - min) + min;
411
+ });
412
+
413
+ this.global.define('push', (arr, val) => {
414
+ if (!Array.isArray(arr)) throw new RuntimeError('push() expects an array', null, this.source);
415
+ arr.push(val); return arr.length;
416
+ });
417
+ this.global.define('pop', arr => {
418
+ if (!Array.isArray(arr)) throw new RuntimeError('pop() expects an array', null, this.source);
419
+ return arr.pop();
420
+ });
421
+ this.global.define('shift', arr => {
422
+ if (!Array.isArray(arr)) throw new RuntimeError('shift() expects an array', null, this.source);
423
+ return arr.shift();
424
+ });
425
+ this.global.define('unshift', (arr, val) => {
426
+ if (!Array.isArray(arr)) throw new RuntimeError('unshift() expects an array', null, this.source);
427
+ arr.unshift(val); return arr.length;
428
+ });
429
+ this.global.define('sort', (arr, fn) => {
430
+ if (!Array.isArray(arr)) throw new RuntimeError('sort() expects an array', null, this.source);
431
+ if (fn && typeof fn === 'function') return arr.sort(fn);
432
+ return arr.sort();
433
+ });
434
+ this.global.define('reverse', arr => {
435
+ if (!Array.isArray(arr)) throw new RuntimeError('reverse() expects an array', null, this.source);
436
+ return arr.reverse();
437
+ });
438
+
439
+ this.global.define('has', (obj, key) => obj && typeof obj === 'object' ? obj.hasOwnProperty(key) : false);
440
+ this.global.define('merge', (obj1, obj2) => {
441
+ if (!obj1 || typeof obj1 !== 'object') obj1 = {};
442
+ if (!obj2 || typeof obj2 !== 'object') obj2 = {};
443
+ return { ...obj1, ...obj2 };
444
+ });
445
+
446
+ this.global.define('uuid', () => {
447
+ // simple random UUID v4
448
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
449
+ const r = Math.random() * 16 | 0;
450
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
451
+ return v.toString(16);
452
+ });
453
+ });
454
+ this.global.define('timestamp', () => Date.now());
455
+ this.global.define('clone', arg => {
456
+ if (Array.isArray(arg)) return [...arg];
457
+ if (arg && typeof arg === 'object') return { ...arg };
458
+ return arg; // primitive types
459
+ });
460
+ this.global.define('typeOf', arg => {
461
+ if (arg === null) return 'null';
462
+ if (Array.isArray(arg)) return 'array';
463
+ return typeof arg;
464
+ });
356
465
 
357
466
  this.global.define('ask', prompt => {
358
467
  const readlineSync = require('readline-sync');
@@ -409,6 +518,271 @@ this.global.define('sleep', async (ms) => {
409
518
  this.global.define('str', arg => {
410
519
  return String(arg);
411
520
  });
521
+ this.global.define('now', () => Date.now());
522
+ this.global.define('formatDate', (timestamp, locale = 'en-US', options = {}) => {
523
+ if (timestamp === null || timestamp === undefined) timestamp = Date.now();
524
+ const t = typeof timestamp === 'number' ? timestamp : Number(timestamp);
525
+ if (isNaN(t)) t = Date.now();
526
+ return new Date(t).toLocaleString(locale, options);
527
+ });
528
+
529
+ this.global.define('readFile', path => {
530
+ if (typeof path !== 'string') path = String(path);
531
+ try {
532
+ return fs.readFileSync(path, 'utf-8');
533
+ } catch (e) {
534
+ throw new RuntimeError('readFile error: ' + e.message, null, this.source);
535
+ }
536
+ });
537
+ this.global.define('writeFile', (path, content) => {
538
+ if (typeof path !== 'string') path = String(path);
539
+ if (typeof content !== 'string') content = String(content);
540
+ try {
541
+ fs.writeFileSync(path, content, 'utf-8');
542
+ return true;
543
+ } catch (e) {
544
+ throw new RuntimeError('writeFile error: ' + e.message, null, this.source);
545
+ }
546
+ });
547
+
548
+ this.global.define('split', (str, separator) => {
549
+ if (typeof str !== 'string') str = String(str);
550
+ if (separator === undefined) separator = '';
551
+ return str.split(separator);
552
+ });
553
+
554
+ this.global.define('join', (arr, separator = '') => {
555
+ if (!Array.isArray(arr)) throw new RuntimeError('join() expects an array', null, this.source);
556
+ return arr.join(separator);
557
+ });
558
+
559
+ this.global.define('substring', (str, start, end) => {
560
+ if (typeof str !== 'string') str = String(str);
561
+ start = Number(start) || 0;
562
+ end = end !== undefined ? Number(end) : undefined;
563
+ return str.substring(start, end);
564
+ });
565
+
566
+ this.global.define('padStart', (str, targetLength, padString = ' ') => {
567
+ if (typeof str !== 'string') str = String(str);
568
+ targetLength = Number(targetLength) || 0;
569
+ return str.padStart(targetLength, padString);
570
+ });
571
+
572
+ this.global.define('padEnd', (str, targetLength, padString = ' ') => {
573
+ if (typeof str !== 'string') str = String(str);
574
+ targetLength = Number(targetLength) || 0;
575
+ return str.padEnd(targetLength, padString);
576
+ });
577
+ this.global.define('unique', arr => {
578
+ if (!Array.isArray(arr)) throw new RuntimeError('unique() expects an array', null, this.source);
579
+ return [...new Set(arr)];
580
+ });
581
+
582
+ this.global.define('indexOf', (arr, val) => {
583
+ if (!Array.isArray(arr)) throw new RuntimeError('indexOf() expects an array', null, this.source);
584
+ return arr.indexOf(val);
585
+ });
586
+
587
+ this.global.define('includesArr', (arr, val) => {
588
+ if (!Array.isArray(arr)) throw new RuntimeError('includesArr() expects an array', null, this.source);
589
+ return arr.includes(val);
590
+ });
591
+
592
+ this.global.define('flatten', arr => {
593
+ if (!Array.isArray(arr)) throw new RuntimeError('flatten() expects an array', null, this.source);
594
+ return arr.flat(Infinity);
595
+ });
596
+
597
+ this.global.define('randomChoice', arr => {
598
+ if (!Array.isArray(arr)) throw new RuntimeError('randomChoice() expects an array', null, this.source);
599
+ return arr[Math.floor(Math.random() * arr.length)];
600
+ });
601
+
602
+ this.global.define('entries', obj => {
603
+ if (!obj || typeof obj !== 'object') throw new RuntimeError('entries() expects an object', null, this.source);
604
+ return Object.entries(obj);
605
+ });
606
+
607
+ this.global.define('invert', obj => {
608
+ if (!obj || typeof obj !== 'object') throw new RuntimeError('invert() expects an object', null, this.source);
609
+ const result = {};
610
+ for (const key in obj) result[obj[key]] = key;
611
+ return result;
612
+ });
613
+
614
+ this.global.define('isEmpty', arg => {
615
+ if (arg == null) return true;
616
+ if (Array.isArray(arg) || typeof arg === 'string') return arg.length === 0;
617
+ if (typeof arg === 'object') return Object.keys(arg).length === 0;
618
+ return false;
619
+ });
620
+
621
+ this.global.define('deepClone', arg => {
622
+ return JSON.parse(JSON.stringify(arg));
623
+ });
624
+
625
+ this.global.define('capitalize', str => {
626
+ if (typeof str !== 'string') str = String(str);
627
+ if (str.length === 0) return '';
628
+ return str[0].toUpperCase() + str.slice(1);
629
+ });
630
+
631
+ this.global.define('reverseStr', str => {
632
+ if (typeof str !== 'string') str = String(str);
633
+ return str.split('').reverse().join('');
634
+ });
635
+
636
+ this.global.define('trimStart', str => {
637
+ if (typeof str !== 'string') str = String(str);
638
+ return str.trimStart();
639
+ });
640
+
641
+ this.global.define('trimEnd', str => {
642
+ if (typeof str !== 'string') str = String(str);
643
+ return str.trimEnd();
644
+ });
645
+
646
+ this.global.define('clamp', (value, min, max) => {
647
+ value = Number(value); min = Number(min); max = Number(max);
648
+ return Math.min(Math.max(value, min), max);
649
+ });
650
+
651
+ this.global.define('sign', value => {
652
+ value = Number(value);
653
+ return Math.sign(value);
654
+ });
655
+
656
+ this.global.define('appendFile', (path, content) => {
657
+ if (typeof path !== 'string') path = String(path);
658
+ if (typeof content !== 'string') content = String(content);
659
+ try {
660
+ fs.appendFileSync(path, content, 'utf-8');
661
+ return true;
662
+ } catch (e) {
663
+ throw new RuntimeError('appendFile error: ' + e.message, null, this.source);
664
+ }
665
+ });
666
+
667
+ this.global.define('exists', path => {
668
+ if (typeof path !== 'string') path = String(path);
669
+ return fs.existsSync(path);
670
+ });
671
+
672
+ this.global.define('mkdir', path => {
673
+ if (typeof path !== 'string') path = String(path);
674
+ if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
675
+ return true;
676
+ });
677
+ this.global.define('count', (arr, value) => {
678
+ if (!Array.isArray(arr)) throw new RuntimeError('count() expects an array', null, this.source);
679
+ return arr.filter(x => x === value).length;
680
+ });
681
+
682
+ this.global.define('uniqueBy', (arr, fn) => {
683
+ if (!Array.isArray(arr)) throw new RuntimeError('uniqueBy() expects an array', null, this.source);
684
+ const seen = new Set();
685
+ const result = [];
686
+ for (const item of arr) {
687
+ const key = fn ? fn(item) : item;
688
+ if (!seen.has(key)) {
689
+ seen.add(key);
690
+ result.push(item);
691
+ }
692
+ }
693
+ return result;
694
+ });
695
+ this.global.define('getProp', (obj, key, defaultValue = null) => {
696
+ if (!obj || typeof obj !== 'object') return defaultValue;
697
+ const keys = key.split('.');
698
+ let current = obj;
699
+ for (const k of keys) {
700
+ if (current[k] === undefined) return defaultValue;
701
+ current = current[k];
702
+ }
703
+ return current;
704
+ });
705
+
706
+ this.global.define('setProp', (obj, key, value) => {
707
+ if (!obj || typeof obj !== 'object') throw new RuntimeError('setProp() expects an object', null, this.source);
708
+ const keys = key.split('.');
709
+ let current = obj;
710
+ for (let i = 0; i < keys.length - 1; i++) {
711
+ if (!current[keys[i]] || typeof current[keys[i]] !== 'object') current[keys[i]] = {};
712
+ current = current[keys[i]];
713
+ }
714
+ current[keys[keys.length - 1]] = value;
715
+ return obj;
716
+ });
717
+
718
+ this.global.define('mergeDeep', (obj1, obj2) => {
719
+ const isObject = val => val && typeof val === 'object';
720
+ const result = {...obj1};
721
+ for (const key in obj2) {
722
+ if (isObject(obj2[key]) && isObject(result[key])) {
723
+ result[key] = this.global.get('mergeDeep')(result[key], obj2[key]);
724
+ } else {
725
+ result[key] = obj2[key];
726
+ }
727
+ }
728
+ return result;
729
+ });
730
+ this.global.define('camelCase', str => {
731
+ if (typeof str !== 'string') str = String(str);
732
+ return str
733
+ .replace(/[-_ ]+./g, s => s.charAt(s.length - 1).toUpperCase())
734
+ .replace(/^[A-Z]/, s => s.toLowerCase());
735
+ });
736
+
737
+ this.global.define('kebabCase', str => {
738
+ if (typeof str !== 'string') str = String(str);
739
+ return str
740
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
741
+ .replace(/\s+/g, '-')
742
+ .replace(/_+/g, '-')
743
+ .toLowerCase();
744
+ });
745
+
746
+ this.global.define('repeatStr', (str, times) => {
747
+ if (typeof str !== 'string') str = String(str);
748
+ return str.repeat(Number(times) || 0);
749
+ });
750
+ this.global.define('randomInt', (min, max) => {
751
+ min = Number(min); max = Number(max);
752
+ if (isNaN(min) || isNaN(max)) return 0;
753
+ return Math.floor(Math.random() * (max - min + 1)) + min;
754
+ });
755
+
756
+ this.global.define('lerp', (a, b, t) => {
757
+ a = Number(a); b = Number(b); t = Number(t);
758
+ return a + (b - a) * t;
759
+ });
760
+
761
+ this.global.define('degToRad', deg => Number(deg) * (Math.PI / 180));
762
+ this.global.define('radToDeg', rad => Number(rad) * (180 / Math.PI));
763
+ this.global.define('readJSON', path => {
764
+ const content = this.global.get('readFile')(path);
765
+ return JSON.parse(content);
766
+ });
767
+
768
+ this.global.define('writeJSON', (path, obj) => {
769
+ const content = JSON.stringify(obj, null, 2);
770
+ return this.global.get('writeFile')(path, content);
771
+ });
772
+
773
+ this.global.define('deleteFile', path => {
774
+ if (typeof path !== 'string') path = String(path);
775
+ if (!fs.existsSync(path)) return false;
776
+ fs.unlinkSync(path);
777
+ return true;
778
+ });
779
+
780
+ this.global.define('rmdir', path => {
781
+ if (typeof path !== 'string') path = String(path);
782
+ if (!fs.existsSync(path)) return false;
783
+ fs.rmSync(path, { recursive: true, force: true });
784
+ return true;
785
+ });
412
786
 
413
787
  }
414
788
 
package/src/starlight.js CHANGED
@@ -12,7 +12,7 @@ const Lexer = require('./lexer');
12
12
  const Parser = require('./parser');
13
13
  const Evaluator = require('./evaluator');
14
14
 
15
- const VERSION = '1.1.16';
15
+ const VERSION = '1.1.17';
16
16
 
17
17
  const COLOR = {
18
18
  reset: '\x1b[0m',