argsbarg 6.0.0 → 6.0.2

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 (43) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +4 -4
  3. package/docs/api-server.md +1 -1
  4. package/docs/config-schema.md +27 -15
  5. package/docs/output-schema.md +107 -75
  6. package/examples/full-example/README.md +8 -7
  7. package/examples/full-example/bun.lock +0 -29
  8. package/examples/full-example/justfile +6 -3
  9. package/examples/full-example/package.json +0 -2
  10. package/examples/full-example/src/commands/status/__generated__/index.ts +5 -0
  11. package/examples/full-example/{schemas/generated/status.json → src/commands/status/__generated__/outputSchema.json} +1 -1
  12. package/examples/full-example/src/commands/status/command.ts +2 -2
  13. package/examples/full-example/src/commands/status/schema.ts +14 -0
  14. package/examples/full-example/src/commands/status/types.ts +1 -11
  15. package/examples/full-example/{schemas/generated/app-config.json → src/config/__generated__/configSchema.json} +1 -1
  16. package/examples/full-example/src/config/__generated__/index.ts +5 -0
  17. package/examples/full-example/src/{types.ts → config/schema.ts} +3 -2
  18. package/examples/full-example/src/program.ts +4 -4
  19. package/package.json +24 -17
  20. package/src/api/openapi.ts +4 -2
  21. package/src/api/result.ts +23 -1
  22. package/src/api/schema-deref.test.ts +99 -0
  23. package/src/api/schema-deref.ts +76 -0
  24. package/src/api.integration.test.ts +85 -2
  25. package/src/cli-errors.ts +3 -0
  26. package/src/cli-tool/full-example-capabilities.test.ts +2 -1
  27. package/src/cli-tool/post-create.ts +3 -3
  28. package/src/cli-tool/program.ts +35 -0
  29. package/src/cli-tool/run-schemagen.ts +23 -0
  30. package/src/cli-tool/schemagen/cleanup.ts +60 -0
  31. package/src/cli-tool/schemagen/discover-schema-roots.ts +103 -0
  32. package/src/cli-tool/schemagen/index.ts +3 -0
  33. package/src/cli-tool/schemagen/names.ts +22 -0
  34. package/src/cli-tool/schemagen/run.ts +108 -0
  35. package/src/cli-tool/schemagen/schemagen.test.ts +125 -0
  36. package/src/docs/mcp-resources.ts +5 -2
  37. package/src/headless/tool-call.ts +16 -6
  38. package/examples/full-example/schemas/configSchemas.ts +0 -6
  39. package/examples/full-example/schemas/outputSchemas.ts +0 -6
  40. package/examples/full-example/scripts/schemagen/discover-schema-roots.test.ts +0 -25
  41. package/examples/full-example/scripts/schemagen/discover-schema-roots.ts +0 -93
  42. package/examples/full-example/scripts/schemagen/naming.ts +0 -82
  43. package/examples/full-example/scripts/schemagen.ts +0 -80
