@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.
- package/README.md +1 -1
- package/dist/flux-cli.js +18 -81
- package/dist/flux.cjs.js +5 -1
- package/dist/flux.esm.js +5 -1
- package/dist/flux.min.js +7 -7
- package/package.json +1 -1
- package/src/self/bundler.js +3 -3
- package/src/self/cli.flux +6 -1
- package/src/self/cli.js +6 -2
- package/src/self/pkg.js +27 -101
- package/src/self/test-runner.js +1 -1
- package/src/self/lexer.stage2.js +0 -700
package/src/self/bundler.js
CHANGED
|
@@ -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(
|
|
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
|
-
├──
|
|
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: "
|
|
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: "
|
|
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
|
|
146
|
-
const
|
|
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
|
-
|
|
161
|
-
|
|
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
|
|
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
|
|
171
|
-
|
|
171
|
+
const devNames = Object.keys(devDeps);
|
|
172
172
|
try {
|
|
173
|
-
if (prodNames.length > 0) {
|
|
174
|
-
const prodPkgs
|
|
175
|
-
const installCmd = "npm install --prefix " + fluxModDir + " " + prodPkgs;
|
|
176
|
-
info("Running: " + installCmd);
|
|
177
|
-
execSync(installCmd, { cwd
|
|
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
|
|
182
|
-
info("Running: " + devCmd);
|
|
183
|
-
execSync(devCmd, { cwd
|
|
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
|
-
}
|
|
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;
|
package/src/self/test-runner.js
CHANGED
|
@@ -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: "
|
|
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
|
}
|