@ucdjs/cli 0.2.2 → 0.3.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/dist/_shared-DlzCE5mE.js +59 -0
- package/dist/analyze-C7RthxQg.js +78 -0
- package/dist/clean-Dm8LIgdA.js +23 -0
- package/dist/{cli-utils-DY82m2wz.js → cli-utils-dAbyq59_.js} +16 -82
- package/dist/cli.js +4 -3
- package/dist/{fields-Cz0PV1Co.js → fields-CbRX6M6H.js} +3 -4
- package/dist/init-D0yQAcdC.js +75 -0
- package/dist/repair-DHtSzSYe.js +19 -0
- package/dist/root-D1JJ1qhM.js +63 -0
- package/dist/{root-oHWSp_5G.js → root-jW0s7hem.js} +3 -4
- package/package.json +29 -17
- package/dist/download-CCx2vdOj.js +0 -203
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createHTTPUCDStore, createNodeUCDStore } from "@ucdjs/ucd-store";
|
|
2
|
+
import { isCancel, multiselect } from "@clack/prompts";
|
|
3
|
+
import { UNICODE_VERSION_METADATA } from "@unicode-utils/core";
|
|
4
|
+
|
|
5
|
+
//#region src/cmd/store/_shared.ts
|
|
6
|
+
const SHARED_FLAGS = [
|
|
7
|
+
["--remote", "Use a Remote UCD Store."],
|
|
8
|
+
["--store-dir", "Directory where the UCD files are stored."],
|
|
9
|
+
["--include", "Patterns to include files in the store."],
|
|
10
|
+
["--exclude", "Patterns to exclude files from the store."],
|
|
11
|
+
["--base-url", "Base URL for the UCD Store."]
|
|
12
|
+
];
|
|
13
|
+
function assertRemoteOrStoreDir(flags) {
|
|
14
|
+
if (!flags.remote && !flags.storeDir) throw new Error("Either --remote or --store-dir must be specified.");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates a UCD store instance based on the provided CLI flags.
|
|
18
|
+
*
|
|
19
|
+
* @param {CLIStoreCmdSharedFlags} flags - Configuration flags for creating the store
|
|
20
|
+
* @returns {Promise<UCDStore | null>} A promise that resolves to a UCDStore instance or null
|
|
21
|
+
* @throws {Error} When store directory is not specified for local stores
|
|
22
|
+
*/
|
|
23
|
+
async function createStoreFromFlags(flags) {
|
|
24
|
+
const { storeDir, remote, baseUrl, include, exclude } = flags;
|
|
25
|
+
if (remote) return createHTTPUCDStore({
|
|
26
|
+
baseUrl,
|
|
27
|
+
globalFilters: {
|
|
28
|
+
include,
|
|
29
|
+
exclude
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (!storeDir) throw new Error("Store directory must be specified when not using remote store.");
|
|
33
|
+
return createNodeUCDStore({
|
|
34
|
+
basePath: storeDir,
|
|
35
|
+
baseUrl,
|
|
36
|
+
globalFilters: {
|
|
37
|
+
include,
|
|
38
|
+
exclude
|
|
39
|
+
},
|
|
40
|
+
versions: flags.versions || []
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async function runVersionPrompt({ input, output } = {}) {
|
|
44
|
+
const selectedVersions = await multiselect({
|
|
45
|
+
options: UNICODE_VERSION_METADATA.map(({ version }) => ({
|
|
46
|
+
value: version,
|
|
47
|
+
label: version
|
|
48
|
+
})),
|
|
49
|
+
message: "Select Unicode versions to initialize the store with:",
|
|
50
|
+
required: true,
|
|
51
|
+
input,
|
|
52
|
+
output
|
|
53
|
+
});
|
|
54
|
+
if (isCancel(selectedVersions)) return [];
|
|
55
|
+
return selectedVersions;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { runVersionPrompt as i, assertRemoteOrStoreDir as n, createStoreFromFlags as r, SHARED_FLAGS as t };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
|
+
import { n as assertRemoteOrStoreDir, r as createStoreFromFlags, t as SHARED_FLAGS } from "./_shared-DlzCE5mE.js";
|
|
3
|
+
import { green, red } from "farver/fast";
|
|
4
|
+
import { UCDStoreUnsupportedFeature } from "@ucdjs/ucd-store";
|
|
5
|
+
|
|
6
|
+
//#region src/cmd/store/analyze.ts
|
|
7
|
+
async function runAnalyzeStore({ flags, versions }) {
|
|
8
|
+
if (flags?.help || flags?.h) {
|
|
9
|
+
printHelp({
|
|
10
|
+
headline: "Analyze UCD Store",
|
|
11
|
+
commandName: "ucd store analyze",
|
|
12
|
+
usage: "[...versions] [...flags]",
|
|
13
|
+
tables: { Flags: [
|
|
14
|
+
...SHARED_FLAGS,
|
|
15
|
+
["--check-orphaned", "Check for orphaned files in the store."],
|
|
16
|
+
["--json", "Output analyze information in JSON format."],
|
|
17
|
+
["--help (-h)", "See all available flags."]
|
|
18
|
+
] }
|
|
19
|
+
});
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (!versions || versions.length === 0) console.info("No specific versions provided. Analyzing all versions in the store.");
|
|
23
|
+
const { storeDir, json, remote, baseUrl, include: patterns, checkOrphaned } = flags;
|
|
24
|
+
try {
|
|
25
|
+
assertRemoteOrStoreDir(flags);
|
|
26
|
+
const store = await createStoreFromFlags({
|
|
27
|
+
baseUrl,
|
|
28
|
+
storeDir,
|
|
29
|
+
remote,
|
|
30
|
+
include: patterns
|
|
31
|
+
});
|
|
32
|
+
if (store == null) {
|
|
33
|
+
console.error("Error: Failed to create UCD store.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const [analyzeData, analyzeError] = await store.analyze({
|
|
37
|
+
checkOrphaned: !!checkOrphaned,
|
|
38
|
+
versions: versions || []
|
|
39
|
+
});
|
|
40
|
+
if (analyzeError != null) {
|
|
41
|
+
console.error(red(`\n❌ Error analyzing store:`));
|
|
42
|
+
console.error(` ${analyzeError.message}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (json) {
|
|
46
|
+
console.info(JSON.stringify(analyzeData, null, 2));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
for (const { version, fileCount, isComplete, missingFiles, orphanedFiles, expectedFileCount } of analyzeData) {
|
|
50
|
+
console.info(`Version: ${version}`);
|
|
51
|
+
if (isComplete) console.info(` Status: ${green("complete")}`);
|
|
52
|
+
else console.warn(` Status: ${red("incomplete")}`);
|
|
53
|
+
console.info(` Files: ${fileCount}`);
|
|
54
|
+
if (missingFiles && missingFiles.length > 0) console.warn(` Missing files: ${missingFiles.length}`);
|
|
55
|
+
if (orphanedFiles && orphanedFiles.length > 0) console.warn(` Orphaned files: ${orphanedFiles.length}`);
|
|
56
|
+
if (expectedFileCount) console.info(` Total files expected: ${expectedFileCount}`);
|
|
57
|
+
}
|
|
58
|
+
} catch (err) {
|
|
59
|
+
if (err instanceof UCDStoreUnsupportedFeature) {
|
|
60
|
+
console.error(red(`\n❌ Error: Unsupported feature:`));
|
|
61
|
+
console.error(` ${err.message}`);
|
|
62
|
+
console.error("");
|
|
63
|
+
console.error("This store does not support the analyze operation.");
|
|
64
|
+
console.error("Please check the store capabilities or use a different store type.");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let message = "Unknown error";
|
|
68
|
+
if (err instanceof Error) message = err.message;
|
|
69
|
+
else if (typeof err === "string") message = err;
|
|
70
|
+
console.error(red(`\n❌ Error analyzing store:`));
|
|
71
|
+
console.error(` ${message}`);
|
|
72
|
+
console.error("Please check the store configuration and try again.");
|
|
73
|
+
console.error("If you believe this is a bug, please report it at https://github.com/ucdjs/ucd/issues");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
export { runAnalyzeStore };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
|
+
import { t as SHARED_FLAGS } from "./_shared-DlzCE5mE.js";
|
|
3
|
+
|
|
4
|
+
//#region src/cmd/store/clean.ts
|
|
5
|
+
async function runCleanStore({ flags }) {
|
|
6
|
+
if (flags?.help || flags?.h) {
|
|
7
|
+
printHelp({
|
|
8
|
+
headline: "Clean an UCD Store",
|
|
9
|
+
commandName: "ucd store clean",
|
|
10
|
+
usage: "[...flags]",
|
|
11
|
+
tables: { Flags: [
|
|
12
|
+
...SHARED_FLAGS,
|
|
13
|
+
["--dry-run", "Show what would be deleted without actually deleting."],
|
|
14
|
+
["--help (-h)", "See all available flags."]
|
|
15
|
+
] }
|
|
16
|
+
});
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { storeDir, dryRun, remote, baseUrl, include: patterns } = flags;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { runCleanStore };
|
|
@@ -3,72 +3,11 @@ import { bgGreen, black, bold, dim, green } from "farver/fast";
|
|
|
3
3
|
import yargs from "yargs-parser";
|
|
4
4
|
|
|
5
5
|
//#region package.json
|
|
6
|
-
var
|
|
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
|
-
};
|
|
6
|
+
var version = "0.3.0";
|
|
68
7
|
|
|
69
8
|
//#endregion
|
|
70
9
|
//#region src/cli-utils.ts
|
|
71
|
-
const SUPPORTED_COMMANDS = new Set(["codegen", "
|
|
10
|
+
const SUPPORTED_COMMANDS = new Set(["codegen", "store"]);
|
|
72
11
|
/**
|
|
73
12
|
* Resolves the CLI command based on the provided arguments.
|
|
74
13
|
*
|
|
@@ -82,13 +21,12 @@ const SUPPORTED_COMMANDS = new Set(["codegen", "download"]);
|
|
|
82
21
|
*/
|
|
83
22
|
function resolveCommand(flags) {
|
|
84
23
|
if (flags.version) return "version";
|
|
85
|
-
const cmd = flags._[
|
|
24
|
+
const cmd = flags._[0];
|
|
86
25
|
if (SUPPORTED_COMMANDS.has(cmd)) return cmd;
|
|
87
26
|
return "help";
|
|
88
27
|
}
|
|
89
28
|
function printHelp({ commandName, headline, usage, tables, description }) {
|
|
90
|
-
const
|
|
91
|
-
const isTinyTerminal = terminalWidth < 60;
|
|
29
|
+
const isTinyTerminal = (process.stdout.columns || 80) < 60;
|
|
92
30
|
const indent = " ";
|
|
93
31
|
const linebreak = () => "";
|
|
94
32
|
const table = (rows, { padding }) => {
|
|
@@ -101,7 +39,7 @@ function printHelp({ commandName, headline, usage, tables, description }) {
|
|
|
101
39
|
return raw.slice(0, -1);
|
|
102
40
|
};
|
|
103
41
|
const message = [];
|
|
104
|
-
if (headline) message.push(`\n${indent}${bgGreen(black(` ${commandName} `))} ${green(`v${
|
|
42
|
+
if (headline) message.push(`\n${indent}${bgGreen(black(` ${commandName} `))} ${green(`v${version ?? "0.0.0"}`)}`, `${indent}${dim(headline)}`);
|
|
105
43
|
if (usage) message.push(linebreak(), `${indent}${bold("USAGE")}`, `${indent}${indent}${green(commandName)} ${usage}`);
|
|
106
44
|
if (description) message.push(linebreak(), `${indent}${bold("DESCRIPTION")}`, `${indent}${indent}${description}`);
|
|
107
45
|
if (tables) {
|
|
@@ -144,21 +82,16 @@ async function runCommand(cmd, flags) {
|
|
|
144
82
|
});
|
|
145
83
|
break;
|
|
146
84
|
case "version":
|
|
147
|
-
console.log(` ${bgGreen(black(` ucd `))} ${green(`v${
|
|
85
|
+
console.log(` ${bgGreen(black(` ucd `))} ${green(`v${version ?? "x.y.z"}`)}`);
|
|
148
86
|
break;
|
|
149
87
|
case "codegen": {
|
|
150
|
-
const { runCodegenRoot } = await import("./root-
|
|
151
|
-
|
|
152
|
-
await runCodegenRoot(subcommand, { flags });
|
|
88
|
+
const { runCodegenRoot } = await import("./root-jW0s7hem.js");
|
|
89
|
+
await runCodegenRoot(flags._[1]?.toString() ?? "", { flags });
|
|
153
90
|
break;
|
|
154
91
|
}
|
|
155
|
-
case "
|
|
156
|
-
const {
|
|
157
|
-
|
|
158
|
-
await runDownload({
|
|
159
|
-
versions,
|
|
160
|
-
flags
|
|
161
|
-
});
|
|
92
|
+
case "store": {
|
|
93
|
+
const { runStoreRoot } = await import("./root-D1JJ1qhM.js");
|
|
94
|
+
await runStoreRoot(flags._[1]?.toString() ?? "", { flags });
|
|
162
95
|
break;
|
|
163
96
|
}
|
|
164
97
|
default: throw new Error(`Error running ${cmd} -- no command found.`);
|
|
@@ -171,7 +104,8 @@ function parseFlags(args) {
|
|
|
171
104
|
boolean: [
|
|
172
105
|
"force",
|
|
173
106
|
"help",
|
|
174
|
-
"h"
|
|
107
|
+
"h",
|
|
108
|
+
"dry-run"
|
|
175
109
|
],
|
|
176
110
|
string: [
|
|
177
111
|
"output-dir",
|
|
@@ -183,8 +117,8 @@ function parseFlags(args) {
|
|
|
183
117
|
async function runCLI(args) {
|
|
184
118
|
try {
|
|
185
119
|
const flags = parseFlags(args);
|
|
186
|
-
|
|
187
|
-
await runCommand(
|
|
120
|
+
process.title = "ucd-cli";
|
|
121
|
+
await runCommand(resolveCommand(flags), flags);
|
|
188
122
|
} catch (err) {
|
|
189
123
|
console.error(err);
|
|
190
124
|
process.exit(1);
|
|
@@ -192,4 +126,4 @@ async function runCLI(args) {
|
|
|
192
126
|
}
|
|
193
127
|
|
|
194
128
|
//#endregion
|
|
195
|
-
export {
|
|
129
|
+
export { runCLI as n, printHelp as t };
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { runCLI } from "./cli-utils-
|
|
1
|
+
import { n as runCLI } from "./cli-utils-dAbyq59_.js";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
|
|
4
4
|
//#region src/cli.ts
|
|
5
|
-
runCLI(process.argv);
|
|
5
|
+
runCLI(process.argv.slice(2));
|
|
6
6
|
|
|
7
|
-
//#endregion
|
|
7
|
+
//#endregion
|
|
8
|
+
export { };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { printHelp } from "./cli-utils-
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { mkdir, readdir, stat, writeFile } from "node:fs/promises";
|
|
@@ -16,8 +16,7 @@ async function scanFiles(inputPath) {
|
|
|
16
16
|
const isDirectory = (await stat(resolvedInputPath)).isDirectory();
|
|
17
17
|
const filesWithVersion = [];
|
|
18
18
|
if (!isDirectory) {
|
|
19
|
-
const
|
|
20
|
-
const versionMatch = parentDir.match(/v(\d+\.\d+\.\d+)/);
|
|
19
|
+
const versionMatch = path.dirname(resolvedInputPath).match(/v(\d+\.\d+\.\d+)/);
|
|
21
20
|
const version = versionMatch ? flattenVersion(versionMatch[1]) : "unknown";
|
|
22
21
|
filesWithVersion.push({
|
|
23
22
|
filePath: resolvedInputPath,
|
|
@@ -108,7 +107,7 @@ async function runFieldCodegen({ inputPath, flags }) {
|
|
|
108
107
|
console.log(`Generated fields for ${results.length} files in ${outputDir}`);
|
|
109
108
|
return;
|
|
110
109
|
}
|
|
111
|
-
const resultsByVersion = new Map();
|
|
110
|
+
const resultsByVersion = /* @__PURE__ */ new Map();
|
|
112
111
|
for (const result of results) {
|
|
113
112
|
const versionResults = resultsByVersion.get(result.version) ?? [];
|
|
114
113
|
versionResults.push(result);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
|
+
import { i as runVersionPrompt, n as assertRemoteOrStoreDir, r as createStoreFromFlags, t as SHARED_FLAGS } from "./_shared-DlzCE5mE.js";
|
|
3
|
+
import { red } from "farver/fast";
|
|
4
|
+
import { UCDStoreUnsupportedFeature } from "@ucdjs/ucd-store";
|
|
5
|
+
|
|
6
|
+
//#region src/cmd/store/init.ts
|
|
7
|
+
async function runInitStore({ flags, versions }) {
|
|
8
|
+
if (flags?.help || flags?.h) {
|
|
9
|
+
printHelp({
|
|
10
|
+
headline: "Initialize an UCD Store",
|
|
11
|
+
commandName: "ucd store init",
|
|
12
|
+
usage: "[...versions] [...flags]",
|
|
13
|
+
tables: { Flags: [
|
|
14
|
+
...SHARED_FLAGS,
|
|
15
|
+
["--force", "Overwrite existing files if they already exist."],
|
|
16
|
+
["--help (-h)", "See all available flags."]
|
|
17
|
+
] }
|
|
18
|
+
});
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const { storeDir, force, remote, baseUrl, include: patterns, dryRun } = flags;
|
|
22
|
+
try {
|
|
23
|
+
assertRemoteOrStoreDir(flags);
|
|
24
|
+
let selectedVersions = versions;
|
|
25
|
+
if (!selectedVersions || selectedVersions.length === 0) {
|
|
26
|
+
const pickedVersions = await runVersionPrompt();
|
|
27
|
+
if (pickedVersions.length === 0) {
|
|
28
|
+
console.error("No versions selected. Operation cancelled.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
selectedVersions = pickedVersions;
|
|
32
|
+
}
|
|
33
|
+
const store = await createStoreFromFlags({
|
|
34
|
+
baseUrl,
|
|
35
|
+
storeDir,
|
|
36
|
+
remote,
|
|
37
|
+
include: patterns,
|
|
38
|
+
versions: selectedVersions
|
|
39
|
+
});
|
|
40
|
+
await store.init({
|
|
41
|
+
force,
|
|
42
|
+
dryRun
|
|
43
|
+
});
|
|
44
|
+
if (!store.initialized) {
|
|
45
|
+
console.error(red(`\n❌ Error: Store initialization failed.`));
|
|
46
|
+
console.error("Please check the store configuration and try again.");
|
|
47
|
+
console.error("This output may help you debug the issue:");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (dryRun) {
|
|
51
|
+
console.info("Store initialized successfully in dry-run mode.");
|
|
52
|
+
console.info("No files have been written to disk.");
|
|
53
|
+
} else console.info("Store initialized successfully.");
|
|
54
|
+
} catch (err) {
|
|
55
|
+
if (err instanceof UCDStoreUnsupportedFeature) {
|
|
56
|
+
console.error(red(`\n❌ Error: Unsupported feature:`));
|
|
57
|
+
console.error(` ${err.message}`);
|
|
58
|
+
console.error("");
|
|
59
|
+
console.error("This store does not support the init operation.");
|
|
60
|
+
console.error("Please check the store capabilities or use a different store type.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
let message = "Unknown error";
|
|
64
|
+
if (err instanceof Error) message = err.message;
|
|
65
|
+
else if (typeof err === "string") message = err;
|
|
66
|
+
console.error(red(`\n❌ Error initializing store:`));
|
|
67
|
+
console.error(` ${message}`);
|
|
68
|
+
console.error("Please check the store configuration and try again.");
|
|
69
|
+
console.error("If the issue persists, consider running with --dry-run to see more details.");
|
|
70
|
+
console.error("If you believe this is a bug, please report it at https://github.com/ucdjs/ucd/issues");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { runInitStore };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
|
+
import { t as SHARED_FLAGS } from "./_shared-DlzCE5mE.js";
|
|
3
|
+
|
|
4
|
+
//#region src/cmd/store/repair.ts
|
|
5
|
+
async function runRepairStore({ flags }) {
|
|
6
|
+
if (flags?.help || flags?.h) {
|
|
7
|
+
printHelp({
|
|
8
|
+
headline: "Repair an UCD Store",
|
|
9
|
+
commandName: "ucd store repair",
|
|
10
|
+
usage: "[versions...] [...flags]",
|
|
11
|
+
tables: { Flags: [...SHARED_FLAGS, ["--help (-h)", "See all available flags."]] }
|
|
12
|
+
});
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const { storeDir, dryRun: _dryRun, force: _force, remote, baseUrl, include: patterns } = flags;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { runRepairStore };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
|
+
|
|
3
|
+
//#region src/cmd/store/root.ts
|
|
4
|
+
const CODEGEN_SUBCOMMANDS = [
|
|
5
|
+
"init",
|
|
6
|
+
"repair",
|
|
7
|
+
"clean",
|
|
8
|
+
"analyze"
|
|
9
|
+
];
|
|
10
|
+
function isValidSubcommand(subcommand) {
|
|
11
|
+
return CODEGEN_SUBCOMMANDS.includes(subcommand);
|
|
12
|
+
}
|
|
13
|
+
async function runStoreRoot(subcommand, { flags }) {
|
|
14
|
+
if (!isValidSubcommand(subcommand) || !isValidSubcommand(subcommand) && (flags?.help || flags?.h)) {
|
|
15
|
+
printHelp({
|
|
16
|
+
commandName: "ucd store",
|
|
17
|
+
usage: "[command] [...flags]",
|
|
18
|
+
tables: {
|
|
19
|
+
Commands: [
|
|
20
|
+
["init", "Initialize an UCD Store."],
|
|
21
|
+
["repair", "Repair an UCD Store."],
|
|
22
|
+
["clean", "Clean an UCD Store."],
|
|
23
|
+
["status", "Show the status of an UCD Store."]
|
|
24
|
+
],
|
|
25
|
+
Flags: [["--help (-h)", "See all available flags."]]
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (subcommand === "init") {
|
|
31
|
+
const { runInitStore } = await import("./init-D0yQAcdC.js");
|
|
32
|
+
await runInitStore({
|
|
33
|
+
versions: flags._.slice(2),
|
|
34
|
+
flags
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (subcommand === "clean") {
|
|
39
|
+
const { runCleanStore } = await import("./clean-Dm8LIgdA.js");
|
|
40
|
+
await runCleanStore({ flags });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (subcommand === "repair") {
|
|
44
|
+
const { runRepairStore } = await import("./repair-DHtSzSYe.js");
|
|
45
|
+
await runRepairStore({
|
|
46
|
+
versions: flags._.slice(2),
|
|
47
|
+
flags
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (subcommand === "analyze") {
|
|
52
|
+
const { runAnalyzeStore } = await import("./analyze-C7RthxQg.js");
|
|
53
|
+
await runAnalyzeStore({
|
|
54
|
+
flags,
|
|
55
|
+
versions: flags._.slice(2)
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Invalid subcommand: ${subcommand}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { runStoreRoot };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { printHelp } from "./cli-utils-
|
|
1
|
+
import { t as printHelp } from "./cli-utils-dAbyq59_.js";
|
|
2
2
|
|
|
3
3
|
//#region src/cmd/codegen/root.ts
|
|
4
4
|
const CODEGEN_SUBCOMMANDS = ["fields"];
|
|
@@ -18,10 +18,9 @@ async function runCodegenRoot(subcommand, { flags }) {
|
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
if (subcommand === "fields") {
|
|
21
|
-
const { runFieldCodegen } = await import("./fields-
|
|
22
|
-
const inputPath = flags._.slice(4)?.toString() ?? "";
|
|
21
|
+
const { runFieldCodegen } = await import("./fields-CbRX6M6H.js");
|
|
23
22
|
await runFieldCodegen({
|
|
24
|
-
inputPath,
|
|
23
|
+
inputPath: flags._.slice(4)?.toString() ?? "",
|
|
25
24
|
flags
|
|
26
25
|
});
|
|
27
26
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ucdjs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Lucas Nørgård",
|
|
@@ -17,6 +17,13 @@
|
|
|
17
17
|
"bugs": {
|
|
18
18
|
"url": "https://github.com/ucdjs/ucd/issues"
|
|
19
19
|
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./dist/cli.js",
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/cli.js",
|
|
25
|
+
"module": "./dist/cli.js",
|
|
26
|
+
"types": "./dist/cli.d.ts",
|
|
20
27
|
"bin": {
|
|
21
28
|
"ucd": "bin/ucd.js"
|
|
22
29
|
},
|
|
@@ -24,30 +31,35 @@
|
|
|
24
31
|
"bin",
|
|
25
32
|
"dist"
|
|
26
33
|
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22.18"
|
|
36
|
+
},
|
|
27
37
|
"dependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@luxass/utils": "
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"@ucdjs/
|
|
38
|
+
"@clack/prompts": "1.0.0-alpha.5",
|
|
39
|
+
"@luxass/utils": "2.7.2",
|
|
40
|
+
"@unicode-utils/core": "0.12.0-beta.18",
|
|
41
|
+
"farver": "0.4.2",
|
|
42
|
+
"yargs-parser": "22.0.0",
|
|
43
|
+
"@ucdjs/schema-gen": "0.2.2",
|
|
44
|
+
"@ucdjs/ucd-store": "0.1.0"
|
|
35
45
|
},
|
|
36
46
|
"devDependencies": {
|
|
37
|
-
"@luxass/eslint-config": "
|
|
38
|
-
"@types/
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
47
|
+
"@luxass/eslint-config": "6.0.1",
|
|
48
|
+
"@types/yargs-parser": "21.0.3",
|
|
49
|
+
"eslint": "9.38.0",
|
|
50
|
+
"publint": "0.3.15",
|
|
51
|
+
"tsdown": "0.15.9",
|
|
52
|
+
"typescript": "5.9.3",
|
|
53
|
+
"vitest-testdirs": "4.2.1",
|
|
54
|
+
"@ucdjs-tooling/tsconfig": "1.0.0",
|
|
55
|
+
"@ucdjs-tooling/tsdown-config": "1.0.0"
|
|
45
56
|
},
|
|
46
57
|
"publishConfig": {
|
|
47
58
|
"access": "public"
|
|
48
59
|
},
|
|
49
60
|
"scripts": {
|
|
50
|
-
"build": "tsdown",
|
|
61
|
+
"build": "tsdown --tsconfig=./tsconfig.build.json",
|
|
62
|
+
"dev": "tsdown --watch",
|
|
51
63
|
"clean": "git clean -xdf dist node_modules",
|
|
52
64
|
"lint": "eslint .",
|
|
53
65
|
"typecheck": "tsc --noEmit"
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import { printHelp } from "./cli-utils-DY82m2wz.js";
|
|
2
|
-
import { gray, green, red, yellow } from "farver/fast";
|
|
3
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
-
import path, { dirname } from "node:path";
|
|
5
|
-
import { UNICODE_VERSION_METADATA, hasUCDPath, mapToUCDPathVersion } from "@luxass/unicode-utils";
|
|
6
|
-
import micromatch from "micromatch";
|
|
7
|
-
|
|
8
|
-
//#region src/cmd/download.ts
|
|
9
|
-
const CONCURRENCY_LIMIT = 3;
|
|
10
|
-
const API_URL = "https://unicode-api.luxass.dev/api/v1";
|
|
11
|
-
const UNICODE_PROXY_URL = "https://unicode-proxy.ucdjs.dev";
|
|
12
|
-
async function runDownload({ versions: providedVersions, flags }) {
|
|
13
|
-
if (flags?.help || flags?.h) {
|
|
14
|
-
printHelp({
|
|
15
|
-
headline: "Download Unicode Data Files",
|
|
16
|
-
commandName: "ucd download",
|
|
17
|
-
usage: "<...versions> [...flags]",
|
|
18
|
-
tables: { Flags: [
|
|
19
|
-
["--output-dir", "Specify the output directory."],
|
|
20
|
-
["--exclude", "Exclude files matching glob patterns (e.g., '*Test*,ReadMe.txt,*.draft')."],
|
|
21
|
-
["--exclude-test", "Exclude all test files (ending with Test.txt)."],
|
|
22
|
-
["--exclude-draft", "Exclude all draft files"],
|
|
23
|
-
["--create-comment-files", "Create comment files for each downloaded file."],
|
|
24
|
-
["--force", "Force the download, even if the files already exist."],
|
|
25
|
-
["--debug", "Enable debug output."],
|
|
26
|
-
["--help (-h)", "See all available flags."]
|
|
27
|
-
] }
|
|
28
|
-
});
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
if (providedVersions.length === 0) {
|
|
32
|
-
console.error(red("No versions provided. Please provide at least one version."));
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
let versions = [];
|
|
36
|
-
if (providedVersions[0] === "all") versions = UNICODE_VERSION_METADATA.filter((v) => !flags.excludeDraft || v.status !== "draft").map((v) => {
|
|
37
|
-
const mappedVersion = mapToUCDPathVersion(v.version);
|
|
38
|
-
return {
|
|
39
|
-
version: v.version,
|
|
40
|
-
mappedVersion: mappedVersion === v.version ? void 0 : mappedVersion
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
else versions = providedVersions.map((v) => {
|
|
44
|
-
const mappedVersion = mapToUCDPathVersion(v);
|
|
45
|
-
return {
|
|
46
|
-
version: v,
|
|
47
|
-
mappedVersion: mappedVersion === v ? void 0 : mappedVersion
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
const invalidVersions = versions.filter(({ version }) => !UNICODE_VERSION_METADATA.find((v) => v.version === version));
|
|
51
|
-
if (invalidVersions.length > 0) {
|
|
52
|
-
console.error(red(`Invalid version(s): ${invalidVersions.map((v) => v.version).join(", ")}. Please provide valid Unicode versions.`));
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const outputDir = flags.outputDir ?? path.join(process.cwd(), "data");
|
|
56
|
-
await mkdir(outputDir, { recursive: true });
|
|
57
|
-
const excludePatterns = flags.exclude?.split(",").map((p) => p.trim()).filter(Boolean) || [];
|
|
58
|
-
if (flags.excludeTest) excludePatterns.push("**/*Test*");
|
|
59
|
-
function getAllFilePaths(entries) {
|
|
60
|
-
const filePaths = [];
|
|
61
|
-
function collectPaths(entryList, currentPath = "") {
|
|
62
|
-
for (const entry of entryList) {
|
|
63
|
-
const fullPath = currentPath ? `${currentPath}/${entry.path}` : entry.path;
|
|
64
|
-
if (!entry.children) filePaths.push(fullPath);
|
|
65
|
-
else if (entry.children.length > 0) collectPaths(entry.children, fullPath);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
collectPaths(entries);
|
|
69
|
-
return filePaths;
|
|
70
|
-
}
|
|
71
|
-
function filterEntriesRecursive(entries) {
|
|
72
|
-
if (excludePatterns.length === 0) return entries;
|
|
73
|
-
const allPaths = getAllFilePaths(entries);
|
|
74
|
-
const patterns = ["**", ...excludePatterns.map((pattern) => `!${pattern}`)];
|
|
75
|
-
const matchedPaths = new Set(micromatch(allPaths, patterns, {
|
|
76
|
-
dot: true,
|
|
77
|
-
nocase: true,
|
|
78
|
-
debug: flags.debug
|
|
79
|
-
}));
|
|
80
|
-
function filterEntries(entryList, prefix = "") {
|
|
81
|
-
const result = [];
|
|
82
|
-
for (const entry of entryList) {
|
|
83
|
-
const fullPath = prefix ? `${prefix}/${entry.path}` : entry.path;
|
|
84
|
-
if (!entry.children) {
|
|
85
|
-
if (matchedPaths.has(fullPath)) result.push(entry);
|
|
86
|
-
} else {
|
|
87
|
-
const filteredChildren = filterEntries(entry.children, fullPath);
|
|
88
|
-
if (filteredChildren.length > 0) result.push({
|
|
89
|
-
...entry,
|
|
90
|
-
children: filteredChildren
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
return filterEntries(entries);
|
|
97
|
-
}
|
|
98
|
-
async function processFileEntries(entries, basePath, versionOutputDir, downloadedFiles, currentDirPath = "", errors) {
|
|
99
|
-
const dirPromises = [];
|
|
100
|
-
const filePromises = [];
|
|
101
|
-
for (const entry of entries) {
|
|
102
|
-
const entryOutputPath = currentDirPath ? path.join(currentDirPath, entry.path) : entry.path;
|
|
103
|
-
const outputPath = path.join(versionOutputDir, entryOutputPath);
|
|
104
|
-
if (entry.children) dirPromises.push((async () => {
|
|
105
|
-
await mkdir(outputPath, { recursive: true });
|
|
106
|
-
await processFileEntries(entry.children || [], `${basePath}/${entry.path}`, versionOutputDir, downloadedFiles, entryOutputPath, errors);
|
|
107
|
-
})());
|
|
108
|
-
else filePromises.push((async () => {
|
|
109
|
-
try {
|
|
110
|
-
await mkdir(dirname(outputPath), { recursive: true });
|
|
111
|
-
const url = `${UNICODE_PROXY_URL}${basePath}/${entry.path}`;
|
|
112
|
-
const response = await fetch(url);
|
|
113
|
-
if (!response.ok) {
|
|
114
|
-
errors.push(`Failed to fetch ${entry.path}: ${response.status} ${response.statusText}`);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const content = await response.text();
|
|
118
|
-
if (flags.createCommentFiles) {
|
|
119
|
-
const parsed = path.parse(outputPath);
|
|
120
|
-
const commentPath = path.join(parsed.dir, `${parsed.name}.comments.txt`);
|
|
121
|
-
await writeFile(commentPath, "");
|
|
122
|
-
}
|
|
123
|
-
await writeFile(outputPath, content);
|
|
124
|
-
downloadedFiles.push(outputPath);
|
|
125
|
-
} catch (err) {
|
|
126
|
-
errors.push(`Error downloading ${entry.path}: ${err.message}`);
|
|
127
|
-
}
|
|
128
|
-
})());
|
|
129
|
-
}
|
|
130
|
-
await Promise.all([...dirPromises, ...filePromises]);
|
|
131
|
-
}
|
|
132
|
-
async function processVersion(version) {
|
|
133
|
-
console.info(`Starting download for Unicode ${green(version.version)}${version.mappedVersion ? gray(` (${green(version.mappedVersion)})`) : ""}`);
|
|
134
|
-
const downloadedFiles = [];
|
|
135
|
-
const errors = [];
|
|
136
|
-
const versionOutputDir = path.join(outputDir, `v${version.version}`);
|
|
137
|
-
await mkdir(versionOutputDir, { recursive: true });
|
|
138
|
-
try {
|
|
139
|
-
const filesResponse = await fetch(`${API_URL}/unicode-files/${version.version}`);
|
|
140
|
-
if (!filesResponse.ok) {
|
|
141
|
-
console.error(red(`Failed to fetch file list for version ${version.version}: ${filesResponse.status} ${filesResponse.statusText}`));
|
|
142
|
-
return {
|
|
143
|
-
version: version.version,
|
|
144
|
-
downloadedFiles,
|
|
145
|
-
errors: [`Failed to fetch file list: ${filesResponse.statusText}`]
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
const fileEntries = await filesResponse.json();
|
|
149
|
-
if (!Array.isArray(fileEntries)) {
|
|
150
|
-
console.error(red(`Invalid response format for version ${version.version}`));
|
|
151
|
-
return {
|
|
152
|
-
version: version.version,
|
|
153
|
-
downloadedFiles,
|
|
154
|
-
errors: ["Invalid response format"]
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
const filteredEntries = filterEntriesRecursive(fileEntries);
|
|
158
|
-
const correctVersion = version.mappedVersion ?? version.version;
|
|
159
|
-
const basePath = `/${correctVersion}${hasUCDPath(correctVersion) ? "/ucd" : ""}`;
|
|
160
|
-
await processFileEntries(filteredEntries, basePath, versionOutputDir, downloadedFiles, "", errors);
|
|
161
|
-
if (downloadedFiles.length === 0 && errors.length === 0) console.warn(yellow(`No files were downloaded for Unicode ${version.version}`));
|
|
162
|
-
else if (downloadedFiles.length > 0) {
|
|
163
|
-
console.info(green(`✓ Downloaded ${downloadedFiles.length} files for Unicode ${version.version}`));
|
|
164
|
-
if (flags.debug) downloadedFiles.forEach((file) => {
|
|
165
|
-
const relativePath = path.relative(versionOutputDir, file);
|
|
166
|
-
console.info(green(` - ${relativePath}`));
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
if (errors.length > 0) {
|
|
170
|
-
console.warn(yellow(`${errors.length} errors occurred during download of Unicode ${version.version}`));
|
|
171
|
-
if (flags.debug) errors.forEach((error) => console.error(red(` - ${error}`)));
|
|
172
|
-
}
|
|
173
|
-
} catch (err) {
|
|
174
|
-
const errorMessage = `Error processing version ${version.version}: ${err.message}`;
|
|
175
|
-
errors.push(errorMessage);
|
|
176
|
-
console.error(red(errorMessage));
|
|
177
|
-
}
|
|
178
|
-
return {
|
|
179
|
-
version: version.version,
|
|
180
|
-
downloadedFiles,
|
|
181
|
-
errors
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
const results = [];
|
|
185
|
-
const versionGroups = [];
|
|
186
|
-
for (let i = 0; i < versions.length; i += CONCURRENCY_LIMIT) versionGroups.push(versions.slice(i, i + CONCURRENCY_LIMIT));
|
|
187
|
-
for (const versionGroup of versionGroups) {
|
|
188
|
-
const batchResults = await Promise.all(versionGroup.map(processVersion));
|
|
189
|
-
results.push(...batchResults);
|
|
190
|
-
}
|
|
191
|
-
const totalFiles = results.reduce((sum, r) => sum + r.downloadedFiles.length, 0);
|
|
192
|
-
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
|
|
193
|
-
const successfulVersions = results.filter((r) => r.downloadedFiles.length > 0).length;
|
|
194
|
-
console.info(`\n${"=".repeat(50)}`);
|
|
195
|
-
console.info("Download Summary:");
|
|
196
|
-
console.info(green(`✓ ${successfulVersions}/${results.length} versions processed successfully`));
|
|
197
|
-
console.info(green(`✓ ${totalFiles} total files downloaded`));
|
|
198
|
-
if (totalErrors > 0) console.warn(yellow(`⚠ ${totalErrors} total errors encountered`));
|
|
199
|
-
console.info("=".repeat(50));
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
//#endregion
|
|
203
|
-
export { runDownload };
|