@@ -1,82 +0,0 @@
1
- /*
2
- Maps discovered schema root type names to generated filenames and bridge export constants.
3
- Matches conventions in docs/output-schema.md and docs/config-schema.md.
4
- */
5
-
6
- /** kebab-case from PascalCase segments. */
7
- export function camelToKebab(name: string): string {
8
- return name
9
- .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
10
- .replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
11
- .toLowerCase();
12
- }
13
-
14
- /** SCREAMING_SNAKE from PascalCase. */
15
- export function camelToScreamingSnake(name: string): string {
16
- return camelToKebab(name).replace(/-/g, "_").toUpperCase();
17
- }
18
-
19
- /** Generated JSON filename for an output-schema root type. */
20
- export function outfileForOutputType(typeName: string): string {
21
- if (typeName.endsWith("JsonOutput")) {
22
- return `${camelToKebab(typeName.slice(0, -"JsonOutput".length))}.json`;
23
- }
24
- if (typeName.endsWith("OpResult")) {
25
- return `${camelToKebab(typeName.slice(0, -"OpResult".length))}-op-result.json`;
26
- }
27
- if (typeName.endsWith("Output")) {
28
- return `${camelToKebab(typeName.slice(0, -"Output".length))}.json`;
29
- }
30
- if (typeName.endsWith("Result")) {
31
- return `${camelToKebab(typeName.slice(0, -"Result".length))}.json`;
32
- }
33
- return `${camelToKebab(typeName)}.json`;
34
- }
35
-
36
- /** Bridge export constant for an output-schema root. */
37
- export function outputSchemaExportName(typeName: string): string {
38
- if (typeName.endsWith("JsonOutput")) {
39
- const base = typeName.slice(0, -"JsonOutput".length);
40
- return `${camelToScreamingSnake(base)}_JSON_OUTPUT_SCHEMA`;
41
- }
42
- if (typeName.endsWith("OpResult")) {
43
- const base = typeName.slice(0, -"OpResult".length);
44
- return `${camelToScreamingSnake(base)}_OP_RESULT_OUTPUT_SCHEMA`;
45
- }
46
- if (typeName.endsWith("Output")) {
47
- const base = typeName.slice(0, -"Output".length);
48
- return `${camelToScreamingSnake(base)}_OUTPUT_SCHEMA`;
49
- }
50
- if (typeName.endsWith("Result")) {
51
- const base = typeName.slice(0, -"Result".length);
52
- return `${camelToScreamingSnake(base)}_RESULT_OUTPUT_SCHEMA`;
53
- }
54
- return `${camelToScreamingSnake(typeName)}_OUTPUT_SCHEMA`;
55
- }
56
-
57
- /** Generated JSON filename for a config-schema root (typically AppConfig → app-config.json). */
58
- export function outfileForConfigType(typeName: string): string {
59
- if (typeName.endsWith("Config")) {
60
- return `${camelToKebab(typeName.slice(0, -"Config".length))}-config.json`;
61
- }
62
- return `${camelToKebab(typeName)}-config.json`;
63
- }
64
-
65
- /** Bridge export constant for a config-schema root (AppConfig → APP_CONFIG_JSON_SCHEMA). */
66
- export function configSchemaExportName(typeName: string): string {
67
- if (typeName.endsWith("Config")) {
68
- const base = typeName.slice(0, -"Config".length);
69
- return `${camelToScreamingSnake(base)}_CONFIG_JSON_SCHEMA`;
70
- }
71
- return `${camelToScreamingSnake(typeName)}_CONFIG_JSON_SCHEMA`;
72
- }
73
-
74
- /** Import path basename for a generated JSON file (no extension). */
75
- export function jsonImportBasename(outfile: string): string {
76
- return outfile.replace(/\.json$/, "");
77
- }
78
-
79
- /** Safe import binding for a generated JSON file (no extension, hyphens → underscores). */
80
- export function jsonImportVar(outfile: string): string {
81
- return jsonImportBasename(outfile).replace(/-/g, "_");
82
- }
@@ -1,80 +0,0 @@
1
- /*
2
- Generate JSON Schema artifacts and bridge modules from discovered types.ts roots.
3
- */
4
-
5
- import { mkdirSync, writeFileSync } from "node:fs";
6
- import { dirname, join } from "node:path";
7
- import { createGenerator } from "ts-json-schema-generator";
8
- import { discoverSchemaRoots, type SchemaRoot } from "./schemagen/discover-schema-roots.ts";
9
- import { jsonImportVar } from "./schemagen/naming.ts";
10
-
11
- const projectRoot = join(import.meta.dir, "..");
12
- const generatedDir = join(projectRoot, "schemas", "generated");
13
-
14
- function generateJson(root: SchemaRoot): Record<string, unknown> {
15
- const generator = createGenerator({
16
- path: join(projectRoot, root.relFile),
17
- type: root.typeName,
18
- tsconfig: join(projectRoot, "tsconfig.json"),
19
- topRef: false,
20
- skipTypeCheck: false,
21
- jsDoc: "extended",
22
- additionalProperties: root.kind === "config" ? false : undefined,
23
- });
24
- const schema = generator.createSchema(root.typeName) as Record<string, unknown>;
25
- if (root.kind === "config") {
26
- schema.additionalProperties = false;
27
- }
28
- return schema;
29
- }
30
-
31
- function writeBridge(path: string, scriptName: string, roots: SchemaRoot[], banner: string): void {
32
- /** Sort by import binding so Biome `organizeImports` does not reorder the bridge file. */
33
- const sorted = [...roots].sort((left, right) =>
34
- jsonImportVar(left.outfile).localeCompare(jsonImportVar(right.outfile)),
35
- );
36
- const lines = [`// Auto-generated by scripts/${scriptName} — do not edit by hand.`, ""];
37
- for (const root of sorted) {
38
- const varName = jsonImportVar(root.outfile);
39
- lines.push(`import ${varName} from "./generated/${root.outfile}";`);
40
- }
41
- if (sorted.length > 0) {
42
- lines.push("");
43
- }
44
- for (const root of sorted) {
45
- const varName = jsonImportVar(root.outfile);
46
- lines.push(`/** ${banner} \`${root.typeName}\`. */`);
47
- lines.push(`export const ${root.exportName} = ${varName} as Record<string, unknown>;`);
48
- lines.push("");
49
- }
50
- writeFileSync(path, `${lines.join("\n")}`);
51
- }
52
-
53
- const roots = discoverSchemaRoots(projectRoot);
54
- const configRoots = roots.filter((r) => r.kind === "config");
55
- const outputRoots = roots.filter((r) => r.kind === "output");
56
-
57
- mkdirSync(generatedDir, { recursive: true });
58
-
59
- for (const root of roots) {
60
- const schema = generateJson(root);
61
- const outPath = join(generatedDir, root.outfile);
62
- mkdirSync(dirname(outPath), { recursive: true });
63
- writeFileSync(outPath, `${JSON.stringify(schema, null, 2)}\n`);
64
- console.log(`wrote schemas/generated/${root.outfile} (${root.typeName})`);
65
- }
66
-
67
- writeBridge(
68
- join(projectRoot, "schemas", "configSchemas.ts"),
69
- "schemagen.ts",
70
- configRoots,
71
- "JSON Schema for program.appConfig.jsonSchema from",
72
- );
73
- writeBridge(
74
- join(projectRoot, "schemas", "outputSchemas.ts"),
75
- "schemagen.ts",
76
- outputRoots,
77
- "JSON Schema for leaf outputSchema from",
78
- );
79
-
80
- console.log(`config roots: ${configRoots.length}, output roots: ${outputRoots.length}`);