@xnoxs/flux-lang 3.4.7 → 3.4.9

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.
@@ -8,6 +8,8 @@ function includes(arr, val) { return arr.includes(val); }
8
8
 
9
9
  function trim(s) { return String(s).trim(); }
10
10
 
11
+ function startsWith(s, prefix) { return String(s).startsWith(prefix); }
12
+
11
13
  function endsWith(s, suffix) { return String(s).endsWith(suffix); }
12
14
 
13
15
  function repeat(s, n) { return String(s).repeat(n); }
@@ -120,10 +122,8 @@ class Bundler {
120
122
  lines.push("\"use strict\";");
121
123
  lines.push("");
122
124
  }
123
- // flux_modules resolver: patches Module._resolveFilename so require() looks in
124
- // flux_modules/node_modules/ first (packages installed via `flux install`).
125
125
  lines.push("// flux_modules resolver");
126
- lines.push("(function(){var _p=require('path'),_fs=require('fs'),_M=require('module'),_d=_p.join(process.cwd(),'flux_modules','node_modules');if(_fs.existsSync(_d)){var _o=_M._resolveFilename.bind(_M);_M._resolveFilename=function(r,p,m,op){if(!r.startsWith('.')&&!r.startsWith('/')&&!r.startsWith('node:')){var _fp=_p.join(_d,r.split('/')[0]);if(_fs.existsSync(_fp)){try{return _o(_p.join(_d,r),p,m,op);}catch(_e){}}}return _o(r,p,m,op);};}})();");
126
+ lines.push(`(function()${var _p=require('path'),_fs=require('fs'),_M=require('module'),_d=_p.join(process.cwd(),'flux_modules','node_modules');if(_fs.existsSync(_d)){var _o=_M._resolveFilename.bind(_M);_M._resolveFilename=function(r,p,m,op){if(!r.startsWith('.')&&!r.startsWith('/')&&!r.startsWith('node:')){var _fp=_p.join(_d,r.split('/')[0]);if(_fs.existsSync(_fp)){try{return _o(_p.join(_d,r),p,m,op);}catch(_e){}}}return _o(r,p,m,op);};}})();`);
127
127
  lines.push("");
128
128
  lines.push("(function() {");
129
129
  lines.push("");
package/src/self/cli.flux CHANGED
@@ -775,7 +775,8 @@ flux run src/main.flux
775
775
  │ └── utils.flux # Utility functions
776
776
  ├── tests/
777
777
  │ └── main.test.flux # Test suite
778
- ├── flux.json # Project config
778
+ ├── flux_modules/ # Packages installed by \`flux install\` (gitignored)
779
+ ├── flux.json # Project config & dependencies
779
780
  └── README.md
