@forwardimpact/libcodegen 0.1.39 → 0.1.41

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.
Files changed (2) hide show
  1. package/bin/fit-codegen.js +63 -53
  2. package/package.json +3 -2
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from "node:fs";
3
+ import fs, { readFileSync } from "node:fs";
4
4
  import fsAsync from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  import { execFileSync } from "node:child_process";
7
- import { parseArgs } from "node:util";
8
7
 
9
8
  import protoLoader from "@grpc/proto-loader";
10
9
  import mustache from "mustache";
11
10
 
11
+ import { createCli, SummaryRenderer } from "@forwardimpact/libcli";
12
12
  import { Finder } from "@forwardimpact/libutil";
13
13
  import { Logger } from "@forwardimpact/libtelemetry";
14
14
  import {
@@ -19,6 +19,39 @@ import {
19
19
  } from "@forwardimpact/libcodegen";
20
20
  import { createStorage } from "@forwardimpact/libstorage";
21
21
 
22
+ const { version: VERSION } = JSON.parse(
23
+ readFileSync(new URL("../package.json", import.meta.url), "utf8"),
24
+ );
25
+
26
+ const definition = {
27
+ name: "fit-codegen",
28
+ version: VERSION,
29
+ description: "Generate protobuf types, service clients, and definitions",
30
+ options: {
31
+ all: { type: "boolean", description: "Generate all code" },
32
+ type: { type: "boolean", description: "Generate protobuf types only" },
33
+ service: {
34
+ type: "boolean",
35
+ description: "Generate service bases only",
36
+ },
37
+ client: { type: "boolean", description: "Generate clients only" },
38
+ definition: {
39
+ type: "boolean",
40
+ description: "Generate service definitions only",
41
+ },
42
+ help: { type: "boolean", short: "h", description: "Show this help" },
43
+ version: { type: "boolean", description: "Show version" },
44
+ json: { type: "boolean", description: "Output help as JSON" },
45
+ },
46
+ examples: [
47
+ "npx fit-codegen --all",
48
+ "npx fit-codegen --type",
49
+ "npx fit-codegen --service",
50
+ ],
51
+ };
52
+
53
+ const cli = createCli(definition);
54
+
22
55
  /**
23
56
  * Create tar.gz bundle of all directories inside sourcePath
24
57
  * @param {string} sourcePath - Path containing directories to bundle
@@ -53,51 +86,16 @@ async function createBundle(sourcePath) {
53
86
  }
54
87
 
55
88
  /**
56
- * Print CLI usage help
57
- */
58
- function printUsage() {
59
- process.stdout.write(
60
- [
61
- "Usage:",
62
- ` npx fit-codegen --all # Generate all code`,
63
- ` npx fit-codegen --type # Generate protobuf types only`,
64
- ` npx fit-codegen --service # Generate service bases only`,
65
- ` npx fit-codegen --client # Generate clients only`,
66
- ` npx fit-codegen --definition # Generate service definitions only`,
67
- ].join("\n") + "\n",
68
- );
69
- }
70
-
71
- /**
72
- * Parse command line flags
89
+ * Parse command line flags using libcli
73
90
  * @returns {object} Parsed flags with convenience methods
74
91
  */
75
92
  function parseFlags() {
76
- const { values } = parseArgs({
77
- options: {
78
- all: {
79
- type: "boolean",
80
- default: false,
81
- },
82
- type: {
83
- type: "boolean",
84
- default: false,
85
- },
86
- service: {
87
- type: "boolean",
88
- default: false,
89
- },
90
- client: {
91
- type: "boolean",
92
- default: false,
93
- },
94
- definition: {
95
- type: "boolean",
96
- default: false,
97
- },
98
- },
99
- });
93
+ const parsed = cli.parse(process.argv.slice(2));
94
+ if (!parsed) {
95
+ process.exit(0);
96
+ }
100
97
 
98
+ const { values } = parsed;
101
99
  const doAll = values.all;
102
100
  return {
103
101
  doTypes: doAll || values.type,
@@ -205,7 +203,6 @@ function countFiles(dirPath) {
205
203
  function printSummary(sourcePath, flags) {
206
204
  const totalFiles = countFiles(sourcePath);
207
205
  const relPath = path.relative(process.cwd(), sourcePath);
208
- const lines = [`Generated ${totalFiles} files in ./${relPath}/`];
209
206
 
210
207
  const dirLabels = {
211
208
  types: "Protocol Buffer types",
@@ -214,6 +211,7 @@ function printSummary(sourcePath, flags) {
214
211
  definitions: "Service definitions",
215
212
  };
216
213
 
214
+ const items = [];
217
215
  if (fs.existsSync(sourcePath)) {
218
216
  const dirs = fs
219
217
  .readdirSync(sourcePath, { withFileTypes: true })
@@ -221,19 +219,28 @@ function printSummary(sourcePath, flags) {
221
219
 
222
220
  for (const dir of dirs) {
223
221
  const label = dirLabels[dir.name];
224
- if (label) lines.push(` ${dir.name}/ — ${label}`);
222
+ if (label) items.push({ label: `${dir.name}/`, description: label });
225
223
  }
226
224
  }
227
225
 
226
+ const summary = new SummaryRenderer({ process });
227
+ summary.render(
228
+ {
229
+ title: `Generated ${totalFiles} files in ./${relPath}/`,
230
+ items,
231
+ },
232
+ process.stdout,
233
+ );
234
+
228
235
  const generated = [
229
236
  flags.doTypes && "types",
230
237
  flags.doServices && "services",
231
238
  flags.doClients && "clients",
232
239
  flags.doDefinitions && "definitions",
233
240
  ].filter(Boolean);
234
- lines.push(`\nCode generation complete (${generated.join(", ")}).`);
235
-
236
- process.stdout.write(lines.join("\n") + "\n");
241
+ process.stdout.write(
242
+ `\nCode generation complete (${generated.join(", ")}).\n`,
243
+ );
237
244
  }
238
245
 
239
246
  /**
@@ -286,9 +293,10 @@ async function runCodegen(protoDirs, projectRoot, finder) {
286
293
  const parsedFlags = parseFlags();
287
294
 
288
295
  if (!parsedFlags.hasGenerationFlags()) {
289
- printUsage();
290
- process.exitCode = 1;
291
- return;
296
+ cli.usageError(
297
+ "no generation flags specified (use --all, --type, --service, --client, or --definition)",
298
+ );
299
+ process.exit(2);
292
300
  }
293
301
 
294
302
  const generatedStorage = createStorage("generated", "local");
@@ -342,12 +350,14 @@ async function main() {
342
350
 
343
351
  await runCodegen(protoDirs, projectRoot, finder);
344
352
  } catch (err) {
345
- process.stderr.write(`Error: ${err.message}\n`);
353
+ const logger = new Logger("codegen");
354
+ logger.exception("main", err);
355
+ cli.error(err.message);
346
356
  process.exit(1);
347
357
  }
348
358
  }
349
359
 
350
360
  main().catch((err) => {
351
- process.stderr.write(`Unexpected error: ${err.message}\n`);
361
+ cli.error(err.message);
352
362
  process.exit(1);
353
363
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forwardimpact/libcodegen",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "Protocol Buffer code generation utilities for Guide",
5
5
  "license": "Apache-2.0",
6
6
  "author": "D. Olsson <hi@senzilla.io>",
@@ -17,13 +17,14 @@
17
17
  "test": "bun run node --test test/*.test.js"
18
18
  },
19
19
  "dependencies": {
20
+ "@forwardimpact/libcli": "^0.1.0",
20
21
  "@forwardimpact/libstorage": "^0.1.53",
21
22
  "@forwardimpact/libtelemetry": "^0.1.22",
22
23
  "@forwardimpact/libutil": "^0.1.64",
23
24
  "@grpc/proto-loader": "^0.8.0",
24
25
  "mustache": "^4.2.0",
25
26
  "protobufjs": "^7.5.4",
26
- "protobufjs-cli": "^2.0.0"
27
+ "protobufjs-cli": "^2.0.1"
27
28
  },
28
29
  "devDependencies": {
29
30
  "@forwardimpact/libharness": "^0.1.5"