argsbarg 6.0.1 → 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 +14 -2
- package/README.md +3 -3
- package/docs/config-schema.md +15 -13
- package/docs/output-schema.md +67 -66
- package/examples/full-example/README.md +7 -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/src/commands/status/command.ts +2 -2
- package/examples/full-example/src/commands/status/types.ts +1 -1
- package/examples/full-example/src/config/__generated__/index.ts +5 -0
- package/examples/full-example/src/program.ts +4 -4
- package/package.json +8 -1
- 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/{examples/full-example/scripts → src/cli-tool}/schemagen/discover-schema-roots.ts +13 -58
- 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/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/naming.ts +0 -99
- package/examples/full-example/scripts/schemagen.ts +0 -91
- /package/examples/full-example/{schemas/generated/status.json → src/commands/status/__generated__/outputSchema.json} +0 -0
- /package/examples/full-example/src/commands/status/{schema-types.ts → schema.ts} +0 -0
- /package/examples/full-example/{schemas/generated/app-config.json → src/config/__generated__/configSchema.json} +0 -0
- /package/examples/full-example/src/config/{schema-types.ts → schema.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ 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
|
+
|
|
10
21
|
## [6.0.1] - 2026-07-22
|
|
11
22
|
|
|
12
23
|
### Added
|
|
@@ -15,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
26
|
|
|
16
27
|
### Changed
|
|
17
28
|
|
|
18
|
-
- **
|
|
29
|
+
- **Colocated schemagen** — `*.schema.json` beside each `schema-types.ts`; exports `configSchema` / `inputSchema` / `outputSchema` (replaces central `*Schemas.ts` bridges).
|
|
19
30
|
- **HTTP tool errors** — return a plain `{ "error": "..." }` JSON body without ANSI color codes or appended CLI help text.
|
|
20
31
|
- **`cliErrWithHelp`** — on `api` / `mcp` invocations, throws a plain error instead of printing contextual help.
|
|
21
32
|
- **`GET /openapi-browser`** — Scalar config preserves schema property order from the OpenAPI document (`orderSchemaPropertiesBy: "preserve"`).
|
|
@@ -728,7 +739,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
|
728
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`).
|
|
729
740
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
730
741
|
|
|
731
|
-
[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
|
|
732
744
|
[6.0.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.1
|
|
733
745
|
[6.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.0
|
|
734
746
|
[5.1.16]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.16
|
package/README.md
CHANGED
|
@@ -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/config/schema
|
|
271
|
-
| `outputSchema` | `src/commands/status/schema
|
|
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/config-schema.md
CHANGED
|
@@ -136,42 +136,42 @@ 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 [schema
|
|
145
|
+
subgraph types [schema.ts]
|
|
146
146
|
Marker["export type configType = AppConfig"]
|
|
147
147
|
end
|
|
148
|
-
subgraph gen [
|
|
149
|
-
Script["
|
|
148
|
+
subgraph gen [argsbarg schemagen]
|
|
149
|
+
Script["argsbarg schemagen"]
|
|
150
150
|
Gen["ts-json-schema-generator"]
|
|
151
151
|
end
|
|
152
|
-
subgraph artifacts [
|
|
153
|
-
Json["
|
|
154
|
-
|
|
152
|
+
subgraph artifacts [Gitignored __generated__]
|
|
153
|
+
Json["configSchema.json"]
|
|
154
|
+
Index["index.ts"]
|
|
155
155
|
end
|
|
156
156
|
subgraph runtime [Runtime]
|
|
157
157
|
Program["program.appConfig.jsonSchema"]
|
|
158
158
|
Validate["argsbarg runtime subset validator"]
|
|
159
159
|
end
|
|
160
160
|
types --> Script --> Gen --> Json
|
|
161
|
-
|
|
161
|
+
Gen --> Index --> Program --> Validate
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
| Piece | Convention |
|
|
165
165
|
| --- | --- |
|
|
166
|
-
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) |
|
|
167
|
-
| Discovery | `export type configType = …` in `src/config/schema
|
|
168
|
-
| 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 |
|
|
169
169
|
| Consumer CI | Optional: `ajv` + `ajv-formats` against the same committed JSON (not an argsbarg runtime dep) |
|
|
170
170
|
|
|
171
171
|
Example:
|
|
172
172
|
|
|
173
173
|
```typescript
|
|
174
|
-
// src/config/schema
|
|
174
|
+
// src/config/schema.ts
|
|
175
175
|
export interface AppConfig {
|
|
176
176
|
apiToken: string;
|
|
177
177
|
}
|
|
@@ -179,6 +179,8 @@ export interface AppConfig {
|
|
|
179
179
|
export type configType = AppConfig;
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
+
Wire on the program root: `import { configSchema } from "./config/__generated__/index.ts"`.
|
|
183
|
+
|
|
182
184
|
### Supported AppConfig shapes (argsbarg runtime validator)
|
|
183
185
|
|
|
184
186
|
| Supported (v1) | Deferred |
|
|
@@ -220,7 +222,7 @@ Object/array/`$ref` properties require `--json` on `configure set` when comma-se
|
|
|
220
222
|
|
|
221
223
|
| Example | Role |
|
|
222
224
|
| --- | --- |
|
|
223
|
-
| [`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` |
|
|
224
226
|
|
|
225
227
|
```bash
|
|
226
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
|
```
|
|
@@ -42,56 +42,52 @@ See [cli-program.md — Structured stdout](cli-program.md#structured-stdout) for
|
|
|
42
42
|
|
|
43
43
|
Production CLIs with several JSON commands tend to use **codegen** so types, handlers, and schemas stay aligned.
|
|
44
44
|
|
|
45
|
-
##
|
|
45
|
+
## Schemagen pipeline (built into argsbarg)
|
|
46
46
|
|
|
47
|
-
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).
|
|
48
50
|
|
|
49
51
|
```mermaid
|
|
50
52
|
flowchart LR
|
|
51
|
-
subgraph types [schema
|
|
53
|
+
subgraph types [schema.ts]
|
|
52
54
|
Config["export type configType = AppConfig"]
|
|
53
55
|
Output["export type outputType = StatusJsonOutput"]
|
|
54
56
|
Input["export type inputType = ToolInput (optional)"]
|
|
55
57
|
end
|
|
56
|
-
subgraph gen [
|
|
57
|
-
Discover["discover
|
|
58
|
-
Script["schemagen.ts / generate-output-schemas.ts"]
|
|
58
|
+
subgraph gen [argsbarg schemagen]
|
|
59
|
+
Discover["discover schema.ts roots"]
|
|
59
60
|
Gen["ts-json-schema-generator"]
|
|
60
61
|
end
|
|
61
|
-
subgraph artifacts [
|
|
62
|
-
Json["
|
|
63
|
-
|
|
62
|
+
subgraph artifacts [Gitignored __generated__]
|
|
63
|
+
Json["configSchema.json / inputSchema.json / outputSchema.json"]
|
|
64
|
+
Index["index.ts re-exports"]
|
|
64
65
|
end
|
|
65
66
|
subgraph runtime [Runtime]
|
|
66
|
-
Leaves["
|
|
67
|
+
Leaves["import { outputSchema } from ./__generated__/index.ts"]
|
|
67
68
|
Docgen["just docgen"]
|
|
68
69
|
end
|
|
69
|
-
types --> Discover -->
|
|
70
|
-
|
|
70
|
+
types --> Discover --> Gen --> Json
|
|
71
|
+
Gen --> Index --> Leaves --> Docgen
|
|
71
72
|
```
|
|
72
73
|
|
|
73
74
|
| Piece | Convention |
|
|
74
75
|
| --- | --- |
|
|
75
|
-
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) (
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
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` |
|
|
79
80
|
| tsconfig | `"resolveJsonModule": true` |
|
|
80
|
-
| 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 |
|
|
81
83
|
| Docgen | `docgen` depends on `schemagen` so saved `./docs/api.md` and `./docs/cli-schema.json` are fresh |
|
|
82
84
|
|
|
83
|
-
Copy these scripts into each consumer repo (they are intentionally duplicated, not published):
|
|
84
|
-
|
|
85
|
-
- `scripts/schemagen.ts` or `scripts/generate-output-schemas.ts` — generate JSON + rewrite bridges
|
|
86
|
-
- `scripts/schemagen/discover-schema-roots.ts` — find roots and map names → filenames / export constants
|
|
87
|
-
- `scripts/schemagen/discover-schema-roots.test.ts` — lock discovery and naming per app
|
|
88
|
-
|
|
89
85
|
### Declaring a schema root
|
|
90
86
|
|
|
91
|
-
Put schema-facing interfaces in **`schema
|
|
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:
|
|
92
88
|
|
|
93
89
|
```typescript
|
|
94
|
-
// src/commands/status/schema
|
|
90
|
+
// src/commands/status/schema.ts
|
|
95
91
|
import type { WorkspaceStatus } from "./types.ts";
|
|
96
92
|
|
|
97
93
|
/** JSON stdout for `myapp status --json`. */
|
|
@@ -104,7 +100,7 @@ export type outputType = StatusJsonOutput;
|
|
|
104
100
|
```
|
|
105
101
|
|
|
106
102
|
```typescript
|
|
107
|
-
// src/ui/runHeadless/schema
|
|
103
|
+
// src/ui/runHeadless/schema.ts — shared by many mutating commands
|
|
108
104
|
import type { HeadlessTaskResult } from "./types.ts";
|
|
109
105
|
|
|
110
106
|
export interface HeadlessOpResult {
|
|
@@ -117,7 +113,7 @@ export type outputType = HeadlessOpResult;
|
|
|
117
113
|
```
|
|
118
114
|
|
|
119
115
|
```typescript
|
|
120
|
-
// src/commands/render-invoice/schema
|
|
116
|
+
// src/commands/render-invoice/schema.ts — custom HTTP/MCP body (pdf-gen)
|
|
121
117
|
export interface RenderInvoiceToolInput {
|
|
122
118
|
format: "pdf" | "html";
|
|
123
119
|
invoice: InvoiceData;
|
|
@@ -129,58 +125,64 @@ export type outputType = RenderInvoiceWrittenOutput;
|
|
|
129
125
|
|
|
130
126
|
| Export | Role |
|
|
131
127
|
| --- | --- |
|
|
132
|
-
| `export type configType = AppConfig` | `program.appConfig.jsonSchema` (one per repo, typically `src/config/schema
|
|
128
|
+
| `export type configType = AppConfig` | `program.appConfig.jsonSchema` (one per repo, typically `src/config/schema.ts`) |
|
|
133
129
|
| `export type outputType = …` | `leaf.outputSchema` |
|
|
134
130
|
| `export type inputType = …` | `leaf.inputSchema` (only when the tool body is not flat CLI flags) |
|
|
135
131
|
|
|
136
|
-
**Domain helpers** stay in `types.ts` (or `core/types.ts`). Discovery scans only `schema
|
|
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.
|
|
137
133
|
|
|
138
|
-
Commands without structured JSON omit `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`.
|
|
139
135
|
|
|
140
136
|
When you do **not** set `inputSchema`, argsbarg builds tool input from CLI `options` + `positionals`.
|
|
141
137
|
|
|
142
|
-
###
|
|
138
|
+
### Generated artifacts
|
|
143
139
|
|
|
144
|
-
|
|
140
|
+
Schemagen writes under `__generated__/` beside each `schema.ts`:
|
|
145
141
|
|
|
146
|
-
|
|
|
147
|
-
| --- | --- | --- |
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
| `Result` | `PrResult` | `pr.json` | `PR_RESULT_OUTPUT_SCHEMA` |
|
|
152
|
-
| `ToolInput` | `RenderInvoiceToolInput` | `render-invoice-tool-input.json` | `RENDER_INVOICE_TOOL_INPUT_SCHEMA` |
|
|
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` |
|
|
153
147
|
|
|
154
|
-
|
|
148
|
+
Wire on the leaf:
|
|
155
149
|
|
|
156
|
-
|
|
150
|
+
```typescript
|
|
151
|
+
import { outputSchema } from "./__generated__/index.ts";
|
|
152
|
+
|
|
153
|
+
export const statusCommand = {
|
|
154
|
+
outputSchema,
|
|
155
|
+
// …
|
|
156
|
+
} satisfies CliLeaf;
|
|
157
|
+
```
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
Shared mutators:
|
|
159
160
|
|
|
160
161
|
```typescript
|
|
161
|
-
|
|
162
|
+
import { outputSchema } from "../../../ui/runHeadless/__generated__/index.ts";
|
|
163
|
+
```
|
|
162
164
|
|
|
163
|
-
|
|
165
|
+
App config:
|
|
164
166
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
```
|
|
167
|
+
```typescript
|
|
168
|
+
import { configSchema } from "./config/__generated__/index.ts";
|
|
168
169
|
|
|
169
|
-
|
|
170
|
+
appConfig: { jsonSchema: configSchema, entries: { … } },
|
|
171
|
+
```
|
|
170
172
|
|
|
171
173
|
## Schema-facing types
|
|
172
174
|
|
|
173
175
|
**Goal:** generated schemas match what handlers actually print, with descriptions agents can read in `docs api`.
|
|
174
176
|
|
|
175
|
-
1. **Schema roots** — `export interface` in `schema
|
|
177
|
+
1. **Schema roots** — `export interface` in `schema.ts`, with `export type outputType = …` (or `inputType` / `configType`).
|
|
176
178
|
2. **Per property** — `/** … */` on every field that should appear in JSON Schema `properties` (including nested named types).
|
|
177
179
|
3. **Unions / enums** — document the alias; generator emits `enum` / `anyOf` with type-level description.
|
|
178
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"`.
|
|
179
|
-
5. **Do not hand-edit** `
|
|
181
|
+
5. **Do not hand-edit** `__generated__/` — change types/JSDoc in `schema.ts`, run `just schemagen`.
|
|
180
182
|
|
|
181
183
|
### Narrowing when runtime ≠ stdout
|
|
182
184
|
|
|
183
|
-
When a shared runtime type is **wider** than one command’s JSON, add a **schema-facing** root in `schema
|
|
185
|
+
When a shared runtime type is **wider** than one command’s JSON, add a **schema-facing** root in `schema.ts`:
|
|
184
186
|
|
|
185
187
|
```typescript
|
|
186
188
|
/** JSON stdout for `myapp pr` and `myapp file`. */
|
|
@@ -201,27 +203,26 @@ Handlers keep using runtime types; only discovered roots (and their type graph)
|
|
|
201
203
|
|
|
202
204
|
## Tests
|
|
203
205
|
|
|
204
|
-
|
|
206
|
+
In argsbarg: `src/cli-tool/schemagen/schemagen.test.ts` locks discovery and generation against `examples/full-example/`.
|
|
207
|
+
|
|
208
|
+
Per consumer repo (optional):
|
|
205
209
|
|
|
206
|
-
- **`
|
|
207
|
-
- **`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.
|
|
208
211
|
|
|
209
212
|
## Contributor workflow
|
|
210
213
|
|
|
211
|
-
1. Add or edit schema roots in `src/**/schema
|
|
212
|
-
2. `just schemagen` — refresh `
|
|
213
|
-
3. Import
|
|
214
|
-
4.
|
|
215
|
-
5.
|
|
216
|
-
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).
|
|
217
219
|
|
|
218
|
-
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`.
|
|
219
221
|
|
|
220
|
-
**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`.
|
|
221
223
|
|
|
222
224
|
## Out of scope
|
|
223
225
|
|
|
224
|
-
- Shared codegen package or monorepo tooling
|
|
225
226
|
- Runtime Zod / `.parse()` on stdout in argsbarg
|
|
226
227
|
- `outputSchema` for plain-text, streaming, or Ink-only commands
|
|
227
228
|
|
|
@@ -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/**/schema
|
|
12
|
+
just schemagen # after changing src/**/schema.ts
|
|
13
13
|
just run status --json
|
|
14
14
|
just run docs readme
|
|
15
15
|
```
|
|
@@ -62,13 +62,13 @@ Undo a local dev install: `just uninstall` (formula + agent artifacts; app confi
|
|
|
62
62
|
|
|
63
63
|
## Schemagen roots
|
|
64
64
|
|
|
65
|
-
| Export in `schema
|
|
66
|
-
| --- | --- |
|
|
67
|
-
| `export type configType = …` | `
|
|
68
|
-
| `export type outputType = …` | `
|
|
69
|
-
| `export type inputType = …` | `
|
|
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` |
|
|
70
70
|
|
|
71
|
-
Discovery walks `src/**/schema
|
|
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`).
|
|
72
72
|
|
|
73
73
|
## Consumer docs
|
|
74
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,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { StatusJsonOutput } from "./schema
|
|
1
|
+
export type { StatusJsonOutput } from "./schema.ts";
|
|
@@ -4,12 +4,12 @@ Kitchen-sink CliProgram — every argsbarg builtin enabled; command registration
|
|
|
4
4
|
|
|
5
5
|
import type { CliAppConfig, CliAppConfigEntry, CliProgram } from "argsbarg";
|
|
6
6
|
import readmeText from "../README.md" with { type: "text" };
|
|
7
|
-
import {
|
|
7
|
+
import { configSchema } from "./config/__generated__/index.ts";
|
|
8
8
|
import { createIdentity } from "../scripts/create-identity.ts";
|
|
9
9
|
import { echoCommand } from "./commands/echo/command.ts";
|
|
10
10
|
import { statusCommand } from "./commands/status/command.ts";
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const configEntries = {
|
|
13
13
|
apiToken: {
|
|
14
14
|
description: "Create at https://example.com/settings/tokens",
|
|
15
15
|
env: `${createIdentity.envPrefix}_API_TOKEN`,
|
|
@@ -34,8 +34,8 @@ export const program = {
|
|
|
34
34
|
version: "1.0.0",
|
|
35
35
|
description: createIdentity.desc,
|
|
36
36
|
appConfig: {
|
|
37
|
-
jsonSchema:
|
|
38
|
-
entries:
|
|
37
|
+
jsonSchema: configSchema,
|
|
38
|
+
entries: configEntries,
|
|
39
39
|
} satisfies CliAppConfig,
|
|
40
40
|
docs: {
|
|
41
41
|
enabled: true,
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "argsbarg",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"main": "./src/index.ts",
|
|
5
5
|
"module": "./src/index.ts",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"ts-json-schema-generator": "^2.3.0"
|
|
8
|
+
},
|
|
6
9
|
"devDependencies": {
|
|
7
10
|
"@biomejs/biome": "^2.5.0",
|
|
8
11
|
"@types/bun": "^1.3.12",
|
|
@@ -13,6 +16,10 @@
|
|
|
13
16
|
".": {
|
|
14
17
|
"types": "./index.d.ts",
|
|
15
18
|
"default": "./src/index.ts"
|
|
19
|
+
},
|
|
20
|
+
"./schemagen": {
|
|
21
|
+
"types": "./src/cli-tool/schemagen/index.ts",
|
|
22
|
+
"default": "./src/cli-tool/schemagen/index.ts"
|
|
16
23
|
}
|
|
17
24
|
},
|
|
18
25
|
"bin": {
|
|
@@ -63,7 +63,8 @@ describe("full-example template", () => {
|
|
|
63
63
|
|
|
64
64
|
test("status command defines outputSchema", () => {
|
|
65
65
|
const statusSource = readFileSync(join(exampleRoot, "src/commands/status/command.ts"), "utf8");
|
|
66
|
-
expect(statusSource).
|
|
66
|
+
expect(statusSource).toMatch(/outputSchema[,:]/);
|
|
67
|
+
expect(statusSource).toContain('from "./__generated__/index.ts"');
|
|
67
68
|
});
|
|
68
69
|
|
|
69
70
|
test("resolveCapabilities matches full sink shape", () => {
|
|
@@ -41,10 +41,10 @@ export async function runPostCreate(targetDir: string, dryRun: boolean): Promise
|
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
|
-
label: "
|
|
44
|
+
label: "argsbarg schemagen",
|
|
45
45
|
run: () => {
|
|
46
46
|
if (dryRun) return;
|
|
47
|
-
const proc = Bun.spawnSync(["
|
|
47
|
+
const proc = Bun.spawnSync(["argsbarg", "schemagen"], {
|
|
48
48
|
cwd: abs,
|
|
49
49
|
stdout: "inherit",
|
|
50
50
|
stderr: "inherit",
|
|
@@ -103,7 +103,7 @@ export async function runPostCreate(targetDir: string, dryRun: boolean): Promise
|
|
|
103
103
|
export function printPostCreatePlan(): void {
|
|
104
104
|
process.stderr.write("Post-create steps:\n");
|
|
105
105
|
process.stderr.write(" 1. bun install\n");
|
|
106
|
-
process.stderr.write(" 2.
|
|
106
|
+
process.stderr.write(" 2. just schemagen\n");
|
|
107
107
|
process.stderr.write(" 3. bun test\n");
|
|
108
108
|
process.stderr.write(" 4. git init + Initial commit (skipped inside existing git work tree)\n");
|
|
109
109
|
}
|