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