@ucdjs/cli 0.1.2 → 0.1.3

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.
@@ -4,7 +4,7 @@ import yargs from "yargs-parser";
4
4
 
5
5
  //#region package.json
6
6
  var name = "@ucdjs/cli";
7
- var version = "0.1.2";
7
+ var version = "0.1.3";
8
8
  var type = "module";
9
9
  var author = {
10
10
  "name": "Lucas Nørgård",
@@ -144,7 +144,7 @@ async function runCommand(cmd, flags) {
144
144
  console.log(` ${bgGreen(black(` ucd `))} ${green(`v${package_default.version ?? "x.y.z"}`)}`);
145
145
  break;
146
146
  case "generate": {
147
- const { runGenerate } = await import("./generate-Z7bYnm_v.js");
147
+ const { runGenerate } = await import("./generate-DBhAloii.js");
148
148
  const versions = flags._.slice(3);
149
149
  await runGenerate({
150
150
  versions,
@@ -153,7 +153,7 @@ async function runCommand(cmd, flags) {
153
153
  break;
154
154
  }
155
155
  case "codegen": {
156
- const { runCodegenRoot } = await import("./root-BT7DL0Ms.js");
156
+ const { runCodegenRoot } = await import("./root-DAq3Tcji.js");
157
157
  const subcommand = flags._[3]?.toString() ?? "";
158
158
  await runCodegenRoot(subcommand, { flags });
159
159
  break;
package/dist/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import { runCLI } from "./cli-utils-DyOk9RI0.js";
1
+ import { runCLI } from "./cli-utils-CtO_eQb6.js";
2
2
  import process from "node:process";
3
3
 
4
4
  //#region src/cli.ts
@@ -0,0 +1,123 @@
1
+ import { printHelp } from "./cli-utils-CtO_eQb6.js";
2
+ import process from "node:process";
3
+ import { existsSync } from "node:fs";
4
+ import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
5
+ import path from "node:path";
6
+ import { RawDataFile } from "@luxass/unicode-utils/data-files";
7
+ import { toKebabCase } from "@luxass/utils";
8
+ import { generateFields } from "@ucdjs/schema-gen";
9
+
10
+ //#region src/cmd/codegen/fields.ts
11
+ function flattenVersion(version) {
12
+ const parts = version.split(".");
13
+ while (parts.length > 1 && parts[parts.length - 1] === "0") parts.pop();
14
+ return parts.join(".");
15
+ }
16
+ async function runFieldCodegen({ inputPath, flags }) {
17
+ if (flags?.help || flags?.h) {
18
+ printHelp({
19
+ headline: "Generate Unicode Data Files",
20
+ commandName: "ucd codegen fields",
21
+ usage: "<input> [...flags]",
22
+ tables: { Flags: [
23
+ ["--openai-key (-k)", "The OpenAI API key to use. (can also be set using OPENAI_API_KEY env var)"],
24
+ ["--output-dir", "Specify the output directory for generated files (defaults to .codegen)"],
25
+ ["--bundle <filename>", "Combine generated files into a single file per version. Use {version} placeholder for version-specific naming"],
26
+ ["--help (-h)", "See all available flags."]
27
+ ] }
28
+ });
29
+ return;
30
+ }
31
+ const openaiKey = flags.openaiKey || process.env.OPENAI_API_KEY;
32
+ if (!openaiKey) {
33
+ console.error("No OpenAI API key provided. Please provide an OpenAI API key.");
34
+ return;
35
+ }
36
+ if (inputPath == null) {
37
+ console.error("No input path provided. Please provide an input path.");
38
+ return;
39
+ }
40
+ const resolvedInputPath = path.resolve(inputPath);
41
+ if (!existsSync(resolvedInputPath)) {
42
+ console.error(`invalid input path: ${inputPath}. Please provide a valid input path.`);
43
+ return;
44
+ }
45
+ const shouldBundle = typeof flags.bundle === "string" || flags.bundle === true;
46
+ const bundleTemplate = typeof flags.bundle === "string" ? flags.bundle : "index.ts";
47
+ let outputDir = flags.outputDir;
48
+ if (!outputDir) if (shouldBundle && (path.isAbsolute(bundleTemplate) || bundleTemplate.startsWith("./") || bundleTemplate.startsWith("../"))) outputDir = path.dirname(bundleTemplate);
49
+ else outputDir = path.join(path.dirname(resolvedInputPath), ".codegen");
50
+ if (outputDir) await mkdir(outputDir, { recursive: true });
51
+ const isDirectory = (await stat(resolvedInputPath)).isDirectory();
52
+ const filesByVersion = new Map();
53
+ if (isDirectory) {
54
+ const dir = await readdir(resolvedInputPath, {
55
+ withFileTypes: true,
56
+ recursive: true
57
+ });
58
+ for (const file of dir) if (file.isFile() && file.name.endsWith(".txt")) {
59
+ const filePath = path.join(file.parentPath, file.name);
60
+ const versionMatch = filePath.match(/v(\d+\.\d+\.\d+)/);
61
+ const version = versionMatch ? flattenVersion(versionMatch[1]) : "unknown";
62
+ const files = filesByVersion.get(version) ?? [];
63
+ files.push(filePath);
64
+ filesByVersion.set(version, files);
65
+ }
66
+ } else {
67
+ const parentDir = path.dirname(resolvedInputPath);
68
+ const versionMatch = parentDir.match(/v(\d+\.\d+\.\d+)/);
69
+ const version = versionMatch ? flattenVersion(versionMatch[1]) : "unknown";
70
+ filesByVersion.set(version, [resolvedInputPath]);
71
+ }
72
+ for (const [version, files] of filesByVersion) {
73
+ const promises = files.map(async (filePath) => {
74
+ const content = await readFile(filePath, "utf-8");
75
+ const datafile = new RawDataFile(content);
76
+ if (datafile.heading == null) {
77
+ console.error(`heading for file ${filePath} is null. Skipping file.`);
78
+ return null;
79
+ }
80
+ const code = await generateFields({
81
+ datafile,
82
+ apiKey: openaiKey
83
+ });
84
+ if (code == null) {
85
+ console.error(`Error generating fields for file: ${filePath}`);
86
+ return null;
87
+ }
88
+ if (!shouldBundle) {
89
+ const fileName = toKebabCase(path.basename(filePath).replace(/\.txt$/, "")).toLowerCase();
90
+ await writeFile(path.join(outputDir, `${fileName}.ts`), code, "utf-8");
91
+ }
92
+ return {
93
+ code,
94
+ fileName: filePath
95
+ };
96
+ });
97
+ const generatedCode = await Promise.all(promises);
98
+ if (shouldBundle) {
99
+ let bundledCode = `// This file is generated by ucd codegen. Do not edit this file directly.\n`;
100
+ bundledCode += `// Unicode Version: ${version}\n\n`;
101
+ for (const result of generatedCode.filter(Boolean)) {
102
+ if (!result) continue;
103
+ const relativePath = path.relative(process.cwd(), result.fileName);
104
+ bundledCode += `// #region ${relativePath}\n`;
105
+ bundledCode += result.code;
106
+ bundledCode += `\n// #endregion\n`;
107
+ }
108
+ const bundleFileName = bundleTemplate.replace("{version}", version);
109
+ let bundlePath;
110
+ if (path.isAbsolute(bundleFileName) || bundleFileName.startsWith("./") || bundleFileName.startsWith("../")) bundlePath = path.resolve(bundleFileName);
111
+ else if (outputDir) bundlePath = path.resolve(path.join(outputDir, bundleFileName));
112
+ else bundlePath = path.resolve(bundleFileName);
113
+ if (!bundlePath.endsWith(".ts")) bundlePath += ".ts";
114
+ await mkdir(path.dirname(bundlePath), { recursive: true });
115
+ await writeFile(bundlePath, bundledCode, "utf-8");
116
+ console.log(`Generated bundled fields for Unicode ${version} in ${bundlePath}`);
117
+ }
118
+ }
119
+ if (!shouldBundle) console.log(`Generated fields for ${Array.from(filesByVersion.values()).flat().length} files in ${outputDir}`);
120
+ }
121
+
122
+ //#endregion
123
+ export { runFieldCodegen };
@@ -1,4 +1,4 @@
1
- import { printHelp } from "./cli-utils-DyOk9RI0.js";
1
+ import { printHelp } from "./cli-utils-CtO_eQb6.js";
2
2
  import { green, yellow } from "farver/fast";
3
3
  import { mkdir, writeFile } from "node:fs/promises";
4
4
  import path, { dirname, join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { printHelp } from "./cli-utils-DyOk9RI0.js";
1
+ import { printHelp } from "./cli-utils-CtO_eQb6.js";
2
2
 
3
3
  //#region src/cmd/codegen/root.ts
4
4
  const CODEGEN_SUBCOMMANDS = ["fields"];
@@ -18,7 +18,7 @@ async function runCodegenRoot(subcommand, { flags }) {
18
18
  return;
19
19
  }
20
20
  if (subcommand === "fields") {
21
- const { runFieldCodegen } = await import("./fields-BqikCPbE.js");
21
+ const { runFieldCodegen } = await import("./fields-DDyAQa-S.js");
22
22
  const inputPath = flags._.slice(4)?.toString() ?? "";
23
23
  await runFieldCodegen({
24
24
  inputPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ucdjs/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Lucas Nørgård",
@@ -29,7 +29,7 @@
29
29
  "@luxass/utils": "^1.4.0",
30
30
  "farver": "^0.4.2",
31
31
  "yargs-parser": "^21.1.1",
32
- "@ucdjs/schema-gen": "0.1.0"
32
+ "@ucdjs/schema-gen": "0.2.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@luxass/eslint-config": "^4.18.1",
@@ -1,98 +0,0 @@
1
- import { printHelp } from "./cli-utils-DyOk9RI0.js";
2
- import { existsSync } from "node:fs";
3
- import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
4
- import path from "node:path";
5
- import { RawDataFile } from "@luxass/unicode-utils/data-files";
6
- import { toKebabCase } from "@luxass/utils";
7
- import { generateFields } from "@ucdjs/schema-gen";
8
-
9
- //#region src/cmd/codegen/fields.ts
10
- async function runFieldCodegen({ inputPath, flags }) {
11
- if (flags?.help || flags?.h) {
12
- printHelp({
13
- headline: "Generate Unicode Data Files",
14
- commandName: "ucd codegen fields",
15
- usage: "<input> [...flags]",
16
- tables: { Flags: [
17
- ["--openai-key (-k)", "The OpenAI API key to use. (can also be set using OPENAI_API_KEY env var)"],
18
- ["--output-dir", "Specify the output directory for generated files (defaults to .codegen)"],
19
- ["--bundle <filename>", "Combine all generated files into a single file, if no filename is provided, the default is index.ts"],
20
- ["--help (-h)", "See all available flags."]
21
- ] }
22
- });
23
- return;
24
- }
25
- const openaiKey = flags.openaiKey || process.env.OPENAI_API_KEY;
26
- if (!openaiKey) {
27
- console.error("No OpenAI API key provided. Please provide an OpenAI API key.");
28
- return;
29
- }
30
- if (inputPath == null) {
31
- console.error("No input path provided. Please provide an input path.");
32
- return;
33
- }
34
- const resolvedInputPath = path.resolve(inputPath);
35
- if (!existsSync(resolvedInputPath)) {
36
- console.error(`invalid input path: ${inputPath}. Please provide a valid input path.`);
37
- return;
38
- }
39
- const outputDir = flags.outputDir || process.cwd();
40
- await mkdir(outputDir, { recursive: true });
41
- const shouldBundle = typeof flags.bundle === "string" || flags.bundle === true;
42
- const bundleFileName = typeof flags.bundle === "string" ? flags.bundle : "index.ts";
43
- const isDirectory = (await stat(resolvedInputPath)).isDirectory();
44
- const files = [];
45
- if (isDirectory) {
46
- const dir = await readdir(resolvedInputPath, {
47
- withFileTypes: true,
48
- recursive: true
49
- });
50
- for (const file of dir) if (file.isFile()) {
51
- if (!file.name.endsWith(".txt")) continue;
52
- files.push(path.join(file.parentPath, file.name));
53
- }
54
- } else files.push(resolvedInputPath);
55
- const promises = files.map(async (filePath) => {
56
- const content = await readFile(filePath, "utf-8");
57
- const datafile = new RawDataFile(content);
58
- if (datafile.heading == null) {
59
- console.error(`heading for file ${filePath} is null. Skipping file.`);
60
- return null;
61
- }
62
- const code = await generateFields({
63
- datafile,
64
- apiKey: openaiKey
65
- });
66
- if (code == null) {
67
- console.error(`Error generating fields for file: ${filePath}`);
68
- return null;
69
- }
70
- if (!shouldBundle) {
71
- const fileName = toKebabCase(path.basename(filePath).replace(/\.txt$/, "")).toLowerCase();
72
- await writeFile(path.join(outputDir, `${fileName}.ts`), code, "utf-8");
73
- }
74
- return {
75
- code,
76
- fileName: filePath.replace(`${process.cwd()}/`, "")
77
- };
78
- });
79
- const generatedCode = await Promise.all(promises);
80
- if (!shouldBundle) {
81
- console.log(`Generated fields for ${files.length} files in ${outputDir}`);
82
- return;
83
- }
84
- let bundledCode = `// This file is generated by ucd codegen. Do not edit this file directly.\n\n`;
85
- for (const { fileName, code } of generatedCode.filter((obj) => obj != null)) {
86
- bundledCode += `//#region ${fileName}\n`;
87
- bundledCode += code;
88
- bundledCode += `\n//#endregion\n`;
89
- bundledCode += "\n\n";
90
- }
91
- let bundlePath = path.resolve(path.join(outputDir, bundleFileName));
92
- if (path.extname(bundleFileName) === "") bundlePath = path.join(outputDir, `${bundleFileName}.ts`);
93
- await writeFile(bundlePath, bundledCode, "utf-8");
94
- console.log(`Generated bundled fields in ${bundlePath}`);
95
- }
96
-
97
- //#endregion
98
- export { runFieldCodegen };