@xnoxs/flux-lang 3.4.9 → 3.5.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/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [3.5.0] — 2026-06-26
11
+
12
+ ### Fixed
13
+ - **ANSI color rendering** — warna CLI (`\u001b[32m` dll) tidak tampil di terminal karena Flux lexer tidak memproses `\u` dan `\x` escape sequences dalam string literal; akibatnya `\\u001b` (literal) masuk ke compiled output dan terminal melihat raw text bukan ESC character. Diperbaiki di semua 3 string parser (double-quote, single-quote, backtick) di `src/lexer.js`
14
+ - **`TERM=dumb` color detection** — environment Replit punya `TERM=dumb` tapi `COLORTERM=truecolor`; color check sebelumnya hanya pakai `isTTY && TERM !== 'dumb'` sehingga warna selalu off. Fix: `hasColor = COLORTERM || FORCE_COLOR || (isTTY && TERM !== 'dumb')`
15
+
16
+ ### Added
17
+ - **Spinner animasi** di semua perintah async CLI:
18
+ - `flux add <pkg>` — spinner resolving → ✓ nama@versi + deskripsi
19
+ - `flux install` — daftar paket + spinner installing → ✓ N installed
20
+ - `flux upgrade [--check]` — spinner per-paket, tampilkan `@lama → baru` atau `— up to date`
21
+ - `flux search <query>` — spinner searching → ✓ Found N result(s)
22
+ - `flux info <pkg>` — spinner fetching → ✓ nama@versi + detail lengkap
23
+ - **`\u` dan `\x` escape support** di semua string literal Flux (termasuk string interpolation)
24
+
25
+ ---
26
+
10
27
  ## [3.4.4] — 2026-06-26
11
28
 
12
29
  ### Added
