@xnoxs/flux-lang 3.4.3 → 3.4.5
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/CHANGELOG.md +13 -0
- package/dist/flux-cli.js +120 -12
- package/dist/flux.cjs.js +1 -1
- package/dist/flux.esm.js +1 -1
- package/dist/flux.min.js +1 -1
- package/package.json +1 -1
- package/src/self/cli.flux +11 -11
- package/src/self/cli.js +1 -1
- package/src/self/pkg.flux +45 -15
- package/src/self/pkg.js +112 -12
- package/src/self/test-runner.flux +8 -8
- package/src/self/test-runner.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [3.4.4] — 2026-06-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`flux upgrade`** — cek semua dependensi di `flux.json` dan update ke versi terbaru dari npm
|
|
14
|
+
- `flux upgrade` — update langsung, tulis ke `flux.json`
|
|
15
|
+
- `flux upgrade --check` — dry-run, hanya tampilkan update yang tersedia tanpa mengubah file
|
|
16
|
+
- Tampilkan `↑ nama@lama → baru` untuk deps yang bisa di-upgrade, `✓ nama@ver — up to date` untuk yang sudah terbaru
|
|
17
|
+
- Tandai `(dev)` untuk devDependencies
|
|
18
|
+
- `flux upgrade` dan `flux upgrade --check` ditambahkan ke help text CLI
|
|
19
|
+
- Semua perintah package manager (`add/remove/install/upgrade/search/info/list`) sekarang tampil di `flux help`
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
10
23
|
## [3.4.3] — 2026-06-26
|
|
11
24
|
|
|
12
25
|
### Fixed
|
package/dist/flux-cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*!
|
|
3
|
-
* flux-lang v3.4.
|
|
3
|
+
* flux-lang v3.4.5
|
|
4
4
|
* Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.
|
|
5
5
|
* (c) 2026 Flux Lang Contributors
|
|
6
6
|
* Released under the MIT License
|
|
@@ -7216,7 +7216,7 @@ var require_package = __commonJS({
|
|
|
7216
7216
|
"package.json"(exports2, module2) {
|
|
7217
7217
|
module2.exports = {
|
|
7218
7218
|
name: "@xnoxs/flux-lang",
|
|
7219
|
-
version: "3.4.
|
|
7219
|
+
version: "3.4.5",
|
|
7220
7220
|
description: "Flux \u2014 A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.",
|
|
7221
7221
|
main: "dist/flux.cjs.js",
|
|
7222
7222
|
module: "dist/flux.esm.js",
|
|
@@ -8571,9 +8571,8 @@ var require_pkg = __commonJS({
|
|
|
8571
8571
|
var Os = require("os");
|
|
8572
8572
|
var { readPackage, writeConfig, loadConfig: loadConfig2 } = require_config2();
|
|
8573
8573
|
var REGISTRY_URL = "https://registry.npmjs.org";
|
|
8574
|
-
var FLUX_PKG_DIR = "flux_modules";
|
|
8575
8574
|
var PKG_FILE = "flux.json";
|
|
8576
|
-
var C2 = { reset: "
|
|
8575
|
+
var C2 = { 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" };
|
|
8577
8576
|
function clr2(c, s) {
|
|
8578
8577
|
return c + s + C2.reset;
|
|
8579
8578
|
}
|
|
@@ -8691,6 +8690,7 @@ var require_pkg = __commonJS({
|
|
|
8691
8690
|
}
|
|
8692
8691
|
module2.exports.cmdRemove = cmdRemove;
|
|
8693
8692
|
async function cmdInstall(opts) {
|
|
8693
|
+
const { execSync } = require("child_process");
|
|
8694
8694
|
const cwd = process.cwd();
|
|
8695
8695
|
const pkg = ensureFluxJson(cwd);
|
|
8696
8696
|
const deps = pkg.dependencies ?? {};
|
|
@@ -8702,18 +8702,39 @@ var require_pkg = __commonJS({
|
|
|
8702
8702
|
return;
|
|
8703
8703
|
}
|
|
8704
8704
|
console.log(clr2(C2.cyan, "\n Installing ") + names.length + " package(s)...\n");
|
|
8705
|
-
const modDir = Path.join(cwd, FLUX_PKG_DIR);
|
|
8706
|
-
if (!Fs.existsSync(modDir)) {
|
|
8707
|
-
Fs.mkdirSync(modDir, { recursive: true });
|
|
8708
|
-
}
|
|
8709
8705
|
for (const name of names) {
|
|
8710
8706
|
const spec = all[name];
|
|
8711
|
-
|
|
8712
|
-
console.log(clr2(C2.gray, " \u25CB ") + name + clr2(C2.gray, "@" + version));
|
|
8707
|
+
console.log(clr2(C2.gray, " \u25CB ") + name + clr2(C2.gray, "@" + spec));
|
|
8713
8708
|
}
|
|
8714
8709
|
console.log();
|
|
8715
|
-
|
|
8716
|
-
|
|
8710
|
+
let pm = "npm";
|
|
8711
|
+
try {
|
|
8712
|
+
execSync("pnpm --version", { stdio: "pipe" });
|
|
8713
|
+
pm = "pnpm";
|
|
8714
|
+
} catch (_) {
|
|
8715
|
+
}
|
|
8716
|
+
const prodNames = Object.keys(deps);
|
|
8717
|
+
const devNames = Object.keys(devDeps);
|
|
8718
|
+
try {
|
|
8719
|
+
if (prodNames.length > 0) {
|
|
8720
|
+
const prodPkgs = prodNames.map((n) => n + "@" + (deps[n] ?? "latest")).join(" ");
|
|
8721
|
+
const installCmd = pm + " install " + prodPkgs;
|
|
8722
|
+
info("Running: " + installCmd);
|
|
8723
|
+
execSync(installCmd, { cwd, stdio: "inherit" });
|
|
8724
|
+
}
|
|
8725
|
+
if (devNames.length > 0) {
|
|
8726
|
+
const devPkgs = devNames.map((n) => n + "@" + (devDeps[n] ?? "latest")).join(" ");
|
|
8727
|
+
const devCmd = pm + " install --save-dev " + devPkgs;
|
|
8728
|
+
info("Running: " + devCmd);
|
|
8729
|
+
execSync(devCmd, { cwd, stdio: "inherit" });
|
|
8730
|
+
}
|
|
8731
|
+
console.log();
|
|
8732
|
+
ok(names.length + " package(s) installed successfully");
|
|
8733
|
+
} catch (e) {
|
|
8734
|
+
console.log();
|
|
8735
|
+
err("Install failed: " + e.message);
|
|
8736
|
+
info("Try running manually: " + pm + " install");
|
|
8737
|
+
}
|
|
8717
8738
|
console.log();
|
|
8718
8739
|
}
|
|
8719
8740
|
module2.exports.cmdInstall = cmdInstall;
|
|
@@ -8836,6 +8857,80 @@ var require_pkg = __commonJS({
|
|
|
8836
8857
|
console.log();
|
|
8837
8858
|
}
|
|
8838
8859
|
module2.exports.cmdPublish = cmdPublish2;
|
|
8860
|
+
async function cmdUpgrade(opts) {
|
|
8861
|
+
const check = opts && opts.check || false;
|
|
8862
|
+
const cwd = process.cwd();
|
|
8863
|
+
const pkg = readPackage(cwd);
|
|
8864
|
+
if (!pkg) {
|
|
8865
|
+
err("No flux.json found. Run: flux init");
|
|
8866
|
+
return;
|
|
8867
|
+
}
|
|
8868
|
+
const allDeps = Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {});
|
|
8869
|
+
const names = Object.keys(allDeps);
|
|
8870
|
+
if (names.length === 0) {
|
|
8871
|
+
info("No dependencies in flux.json");
|
|
8872
|
+
return;
|
|
8873
|
+
}
|
|
8874
|
+
console.log();
|
|
8875
|
+
console.log(clr2(C2.cyan, " Checking " + names.length + " package(s) for updates...\n"));
|
|
8876
|
+
let updated = 0;
|
|
8877
|
+
let upToDate = 0;
|
|
8878
|
+
let failed = 0;
|
|
8879
|
+
for (const name of names) {
|
|
8880
|
+
const current = allDeps[name].replace(/^[\^~>=<\s]+/, "");
|
|
8881
|
+
try {
|
|
8882
|
+
const data = await fetchJson(REGISTRY_URL + "/" + name);
|
|
8883
|
+
const latest = data["dist-tags"] && data["dist-tags"].latest;
|
|
8884
|
+
if (!latest) {
|
|
8885
|
+
err(name + " \u2014 could not resolve latest");
|
|
8886
|
+
failed++;
|
|
8887
|
+
continue;
|
|
8888
|
+
}
|
|
8889
|
+
const isDev = !!(pkg.devDependencies && pkg.devDependencies[name]);
|
|
8890
|
+
const tag = isDev ? clr2(C2.blue, " (dev)") : "";
|
|
8891
|
+
if (current === latest) {
|
|
8892
|
+
console.log(" " + clr2(C2.gray, "\u2713") + " " + clr2(C2.bold, name) + clr2(C2.gray, "@" + current + " \u2014 up to date") + tag);
|
|
8893
|
+
upToDate++;
|
|
8894
|
+
} else {
|
|
8895
|
+
console.log(" " + clr2(C2.yellow, "\u2191") + " " + clr2(C2.bold, name) + clr2(C2.gray, "@" + current) + " \u2192 " + clr2(C2.green, latest) + tag);
|
|
8896
|
+
if (!check) {
|
|
8897
|
+
if (isDev) {
|
|
8898
|
+
if (!pkg.devDependencies) pkg.devDependencies = {};
|
|
8899
|
+
pkg.devDependencies[name] = "^" + latest;
|
|
8900
|
+
} else {
|
|
8901
|
+
if (!pkg.dependencies) pkg.dependencies = {};
|
|
8902
|
+
pkg.dependencies[name] = "^" + latest;
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
updated++;
|
|
8906
|
+
}
|
|
8907
|
+
} catch (e) {
|
|
8908
|
+
err(name + " \u2014 " + e.message);
|
|
8909
|
+
failed++;
|
|
8910
|
+
}
|
|
8911
|
+
}
|
|
8912
|
+
console.log();
|
|
8913
|
+
if (check) {
|
|
8914
|
+
console.log(clr2(C2.cyan, " Check mode: no changes written."));
|
|
8915
|
+
if (updated > 0) {
|
|
8916
|
+
console.log(clr2(C2.yellow, " " + updated + " update(s) available. Run: flux upgrade"));
|
|
8917
|
+
} else {
|
|
8918
|
+
console.log(clr2(C2.green, " All packages are up to date."));
|
|
8919
|
+
}
|
|
8920
|
+
} else {
|
|
8921
|
+
if (updated > 0) {
|
|
8922
|
+
const pkgPath = Path.join(cwd, "flux.json");
|
|
8923
|
+
Fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
8924
|
+
ok(updated + " package(s) updated in flux.json");
|
|
8925
|
+
info("Run: flux install to apply changes");
|
|
8926
|
+
} else {
|
|
8927
|
+
console.log(clr2(C2.green, " \u2713 All packages are already up to date."));
|
|
8928
|
+
}
|
|
8929
|
+
if (failed > 0) info(failed + " package(s) could not be checked");
|
|
8930
|
+
}
|
|
8931
|
+
console.log();
|
|
8932
|
+
}
|
|
8933
|
+
module2.exports.cmdUpgrade = cmdUpgrade;
|
|
8839
8934
|
}
|
|
8840
8935
|
});
|
|
8841
8936
|
|
|
@@ -8914,6 +9009,13 @@ function showHelp() {
|
|
|
8914
9009
|
["fmt <file.flux>", "Format source code in-place"],
|
|
8915
9010
|
["test [dir]", "Discover and run *.test.flux files"],
|
|
8916
9011
|
["publish [--patch|minor|major]", "Bump version, update CHANGELOG, tag & release"],
|
|
9012
|
+
["add <package>[@ver] [--dev]", "Add a dependency to flux.json"],
|
|
9013
|
+
["remove <package>", "Remove a dependency from flux.json"],
|
|
9014
|
+
["install", "Install all dependencies from flux.json"],
|
|
9015
|
+
["upgrade [--check]", "Upgrade all dependencies to latest versions"],
|
|
9016
|
+
["search <query>", "Search the npm registry for packages"],
|
|
9017
|
+
["info <package>", "Show package details from npm registry"],
|
|
9018
|
+
["list", "List installed dependencies from flux.json"],
|
|
8917
9019
|
["tokens <file.flux>", "Show lexer token list"],
|
|
8918
9020
|
["ast <file.flux>", "Show Abstract Syntax Tree (JSON)"],
|
|
8919
9021
|
["repl", "Interactive REPL mode"],
|
|
@@ -10326,6 +10428,12 @@ function main() {
|
|
|
10326
10428
|
cmdList({});
|
|
10327
10429
|
break;
|
|
10328
10430
|
}
|
|
10431
|
+
case "upgrade": {
|
|
10432
|
+
const { cmdUpgrade } = require_pkg();
|
|
10433
|
+
const isCheck = process.argv.includes("--check");
|
|
10434
|
+
cmdUpgrade({ check: isCheck });
|
|
10435
|
+
break;
|
|
10436
|
+
}
|
|
10329
10437
|
case "repl":
|
|
10330
10438
|
case void 0:
|
|
10331
10439
|
if (!cmd) {
|
package/dist/flux.cjs.js
CHANGED
package/dist/flux.esm.js
CHANGED
package/dist/flux.min.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xnoxs/flux-lang",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.5",
|
|
4
4
|
"description": "Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.",
|
|
5
5
|
"main": "dist/flux.cjs.js",
|
|
6
6
|
"module": "dist/flux.esm.js",
|
package/src/self/cli.flux
CHANGED
|
@@ -27,17 +27,17 @@ val STAGE = FLUX_STAGE ?? "self-hosted"
|
|
|
27
27
|
|
|
28
28
|
// ── ANSI Colors ───────────────────────────────────────────────
|
|
29
29
|
val C = {
|
|
30
|
-
reset: "\
|
|
31
|
-
bold: "\
|
|
32
|
-
dim: "\
|
|
33
|
-
red: "\
|
|
34
|
-
green: "\
|
|
35
|
-
yellow: "\
|
|
36
|
-
blue: "\
|
|
37
|
-
cyan: "\
|
|
38
|
-
white: "\
|
|
39
|
-
gray: "\
|
|
40
|
-
magenta: "\
|
|
30
|
+
reset: "\u001b[0m",
|
|
31
|
+
bold: "\u001b[1m",
|
|
32
|
+
dim: "\u001b[2m",
|
|
33
|
+
red: "\u001b[31m",
|
|
34
|
+
green: "\u001b[32m",
|
|
35
|
+
yellow: "\u001b[33m",
|
|
36
|
+
blue: "\u001b[34m",
|
|
37
|
+
cyan: "\u001b[36m",
|
|
38
|
+
white: "\u001b[37m",
|
|
39
|
+
gray: "\u001b[90m",
|
|
40
|
+
magenta: "\u001b[35m",
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
val noColor = process.env.NO_COLOR or not process.stdout.isTTY
|
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: "\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" };
|
|
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));
|
package/src/self/pkg.flux
CHANGED
|
@@ -25,15 +25,15 @@ val PKG_FILE = "flux.json"
|
|
|
25
25
|
|
|
26
26
|
// ── ANSI colors ───────────────────────────────────────────────
|
|
27
27
|
val C = {
|
|
28
|
-
reset: "\
|
|
29
|
-
bold: "\
|
|
30
|
-
dim: "\
|
|
31
|
-
red: "\
|
|
32
|
-
green: "\
|
|
33
|
-
yellow: "\
|
|
34
|
-
blue: "\
|
|
35
|
-
cyan: "\
|
|
36
|
-
gray: "\
|
|
28
|
+
reset: "\u001b[0m",
|
|
29
|
+
bold: "\u001b[1m",
|
|
30
|
+
dim: "\u001b[2m",
|
|
31
|
+
red: "\u001b[31m",
|
|
32
|
+
green: "\u001b[32m",
|
|
33
|
+
yellow: "\u001b[33m",
|
|
34
|
+
blue: "\u001b[34m",
|
|
35
|
+
cyan: "\u001b[36m",
|
|
36
|
+
gray: "\u001b[90m",
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
fn clr(c, s): return c + s + C.reset
|
|
@@ -157,6 +157,8 @@ export fn cmdRemove(names, opts):
|
|
|
157
157
|
|
|
158
158
|
// ── flux install ──────────────────────────────────────────────
|
|
159
159
|
export async fn cmdInstall(opts):
|
|
160
|
+
import { execSync } from "child_process"
|
|
161
|
+
|
|
160
162
|
val cwd = process.cwd()
|
|
161
163
|
val pkg = ensureFluxJson(cwd)
|
|
162
164
|
|
|
@@ -171,17 +173,45 @@ export async fn cmdInstall(opts):
|
|
|
171
173
|
|
|
172
174
|
console.log(clr(C.cyan, "\n Installing ") + names.length + " package(s)...\n")
|
|
173
175
|
|
|
174
|
-
val modDir = Path.join(cwd, FLUX_PKG_DIR)
|
|
175
|
-
if not Fs.existsSync(modDir): Fs.mkdirSync(modDir, { recursive: true })
|
|
176
|
-
|
|
177
176
|
for name in names:
|
|
178
177
|
val spec = all[name]
|
|
179
178
|
val version = spec.replace(/[\^~>=<]/g, "").split(" ")[0]
|
|
180
|
-
console.log(clr(C.gray, " ○ ") + name + clr(C.gray, "@" +
|
|
179
|
+
console.log(clr(C.gray, " ○ ") + name + clr(C.gray, "@" + spec))
|
|
181
180
|
|
|
182
181
|
console.log()
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
|
|
183
|
+
// Detect available package manager: prefer pnpm, fall back to npm
|
|
184
|
+
var pm = "npm"
|
|
185
|
+
try:
|
|
186
|
+
execSync("pnpm --version", { stdio: "pipe" })
|
|
187
|
+
pm = "pnpm"
|
|
188
|
+
catch(e):
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
val prodNames = Object.keys(deps)
|
|
192
|
+
val devNames = Object.keys(devDeps)
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
if prodNames.length > 0:
|
|
196
|
+
val prodPkgs = prodNames.map(n -> n + "@" + (deps[n] ?? "latest")).join(" ")
|
|
197
|
+
val installCmd = pm + " install " + prodPkgs
|
|
198
|
+
info("Running: " + installCmd)
|
|
199
|
+
execSync(installCmd, { cwd: cwd, stdio: "inherit" })
|
|
200
|
+
|
|
201
|
+
if devNames.length > 0:
|
|
202
|
+
val devPkgs = devNames.map(n -> n + "@" + (devDeps[n] ?? "latest")).join(" ")
|
|
203
|
+
val devFlag = pm == "pnpm" ? " --save-dev" : " --save-dev"
|
|
204
|
+
val devCmd = pm + " install" + devFlag + " " + devPkgs
|
|
205
|
+
info("Running: " + devCmd)
|
|
206
|
+
execSync(devCmd, { cwd: cwd, stdio: "inherit" })
|
|
207
|
+
|
|
208
|
+
console.log()
|
|
209
|
+
ok(names.length + " package(s) installed successfully")
|
|
210
|
+
catch(e):
|
|
211
|
+
console.log()
|
|
212
|
+
err("Install failed: " + e.message)
|
|
213
|
+
info("Try running manually: " + pm + " install")
|
|
214
|
+
|
|
185
215
|
console.log()
|
|
186
216
|
|
|
187
217
|
// ── flux list ─────────────────────────────────────────────────
|
package/src/self/pkg.js
CHANGED
|
@@ -19,7 +19,7 @@ const { readPackage, writeConfig, loadConfig } = require("./config");
|
|
|
19
19
|
const REGISTRY_URL = "https://registry.npmjs.org";
|
|
20
20
|
const FLUX_PKG_DIR = "flux_modules";
|
|
21
21
|
const PKG_FILE = "flux.json";
|
|
22
|
-
const C = { reset: "
|
|
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" };
|
|
23
23
|
function clr(c, s) {
|
|
24
24
|
return ((c + s) + C.reset);
|
|
25
25
|
}
|
|
@@ -139,10 +139,11 @@ function cmdRemove(names, opts) {
|
|
|
139
139
|
}
|
|
140
140
|
module.exports.cmdRemove = cmdRemove;
|
|
141
141
|
async function cmdInstall(opts) {
|
|
142
|
+
const { execSync } = require("child_process");
|
|
142
143
|
const cwd = process.cwd();
|
|
143
144
|
const pkg = ensureFluxJson(cwd);
|
|
144
|
-
const deps = (pkg.dependencies ?? {
|
|
145
|
-
const devDeps = (pkg.devDependencies ?? {
|
|
145
|
+
const deps = (pkg.dependencies ?? {});
|
|
146
|
+
const devDeps = (pkg.devDependencies ?? {});
|
|
146
147
|
const all = { ...deps, ...devDeps };
|
|
147
148
|
const names = Object.keys(all);
|
|
148
149
|
if ((names.length == 0)) {
|
|
@@ -150,18 +151,42 @@ async function cmdInstall(opts) {
|
|
|
150
151
|
return;
|
|
151
152
|
}
|
|
152
153
|
console.log(((clr(C.cyan, "\n Installing ") + names.length) + " package(s)...\n"));
|
|
153
|
-
const modDir = Path.join(cwd, FLUX_PKG_DIR);
|
|
154
|
-
if (!Fs.existsSync(modDir)) {
|
|
155
|
-
Fs.mkdirSync(modDir, { recursive: true });
|
|
156
|
-
}
|
|
157
154
|
for (const name of names) {
|
|
158
155
|
const spec = all[name];
|
|
159
|
-
|
|
160
|
-
console.log(((clr(C.gray, " ○ ") + name) + clr(C.gray, ("@" + version))));
|
|
156
|
+
console.log(((clr(C.gray, " ○ ") + name) + clr(C.gray, ("@" + spec))));
|
|
161
157
|
}
|
|
162
158
|
console.log();
|
|
163
|
-
|
|
164
|
-
|
|
159
|
+
|
|
160
|
+
// Detect available package manager: prefer pnpm, fall back to npm
|
|
161
|
+
let pm = "npm";
|
|
162
|
+
try {
|
|
163
|
+
execSync("pnpm --version", { stdio: "pipe" });
|
|
164
|
+
pm = "pnpm";
|
|
165
|
+
} catch (_) {}
|
|
166
|
+
|
|
167
|
+
const prodNames = Object.keys(deps);
|
|
168
|
+
const devNames = Object.keys(devDeps);
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
if (prodNames.length > 0) {
|
|
172
|
+
const prodPkgs = prodNames.map(n => n + "@" + (deps[n] ?? "latest")).join(" ");
|
|
173
|
+
const installCmd = pm + " install " + prodPkgs;
|
|
174
|
+
info("Running: " + installCmd);
|
|
175
|
+
execSync(installCmd, { cwd: cwd, stdio: "inherit" });
|
|
176
|
+
}
|
|
177
|
+
if (devNames.length > 0) {
|
|
178
|
+
const devPkgs = devNames.map(n => n + "@" + (devDeps[n] ?? "latest")).join(" ");
|
|
179
|
+
const devCmd = pm + " install --save-dev " + devPkgs;
|
|
180
|
+
info("Running: " + devCmd);
|
|
181
|
+
execSync(devCmd, { cwd: cwd, stdio: "inherit" });
|
|
182
|
+
}
|
|
183
|
+
console.log();
|
|
184
|
+
ok(names.length + " package(s) installed successfully");
|
|
185
|
+
} catch (e) {
|
|
186
|
+
console.log();
|
|
187
|
+
err("Install failed: " + e.message);
|
|
188
|
+
info("Try running manually: " + pm + " install");
|
|
189
|
+
}
|
|
165
190
|
console.log();
|
|
166
191
|
}
|
|
167
192
|
module.exports.cmdInstall = cmdInstall;
|
|
@@ -283,4 +308,79 @@ function cmdPublish(opts) {
|
|
|
283
308
|
info("Run: flux publish --registry <url> for a custom registry");
|
|
284
309
|
console.log();
|
|
285
310
|
}
|
|
286
|
-
module.exports.cmdPublish = cmdPublish;
|
|
311
|
+
module.exports.cmdPublish = cmdPublish;
|
|
312
|
+
|
|
313
|
+
// ── flux upgrade [--check] ─────────────────────────────────────────────────
|
|
314
|
+
// Checks all dependencies in flux.json for newer versions and updates them.
|
|
315
|
+
// --check : dry-run, only show what would change without writing
|
|
316
|
+
async function cmdUpgrade(opts) {
|
|
317
|
+
const check = (opts && opts.check) || false;
|
|
318
|
+
const cwd = process.cwd();
|
|
319
|
+
const pkg = readPackage(cwd);
|
|
320
|
+
if (!pkg) { err('No flux.json found. Run: flux init'); return; }
|
|
321
|
+
|
|
322
|
+
const allDeps = Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {});
|
|
323
|
+
const names = Object.keys(allDeps);
|
|
324
|
+
if (names.length === 0) { info('No dependencies in flux.json'); return; }
|
|
325
|
+
|
|
326
|
+
console.log();
|
|
327
|
+
console.log(clr(C.cyan, ' Checking ' + names.length + ' package(s) for updates...\n'));
|
|
328
|
+
|
|
329
|
+
let updated = 0;
|
|
330
|
+
let upToDate = 0;
|
|
331
|
+
let failed = 0;
|
|
332
|
+
|
|
333
|
+
for (const name of names) {
|
|
334
|
+
const current = allDeps[name].replace(/^[\^~>=<\s]+/, '');
|
|
335
|
+
try {
|
|
336
|
+
const data = await fetchJson(REGISTRY_URL + '/' + name);
|
|
337
|
+
const latest = data['dist-tags'] && data['dist-tags'].latest;
|
|
338
|
+
if (!latest) { err(name + ' — could not resolve latest'); failed++; continue; }
|
|
339
|
+
|
|
340
|
+
const isDev = !!(pkg.devDependencies && pkg.devDependencies[name]);
|
|
341
|
+
const tag = isDev ? clr(C.blue, ' (dev)') : '';
|
|
342
|
+
|
|
343
|
+
if (current === latest) {
|
|
344
|
+
console.log(' ' + clr(C.gray, '✓') + ' ' + clr(C.bold, name) + clr(C.gray, '@' + current + ' — up to date') + tag);
|
|
345
|
+
upToDate++;
|
|
346
|
+
} else {
|
|
347
|
+
console.log(' ' + clr(C.yellow, '↑') + ' ' + clr(C.bold, name) + clr(C.gray, '@' + current) + ' → ' + clr(C.green, latest) + tag);
|
|
348
|
+
if (!check) {
|
|
349
|
+
if (isDev) {
|
|
350
|
+
if (!pkg.devDependencies) pkg.devDependencies = {};
|
|
351
|
+
pkg.devDependencies[name] = '^' + latest;
|
|
352
|
+
} else {
|
|
353
|
+
if (!pkg.dependencies) pkg.dependencies = {};
|
|
354
|
+
pkg.dependencies[name] = '^' + latest;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
updated++;
|
|
358
|
+
}
|
|
359
|
+
} catch (e) {
|
|
360
|
+
err(name + ' — ' + e.message);
|
|
361
|
+
failed++;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
console.log();
|
|
366
|
+
if (check) {
|
|
367
|
+
console.log(clr(C.cyan, ' Check mode: no changes written.'));
|
|
368
|
+
if (updated > 0) {
|
|
369
|
+
console.log(clr(C.yellow, ' ' + updated + ' update(s) available. Run: flux upgrade'));
|
|
370
|
+
} else {
|
|
371
|
+
console.log(clr(C.green, ' All packages are up to date.'));
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
if (updated > 0) {
|
|
375
|
+
const pkgPath = Path.join(cwd, 'flux.json');
|
|
376
|
+
Fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
377
|
+
ok(updated + ' package(s) updated in flux.json');
|
|
378
|
+
info('Run: flux install to apply changes');
|
|
379
|
+
} else {
|
|
380
|
+
console.log(clr(C.green, ' ✓ All packages are already up to date.'));
|
|
381
|
+
}
|
|
382
|
+
if (failed > 0) info(failed + ' package(s) could not be checked');
|
|
383
|
+
}
|
|
384
|
+
console.log();
|
|
385
|
+
}
|
|
386
|
+
module.exports.cmdUpgrade = cmdUpgrade;
|
|
@@ -13,14 +13,14 @@ import Path from "path"
|
|
|
13
13
|
import Os from "os"
|
|
14
14
|
|
|
15
15
|
val C = {
|
|
16
|
-
reset: '\
|
|
17
|
-
bold: '\
|
|
18
|
-
red: '\
|
|
19
|
-
green: '\
|
|
20
|
-
yellow: '\
|
|
21
|
-
cyan: '\
|
|
22
|
-
gray: '\
|
|
23
|
-
dim: '\
|
|
16
|
+
reset: '\u001b[0m',
|
|
17
|
+
bold: '\u001b[1m',
|
|
18
|
+
red: '\u001b[31m',
|
|
19
|
+
green: '\u001b[32m',
|
|
20
|
+
yellow: '\u001b[33m',
|
|
21
|
+
cyan: '\u001b[36m',
|
|
22
|
+
gray: '\u001b[90m',
|
|
23
|
+
dim: '\u001b[2m',
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
fn clr(c, s):
|
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: "\x1b[0m", bold: "\x1b[1m", red: "\x1b[31m", green: "\x1b[32m", yellow: "\x1b[33m", cyan: "\x1b[36m", gray: "\x1b[90m", dim: "\x1b[2m" };
|
|
25
25
|
function clr(c, s) {
|
|
26
26
|
return (process.env.NO_COLOR ? s : ((c + s) + C.reset));
|
|
27
27
|
}
|