@xnoxs/flux-lang 4.0.8 → 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.
@@ -1,3 +1,5 @@
1
+ /* compiled from src/self/checker.flux by Flux Lang */
2
+ 'use strict';
1
3
  // Generated by Flux Transpiler v3.2.0
2
4
  "use strict";
3
5
 
package/src/self/cli.flux CHANGED
@@ -73,14 +73,13 @@ fn showHelp():
73
73
  console.log(bold("COMPILER:"))
74
74
  val compilerCmds = [
75
75
  ["compile <file.flux>", "Compile .flux → .js"],
76
- ["bundle <entry.flux>", "Bundle multi-file project into one .js"],
77
- ["run <file.flux>", "Compile and run a single-file script"],
76
+ ["bundle <entry.flux>", "Bundle multiple files into one .js"],
77
+ ["run <file.flux>", "Compile and run immediately"],
78
78
  ["watch <file.flux>", "Watch for changes, auto-compile"],
79
79
  ["check <file.flux>", "Type-check and static analysis"],
80
80
  ]
81
- compilerCmds.forEach(pair ->
82
- console.log(" " + green(("flux " + pair[0]).padEnd(36)) + " " + gray(pair[1]))
83
- )
81
+ for [cmd, desc] in compilerCmds:
82
+ console.log(" " + green(("flux " + cmd).padEnd(36)) + " " + gray(desc))
84
83
 
85
84
  console.log()
86
85
  console.log(bold("TOOLING:"))
@@ -92,25 +91,23 @@ fn showHelp():
92
91
  ["tokens <file.flux>", "Show lexer token list"],
93
92
  ["ast <file.flux>", "Show Abstract Syntax Tree (JSON)"],
94
93
  ]
95
- toolCmds.forEach(pair ->
96
- console.log(" " + green(("flux " + pair[0]).padEnd(36)) + " " + gray(pair[1]))
97
- )
94
+ for [cmd, desc] in toolCmds:
95
+ console.log(" " + green(("flux " + cmd).padEnd(36)) + " " + gray(desc))
98
96
 
99
97
  console.log()
100
98
  console.log(bold("PACKAGE MANAGER:"))
101
99
  val pkgCmds = [
102
- ["init [name] [--template]", "Scaffold a new Flux project"],
103
- ["add <pkg[@version]>", "Add a dependency (npm install --save)"],
104
- ["remove <pkg>", "Remove a dependency (npm uninstall)"],
105
- ["install", "Install all dependencies (npm install)"],
100
+ ["init [name]", "Scaffold a new Flux project"],
101
+ ["add <pkg[@version]>", "Add a dependency"],
102
+ ["remove <pkg>", "Remove a dependency"],
103
+ ["install", "Install all dependencies"],
106
104
  ["list", "List installed packages"],
107
- ["search <query>", "Search the npm registry"],
105
+ ["search <query>", "Search the package registry"],
108
106
  ["info <pkg>", "Show package details"],
109
- ["publish", "Publish package to npm registry"],
107
+ ["publish", "Publish package to registry"],
110
108
  ]
111
- pkgCmds.forEach(pair ->
112
- console.log(" " + cyan(("flux " + pair[0]).padEnd(36)) + " " + gray(pair[1]))
113
- )
109
+ for [cmd, desc] in pkgCmds:
110
+ console.log(" " + cyan(("flux " + cmd).padEnd(36)) + " " + gray(desc))
114
111
 
115
112
  console.log()
116
113
  console.log(bold("SELF-HOSTED:"))
@@ -119,9 +116,8 @@ fn showHelp():
119
116
  ["self-hosted build", "Bootstrap: compile compiler with itself"],
120
117
  ["self-hosted verify", "Verify self-hosted output matches stage-0"],
121
118
  ]
122
- selfCmds.forEach(pair ->
123
- console.log(" " + yellow(("flux " + pair[0]).padEnd(36)) + " " + gray(pair[1]))
124
- )
119
+ for [cmd, desc] in selfCmds:
120
+ console.log(" " + yellow(("flux " + cmd).padEnd(36)) + " " + gray(desc))
125
121
 
