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.
- package/CHANGELOG.md +27 -1
- package/README.md +4 -4
- package/docs/api-server.md +1 -1
- package/docs/config-schema.md +27 -15
- package/docs/output-schema.md +107 -75
- package/examples/full-example/README.md +8 -7
- package/examples/full-example/bun.lock +0 -29
- package/examples/full-example/justfile +6 -3
- package/examples/full-example/package.json +0 -2
- package/examples/full-example/src/commands/status/__generated__/index.ts +5 -0
- package/examples/full-example/{schemas/generated/status.json → src/commands/status/__generated__/outputSchema.json} +1 -1
- package/examples/full-example/src/commands/status/command.ts +2 -2
- package/examples/full-example/src/commands/status/schema.ts +14 -0
- package/examples/full-example/src/commands/status/types.ts +1 -11
- package/examples/full-example/{schemas/generated/app-config.json → src/config/__generated__/configSchema.json} +1 -1
- package/examples/full-example/src/config/__generated__/index.ts +5 -0
- package/examples/full-example/src/{types.ts → config/schema.ts} +3 -2
- package/examples/full-example/src/program.ts +4 -4
- package/package.json +24 -17
- package/src/api/openapi.ts +4 -2
- package/src/api/result.ts +23 -1
- package/src/api/schema-deref.test.ts +99 -0
- package/src/api/schema-deref.ts +76 -0
- package/src/api.integration.test.ts +85 -2
- package/src/cli-errors.ts +3 -0
- package/src/cli-tool/full-example-capabilities.test.ts +2 -1
- package/src/cli-tool/post-create.ts +3 -3
- package/src/cli-tool/program.ts +35 -0
- package/src/cli-tool/run-schemagen.ts +23 -0
- package/src/cli-tool/schemagen/cleanup.ts +60 -0
- package/src/cli-tool/schemagen/discover-schema-roots.ts +103 -0
- package/src/cli-tool/schemagen/index.ts +3 -0
- package/src/cli-tool/schemagen/names.ts +22 -0
- package/src/cli-tool/schemagen/run.ts +108 -0
- package/src/cli-tool/schemagen/schemagen.test.ts +125 -0
- package/src/docs/mcp-resources.ts +5 -2
- package/src/headless/tool-call.ts +16 -6
- package/examples/full-example/schemas/configSchemas.ts +0 -6
- package/examples/full-example/schemas/outputSchemas.ts +0 -6
- package/examples/full-example/scripts/schemagen/discover-schema-roots.test.ts +0 -25
- package/examples/full-example/scripts/schemagen/discover-schema-roots.ts +0 -93
- package/examples/full-example/scripts/schemagen/naming.ts +0 -82
- package/examples/full-example/scripts/schemagen.ts +0 -80
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [6.0.2] - 2026-07-22
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`argsbarg schemagen`** — centralized JSON Schema generation from `src/**/schema.ts` into colocated `__generated__/` directories (`configSchema.json`, `inputSchema.json`, `outputSchema.json`, plus `index.ts` re-exports). Removes orphan `__generated__/` trees and stale JSON when schema roots or kinds are removed.
|
|
15
|
+
- **`argsbarg/schemagen`** export — `runSchemagen`, `discoverSchemaRoots`, and naming helpers (`src/cli-tool/schemagen/`).
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **Schemagen convention** — replace per-repo `scripts/schemagen*` copies and `schema-types.ts` bindings with `schema.ts` + gitignored `__generated__/`. Run via `just schemagen` (`argsbarg schemagen` with `node_modules/.bin` on `PATH`).
|
|
20
|
+
|
|
21
|
+
## [6.0.1] - 2026-07-22
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **OpenAPI schema dereferencing** — inline internal `$ref` pointers when building OpenAPI documents so API reference UIs show nested request shapes.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **Colocated schemagen** — `*.schema.json` beside each `schema-types.ts`; exports `configSchema` / `inputSchema` / `outputSchema` (replaces central `*Schemas.ts` bridges).
|
|
30
|
+
- **HTTP tool errors** — return a plain `{ "error": "..." }` JSON body without ANSI color codes or appended CLI help text.
|
|
31
|
+
- **`cliErrWithHelp`** — on `api` / `mcp` invocations, throws a plain error instead of printing contextual help.
|
|
32
|
+
- **`GET /openapi-browser`** — Scalar config preserves schema property order from the OpenAPI document (`orderSchemaPropertiesBy: "preserve"`).
|
|
33
|
+
|
|
10
34
|
## [6.0.0] - 2026-07-22
|
|
11
35
|
|
|
12
36
|
### Added
|
|
@@ -715,7 +739,9 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
|
715
739
|
- Migrate schemas: rename every `children` property to **`commands`**; move positional definitions to **`CliPositional`** objects on `positionals` and strip `positional` / `argMin` / `argMax` from flag definitions under `options` (flags only carry `name`, `description`, `kind`, and optional `shortName`).
|
|
716
740
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
717
741
|
|
|
718
|
-
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v6.0.
|
|
742
|
+
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v6.0.2...HEAD
|
|
743
|
+
[6.0.2]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.2
|
|
744
|
+
[6.0.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.1
|
|
719
745
|
[6.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.0
|
|
720
746
|
[5.1.16]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.16
|
|
721
747
|
[5.1.15]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.15
|
package/README.md
CHANGED
|
@@ -167,7 +167,7 @@ Add app-specific conventions in a second rule if needed. Copy the rule from the
|
|
|
167
167
|
|
|
168
168
|
1. Build a **program root** with `satisfies CliProgram` (or `: CliProgram`): `key` is the app name, `commands` are top-level subcommands, `options` are global flags. A router root must not set `handler` or declare `positionals` (validated at startup). A leaf root may set `handler` and `positionals` directly. Use `fallbackCommand` / `fallbackMode` on any **routing node** for default subcommand routing (not root-only).
|
|
169
169
|
2. Call `await new Cli(program).run()` — validates, parses argv, renders help or errors, invokes the leaf handler, and `process.exit`s with status **0** on success, **1** on implicit help or error (explicit `--help` → **0**).
|
|
170
|
-
3. From a handler, `cliErrWithHelp(ctx, "message")` prints a red error line plus contextual help on stderr and exits **1
|
|
170
|
+
3. From a handler, `cliErrWithHelp(ctx, "message")` prints a red error line plus contextual help on stderr and exits **1** (CLI only; API/MCP invocations throw a plain `Error`).
|
|
171
171
|
|
|
172
172
|
|
|
173
173
|
|
|
@@ -267,9 +267,9 @@ To refresh the Cursor rule in an existing consumer: `bun scripts/merge-cli-progr
|
|
|
267
267
|
| Area | Files / wiring |
|
|
268
268
|
| --------------------- | -------------------------------------------------------------------------------------- |
|
|
269
269
|
| All builtins | `completion`, `version`, `configure`, `docs`, `mcp`, `api`, `configure get`/`set` |
|
|
270
|
-
| `program.appConfig` | `src/
|
|
271
|
-
| `outputSchema` | `src/commands/status/
|
|
272
|
-
| Schemagen | `
|
|
270
|
+
| `program.appConfig` | `src/config/schema.ts` → `configSchema` from `__generated__/` |
|
|
271
|
+
| `outputSchema` | `src/commands/status/schema.ts` → `outputSchema` from `__generated__/` |
|
|
272
|
+
| Schemagen | `just schemagen` → `argsbarg schemagen` (justfile exports `node_modules/.bin` on `PATH`) |
|
|
273
273
|
| Command layout | `src/commands/<name>/command.ts`; registration in `src/program.ts` |
|
|
274
274
|
| MCP doc topics | `docs.topics` auto-exposed as `<key>://docs/<topic>` resources when docs + MCP enabled |
|
|
275
275
|
| Package import | `from "argsbarg"` (not relative to argsbarg `src/`) |
|
package/docs/api-server.md
CHANGED
|
@@ -134,7 +134,7 @@ All responses include wide-open CORS headers (`Access-Control-Allow-Origin: *`).
|
|
|
134
134
|
|
|
135
135
|
## OpenAPI
|
|
136
136
|
|
|
137
|
-
Call `generateOpenApi(program)` or `openApiJson(program)` from the package, fetch `GET /openapi.json` from a running server, or run `myapp docs openapi` / `myapp docs openapi --save` (writes `./docs/openapi.json` when `docs.enabled` and `apiServer.enabled`).
|
|
137
|
+
Call `generateOpenApi(program)` or `openApiJson(program)` from the package, fetch `GET /openapi.json` from a running server, or run `myapp docs openapi` / `myapp docs openapi --save` (writes `./docs/openapi.json` when `docs.enabled` and `apiServer.enabled`). Nested `inputSchema` / `outputSchema` `$ref` pointers are dereferenced when the OpenAPI document is built so API reference UIs can show nested request shapes.
|
|
138
138
|
|
|
139
139
|
## Complex tool inputs
|
|
140
140
|
|
package/docs/config-schema.md
CHANGED
|
@@ -136,39 +136,51 @@ Interactive `configure` does not persist values supplied only by env or `resolve
|
|
|
136
136
|
| **Omit `jsonSchema`** | Simple apps; all values stored as strings; use `entry.default` |
|
|
137
137
|
| **Codegen from TypeScript** | Typed config, nested objects, shared with JSON Schema CI |
|
|
138
138
|
|
|
139
|
-
## Recommended pipeline (
|
|
139
|
+
## Recommended pipeline (argsbarg schemagen)
|
|
140
140
|
|
|
141
141
|
Mirror the [output-schema.md](output-schema.md) pattern for config:
|
|
142
142
|
|
|
143
143
|
```mermaid
|
|
144
144
|
flowchart LR
|
|
145
|
-
subgraph types [
|
|
146
|
-
|
|
147
|
-
Marker["JSDoc contains Config schema"]
|
|
145
|
+
subgraph types [schema.ts]
|
|
146
|
+
Marker["export type configType = AppConfig"]
|
|
148
147
|
end
|
|
149
|
-
subgraph gen [
|
|
150
|
-
Script["
|
|
148
|
+
subgraph gen [argsbarg schemagen]
|
|
149
|
+
Script["argsbarg schemagen"]
|
|
151
150
|
Gen["ts-json-schema-generator"]
|
|
152
151
|
end
|
|
153
|
-
subgraph artifacts [
|
|
154
|
-
Json["
|
|
155
|
-
|
|
152
|
+
subgraph artifacts [Gitignored __generated__]
|
|
153
|
+
Json["configSchema.json"]
|
|
154
|
+
Index["index.ts"]
|
|
156
155
|
end
|
|
157
156
|
subgraph runtime [Runtime]
|
|
158
157
|
Program["program.appConfig.jsonSchema"]
|
|
159
158
|
Validate["argsbarg runtime subset validator"]
|
|
160
159
|
end
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
types --> Script --> Gen --> Json
|
|
161
|
+
Gen --> Index --> Program --> Validate
|
|
163
162
|
```
|
|
164
163
|
|
|
165
164
|
| Piece | Convention |
|
|
166
165
|
| --- | --- |
|
|
167
|
-
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) |
|
|
168
|
-
| Discovery |
|
|
169
|
-
| Artifacts |
|
|
166
|
+
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) (bundled with argsbarg) |
|
|
167
|
+
| Discovery | `export type configType = …` in `src/config/schema.ts` (type defined in same file) |
|
|
168
|
+
| Artifacts | `src/config/__generated__/` — gitignored; run `just schemagen` after clone |
|
|
170
169
|
| Consumer CI | Optional: `ajv` + `ajv-formats` against the same committed JSON (not an argsbarg runtime dep) |
|
|
171
170
|
|
|
171
|
+
Example:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// src/config/schema.ts
|
|
175
|
+
export interface AppConfig {
|
|
176
|
+
apiToken: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export type configType = AppConfig;
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Wire on the program root: `import { configSchema } from "./config/__generated__/index.ts"`.
|
|
183
|
+
|
|
172
184
|
### Supported AppConfig shapes (argsbarg runtime validator)
|
|
173
185
|
|
|
174
186
|
| Supported (v1) | Deferred |
|
|
@@ -210,7 +222,7 @@ Object/array/`$ref` properties require `--json` on `configure set` when comma-se
|
|
|
210
222
|
|
|
211
223
|
| Example | Role |
|
|
212
224
|
| --- | --- |
|
|
213
|
-
| [`examples/full-example/`](../examples/full-example/) | **Copy template** —
|
|
225
|
+
| [`examples/full-example/`](../examples/full-example/) | **Copy template** — `argsbarg schemagen`, `program.appConfig`, built-in `configure get`/`set` |
|
|
214
226
|
|
|
215
227
|
```bash
|
|
216
228
|
cd examples/full-example && just setup && just schemagen
|
package/docs/output-schema.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# Output schemas (`outputSchema`)
|
|
2
2
|
|
|
3
|
-
How to describe JSON stdout on leaf commands — and
|
|
3
|
+
How to describe JSON stdout on leaf commands — and the **argsbarg schemagen** pipeline used in production apps.
|
|
4
4
|
|
|
5
5
|
## Argsbarg contract
|
|
6
6
|
|
|
7
7
|
On **leaf commands**, set `outputSchema` to a JSON Schema object when the handler emits JSON (typically with `--json`, always for JSON-only commands, or on the MCP headless path).
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
|
-
import {
|
|
10
|
+
import { outputSchema } from "./__generated__/index.ts";
|
|
11
11
|
|
|
12
12
|
export const status = {
|
|
13
13
|
key: "status",
|
|
14
14
|
description: "Show environment status.",
|
|
15
|
-
outputSchema
|
|
15
|
+
outputSchema,
|
|
16
16
|
handler: async (ctx) => { /* writes JSON to stdout */ },
|
|
17
17
|
} satisfies CliLeaf;
|
|
18
18
|
```
|
|
@@ -23,8 +23,9 @@ export const status = {
|
|
|
23
23
|
| `myapp docs api` | Markdown per-command **Output** section |
|
|
24
24
|
| `myapp docs skill` | `reference.md` for agent skills |
|
|
25
25
|
| MCP `tools/list` | Optional `outputSchema` on each tool |
|
|
26
|
+
| HTTP `GET /openapi.json` | Response schema per tool |
|
|
26
27
|
|
|
27
|
-
**Not validated at runtime** — argsbarg does not parse or reject handler stdout against the schema today. The schema is documentation and MCP metadata.
|
|
28
|
+
**Not validated at runtime** — argsbarg does not parse or reject handler stdout against the schema today. The schema is documentation and MCP/HTTP metadata.
|
|
28
29
|
|
|
29
30
|
**Set on the leaf only** — not under `mcpTool` (legacy `mcpTool.outputSchema` still resolves but is deprecated).
|
|
30
31
|
|
|
@@ -41,124 +42,156 @@ See [cli-program.md — Structured stdout](cli-program.md#structured-stdout) for
|
|
|
41
42
|
|
|
42
43
|
Production CLIs with several JSON commands tend to use **codegen** so types, handlers, and schemas stay aligned.
|
|
43
44
|
|
|
44
|
-
##
|
|
45
|
+
## Schemagen pipeline (built into argsbarg)
|
|
45
46
|
|
|
46
|
-
No
|
|
47
|
+
No per-repo scripts to copy — run **`argsbarg schemagen`** (or `import { runSchemagen } from "argsbarg/schemagen"`).
|
|
48
|
+
|
|
49
|
+
Reference implementations: **sqsp-qa-manager-poc**, **sqsp-workspaces**, **sqsp-i18n-tools-poc**, **pdf-gen** (see each repo’s `docs/architecture.md` for which commands use which schema root).
|
|
47
50
|
|
|
48
51
|
```mermaid
|
|
49
52
|
flowchart LR
|
|
50
|
-
subgraph types [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
subgraph types [schema.ts]
|
|
54
|
+
Config["export type configType = AppConfig"]
|
|
55
|
+
Output["export type outputType = StatusJsonOutput"]
|
|
56
|
+
Input["export type inputType = ToolInput (optional)"]
|
|
54
57
|
end
|
|
55
|
-
subgraph gen [
|
|
56
|
-
Discover["
|
|
57
|
-
Script["scripts/generate-output-schemas.ts"]
|
|
58
|
+
subgraph gen [argsbarg schemagen]
|
|
59
|
+
Discover["discover schema.ts roots"]
|
|
58
60
|
Gen["ts-json-schema-generator"]
|
|
59
61
|
end
|
|
60
|
-
subgraph artifacts [
|
|
61
|
-
Json["
|
|
62
|
-
|
|
62
|
+
subgraph artifacts [Gitignored __generated__]
|
|
63
|
+
Json["configSchema.json / inputSchema.json / outputSchema.json"]
|
|
64
|
+
Index["index.ts re-exports"]
|
|
63
65
|
end
|
|
64
66
|
subgraph runtime [Runtime]
|
|
65
|
-
Leaves["
|
|
67
|
+
Leaves["import { outputSchema } from ./__generated__/index.ts"]
|
|
66
68
|
Docgen["just docgen"]
|
|
67
69
|
end
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Discover --> Script --> Gen --> Json
|
|
71
|
-
Script --> Bridge --> Leaves --> Docgen
|
|
70
|
+
types --> Discover --> Gen --> Json
|
|
71
|
+
Gen --> Index --> Leaves --> Docgen
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
| Piece | Convention |
|
|
75
75
|
| --- | --- |
|
|
76
|
-
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) (
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
76
|
+
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) (bundled as an argsbarg dependency) |
|
|
77
|
+
| Discovery | Walk `src/**/schema.ts`; generate from `export type outputType = …` / `inputType` / `configType` when the target type is **defined in that file** |
|
|
78
|
+
| Artifacts | `src/**/__generated__/` — gitignored; run schemagen after clone or when `schema.ts` changes |
|
|
79
|
+
| Invocation | `just schemagen` — justfile exports `node_modules/.bin` on `PATH` for local `argsbarg` |
|
|
80
80
|
| tsconfig | `"resolveJsonModule": true` |
|
|
81
|
-
| CI | `just check`: `schemagen` →
|
|
81
|
+
| CI | `just check`: `schemagen` → typecheck (no git diff on generated files) |
|
|
82
|
+
| Cleanup | Schemagen removes orphan `__generated__/` dirs and stale JSON when roots or kinds are removed |
|
|
82
83
|
| Docgen | `docgen` depends on `schemagen` so saved `./docs/api.md` and `./docs/cli-schema.json` are fresh |
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- `scripts/generate-output-schemas.ts` — generate JSON + rewrite the bridge
|
|
87
|
-
- `scripts/schemagen/discover-schema-roots.ts` — find roots and map names → filenames / export constants
|
|
88
|
-
- `scripts/schemagen/discover-schema-roots.test.ts` — lock discovery and naming per app
|
|
85
|
+
### Declaring a schema root
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
Put schema-facing interfaces in **`src/**/types.ts`** (e.g. `src/commands/status/types.ts`, `src/ui/runHeadless/types.ts`, `src/core/types.ts`). Add a JSDoc line containing **`JSON payload`** on the exported interface:
|
|
87
|
+
Put schema-facing interfaces in **`schema.ts`** next to the command (or in a shared module when several commands reuse one shape). Export a role alias:
|
|
93
88
|
|
|
94
89
|
```typescript
|
|
95
|
-
|
|
90
|
+
// src/commands/status/schema.ts
|
|
91
|
+
import type { WorkspaceStatus } from "./types.ts";
|
|
92
|
+
|
|
93
|
+
/** JSON stdout for `myapp status --json`. */
|
|
96
94
|
export interface StatusJsonOutput {
|
|
97
|
-
|
|
95
|
+
workspaces: WorkspaceStatus[];
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
/**
|
|
98
|
+
/** Schemagen root for leaf outputSchema. */
|
|
99
|
+
export type outputType = StatusJsonOutput;
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// src/ui/runHeadless/schema.ts — shared by many mutating commands
|
|
104
|
+
import type { HeadlessTaskResult } from "./types.ts";
|
|
105
|
+
|
|
101
106
|
export interface HeadlessOpResult {
|
|
102
107
|
command: string;
|
|
103
108
|
exitCode: number;
|
|
104
109
|
tasks: HeadlessTaskResult[];
|
|
105
110
|
}
|
|
111
|
+
|
|
112
|
+
export type outputType = HeadlessOpResult;
|
|
106
113
|
```
|
|
107
114
|
|
|
108
|
-
|
|
115
|
+
```typescript
|
|
116
|
+
// src/commands/render-invoice/schema.ts — custom HTTP/MCP body (pdf-gen)
|
|
117
|
+
export interface RenderInvoiceToolInput {
|
|
118
|
+
format: "pdf" | "html";
|
|
119
|
+
invoice: InvoiceData;
|
|
120
|
+
}
|
|
109
121
|
|
|
110
|
-
|
|
122
|
+
export type inputType = RenderInvoiceToolInput;
|
|
123
|
+
export type outputType = RenderInvoiceWrittenOutput;
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
| Export | Role |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| `export type configType = AppConfig` | `program.appConfig.jsonSchema` (one per repo, typically `src/config/schema.ts`) |
|
|
129
|
+
| `export type outputType = …` | `leaf.outputSchema` |
|
|
130
|
+
| `export type inputType = …` | `leaf.inputSchema` (only when the tool body is not flat CLI flags) |
|
|
111
131
|
|
|
112
|
-
|
|
132
|
+
**Domain helpers** stay in `types.ts` (or `core/types.ts`). Discovery scans only `schema.ts`. Re-export-only files (`export type outputType = HeadlessOpResult` pointing at another module) are **not** generation roots — generate once from the canonical definition file.
|
|
113
133
|
|
|
114
|
-
|
|
115
|
-
| --- | --- | --- | --- |
|
|
116
|
-
| `JsonOutput` | `StatusJsonOutput` | `status.json` | `STATUS_JSON_OUTPUT_SCHEMA` |
|
|
117
|
-
| `OpResult` | `HeadlessOpResult` | `headless-op-result.json` | `HEADLESS_OP_RESULT_OUTPUT_SCHEMA` |
|
|
118
|
-
| `Output` | `OpenUrlOutput` | `open-url.json` | `OPEN_URL_OUTPUT_SCHEMA` |
|
|
119
|
-
| `Result` | `UidsResult` | `uids.json` | `UIDS_OUTPUT_SCHEMA` |
|
|
134
|
+
Commands without structured JSON omit `schema.ts`. Shared shapes (e.g. `HeadlessOpResult`) live in one canonical `schema.ts`; other commands import `{ outputSchema }` from that module’s `__generated__/index.ts`.
|
|
120
135
|
|
|
121
|
-
|
|
136
|
+
When you do **not** set `inputSchema`, argsbarg builds tool input from CLI `options` + `positionals`.
|
|
122
137
|
|
|
123
|
-
### Generated
|
|
138
|
+
### Generated artifacts
|
|
124
139
|
|
|
125
|
-
`
|
|
140
|
+
Schemagen writes under `__generated__/` beside each `schema.ts`:
|
|
141
|
+
|
|
142
|
+
| Kind | Generated file | Exported const (from `__generated__/index.ts`) |
|
|
143
|
+
| --- | --- | --- |
|
|
144
|
+
| config | `configSchema.json` | `configSchema` |
|
|
145
|
+
| output | `outputSchema.json` | `outputSchema` |
|
|
146
|
+
| input | `inputSchema.json` | `inputSchema` |
|
|
147
|
+
|
|
148
|
+
Wire on the leaf:
|
|
126
149
|
|
|
127
150
|
```typescript
|
|
128
|
-
|
|
151
|
+
import { outputSchema } from "./__generated__/index.ts";
|
|
129
152
|
|
|
130
|
-
|
|
153
|
+
export const statusCommand = {
|
|
154
|
+
outputSchema,
|
|
155
|
+
// …
|
|
156
|
+
} satisfies CliLeaf;
|
|
157
|
+
```
|
|
131
158
|
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
Shared mutators:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { outputSchema } from "../../../ui/runHeadless/__generated__/index.ts";
|
|
134
163
|
```
|
|
135
164
|
|
|
136
|
-
|
|
165
|
+
App config:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { configSchema } from "./config/__generated__/index.ts";
|
|
169
|
+
|
|
170
|
+
appConfig: { jsonSchema: configSchema, entries: { … } },
|
|
171
|
+
```
|
|
137
172
|
|
|
138
173
|
## Schema-facing types
|
|
139
174
|
|
|
140
175
|
**Goal:** generated schemas match what handlers actually print, with descriptions agents can read in `docs api`.
|
|
141
176
|
|
|
142
|
-
1. **Schema roots** — `export interface` in
|
|
177
|
+
1. **Schema roots** — `export interface` in `schema.ts`, with `export type outputType = …` (or `inputType` / `configType`).
|
|
143
178
|
2. **Per property** — `/** … */` on every field that should appear in JSON Schema `properties` (including nested named types).
|
|
144
179
|
3. **Unions / enums** — document the alias; generator emits `enum` / `anyOf` with type-level description.
|
|
145
180
|
4. **Formats** — property JSDoc can include `@format date-time` for ISO timestamps; add a smoke test that the generated property has `format: "date-time"`.
|
|
146
|
-
5. **Do not hand-edit** `
|
|
181
|
+
5. **Do not hand-edit** `__generated__/` — change types/JSDoc in `schema.ts`, run `just schemagen`.
|
|
147
182
|
|
|
148
183
|
### Narrowing when runtime ≠ stdout
|
|
149
184
|
|
|
150
|
-
When a shared runtime type is **wider** than one command’s JSON, add a **schema-facing** root in `
|
|
185
|
+
When a shared runtime type is **wider** than one command’s JSON, add a **schema-facing** root in `schema.ts`:
|
|
151
186
|
|
|
152
187
|
```typescript
|
|
153
|
-
/**
|
|
154
|
-
export type ResultSource = TranslationReadinessSource | { kind: "uids"; uids: string[] };
|
|
155
|
-
|
|
156
|
-
/** JSON payload for `myapp pr` and `myapp file`. */
|
|
188
|
+
/** JSON stdout for `myapp pr` and `myapp file`. */
|
|
157
189
|
export interface TranslationReadinessResult {
|
|
158
190
|
source: TranslationReadinessSource;
|
|
159
191
|
evaluatedAt: string;
|
|
160
|
-
// ...
|
|
161
192
|
}
|
|
193
|
+
|
|
194
|
+
export type outputType = TranslationReadinessResult;
|
|
162
195
|
```
|
|
163
196
|
|
|
164
197
|
Patterns:
|
|
@@ -170,33 +203,32 @@ Handlers keep using runtime types; only discovered roots (and their type graph)
|
|
|
170
203
|
|
|
171
204
|
## Tests
|
|
172
205
|
|
|
173
|
-
|
|
206
|
+
In argsbarg: `src/cli-tool/schemagen/schemagen.test.ts` locks discovery and generation against `examples/full-example/`.
|
|
207
|
+
|
|
208
|
+
Per consumer repo (optional):
|
|
174
209
|
|
|
175
|
-
- **`
|
|
176
|
-
- **`src/schemas/outputSchemas.test.ts`** (optional) — schema shape smoke tests: object root, key `description` fields, enums, `@format date-time`.
|
|
210
|
+
- **`src/generated-schemas.test.ts`** — smoke-test that key `outputSchema` objects have expected shape.
|
|
177
211
|
|
|
178
212
|
## Contributor workflow
|
|
179
213
|
|
|
180
|
-
1. Add or edit schema
|
|
181
|
-
2. `just schemagen` — refresh `src
|
|
182
|
-
3. Import
|
|
183
|
-
4.
|
|
184
|
-
5.
|
|
185
|
-
6. Document which commands use which roots in **your** `docs/architecture.md` (argsbarg does not maintain per-app tables).
|
|
214
|
+
1. Add or edit schema roots in `src/**/schema.ts` with `outputType` / `inputType` / `configType` and per-field JSDoc.
|
|
215
|
+
2. `just schemagen` — refresh `src/**/__generated__/`.
|
|
216
|
+
3. Import `{ outputSchema }` / `{ inputSchema }` / `{ configSchema }` from the relevant `__generated__/index.ts`.
|
|
217
|
+
4. `just docgen` / `myapp docs api --save` — refresh consumer docs.
|
|
218
|
+
5. Document which commands use which roots in **your** `docs/architecture.md` (argsbarg does not maintain per-app tables).
|
|
186
219
|
|
|
187
|
-
Add a bullet under your app’s `**… conventions:**` block in `.cursor/rules/cli-program.mdc` pointing at `node_modules/argsbarg/docs/output-schema.md
|
|
220
|
+
Add a bullet under your app’s `**… conventions:**` block in `.cursor/rules/cli-program.mdc` pointing at `node_modules/argsbarg/docs/output-schema.md`.
|
|
188
221
|
|
|
189
|
-
**Reference implementation:** [`examples/full-example/`](../examples/full-example/) in this repo
|
|
222
|
+
**Reference implementation:** [`examples/full-example/`](../examples/full-example/) in this repo — `schema.ts` roots, `__generated__/`, and `status` leaf with `outputSchema`.
|
|
190
223
|
|
|
191
224
|
## Out of scope
|
|
192
225
|
|
|
193
|
-
- Shared codegen package or monorepo tooling
|
|
194
226
|
- Runtime Zod / `.parse()` on stdout in argsbarg
|
|
195
227
|
- `outputSchema` for plain-text, streaming, or Ink-only commands
|
|
196
|
-
- Schema roots outside `src/**/types.ts` (use a dedicated `types.ts` next to handlers instead of `resolve.ts`)
|
|
197
228
|
|
|
198
229
|
## See also
|
|
199
230
|
|
|
231
|
+
- [config-schema.md](config-schema.md) — `configType` / `program.appConfig`
|
|
200
232
|
- [cli-program.md](cli-program.md) — structured stdout, headless JSON, `read*Flags`
|
|
201
233
|
- [mcp.md](mcp.md) — `tools/list`, `structuredContent`
|
|
202
234
|
- [bundled-docs.md](bundled-docs.md) — `docs api` / `docs cli-schema` docgen
|
|
@@ -9,7 +9,7 @@ From a git checkout at this directory (requires [Homebrew](https://brew.sh), [ju
|
|
|
9
9
|
```bash
|
|
10
10
|
brew install just bun
|
|
11
11
|
just setup
|
|
12
|
-
just schemagen # after changing src/**/
|
|
12
|
+
just schemagen # after changing src/**/schema.ts
|
|
13
13
|
just run status --json
|
|
14
14
|
just run docs readme
|
|
15
15
|
```
|
|
@@ -60,14 +60,15 @@ just test-release
|
|
|
60
60
|
|
|
61
61
|
Undo a local dev install: `just uninstall` (formula + agent artifacts; app config removed by formula `uninstall`), `just uninstall-config` (app config only, without uninstalling the formula).
|
|
62
62
|
|
|
63
|
-
## Schemagen
|
|
63
|
+
## Schemagen roots
|
|
64
64
|
|
|
65
|
-
|
|
|
66
|
-
| --- | --- |
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
65
|
+
| Export in `schema.ts` | Generated artifact | Import on leaf / program |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| `export type configType = …` | `__generated__/configSchema.json` | `{ configSchema }` from `config/__generated__/index.ts` → `program.appConfig.jsonSchema` |
|
|
68
|
+
| `export type outputType = …` | `__generated__/outputSchema.json` | `{ outputSchema }` from `__generated__/index.ts` → `leaf.outputSchema` |
|
|
69
|
+
| `export type inputType = …` | `__generated__/inputSchema.json` | `{ inputSchema }` from `__generated__/index.ts` → `leaf.inputSchema` |
|
|
69
70
|
|
|
70
|
-
Discovery walks `src/**/
|
|
71
|
+
Discovery walks `src/**/schema.ts` only. Domain helpers stay in sibling `types.ts`. `__generated__/` is gitignored — run `argsbarg schemagen` (via `just schemagen` or `just setup`).
|
|
71
72
|
|
|
72
73
|
## Consumer docs
|
|
73
74
|
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@biomejs/biome": "^2.5.0",
|
|
12
12
|
"@types/bun": "^1.3.12",
|
|
13
|
-
"ts-json-schema-generator": "^2.3.0",
|
|
14
13
|
"typescript": "^5.9.3",
|
|
15
14
|
},
|
|
16
15
|
},
|
|
@@ -36,40 +35,12 @@
|
|
|
36
35
|
|
|
37
36
|
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
|
38
37
|
|
|
39
|
-
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
|
40
|
-
|
|
41
38
|
"@types/node": ["@types/node@26.0.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA=="],
|
|
42
39
|
|
|
43
40
|
"argsbarg": ["argsbarg@file:../..", { "devDependencies": { "@biomejs/biome": "^2.5.0", "@types/bun": "^1.3.12", "typescript": "^5.9.3" }, "bin": { "argsbarg": "src/index.ts" } }],
|
|
44
41
|
|
|
45
|
-
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
|
46
|
-
|
|
47
|
-
"brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
|
48
|
-
|
|
49
42
|
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
|
50
43
|
|
|
51
|
-
"commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
|
|
52
|
-
|
|
53
|
-
"glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
|
54
|
-
|
|
55
|
-
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
|
56
|
-
|
|
57
|
-
"lru-cache": ["lru-cache@11.5.1", "", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="],
|
|
58
|
-
|
|
59
|
-
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
|
60
|
-
|
|
61
|
-
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
|
62
|
-
|
|
63
|
-
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
|
64
|
-
|
|
65
|
-
"path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
|
66
|
-
|
|
67
|
-
"safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
|
|
68
|
-
|
|
69
|
-
"ts-json-schema-generator": ["ts-json-schema-generator@2.9.0", "", { "dependencies": { "@types/json-schema": "^7.0.15", "commander": "^14.0.3", "glob": "^13.0.6", "json5": "^2.2.3", "normalize-path": "^3.0.0", "safe-stable-stringify": "^2.5.0", "tslib": "^2.8.1", "typescript": "^5.9.3" }, "bin": { "ts-json-schema-generator": "bin/ts-json-schema-generator.js" } }, "sha512-NR5ZE108uiPtBHBJNGnhwoUaUx5vWTDJzDFG9YlRoqxPU76n+5FClRh92dcGgysbe1smRmYalM9Saj97GW1J4Q=="],
|
|
70
|
-
|
|
71
|
-
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
72
|
-
|
|
73
44
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
74
45
|
|
|
75
46
|
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
set shell := ["bash", "-eu", "-o", "pipefail", "-c"]
|
|
2
2
|
|
|
3
|
+
export PATH := justfile_directory() + "/node_modules/.bin:" + env_var("PATH")
|
|
4
|
+
|
|
3
5
|
cli_key := `bun scripts/print-identity.ts key`
|
|
4
6
|
tap_org := `bun scripts/print-identity.ts tapOrg`
|
|
5
7
|
tap_repo := `bun scripts/print-identity.ts tapRepo`
|
|
@@ -19,9 +21,8 @@ build:
|
|
|
19
21
|
bun build ./src/index.ts --compile --outfile=dist/{{cli_key}}
|
|
20
22
|
@rm -f .*.bun-build
|
|
21
23
|
|
|
22
|
-
# Run schemagen,
|
|
24
|
+
# Run schemagen, typecheck, and format
|
|
23
25
|
check: schemagen format typecheck
|
|
24
|
-
git diff --exit-code schemas/
|
|
25
26
|
|
|
26
27
|
# Run the CLI from source with optional args; restarts on file changes
|
|
27
28
|
dev *ARGS:
|
|
@@ -84,11 +85,13 @@ run *ARGS:
|
|
|
84
85
|
|
|
85
86
|
# Generate JSON Schema artifacts from TypeScript types
|
|
86
87
|
schemagen:
|
|
87
|
-
|
|
88
|
+
argsbarg schemagen
|
|
88
89
|
|
|
89
90
|
# Install bun/npm dependencies
|
|
91
|
+
# Install bun/npm dependencies and generate schemas
|
|
90
92
|
setup:
|
|
91
93
|
bun install
|
|
94
|
+
just schemagen
|
|
92
95
|
|
|
93
96
|
# Run unit tests (after check)
|
|
94
97
|
test: check
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"biome": "biome",
|
|
12
|
-
"schemagen": "bun run scripts/schemagen.ts",
|
|
13
12
|
"start": "bun run src/index.ts"
|
|
14
13
|
},
|
|
15
14
|
"dependencies": {
|
|
@@ -18,7 +17,6 @@
|
|
|
18
17
|
"devDependencies": {
|
|
19
18
|
"@biomejs/biome": "^2.5.0",
|
|
20
19
|
"@types/bun": "^1.3.12",
|
|
21
|
-
"ts-json-schema-generator": "^2.3.0",
|
|
22
20
|
"typescript": "^5.9.3"
|
|
23
21
|
}
|
|
24
22
|
}
|
|
@@ -3,7 +3,7 @@ Status leaf — demonstrates outputSchema and ctx.appConfig.
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { type CliLeaf, CliOptionKind } from "argsbarg";
|
|
6
|
-
import {
|
|
6
|
+
import { outputSchema } from "./__generated__/index.ts";
|
|
7
7
|
import type { StatusJsonOutput } from "./types.ts";
|
|
8
8
|
|
|
9
9
|
export const statusCommand = {
|
|
@@ -16,7 +16,7 @@ export const statusCommand = {
|
|
|
16
16
|
kind: CliOptionKind.Presence,
|
|
17
17
|
},
|
|
18
18
|
],
|
|
19
|
-
outputSchema
|
|
19
|
+
outputSchema,
|
|
20
20
|
handler: (ctx) => {
|
|
21
21
|
const out: StatusJsonOutput = {
|
|
22
22
|
defaultRegion: ctx.appConfig.get("defaultRegion") as string | undefined,
|