780
781
  \`\`\`
781
782
 
@@ -820,6 +821,10 @@ flux run src/main.flux
820
821
  console.log(" " + yellow("cd " + projectName))
821
822
  console.log(" " + yellow("flux run src/main.flux"))
822
823
  console.log()
824
+ console.log(gray(" Add packages (installed into flux_modules/):"))
825
+ console.log(" " + yellow("flux add <package>"))
826
+ console.log(" " + yellow("flux install"))
827
+ console.log()
823
828
  console.log(gray(" Or run the test suite:"))
824
829
  console.log(" " + yellow("flux test tests/"))
825
830
  console.log()
package/src/self/cli.js CHANGED
@@ -57,7 +57,7 @@ const { loadConfig } = require("./config");
57
57
  const { cmdAdd, cmdRemove, cmdInstall, cmdList, cmdSearch, cmdInfo, cmdPublish } = require("./pkg");
58
58
  const VERSION = (FLUX_VERSION ?? "3.0.0");
59
59
  const STAGE = (FLUX_STAGE ?? "self-hosted");
60
- const C = { reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", red: "\x1b[31m", green: "\x1b[32m", yellow: "\x1b[33m", blue: "\x1b[34m", cyan: "\x1b[36m", white: "\x1b[37m", gray: "\x1b[90m", magenta: "\x1b[35m" };
60
+ const C = { reset: "\\u001b[0m", bold: "\\u001b[1m", dim: "\\u001b[2m", red: "\\u001b[31m", green: "\\u001b[32m", yellow: "\\u001b[33m", blue: "\\u001b[34m", cyan: "\\u001b[36m", white: "\\u001b[37m", gray: "\\u001b[90m", magenta: "\\u001b[35m" };
61
61
  const noColor = (process.env.NO_COLOR || !process.stdout.isTTY);
62
62
  function clr(c, s) {
63
63
  return (noColor ? s : ((c + s) + C.reset));
@@ -586,7 +586,7 @@ function cmdInit(name, opts) {
586
586
  const testFlux = "// Tests for {projectName}\n// Run: flux test tests/\n\n// ── Functions under test ──────────────────────────────────────\nfn add(a, b):\n return a + b\n\nfn mul(a, b):\n return a * b\n\nfn clamp(value, lo, hi):\n if value < lo: return lo\n if value > hi: return hi\n return value\n\nfn average(nums):\n if nums.length == 0: return 0\n return nums.reduce((s, x) -> s + x, 0) / nums.length\n\ntype Result = Ok(value) | Err(message)\n\nfn safeDivide(a, b):\n if b == 0: return Err(\"div by zero\")\n return Ok(a / b)\n\n// ── Test functions ────────────────────────────────────────────\nfn test_add():\n assert(add(1, 2) == 3, \"1+2=3\")\n assert(add(0, 0) == 0, \"0+0=0\")\n assert(add(-1, 1) == 0, \"-1+1=0\")\n\nfn test_mul():\n assert(mul(3, 4) == 12, \"3*4=12\")\n assert(mul(0, 5) == 0, \"0*5=0\")\n\nfn test_clamp():\n assert(clamp(5, 0, 10) == 5, \"within range\")\n assert(clamp(-1, 0, 10) == 0, \"below min\")\n assert(clamp(15, 0, 10) == 10, \"above max\")\n\nfn test_average():\n assert(average([2, 4, 6]) == 4, \"average of 2,4,6\")\n assert(average([]) == 0, \"empty list\")\n\nfn test_safe_divide():\n val ok = safeDivide(10, 2)\n match ok:\n when Ok(v): assert(v == 5, \"10/2=5\")\n when Err(e): assert(false, \"unexpected error\")\n val err = safeDivide(10, 0)\n match err:\n when Ok(v): assert(false, \"expected error\")\n when Err(e): assert(e == \"div by zero\", \"error message\")\n\nfn test_pipe_operator():\n val result = [1, 2, 3, 4, 5] |> filter(n -> n > 2) |> map(n -> n * 2)\n assert(result.length == 3, \"filter length\")\n assert(result[0] == 6, \"first element\")\n assert(result[2] == 10, \"last element\")";
587
587
  const fluxJson = { name: projectName, version: "1.0.0", description: (("A Flux Lang v" + VERSION) + " project"), author: "", license: "MIT", entry: "src/main.flux", outDir: "dist", sourcemap: false, typecheck: true, scripts: { start: "flux run src/main.flux", build: "flux bundle src/main.flux -o dist/bundle.js", dev: "flux watch src/main.flux", check: "flux check src/main.flux", test: "flux test tests/", fmt: "flux fmt src/", lint: "flux lint src/" }, dependencies: { }, devDependencies: { "@xnoxs/flux-lang": ("^" + VERSION) } };
588
588
  const gitignore = "node_modules/\ndist/\nflux_modules/\n*.js.map\n.DS_Store\n";
589
- const readme = "# {projectName}\n\nA project built with [Flux Lang](https://flux-lang.dev) v{VERSION} — the self-hosted compiler.\n\n## Quick Start\n\n```bash\nflux run src/main.flux\n```\n\n## Project Structure\n\n```\n{projectName}/\n├── src/\n│ ├── main.flux # Entry point\n│ └── utils.flux # Utility functions\n├── tests/\n│ └── main.test.flux # Test suite\n├── flux.json # Project config\n└── README.md\n```\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `flux run src/main.flux` | Run the project |\n| `flux bundle src/main.flux -o dist/bundle.js` | Bundle to single file |\n| `flux watch src/main.flux` | Watch mode |\n| `flux check src/main.flux` | Type check + static analysis |\n| `flux test tests/` | Run all tests |\n| `flux fmt src/` | Format source code |\n| `flux lint src/` | Lint for issues |\n| `flux add <package>` | Add a dependency |";
589
+ const readme = "# {projectName}\n\nA project built with [Flux Lang](https://flux-lang.dev) v{VERSION} — the self-hosted compiler.\n\n## Quick Start\n\n```bash\nflux run src/main.flux\n```\n\n## Project Structure\n\n```\n{projectName}/\n├── src/\n│ ├── main.flux # Entry point\n│ └── utils.flux # Utility functions\n├── tests/\n│ └── main.test.flux # Test suite\n├── flux_modules/ # Packages installed by `flux install` (gitignored)\n├── flux.json # Project config & dependencies\n└── README.md\n```\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `flux run src/main.flux` | Run the project |\n| `flux bundle src/main.flux -o dist/bundle.js` | Bundle to single file |\n| `flux watch src/main.flux` | Watch mode |\n| `flux check src/main.flux` | Type check + static analysis |\n| `flux test tests/` | Run all tests |\n| `flux fmt src/` | Format source code |\n| `flux lint src/` | Lint for issues |\n| `flux add <package>` | Add a dependency |";
590
590
  const allFiles = [(projectName + "/src/main.flux"), (projectName + "/src/utils.flux"), (projectName + "/tests/main.test.flux"), (projectName + "/flux.json"), (projectName + "/.gitignore"), (projectName + "/README.md")];