126
122
  console.log()
127
123
  console.log(bold("OPTIONS:"))
@@ -132,7 +128,6 @@ fn showHelp():
132
128
  console.log(" " + yellow("--typecheck ") + " Enable type checking")
133
129
  console.log(" " + yellow("--stdout ") + " Print to terminal")
134
130
  console.log(" " + yellow("--no-color ") + " Disable colors")
135
- console.log(" " + yellow("--template ") + " Init template: script, server, webapp")
136
131
  console.log()
137
132
 
138
133
  // ── Parse CLI args ────────────────────────────────────────────
@@ -150,7 +145,6 @@ fn parseArgs(argv):
150
145
  verbose: false,
151
146
  jsx: false,
152
147
  jsxTarget: "browser",
153
- template: null,
154
148
  }
155
149
  val positional = []
156
150
  var i = 0
@@ -180,9 +174,6 @@ fn parseArgs(argv):
180
174
  else if a == "--jsx-target":
181
175
  i = i + 1
182
176
  opts.jsxTarget = args[i]
183
- else if a == "--template" or a == "-t":
184
- i = i + 1
185
- opts.template = args[i]
186
177
  else if not a.startsWith("--"):
187
178
  positional.push(a)
188
179
  i = i + 1
@@ -245,22 +236,6 @@ fn printErrors(errors, source, filePath):
245
236
  console.error(cyan(" Hint: ") + gray(err.hint))
246
237
  console.error()
247
238
 
248
- // ── Detect inter-file .flux imports in source ─────────────────
249
- fn findFluxImports(source):
250
- val found = []
251
- val lines = source.split("\n")
252
- for line in lines:
253
- val trimmed = line.trim()
254
- // Match: import ... from "./something" or import ... from "../something"
255
- // where the path is relative (starts with ./ or ../)
256
- val m = trimmed.match(/^import\s+.+\s+from\s+["'](\.[^"']+)["']/)
257
- if m:
258
- val src = m[1]
259
- // Relative import to a .flux file (explicit or implicit extension)
260
- if not src.endsWith(".js") and not src.endsWith(".json") and not src.endsWith(".node"):
261
- found.push(src)
262
- return found
263
-
264
239
  // ══════════════════════════════════════════════════════════════
265
240
  // Commands
266
241
  // ══════════════════════════════════════════════════════════════
@@ -315,23 +290,6 @@ fn cmdCompile(filePath, opts):
315
290
  // ── flux run ──────────────────────────────────────────────────
316
291
  fn cmdRun(filePath, opts):
317
292
  val { source, abs } = readFluxFile(filePath)
