@xnoxs/flux-lang 3.1.1 → 3.2.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.
package/dist/flux.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * flux-lang v3.1.1
2
+ * flux-lang v3.2.0
3
3
  * Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.
4
4
  * (c) 2026 Flux Lang Contributors
5
5
  * Released under the MIT License
@@ -984,18 +984,48 @@ var require_parser = __commonJS({
984
984
  }
985
985
  return stmts;
986
986
  }
987
+ // ── Decorator parsing: @name or @name(args) ───────────────────
988
+ parseDecorators() {
989
+ const decorators = [];
990
+ while (this.check(T.AT)) {
991
+ const loc = this.skip();
992
+ const name = this.eat(T.IDENT).value;
993
+ let args = [];
994
+ if (this.check(T.LPAREN)) {
995
+ this.pos++;
996
+ while (!this.check(T.RPAREN) && !this.check(T.EOF)) {
997
+ args.push(this.parseExpr());
998
+ if (!this.maybe(T.COMMA)) break;
999
+ }
1000
+ this.eat(T.RPAREN);
1001
+ }
1002
+ decorators.push({ name, args, loc });
1003
+ this.skipNewlines();
1004
+ }
1005
+ return decorators;
1006
+ }
987
1007
  parseOneStmt() {
1008
+ const decorators = this.check(T.AT) ? this.parseDecorators() : [];
988
1009
  const tok = this.peek();
989
1010
  switch (tok.type) {
990
1011
  case T.VAR:
991
1012
  case T.VAL:
992
1013
  return this.parseVarDecl();
993
- case T.FN:
994
- return this.parseFnDecl();
995
- case T.ASYNC:
996
- return this.parseAsyncFn();
997
- case T.CLASS:
998
- return this.parseClassDecl();
1014
+ case T.FN: {
1015
+ const n = this.parseFnDecl();
1016
+ if (decorators.length) n.decorators = decorators;
1017
+ return n;
1018
+ }
1019
+ case T.ASYNC: {
1020
+ const n = this.parseAsyncFn();
1021
+ if (decorators.length) n.decorators = decorators;
1022
+ return n;
1023
+ }
1024
+ case T.CLASS: {
1025
+ const n = this.parseClassDecl();
1026
+ if (decorators.length) n.decorators = decorators;
1027
+ return n;
1028
+ }
999
1029
  case T.IF:
1000
1030
  return this.parseIf();
1001
1031
  case T.FOR:
@@ -1576,6 +1606,26 @@ var require_parser = __commonJS({
1576
1606
  m.modifiers = mods;
1577
1607
  m.modifiers.add("static");
1578
1608
  methods.push(m);
1609
+ } else if (this.check(T.VAR) || this.check(T.VAL)) {
1610
+ const fieldKind = this.skip().type === T.VAR ? "var" : "val";
1611
+ const fname = this.eat(T.IDENT).value;
1612
+ let optional = false;
1613
+ let ftype = null;
1614
+ if (this.check(T.QUESTION)) {
1615
+ this.pos++;
1616
+ optional = true;
1617
+ }
1618
+ if (this.check(T.COLON)) {
1619
+ this.pos++;
1620
+ ftype = this.parseTypeAnn();
1621
+ }
1622
+ let init = null;
1623
+ if (this.check(T.EQ)) {
1624
+ this.pos++;
1625
+ init = this.parseExpr();
1626
+ }
1627
+ this.skipNewlines();
1628
+ fields.push({ name: fname, typeAnn: ftype, optional, modifiers: mods, init, fieldKind });
1579
1629
  } else if (this.check(T.IDENT)) {
1580
1630
  const fname = this.eat(T.IDENT).value;
1581
1631
  let optional = false;
@@ -1586,7 +1636,7 @@ var require_parser = __commonJS({
1586
1636
  this.eat(T.COLON);
1587
1637
  const ftype = this.parseTypeAnn();
1588
1638
  this.skipNewlines();
1589
- fields.push({ name: fname, typeAnn: ftype, optional, modifiers: mods });
1639
+ fields.push({ name: fname, typeAnn: ftype, optional, modifiers: mods, init: null });
1590
1640
  } else {
1591
1641
  this.skip();
1592
1642
  }
@@ -2500,7 +2550,7 @@ function _fmt(v, s) {
2500
2550
  this.lines = [];
2501
2551
  this.level = 0;
2502
2552
  this._needsFmt = false;
2503
- this.emit("// Generated by Flux Transpiler v3.1.0");
2553
+ this.emit("// Generated by Flux Transpiler v3.2.0");
2504
2554
  this.emit('"use strict";');
2505
2555
  this.blank();
2506
2556
  for (const node of ast.body) this.genStmt(node);
@@ -2604,23 +2654,44 @@ function _fmt(v, s) {
2604
2654
  this.out();
2605
2655
  this.emit("}");
2606
2656
  }
2657
+ if (node.name && node.decorators && node.decorators.length > 0) {
2658
+ for (let i = node.decorators.length - 1; i >= 0; i--) {
2659
+ const dec = node.decorators[i];
2660
+ const decArgs = dec.args.length > 0 ? `(${dec.args.map((a) => this.genExpr(a)).join(", ")})(${node.name})` : `(${node.name})`;
2661
+ this.emit(`${node.name} = ${dec.name}${decArgs};`);
2662
+ }
2663
+ }
2607
2664
  }
2608
2665
  // ── class ──────────────────────────────────────────────────────
2609
2666
  genClass(node) {
2610
2667
  const ext = node.superClass ? ` extends ${node.superClass}` : "";
2611
2668
  this.emit(`class ${node.name}${ext} {`);
2612
2669
  this.in();
2670
+ const isPrivate = (f) => f.modifiers && f.modifiers.has("private");
2671
+ const fieldName = (f) => isPrivate(f) ? `#${f.name}` : f.name;
2672
+ const fieldRef = (f) => isPrivate(f) ? `this.#${f.name}` : `this.${f.name}`;
2673
+ const privateFields = node.fields.filter(isPrivate);
2674
+ for (const f of privateFields) this.emit(`#${f.name};`);
2675
+ if (privateFields.length > 0) this.blank();
2613
2676
  const allFields = getAllFields(node.name, this.clsReg);
2614
- if (allFields.length > 0) {
2615
- const params = allFields.map((f) => f.name).join(", ");
2677
+ const paramFields = allFields.filter((f) => f.init == null && !isPrivate(f));
2678
+ const initFields = allFields.filter((f) => f.init != null);
2679
+ const ownInitFields = node.fields.filter((f) => f.init != null);
2680
+ const needsCtor = paramFields.length > 0 || initFields.length > 0 || privateFields.length > 0;
2681
+ if (needsCtor) {
2682
+ const params = paramFields.map((f) => f.name).join(", ");
2616
2683
  this.emit(`constructor(${params}) {`);
2617
2684
  this.in();
2618
2685
  if (node.superClass && this.clsReg[node.superClass]) {
2619
2686
  const parentFields = getAllFields(node.superClass, this.clsReg);
2620
- if (parentFields.length > 0)
2621
- this.emit(`super(${parentFields.map((f) => f.name).join(", ")});`);
2622
- }
2623
- for (const f of node.fields) this.emit(`this.${f.name} = ${f.name};`);
2687
+ const parentParams = parentFields.filter((f) => f.init == null);
2688
+ if (parentParams.length > 0)
2689
+ this.emit(`super(${parentParams.map((f) => f.name).join(", ")});`);
2690
+ }
2691
+ for (const f of node.fields.filter((f2) => f2.init == null && !isPrivate(f2)))
2692
+ this.emit(`${fieldRef(f)} = ${f.name};`);
2693
+ for (const f of ownInitFields)
2694
+ this.emit(`${fieldRef(f)} = ${this.genExpr(f.init)};`);
2624
2695
  this.out();
2625
2696
  this.emit("}");
2626
2697
  this.blank();
@@ -2645,6 +2716,13 @@ function _fmt(v, s) {
2645
2716
  }
2646
2717
  this.out();
2647
2718
  this.emit("}");
2719
+ if (node.decorators && node.decorators.length > 0) {
2720
+ for (let i = node.decorators.length - 1; i >= 0; i--) {
2721
+ const dec = node.decorators[i];
2722
+ const decArgs = dec.args.length > 0 ? `(${dec.args.map((a) => this.genExpr(a)).join(", ")})(${node.name})` : `(${node.name})`;
2723
+ this.emit(`${node.name} = ${dec.name}${decArgs};`);
2724
+ }
2725
+ }
2648
2726
  this.blank();
2649
2727
  }
2650
2728
  // ── if / else if / else ─────────────────────────────────────────
@@ -5874,41 +5952,16 @@ var require_stdlib = __commonJS({
5874
5952
  "src/stdlib.js"(exports, module) {
5875
5953
  "use strict";
5876
5954
  var STDLIB_SYMBOLS = [
5955
+ // Sequences
5877
5956
  "range",
5878
5957
  "zip",
5879
5958
  "enumerate",
5880
- "clamp",
5881
- "sum",
5882
- "product",
5883
5959
  "flatten",
5884
5960
  "chunk",
5885
5961
  "unique",
5886
5962
  "groupBy",
5887
5963
  "sortBy",
5888
- "pick",
5889
- "omit",
5890
- "deepEqual",
5891
- "deepClone",
5892
- "sleep",
5893
- "retry",
5894
- "memoize",
5895
- "pipe",
5896
- "compose",
5897
- "partial",
5898
- "curry",
5899
- "capitalize",
5900
- "camelCase",
5901
- "snakeCase",
5902
- "kebabCase",
5903
- "truncate",
5904
- "pad",
5905
- "randInt",
5906
- "sample",
5907
- "shuffle",
5908
- "mapValues",
5909
- "filterValues",
5910
- "fromEntries",
5911
- // Array pipe helpers — standalone wrappers around Array.prototype methods
5964
+ // Array pipe helpers
5912
5965
  "map",
5913
5966
  "filter",
5914
5967
  "reduce",
@@ -5921,7 +5974,106 @@ var require_stdlib = __commonJS({
5921
5974
  "sort",
5922
5975
  "flat",
5923
5976
  "flatMap",
5924
- "includes"
5977
+ "includes",
5978
+ // Array extras
5979
+ "first",
5980
+ "last",
5981
+ "take",
5982
+ "drop",
5983
+ "takeWhile",
5984
+ "dropWhile",
5985
+ "compact",
5986
+ "intersection",
5987
+ "difference",
5988
+ "arrayUnion",
5989
+ "unzip",
5990
+ "countBy",
5991
+ "minBy",
5992
+ "maxBy",
5993
+ "toPairs",
5994
+ "partition",
5995
+ "count",
5996
+ "head",
5997
+ "tail",
5998
+ "nth",
5999
+ "rotate",
6000
+ "sliding",
6001
+ // Math
6002
+ "clamp",
6003
+ "sum",
6004
+ "product",
6005
+ "min",
6006
+ "max",
6007
+ "abs",
6008
+ "floor",
6009
+ "ceil",
6010
+ "round",
6011
+ "mean",
6012
+ "median",
6013
+ "stdDev",
6014
+ "lerp",
6015
+ "randInt",
6016
+ "sample",
6017
+ "shuffle",
6018
+ // Objects
6019
+ "pick",
6020
+ "omit",
6021
+ "deepEqual",
6022
+ "deepClone",
6023
+ "mapValues",
6024
+ "filterValues",
6025
+ "fromEntries",
6026
+ "keys",
6027
+ "values",
6028
+ "entries",
6029
+ "merge",
6030
+ "invert",
6031
+ "defaults",
6032
+ // Strings
6033
+ "capitalize",
6034
+ "camelCase",
6035
+ "snakeCase",
6036
+ "kebabCase",
6037
+ "truncate",
6038
+ "pad",
6039
+ "padStart",
6040
+ "padEnd",
6041
+ "trim",
6042
+ "trimStart",
6043
+ "trimEnd",
6044
+ "words",
6045
+ "lines",
6046
+ "startsWith",
6047
+ "endsWith",
6048
+ "repeat",
6049
+ "replaceAll",
6050
+ "reverseStr",
6051
+ // Type checks
6052
+ "isNil",
6053
+ "isString",
6054
+ "isNumber",
6055
+ "isArray",
6056
+ "isObject",
6057
+ "isFunction",
6058
+ "isBool",
6059
+ // Async
6060
+ "sleep",
6061
+ "retry",
6062
+ "memoize",
6063
+ "timeout",
6064
+ "debounce",
6065
+ "throttle",
6066
+ "allSettled",
6067
+ // Functional
6068
+ "pipe",
6069
+ "compose",
6070
+ "partial",
6071
+ "curry",
6072
+ "identity",
6073
+ "noop",
6074
+ "once",
6075
+ "flip",
6076
+ "complement"
5925
6077
  ];
5926
6078
  function buildStdlib(symbols) {
5927
6079
  const needed = symbols ? new Set(symbols.filter((s) => STDLIB_SYMBOLS.includes(s))) : new Set(STDLIB_SYMBOLS);
@@ -6045,6 +6197,148 @@ function sortBy(arr, fn) {
6045
6197
  var kb = typeof fn === 'function' ? fn(b) : b[fn];
6046
6198
  return ka < kb ? -1 : ka > kb ? 1 : 0;
6047
6199
  });
6200
+ }`);
6201
+ }
6202
+ if (needed.has("first") || needed.has("head")) {
6203
+ parts.push(`
6204
+ function first(arr) { return arr[0]; }
6205
+ function head(arr) { return arr[0]; }`);
6206
+ }
6207
+ if (needed.has("last")) {
6208
+ parts.push(`
6209
+ function last(arr) { return arr[arr.length - 1]; }`);
6210
+ }
6211
+ if (needed.has("tail")) {
6212
+ parts.push(`
6213
+ function tail(arr) { return arr.slice(1); }`);
6214
+ }
6215
+ if (needed.has("nth")) {
6216
+ parts.push(`
6217
+ function nth(arr, n) { return n < 0 ? arr[arr.length + n] : arr[n]; }`);
6218
+ }
6219
+ if (needed.has("take")) {
6220
+ parts.push(`
6221
+ function take(arr, n) { return arr.slice(0, n); }`);
6222
+ }
6223
+ if (needed.has("drop")) {
6224
+ parts.push(`
6225
+ function drop(arr, n) { return arr.slice(n); }`);
6226
+ }
6227
+ if (needed.has("takeWhile")) {
6228
+ parts.push(`
6229
+ function takeWhile(arr, fn) {
6230
+ var i = 0;
6231
+ while (i < arr.length && fn(arr[i])) i++;
6232
+ return arr.slice(0, i);
6233
+ }`);
6234
+ }
6235
+ if (needed.has("dropWhile")) {
6236
+ parts.push(`
6237
+ function dropWhile(arr, fn) {
6238
+ var i = 0;
6239
+ while (i < arr.length && fn(arr[i])) i++;
6240
+ return arr.slice(i);
6241
+ }`);
6242
+ }
6243
+ if (needed.has("compact")) {
6244
+ parts.push(`
6245
+ function compact(arr) {
6246
+ return arr.filter(function(v) { return v != null && v !== false && v !== 0 && v !== ''; });
6247
+ }`);
6248
+ }
6249
+ if (needed.has("intersection")) {
6250
+ parts.push(`
6251
+ function intersection(a, b) {
6252
+ var s = new Set(b);
6253
+ return a.filter(function(v) { return s.has(v); });
6254
+ }`);
6255
+ }
6256
+ if (needed.has("difference")) {
6257
+ parts.push(`
6258
+ function difference(a, b) {
6259
+ var s = new Set(b);
6260
+ return a.filter(function(v) { return !s.has(v); });
6261
+ }`);
6262
+ }
6263
+ if (needed.has("arrayUnion")) {
6264
+ parts.push(`
6265
+ function arrayUnion(a, b) {
6266
+ return Array.from(new Set(a.concat(b)));
6267
+ }`);
6268
+ }
6269
+ if (needed.has("unzip")) {
6270
+ parts.push(`
6271
+ function unzip(pairs) {
6272
+ var a = [], b = [];
6273
+ for (var i = 0; i < pairs.length; i++) { a.push(pairs[i][0]); b.push(pairs[i][1]); }
6274
+ return [a, b];
6275
+ }`);
6276
+ }
6277
+ if (needed.has("countBy")) {
6278
+ parts.push(`
6279
+ function countBy(arr, fn) {
6280
+ return arr.reduce(function(acc, v) {
6281
+ var k = typeof fn === 'function' ? fn(v) : v[fn];
6282
+ acc[k] = (acc[k] || 0) + 1;
6283
+ return acc;
6284
+ }, {});
6285
+ }`);
6286
+ }
6287
+ if (needed.has("minBy")) {
6288
+ parts.push(`
6289
+ function minBy(arr, fn) {
6290
+ if (!arr.length) return undefined;
6291
+ return arr.reduce(function(best, v) {
6292
+ return (typeof fn === 'function' ? fn(v) : v[fn]) < (typeof fn === 'function' ? fn(best) : best[fn]) ? v : best;
6293
+ });
6294
+ }`);
6295
+ }
6296
+ if (needed.has("maxBy")) {
6297
+ parts.push(`
6298
+ function maxBy(arr, fn) {
6299
+ if (!arr.length) return undefined;
6300
+ return arr.reduce(function(best, v) {
6301
+ return (typeof fn === 'function' ? fn(v) : v[fn]) > (typeof fn === 'function' ? fn(best) : best[fn]) ? v : best;
6302
+ });
6303
+ }`);
6304
+ }
6305
+ if (needed.has("toPairs")) {
6306
+ parts.push(`
6307
+ function toPairs(obj) {
6308
+ return Object.keys(obj).map(function(k) { return [k, obj[k]]; });
6309
+ }`);
6310
+ }
6311
+ if (needed.has("partition")) {
6312
+ parts.push(`
6313
+ function partition(arr, fn) {
6314
+ var yes = [], no = [];
6315
+ arr.forEach(function(v) { (fn(v) ? yes : no).push(v); });
6316
+ return [yes, no];
6317
+ }`);
6318
+ }
6319
+ if (needed.has("count")) {
6320
+ parts.push(`
6321
+ function count(arr, fn) {
6322
+ if (typeof fn !== 'function') return arr.length;
6323
+ return arr.reduce(function(n, v) { return fn(v) ? n + 1 : n; }, 0);
6324
+ }`);
6325
+ }
6326
+ if (needed.has("rotate")) {
6327
+ parts.push(`
6328
+ function rotate(arr, n) {
6329
+ var len = arr.length;
6330
+ if (!len) return [];
6331
+ var k = ((n % len) + len) % len;
6332
+ return arr.slice(k).concat(arr.slice(0, k));
6333
+ }`);
6334
+ }
6335
+ if (needed.has("sliding")) {
6336
+ parts.push(`
6337
+ function sliding(arr, size, step) {
6338
+ step = step || 1;
6339
+ var out = [];
6340
+ for (var i = 0; i + size <= arr.length; i += step) out.push(arr.slice(i, i + size));
6341
+ return out;
6048
6342
  }`);
6049
6343
  }
6050
6344
  if (needed.has("clamp")) {
@@ -6064,6 +6358,69 @@ function sum(arr) {
6064
6358
  function product(arr) {
6065
6359
  return arr.reduce(function(a, b) { return a * b; }, 1);
6066
6360
  }`);
6361
+ }
6362
+ if (needed.has("min")) {
6363
+ parts.push(`
6364
+ function min(arr) {
6365
+ if (arguments.length > 1) return Math.min.apply(null, arguments);
6366
+ return Math.min.apply(null, arr);
6367
+ }`);
6368
+ }
6369
+ if (needed.has("max")) {
6370
+ parts.push(`
6371
+ function max(arr) {
6372
+ if (arguments.length > 1) return Math.max.apply(null, arguments);
6373
+ return Math.max.apply(null, arr);
6374
+ }`);
6375
+ }
6376
+ if (needed.has("abs")) {
6377
+ parts.push(`
6378
+ function abs(n) { return Math.abs(n); }`);
6379
+ }
6380
+ if (needed.has("floor")) {
6381
+ parts.push(`
6382
+ function floor(n) { return Math.floor(n); }`);
6383
+ }
6384
+ if (needed.has("ceil")) {
6385
+ parts.push(`
6386
+ function ceil(n) { return Math.ceil(n); }`);
6387
+ }
6388
+ if (needed.has("round")) {
6389
+ parts.push(`
6390
+ function round(n, decimals) {
6391
+ if (decimals == null) return Math.round(n);
6392
+ var f = Math.pow(10, decimals);
6393
+ return Math.round(n * f) / f;
6394
+ }`);
6395
+ }
6396
+ if (needed.has("mean")) {
6397
+ parts.push(`
6398
+ function mean(arr) {
6399
+ if (!arr.length) return 0;
6400
+ return arr.reduce(function(a, b) { return a + b; }, 0) / arr.length;
6401
+ }`);
6402
+ }
6403
+ if (needed.has("median")) {
6404
+ parts.push(`
6405
+ function median(arr) {
6406
+ if (!arr.length) return 0;
6407
+ var s = arr.slice().sort(function(a, b) { return a - b; });
6408
+ var m = Math.floor(s.length / 2);
6409
+ return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
6410
+ }`);
6411
+ }
6412
+ if (needed.has("stdDev")) {
6413
+ parts.push(`
6414
+ function stdDev(arr) {
6415
+ if (!arr.length) return 0;
6416
+ var m = arr.reduce(function(a, b) { return a + b; }, 0) / arr.length;
6417
+ var variance = arr.reduce(function(acc, v) { return acc + (v - m) * (v - m); }, 0) / arr.length;
6418
+ return Math.sqrt(variance);
6419
+ }`);
6420
+ }
6421
+ if (needed.has("lerp")) {
6422
+ parts.push(`
6423
+ function lerp(a, b, t) { return a + (b - a) * t; }`);
6067
6424
  }
6068
6425
  if (needed.has("randInt")) {
6069
6426
  parts.push(`
@@ -6125,6 +6482,43 @@ function filterValues(obj, fn) {
6125
6482
  parts.push(`
6126
6483
  function fromEntries(entries) {
6127
6484
  return Object.fromEntries(entries);
6485
+ }`);
6486
+ }
6487
+ if (needed.has("keys")) {
6488
+ parts.push(`
6489
+ function keys(obj) { return Object.keys(obj); }`);
6490
+ }
6491
+ if (needed.has("values")) {
6492
+ parts.push(`
6493
+ function values(obj) { return Object.values(obj); }`);
6494
+ }
6495
+ if (needed.has("entries")) {
6496
+ parts.push(`
6497
+ function entries(obj) { return Object.entries(obj); }`);
6498
+ }
6499
+ if (needed.has("merge")) {
6500
+ parts.push(`
6501
+ function merge() {
6502
+ return Object.assign.apply(Object, [{}].concat(Array.from(arguments)));
6503
+ }`);
6504
+ }
6505
+ if (needed.has("invert")) {
6506
+ parts.push(`
6507
+ function invert(obj) {
6508
+ var out = {};
6509
+ Object.keys(obj).forEach(function(k) { out[obj[k]] = k; });
6510
+ return out;
6511
+ }`);
6512
+ }
6513
+ if (needed.has("defaults")) {
6514
+ parts.push(`
6515
+ function defaults(obj) {
6516
+ var sources = Array.from(arguments).slice(1);
6517
+ var out = Object.assign({}, obj);
6518
+ sources.forEach(function(s) {
6519
+ Object.keys(s).forEach(function(k) { if (out[k] == null) out[k] = s[k]; });
6520
+ });
6521
+ return out;
6128
6522
  }`);
6129
6523
  }
6130
6524
  if (needed.has("deepEqual")) {
@@ -6138,6 +6532,133 @@ function deepEqual(a, b) {
6138
6532
  function deepClone(v) {
6139
6533
  return JSON.parse(JSON.stringify(v));
6140
6534
  }`);
6535
+ }
6536
+ if (needed.has("capitalize")) {
6537
+ parts.push(`
6538
+ function capitalize(s) {
6539
+ return s ? s[0].toUpperCase() + s.slice(1) : s;
6540
+ }`);
6541
+ }
6542
+ if (needed.has("camelCase")) {
6543
+ parts.push(`
6544
+ function camelCase(s) {
6545
+ return s.replace(/[-_\\s]+(.)/g, function(_, c) { return c.toUpperCase(); }).replace(/^./, function(c) { return c.toLowerCase(); });
6546
+ }`);
6547
+ }
6548
+ if (needed.has("snakeCase")) {
6549
+ parts.push(`
6550
+ function snakeCase(s) {
6551
+ return s.replace(/([A-Z])/g, function(c) { return '_' + c.toLowerCase(); }).replace(/[-\\s]+/g, '_').replace(/^_/, '');
6552
+ }`);
6553
+ }
6554
+ if (needed.has("kebabCase")) {
6555
+ parts.push(`
6556
+ function kebabCase(s) {
6557
+ return s.replace(/([A-Z])/g, function(c) { return '-' + c.toLowerCase(); }).replace(/[_\\s]+/g, '-').replace(/^-/, '');
6558
+ }`);
6559
+ }
6560
+ if (needed.has("truncate")) {
6561
+ parts.push(`
6562
+ function truncate(s, len, suffix) {
6563
+ suffix = suffix != null ? suffix : '...';
6564
+ if (s.length <= len) return s;
6565
+ var cut = len - suffix.length;
6566
+ if (cut <= 0) return suffix.slice(0, len);
6567
+ return s.slice(0, cut) + suffix;
6568
+ }`);
6569
+ }
6570
+ if (needed.has("pad")) {
6571
+ parts.push(`
6572
+ function pad(s, len, char) {
6573
+ char = char || ' ';
6574
+ s = String(s);
6575
+ var total = len - s.length;
6576
+ if (total <= 0) return s;
6577
+ var half = Math.floor(total / 2);
6578
+ return char.repeat(half) + s + char.repeat(total - half);
6579
+ }`);
6580
+ }
6581
+ if (needed.has("padStart")) {
6582
+ parts.push(`
6583
+ function padStart(s, len, char) {
6584
+ return String(s).padStart(len, char || ' ');
6585
+ }`);
6586
+ }
6587
+ if (needed.has("padEnd")) {
6588
+ parts.push(`
6589
+ function padEnd(s, len, char) {
6590
+ return String(s).padEnd(len, char || ' ');
6591
+ }`);
6592
+ }
6593
+ if (needed.has("trim")) {
6594
+ parts.push(`
6595
+ function trim(s) { return String(s).trim(); }`);
6596
+ }
6597
+ if (needed.has("trimStart")) {
6598
+ parts.push(`
6599
+ function trimStart(s) { return String(s).trimStart(); }`);
6600
+ }
6601
+ if (needed.has("trimEnd")) {
6602
+ parts.push(`
6603
+ function trimEnd(s) { return String(s).trimEnd(); }`);
6604
+ }
6605
+ if (needed.has("words")) {
6606
+ parts.push(`
6607
+ function words(s) { return String(s).trim().split(/\\s+/); }`);
6608
+ }
6609
+ if (needed.has("lines")) {
6610
+ parts.push(`
6611
+ function lines(s) { return String(s).split(/\\r?\\n/); }`);
6612
+ }
6613
+ if (needed.has("startsWith")) {
6614
+ parts.push(`
6615
+ function startsWith(s, prefix) { return String(s).startsWith(prefix); }`);
6616
+ }
6617
+ if (needed.has("endsWith")) {
6618
+ parts.push(`
6619
+ function endsWith(s, suffix) { return String(s).endsWith(suffix); }`);
6620
+ }
6621
+ if (needed.has("repeat")) {
6622
+ parts.push(`
6623
+ function repeat(s, n) { return String(s).repeat(n); }`);
6624
+ }
6625
+ if (needed.has("replaceAll")) {
6626
+ parts.push(`
6627
+ function replaceAll(s, search, replacement) {
6628
+ return String(s).split(search).join(replacement);
6629
+ }`);
6630
+ }
6631
+ if (needed.has("reverseStr")) {
6632
+ parts.push(`
6633
+ function reverseStr(s) { return String(s).split('').reverse().join(''); }`);
6634
+ }
6635
+ if (needed.has("isNil")) {
6636
+ parts.push(`
6637
+ function isNil(v) { return v == null; }`);
6638
+ }
6639
+ if (needed.has("isString")) {
6640
+ parts.push(`
6641
+ function isString(v) { return typeof v === 'string'; }`);
6642
+ }
6643
+ if (needed.has("isNumber")) {
6644
+ parts.push(`
6645
+ function isNumber(v) { return typeof v === 'number' && !isNaN(v); }`);
6646
+ }
6647
+ if (needed.has("isArray")) {
6648
+ parts.push(`
6649
+ function isArray(v) { return Array.isArray(v); }`);
6650
+ }
6651
+ if (needed.has("isObject")) {
6652
+ parts.push(`
6653
+ function isObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }`);
6654
+ }
6655
+ if (needed.has("isFunction")) {
6656
+ parts.push(`
6657
+ function isFunction(v) { return typeof v === 'function'; }`);
6658
+ }
6659
+ if (needed.has("isBool")) {
6660
+ parts.push(`
6661
+ function isBool(v) { return typeof v === 'boolean'; }`);
6141
6662
  }
6142
6663
  if (needed.has("sleep")) {
6143
6664
  parts.push(`
@@ -6153,9 +6674,48 @@ async function retry(fn, attempts, delay) {
6153
6674
  for (var i = 0; i < attempts; i++) {
6154
6675
  try { return await fn(); } catch(e) {
6155
6676
  if (i === attempts - 1) throw e;
6156
- await sleep(delay * Math.pow(2, i));
6677
+ await new Promise(function(r) { setTimeout(r, delay * Math.pow(2, i)); });
6157
6678
  }
6158
6679
  }
6680
+ }`);
6681
+ }
6682
+ if (needed.has("timeout")) {
6683
+ parts.push(`
6684
+ function timeout(fn, ms) {
6685
+ return Promise.race([
6686
+ typeof fn === 'function' ? fn() : fn,
6687
+ new Promise(function(_, reject) {
6688
+ setTimeout(function() { reject(new Error('Timeout after ' + ms + 'ms')); }, ms);
6689
+ })
6690
+ ]);
6691
+ }`);
6692
+ }
6693
+ if (needed.has("allSettled")) {
6694
+ parts.push(`
6695
+ function allSettled(promises) {
6696
+ return Promise.allSettled(promises);
6697
+ }`);
6698
+ }
6699
+ if (needed.has("debounce")) {
6700
+ parts.push(`
6701
+ function debounce(fn, ms) {
6702
+ var timer;
6703
+ return function() {
6704
+ clearTimeout(timer);
6705
+ var args = arguments;
6706
+ var ctx = this;
6707
+ timer = setTimeout(function() { fn.apply(ctx, args); }, ms);
6708
+ };
6709
+ }`);
6710
+ }
6711
+ if (needed.has("throttle")) {
6712
+ parts.push(`
6713
+ function throttle(fn, ms) {
6714
+ var last = 0;
6715
+ return function() {
6716
+ var now = Date.now();
6717
+ if (now - last >= ms) { last = now; return fn.apply(this, arguments); }
6718
+ };
6159
6719
  }`);
6160
6720
  }
6161
6721
  if (needed.has("memoize")) {
@@ -6202,50 +6762,37 @@ function curry(fn) {
6202
6762
  };
6203
6763
  }`);
6204
6764
  }
6205
- if (needed.has("capitalize")) {
6765
+ if (needed.has("identity")) {
6206
6766
  parts.push(`
6207
- function capitalize(s) {
6208
- return s ? s[0].toUpperCase() + s.slice(1) : s;
6209
- }`);
6767
+ function identity(v) { return v; }`);
6210
6768
  }
6211
- if (needed.has("camelCase")) {
6769
+ if (needed.has("noop")) {
6212
6770
  parts.push(`
6213
- function camelCase(s) {
6214
- return s.replace(/[-_\\s]+(.)/g, function(_, c) { return c.toUpperCase(); }).replace(/^./, function(c) { return c.toLowerCase(); });
6215
- }`);
6771
+ function noop() {}`);
6216
6772
  }
6217
- if (needed.has("snakeCase")) {
6218
- parts.push(`
6219
- function snakeCase(s) {
6220
- return s.replace(/([A-Z])/g, function(c) { return '_' + c.toLowerCase(); }).replace(/[-\\s]+/g, '_').replace(/^_/, '');
6221
- }`);
6222
- }
6223
- if (needed.has("kebabCase")) {
6773
+ if (needed.has("once")) {
6224
6774
  parts.push(`
6225
- function kebabCase(s) {
6226
- return s.replace(/([A-Z])/g, function(c) { return '-' + c.toLowerCase(); }).replace(/[_\\s]+/g, '-').replace(/^-/, '');
6775
+ function once(fn) {
6776
+ var called = false, result;
6777
+ return function() {
6778
+ if (!called) { called = true; result = fn.apply(this, arguments); }
6779
+ return result;
6780
+ };
6227
6781
  }`);
6228
6782
  }
6229
- if (needed.has("truncate")) {
6783
+ if (needed.has("flip")) {
6230
6784
  parts.push(`
6231
- function truncate(s, len, suffix) {
6232
- suffix = suffix != null ? suffix : '...';
6233
- if (s.length <= len) return s;
6234
- // FIX: guard against suffix longer than len to avoid negative slice index
6235
- var cut = len - suffix.length;
6236
- if (cut <= 0) return suffix.slice(0, len);
6237
- return s.slice(0, cut) + suffix;
6785
+ function flip(fn) {
6786
+ return function() {
6787
+ var args = Array.from(arguments);
6788
+ return fn.apply(this, [args[1], args[0]].concat(args.slice(2)));
6789
+ };
6238
6790
  }`);
6239
6791
  }
6240
- if (needed.has("pad")) {
6792
+ if (needed.has("complement")) {
6241
6793
  parts.push(`
6242
- function pad(s, len, char) {
6243
- char = char || ' ';
6244
- s = String(s);
6245
- var total = len - s.length;
6246
- if (total <= 0) return s;
6247
- var half = Math.floor(total / 2);
6248
- return char.repeat(half) + s + char.repeat(total - half);
6794
+ function complement(fn) {
6795
+ return function() { return !fn.apply(this, arguments); };
6249
6796
  }`);
6250
6797
  }
6251
6798
  parts.push("// \u2500\u2500 end stdlib \u2500\u2500\n");