package/bin/flux.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
- require('../dist/flux-cli.js');
3
+ require('../src/cli.js');
package/dist/flux-cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /*!
3
- * flux-lang v3.4.9
3
+ * flux-lang v3.5.0
4
4
  * Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.
5
5
  * (c) 2026 Flux Lang Contributors
6
6
  * Released under the MIT License
@@ -153,6 +153,8 @@ var require_lexer = __commonJS({
153
153
  SATISFIES: "SATISFIES",
154
154
  IS: "IS",
155
155
  CONST: "CONST",
156
+ // Keywords — property/object operators
157
+ DELETE: "DELETE",
156
158
  // Operators
157
159
  PLUS: "PLUS",
158
160
  MINUS: "MINUS",
@@ -281,6 +283,7 @@ var require_lexer = __commonJS({
281
283
  satisfies: T.SATISFIES,
282
284
  is: T.IS,
283
285
  const: T.CONST,
286
+ delete: T.DELETE,
284
287
  true: "__TRUE__",
285
288
  false: "__FALSE__",
286
289
  null: "__NULL__"
@@ -347,7 +350,15 @@ var require_lexer = __commonJS({
347
350
  if (this.ch() === "\\") {
348
351
  this.adv();
349
352
  const e = this.adv();
350
- s += { n: "\n", t: " ", "`": "`", "\\": "\\" }[e] || "\\" + e;
353
+ if (e === "u") {
354
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
355
+ s += String.fromCodePoint(parseInt(hex, 16));
356
+ } else if (e === "x") {
357
+ const hex = this.adv() + this.adv();
358
+ s += String.fromCodePoint(parseInt(hex, 16));
359
+ } else {
360
+ s += { n: "\n", t: " ", r: "\r", "`": "`", "\\": "\\" }[e] || "\\" + e;
361
+ }
351
362
  } else {
352
363
  s += this.adv();
353
364
  }
@@ -374,7 +385,15 @@ var require_lexer = __commonJS({
374
385
  if (this.ch() === "\\") {
375
386
  this.adv();
376
387
  const e = this.adv();
377
- text += { n: "\n", t: " ", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
388
+ if (e === "u") {
389
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
390
+ text += String.fromCodePoint(parseInt(hex, 16));
391
+ } else if (e === "x") {
392
+ const hex = this.adv() + this.adv();
393
+ text += String.fromCodePoint(parseInt(hex, 16));
394
+ } else {
395
+ text += { n: "\n", t: " ", r: "\r", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
396
+ }
378
397
  } else if (this.ch() === "{") {
379
398
  parts.push({ type: "text", value: text });
380
399
  text = "";
@@ -569,7 +588,15 @@ var require_lexer = __commonJS({
569
588
  if (this.ch() === "\\") {
570
589
  this.adv();
571
590
  const e = this.adv();
572
- s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
591
+ if (e === "u") {
592
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
593
+ s += String.fromCodePoint(parseInt(hex, 16));
594
+ } else if (e === "x") {
595
+ const hex = this.adv() + this.adv();
596
+ s += String.fromCodePoint(parseInt(hex, 16));
597
+ } else {
598
+ s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
599
+ }
573
600
  } else {
574
601
  s += this.adv();
575
602
  }
@@ -2258,9 +2285,9 @@ var require_parser = __commonJS({
2258
2285
  this.pos++;
2259
2286
  return { type: "TypeofExpr", operand: this.parseUnary() };
2260
2287
  }
2261
- if (this.check(T.IDENT) && this.tokens[this.pos].value === "delete") {
2288
+ if (this.check(T.DELETE)) {
2262
2289
  this.pos++;
2263
- return { type: "UnaryExpr", op: "delete ", operand: this.parseUnary() };
2290
+ return { type: "DeleteExpr", operand: this.parseUnary() };
2264
2291
  }
2265
2292
  return this.parseLambdaOrPostfix();
2266
2293
  }
@@ -3093,6 +3120,8 @@ function _fmt(v, s) {
3093
3120
  return `await ${this.genExpr(node.operand)}`;
3094
3121
  case "TypeofExpr":
3095
3122
  return `typeof ${this.genExpr(node.operand)}`;
3123
+ case "DeleteExpr":
3124
+ return `delete ${this.genExpr(node.operand)}`;
3096
3125
  case "SpreadExpr":
3097
3126
  return `...${this.genExpr(node.expr)}`;
3098
3127
  case "CallExpr": {
@@ -7223,7 +7252,7 @@ var require_package = __commonJS({
7223
7252
  "package.json"(exports2, module2) {
7224
7253
  module2.exports = {
7225
7254
  name: "@xnoxs/flux-lang",
7226
- version: "3.4.9",
7255
+ version: "3.5.0",
7227
7256
  description: "Flux \u2014 A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.",
7228
7257
  main: "dist/flux.cjs.js",
7229
7258
  module: "dist/flux.esm.js",
@@ -8579,9 +8608,11 @@ var require_pkg = __commonJS({
8579
8608
  var { readPackage, writeConfig, loadConfig: loadConfig2 } = require_config2();
8580
8609
  var REGISTRY_URL = "https://registry.npmjs.org";
8581
8610
  var PKG_FILE = "flux.json";
8582
- var C2 = { reset: "\\u001b[0m", bold: "\\u001b[1m", dim: "\\u001b[2m", red: "\\u001b[31m", green: "\\u001b[32m", yellow: "\\u001b[33m", blue: "\\u001b[34m", cyan: "\\u001b[36m", gray: "\\u001b[90m" };
8611
+ var C2 = { reset: "\x1B[0m", bold: "\x1B[1m", dim: "\x1B[2m", red: "\x1B[31m", green: "\x1B[32m", yellow: "\x1B[33m", blue: "\x1B[34m", cyan: "\x1B[36m", gray: "\x1B[90m" };
8612
+ var hasColor2 = process.env.COLORTERM || process.env.FORCE_COLOR || process.stdout.isTTY && process.env.TERM != "dumb";
8613
+ var noColor2 = process.env.NO_COLOR || !hasColor2;
8583
8614
  function clr2(c, s) {
8584
- return c + s + C2.reset;
8615
+ return noColor2 ? s : c + s + C2.reset;
8585
8616
  }
8586
8617
  function ok(msg) {
8587
8618
  console.log(clr2(C2.green, "\u2713 ") + msg);
@@ -8592,6 +8623,29 @@ var require_pkg = __commonJS({
8592
8623
  function info(msg) {
8593
8624
  console.log(clr2(C2.cyan, " ") + msg);
8594
8625
  }
8626
+ function createSpinner(msg) {
8627
+ if (noColor2) {
8628
+ let _stop2 = function(ok_, done) {
8629
+ process.stdout.write(" " + (ok_ ? "\u2713" : "\u2717") + " " + done + "\n");
8630
+ };
8631
+ var _stop = _stop2;
8632
+ process.stdout.write(" " + msg + " ...\n");
8633
+ return { stop: _stop2 };
8634
+ }
8635
+ const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
8636
+ let fi = 0;
8637
+ function tick() {
8638
+ process.stdout.write("\r " + clr2(C2.cyan, frames[fi % frames.length]) + " " + msg + " ");
8639
+ fi = fi + 1;
8640
+ }
8641
+ const timer = setInterval(tick, 80);
8642
+ function stop(ok_, done) {
8643
+ clearInterval(timer);
8644
+ const icon = ok_ ? clr2(C2.green, "\u2713") : clr2(C2.red, "\u2717");
8645
+ process.stdout.write("\r " + icon + " " + done + " \n");
8646
+ }
8647
+ return { stop };
8648
+ }
8595
8649
  async function fetchJson(url) {
8596
8650
  const mod = url.startsWith("https") ? Https : Http;
8597
8651
  function doRequest(resolve, reject) {
@@ -8641,15 +8695,17 @@ var require_pkg = __commonJS({
8641
8695
  const isDev = (opts == null ? void 0 : opts.dev) ?? false;
8642
8696
  const cwd = process.cwd();
8643
8697
  const pkg = ensureFluxJson(cwd);
8698
+ let addedCount = 0;
8699
+ console.log();
8644
8700
  for (const spec of specs) {
8645
8701
  const { name, version } = parsePackageSpec(spec);
8646
- console.log(clr2(C2.cyan, "\n Adding ") + clr2(C2.bold, name) + clr2(C2.gray, "@" + version) + " ...");
8702
+ const spinner = createSpinner(clr2(C2.bold, name) + clr2(C2.gray, "@" + version));
8647
8703
  try {
8648
8704
  const info_ = await fetchJson(REGISTRY_URL + "/" + name);
8649
8705
  const resolvedVersion = version == "latest" ? ((_a = info_["dist-tags"]) == null ? void 0 : _a.latest) ?? "1.0.0" : version;
8650
8706
  const versionInfo = (_b = info_.versions) == null ? void 0 : _b[resolvedVersion];
8651
8707
  if (!versionInfo) {
8652
- err("Version " + resolvedVersion + " not found for " + name);
8708
+ spinner.stop(false, clr2(C2.bold, name) + clr2(C2.gray, "@" + resolvedVersion) + " \u2014 version not found");
8653
8709
  continue;
8654
8710
  }
8655
8711
  const depKey = isDev ? "devDependencies" : "dependencies";
@@ -8658,16 +8714,18 @@ var require_pkg = __commonJS({
8658
8714
  }
8659
8715
  pkg[depKey][name] = "^" + resolvedVersion;
8660
8716
  saveFluxJson(pkg, cwd);
8661
- const desc = versionInfo.description ? clr2(C2.gray, " \u2014 " + versionInfo.description) : "";
8662
- ok(name + clr2(C2.green, "@" + resolvedVersion) + desc);
8663
- info("Added to " + (isDev ? "devDependencies" : "dependencies"));
8717
+ const shortDesc = versionInfo.description ? clr2(C2.gray, " \u2014 " + versionInfo.description.slice(0, 55)) : "";
8718
+ spinner.stop(true, clr2(C2.bold, name) + clr2(C2.green, "@" + resolvedVersion) + shortDesc);
8719
+ addedCount = addedCount + 1;
8664
8720
  } catch (e) {
8665
- err("Failed to fetch " + name + ": " + e.message);
8721
+ spinner.stop(false, clr2(C2.bold, name) + " \u2014 " + e.message);
8666
8722
  }
8667
8723
  }
8668
8724
  console.log();
8669
- console.log(clr2(C2.gray, " Run ") + clr2(C2.yellow, "flux install") + clr2(C2.gray, " to install packages"));
8670
- console.log();
8725
+ if (addedCount > 0) {
8726
+ console.log(" " + clr2(C2.gray, "Run ") + clr2(C2.yellow, "flux install") + clr2(C2.gray, " to install packages"));
8727
+ console.log();
8728
+ }
8671
8729
  }
8672
8730
  module2.exports.cmdAdd = cmdAdd;
8673
8731
  function cmdRemove(names, opts) {
@@ -8706,13 +8764,19 @@ var require_pkg = __commonJS({
8706
8764
  const all = { ...deps, ...devDeps };
8707
8765
  const names = Object.keys(all);
8708
8766
  if (names.length == 0) {
8767
+ console.log();
8709
8768
  info("No dependencies found in flux.json");
8769
+ console.log();
8710
8770
  return;
8711
8771
  }
8712
- console.log(clr2(C2.cyan, "\n Installing ") + names.length + " package(s) into flux_modules/...\n");
8772
+ console.log();
8773
+ console.log(" " + clr2(C2.bold, pkg.name ?? "project") + clr2(C2.gray, " \u2014 " + names.length + " package(s)"));
8774
+ console.log();
8713
8775
  for (const name of names) {
8714
8776
  const spec = all[name];
8715
- console.log(clr2(C2.gray, " \u25CB ") + name + clr2(C2.gray, "@" + spec));
8777
+ const isDev_ = Object.prototype.hasOwnProperty.call(devDeps, name);
8778
+ const tag = isDev_ ? clr2(C2.gray, " dev") : "";
8779
+ console.log(" " + clr2(C2.gray, "\u25CB") + " " + clr2(isDev_ ? C2.blue : C2.green, name) + clr2(C2.gray, "@" + spec) + tag);
8716
8780
  }
8717
8781
  console.log();
8718
8782
  if (!Fs.existsSync(fluxModDir)) {
@@ -8725,26 +8789,25 @@ var require_pkg = __commonJS({
8725
8789
  }
8726
8790
  const prodNames = Object.keys(deps);
8727
8791
  const devNames = Object.keys(devDeps);
8792
+ const spinner = createSpinner("Installing packages into flux_modules/");
8728
8793
  try {
8729
8794
  if (prodNames.length > 0) {
8730
8795
  const prodPkgs = prodNames.map((n) => n + "@" + (deps[n] ?? "latest")).join(" ");
8731
8796
  const installCmd = "npm install --prefix " + fluxModDir + " " + prodPkgs;
8732
- info("Running: " + installCmd);
8733
- execSync(installCmd, { cwd, stdio: "inherit" });
8797
+ execSync(installCmd, { cwd, stdio: "pipe" });
8734
8798
  }
8735
8799
  if (devNames.length > 0) {
8736
8800
  const devPkgs = devNames.map((n) => n + "@" + (devDeps[n] ?? "latest")).join(" ");
8737
8801
  const devCmd = "npm install --prefix " + fluxModDir + " --save-dev " + devPkgs;
8738
- info("Running: " + devCmd);
8739
- execSync(devCmd, { cwd, stdio: "inherit" });
8802
+ execSync(devCmd, { cwd, stdio: "pipe" });
8740
8803
  }
8804
+ spinner.stop(true, names.length + " package(s) installed into " + clr2(C2.gray, "flux_modules/"));
8741
8805
  console.log();
8742
- ok(names.length + " package(s) installed into flux_modules/node_modules/");
8743
- info("Packages resolve automatically when using: flux run, flux bundle");
8806
+ console.log(" " + clr2(C2.gray, "Packages resolve automatically when using: ") + clr2(C2.yellow, "flux run") + clr2(C2.gray, ", ") + clr2(C2.yellow, "flux bundle"));
8744
8807
  } catch (e) {
8808
+ spinner.stop(false, "Install failed: " + e.message);
8745
8809
  console.log();
8746
- err("Install failed: " + e.message);
8747
- info("Try manually: npm install --prefix ./flux_modules <package>");
8810
+ console.log(" " + clr2(C2.gray, "Try: ") + clr2(C2.yellow, "npm install --prefix ./flux_modules <package>"));
8748
8811
  }
8749
8812
  console.log();
8750
8813
  }
@@ -8783,64 +8846,150 @@ var require_pkg = __commonJS({
8783
8846
  module2.exports.cmdList = cmdList;
8784
8847
  async function cmdSearch(query, opts) {
8785
8848
  var _a;
8786
- console.log(clr2(C2.cyan, "\n Searching for ") + clr2(C2.bold, '"' + query + '"') + " ...\n");
8849
+ console.log();
8850
+ const spinner = createSpinner("Searching for " + clr2(C2.bold, '"' + query + '"'));
8787
8851
  try {
8788
- const url = REGISTRY_URL + "/-/v1/search?text=" + encodeURIComponent(query + " keywords:flux") + "&size=10";
8852
+ const url = REGISTRY_URL + "/-/v1/search?text=" + encodeURIComponent(query) + "&size=10";
8789
8853
  const results = await fetchJson(url);
8790
8854
  const objects = results.objects ?? [];
8791
8855
  if (objects.length == 0) {
8792
- info("No packages found for: " + query);
8856
+ spinner.stop(false, "No packages found for: " + query);
8793
8857
  console.log();
8794
8858
  return;
8795
8859
  }
8860
+ spinner.stop(true, "Found " + objects.length + " result(s) for " + clr2(C2.bold, '"' + query + '"'));
8861
+ console.log();
8796
8862
  for (const obj of objects) {
8797
8863
  const p = obj.package;
8798
8864
  console.log(" " + clr2(C2.bold, p.name) + clr2(C2.gray, " v" + p.version));
8799
8865
  if (p.description) {
8800
8866
  console.log(" " + clr2(C2.gray, p.description));
8801
8867
  }
8802
- console.log(" " + clr2(C2.blue, ((_a = p.links) == null ? void 0 : _a.npm) ?? ""));
8868
+ if ((_a = p.links) == null ? void 0 : _a.npm) {
8869
+ console.log(" " + clr2(C2.blue, p.links.npm));
8870
+ }
8803
8871
  console.log();
8804
8872
  }
8805
8873
  } catch (e) {
8806
- err("Search failed: " + e.message);
8874
+ spinner.stop(false, "Search failed: " + e.message);
8875
+ console.log();
8807
8876
  }
8808
8877
  }
8809
8878
  module2.exports.cmdSearch = cmdSearch;
8810
8879
  async function cmdInfo(name, opts) {
8811
8880
  var _a, _b, _c, _d, _e;
8812
- console.log(clr2(C2.cyan, "\n Fetching info for ") + clr2(C2.bold, name) + " ...\n");
8881
+ console.log();
8882
+ const spinner = createSpinner("Fetching info for " + clr2(C2.bold, name));
8813
8883
  try {
8814
8884
  const info_ = await fetchJson(REGISTRY_URL + "/" + name);
8815
8885
  const latest = ((_a = info_["dist-tags"]) == null ? void 0 : _a.latest) ?? "unknown";
8816
8886
  const ver = ((_b = info_.versions) == null ? void 0 : _b[latest]) ?? {};
8817
- console.log(clr2(C2.bold, " " + name) + clr2(C2.gray, " v" + latest));
8887
+ spinner.stop(true, clr2(C2.bold, name) + clr2(C2.green, "@" + latest));
8888
+ console.log();
8818
8889
  if (ver.description) {
8819
- console.log(" " + ver.description);
8890
+ console.log(" " + clr2(C2.gray, ver.description));
8820
8891
  }
8821
8892
  console.log();
8822
- console.log(clr2(C2.gray, " license: ") + (ver.license ?? "unknown"));
8823
- console.log(clr2(C2.gray, " author: ") + (((_c = ver.author) == null ? void 0 : _c.name) ?? ver.author ?? "unknown"));
8893
+ console.log(" " + clr2(C2.gray, "license:") + " " + (ver.license ?? "unknown"));
8894
+ console.log(" " + clr2(C2.gray, "author: ") + " " + (((_c = ver.author) == null ? void 0 : _c.name) ?? ver.author ?? "unknown"));
8824
8895
  const homepage = ver.homepage ?? info_.homepage;
8825
8896
  if (homepage) {
8826
- console.log(clr2(C2.gray, " home: ") + clr2(C2.blue, homepage));
8897
+ console.log(" " + clr2(C2.gray, "home: ") + " " + clr2(C2.blue, homepage));
8827
8898
  }
8828
8899
  const repo = ((_d = ver.repository) == null ? void 0 : _d.url) ?? ((_e = info_.repository) == null ? void 0 : _e.url);
8829
8900
  if (repo) {
8830
- console.log(clr2(C2.gray, " repo: ") + clr2(C2.blue, repo.replace("git+", "").replace(".git", "")));
8901
+ console.log(" " + clr2(C2.gray, "repo: ") + " " + clr2(C2.blue, repo.replace("git+", "").replace(".git", "")));
8831
8902
  }
8832
8903
  const keywords = ver.keywords ?? [];
8833
8904
  if (keywords.length > 0) {
8834
- console.log(clr2(C2.gray, " tags: ") + keywords.slice(0, 8).join(", "));
8905
+ console.log(" " + clr2(C2.gray, "tags: ") + " " + keywords.slice(0, 8).join(", "));
8835
8906
  }
8836
8907
  console.log();
8837
- console.log(clr2(C2.gray, " Install: ") + clr2(C2.yellow, "flux add " + name));
8908
+ console.log(" " + clr2(C2.gray, "Install: ") + clr2(C2.yellow, "flux add " + name));
8838
8909
  console.log();
8839
8910
  } catch (e) {
8840
- err("Could not fetch info for " + name + ": " + e.message);
8911
+ spinner.stop(false, "Could not fetch info for " + name + ": " + e.message);
8912
+ console.log();
8841
8913
  }
8842
8914
  }
8843
8915
  module2.exports.cmdInfo = cmdInfo;
8916
+ async function cmdUpgrade(opts) {
8917
+ var _a, _b;
8918
+ const isCheck = (opts == null ? void 0 : opts.check) ?? false;
8919
+ const cwd = process.cwd();
8920
+ const pkg = ensureFluxJson(cwd);
8921
+ const deps = pkg.dependencies ?? {};
8922
+ const devDeps = pkg.devDependencies ?? {};
8923
+ const allKeys = [...Object.keys(deps), ...Object.keys(devDeps)];
8924
+ if (allKeys.length == 0) {
8925
+ console.log();
8926
+ info("No dependencies to upgrade");
8927
+ console.log();
8928
+ return;
8929
+ }
8930
+ console.log();
8931
+ let updated = 0;
8932
+ for (const name of Object.keys(deps)) {
8933
+ const spinner = createSpinner(clr2(C2.green, name));
8934
+ try {
8935
+ const info_ = await fetchJson(REGISTRY_URL + "/" + name);
8936
+ const latest = ((_a = info_["dist-tags"]) == null ? void 0 : _a.latest) ?? null;
8937
+ if (!latest) {
8938
+ spinner.stop(false, clr2(C2.green, name) + " \u2014 could not resolve latest version");
8939
+ continue;
8940
+ }
8941
+ const current = deps[name].replace("^", "").replace("~", "");
8942
+ if (latest == current) {
8943
+ spinner.stop(true, clr2(C2.green, name) + clr2(C2.gray, "@" + current + " \u2014 up to date"));
8944
+ } else {
8945
+ spinner.stop(true, clr2(C2.green, name) + clr2(C2.gray, "@" + current) + " \u2192 " + clr2(C2.yellow, latest));
8946
+ if (!isCheck) {
8947
+ pkg.dependencies[name] = "^" + latest;
8948
+ updated = updated + 1;
8949
+ }
8950
+ }
8951
+ } catch (e) {
8952
+ spinner.stop(false, clr2(C2.green, name) + " \u2014 " + e.message);
8953
+ }
8954
+ }
8955
+ for (const name of Object.keys(devDeps)) {
8956
+ const spinner = createSpinner(clr2(C2.blue, name) + clr2(C2.gray, " (dev)"));
8957
+ try {
8958
+ const info_ = await fetchJson(REGISTRY_URL + "/" + name);
8959
+ const latest = ((_b = info_["dist-tags"]) == null ? void 0 : _b.latest) ?? null;
8960
+ if (!latest) {
8961
+ spinner.stop(false, clr2(C2.blue, name) + " \u2014 could not resolve latest version");
8962
+ continue;
8963
+ }
8964
+ const current = devDeps[name].replace("^", "").replace("~", "");
8965
+ if (latest == current) {
8966
+ spinner.stop(true, clr2(C2.blue, name) + clr2(C2.gray, "@" + current + " \u2014 up to date"));
8967
+ } else {
8968
+ spinner.stop(true, clr2(C2.blue, name) + clr2(C2.gray, "@" + current) + " \u2192 " + clr2(C2.yellow, latest) + clr2(C2.gray, " (dev)"));
8969
+ if (!isCheck) {
8970
+ pkg.devDependencies[name] = "^" + latest;
8971
+ updated = updated + 1;
8972
+ }
8973
+ }
8974
+ } catch (e) {
8975
+ spinner.stop(false, clr2(C2.blue, name) + " \u2014 " + e.message);
8976
+ }
8977
+ }
8978
+ console.log();
8979
+ if (isCheck) {
8980
+ ok("Check complete \u2014 run " + clr2(C2.yellow, "flux upgrade") + " to apply upgrades");
8981
+ } else {
8982
+ if (updated > 0) {
8983
+ saveFluxJson(pkg, cwd);
8984
+ ok(updated + " package(s) updated in flux.json");
8985
+ console.log(" " + clr2(C2.gray, "Run ") + clr2(C2.yellow, "flux install") + clr2(C2.gray, " to install upgraded packages"));
8986
+ } else {
8987
+ ok("All packages are already up to date");
8988
+ }
8989
+ }
8990
+ console.log();
8991
+ }
8992
+ module2.exports.cmdUpgrade = cmdUpgrade;
8844
8993
  function cmdPublish2(opts) {
8845
8994
  const cwd = process.cwd();
8846
8995
  const pkg = readPackage(cwd);
@@ -8917,7 +9066,8 @@ var C = {
8917
9066
  gray: "\x1B[90m"
8918
9067
  };
8919
9068
  var colored = (c, s) => `${c}${s}${C.reset}`;
8920
- var noColor = process.env.NO_COLOR || !process.stdout.isTTY;
9069
+ var hasColor = !!(process.env.COLORTERM || process.env.FORCE_COLOR || process.stdout.isTTY && process.env.TERM !== "dumb");
9070
+ var noColor = !!(process.env.NO_COLOR || !hasColor);
8921
9071
  var clr = (c, s) => noColor ? s : colored(c, s);
8922
9072
  function banner() {
8923
9073
  console.log(clr(C.cyan, C.bold + `
package/dist/flux.cjs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * flux-lang v3.4.9
2
+ * flux-lang v3.5.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
@@ -82,6 +82,8 @@ var require_lexer = __commonJS({
82
82
  SATISFIES: "SATISFIES",
83
83
  IS: "IS",
84
84
  CONST: "CONST",
85
+ // Keywords — property/object operators
86
+ DELETE: "DELETE",
85
87
  // Operators
86
88
  PLUS: "PLUS",
87
89
  MINUS: "MINUS",
@@ -210,6 +212,7 @@ var require_lexer = __commonJS({
210
212
  satisfies: T.SATISFIES,
211
213
  is: T.IS,
212
214
  const: T.CONST,
215
+ delete: T.DELETE,
213
216
  true: "__TRUE__",
214
217
  false: "__FALSE__",
215
218
  null: "__NULL__"
@@ -276,7 +279,15 @@ var require_lexer = __commonJS({
276
279
  if (this.ch() === "\\") {
277
280
  this.adv();
278
281
  const e = this.adv();
279
- s += { n: "\n", t: " ", "`": "`", "\\": "\\" }[e] || "\\" + e;
282
+ if (e === "u") {
283
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
284
+ s += String.fromCodePoint(parseInt(hex, 16));
285
+ } else if (e === "x") {
286
+ const hex = this.adv() + this.adv();
287
+ s += String.fromCodePoint(parseInt(hex, 16));
288
+ } else {
289
+ s += { n: "\n", t: " ", r: "\r", "`": "`", "\\": "\\" }[e] || "\\" + e;
290
+ }
280
291
  } else {
281
292
  s += this.adv();
282
293
  }
@@ -303,7 +314,15 @@ var require_lexer = __commonJS({
303
314
  if (this.ch() === "\\") {
304
315
  this.adv();
305
316
  const e = this.adv();
306
- text += { n: "\n", t: " ", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
317
+ if (e === "u") {
318
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
319
+ text += String.fromCodePoint(parseInt(hex, 16));
320
+ } else if (e === "x") {
321
+ const hex = this.adv() + this.adv();
322
+ text += String.fromCodePoint(parseInt(hex, 16));
323
+ } else {
324
+ text += { n: "\n", t: " ", r: "\r", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
325
+ }
307
326
  } else if (this.ch() === "{") {
308
327
  parts.push({ type: "text", value: text });
309
328
  text = "";
@@ -498,7 +517,15 @@ var require_lexer = __commonJS({
498
517
  if (this.ch() === "\\") {
499
518
  this.adv();
500
519
  const e = this.adv();
501
- s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
520
+ if (e === "u") {
521
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
522
+ s += String.fromCodePoint(parseInt(hex, 16));
523
+ } else if (e === "x") {
524
+ const hex = this.adv() + this.adv();
525
+ s += String.fromCodePoint(parseInt(hex, 16));
526
+ } else {
527
+ s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
528
+ }
502
529
  } else {
503
530
  s += this.adv();
504
531
  }
@@ -2187,9 +2214,9 @@ var require_parser = __commonJS({
2187
2214
  this.pos++;
2188
2215
  return { type: "TypeofExpr", operand: this.parseUnary() };
2189
2216
  }
2190
- if (this.check(T.IDENT) && this.tokens[this.pos].value === "delete") {
2217
+ if (this.check(T.DELETE)) {
2191
2218
  this.pos++;
2192
- return { type: "UnaryExpr", op: "delete ", operand: this.parseUnary() };
2219
+ return { type: "DeleteExpr", operand: this.parseUnary() };
2193
2220
  }
2194
2221
  return this.parseLambdaOrPostfix();
2195
2222
  }
@@ -3022,6 +3049,8 @@ function _fmt(v, s) {
3022
3049
  return `await ${this.genExpr(node.operand)}`;
3023
3050
  case "TypeofExpr":
3024
3051
  return `typeof ${this.genExpr(node.operand)}`;
3052
+ case "DeleteExpr":
3053
+ return `delete ${this.genExpr(node.operand)}`;
3025
3054
  case "SpreadExpr":
3026
3055
  return `...${this.genExpr(node.expr)}`;
3027
3056
  case "CallExpr": {
package/dist/flux.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * flux-lang v3.4.9
2
+ * flux-lang v3.5.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
@@ -87,6 +87,8 @@ var require_lexer = __commonJS({
87
87
  SATISFIES: "SATISFIES",
88
88
  IS: "IS",
89
89
  CONST: "CONST",
90
+ // Keywords — property/object operators
91
+ DELETE: "DELETE",
90
92
  // Operators
91
93
  PLUS: "PLUS",
92
94
  MINUS: "MINUS",
@@ -215,6 +217,7 @@ var require_lexer = __commonJS({
215
217
  satisfies: T.SATISFIES,
216
218
  is: T.IS,
217
219
  const: T.CONST,
220
+ delete: T.DELETE,
218
221
  true: "__TRUE__",
219
222
  false: "__FALSE__",
220
223
  null: "__NULL__"
@@ -281,7 +284,15 @@ var require_lexer = __commonJS({
281
284
  if (this.ch() === "\\") {
282
285
  this.adv();
283
286
  const e = this.adv();
284
- s += { n: "\n", t: " ", "`": "`", "\\": "\\" }[e] || "\\" + e;
287
+ if (e === "u") {
288
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
289
+ s += String.fromCodePoint(parseInt(hex, 16));
290
+ } else if (e === "x") {
291
+ const hex = this.adv() + this.adv();
292
+ s += String.fromCodePoint(parseInt(hex, 16));
293
+ } else {
294
+ s += { n: "\n", t: " ", r: "\r", "`": "`", "\\": "\\" }[e] || "\\" + e;
295
+ }
285
296
  } else {
286
297
  s += this.adv();
287
298
  }
@@ -308,7 +319,15 @@ var require_lexer = __commonJS({
308
319
  if (this.ch() === "\\") {
309
320
  this.adv();
310
321
  const e = this.adv();
311
- text += { n: "\n", t: " ", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
322
+ if (e === "u") {
323
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
324
+ text += String.fromCodePoint(parseInt(hex, 16));
325
+ } else if (e === "x") {
326
+ const hex = this.adv() + this.adv();
327
+ text += String.fromCodePoint(parseInt(hex, 16));
328
+ } else {
329
+ text += { n: "\n", t: " ", r: "\r", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
330
+ }
312
331
  } else if (this.ch() === "{") {
313
332
  parts.push({ type: "text", value: text });
314
333
  text = "";
@@ -503,7 +522,15 @@ var require_lexer = __commonJS({
503
522
  if (this.ch() === "\\") {
504
523
  this.adv();
505
524
  const e = this.adv();
506
- s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
525
+ if (e === "u") {
526
+ const hex = this.adv() + this.adv() + this.adv() + this.adv();
527
+ s += String.fromCodePoint(parseInt(hex, 16));
528
+ } else if (e === "x") {
529
+ const hex = this.adv() + this.adv();
530
+ s += String.fromCodePoint(parseInt(hex, 16));
531
+ } else {
532
+ s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
533
+ }
507
534
  } else {
508
535
  s += this.adv();
509
536
  }
@@ -2192,9 +2219,9 @@ var require_parser = __commonJS({
2192
2219
  this.pos++;
2193
2220
  return { type: "TypeofExpr", operand: this.parseUnary() };
2194
2221
  }
2195
- if (this.check(T.IDENT) && this.tokens[this.pos].value === "delete") {
2222
+ if (this.check(T.DELETE)) {
2196
2223
  this.pos++;
2197
- return { type: "UnaryExpr", op: "delete ", operand: this.parseUnary() };
2224
+ return { type: "DeleteExpr", operand: this.parseUnary() };
2198
2225
  }
2199
2226
  return this.parseLambdaOrPostfix();
2200
2227
  }
@@ -3027,6 +3054,8 @@ function _fmt(v, s) {
3027
3054
  return `await ${this.genExpr(node.operand)}`;
3028
3055
  case "TypeofExpr":
3029
3056
  return `typeof ${this.genExpr(node.operand)}`;
3057
+ case "DeleteExpr":
3058
+ return `delete ${this.genExpr(node.operand)}`;
3030
3059
  case "SpreadExpr":
3031
3060
  return `...${this.genExpr(node.expr)}`;
3032
3061
  case "CallExpr": {