318
-
319
- // Detect inter-file .flux imports — flux run cannot handle them
320
- val fluxImports = findFluxImports(source)
321
- if fluxImports.length > 0:
322
- val example = fluxImports[0]
323
- val entryRel = Path.relative(process.cwd(), abs)
324
- val outFile = Path.basename(abs, ".flux") + ".js"
325
- console.error(red("\n✗ Cannot run a multi-file Flux project with `flux run`.\n"))
326
- console.error(" Found: " + yellow("import ... from \"" + example + "\""))
327
- console.error()
328
- console.error(" Use " + cyan("flux bundle") + " to compile all files into one, then run it:\n")
329
- console.error(" " + yellow("flux bundle " + entryRel + " -o dist/" + outFile))
330
- console.error(" " + yellow("node dist/" + outFile))
331
- console.error()
332
- console.error(" Or use " + cyan("flux run") + " only for single-file scripts (no inter-file .flux imports).\n")
333
- process.exit(1)
334
-
335
293
  val result = transpile(source, {
336
294
  jsx: opts.jsx ?? false,
337
295
  jsxTarget: opts.jsxTarget ?? "browser",
@@ -488,11 +446,6 @@ fn cmdBundle(entryPath, opts):
488
446
  console.log(result.code)
489
447
  return
490
448
 
491
- // Ensure output directory exists
492
- val outDir = Path.dirname(Path.resolve(outFile))
493
- if not Fs.existsSync(outDir):
494
- Fs.mkdirSync(outDir, { recursive: true })
495
-
496
449
  Fs.writeFileSync(outFile, result.code, "utf8")
497
450
  val kb = (result.code.length / 1024).toFixed(1)
498
451
  console.log(
@@ -625,8 +578,7 @@ fn cmdRepl(opts):
625
578
  // ── flux init ────────────────────────────────────────────────
626
579
  fn cmdInit(name, opts):
627
580
  val projectName = name ?? "my-flux-app"
628
- val template = opts.template ?? "script"
629
- val dir = Path.resolve(projectName)
581
+ val dir = Path.resolve(projectName)
630
582
 
631
583
  if Fs.existsSync(dir):
632
584
  console.error(red("✗ Directory already exists: " + projectName))
@@ -636,251 +588,246 @@ fn cmdInit(name, opts):
636
588
  Fs.mkdirSync(Path.join(dir, "src"), { recursive: true })
637
589
  Fs.mkdirSync(Path.join(dir, "tests"), { recursive: true })
638
590
 
639
- val gitignore = "node_modules/\ndist/\n*.js.map\n.DS_Store\n"
591
+ val mainFlux = `// {projectName} — built with Flux Lang v{VERSION}
592
+ // Run: flux run src/main.flux
593
+
594
+ // ── Algebraic Data Types + Pattern Matching ───────────────────
595
+ type Shape = Circle(radius) | Rect(width, height) | Triangle(base, height)
596
+
597
+ fn area(shape):
598
+ match shape:
599
+ when Circle(r): return Math.PI * r * r
600
+ when Rect(w, h): return w * h
601
+ when Triangle(b, h): return 0.5 * b * h
602
+
603
+ fn describe(shape):
604
+ match shape:
605
+ when Circle(r): return "Circle(r={r:.2f})"
606
+ when Rect(w, h): return "Rect({w:.1f}x{h:.1f})"
607
+ when Triangle(b, h): return "Triangle(b={b:.1f}, h={h:.1f})"
608
+
609
+ // ── Result type ───────────────────────────────────────────────
610
+ type Result = Ok(value) | Err(message)
611
+
612
+ fn safeDivide(a, b):
613
+ if b == 0: return Err("division by zero")
614
+ return Ok(a / b)
615
+
616
+ // ── Utility functions ─────────────────────────────────────────
617
+ fn greet(name): return "Hello from Flux, {name}!"
618
+
619
+ fn formatList(items):
620
+ if items.length == 0: return "(empty)"
621
+ return "[" + items.join(", ") + "]"
622
+
623
+ fn clamp(value, lo, hi):
624
+ if value < lo: return lo
625
+ if value > hi: return hi
626
+ return value
627
+
628
+ // ── Pipe operator + stdlib ────────────────────────────────────
629
+ val numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
630
+ val processed = numbers
631
+ |> filter(n -> n > 3)
632
+ |> map(n -> n * n)
633
+ |> sort
634
+
635
+ // ── Main ──────────────────────────────────────────────────────
636
+ print(greet("{projectName}"))
637
+ print("Squares > 3: {formatList(processed)}")
638
+ print("clamp(12, 0, 10) = {clamp(12, 0, 10)}")
639
+
640
+ val shapes = [Circle(5.0), Rect(8.0, 3.0), Triangle(6.0, 4.0)]
641
+ for shape in shapes:
642
+ val a = area(shape)
643
+ print("{describe(shape)} area={a:.2f}")
644
+
645
+ match safeDivide(10.0, 3.0):
646
+ when Ok(v): print("10 / 3 = {v:.4f}")
647
+ when Err(e): print("Error: {e}")
648
+ `
649
+
650
+ val utilsFlux = `// Utility functions for {projectName}
651
+ // Use with: flux bundle src/main.flux (bundles imports automatically)
652
+
653
+ export fn greet(name):
654
+ return "Hello from Flux, {name}!"
655
+
656
+ export fn formatList(items):
657
+ if items.length == 0: return "(empty)"
658
+ return "[" + items.join(", ") + "]"
659
+
660
+ export fn clamp(value, lo, hi):
661
+ if value < lo: return lo
662
+ if value > hi: return hi
663
+ return value
664
+
665
+ export fn sum(nums):
666
+ return nums.reduce((acc, x) -> acc + x, 0)
667
+
668
+ export fn average(nums):
669
+ if nums.length == 0: return 0
670
+ return sum(nums) / nums.length
671
+ `
640
672
 
641
673
  val testFlux = `// Tests for {projectName}
642
674
  // Run: flux test tests/
643
675
 
676
+ // ── Functions under test ──────────────────────────────────────
644
677
  fn add(a, b):
645
678
  return a + b
646
679
 
680
+ fn mul(a, b):
681
+ return a * b
682
+
647
683
  fn clamp(value, lo, hi):
648
684
  if value < lo: return lo
649
685
  if value > hi: return hi
650
686
  return value
651
687
 
688
+ fn average(nums):
689
+ if nums.length == 0: return 0
690
+ return nums.reduce((s, x) -> s + x, 0) / nums.length
691
+
692
+ type Result = Ok(value) | Err(message)
693
+
694
+ fn safeDivide(a, b):
695
+ if b == 0: return Err("div by zero")
696
+ return Ok(a / b)
697
+
698
+ // ── Test functions ────────────────────────────────────────────
652
699
  fn test_add():
653
700
  assert(add(1, 2) == 3, "1+2=3")
654
701
  assert(add(0, 0) == 0, "0+0=0")
655
702
  assert(add(-1, 1) == 0, "-1+1=0")
656
703
 
704
+ fn test_mul():
705
+ assert(mul(3, 4) == 12, "3*4=12")
706
+ assert(mul(0, 5) == 0, "0*5=0")
707
+
657
708
  fn test_clamp():
658
709
  assert(clamp(5, 0, 10) == 5, "within range")
659
710
  assert(clamp(-1, 0, 10) == 0, "below min")
660
711
  assert(clamp(15, 0, 10) == 10, "above max")
661
- `
662
-
663
- // ── Template: script (default) — single file, no inter-file imports ──
664
- if template == "script":
665
- val mainFlux = `// {projectName} — a Flux script
666
- // Run: npm run dev (or: node_modules/.bin/flux run src/main.flux)
667
-
668
- import Fs from "fs"
669
- import Path from "path"
670
712
 
671
- fn main():
672
- print("Hello from Flux!")
673
- print("Node version: {process.version}")
674
-
675
- main()
713
+ fn test_average():
714
+ assert(average([2, 4, 6]) == 4, "average of 2,4,6")
715
+ assert(average([]) == 0, "empty list")
716
+
717
+ fn test_safe_divide():
718
+ val ok = safeDivide(10, 2)
719
+ match ok:
720
+ when Ok(v): assert(v == 5, "10/2=5")
721
+ when Err(e): assert(false, "unexpected error")
722
+ val err = safeDivide(10, 0)
723
+ match err:
724
+ when Ok(v): assert(false, "expected error")
725
+ when Err(e): assert(e == "div by zero", "error message")
726
+
727
+ fn test_pipe_operator():
728
+ val result = [1, 2, 3, 4, 5] |> filter(n -> n > 2) |> map(n -> n * 2)
729
+ assert(result.length == 3, "filter length")
730
+ assert(result[0] == 6, "first element")
731
+ assert(result[2] == 10, "last element")
676
732
  `
677
733
 
678
- val pkgJson = {
679
- name: projectName,
680
- version: "1.0.0",
681
- description: "A Flux project",
682
- main: "dist/main.js",
683
- scripts: {
684
- dev: "flux run src/main.flux",
685
- build: "flux bundle src/main.flux -o dist/main.js",
686
- start: "node dist/main.js",
687
- test: "flux test tests/",
688
- },
689
- flux: {
690
- entry: "src/main.flux",
691
- outDir: "dist",
692
- mangle: false,
693
- sourcemap: false,
694
- },
695
- dependencies: {
696
- "@xnoxs/flux-lang": "^" + VERSION,
697
- },
698
- devDependencies: {},
699
- }
700
-
701
- Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8")
702
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8")
703
- Fs.writeFileSync(Path.join(dir, "package.json"), JSON.stringify(pkgJson, null, 2) + "\n", "utf8")
704
- Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8")
705
-
706
- console.log()
707
- console.log(green("✓ Project ") + bold(projectName + "/") + green(" created with template ") + cyan("script"))
708
- console.log()
709
- console.log(bold(" Next steps:"))
710
- console.log(" " + yellow("cd " + projectName))
711
- console.log(" " + yellow("npm install"))
712
- console.log(" " + yellow("npm run dev"))
713
- console.log()
714
- console.log(gray(" Add packages:"))
715
- console.log(" " + yellow("flux add <package>"))
716
- console.log()
717
- return
718
-
719
- // ── Template: server — Express HTTP server, single file ──
720
- if template == "server":
721
- val serverFlux = `// {projectName} — Flux HTTP server
722
- // Run: npm run dev
723
- // Build: npm run build && npm start
734
+ val fluxJson = {
735
+ name: projectName,
736
+ version: "1.0.0",
737
+ description: "A Flux Lang v" + VERSION + " project",
738
+ author: "",
739
+ license: "MIT",
740
+ entry: "src/main.flux",
741
+ outDir: "dist",
742
+ sourcemap: false,
743
+ typecheck: true,
744
+ scripts: {
745
+ start: "flux run src/main.flux",
746
+ build: "flux bundle src/main.flux -o dist/bundle.js",
747
+ dev: "flux watch src/main.flux",
748
+ check: "flux check src/main.flux",
749
+ test: "flux test tests/",
750
+ fmt: "flux fmt src/",
751
+ lint: "flux lint src/",
752
+ },
753
+ dependencies: {},
754
+ devDependencies: { "@xnoxs/flux-lang": "^" + VERSION },
755
+ }
724
756
 
725
- import Express from "express"
757
+ val gitignore = "node_modules/\ndist/\nflux_modules/\n*.js.map\n.DS_Store\n"
726
758
 
727
- val app = Express()
728
- val PORT = process.env.PORT or 3000
759
+ val readme = `# {projectName}
729
760
 
730
- app.use(Express.json())
761
+ A project built with [Flux Lang](https://flux-lang.dev) v{VERSION} — the self-hosted compiler.
731
762
 
732
- app.get("/", (req, res) ->
733
- res.json({ status: "ok", message: "Hello from Flux!", port: PORT })
734
- )
763
+ ## Quick Start
735
764
 
736
- app.listen(PORT, -> print("Server running at http://localhost:{PORT}"))
737
- `
765
+ \`\`\`bash
766
+ flux run src/main.flux
767
+ \`\`\`
738
768
 
739
- val pkgJson = {
740
- name: projectName,
741
- version: "1.0.0",
742
- description: "A Flux HTTP server",
743
- main: "dist/server.js",
744
- scripts: {
745
- dev: "flux run src/server.flux",
746
- build: "flux bundle src/server.flux -o dist/server.js",
747
- start: "node dist/server.js",
748
- test: "flux test tests/",
749
- },
750
- flux: {
751
- entry: "src/server.flux",
752
- outDir: "dist",
753
- mangle: false,
754
- sourcemap: false,
755
- },
756
- dependencies: {
757
- "@xnoxs/flux-lang": "^" + VERSION,
758
- "express": "^4.18.0",
759
- },
760
- devDependencies: {},
761
- }
762
-
763
- Fs.writeFileSync(Path.join(dir, "src", "server.flux"), serverFlux, "utf8")
764
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8")
765
- Fs.writeFileSync(Path.join(dir, "package.json"), JSON.stringify(pkgJson, null, 2) + "\n", "utf8")
766
- Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8")
769
+ ## Project Structure
767
770
 
768
- console.log()
769
- console.log(green("✓ Project ") + bold(projectName + "/") + green(" created with template ") + cyan("server"))
770
- console.log()
771
- console.log(bold(" Next steps:"))
772
- console.log(" " + yellow("cd " + projectName))
773
- console.log(" " + yellow("npm install"))
774
- console.log(" " + yellow("npm run dev"))
775
- console.log()
776
- console.log(gray(" Build for production:"))
777
- console.log(" " + yellow("npm run build && npm start"))
778
- console.log()
779
- return
771
+ \`\`\`
772
+ {projectName}/
773
+ ├── src/
774
+ │ ├── main.flux # Entry point
775
+ │ └── utils.flux # Utility functions
776
+ ├── tests/
777
+ │ └── main.test.flux # Test suite
778
+ ├── flux_modules/ # Packages installed by \`flux install\` (gitignored)
779
+ ├── flux.json # Project config & dependencies
780
+ └── README.md
781
+ \`\`\`
780
782
 
781
- // ── Template: webapp — multi-file project, uses flux bundle ──
782
- if template == "webapp":
783
- val utilsFlux = `// Utility functions
784
- export fn formatDate(date):
785
- val d = new Date(date)
786
- return d.toISOString().split("T")[0]
783
+ ## Commands
787
784
 
788
- export fn paginate(items, page, perPage):
789
- val start = (page - 1) * perPage
790
- return items.slice(start, start + perPage)
785
+ | Command | Description |
786
+ |---|---|
787
+ | \`flux run src/main.flux\` | Run the project |
788
+ | \`flux bundle src/main.flux -o dist/bundle.js\` | Bundle to single file |
789
+ | \`flux watch src/main.flux\` | Watch mode |
790
+ | \`flux check src/main.flux\` | Type check + static analysis |
791
+ | \`flux test tests/\` | Run all tests |
792
+ | \`flux fmt src/\` | Format source code |
793
+ | \`flux lint src/\` | Lint for issues |
794
+ | \`flux add <package>\` | Add a dependency |
791
795
  `
792
796
 
793
- val routesFlux = `// Route handlers
794
- import { formatDate, paginate } from "./utils" // inter-file .flux import
795
-
796
- val items = [
797
- { id: 1, name: "Item A", date: "2024-01-01" },
798
- { id: 2, name: "Item B", date: "2024-02-01" },
799
- { id: 3, name: "Item C", date: "2024-03-01" },
800
- ]
801
-
802
- export fn setupRoutes(app):
803
- app.get("/items", (req, res) ->
804
- val page = parseInt(req.query.page or "1")
805
- val perPage = parseInt(req.query.per_page or "10")
806
- val data = paginate(items, page, perPage)
807
- res.json({ data, page })
808
- )
809
-
810
- app.get("/items/:id", (req, res) ->
811
- val item = items.find(i -> i.id == parseInt(req.params.id))
812
- if item == null:
813
- res.status(404).json({ error: "Not found" })
814
- else:
815
- res.json({ data: item, date: formatDate(item.date) })
816
- )
817
- `
818
-
819
- val serverFlux = `// Entry point — MUST be compiled with: npm run build
820
- // Inter-file .flux imports only work via flux bundle, NOT flux run
821
- import Express from "express"
822
- import { setupRoutes } from "./routes" // inter-file .flux import
823
-
824
- val app = Express()
825
- val PORT = process.env.PORT or 3000
826
-
827
- app.use(Express.json())
828
- setupRoutes(app)
829
-
830
- app.listen(PORT, -> print("{projectName} running at http://localhost:{PORT}"))
831
- `
797
+ val allFiles = [
798
+ projectName + "/src/main.flux",
799
+ projectName + "/src/utils.flux",
800
+ projectName + "/tests/main.test.flux",
801
+ projectName + "/flux.json",
802
+ projectName + "/.gitignore",
803
+ projectName + "/README.md",
804
+ ]
832
805
 
833
- val pkgJson = {
834
- name: projectName,
835
- version: "1.0.0",
836
- description: "A Flux web app",
837
- main: "dist/server.js",
838
- scripts: {
839
- build: "flux bundle src/server.flux -o dist/server.js",
840
- start: "node dist/server.js",
841
- dev: "flux bundle src/server.flux -o dist/server.js && node dist/server.js",
842
- watch: "flux watch src/server.flux",
843
- test: "flux test tests/",
844
- },
845
- flux: {
846
- entry: "src/server.flux",
847
- outDir: "dist",
848
- mangle: false,
849
- sourcemap: true,
850
- },
851
- dependencies: {
852
- "@xnoxs/flux-lang": "^" + VERSION,
853
- "express": "^4.18.0",
854
- },
855
- devDependencies: {},
856
- }
857
-
858
- Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8")
859
- Fs.writeFileSync(Path.join(dir, "src", "routes.flux"), routesFlux, "utf8")
860
- Fs.writeFileSync(Path.join(dir, "src", "server.flux"), serverFlux, "utf8")
861
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8")
862
- Fs.writeFileSync(Path.join(dir, "package.json"), JSON.stringify(pkgJson, null, 2) + "\n", "utf8")
863
- Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8")
806
+ Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8")
807
+ Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8")
808
+ Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8")
809
+ Fs.writeFileSync(Path.join(dir, "flux.json"), JSON.stringify(fluxJson, null, 2) + "\n", "utf8")
810
+ Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8")
811
+ Fs.writeFileSync(Path.join(dir, "README.md"), readme, "utf8")
864
812
 
865
- console.log()
866
- console.log(green("✓ Project ") + bold(projectName + "/") + green(" created with template ") + cyan("webapp"))
867
- console.log()
868
- console.log(bold(" Next steps:"))
869
- console.log(" " + yellow("cd " + projectName))
870
- console.log(" " + yellow("npm install") + gray(" # install dependencies"))
871
- console.log(" " + yellow("npm run build") + gray(" # compile all .flux → dist/server.js"))
872
- console.log(" " + yellow("npm start") + gray(" # run the server"))
873
- console.log()
874
- console.log(yellow(" Note: ") + gray("This project uses multiple .flux files."))
875
- console.log(gray(" Always build with ") + yellow("npm run build") + gray(" (flux bundle) before running."))
876
- console.log(gray(" Do NOT use ") + red("flux run") + gray(" on files that import other .flux files."))
877
- console.log()
878
- return
879
-
880
- // Unknown template
881
- console.error(red(" Unknown template: " + template))
882
- console.error(gray(" Available templates: script, server, webapp"))
883
- process.exit(1)
813
+ console.log()
814
+ console.log(green("✓ Created: ") + bold(projectName + "/"))
815
+ console.log()
816
+ console.log(gray(" Files:"))
817
+ for f in allFiles:
818
+ console.log(" " + cyan(f))
819
+ console.log()
820
+ console.log(bold(" Next steps:"))
821
+ console.log(" " + yellow("cd " + projectName))
822
+ console.log(" " + yellow("flux run src/main.flux"))
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()
828
+ console.log(gray(" Or run the test suite:"))
829
+ console.log(" " + yellow("flux test tests/"))
830
+ console.log()
884
831
 
885
832
  // ── flux self-hosted ──────────────────────────────────────────
886
833
  fn cmdSelfHosted(sub, opts):
@@ -1028,7 +975,6 @@ fn main():
1028
975
  when "tokens": cmdTokens(positional[1], opts)
1029
976
  when "ast": cmdAst(positional[1], opts)
1030
977
  when "repl": cmdRepl(opts)
1031
- when "test": runTests(positional[1] ?? 'tests/', src -> transpile(src, {}))
1032
978
  when "init": cmdInit(positional[1], opts)
1033
979
  when "add": cmdAdd(positional.slice(1), opts)
1034
980
  when "remove": cmdRemove(positional.slice(1), opts)