591
591
  Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8");
592
592
  Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8");
@@ -606,6 +606,10 @@ function cmdInit(name, opts) {
606
606
  console.log((" " + yellow(("cd " + projectName))));
607
607
  console.log((" " + yellow("flux run src/main.flux")));
608
608
  console.log();
609
+ console.log(gray(" Add packages (installed into flux_modules/):"));
610
+ console.log((" " + yellow("flux add <package>")));
611
+ console.log((" " + yellow("flux install")));
612
+ console.log();
609
613
  console.log(gray(" Or run the test suite:"));
610
614
  console.log((" " + yellow("flux test tests/")));
611
615
  console.log();
package/src/self/pkg.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // ── Flux stdlib ──
2
2
 
3
+ function map(arr, fn) { return arr.map(fn); }
4
+
3
5
  function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
4
6
 
5
7
  function keys(obj) { return Object.keys(obj); }
@@ -19,7 +21,7 @@ const { readPackage, writeConfig, loadConfig } = require("./config");
19
21
  const REGISTRY_URL = "https://registry.npmjs.org";
20
22
  const FLUX_PKG_DIR = "flux_modules";
21
23
  const PKG_FILE = "flux.json";
22
- const C = { 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" };
24
+ const C = { 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" };
23
25
  function clr(c, s) {
24
26
  return ((c + s) + C.reset);
25
27
  }
@@ -142,8 +144,9 @@ async function cmdInstall(opts) {
142
144
  const { execSync } = require("child_process");
143
145
  const cwd = process.cwd();
144
146
  const pkg = ensureFluxJson(cwd);
145
- const deps = (pkg.dependencies ?? {});
146
- const devDeps = (pkg.devDependencies ?? {});
147
+ const fluxModDir = Path.join(cwd, "flux_modules");
148
+ const deps = (pkg.dependencies ?? { });
149
+ const devDeps = (pkg.devDependencies ?? { });
147
150
  const all = { ...deps, ...devDeps };
148
151
  const names = Object.keys(all);
149
152
  if ((names.length == 0)) {
@@ -156,38 +159,36 @@ async function cmdInstall(opts) {
156
159
  console.log(((clr(C.gray, " ○ ") + name) + clr(C.gray, ("@" + spec))));
157
160
  }
158
161
  console.log();
159
-
160
- // Ensure flux_modules/ exists with a minimal package.json
161
- const fluxModDir = Path.join(cwd, "flux_modules");
162
- if (!Fs.existsSync(fluxModDir)) Fs.mkdirSync(fluxModDir, { recursive: true });
162
+ if (!Fs.existsSync(fluxModDir)) {
163
+ Fs.mkdirSync(fluxModDir, { recursive: true });
164
+ }
163
165
  const fluxPkgFile = Path.join(fluxModDir, "package.json");
164
166
  if (!Fs.existsSync(fluxPkgFile)) {
165
- const fluxPkg = { name: (pkg.name || "flux-project") + "-flux-modules", version: "1.0.0", private: true };
166
- Fs.writeFileSync(fluxPkgFile, JSON.stringify(fluxPkg, null, 2) + "\n", "utf8");
167
+ const fluxPkg = { name: (pkg.name + "-flux-modules"), version: "1.0.0", private: true };
168
+ Fs.writeFileSync(fluxPkgFile, (JSON.stringify(fluxPkg, null, 2) + "\n"), "utf8");
167
169
  }
168
-
169
170
  const prodNames = Object.keys(deps);
170
- const devNames = Object.keys(devDeps);
171
-
171
+ const devNames = Object.keys(devDeps);
172
172
  try {
173
- if (prodNames.length > 0) {
174
- const prodPkgs = prodNames.map(n => n + "@" + (deps[n] ?? "latest")).join(" ");
175
- const installCmd = "npm install --prefix " + fluxModDir + " " + prodPkgs;
176
- info("Running: " + installCmd);
177
- execSync(installCmd, { cwd: cwd, stdio: "inherit" });
173
+ if ((prodNames.length > 0)) {
174
+ const prodPkgs = prodNames.map((n) => ((n + "@") + (deps[n] ?? "latest"))).join(" ");
175
+ const installCmd = ((("npm install --prefix " + fluxModDir) + " ") + prodPkgs);
176
+ info(("Running: " + installCmd));
177
+ execSync(installCmd, { cwd, stdio: "inherit" });
178
178
  }
179
- if (devNames.length > 0) {
180
- const devPkgs = devNames.map(n => n + "@" + (devDeps[n] ?? "latest")).join(" ");
181
- const devCmd = "npm install --prefix " + fluxModDir + " --save-dev " + devPkgs;
182
- info("Running: " + devCmd);
183
- execSync(devCmd, { cwd: cwd, stdio: "inherit" });
179
+ if ((devNames.length > 0)) {
180
+ const devPkgs = devNames.map((n) => ((n + "@") + (devDeps[n] ?? "latest"))).join(" ");
181
+ const devCmd = ((("npm install --prefix " + fluxModDir) + " --save-dev ") + devPkgs);
182
+ info(("Running: " + devCmd));
183
+ execSync(devCmd, { cwd, stdio: "inherit" });
184
184
  }
185
185
  console.log();
186
- ok(names.length + " package(s) installed into flux_modules/node_modules/");
186
+ ok((names.length + " package(s) installed into flux_modules/node_modules/"));
187
187
  info("Packages resolve automatically when using: flux run, flux bundle");
188
- } catch (e) {
188
+ }
189
+ catch (e) {
189
190
  console.log();
190
- err("Install failed: " + e.message);
191
+ err(("Install failed: " + e.message));
191
192
  info("Try manually: npm install --prefix ./flux_modules <package>");
192
193
  }
193
194
  console.log();
@@ -311,79 +312,4 @@ function cmdPublish(opts) {
311
312
  info("Run: flux publish --registry <url> for a custom registry");
312
313
  console.log();
313
314
  }
314
- module.exports.cmdPublish = cmdPublish;
315
-
316
- // ── flux upgrade [--check] ─────────────────────────────────────────────────
317
- // Checks all dependencies in flux.json for newer versions and updates them.
318
- // --check : dry-run, only show what would change without writing
319
- async function cmdUpgrade(opts) {
320
- const check = (opts && opts.check) || false;
321
- const cwd = process.cwd();
322
- const pkg = readPackage(cwd);
323
- if (!pkg) { err('No flux.json found. Run: flux init'); return; }
324
-
325
- const allDeps = Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {});
326
- const names = Object.keys(allDeps);
327
- if (names.length === 0) { info('No dependencies in flux.json'); return; }
328
-
329
- console.log();
330
- console.log(clr(C.cyan, ' Checking ' + names.length + ' package(s) for updates...\n'));
331
-
332
- let updated = 0;
333
- let upToDate = 0;
334
- let failed = 0;
335
-
336
- for (const name of names) {
337
- const current = allDeps[name].replace(/^[\^~>=<\s]+/, '');
338
- try {
339
- const data = await fetchJson(REGISTRY_URL + '/' + name);
340
- const latest = data['dist-tags'] && data['dist-tags'].latest;
341
- if (!latest) { err(name + ' — could not resolve latest'); failed++; continue; }
342
-
343
- const isDev = !!(pkg.devDependencies && pkg.devDependencies[name]);
344
- const tag = isDev ? clr(C.blue, ' (dev)') : '';
345
-
346
- if (current === latest) {
347
- console.log(' ' + clr(C.gray, '✓') + ' ' + clr(C.bold, name) + clr(C.gray, '@' + current + ' — up to date') + tag);
348
- upToDate++;
349
- } else {
350
- console.log(' ' + clr(C.yellow, '↑') + ' ' + clr(C.bold, name) + clr(C.gray, '@' + current) + ' → ' + clr(C.green, latest) + tag);
351
- if (!check) {
352
- if (isDev) {
353
- if (!pkg.devDependencies) pkg.devDependencies = {};
354
- pkg.devDependencies[name] = '^' + latest;
355
- } else {
356
- if (!pkg.dependencies) pkg.dependencies = {};
357
- pkg.dependencies[name] = '^' + latest;
358
- }
359
- }
360
- updated++;
361
- }
362
- } catch (e) {
363
- err(name + ' — ' + e.message);
364
- failed++;
365
- }
366
- }
367
-
368
- console.log();
369
- if (check) {
370
- console.log(clr(C.cyan, ' Check mode: no changes written.'));
371
- if (updated > 0) {
372
- console.log(clr(C.yellow, ' ' + updated + ' update(s) available. Run: flux upgrade'));
373
- } else {
374
- console.log(clr(C.green, ' All packages are up to date.'));
375
- }
376
- } else {
377
- if (updated > 0) {
378
- const pkgPath = Path.join(cwd, 'flux.json');
379
- Fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
380
- ok(updated + ' package(s) updated in flux.json');
381
- info('Run: flux install to apply changes');
382
- } else {
383
- console.log(clr(C.green, ' ✓ All packages are already up to date.'));
384
- }
385
- if (failed > 0) info(failed + ' package(s) could not be checked');
386
- }
387
- console.log();
388
- }
389
- module.exports.cmdUpgrade = cmdUpgrade;
315
+ module.exports.cmdPublish = cmdPublish;
@@ -21,7 +21,7 @@ function repeat(s, n) { return String(s).repeat(n); }
21
21
  const Fs = require("fs");
22
22
  const Path = require("path");
23
23
  const Os = require("os");
24
- const C = { reset: "\x1b[0m", bold: "\x1b[1m", red: "\x1b[31m", green: "\x1b[32m", yellow: "\x1b[33m", cyan: "\x1b[36m", gray: "\x1b[90m", dim: "\x1b[2m" };
24
+ const C = { reset: "\\u001b[0m", bold: "\\u001b[1m", red: "\\u001b[31m", green: "\\u001b[32m", yellow: "\\u001b[33m", cyan: "\\u001b[36m", gray: "\\u001b[90m", dim: "\\u001b[2m" };
25
25
  function clr(c, s) {
26
26
  return (process.env.NO_COLOR ? s : ((c + s) + C.reset));
27
27
  }