@ucdjs/cli 0.2.2 → 0.3.1-beta.1
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/bin/ucd.js +1 -1
- package/dist/_shared-CgcKJJFf.mjs +113 -0
- package/dist/analyze-D8AeAGDR.mjs +75 -0
- package/dist/cli.mjs +403 -0
- package/dist/{fields-Cz0PV1Co.js → fields-BvLDPLGg.mjs} +9 -19
- package/dist/get-CHw5s5Ab.mjs +63 -0
- package/dist/hash-BAViT6QD.mjs +116 -0
- package/dist/info-D2uPOmns.mjs +100 -0
- package/dist/info-ZGysg0N_.mjs +75 -0
- package/dist/init-DilsO33p.mjs +126 -0
- package/dist/list-C1bd3Vq4.mjs +89 -0
- package/dist/mirror-DLYQGa33.mjs +130 -0
- package/dist/root-BnOeYqGP.mjs +57 -0
- package/dist/root-C_Ycy7kI.mjs +88 -0
- package/dist/{root-oHWSp_5G.js → root-CfALAyOQ.mjs} +6 -5
- package/dist/root-DXVHyPa6.mjs +61 -0
- package/dist/status-DI1HruH0.mjs +136 -0
- package/dist/sync-DEtQ-jZc.mjs +160 -0
- package/dist/validate-DVr1TaHK.mjs +114 -0
- package/dist/verify-ME4bDNIT.mjs +114 -0
- package/package.json +34 -18
- package/dist/cli-utils-DY82m2wz.js +0 -195
- package/dist/cli.js +0 -7
- package/dist/download-CCx2vdOj.js +0 -203
- /package/dist/{cli.d.ts → cli.d.mts} +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { _ as output, c as bold, p as green, t as printHelp, u as dim, v as red, y as yellow } from "./cli.mjs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { safeJsonParse } from "@ucdjs-internal/shared";
|
|
6
|
+
import { getLockfilePath, validateLockfile } from "@ucdjs/lockfile";
|
|
7
|
+
|
|
8
|
+
//#region src/cmd/lockfile/validate.ts
|
|
9
|
+
async function runLockfileValidate({ flags }) {
|
|
10
|
+
if (flags?.help || flags?.h) {
|
|
11
|
+
printHelp({
|
|
12
|
+
headline: "Validate lockfile against the expected schema",
|
|
13
|
+
commandName: "ucd lockfile validate",
|
|
14
|
+
usage: "[...flags]",
|
|
15
|
+
description: "Parse and validate the UCD store lockfile, reporting any schema violations or structural issues.",
|
|
16
|
+
tables: { Flags: [
|
|
17
|
+
["--store-dir", "Directory where the UCD store is located (defaults to current directory)."],
|
|
18
|
+
["--json", "Output validation results as JSON."],
|
|
19
|
+
["--help (-h)", "See all available flags."]
|
|
20
|
+
] }
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const { storeDir, json } = flags;
|
|
25
|
+
const lockfilePath = resolve(storeDir ? resolve(storeDir) : process.cwd(), getLockfilePath());
|
|
26
|
+
try {
|
|
27
|
+
let rawContent;
|
|
28
|
+
try {
|
|
29
|
+
rawContent = await readFile(lockfilePath, "utf-8");
|
|
30
|
+
} catch {
|
|
31
|
+
if (json) output.json({
|
|
32
|
+
valid: false,
|
|
33
|
+
lockfilePath,
|
|
34
|
+
error: "LOCKFILE_NOT_FOUND",
|
|
35
|
+
message: `Lockfile not found at "${lockfilePath}"`
|
|
36
|
+
});
|
|
37
|
+
else {
|
|
38
|
+
output.error(red(`\n❌ Error: Lockfile not found at "${lockfilePath}".`));
|
|
39
|
+
output.error(`\n Run ${green("ucd store init")} to create a new store.`);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const jsonData = safeJsonParse(rawContent);
|
|
44
|
+
if (!jsonData) {
|
|
45
|
+
if (json) output.json({
|
|
46
|
+
valid: false,
|
|
47
|
+
lockfilePath,
|
|
48
|
+
error: "INVALID_JSON",
|
|
49
|
+
message: "Lockfile is not valid JSON"
|
|
50
|
+
});
|
|
51
|
+
else {
|
|
52
|
+
output.error(red(`\n❌ Validation failed: Lockfile is not valid JSON.`));
|
|
53
|
+
output.error(` ${dim(`Path: ${lockfilePath}`)}`);
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const result = validateLockfile(jsonData);
|
|
58
|
+
if (!result.valid) {
|
|
59
|
+
const issues = result.errors ?? [];
|
|
60
|
+
if (json) output.json({
|
|
61
|
+
valid: false,
|
|
62
|
+
lockfilePath,
|
|
63
|
+
error: "SCHEMA_VALIDATION_FAILED",
|
|
64
|
+
issues
|
|
65
|
+
});
|
|
66
|
+
else {
|
|
67
|
+
output.error(red(`\n❌ Validation failed: Lockfile does not match expected schema.`));
|
|
68
|
+
output.error(` ${dim(`Path: ${lockfilePath}`)}\n`);
|
|
69
|
+
output.log(` ${bold("Issues:")}`);
|
|
70
|
+
for (const issue of issues) output.log(` ${yellow("•")} ${bold(issue.path || "(root)")}: ${issue.message}`);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const warnings = [];
|
|
75
|
+
const lockfile = result.data;
|
|
76
|
+
const versionCount = Object.keys(lockfile.versions).length;
|
|
77
|
+
if (versionCount === 0) warnings.push("Lockfile has no versions tracked.");
|
|
78
|
+
for (const [version, entry] of Object.entries(lockfile.versions)) {
|
|
79
|
+
if (entry.fileCount === 0) warnings.push(`Version "${version}" has 0 files.`);
|
|
80
|
+
if (entry.totalSize === 0 && entry.fileCount > 0) warnings.push(`Version "${version}" has files but totalSize is 0.`);
|
|
81
|
+
}
|
|
82
|
+
if (json) output.json({
|
|
83
|
+
valid: true,
|
|
84
|
+
lockfilePath,
|
|
85
|
+
lockfileVersion: lockfile.lockfileVersion,
|
|
86
|
+
versionCount,
|
|
87
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
88
|
+
});
|
|
89
|
+
else {
|
|
90
|
+
output.log(green(`\n✅ Lockfile is valid.`));
|
|
91
|
+
output.log(` ${dim(`Path: ${lockfilePath}`)}`);
|
|
92
|
+
output.log(` ${bold("Lockfile Version:")} ${lockfile.lockfileVersion}`);
|
|
93
|
+
output.log(` ${bold("Tracked Versions:")} ${versionCount}`);
|
|
94
|
+
if (warnings.length > 0) {
|
|
95
|
+
output.log(`\n ${yellow(bold("Warnings:"))}`);
|
|
96
|
+
for (const warning of warnings) output.log(` ${yellow("•")} ${warning}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
if (json) output.json({
|
|
101
|
+
valid: false,
|
|
102
|
+
lockfilePath,
|
|
103
|
+
error: "UNKNOWN_ERROR",
|
|
104
|
+
message: err instanceof Error ? err.message : String(err)
|
|
105
|
+
});
|
|
106
|
+
else {
|
|
107
|
+
output.error(red(`\n❌ Validation error:`));
|
|
108
|
+
if (err instanceof Error) output.error(` ${err.message}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
export { runLockfileValidate };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { _ as output, p as green, t as printHelp, v as red, y as yellow } from "./cli.mjs";
|
|
2
|
+
import { a as assertRemoteOrStoreDir, n as REMOTE_CAPABLE_FLAGS, o as createStoreFromFlags, r as SHARED_FLAGS } from "./_shared-CgcKJJFf.mjs";
|
|
3
|
+
import { createUCDClient } from "@ucdjs/client";
|
|
4
|
+
import { UCDJS_API_BASE_URL } from "@ucdjs/env";
|
|
5
|
+
import { createDebugger } from "@ucdjs-internal/shared";
|
|
6
|
+
import { getLockfilePath, readLockfile } from "@ucdjs/lockfile";
|
|
7
|
+
|
|
8
|
+
//#region src/cmd/store/verify.ts
|
|
9
|
+
const debug = createDebugger("ucdjs:cli:store:verify");
|
|
10
|
+
async function runVerifyStore({ flags }) {
|
|
11
|
+
if (flags?.help || flags?.h) {
|
|
12
|
+
printHelp({
|
|
13
|
+
headline: "Verify UCD Store integrity",
|
|
14
|
+
commandName: "ucd store verify",
|
|
15
|
+
usage: "[...versions] [...flags]",
|
|
16
|
+
tables: { Flags: [
|
|
17
|
+
...REMOTE_CAPABLE_FLAGS,
|
|
18
|
+
...SHARED_FLAGS,
|
|
19
|
+
["--json", "Output verification results in JSON format."],
|
|
20
|
+
["--help (-h)", "See all available flags."]
|
|
21
|
+
] }
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const { storeDir, remote, baseUrl, include: patterns, exclude: excludePatterns, json } = flags;
|
|
26
|
+
assertRemoteOrStoreDir(flags);
|
|
27
|
+
const store = await createStoreFromFlags({
|
|
28
|
+
baseUrl,
|
|
29
|
+
storeDir,
|
|
30
|
+
remote,
|
|
31
|
+
include: patterns,
|
|
32
|
+
exclude: excludePatterns,
|
|
33
|
+
requireExistingStore: true
|
|
34
|
+
});
|
|
35
|
+
const lockfilePath = getLockfilePath();
|
|
36
|
+
const bridge = store.fs;
|
|
37
|
+
let lockfile;
|
|
38
|
+
try {
|
|
39
|
+
lockfile = await readLockfile(bridge, lockfilePath);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
debug?.("Error reading lockfile:", err);
|
|
42
|
+
if (remote) {
|
|
43
|
+
output.error(red(`\n❌ Error: Could not read lockfile from remote store.`));
|
|
44
|
+
output.error("Verify operation requires a lockfile. For remote stores, the lockfile must be accessible via the API.");
|
|
45
|
+
} else {
|
|
46
|
+
output.error(red(`\n❌ Error: Lockfile not found at ${lockfilePath}`));
|
|
47
|
+
output.error("Run 'ucd store init' to create a new store.");
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const lockfileVersions = Object.keys(lockfile.versions);
|
|
52
|
+
const client = await createUCDClient(baseUrl || UCDJS_API_BASE_URL);
|
|
53
|
+
const configResult = await client.config.get();
|
|
54
|
+
let availableVersions = [];
|
|
55
|
+
if (configResult.error || !configResult.data) {
|
|
56
|
+
const apiResult = await client.versions.list();
|
|
57
|
+
if (apiResult.error) {
|
|
58
|
+
output.error(red(`\n❌ Error fetching versions: ${apiResult.error.message}`));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!apiResult.data) {
|
|
62
|
+
output.error(red(`\n❌ Error: No versions data returned from API.`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
availableVersions = apiResult.data.map(({ version }) => version);
|
|
66
|
+
} else {
|
|
67
|
+
availableVersions = configResult.data.versions ?? [];
|
|
68
|
+
if (availableVersions.length === 0) {
|
|
69
|
+
const apiResult = await client.versions.list();
|
|
70
|
+
if (apiResult.error) {
|
|
71
|
+
output.error(red(`\n❌ Error fetching versions: ${apiResult.error.message}`));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!apiResult.data) {
|
|
75
|
+
output.error(red(`\n❌ Error: No versions data returned from API.`));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
availableVersions = apiResult.data.map(({ version }) => version);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const availableVersionsSet = new Set(availableVersions);
|
|
82
|
+
const lockfileVersionsSet = new Set(lockfileVersions);
|
|
83
|
+
const missingVersions = lockfileVersions.filter((v) => !availableVersionsSet.has(v));
|
|
84
|
+
const extraVersions = availableVersions.filter((v) => !lockfileVersionsSet.has(v));
|
|
85
|
+
const validVersions = lockfileVersions.filter((v) => availableVersionsSet.has(v));
|
|
86
|
+
const isValid = missingVersions.length === 0;
|
|
87
|
+
if (json) {
|
|
88
|
+
output.json({
|
|
89
|
+
valid: isValid,
|
|
90
|
+
lockfileVersions,
|
|
91
|
+
availableVersions,
|
|
92
|
+
missingVersions,
|
|
93
|
+
extraVersions,
|
|
94
|
+
validVersions
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (isValid) {
|
|
99
|
+
output.log(green("\n✓ Store verification passed\n"));
|
|
100
|
+
output.log(`All ${lockfileVersions.length} version(s) in lockfile are available in API.`);
|
|
101
|
+
} else {
|
|
102
|
+
output.error(red("\n❌ Store verification failed\n"));
|
|
103
|
+
output.error(`Found ${missingVersions.length} version(s) in lockfile that are not available in API:`);
|
|
104
|
+
for (const version of missingVersions) output.error(` - ${version}`);
|
|
105
|
+
}
|
|
106
|
+
if (extraVersions.length > 0) {
|
|
107
|
+
output.log(yellow(`\n⚠ Note: ${extraVersions.length} version(s) available in API but not in lockfile:`));
|
|
108
|
+
for (const version of extraVersions) output.log(` + ${version}`);
|
|
109
|
+
output.log("Run 'ucd store sync' to update the lockfile.");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
export { runVerifyStore };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ucdjs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Lucas Nørgård",
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"bugs": {
|
|
18
18
|
"url": "https://github.com/ucdjs/ucd/issues"
|
|
19
19
|
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./dist/cli.mjs",
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"types": "./dist/cli.d.mts",
|
|
20
25
|
"bin": {
|
|
21
26
|
"ucd": "bin/ucd.js"
|
|
22
27
|
},
|
|
@@ -24,32 +29,43 @@
|
|
|
24
29
|
"bin",
|
|
25
30
|
"dist"
|
|
26
31
|
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=22.18"
|
|
34
|
+
},
|
|
27
35
|
"dependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@luxass/utils": "
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"@ucdjs/
|
|
36
|
+
"@clack/prompts": "1.0.0",
|
|
37
|
+
"@luxass/utils": "2.7.3",
|
|
38
|
+
"@unicode-utils/core": "0.12.0-beta.19",
|
|
39
|
+
"farver": "0.4.2",
|
|
40
|
+
"yargs-parser": "22.0.0",
|
|
41
|
+
"@ucdjs-internal/shared": "0.1.1-beta.1",
|
|
42
|
+
"@ucdjs/client": "0.1.1-beta.1",
|
|
43
|
+
"@ucdjs/schema-gen": "0.2.3-beta.1",
|
|
44
|
+
"@ucdjs/env": "0.1.1-beta.1",
|
|
45
|
+
"@ucdjs/lockfile": "0.1.1-beta.1",
|
|
46
|
+
"@ucdjs/fs-bridge": "0.1.1-beta.1",
|
|
47
|
+
"@ucdjs/ucd-store": "1.0.1-beta.1",
|
|
48
|
+
"@ucdjs/schemas": "0.1.1-beta.1"
|
|
35
49
|
},
|
|
36
50
|
"devDependencies": {
|
|
37
|
-
"@luxass/eslint-config": "
|
|
38
|
-
"@types/
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
51
|
+
"@luxass/eslint-config": "7.2.0",
|
|
52
|
+
"@types/yargs-parser": "21.0.3",
|
|
53
|
+
"eslint": "10.0.0",
|
|
54
|
+
"publint": "0.3.17",
|
|
55
|
+
"tsdown": "0.20.3",
|
|
56
|
+
"typescript": "5.9.3",
|
|
57
|
+
"vitest-testdirs": "4.4.2",
|
|
58
|
+
"@ucdjs-tooling/tsdown-config": "1.0.0",
|
|
59
|
+
"@ucdjs-tooling/tsconfig": "1.0.0"
|
|
45
60
|
},
|
|
46
61
|
"publishConfig": {
|
|
47
62
|
"access": "public"
|
|
48
63
|
},
|
|
49
64
|
"scripts": {
|
|
50
|
-
"build": "tsdown",
|
|
65
|
+
"build": "tsdown --tsconfig=./tsconfig.build.json",
|
|
66
|
+
"dev": "tsdown --watch",
|
|
51
67
|
"clean": "git clean -xdf dist node_modules",
|
|
52
68
|
"lint": "eslint .",
|
|
53
|
-
"typecheck": "tsc --noEmit"
|
|
69
|
+
"typecheck": "tsc --noEmit -p tsconfig.build.json"
|
|
54
70
|
}
|
|
55
71
|
}
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import process from "node:process";
|
|
2
|
-
import { bgGreen, black, bold, dim, green } from "farver/fast";
|
|
3
|
-
import yargs from "yargs-parser";
|
|
4
|
-
|
|
5
|
-
//#region package.json
|
|
6
|
-
var name = "@ucdjs/cli";
|
|
7
|
-
var version = "0.2.2";
|
|
8
|
-
var type = "module";
|
|
9
|
-
var author = {
|
|
10
|
-
"name": "Lucas Nørgård",
|
|
11
|
-
"email": "lucasnrgaard@gmail.com",
|
|
12
|
-
"url": "https://luxass.dev"
|
|
13
|
-
};
|
|
14
|
-
var packageManager = "pnpm@10.11.0";
|
|
15
|
-
var license = "MIT";
|
|
16
|
-
var homepage = "https://github.com/ucdjs/ucd";
|
|
17
|
-
var repository = {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/ucdjs/ucd.git",
|
|
20
|
-
"directory": "packages/cli"
|
|
21
|
-
};
|
|
22
|
-
var bugs = { "url": "https://github.com/ucdjs/ucd/issues" };
|
|
23
|
-
var bin = { "ucd": "bin/ucd.js" };
|
|
24
|
-
var files = ["bin", "dist"];
|
|
25
|
-
var scripts = {
|
|
26
|
-
"build": "tsdown",
|
|
27
|
-
"clean": "git clean -xdf dist node_modules",
|
|
28
|
-
"lint": "eslint .",
|
|
29
|
-
"typecheck": "tsc --noEmit"
|
|
30
|
-
};
|
|
31
|
-
var dependencies = {
|
|
32
|
-
"@luxass/unicode-utils": "catalog:prod",
|
|
33
|
-
"@luxass/utils": "catalog:prod",
|
|
34
|
-
"@ucdjs/schema-gen": "workspace:*",
|
|
35
|
-
"farver": "catalog:prod",
|
|
36
|
-
"micromatch": "catalog:prod",
|
|
37
|
-
"p-limit": "catalog:prod",
|
|
38
|
-
"yargs-parser": "catalog:prod"
|
|
39
|
-
};
|
|
40
|
-
var devDependencies = {
|
|
41
|
-
"@luxass/eslint-config": "catalog:dev",
|
|
42
|
-
"@types/micromatch": "catalog:dev",
|
|
43
|
-
"@types/yargs-parser": "catalog:dev",
|
|
44
|
-
"eslint": "catalog:dev",
|
|
45
|
-
"publint": "catalog:dev",
|
|
46
|
-
"tsdown": "catalog:dev",
|
|
47
|
-
"typescript": "catalog:dev",
|
|
48
|
-
"vitest-testdirs": "catalog:dev"
|
|
49
|
-
};
|
|
50
|
-
var publishConfig = { "access": "public" };
|
|
51
|
-
var package_default = {
|
|
52
|
-
name,
|
|
53
|
-
version,
|
|
54
|
-
type,
|
|
55
|
-
author,
|
|
56
|
-
packageManager,
|
|
57
|
-
license,
|
|
58
|
-
homepage,
|
|
59
|
-
repository,
|
|
60
|
-
bugs,
|
|
61
|
-
bin,
|
|
62
|
-
files,
|
|
63
|
-
scripts,
|
|
64
|
-
dependencies,
|
|
65
|
-
devDependencies,
|
|
66
|
-
publishConfig
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
//#endregion
|
|
70
|
-
//#region src/cli-utils.ts
|
|
71
|
-
const SUPPORTED_COMMANDS = new Set(["codegen", "download"]);
|
|
72
|
-
/**
|
|
73
|
-
* Resolves the CLI command based on the provided arguments.
|
|
74
|
-
*
|
|
75
|
-
* If the `version` flag is present, it returns the "version" command.
|
|
76
|
-
* Otherwise, it checks if the third argument in the positional arguments (`flags._[2]`)
|
|
77
|
-
* is a supported command. If it is, it returns that command.
|
|
78
|
-
* If no supported command is found, it defaults to the "help" command.
|
|
79
|
-
*
|
|
80
|
-
* @param {Arguments} flags - The parsed arguments from the command line.
|
|
81
|
-
* @returns {CLICommand} The resolved CLI command.
|
|
82
|
-
*/
|
|
83
|
-
function resolveCommand(flags) {
|
|
84
|
-
if (flags.version) return "version";
|
|
85
|
-
const cmd = flags._[2];
|
|
86
|
-
if (SUPPORTED_COMMANDS.has(cmd)) return cmd;
|
|
87
|
-
return "help";
|
|
88
|
-
}
|
|
89
|
-
function printHelp({ commandName, headline, usage, tables, description }) {
|
|
90
|
-
const terminalWidth = process.stdout.columns || 80;
|
|
91
|
-
const isTinyTerminal = terminalWidth < 60;
|
|
92
|
-
const indent = " ";
|
|
93
|
-
const linebreak = () => "";
|
|
94
|
-
const table = (rows, { padding }) => {
|
|
95
|
-
let raw = "";
|
|
96
|
-
for (const [command, help] of rows) if (isTinyTerminal) raw += `${indent}${indent}${bold(command)}\n${indent}${indent}${indent}${dim(help)}\n`;
|
|
97
|
-
else {
|
|
98
|
-
const paddedCommand = command.padEnd(padding);
|
|
99
|
-
raw += `${indent}${indent}${bold(paddedCommand)} ${dim(help)}\n`;
|
|
100
|
-
}
|
|
101
|
-
return raw.slice(0, -1);
|
|
102
|
-
};
|
|
103
|
-
const message = [];
|
|
104
|
-
if (headline) message.push(`\n${indent}${bgGreen(black(` ${commandName} `))} ${green(`v${package_default.version ?? "0.0.0"}`)}`, `${indent}${dim(headline)}`);
|
|
105
|
-
if (usage) message.push(linebreak(), `${indent}${bold("USAGE")}`, `${indent}${indent}${green(commandName)} ${usage}`);
|
|
106
|
-
if (description) message.push(linebreak(), `${indent}${bold("DESCRIPTION")}`, `${indent}${indent}${description}`);
|
|
107
|
-
if (tables) {
|
|
108
|
-
function calculateTablePadding(rows) {
|
|
109
|
-
const maxLength = rows.reduce((val, [first]) => Math.max(val, first.length), 0);
|
|
110
|
-
return Math.min(maxLength, 30) + 2;
|
|
111
|
-
}
|
|
112
|
-
const tableEntries = Object.entries(tables);
|
|
113
|
-
for (const [tableTitle, tableRows] of tableEntries) {
|
|
114
|
-
const padding = calculateTablePadding(tableRows);
|
|
115
|
-
message.push(linebreak(), `${indent}${bold(tableTitle.toUpperCase())}`, table(tableRows, { padding }));
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
message.push(linebreak(), `${indent}${dim(`Run with --help for more information on specific commands.`)}`);
|
|
119
|
-
console.log(`${message.join("\n")}\n`);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Runs a command based on the provided CLI command and flags.
|
|
123
|
-
*
|
|
124
|
-
* @param {CLICommand} cmd - The CLI command to execute.
|
|
125
|
-
* @param {Arguments} flags - The flags passed to the command.
|
|
126
|
-
* @returns {Promise<void>} A promise that resolves when the command has finished executing.
|
|
127
|
-
* @throws An error if the command is not found.
|
|
128
|
-
*/
|
|
129
|
-
async function runCommand(cmd, flags) {
|
|
130
|
-
switch (cmd) {
|
|
131
|
-
case "help":
|
|
132
|
-
printHelp({
|
|
133
|
-
commandName: "ucd",
|
|
134
|
-
headline: "A CLI for working with the Unicode Character Database (UCD).",
|
|
135
|
-
usage: "[command] [...flags]",
|
|
136
|
-
tables: {
|
|
137
|
-
"Commands": [["download", "Download Unicode data files."], ["codegen", "Generate TypeScript code from UCD data."]],
|
|
138
|
-
"Global Flags": [
|
|
139
|
-
["--force", "Force the operation to run, even if it's not needed."],
|
|
140
|
-
["--version", "Show the version number and exit."],
|
|
141
|
-
["--help", "Show this help message."]
|
|
142
|
-
]
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
break;
|
|
146
|
-
case "version":
|
|
147
|
-
console.log(` ${bgGreen(black(` ucd `))} ${green(`v${package_default.version ?? "x.y.z"}`)}`);
|
|
148
|
-
break;
|
|
149
|
-
case "codegen": {
|
|
150
|
-
const { runCodegenRoot } = await import("./root-oHWSp_5G.js");
|
|
151
|
-
const subcommand = flags._[3]?.toString() ?? "";
|
|
152
|
-
await runCodegenRoot(subcommand, { flags });
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
case "download": {
|
|
156
|
-
const { runDownload } = await import("./download-CCx2vdOj.js");
|
|
157
|
-
const versions = flags._.slice(3);
|
|
158
|
-
await runDownload({
|
|
159
|
-
versions,
|
|
160
|
-
flags
|
|
161
|
-
});
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
default: throw new Error(`Error running ${cmd} -- no command found.`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
function parseFlags(args) {
|
|
168
|
-
return yargs(args, {
|
|
169
|
-
configuration: { "parse-positional-numbers": false },
|
|
170
|
-
default: { force: false },
|
|
171
|
-
boolean: [
|
|
172
|
-
"force",
|
|
173
|
-
"help",
|
|
174
|
-
"h"
|
|
175
|
-
],
|
|
176
|
-
string: [
|
|
177
|
-
"output-dir",
|
|
178
|
-
"input-dir",
|
|
179
|
-
"output-file"
|
|
180
|
-
]
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
async function runCLI(args) {
|
|
184
|
-
try {
|
|
185
|
-
const flags = parseFlags(args);
|
|
186
|
-
const cmd = resolveCommand(flags);
|
|
187
|
-
await runCommand(cmd, flags);
|
|
188
|
-
} catch (err) {
|
|
189
|
-
console.error(err);
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
//#endregion
|
|
195
|
-
export { printHelp, runCLI };
|