@xnoxs/flux-lang 4.0.7 → 4.0.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/src/self/cli.js CHANGED
@@ -1,10 +1,12 @@
1
- /* compiled from src/self/cli.flux */
1
+ /* compiled from src/self/cli.flux by Flux Lang */
2
2
  'use strict';
3
3
  // ── Flux stdlib ──
4
4
 
5
- function forEach(arr, fn) { arr.forEach(fn); return arr; }
5
+ function map(arr, fn) { return arr.map(fn); }
6
6
 
7
- function find(arr, fn) { return arr.find(fn); }
7
+ function filter(arr, fn) { return arr.filter(fn); }
8
+
9
+ function reduce(arr, fn, init) { return arguments.length >= 3 ? arr.reduce(fn, init) : arr.reduce(fn); }
8
10
 
9
11
  function some(arr, fn) { return arr.some(fn); }
10
12
 
@@ -14,6 +16,10 @@ function clamp(val, min, max) {
14
16
  return Math.min(Math.max(val, min), max);
15
17
  }
16
18
 
19
+ function sum(arr) {
20
+ return arr.reduce(function(a, b) { return a + b; }, 0);
21
+ }
22
+
17
23
  function max(arr) {
18
24
  if (arguments.length > 1) return Math.max.apply(null, arguments);
19
25
  return Math.max.apply(null, arr);
@@ -92,20 +98,32 @@ function showHelp() {
92
98
  console.log(bold("USAGE:"));
93
99
  console.log(" flux <command> [options]\n");
94
100
  console.log(bold("COMPILER:"));
95
- const compilerCmds = [["compile <file.flux>", "Compile .flux → .js"], ["bundle <entry.flux>", "Bundle multi-file project into one .js"], ["run <file.flux>", "Compile and run a single-file script"], ["watch <file.flux>", "Watch for changes, auto-compile"], ["check <file.flux>", "Type-check and static analysis"]];
96
- compilerCmds.forEach((pair) => console.log((((" " + green(("flux " + pair[0]).padEnd(36))) + " ") + gray(pair[1]))));
101
+ const compilerCmds = [["compile <file.flux>", "Compile .flux → .js"], ["bundle <entry.flux>", "Bundle multiple files into one .js"], ["run <file.flux>", "Compile and run immediately"], ["watch <file.flux>", "Watch for changes, auto-compile"], ["check <file.flux>", "Type-check and static analysis"]];
102
+ for (const __item__ of compilerCmds) {
103
+ const [cmd, desc] = __item__;
104
+ console.log((((" " + green(("flux " + cmd).padEnd(36))) + " ") + gray(desc)));
105
+ }
97
106
  console.log();
98
107
  console.log(bold("TOOLING:"));
99
108
  const toolCmds = [["lint <file.flux>", "Full lint: types + style + immutability"], ["fmt <file.flux>", "Format source code in-place"], ["test [dir]", "Run *.test.flux files"], ["repl", "Interactive REPL mode"], ["tokens <file.flux>", "Show lexer token list"], ["ast <file.flux>", "Show Abstract Syntax Tree (JSON)"]];
100
- toolCmds.forEach((pair) => console.log((((" " + green(("flux " + pair[0]).padEnd(36))) + " ") + gray(pair[1]))));
109
+ for (const __item__ of toolCmds) {
110
+ const [cmd, desc] = __item__;
111
+ console.log((((" " + green(("flux " + cmd).padEnd(36))) + " ") + gray(desc)));
112
+ }
101
113
  console.log();
102
114
  console.log(bold("PACKAGE MANAGER:"));
103
- const pkgCmds = [["init [name] [--template]", "Scaffold a new Flux project"], ["add <pkg[@version]>", "Add a dependency (npm install --save)"], ["remove <pkg>", "Remove a dependency (npm uninstall)"], ["install", "Install all dependencies (npm install)"], ["list", "List installed packages"], ["search <query>", "Search the npm registry"], ["info <pkg>", "Show package details"], ["publish", "Publish package to npm registry"]];
104
- pkgCmds.forEach((pair) => console.log((((" " + cyan(("flux " + pair[0]).padEnd(36))) + " ") + gray(pair[1]))));
115
+ const pkgCmds = [["init [name]", "Scaffold a new Flux project"], ["add <pkg[@version]>", "Add a dependency"], ["remove <pkg>", "Remove a dependency"], ["install", "Install all dependencies"], ["list", "List installed packages"], ["search <query>", "Search the package registry"], ["info <pkg>", "Show package details"], ["publish", "Publish package to registry"]];
116
+ for (const __item__ of pkgCmds) {
117
+ const [cmd, desc] = __item__;
118
+ console.log((((" " + cyan(("flux " + cmd).padEnd(36))) + " ") + gray(desc)));
119
+ }
105
120
  console.log();
106
121
  console.log(bold("SELF-HOSTED:"));
107
122
  const selfCmds = [["self-hosted", "Show self-hosted compiler status"], ["self-hosted build", "Bootstrap: compile compiler with itself"], ["self-hosted verify", "Verify self-hosted output matches stage-0"]];
108
- selfCmds.forEach((pair) => console.log((((" " + yellow(("flux " + pair[0]).padEnd(36))) + " ") + gray(pair[1]))));
123
+ for (const __item__ of selfCmds) {
124
+ const [cmd, desc] = __item__;
125
+ console.log((((" " + yellow(("flux " + cmd).padEnd(36))) + " ") + gray(desc)));
126
+ }
109
127
  console.log();
110
128
  console.log(bold("OPTIONS:"));
111
129
  console.log(((" " + yellow("--out, -o <file> ")) + " Output file"));
@@ -115,12 +133,11 @@ function showHelp() {
115
133
  console.log(((" " + yellow("--typecheck ")) + " Enable type checking"));
116
134
  console.log(((" " + yellow("--stdout ")) + " Print to terminal"));
117
135
  console.log(((" " + yellow("--no-color ")) + " Disable colors"));
118
- console.log(((" " + yellow("--template ")) + " Init template: script, server, webapp"));
119
136
  console.log();
120
137
  }
121
138
  function parseArgs(argv) {
122
139
  const args = argv.slice(2);
123
- const opts = { out: null, sourcemap: false, mangle: false, typecheck: false, strict: false, stdout: false, watch: false, dev: false, verbose: false, jsx: false, jsxTarget: "browser", template: null };
140
+ const opts = { out: null, sourcemap: false, mangle: false, typecheck: false, strict: false, stdout: false, watch: false, dev: false, verbose: false, jsx: false, jsxTarget: "browser" };
124
141
  const positional = [];
125
142
  let i = 0;
126
143
  while ((i < args.length)) {
@@ -160,10 +177,6 @@ function parseArgs(argv) {
160
177
  i = (i + 1);
161
178
  opts.jsxTarget = args[i];
162
179
  }
163
- else if (((a == "--template") || (a == "-t"))) {
164
- i = (i + 1);
165
- opts.template = args[i];
166
- }
167
180
  else if (!a.startsWith("--")) {
168
181
  positional.push(a);
169
182
  }
@@ -232,21 +245,6 @@ function printErrors(errors, source, filePath) {
232
245
  }
233
246
  console.error();
234
247
  }
235
- function findFluxImports(source) {
236
- const found = [];
237
- const lines = source.split("\n");
238
- for (const line of lines) {
239
- const trimmed = line.trim();
240
- const m = trimmed.match(/^import\s+.+\s+from\s+["'](\.[^"']+)["']/);
241
- if (m) {
242
- const src = m[1];
243
- if (((!src.endsWith(".js") && !src.endsWith(".json")) && !src.endsWith(".node"))) {
244
- found.push(src);
245
- }
246
- }
247
- }
248
- return found;
249
- }
250
248
  function cmdCompile(filePath, opts) {
251
249
  const { source, abs } = readFluxFile(filePath);
252
250
  const cfg = loadConfig(Path.dirname(abs));
@@ -280,21 +278,6 @@ function cmdCompile(filePath, opts) {
280
278
  }
281
279
  function cmdRun(filePath, opts) {
282
280
  const { source, abs } = readFluxFile(filePath);
283
- const fluxImports = findFluxImports(source);
284
- if ((fluxImports.length > 0)) {
285
- const example = fluxImports[0];
286
- const entryRel = Path.relative(process.cwd(), abs);
287
- const outFile = (Path.basename(abs, ".flux") + ".js");
288
- console.error(red("\n✗ Cannot run a multi-file Flux project with `flux run`.\n"));
289
- console.error((" Found: " + yellow((("import ... from \"" + example) + "\""))));
290
- console.error();
291
- console.error(((" Use " + cyan("flux bundle")) + " to compile all files into one, then run it:\n"));
292
- console.error((" " + yellow(((("flux bundle " + entryRel) + " -o dist/") + outFile))));
293
- console.error((" " + yellow(("node dist/" + outFile))));
294
- console.error();
295
- console.error(((" Or use " + cyan("flux run")) + " only for single-file scripts (no inter-file .flux imports).\n"));
296
- process.exit(1);
297
- }
298
281
  const result = transpile(source, { jsx: (opts.jsx ?? false), jsxTarget: (opts.jsxTarget ?? "browser"), mangle: false });
299
282
  if (!result.success) {
300
283
  console.error(red("\n✗ Compile error"));
@@ -462,10 +445,6 @@ function cmdBundle(entryPath, opts) {
462
445
  console.log(result.code);
463
446
  return;
464
447
  }
465
- const outDir = Path.dirname(Path.resolve(outFile));
466
- if (!Fs.existsSync(outDir)) {
467
- Fs.mkdirSync(outDir, { recursive: true });
468
- }
469
448
  Fs.writeFileSync(outFile, result.code, "utf8");
470
449
  const kb = (result.code.length / 1024).toFixed(1);
471
450
  console.log((((((green("✓ Bundle done") + gray(((" (" + elapsed) + "ms) "))) + Path.basename(abs)) + gray(((" + " + (result.modules - 1)) + " module(s) → "))) + cyan(Path.relative(process.cwd(), outFile))) + gray(((" [" + kb) + " KB]"))));
@@ -596,7 +575,6 @@ function cmdRepl(opts) {
596
575
  }
597
576
  function cmdInit(name, opts) {
598
577
  const projectName = (name ?? "my-flux-app");
599
- const template = (opts.template ?? "script");
600
578
  const dir = Path.resolve(projectName);
601
579
  if (Fs.existsSync(dir)) {
602
580
  console.error(red(("✗ Directory already exists: " + projectName)));
@@ -605,77 +583,38 @@ function cmdInit(name, opts) {
605
583
  Fs.mkdirSync(dir, { recursive: true });
606
584
  Fs.mkdirSync(Path.join(dir, "src"), { recursive: true });
607
585
  Fs.mkdirSync(Path.join(dir, "tests"), { recursive: true });
608
- const gitignore = "node_modules/\ndist/\n*.js.map\n.DS_Store\n";
609
- const testFlux = "// Tests for {projectName}\n// Run: flux test tests/\n\nfn add(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 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_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\")";
610
- if ((template == "script")) {
611
- const mainFlux = "// {projectName} a Flux script\n// Run: npm run dev (or: node_modules/.bin/flux run src/main.flux)\n\nimport Fs from \"fs\"\nimport Path from \"path\"\n\nfn main():\n print(\"Hello from Flux!\")\n print(\"Node version: {process.version}\")\n\nmain()";
612
- const pkgJson = { name: projectName, version: "1.0.0", description: "A Flux project", main: "dist/main.js", scripts: { dev: "flux run src/main.flux", build: "flux bundle src/main.flux -o dist/main.js", start: "node dist/main.js", test: "flux test tests/" }, flux: { entry: "src/main.flux", outDir: "dist", mangle: false, sourcemap: false }, dependencies: { "@xnoxs/flux-lang": ("^" + VERSION) }, devDependencies: { } };
613
- Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8");
614
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8");
615
- Fs.writeFileSync(Path.join(dir, "package.json"), (JSON.stringify(pkgJson, null, 2) + "\n"), "utf8");
616
- Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8");
617
- console.log();
618
- console.log((((green("✓ Project ") + bold((projectName + "/"))) + green(" created with template ")) + cyan("script")));
619
- console.log();
620
- console.log(bold(" Next steps:"));
621
- console.log((" " + yellow(("cd " + projectName))));
622
- console.log((" " + yellow("npm install")));
623
- console.log((" " + yellow("npm run dev")));
624
- console.log();
625
- console.log(gray(" Add packages:"));
626
- console.log((" " + yellow("flux add <package>")));
627
- console.log();
628
- return;
629
- }
630
- if ((template == "server")) {
631
- const serverFlux = "// {projectName} — Flux HTTP server\n// Run: npm run dev\n// Build: npm run build && npm start\n\nimport Express from \"express\"\n\nval app = Express()\nval PORT = process.env.PORT or 3000\n\napp.use(Express.json())\n\napp.get(\"/\", (req, res) ->\n res.json({ status: \"ok\", message: \"Hello from Flux!\", port: PORT })\n)\n\napp.listen(PORT, -> print(\"Server running at http://localhost:{PORT}\"))";
632
- const pkgJson = { name: projectName, version: "1.0.0", description: "A Flux HTTP server", main: "dist/server.js", scripts: { dev: "flux run src/server.flux", build: "flux bundle src/server.flux -o dist/server.js", start: "node dist/server.js", test: "flux test tests/" }, flux: { entry: "src/server.flux", outDir: "dist", mangle: false, sourcemap: false }, dependencies: { "@xnoxs/flux-lang": ("^" + VERSION), express: "^4.18.0" }, devDependencies: { } };
633
- Fs.writeFileSync(Path.join(dir, "src", "server.flux"), serverFlux, "utf8");
634
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8");
635
- Fs.writeFileSync(Path.join(dir, "package.json"), (JSON.stringify(pkgJson, null, 2) + "\n"), "utf8");
636
- Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8");
637
- console.log();
638
- console.log((((green("✓ Project ") + bold((projectName + "/"))) + green(" created with template ")) + cyan("server")));
639
- console.log();
640
- console.log(bold(" Next steps:"));
641
- console.log((" " + yellow(("cd " + projectName))));
642
- console.log((" " + yellow("npm install")));
643
- console.log((" " + yellow("npm run dev")));
644
- console.log();
645
- console.log(gray(" Build for production:"));
646
- console.log((" " + yellow("npm run build && npm start")));
647
- console.log();
648
- return;
649
- }
650
- if ((template == "webapp")) {
651
- const utilsFlux = "// Utility functions\nexport fn formatDate(date):\n val d = new Date(date)\n return d.toISOString().split(\"T\")[0]\n\nexport fn paginate(items, page, perPage):\n val start = (page - 1) * perPage\n return items.slice(start, start + perPage)";
652
- const routesFlux = "// Route handlers\nimport { formatDate, paginate } from \"./utils\" // inter-file .flux import\n\nval items = [\n { id: 1, name: \"Item A\", date: \"2024-01-01\" },\n { id: 2, name: \"Item B\", date: \"2024-02-01\" },\n { id: 3, name: \"Item C\", date: \"2024-03-01\" },\n]\n\nexport fn setupRoutes(app):\n app.get(\"/items\", (req, res) ->\n val page = parseInt(req.query.page or \"1\")\n val perPage = parseInt(req.query.per_page or \"10\")\n val data = paginate(items, page, perPage)\n res.json({ data, page })\n )\n\n app.get(\"/items/:id\", (req, res) ->\n val item = items.find(i -> i.id == parseInt(req.params.id))\n if item == null:\n res.status(404).json({ error: \"Not found\" })\n else:\n res.json({ data: item, date: formatDate(item.date) })\n )";
653
- const serverFlux = "// Entry point — MUST be compiled with: npm run build\n// Inter-file .flux imports only work via flux bundle, NOT flux run\nimport Express from \"express\"\nimport { setupRoutes } from \"./routes\" // inter-file .flux import\n\nval app = Express()\nval PORT = process.env.PORT or 3000\n\napp.use(Express.json())\nsetupRoutes(app)\n\napp.listen(PORT, -> print(\"{projectName} running at http://localhost:{PORT}\"))";
654
- const pkgJson = { name: projectName, version: "1.0.0", description: "A Flux web app", main: "dist/server.js", scripts: { build: "flux bundle src/server.flux -o dist/server.js", start: "node dist/server.js", dev: "flux bundle src/server.flux -o dist/server.js && node dist/server.js", watch: "flux watch src/server.flux", test: "flux test tests/" }, flux: { entry: "src/server.flux", outDir: "dist", mangle: false, sourcemap: true }, dependencies: { "@xnoxs/flux-lang": ("^" + VERSION), express: "^4.18.0" }, devDependencies: { } };
655
- Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8");
656
- Fs.writeFileSync(Path.join(dir, "src", "routes.flux"), routesFlux, "utf8");
657
- Fs.writeFileSync(Path.join(dir, "src", "server.flux"), serverFlux, "utf8");
658
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8");
659
- Fs.writeFileSync(Path.join(dir, "package.json"), (JSON.stringify(pkgJson, null, 2) + "\n"), "utf8");
660
- Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8");
661
- console.log();
662
- console.log((((green("✓ Project ") + bold((projectName + "/"))) + green(" created with template ")) + cyan("webapp")));
663
- console.log();
664
- console.log(bold(" Next steps:"));
665
- console.log((" " + yellow(("cd " + projectName))));
666
- console.log(((" " + yellow("npm install")) + gray(" # install dependencies")));
667
- console.log(((" " + yellow("npm run build")) + gray(" # compile all .flux → dist/server.js")));
668
- console.log(((" " + yellow("npm start")) + gray(" # run the server")));
669
- console.log();
670
- console.log((yellow(" Note: ") + gray("This project uses multiple .flux files.")));
671
- console.log(((gray(" Always build with ") + yellow("npm run build")) + gray(" (flux bundle) before running.")));
672
- console.log(((gray(" Do NOT use ") + red("flux run")) + gray(" on files that import other .flux files.")));
673
- console.log();
674
- return;
586
+ const mainFlux = "// {projectName} — built with Flux Lang v{VERSION}\n// Run: flux run src/main.flux\n\n// ── Algebraic Data Types + Pattern Matching ───────────────────\ntype Shape = Circle(radius) | Rect(width, height) | Triangle(base, height)\n\nfn area(shape):\n match shape:\n when Circle(r): return Math.PI * r * r\n when Rect(w, h): return w * h\n when Triangle(b, h): return 0.5 * b * h\n\nfn describe(shape):\n match shape:\n when Circle(r): return \"Circle(r={r:.2f})\"\n when Rect(w, h): return \"Rect({w:.1f}x{h:.1f})\"\n when Triangle(b, h): return \"Triangle(b={b:.1f}, h={h:.1f})\"\n\n// ── Result type ───────────────────────────────────────────────\ntype Result = Ok(value) | Err(message)\n\nfn safeDivide(a, b):\n if b == 0: return Err(\"division by zero\")\n return Ok(a / b)\n\n// ── Utility functions ─────────────────────────────────────────\nfn greet(name): return \"Hello from Flux, {name}!\"\n\nfn formatList(items):\n if items.length == 0: return \"(empty)\"\n return \"[\" + items.join(\", \") + \"]\"\n\nfn clamp(value, lo, hi):\n if value < lo: return lo\n if value > hi: return hi\n return value\n\n// ── Pipe operator + stdlib ────────────────────────────────────\nval numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\nval processed = numbers\n |> filter(n -> n > 3)\n |> map(n -> n * n)\n |> sort\n\n// ── Main ──────────────────────────────────────────────────────\nprint(greet(\"{projectName}\"))\nprint(\"Squares > 3: {formatList(processed)}\")\nprint(\"clamp(12, 0, 10) = {clamp(12, 0, 10)}\")\n\nval shapes = [Circle(5.0), Rect(8.0, 3.0), Triangle(6.0, 4.0)]\nfor shape in shapes:\n val a = area(shape)\n print(\"{describe(shape)} area={a:.2f}\")\n\nmatch safeDivide(10.0, 3.0):\n when Ok(v): print(\"10 / 3 = {v:.4f}\")\n when Err(e): print(\"Error: {e}\")";
587
+ const utilsFlux = "// Utility functions for {projectName}\n// Use with: flux bundle src/main.flux (bundles imports automatically)\n\nexport fn greet(name):\n return \"Hello from Flux, {name}!\"\n\nexport fn formatList(items):\n if items.length == 0: return \"(empty)\"\n return \"[\" + items.join(\", \") + \"]\"\n\nexport fn clamp(value, lo, hi):\n if value < lo: return lo\n if value > hi: return hi\n return value\n\nexport fn sum(nums):\n return nums.reduce((acc, x) -> acc + x, 0)\n\nexport fn average(nums):\n if nums.length == 0: return 0\n return sum(nums) / nums.length";
588
+ 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\")";
589
+ 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) } };
590
+ const gitignore = "node_modules/\ndist/\nflux_modules/\n*.js.map\n.DS_Store\n";
591
+ 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 |";
592
+ const allFiles = [(projectName + "/src/main.flux"), (projectName + "/src/utils.flux"), (projectName + "/tests/main.test.flux"), (projectName + "/flux.json"), (projectName + "/.gitignore"), (projectName + "/README.md")];
593
+ Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8");
594
+ Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8");
595
+ Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8");
596
+ Fs.writeFileSync(Path.join(dir, "flux.json"), (JSON.stringify(fluxJson, null, 2) + "\n"), "utf8");
597
+ Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8");
598
+ Fs.writeFileSync(Path.join(dir, "README.md"), readme, "utf8");
599
+ console.log();
600
+ console.log((green("✓ Created: ") + bold((projectName + "/"))));
601
+ console.log();
602
+ console.log(gray(" Files:"));
603
+ for (const f of allFiles) {
604
+ console.log((" " + cyan(f)));
675
605
  }
676
- console.error(red(("✗ Unknown template: " + template)));
677
- console.error(gray(" Available templates: script, server, webapp"));
678
- process.exit(1);
606
+ console.log();
607
+ console.log(bold(" Next steps:"));
608
+ console.log((" " + yellow(("cd " + projectName))));
609
+ console.log((" " + yellow("flux run src/main.flux")));
610
+ console.log();
611
+ console.log(gray(" Add packages (installed into flux_modules/):"));
612
+ console.log((" " + yellow("flux add <package>")));
613
+ console.log((" " + yellow("flux install")));
614
+ console.log();
615
+ console.log(gray(" Or run the test suite:"));
616
+ console.log((" " + yellow("flux test tests/")));
617
+ console.log();
679
618
  }
680
619
  function cmdSelfHosted(sub, opts) {
681
620
  const SELF = Path.join(__dirname, ".");
@@ -840,9 +779,6 @@ function main() {
840
779
  else if (cmd === "repl") {
841
780
  return cmdRepl(opts);
842
781
  }
843
- else if (cmd === "test") {
844
- return runTests((positional[1] ?? "tests/"), (src) => transpile(src, { }));
845
- }
846
782
  else if (cmd === "init") {
847
783
  return cmdInit(positional[1], opts);
848
784
  }