@xnoxs/flux-lang 3.5.3 → 4.0.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/src/self/pkg.flux CHANGED
@@ -323,6 +323,82 @@ export async fn cmdInfo(name, opts):
323
323
  catch(e):
324
324
  err("Could not fetch info for " + name + ": " + e.message)
325
325
 
326
+ // ── flux upgrade [--check] ────────────────────────────────────
327
+ export async fn cmdUpgrade(opts):
328
+ val isCheck = opts?.check ?? false
329
+ val cwd = process.cwd()
330
+ val pkg = readPackage(cwd)
331
+
332
+ if not pkg:
333
+ err("No flux.json found. Run: flux init")
334
+ return
335
+
336
+ val deps = pkg.dependencies ?? {}
337
+ val devDeps = pkg.devDependencies ?? {}
338
+ val all = { ...deps, ...devDeps }
339
+ val names = Object.keys(all)
340
+
341
+ if names.length == 0:
342
+ info("No dependencies to upgrade")
343
+ console.log()
344
+ return
345
+
346
+ if isCheck:
347
+ console.log(clr(C.cyan, "\n Checking " + names.length + " package(s) for updates...\n"))
348
+ else:
349
+ console.log(clr(C.cyan, "\n Upgrading " + names.length + " package(s) to latest...\n"))
350
+
351
+ var outdated = 0
352
+ var updated = 0
353
+
354
+ for name in names:
355
+ val current = all[name]
356
+ val spinner = startSpinner("Checking " + clr(C.bold, name) + " ...")
357
+ try:
358
+ val info_ = await fetchJson(REGISTRY_URL + "/" + name)
359
+ val latest = info_["dist-tags"]?.latest ?? null
360
+ stopSpinner(spinner)
361
+
362
+ if not latest:
363
+ console.log(" " + clr(C.gray, "? ") + clr(C.bold, name) + clr(C.gray, " — could not resolve latest"))
364
+ continue
365
+
366
+ val currentClean = current.replace("^", "").replace("~", "")
367
+ if currentClean == latest:
368
+ console.log(" " + clr(C.green, "✓ ") + clr(C.bold, name) + clr(C.gray, " " + current + " (up to date)"))
369
+ else:
370
+ outdated = outdated + 1
371
+ if isCheck:
372
+ console.log(" " + clr(C.yellow, "↑ ") + clr(C.bold, name) + clr(C.gray, " " + current + " → ") + clr(C.green, "^" + latest))
373
+ else:
374
+ val isDev = devDeps[name] != null
375
+ val depKey = isDev ? "devDependencies" : "dependencies"
376
+ pkg[depKey][name] = "^" + latest
377
+ updated = updated + 1
378
+ console.log(" " + clr(C.green, "✓ ") + clr(C.bold, name) + clr(C.gray, " " + current + " → ") + clr(C.green, "^" + latest))
379
+
380
+ catch(e):
381
+ stopSpinner(spinner)
382
+ console.log(" " + clr(C.red, "✗ ") + clr(C.bold, name) + clr(C.gray, " — " + e.message))
383
+
384
+ console.log()
385
+
386
+ if isCheck:
387
+ if outdated == 0:
388
+ ok("All packages are up to date")
389
+ else:
390
+ console.log(clr(C.yellow, " " + outdated + " package(s) can be upgraded"))
391
+ console.log(clr(C.gray, " Run ") + clr(C.yellow, "flux upgrade") + clr(C.gray, " to apply updates"))
392
+ else:
393
+ if updated == 0:
394
+ ok("All packages are already up to date")
395
+ else:
396
+ saveFluxJson(pkg, cwd)
397
+ ok(updated + " package(s) updated in flux.json")
398
+ console.log(clr(C.gray, " Run ") + clr(C.yellow, "flux install") + clr(C.gray, " to install updated versions"))
399
+
400
+ console.log()
401
+
326
402
  // ── flux publish ──────────────────────────────────────────────
327
403
  export fn cmdPublish(opts):
328
404
  val cwd = process.cwd()
package/src/self/pkg.js CHANGED
@@ -310,6 +310,88 @@ async function cmdInfo(name, opts) {
310
310
  }
311
311
  }
312
312
  module.exports.cmdInfo = cmdInfo;
