@xnoxs/flux-lang 3.4.8 → 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.8
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,6 +2285,10 @@ var require_parser = __commonJS({
2258
2285
  this.pos++;
2259
2286
  return { type: "TypeofExpr", operand: this.parseUnary() };
2260
2287
  }
2288
+ if (this.check(T.DELETE)) {
2289
+ this.pos++;
2290
+ return { type: "DeleteExpr", operand: this.parseUnary() };
2291
+ }
2261
2292
  return this.parseLambdaOrPostfix();
2262
2293
  }
2263
2294
  parseLambdaOrPostfix() {
@@ -3089,6 +3120,8 @@ function _fmt(v, s) {
3089
3120
  return `await ${this.genExpr(node.operand)}`;
3090
3121
  case "TypeofExpr":
3091
3122
  return `typeof ${this.genExpr(node.operand)}`;
3123
+ case "DeleteExpr":
3124
+ return `delete ${this.genExpr(node.operand)}`;
3092
3125
  case "SpreadExpr":
3093
3126
  return `...${this.genExpr(node.expr)}`;
3094
3127
  case "CallExpr": {
@@ -7219,7 +7252,7 @@ var require_package = __commonJS({
7219
7252
  "package.json"(exports2, module2) {
7220
7253
  module2.exports = {
7221
7254
  name: "@xnoxs/flux-lang",
7222
- version: "3.4.8",
7255
+ version: "3.5.0",
7223
7256
  description: "Flux \u2014 A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.",
7224
7257
  main: "dist/flux.cjs.js",
7225
7258
  module: "dist/flux.esm.js",
@@ -8576,8 +8609,10 @@ var require_pkg = __commonJS({
8576
8609
  var REGISTRY_URL = "https://registry.npmjs.org";
8577
8610
  var PKG_FILE = "flux.json";
8578
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;
8579
8614
  function clr2(c, s) {
8580
- return c + s + C2.reset;
8615
+ return noColor2 ? s : c + s + C2.reset;
8581
8616
  }
8582
8617
  function ok(msg) {
8583
8618
  console.log(clr2(C2.green, "\u2713 ") + msg);
@@ -8588,6 +8623,29 @@ var require_pkg = __commonJS({
8588
8623
  function info(msg) {
8589
8624
  console.log(clr2(C2.cyan, " ") + msg);
8590
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
+ }
8591
8649
  async function fetchJson(url) {
8592
8650
  const mod = url.startsWith("https") ? Https : Http;
8593
8651
  function doRequest(resolve, reject) {
@@ -8637,15 +8695,17 @@ var require_pkg = __commonJS({
8637
8695
  const isDev = (opts == null ? void 0 : opts.dev) ?? false;
8638
8696
  const cwd = process.cwd();
8639
8697
  const pkg = ensureFluxJson(cwd);
8698
+ let addedCount = 0;
8699
+ console.log();
8640
8700
  for (const spec of specs) {
8641
8701
  const { name, version } = parsePackageSpec(spec);
8642
- 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));
8643
8703
  try {
8644
8704
  const info_ = await fetchJson(REGISTRY_URL + "/" + name);
8645
8705
  const resolvedVersion = version == "latest" ? ((_a = info_["dist-tags"]) == null ? void 0 : _a.latest) ?? "1.0.0" : version;
8646
8706
  const versionInfo = (_b = info_.versions) == null ? void 0 : _b[resolvedVersion];
8647
8707
  if (!versionInfo) {
8648
- err("Version " + resolvedVersion + " not found for " + name);
8708
+ spinner.stop(false, clr2(C2.bold, name) + clr2(C2.gray, "@" + resolvedVersion) + " \u2014 version not found");
8649
8709
  continue;
8650
8710
  }
8651
8711
  const depKey = isDev ? "devDependencies" : "dependencies";
@@ -8654,16 +8714,18 @@ var require_pkg = __commonJS({
8654
8714
  }
8655
8715
  pkg[depKey][name] = "^" + resolvedVersion;
8656
8716
  saveFluxJson(pkg, cwd);
8657
- const desc = versionInfo.description ? clr2(C2.gray, " \u2014 " + versionInfo.description) : "";
8658
- ok(name + clr2(C2.green, "@" + resolvedVersion) + desc);
8659
- 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;
8660
8720
  } catch (e) {
8661
- err("Failed to fetch " + name + ": " + e.message);
8721
+ spinner.stop(false, clr2(C2.bold, name) + " \u2014 " + e.message);
8662
8722
  }
8663
8723
  }
8664
8724
  console.log();
8665
- console.log(clr2(C2.gray, " Run ") + clr2(C2.yellow, "flux install") + clr2(C2.gray, " to install packages"));
8666
- 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
+ }
8667
8729
  }
8668
8730
  module2.exports.cmdAdd = cmdAdd;
8669
8731
  function cmdRemove(names, opts) {
@@ -8696,49 +8758,56 @@ var require_pkg = __commonJS({
8696
8758
  const { execSync } = require("child_process");
8697
8759
  const cwd = process.cwd();
8698
8760
  const pkg = ensureFluxJson(cwd);
8761
+ const fluxModDir = Path.join(cwd, "flux_modules");
8699
8762
  const deps = pkg.dependencies ?? {};
8700
8763
  const devDeps = pkg.devDependencies ?? {};
8701
8764
  const all = { ...deps, ...devDeps };
8702
8765
  const names = Object.keys(all);
8703
8766
  if (names.length == 0) {
8767
+ console.log();
8704
8768
  info("No dependencies found in flux.json");
8769
+ console.log();
8705
8770
  return;
8706
8771
  }
8707
- 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();
8708
8775
  for (const name of names) {
8709
8776
  const spec = all[name];
8710
- 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);
8711
8780
  }
8712
8781
  console.log();
8713
- const fluxModDir = Path.join(cwd, "flux_modules");
8714
- if (!Fs.existsSync(fluxModDir)) Fs.mkdirSync(fluxModDir, { recursive: true });
8782
+ if (!Fs.existsSync(fluxModDir)) {
8783
+ Fs.mkdirSync(fluxModDir, { recursive: true });
8784
+ }
8715
8785
  const fluxPkgFile = Path.join(fluxModDir, "package.json");
8716
8786
  if (!Fs.existsSync(fluxPkgFile)) {
8717
- const fluxPkg = { name: (pkg.name || "flux-project") + "-flux-modules", version: "1.0.0", private: true };
8787
+ const fluxPkg = { name: pkg.name + "-flux-modules", version: "1.0.0", private: true };
8718
8788
  Fs.writeFileSync(fluxPkgFile, JSON.stringify(fluxPkg, null, 2) + "\n", "utf8");
8719
8789
  }
8720
8790
  const prodNames = Object.keys(deps);
8721
8791
  const devNames = Object.keys(devDeps);
8792
+ const spinner = createSpinner("Installing packages into flux_modules/");
8722
8793
  try {
8723
8794
  if (prodNames.length > 0) {
8724
8795
  const prodPkgs = prodNames.map((n) => n + "@" + (deps[n] ?? "latest")).join(" ");
8725
8796
  const installCmd = "npm install --prefix " + fluxModDir + " " + prodPkgs;
8726
- info("Running: " + installCmd);
8727
- execSync(installCmd, { cwd, stdio: "inherit" });
8797
+ execSync(installCmd, { cwd, stdio: "pipe" });
8728
8798
  }
8729
8799
  if (devNames.length > 0) {
8730
8800
  const devPkgs = devNames.map((n) => n + "@" + (devDeps[n] ?? "latest")).join(" ");
8731
8801
  const devCmd = "npm install --prefix " + fluxModDir + " --save-dev " + devPkgs;
8732
- info("Running: " + devCmd);
8733
- execSync(devCmd, { cwd, stdio: "inherit" });
8802
+ execSync(devCmd, { cwd, stdio: "pipe" });
8734
8803
  }
8804
+ spinner.stop(true, names.length + " package(s) installed into " + clr2(C2.gray, "flux_modules/"));
8735
8805
  console.log();
8736
- ok(names.length + " package(s) installed into flux_modules/node_modules/");
8737
- 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"));
8738
8807
  } catch (e) {
8808
+ spinner.stop(false, "Install failed: " + e.message);
8739
8809
  console.log();
8740
- err("Install failed: " + e.message);
8741
- 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>"));
8742
8811
  }
8743
8812
  console.log();
8744
8813
  }
@@ -8777,64 +8846,150 @@ var require_pkg = __commonJS({
8777
8846
  module2.exports.cmdList = cmdList;
8778
8847
  async function cmdSearch(query, opts) {
8779
8848
  var _a;
8780
- 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 + '"'));
8781
8851
  try {
8782
- 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";
8783
8853
  const results = await fetchJson(url);
8784
8854
  const objects = results.objects ?? [];
8785
8855
  if (objects.length == 0) {
8786
- info("No packages found for: " + query);
8856
+ spinner.stop(false, "No packages found for: " + query);
8787
8857
  console.log();
8788
8858
  return;
8789
8859
  }
8860
+ spinner.stop(true, "Found " + objects.length + " result(s) for " + clr2(C2.bold, '"' + query + '"'));
8861
+ console.log();
8790
8862
  for (const obj of objects) {
8791
8863
  const p = obj.package;
8792
8864
  console.log(" " + clr2(C2.bold, p.name) + clr2(C2.gray, " v" + p.version));
8793
8865
  if (p.description) {
8794
8866
  console.log(" " + clr2(C2.gray, p.description));
8795
8867
  }
8796
- 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
+ }
8797
8871
  console.log();
8798
8872
  }
8799
8873
  } catch (e) {
8800
- err("Search failed: " + e.message);
8874
+ spinner.stop(false, "Search failed: " + e.message);
8875
+ console.log();
8801
8876
  }
8802
8877
  }
8803
8878
  module2.exports.cmdSearch = cmdSearch;
8804
8879
  async function cmdInfo(name, opts) {
8805
8880
  var _a, _b, _c, _d, _e;
8806
- 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));
8807
8883
  try {
8808
8884
  const info_ = await fetchJson(REGISTRY_URL + "/" + name);
8809
8885
  const latest = ((_a = info_["dist-tags"]) == null ? void 0 : _a.latest) ?? "unknown";
8810
8886
  const ver = ((_b = info_.versions) == null ? void 0 : _b[latest]) ?? {};
8811
- 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();
8812
8889
  if (ver.description) {
8813
- console.log(" " + ver.description);
8890
+ console.log(" " + clr2(C2.gray, ver.description));
8814
8891
  }
8815
8892
  console.log();
8816
- console.log(clr2(C2.gray, " license: ") + (ver.license ?? "unknown"));
8817
- 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"));
8818
8895
  const homepage = ver.homepage ?? info_.homepage;
8819
8896
  if (homepage) {
8820
- console.log(clr2(C2.gray, " home: ") + clr2(C2.blue, homepage));
8897
+ console.log(" " + clr2(C2.gray, "home: ") + " " + clr2(C2.blue, homepage));
8821
8898
  }
8822
8899
  const repo = ((_d = ver.repository) == null ? void 0 : _d.url) ?? ((_e = info_.repository) == null ? void 0 : _e.url);
8823
8900
  if (repo) {
8824
- 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", "")));
8825
8902
  }
8826
8903
  const keywords = ver.keywords ?? [];
8827
8904
  if (keywords.length > 0) {
8828
- console.log(clr2(C2.gray, " tags: ") + keywords.slice(0, 8).join(", "));
8905
+ console.log(" " + clr2(C2.gray, "tags: ") + " " + keywords.slice(0, 8).join(", "));
8829
8906
  }
8830
8907
  console.log();
8831
- 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));
8832
8909
  console.log();
8833
8910
  } catch (e) {
8834
- err("Could not fetch info for " + name + ": " + e.message);
8911
+ spinner.stop(false, "Could not fetch info for " + name + ": " + e.message);
8912
+ console.log();
8835
8913
  }
8836
8914
  }
8837
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;
8838
8993
  function cmdPublish2(opts) {
8839
8994
  const cwd = process.cwd();
8840
8995
  const pkg = readPackage(cwd);
@@ -8862,80 +9017,6 @@ var require_pkg = __commonJS({
8862
9017
  console.log();
8863
9018
  }
8864
9019
  module2.exports.cmdPublish = cmdPublish2;
8865
- async function cmdUpgrade(opts) {
8866
- const check = opts && opts.check || false;
8867
- const cwd = process.cwd();
8868
- const pkg = readPackage(cwd);
8869
- if (!pkg) {
8870
- err("No flux.json found. Run: flux init");
8871
- return;
8872
- }
8873
- const allDeps = Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {});
8874
- const names = Object.keys(allDeps);
8875
- if (names.length === 0) {
8876
- info("No dependencies in flux.json");
8877
- return;
8878
- }
8879
- console.log();
8880
- console.log(clr2(C2.cyan, " Checking " + names.length + " package(s) for updates...\n"));
8881
- let updated = 0;
8882
- let upToDate = 0;
8883
- let failed = 0;
8884
- for (const name of names) {
8885
- const current = allDeps[name].replace(/^[\^~>=<\s]+/, "");
8886
- try {
8887
- const data = await fetchJson(REGISTRY_URL + "/" + name);
8888
- const latest = data["dist-tags"] && data["dist-tags"].latest;
8889
- if (!latest) {
8890
- err(name + " \u2014 could not resolve latest");
8891
- failed++;
8892
- continue;
8893
- }
8894
- const isDev = !!(pkg.devDependencies && pkg.devDependencies[name]);
8895
- const tag = isDev ? clr2(C2.blue, " (dev)") : "";
8896
- if (current === latest) {
8897
- console.log(" " + clr2(C2.gray, "\u2713") + " " + clr2(C2.bold, name) + clr2(C2.gray, "@" + current + " \u2014 up to date") + tag);
8898
- upToDate++;
8899
- } else {
8900
- console.log(" " + clr2(C2.yellow, "\u2191") + " " + clr2(C2.bold, name) + clr2(C2.gray, "@" + current) + " \u2192 " + clr2(C2.green, latest) + tag);
8901
- if (!check) {
8902
- if (isDev) {
8903
- if (!pkg.devDependencies) pkg.devDependencies = {};
8904
- pkg.devDependencies[name] = "^" + latest;
8905
- } else {
8906
- if (!pkg.dependencies) pkg.dependencies = {};
8907
- pkg.dependencies[name] = "^" + latest;
8908
- }
8909
- }
8910
- updated++;
8911
- }
8912
- } catch (e) {
8913
- err(name + " \u2014 " + e.message);
8914
- failed++;
8915
- }
8916
- }
8917
- console.log();
8918
- if (check) {
8919
- console.log(clr2(C2.cyan, " Check mode: no changes written."));
8920
- if (updated > 0) {
8921
- console.log(clr2(C2.yellow, " " + updated + " update(s) available. Run: flux upgrade"));
8922
- } else {
8923
- console.log(clr2(C2.green, " All packages are up to date."));
8924
- }
8925
- } else {
8926
- if (updated > 0) {
8927
- const pkgPath = Path.join(cwd, "flux.json");
8928
- Fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
8929
- ok(updated + " package(s) updated in flux.json");
8930
- info("Run: flux install to apply changes");
8931
- } else {
8932
- console.log(clr2(C2.green, " \u2713 All packages are already up to date."));
8933
- }
8934
- if (failed > 0) info(failed + " package(s) could not be checked");
8935
- }
8936
- console.log();
8937
- }
8938
- module2.exports.cmdUpgrade = cmdUpgrade;
8939
9020
  }
8940
9021
  });
8941
9022
 
@@ -8985,7 +9066,8 @@ var C = {
8985
9066
  gray: "\x1B[90m"
8986
9067
  };
8987
9068
  var colored = (c, s) => `${c}${s}${C.reset}`;
8988
- 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);
8989
9071
  var clr = (c, s) => noColor ? s : colored(c, s);
8990
9072
  function banner() {
8991
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.8
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,6 +2214,10 @@ var require_parser = __commonJS({
2187
2214
  this.pos++;
2188
2215
  return { type: "TypeofExpr", operand: this.parseUnary() };
2189
2216
  }
2217
+ if (this.check(T.DELETE)) {
2218
+ this.pos++;
2219
+ return { type: "DeleteExpr", operand: this.parseUnary() };
2220
+ }
2190
2221
  return this.parseLambdaOrPostfix();
2191
2222
  }
2192
2223
  parseLambdaOrPostfix() {
@@ -3018,6 +3049,8 @@ function _fmt(v, s) {
3018
3049
  return `await ${this.genExpr(node.operand)}`;
3019
3050
  case "TypeofExpr":
3020
3051
  return `typeof ${this.genExpr(node.operand)}`;
3052
+ case "DeleteExpr":
3053
+ return `delete ${this.genExpr(node.operand)}`;
3021
3054
  case "SpreadExpr":
3022
3055
  return `...${this.genExpr(node.expr)}`;
3023
3056
  case "CallExpr": {