@xnoxs/flux-lang 3.4.8 → 3.5.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/CHANGELOG.md +17 -0
- package/bin/flux.js +1 -1
- package/dist/flux-cli.js +199 -117
- package/dist/flux.cjs.js +37 -4
- package/dist/flux.esm.js +37 -4
- package/dist/flux.min.js +33 -33
- package/package.json +1 -1
- package/src/self/bundler.js +3 -3
- package/src/self/cli.js +1 -1
- package/src/self/pkg.flux +144 -37
- package/src/self/pkg.js +179 -129
- package/src/self/test-runner.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xnoxs/flux-lang",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
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/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.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));
|
package/src/self/pkg.flux
CHANGED
|
@@ -36,11 +36,33 @@ val C = {
|
|
|
36
36
|
gray: "\u001b[90m",
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
val hasColor = process.env.COLORTERM or process.env.FORCE_COLOR or (process.stdout.isTTY and process.env.TERM != "dumb")
|
|
40
|
+
val noColor = process.env.NO_COLOR or not hasColor
|
|
41
|
+
|
|
42
|
+
fn clr(c, s): return noColor ? s : c + s + C.reset
|
|
40
43
|
fn ok(msg): console.log(clr(C.green, "✓ ") + msg)
|
|
41
44
|
fn err(msg): console.error(clr(C.red, "✗ ") + msg)
|
|
42
45
|
fn info(msg): console.log(clr(C.cyan, " ") + msg)
|
|
43
46
|
|
|
47
|
+
// ── Spinner animation ─────────────────────────────────────────
|
|
48
|
+
fn createSpinner(msg):
|
|
49
|
+
if noColor:
|
|
50
|
+
process.stdout.write(" " + msg + " ...\n")
|
|
51
|
+
fn _stop(ok_, done):
|
|
52
|
+
process.stdout.write(" " + (ok_ ? "✓" : "✗") + " " + done + "\n")
|
|
53
|
+
return { stop: _stop }
|
|
54
|
+
val frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
|
|
55
|
+
var fi = 0
|
|
56
|
+
fn tick():
|
|
57
|
+
process.stdout.write("\r " + clr(C.cyan, frames[fi % frames.length]) + " " + msg + " ")
|
|
58
|
+
fi = fi + 1
|
|
59
|
+
val timer = setInterval(tick, 80)
|
|
60
|
+
fn stop(ok_, done):
|
|
61
|
+
clearInterval(timer)
|
|
62
|
+
val icon = ok_ ? clr(C.green, "✓") : clr(C.red, "✗")
|
|
63
|
+
process.stdout.write("\r " + icon + " " + done + " \n")
|
|
64
|
+
return { stop: stop }
|
|
65
|
+
|
|
44
66
|
// ── HTTP fetch (Node built-in, no dependencies) ───────────────
|
|
45
67
|
async fn fetchJson(url):
|
|
46
68
|
val mod = url.startsWith("https") ? Https : Http
|
|
@@ -100,10 +122,12 @@ export async fn cmdAdd(specs, opts):
|
|
|
100
122
|
val isDev = opts?.dev ?? false
|
|
101
123
|
val cwd = process.cwd()
|
|
102
124
|
val pkg = ensureFluxJson(cwd)
|
|
125
|
+
var addedCount = 0
|
|
103
126
|
|
|
127
|
+
console.log()
|
|
104
128
|
for spec in specs:
|
|
105
129
|
val { name, version } = parsePackageSpec(spec)
|
|
106
|
-
|
|
130
|
+
val spinner = createSpinner(clr(C.bold, name) + clr(C.gray, "@" + version))
|
|
107
131
|
|
|
108
132
|
try:
|
|
109
133
|
val info_ = await fetchJson(REGISTRY_URL + "/" + name)
|
|
@@ -111,25 +135,25 @@ export async fn cmdAdd(specs, opts):
|
|
|
111
135
|
|
|
112
136
|
val versionInfo = info_.versions?.[resolvedVersion]
|
|
113
137
|
if not versionInfo:
|
|
114
|
-
|
|
138
|
+
spinner.stop(false, clr(C.bold, name) + clr(C.gray, "@" + resolvedVersion) + " — version not found")
|
|
115
139
|
continue
|
|
116
140
|
|
|
117
141
|
val depKey = isDev ? "devDependencies" : "dependencies"
|
|
118
142
|
if not pkg[depKey]: pkg[depKey] = {}
|
|
119
143
|
pkg[depKey][name] = "^" + resolvedVersion
|
|
120
|
-
|
|
121
144
|
saveFluxJson(pkg, cwd)
|
|
122
145
|
|
|
123
|
-
val
|
|
124
|
-
|
|
125
|
-
|
|
146
|
+
val shortDesc = versionInfo.description ? clr(C.gray, " — " + versionInfo.description.slice(0, 55)) : ""
|
|
147
|
+
spinner.stop(true, clr(C.bold, name) + clr(C.green, "@" + resolvedVersion) + shortDesc)
|
|
148
|
+
addedCount = addedCount + 1
|
|
126
149
|
|
|
127
150
|
catch(e):
|
|
128
|
-
|
|
151
|
+
spinner.stop(false, clr(C.bold, name) + " — " + e.message)
|
|
129
152
|
|
|
130
153
|
console.log()
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
if addedCount > 0:
|
|
155
|
+
console.log(" " + clr(C.gray, "Run ") + clr(C.yellow, "flux install") + clr(C.gray, " to install packages"))
|
|
156
|
+
console.log()
|
|
133
157
|
|
|
134
158
|
// ── flux remove <pkg> ─────────────────────────────────────────
|
|
135
159
|
export fn cmdRemove(names, opts):
|
|
@@ -169,15 +193,19 @@ export async fn cmdInstall(opts):
|
|
|
169
193
|
val names = Object.keys(all)
|
|
170
194
|
|
|
171
195
|
if names.length == 0:
|
|
196
|
+
console.log()
|
|
172
197
|
info("No dependencies found in flux.json")
|
|
198
|
+
console.log()
|
|
173
199
|
return
|
|
174
200
|
|
|
175
|
-
console.log(
|
|
176
|
-
|
|
201
|
+
console.log()
|
|
202
|
+
console.log(" " + clr(C.bold, pkg.name ?? "project") + clr(C.gray, " — " + names.length + " package(s)"))
|
|
203
|
+
console.log()
|
|
177
204
|
for name in names:
|
|
178
205
|
val spec = all[name]
|
|
179
|
-
|
|
180
|
-
|
|
206
|
+
val isDev_ = Object.prototype.hasOwnProperty.call(devDeps, name)
|
|
207
|
+
val tag = isDev_ ? clr(C.gray, " dev") : ""
|
|
208
|
+
console.log(" " + clr(C.gray, "○") + " " + clr(isDev_ ? C.blue : C.green, name) + clr(C.gray, "@" + spec) + tag)
|
|
181
209
|
console.log()
|
|
182
210
|
|
|
183
211
|
// Ensure flux_modules/ exists with a minimal package.json
|
|
@@ -191,27 +219,26 @@ export async fn cmdInstall(opts):
|
|
|
191
219
|
|
|
192
220
|
val prodNames = Object.keys(deps)
|
|
193
221
|
val devNames = Object.keys(devDeps)
|
|
222
|
+
val spinner = createSpinner("Installing packages into flux_modules/")
|
|
194
223
|
|
|
195
224
|
try:
|
|
196
225
|
if prodNames.length > 0:
|
|
197
226
|
val prodPkgs = prodNames.map(n -> n + "@" + (deps[n] ?? "latest")).join(" ")
|
|
198
227
|
val installCmd = "npm install --prefix " + fluxModDir + " " + prodPkgs
|
|
199
|
-
|
|
200
|
-
execSync(installCmd, { cwd: cwd, stdio: "inherit" })
|
|
228
|
+
execSync(installCmd, { cwd: cwd, stdio: "pipe" })
|
|
201
229
|
|
|
202
230
|
if devNames.length > 0:
|
|
203
231
|
val devPkgs = devNames.map(n -> n + "@" + (devDeps[n] ?? "latest")).join(" ")
|
|
204
232
|
val devCmd = "npm install --prefix " + fluxModDir + " --save-dev " + devPkgs
|
|
205
|
-
|
|
206
|
-
execSync(devCmd, { cwd: cwd, stdio: "inherit" })
|
|
233
|
+
execSync(devCmd, { cwd: cwd, stdio: "pipe" })
|
|
207
234
|
|
|
235
|
+
spinner.stop(true, names.length + " package(s) installed into " + clr(C.gray, "flux_modules/"))
|
|
208
236
|
console.log()
|
|
209
|
-
|
|
210
|
-
info("Packages resolve automatically when using: flux run, flux bundle")
|
|
237
|
+
console.log(" " + clr(C.gray, "Packages resolve automatically when using: ") + clr(C.yellow, "flux run") + clr(C.gray, ", ") + clr(C.yellow, "flux bundle"))
|
|
211
238
|
catch(e):
|
|
239
|
+
spinner.stop(false, "Install failed: " + e.message)
|
|
212
240
|
console.log()
|
|
213
|
-
|
|
214
|
-
info("Try manually: npm install --prefix ./flux_modules <package>")
|
|
241
|
+
console.log(" " + clr(C.gray, "Try: ") + clr(C.yellow, "npm install --prefix ./flux_modules <package>"))
|
|
215
242
|
|
|
216
243
|
console.log()
|
|
217
244
|
|
|
@@ -249,58 +276,138 @@ export fn cmdList(opts):
|
|
|
249
276
|
|
|
250
277
|
// ── flux search <query> ───────────────────────────────────────
|
|
251
278
|
export async fn cmdSearch(query, opts):
|
|
252
|
-
console.log(
|
|
279
|
+
console.log()
|
|
280
|
+
val spinner = createSpinner("Searching for " + clr(C.bold, '"' + query + '"'))
|
|
253
281
|
try:
|
|
254
|
-
val url = REGISTRY_URL + "/-/v1/search?text=" + encodeURIComponent(query
|
|
282
|
+
val url = REGISTRY_URL + "/-/v1/search?text=" + encodeURIComponent(query) + "&size=10"
|
|
255
283
|
val results = await fetchJson(url)
|
|
256
284
|
val objects = results.objects ?? []
|
|
257
285
|
|
|
258
286
|
if objects.length == 0:
|
|
259
|
-
|
|
287
|
+
spinner.stop(false, "No packages found for: " + query)
|
|
260
288
|
console.log()
|
|
261
289
|
return
|
|
262
290
|
|
|
291
|
+
spinner.stop(true, "Found " + objects.length + " result(s) for " + clr(C.bold, '"' + query + '"'))
|
|
292
|
+
console.log()
|
|
293
|
+
|
|
263
294
|
for obj in objects:
|
|
264
295
|
val p = obj.package
|
|
265
296
|
console.log(" " + clr(C.bold, p.name) + clr(C.gray, " v" + p.version))
|
|
266
297
|
if p.description:
|
|
267
298
|
console.log(" " + clr(C.gray, p.description))
|
|
268
|
-
|
|
299
|
+
if p.links?.npm:
|
|
300
|
+
console.log(" " + clr(C.blue, p.links.npm))
|
|
269
301
|
console.log()
|
|
270
302
|
|
|
271
303
|
catch(e):
|
|
272
|
-
|
|
304
|
+
spinner.stop(false, "Search failed: " + e.message)
|
|
305
|
+
console.log()
|
|
273
306
|
|
|
274
307
|
// ── flux info <pkg> ───────────────────────────────────────────
|
|
275
308
|
export async fn cmdInfo(name, opts):
|
|
276
|
-
console.log(
|
|
309
|
+
console.log()
|
|
310
|
+
val spinner = createSpinner("Fetching info for " + clr(C.bold, name))
|
|
277
311
|
try:
|
|
278
312
|
val info_ = await fetchJson(REGISTRY_URL + "/" + name)
|
|
279
313
|
val latest = info_["dist-tags"]?.latest ?? "unknown"
|
|
280
314
|
val ver = info_.versions?.[latest] ?? {}
|
|
281
315
|
|
|
282
|
-
|
|
283
|
-
if ver.description: console.log(" " + ver.description)
|
|
316
|
+
spinner.stop(true, clr(C.bold, name) + clr(C.green, "@" + latest))
|
|
284
317
|
console.log()
|
|
285
|
-
console.log(clr(C.gray,
|
|
286
|
-
console.log(
|
|
318
|
+
if ver.description: console.log(" " + clr(C.gray, ver.description))
|
|
319
|
+
console.log()
|
|
320
|
+
console.log(" " + clr(C.gray, "license:") + " " + (ver.license ?? "unknown"))
|
|
321
|
+
console.log(" " + clr(C.gray, "author: ") + " " + (ver.author?.name ?? ver.author ?? "unknown"))
|
|
287
322
|
|
|
288
323
|
val homepage = ver.homepage ?? info_.homepage
|
|
289
|
-
if homepage: console.log(clr(C.gray, "
|
|
324
|
+
if homepage: console.log(" " + clr(C.gray, "home: ") + " " + clr(C.blue, homepage))
|
|
290
325
|
|
|
291
326
|
val repo = ver.repository?.url ?? info_.repository?.url
|
|
292
|
-
if repo: console.log(clr(C.gray, "
|
|
327
|
+
if repo: console.log(" " + clr(C.gray, "repo: ") + " " + clr(C.blue, repo.replace("git+", "").replace(".git", "")))
|
|
293
328
|
|
|
294
329
|
val keywords = ver.keywords ?? []
|
|
295
330
|
if keywords.length > 0:
|
|
296
|
-
console.log(clr(C.gray, "
|
|
331
|
+
console.log(" " + clr(C.gray, "tags: ") + " " + keywords.slice(0, 8).join(", "))
|
|
297
332
|
|
|
298
333
|
console.log()
|
|
299
|
-
console.log(clr(C.gray, "
|
|
334
|
+
console.log(" " + clr(C.gray, "Install: ") + clr(C.yellow, "flux add " + name))
|
|
300
335
|
console.log()
|
|
301
336
|
|
|
302
337
|
catch(e):
|
|
303
|
-
|
|
338
|
+
spinner.stop(false, "Could not fetch info for " + name + ": " + e.message)
|
|
339
|
+
console.log()
|
|
340
|
+
|
|
341
|
+
// ── flux upgrade [--check] ────────────────────────────────────
|
|
342
|
+
export async fn cmdUpgrade(opts):
|
|
343
|
+
val isCheck = opts?.check ?? false
|
|
344
|
+
val cwd = process.cwd()
|
|
345
|
+
val pkg = ensureFluxJson(cwd)
|
|
346
|
+
|
|
347
|
+
val deps = pkg.dependencies ?? {}
|
|
348
|
+
val devDeps = pkg.devDependencies ?? {}
|
|
349
|
+
val allKeys = [...Object.keys(deps), ...Object.keys(devDeps)]
|
|
350
|
+
|
|
351
|
+
if allKeys.length == 0:
|
|
352
|
+
console.log()
|
|
353
|
+
info("No dependencies to upgrade")
|
|
354
|
+
console.log()
|
|
355
|
+
return
|
|
356
|
+
|
|
357
|
+
console.log()
|
|
358
|
+
var updated = 0
|
|
359
|
+
|
|
360
|
+
for name in Object.keys(deps):
|
|
361
|
+
val spinner = createSpinner(clr(C.green, name))
|
|
362
|
+
try:
|
|
363
|
+
val info_ = await fetchJson(REGISTRY_URL + "/" + name)
|
|
364
|
+
val latest = info_["dist-tags"]?.latest ?? null
|
|
365
|
+
if not latest:
|
|
366
|
+
spinner.stop(false, clr(C.green, name) + " — could not resolve latest version")
|
|
367
|
+
continue
|
|
368
|
+
val current = deps[name].replace("^", "").replace("~", "")
|
|
369
|
+
if latest == current:
|
|
370
|
+
spinner.stop(true, clr(C.green, name) + clr(C.gray, "@" + current + " — up to date"))
|
|
371
|
+
else:
|
|
372
|
+
spinner.stop(true, clr(C.green, name) + clr(C.gray, "@" + current) + " → " + clr(C.yellow, latest))
|
|
373
|
+
if not isCheck:
|
|
374
|
+
pkg.dependencies[name] = "^" + latest
|
|
375
|
+
updated = updated + 1
|
|
376
|
+
catch(e):
|
|
377
|
+
spinner.stop(false, clr(C.green, name) + " — " + e.message)
|
|
378
|
+
|
|
379
|
+
for name in Object.keys(devDeps):
|
|
380
|
+
val spinner = createSpinner(clr(C.blue, name) + clr(C.gray, " (dev)"))
|
|
381
|
+
try:
|
|
382
|
+
val info_ = await fetchJson(REGISTRY_URL + "/" + name)
|
|
383
|
+
val latest = info_["dist-tags"]?.latest ?? null
|
|
384
|
+
if not latest:
|
|
385
|
+
spinner.stop(false, clr(C.blue, name) + " — could not resolve latest version")
|
|
386
|
+
continue
|
|
387
|
+
val current = devDeps[name].replace("^", "").replace("~", "")
|
|
388
|
+
if latest == current:
|
|
389
|
+
spinner.stop(true, clr(C.blue, name) + clr(C.gray, "@" + current + " — up to date"))
|
|
390
|
+
else:
|
|
391
|
+
spinner.stop(true, clr(C.blue, name) + clr(C.gray, "@" + current) + " → " + clr(C.yellow, latest) + clr(C.gray, " (dev)"))
|
|
392
|
+
if not isCheck:
|
|
393
|
+
pkg.devDependencies[name] = "^" + latest
|
|
394
|
+
updated = updated + 1
|
|
395
|
+
catch(e):
|
|
396
|
+
spinner.stop(false, clr(C.blue, name) + " — " + e.message)
|
|
397
|
+
|
|
398
|
+
console.log()
|
|
399
|
+
|
|
400
|
+
if isCheck:
|
|
401
|
+
ok("Check complete — run " + clr(C.yellow, "flux upgrade") + " to apply upgrades")
|
|
402
|
+
else:
|
|
403
|
+
if updated > 0:
|
|
404
|
+
saveFluxJson(pkg, cwd)
|
|
405
|
+
ok(updated + " package(s) updated in flux.json")
|
|
406
|
+
console.log(" " + clr(C.gray, "Run ") + clr(C.yellow, "flux install") + clr(C.gray, " to install upgraded packages"))
|
|
407
|
+
else:
|
|
408
|
+
ok("All packages are already up to date")
|
|
409
|
+
|
|
410
|
+
console.log()
|
|
304
411
|
|
|
305
412
|
// ── flux publish ──────────────────────────────────────────────
|
|
306
413
|
export fn cmdPublish(opts):
|