313
+ async function cmdUpgrade(opts) {
314
+ const isCheck = (opts?.check ?? false);
315
+ const cwd = process.cwd();
316
+ const pkg = readPackage(cwd);
317
+ if (!pkg) {
318
+ err("No flux.json found. Run: flux init");
319
+ return;
320
+ }
321
+ const deps = (pkg.dependencies ?? { });
322
+ const devDeps = (pkg.devDependencies ?? { });
323
+ const all = { ...deps, ...devDeps };
324
+ const names = Object.keys(all);
325
+ if ((names.length == 0)) {
326
+ info("No dependencies to upgrade");
327
+ console.log();
328
+ return;
329
+ }
330
+ if (isCheck) {
331
+ console.log(clr(C.cyan, (("\n Checking " + names.length) + " package(s) for updates...\n")));
332
+ }
333
+ else {
334
+ console.log(clr(C.cyan, (("\n Upgrading " + names.length) + " package(s) to latest...\n")));
335
+ }
336
+ let outdated = 0;
337
+ let updated = 0;
338
+ for (const name of names) {
339
+ const current = all[name];
340
+ const spinner = startSpinner((("Checking " + clr(C.bold, name)) + " ..."));
341
+ try {
342
+ const info_ = await fetchJson(((REGISTRY_URL + "/") + name));
343
+ const latest = (info_["dist-tags"]?.latest ?? null);
344
+ stopSpinner(spinner);
345
+ if (!latest) {
346
+ console.log((((" " + clr(C.gray, "? ")) + clr(C.bold, name)) + clr(C.gray, " — could not resolve latest")));
347
+ continue;
348
+ }
349
+ const currentClean = current.replace("^", "").replace("~", "");
350
+ if ((currentClean == latest)) {
351
+ console.log((((" " + clr(C.green, "✓ ")) + clr(C.bold, name)) + clr(C.gray, ((" " + current) + " (up to date)"))));
352
+ }
353
+ else {
354
+ outdated = (outdated + 1);
355
+ if (isCheck) {
356
+ console.log(((((" " + clr(C.yellow, "↑ ")) + clr(C.bold, name)) + clr(C.gray, ((" " + current) + " → "))) + clr(C.green, ("^" + latest))));
357
+ }
358
+ else {
359
+ const isDev = (devDeps[name] != null);
360
+ const depKey = (isDev ? "devDependencies" : "dependencies");
361
+ pkg[depKey][name] = ("^" + latest);
362
+ updated = (updated + 1);
363
+ console.log(((((" " + clr(C.green, "✓ ")) + clr(C.bold, name)) + clr(C.gray, ((" " + current) + " → "))) + clr(C.green, ("^" + latest))));
364
+ }
365
+ }
366
+ }
367
+ catch (e) {
368
+ stopSpinner(spinner);
369
+ console.log((((" " + clr(C.red, "✗ ")) + clr(C.bold, name)) + clr(C.gray, (" — " + e.message))));
370
+ }
371
+ }
372
+ console.log();
373
+ if (isCheck) {
374
+ if ((outdated == 0)) {
375
+ ok("All packages are up to date");
376
+ }
377
+ else {
378
+ console.log(clr(C.yellow, ((" " + outdated) + " package(s) can be upgraded")));
379
+ console.log(((clr(C.gray, " Run ") + clr(C.yellow, "flux upgrade")) + clr(C.gray, " to apply updates")));
380
+ }
381
+ }
382
+ else {
383
+ if ((updated == 0)) {
384
+ ok("All packages are already up to date");
385
+ }
386
+ else {
387
+ saveFluxJson(pkg, cwd);
388
+ ok((updated + " package(s) updated in flux.json"));
389
+ console.log(((clr(C.gray, " Run ") + clr(C.yellow, "flux install")) + clr(C.gray, " to install updated versions")));
390
+ }
391
+ }
392
+ console.log();
393
+ }
394
+ module.exports.cmdUpgrade = cmdUpgrade;
313
395
  function cmdPublish(opts) {
314
396
  const cwd = process.cwd();
315
397
  const pkg = readPackage(cwd);
@@ -1,5 +1,5 @@
1
1
  // ============================================================
2
- // Flux Self-Hosted Transpiler — v3.0 (100% Self-Hosting)
2
+ // Flux Self-Hosted Transpiler — v3.5 (100% Self-Hosting)
3
3
  // src/self/transpiler.flux — written in Flux, compiled by stage-0
4
4
  //
5
5
  // Full pipeline:
@@ -15,8 +15,18 @@ import { transformJsx, FLUX_H_BROWSER, FLUX_H_SERVER, FLUX_CSS_BROWSER, FLUX_CSS
15
15
  import { Checker } from './checker'
16
16
  import { FluxTypeChecker } from './type-checker'
17
17
 
18
- // ── Version info ─────────────────────────────────────────────
19
- export val FLUX_VERSION = "3.0.0"
18
+ // ── Version info — always in sync with package.json ──────────
19
+ import Fs from "fs"
20
+ import Path from "path"
21
+
22
+ fn _readFluxVersion():
23
+ try:
24
+ val pkgPath = Path.resolve(__dirname, "../../package.json")
25
+ return JSON.parse(Fs.readFileSync(pkgPath, "utf8")).version
26
+ catch(e):
27
+ return "4.0.0"
28
+
29
+ export val FLUX_VERSION = _readFluxVersion()
20
30
  export val FLUX_STAGE = "self-hosted"
21
31
 
22
32
  // ── Public API ────────────────────────────────────────────────
@@ -89,7 +99,7 @@ export fn transpile(source, options):
89
99
  // ── Stage 5: Code generation ────────────────────────────────
90
100
  result.stage = "codegen"
91
101
  val indent = opts.mangle ? "" : " "
92
- val cg = makeCodeGen({ indent })
102
+ val cg = makeCodeGen({ indent, version: FLUX_VERSION })
93
103
  val genResult = cg.generate(ast)
94
104
  var code = genResult.code
95
105
 
@@ -1,83 +1 @@
1
- // Generated by Flux Transpiler v3.2.0
2
- "use strict";
3
-
4
- const { Lexer, lexerize, T } = require("./lexer");
5
- const { Parser, makeParser } = require("./parser");
6
- const { CodeGenerator, makeCodeGen } = require("./codegen");
7
- const { transformCss } = require("./css-preprocessor");
8
- const { transformJsx, FLUX_H_BROWSER, FLUX_H_SERVER, FLUX_CSS_BROWSER, FLUX_CSS_SERVER } = require("./jsx");
9
- const { Checker } = require("./checker");
10
- const { FluxTypeChecker } = require("./type-checker");
11
- const FLUX_VERSION = "3.0.0";
12
- module.exports.FLUX_VERSION = FLUX_VERSION;
13
- const FLUX_STAGE = "self-hosted";
14
- module.exports.FLUX_STAGE = FLUX_STAGE;
15
- function transpile(source, options) {
16
- const opts = (options ?? { });
17
- const result = { success: false, output: "", ast: null, tokens: null, errors: [], typeErrors: [], typeWarnings: [], stage: "" };
18
- try {
19
- let src = source;
20
- result.stage = "css";
21
- if ((opts.css != false)) {
22
- src = transformCss(src);
23
- }
24
- result.stage = "jsx";
25
- if (opts.jsx) {
26
- const jsxTarget = (opts.jsxTarget ?? "browser");
27
- const jsxResult = transformJsx(src, { target: jsxTarget });
28
- src = jsxResult.source;
29
- if (jsxResult.hasJsx) {
30
- opts._jsxHelpers = jsxResult.runtimeHelpers;
31
- }
32
- }
33
- result.stage = "lexer";
34
- const lexer = lexerize(src);
35
- const tokens = lexer.tokenize();
36
- result.tokens = tokens;
37
- result.stage = "parser";
38
- const ast = makeParser(tokens).parse();
39
- result.ast = ast;
40
- if ((opts.check != false)) {
41
- result.stage = "checker";
42
- const checker = new Checker([], []);
43
- const checkResult = checker.check(ast);
44
- if ((checkResult.errors.length > 0)) {
45
- result.errors = checkResult.errors;
46
- result.stage = null;
47
- return result;
48
- }
49
- }
50
- if (opts.typecheck) {
51
- result.stage = "type-checker";
52
- const tc = new FluxTypeChecker([], [], new Map(), new Map(), new Map(), new Map());
53
- const tcResult = tc.check(ast);
54
- result.typeErrors = tcResult.errors;
55
- result.typeWarnings = tcResult.warnings;
56
- if ((opts.strict && (tcResult.errors.length > 0))) {
57
- result.errors = tcResult.errors;
58
- result.stage = null;
59
- return result;
60
- }
61
- }
62
- result.stage = "codegen";
63
- const indent = (opts.mangle ? "" : " ");
64
- const cg = makeCodeGen({ indent });
65
- const genResult = cg.generate(ast);
66
- let code = genResult.code;
67
- if (opts._jsxHelpers) {
68
- code = ((opts._jsxHelpers + "\n") + code);
69
- }
70
- result.output = code;
71
- result.success = true;
72
- result.stage = null;
73
- }
74
- catch (e) {
75
- result.errors.push({ message: e.message, name: e.name, stage: result.stage });
76
- }
77
- return result;
78
- }
79
- module.exports.transpile = transpile;
80
- function transpileFile(source, opts) {
81
- return transpile(source, { check: true, typecheck: (opts?.typecheck ?? false), jsx: (opts?.jsx ?? false), jsxTarget: (opts?.jsxTarget ?? "browser"), mangle: (opts?.mangle ?? false), strict: (opts?.strict ?? false), ...(opts ?? { }) });
82
- }
83
- module.exports.transpileFile = transpileFile;
1
+ "use strict"; const { Lexer, lexerize, T } = require("./lexer"); const { Parser, makeParser } = require("./parser"); const { CodeGenerator, makeCodeGen } = require("./codegen"); const { transformCss } = require("./css-preprocessor"); const { transformJsx, FLUX_H_BROWSER, FLUX_H_SERVER, FLUX_CSS_BROWSER, FLUX_CSS_SERVER } = require("./jsx"); const { Checker } = require("./checker"); const { FluxTypeChecker } = require("./type-checker"); const Fs = require("fs"); const Path = require("path"); function _a() { try { const pkgPath = Path.resolve(__dirname, "../../package.json"); return JSON.parse(Fs.readFileSync(pkgPath, "utf8")).version; } catch (_b) { return "4.0.0"; } } const FLUX_VERSION = _a(); module.exports.FLUX_VERSION = FLUX_VERSION; const FLUX_STAGE = "self-hosted"; module.exports.FLUX_STAGE = FLUX_STAGE; function transpile(_c, _d) { const opts = (_d ?? { }); const result = { success: false, output: "", ast: null, tokens: null, errors: [], typeErrors: [], typeWarnings: [], stage: "" }; try { let src = _c; result.stage = "css"; if ((opts.css != false)) { src = transformCss(src); } result.stage = "jsx"; if (opts.jsx) { const jsxTarget = (opts.jsxTarget ?? "browser"); const jsxResult = transformJsx(src, { target: jsxTarget }); src = jsxResult.source; if (jsxResult.hasJsx) { opts._jsxHelpers = jsxResult.runtimeHelpers; } } result.stage = "lexer"; const lexer = lexerize(src); const tokens = lexer.tokenize(); result.tokens = tokens; result.stage = "parser"; const ast = makeParser(tokens).parse(); result.ast = ast; if ((opts.check != false)) { result.stage = "checker"; const checker = new Checker([], []); const checkResult = checker.check(ast); if ((checkResult.errors.length > 0)) { result.errors = checkResult.errors; result.stage = null; return result; } } if (opts.typecheck) { result.stage = "type-checker"; const tc = new FluxTypeChecker([], [], new Map(), new Map(), new Map(), new Map()); const tcResult = tc.check(ast); result.typeErrors = tcResult.errors; result.typeWarnings = tcResult.warnings; if ((opts.strict && (tcResult.errors.length > 0))) { result.errors = tcResult.errors; result.stage = null; return result; } } result.stage = "codegen"; const indent = (opts.mangle ? "" : " "); const cg = makeCodeGen({ indent, version: FLUX_VERSION }); const genResult = cg.generate(ast); let code = genResult.code; if (opts._jsxHelpers) { code = ((opts._jsxHelpers + "\n") + code); } result.output = code; result.success = true; result.stage = null; } catch (_b) { result.errors.push({ message: _b.message, name: _b.name, stage: result.stage }); } return result; } module.exports.transpile = transpile; function transpileFile(_c, _e) { return transpile(_c, { check: true, typecheck: (_e?.typecheck ?? false), jsx: (_e?.jsx ?? false), jsxTarget: (_e?.jsxTarget ?? "browser"), mangle: (_e?.mangle ?? false), strict: (_e?.strict ?? false), ...(_e ?? { }) }); } module.exports.transpileFile = transpileFile;
@@ -734,6 +734,18 @@ export class FluxTypeChecker:
734
734
  clsEnv.set("self", T_OBJECT(shape))
735
735
  for m in node.methods: self._checkStmt(m, clsEnv)
736
736
 
737
+ else if node.type == "DeclareDecl":
738
+ val d = node.decl
739
+ if d.type == "FnDecl":
740
+ val retType = d.retType ? parseAnnotation(d.retType) : null
741
+ val paramTypes = d.params.map(p -> p.typeAnn ? parseAnnotation(p.typeAnn) : T_UNKNOWN)
742
+ if d.name: env.set(d.name, T_FN(paramTypes, retType ?? T_UNKNOWN))
743
+ else if d.type == "VarDecl":
744
+ val t = d.typeAnn ? parseAnnotation(d.typeAnn) : T_UNKNOWN
745
+ env.set(d.name, t)
746
+ else if d.type == "ClassDecl":
747
+ env.set(d.name, T_NAMED(d.name))
748
+
737
749
  else if node.type == "TypeDecl":
738
750
  for v in node.variants:
739
751
  if v.fields.length == 0: