@workos/oagen 0.0.1

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 (64) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/LICENSE.txt +21 -0
  3. package/README.md +197 -0
  4. package/dist/chunk-CIX5NOBF.js +263 -0
  5. package/dist/chunk-IJ5E5AE7.js +1040 -0
  6. package/dist/chunk-P5XUDUGY.js +1748 -0
  7. package/dist/cli/index.js +5603 -0
  8. package/dist/compat/index.d.ts +195 -0
  9. package/dist/compat/index.js +4453 -0
  10. package/dist/index.d.ts +300 -0
  11. package/dist/index.js +1733 -0
  12. package/dist/scripts/smoke/baseline.js +1751 -0
  13. package/dist/scripts/smoke/sdk-test.js +93 -0
  14. package/dist/smoke.js +1963 -0
  15. package/dist/types-B5t9O9Wm.d.ts +367 -0
  16. package/dist/verify/index.d.ts +76 -0
  17. package/dist/verify/index.js +336 -0
  18. package/docs/advanced/index.md +11 -0
  19. package/docs/advanced/oagen-ignore.md +144 -0
  20. package/docs/agents/architecture.md +53 -0
  21. package/docs/agents/emitters.md +69 -0
  22. package/docs/agents/testing.md +60 -0
  23. package/docs/architecture/dependency-layers.md +75 -0
  24. package/docs/architecture/emitter-contract.md +160 -0
  25. package/docs/architecture/extractor-contract.md +227 -0
  26. package/docs/architecture/ir-types.md +275 -0
  27. package/docs/architecture/non-additive-changes.md +76 -0
  28. package/docs/architecture/pipeline.md +110 -0
  29. package/docs/architecture/workflows.md +215 -0
  30. package/docs/cli.md +156 -0
  31. package/docs/contributor/index.md +10 -0
  32. package/docs/contributor/public-api.md +59 -0
  33. package/docs/contributor/versioning.md +48 -0
  34. package/docs/core/index.md +12 -0
  35. package/docs/core/minimal-emitter.md +134 -0
  36. package/docs/core/quickstart.md +142 -0
  37. package/docs/diagrams/generate-sdk-workflow.md +50 -0
  38. package/docs/index.md +40 -0
  39. package/examples/reference-emitter/README.md +41 -0
  40. package/examples/reference-emitter/oagen.config.ts +7 -0
  41. package/examples/reference-emitter/spec/github-subset.yml +400 -0
  42. package/examples/reference-emitter/src/emitter.ts +52 -0
  43. package/examples/reference-emitter/src/generators/client.ts +37 -0
  44. package/examples/reference-emitter/src/generators/config.ts +19 -0
  45. package/examples/reference-emitter/src/generators/enums.ts +16 -0
  46. package/examples/reference-emitter/src/generators/errors.ts +39 -0
  47. package/examples/reference-emitter/src/generators/models.ts +29 -0
  48. package/examples/reference-emitter/src/generators/resources.ts +60 -0
  49. package/examples/reference-emitter/src/generators/tests.ts +7 -0
  50. package/examples/reference-emitter/src/index.ts +1 -0
  51. package/examples/reference-emitter/src/naming.ts +21 -0
  52. package/examples/reference-emitter/src/type-mapper.ts +39 -0
  53. package/examples/reference-emitter/tsconfig.json +19 -0
  54. package/package.json +102 -0
  55. package/skills/generate-emitter/SKILL.md +393 -0
  56. package/skills/generate-emitter/references/common-pitfalls.md +23 -0
  57. package/skills/generate-emitter/references/generator-guide.md +201 -0
  58. package/skills/generate-emitter/references/project-scaffold.md +138 -0
  59. package/skills/generate-extractor/SKILL.md +200 -0
  60. package/skills/generate-sdk/SKILL.md +155 -0
  61. package/skills/generate-smoke-test/SKILL.md +185 -0
  62. package/skills/integrate/SKILL.md +108 -0
  63. package/skills/verify-compat/SKILL.md +151 -0
  64. package/skills/verify-smoke-test/SKILL.md +176 -0
package/docs/cli.md ADDED
@@ -0,0 +1,156 @@
1
+ # CLI Reference
2
+
3
+ All commands support `--help` for full usage details.
4
+
5
+ ## `oagen generate`
6
+
7
+ Generate SDK code from an OpenAPI spec.
8
+
9
+ ```bash
10
+ oagen generate --spec openapi.yml --lang node --output ./sdk --namespace WorkOS
11
+ ```
12
+
13
+ | Argument | Required | Default | Description |
14
+ | ---------------------- | -------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
+ | `--spec <path>` | No | `OPENAPI_SPEC_PATH` env | Path to an OpenAPI 3.x spec file. |
16
+ | `--lang <language>` | Yes | | Target language — must have a registered emitter (via `oagen.config.ts`) |
17
+ | `--output <dir>` | Yes | | Directory to write generated files into |
18
+ | `--namespace <name>` | No | Spec's `info.title` | SDK namespace in PascalCase — used directly for code identifiers (e.g., `WorkOS::Client`) and converted to `snake_case` for file paths (e.g., `lib/work_os/`). Use PascalCase with the exact casing you want (e.g., `WorkOS` not `work_os`). |
19
+ | `--dry-run` | No | `false` | Print the list of file paths that would be generated, without writing anything to disk |
20
+ | `--api-surface <path>` | No | | Path to baseline API surface JSON for compat overlay |
21
+ | `--manifest <path>` | No | `<output>/smoke-manifest.json` | Path to smoke-manifest.json for method overlay (auto-discovered in output dir if present) |
22
+ | `--no-compat-check` | No | `false` | Skip compat overlay even if `--api-surface` is provided |
23
+
24
+ ## `oagen diff`
25
+
26
+ Review or apply spec changes. Use `--report` to see what changed, or pass `--lang` and `--output` to incrementally regenerate affected files.
27
+
28
+ ```bash
29
+ oagen diff --old v1.yml --new v2.yml --report # review changes
30
+ oagen diff --old v1.yml --new v2.yml --lang node --output ./sdk # regenerate
31
+ ```
32
+
33
+ | Argument | Required | Description |
34
+ | ---------------------- | -------- | ------------------------------------------------------- |
35
+ | `--old <path>` | Yes | Path to the old/previous spec |
36
+ | `--new <path>` | Yes | Path to the new/current spec |
37
+ | `--lang <language>` | No | Target language (required unless `--report`) |
38
+ | `--output <dir>` | No | Output directory for regenerated files |
39
+ | `--report` | No | Output a diff report as JSON instead of generating code |
40
+ | `--force` | No | Allow file deletions without confirmation |
41
+ | `--api-surface <path>` | No | Path to baseline API surface JSON for compat overlay |
42
+ | `--manifest <path>` | No | Path to smoke-manifest.json for method overlay |
43
+
44
+ ## `oagen extract`
45
+
46
+ Extract the public API surface from an existing SDK. Produces a JSON file used as input for compat overlay and verification.
47
+
48
+ ```bash
49
+ oagen extract --sdk-path ./existing-sdk --lang ruby --output ./sdk/sdk-ruby-surface.json
50
+ oagen extract --sdk-path ./existing-sdk --lang ruby --output my-surface.json
51
+ ```
52
+
53
+ | Argument | Required | Default | Description |
54
+ | ------------------- | -------- | ------------------------- | --------------------------------------------------------------------------------------------------------------- |
55
+ | `--sdk-path <path>` | Yes | | Path to the live SDK |
56
+ | `--lang <language>` | Yes | | Target language |
57
+ | `--output <path>` | No | `sdk-{lang}-surface.json` | Output file path (recommend writing to your output dir, e.g. `./sdk/sdk-ruby-surface.json`, and gitignoring it) |
58
+
59
+ ## `oagen verify`
60
+
61
+ Verify an already-generated SDK — run smoke tests and optional compat checks. Use after `oagen generate` or `oagen diff`.
62
+
63
+ ```bash
64
+ oagen verify --lang node --output ./sdk --spec openapi.yml
65
+
66
+ # With compat check
67
+ oagen verify --lang node --output ./sdk --spec openapi.yml \
68
+ --api-surface ./sdk/sdk-node-surface.json
69
+ ```
70
+
71
+ | Argument | Required | Default | Description |
72
+ | ----------------------- | -------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------- |
73
+ | `--lang <language>` | Yes | | Target language |
74
+ | `--output <dir>` | Yes | | Path to the generated SDK |
75
+ | `--spec <path>` | No | `OPENAPI_SPEC_PATH` env | Path to an OpenAPI 3.x spec file |
76
+ | `--api-surface <path>` | No | | Baseline API surface JSON — enables compat verification |
77
+ | `--raw-results <path>` | No | auto-generated | Path to an existing smoke baseline file to diff against |
78
+ | `--smoke-config <path>` | No | | Smoke config JSON for skip lists and service mappings |
79
+ | `--smoke-runner <path>` | No | | Custom smoke runner script (overrides built-in `sdk-test.ts`) |
80
+ | `--scope <mode>` | No | `spec-only` when `--spec` given | Compat scope: `full` compares all baseline symbols, `spec-only` only compares symbols derivable from the spec |
81
+ | `--diagnostics` | No | `false` | Output `verify-diagnostics.json` with structured violation breakdown |
82
+ | `--max-retries <n>` | No | `3` | Max retry iterations for self-correcting overlay loop (set to 0 for single-pass) |
83
+
84
+ **Exit codes:**
85
+
86
+ | Code | Meaning | Details |
87
+ | ---- | ----------------------------------------------------------------------- | --------------------------- |
88
+ | 0 | Clean — all checks passed | |
89
+ | 1 | Findings — CRITICAL smoke mismatches, compat violations, or missing ops | `smoke-diff-findings.json` |
90
+ | 2 | Compile error — SDK failed type check | `smoke-compile-errors.json` |
91
+
92
+ ## `oagen init`
93
+
94
+ Scaffold a new emitter project with all boilerplate files and a compilable stub emitter.
95
+
96
+ ```bash
97
+ oagen init --lang ruby
98
+ oagen init --lang go --project ./my-emitter
99
+ ```
100
+
101
+ | Argument | Required | Default | Description |
102
+ | ------------------- | -------- | ------- | ------------------------------------ |
103
+ | `--lang <language>` | Yes | | Target language (e.g., `ruby`, `go`) |
104
+ | `--project <dir>` | No | `.` | Directory to create the project in |
105
+
106
+ Creates:
107
+
108
+ - `package.json` with `@workos/oagen` dependency and `sdk:generate`/`sdk:verify`/`sdk:extract` scripts
109
+ - `tsconfig.json`, `vitest.config.ts`, `tsup.config.ts` — build/test tooling
110
+ - `oagen.config.ts` — registers the stub emitter
111
+ - `src/{language}/index.ts` — stub emitter implementing the full `Emitter` interface
112
+ - `src/index.ts` — barrel export
113
+ - Empty directories: `test/`, `smoke/`, `docs/sdk-architecture/`
114
+
115
+ After initialization, `npm run typecheck` passes immediately. Implement your emitter methods in `src/{language}/` to start generating SDK code.
116
+
117
+ ## `oagen parse`
118
+
119
+ Parse an OpenAPI spec and output the IR as JSON to stdout. Useful for inspecting what the parser extracts.
120
+
121
+ ```bash
122
+ oagen parse --spec openapi.yml
123
+ ```
124
+
125
+ | Argument | Required | Default | Description |
126
+ | --------------- | -------- | ----------------------- | ------------------------------------------------ |
127
+ | `--spec <path>` | No | `OPENAPI_SPEC_PATH` env | Path to an OpenAPI 3.x spec file (YAML or JSON). |
128
+
129
+ ## Configuration (`oagen.config.ts`)
130
+
131
+ Place an `oagen.config.ts` (or `.js`/`.mjs`) in your project root to register emitters, extractors, and customize pipeline behavior. The CLI loads this file at startup before any command runs.
132
+
133
+ ```ts
134
+ import type { OagenConfig } from "@workos/oagen";
135
+ import { nodeEmitter } from "./src/node/index.js";
136
+ import { nodeExtractor } from "./src/node/extractor.js";
137
+
138
+ const config: OagenConfig = {
139
+ emitters: [nodeEmitter],
140
+ extractors: [nodeExtractor],
141
+ docUrl: "https://workos.com/docs",
142
+ };
143
+
144
+ export default config;
145
+ ```
146
+
147
+ ### Options
148
+
149
+ | Key | Type | Description |
150
+ | ---------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
151
+ | `emitters` | `Emitter[]` | Language emitters to register. Each emitter implements the `Emitter` interface and generates SDK files for one target language. |
152
+ | `extractors` | `Extractor[]` | API surface extractors to register. Each extractor parses a live SDK and produces an `ApiSurface` JSON used for compat verification. |
153
+ | `emitterProject` | `string` | Path to the emitter project directory. Used by skills to scaffold new emitters, tests, and smoke runners in the correct location. |
154
+ | `smokeRunners` | `Record<string, string>` | Map from language key to custom smoke runner script path. Overrides the built-in `sdk-test.ts` for `oagen verify`. Can also be set per-invocation with `--smoke-runner`. |
155
+ | `operationIdTransform` | `(id: string) => string` | Custom transform for operation IDs. Receives the raw `operationId` from the spec; return the desired operation name. No additional casing conversion is applied. When omitted, `operationId` values are converted to `camelCase`. |
156
+ | `docUrl` | `string` | Base URL for documentation links. When set, relative markdown paths in descriptions (e.g. `[User](/reference/authkit/user)`) are expanded to full URLs (e.g. `[User](https://workos.com/docs/reference/authkit/user)`). |
@@ -0,0 +1,10 @@
1
+ # Contributor Docs
2
+
3
+ These documents describe the maintenance rules for oagen itself and the guarantees made to consumers of the public API. If you are modifying oagen core (the parser, engine, IR types, compat system, or CLI), start here to understand what contracts you must preserve.
4
+
5
+ ## Key Documents
6
+
7
+ - [Public API Policy](public-api.md) — three-tier public surface (core default export, advanced subpaths, internal) and what constitutes a breaking change
8
+ - [Versioning and Migration](versioning.md) — IR version bumping rules, package versioning, and advanced workflow compatibility
9
+ - [Dependency Layers](../architecture/dependency-layers.md) — one-way import matrix (`ir → utils → parser → engine/differ/compat → cli`) enforced by structural linter
10
+ - [Pipeline Architecture](../architecture/pipeline.md) — three-stage parse/emit/write flow with orchestrator details
@@ -0,0 +1,59 @@
1
+ # Public API Policy
2
+
3
+ This document defines what oagen treats as public API for OSS consumers.
4
+
5
+ ## Core Public API
6
+
7
+ The default `@workos/oagen` entrypoint is the core public API.
8
+
9
+ It includes:
10
+
11
+ - IR types
12
+ - parser entrypoints such as `parseSpec`
13
+ - emitter-facing types such as `Emitter`, `EmitterContext`, and `GeneratedFile`
14
+ - generation runtime entrypoints such as `generate`, `generateFiles`, and `generateIncremental`
15
+ - spec diffing APIs such as `diffSpecs` and `mapChangesToFiles`
16
+ - naming utilities used by emitters
17
+ - `planOperation`
18
+ - config typing needed by emitter projects
19
+
20
+ Changes to this surface require a deliberate compatibility review.
21
+
22
+ ## Advanced Public API
23
+
24
+ The following APIs are public, but not part of the default entrypoint:
25
+
26
+ - `@workos/oagen/compat`
27
+ - `@workos/oagen/verify`
28
+
29
+ These modules cover compatibility overlays, extractor registration, built-in extractors, and verification helpers. They are supported, but they are more opinionated and may evolve faster than the core framework surface.
30
+
31
+ ## Internal API
32
+
33
+ Anything not exported from a package entrypoint should be treated as internal implementation detail, including:
34
+
35
+ - deep imports into `src/*`
36
+ - CLI implementation modules
37
+ - parser internals below `parseSpec`
38
+ - compat internals below the documented compat entrypoint
39
+ - verify internals below the documented verify entrypoint
40
+
41
+ Internal APIs may change without notice.
42
+
43
+ ## Documentation Rule
44
+
45
+ If an API is intended for external use, it must satisfy all of the following:
46
+
47
+ 1. It is exported from a package entrypoint.
48
+ 2. It is documented in user-facing docs.
49
+ 3. It has tests that reflect the intended behavior.
50
+
51
+ If one of those is missing, the API should be considered provisional at best.
52
+
53
+ ## Stability Rule
54
+
55
+ When in doubt:
56
+
57
+ - keep the default entrypoint small
58
+ - prefer adding advanced capabilities behind explicit subpaths
59
+ - avoid promoting internal helpers into the public surface unless they are needed by emitter authors
@@ -0,0 +1,48 @@
1
+ # Versioning and Migration
2
+
3
+ oagen has two different compatibility concerns. They should not be treated as interchangeable.
4
+
5
+ ## 1. Package Version
6
+
7
+ The npm package version communicates overall release maturity and changelog history.
8
+
9
+ ## 2. Advanced Workflow Compatibility
10
+
11
+ Compat extraction, overlays, smoke verification, and target integration are higher-level workflows built on top of the core framework. They may require narrower migration guidance than the core parser/emitter contract.
12
+
13
+ Treat changes here as public if they affect:
14
+
15
+ - documented CLI flags
16
+ - documented subpath exports
17
+ - persisted file formats such as extracted API surfaces or diagnostics files
18
+
19
+ ## Compile-Time Safety
20
+
21
+ The primary compatibility mechanism is `assertNever`, which enforces exhaustive `switch` statements over `TypeRef.kind` at compile time. Adding a new IR variant causes build failures in any emitter that doesn't handle it.
22
+
23
+ ## Migration Guidance
24
+
25
+ Every release that changes public behavior should describe:
26
+
27
+ 1. what changed
28
+ 2. who is affected
29
+ 3. whether the change is core or advanced
30
+ 4. what users need to update
31
+
32
+ At minimum, migration notes should call out:
33
+
34
+ - IR shape changes
35
+ - emitter contract changes
36
+ - config shape changes
37
+ - CLI flag changes
38
+ - compat JSON format changes
39
+
40
+ ## Release Discipline
41
+
42
+ Before broadening the public surface:
43
+
44
+ 1. decide whether the API belongs in the core entrypoint or an advanced subpath
45
+ 2. document it
46
+ 3. add tests that exercise its intended use by external consumers
47
+
48
+ If that discipline is too expensive, the API is not ready to be public.
@@ -0,0 +1,12 @@
1
+ # Core Docs
2
+
3
+ These documents define the stable center of oagen as an OSS framework.
4
+
5
+ - [Minimal Quickstart](quickstart.md)
6
+ - [Minimal Emitter](minimal-emitter.md)
7
+ - [CLI Reference](../cli.md)
8
+ - [Pipeline Architecture](../architecture/pipeline.md)
9
+ - [IR Type System Reference](../architecture/ir-types.md)
10
+ - [Emitter Contract](../architecture/emitter-contract.md)
11
+
12
+ Read the quickstart first. The goal is to get from a spec to generated files without learning compatibility overlays, extractors, or smoke workflows.
@@ -0,0 +1,134 @@
1
+ # Minimal Emitter
2
+
3
+ This guide shows the smallest useful emitter shape in oagen.
4
+
5
+ Use it when you want to understand the minimum contract quickly. If you need the full interface details, overlay behavior, and versioning rules, read the [Emitter Contract](../architecture/emitter-contract.md).
6
+
7
+ ## Goal
8
+
9
+ A minimal emitter should:
10
+
11
+ - declare a `language`
12
+ - return files from at least one generator method
13
+ - return `[]` from methods the language does not use yet
14
+
15
+ That is enough to prove the parser, runtime, and file-writing loop are working.
16
+
17
+ ## Smallest Practical Skeleton
18
+
19
+ ```ts
20
+ import type {
21
+ ApiSpec,
22
+ Emitter,
23
+ Enum,
24
+ GeneratedFile,
25
+ Model,
26
+ Service,
27
+ } from "@workos/oagen";
28
+
29
+ function namesFile(path: string, values: string[]): GeneratedFile[] {
30
+ if (values.length === 0) return [];
31
+ return [{ path, content: values.join("\n") }];
32
+ }
33
+
34
+ export const demoEmitter: Emitter = {
35
+ language: "demo",
36
+
37
+ generateModels(models: Model[]): GeneratedFile[] {
38
+ return namesFile(
39
+ "models.txt",
40
+ models.map((model) => model.name),
41
+ );
42
+ },
43
+
44
+ generateEnums(enums: Enum[]): GeneratedFile[] {
45
+ return namesFile(
46
+ "enums.txt",
47
+ enums.map((entry) => entry.name),
48
+ );
49
+ },
50
+
51
+ generateResources(services: Service[]): GeneratedFile[] {
52
+ return namesFile(
53
+ "services.txt",
54
+ services.map((service) => service.name),
55
+ );
56
+ },
57
+
58
+ generateClient(spec: ApiSpec): GeneratedFile[] {
59
+ return [
60
+ {
61
+ path: "summary.txt",
62
+ content: [
63
+ `name: ${spec.name}`,
64
+ `services: ${spec.services.length}`,
65
+ ].join("\n"),
66
+ },
67
+ ];
68
+ },
69
+
70
+ generateErrors(): GeneratedFile[] {
71
+ return [];
72
+ },
73
+
74
+ generateConfig(): GeneratedFile[] {
75
+ return [];
76
+ },
77
+
78
+ generateTypeSignatures(): GeneratedFile[] {
79
+ return [];
80
+ },
81
+
82
+ generateTests(): GeneratedFile[] {
83
+ return [];
84
+ },
85
+
86
+ fileHeader(): string {
87
+ return "# Generated by oagen";
88
+ },
89
+ };
90
+ ```
91
+
92
+ ## What This Proves
93
+
94
+ With just this emitter, you can verify:
95
+
96
+ - the spec parses into IR
97
+ - the emitter is registered correctly
98
+ - the generation runtime calls each method in the expected order
99
+ - output files are written to disk
100
+
101
+ ## What It Does Not Cover Yet
102
+
103
+ This is intentionally incomplete. It does not try to solve:
104
+
105
+ - language-specific naming conventions
106
+ - request/response rendering
107
+ - operation planning
108
+ - compatibility overlays
109
+ - smoke verification
110
+ - integration into an existing SDK
111
+
112
+ ## The First Real Upgrade
113
+
114
+ After the minimal emitter works, the next step is usually to make `generateResources()` and `generateClient()` understand operations rather than only names.
115
+
116
+ That is when `planOperation()` becomes useful:
117
+
118
+ ```ts
119
+ import { planOperation } from "@workos/oagen";
120
+
121
+ for (const service of services) {
122
+ for (const operation of service.operations) {
123
+ const plan = planOperation(operation);
124
+ // render using plan.hasBody, plan.isPaginated, plan.responseModelName, ...
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## Recommended Path
130
+
131
+ 1. Start with this minimal emitter.
132
+ 2. Make generation deterministic and add golden tests.
133
+ 3. Add real model and operation rendering.
134
+ 4. Only then add advanced features like compat overlays or smoke verification.
@@ -0,0 +1,142 @@
1
+ # Minimal Quickstart
2
+
3
+ This guide takes you from an OpenAPI spec to a tiny working emitter with the fewest moving parts possible.
4
+
5
+ ## What You Will Build
6
+
7
+ - parse an OpenAPI spec into oagen's IR
8
+ - scaffold an emitter project
9
+ - replace the stub emitter with a minimal implementation
10
+ - generate a few files
11
+
12
+ This quickstart intentionally ignores advanced features like API-surface extraction, compatibility overlays, smoke verification, and live-SDK integration.
13
+
14
+ ## 1. Install oagen
15
+
16
+ ```bash
17
+ npm install @workos/oagen
18
+ ```
19
+
20
+ ## 2. Inspect Your Spec
21
+
22
+ ```bash
23
+ oagen parse --spec openapi.yml
24
+ ```
25
+
26
+ This prints the parsed IR as JSON. Before writing an emitter, confirm the parser is extracting the services, models, and enums you expect.
27
+
28
+ ## 3. Scaffold an Emitter Project
29
+
30
+ ```bash
31
+ oagen init --lang demo --project ./demo-emitter
32
+ cd ./demo-emitter
33
+ npm install
34
+ ```
35
+
36
+ The scaffold gives you:
37
+
38
+ - `oagen.config.ts`
39
+ - `src/demo/index.ts`
40
+ - build/test tooling
41
+ - `sdk:generate` and related package scripts
42
+
43
+ ## 4. Replace the Stub Emitter
44
+
45
+ Edit `src/demo/index.ts` to return a few simple files:
46
+
47
+ ```ts
48
+ import type {
49
+ ApiSpec,
50
+ Emitter,
51
+ Enum,
52
+ GeneratedFile,
53
+ Model,
54
+ Service,
55
+ } from "@workos/oagen";
56
+
57
+ function renderSummary(spec: ApiSpec): string {
58
+ return [
59
+ `name: ${spec.name}`,
60
+ `services: ${spec.services.length}`,
61
+ `models: ${spec.models.length}`,
62
+ `enums: ${spec.enums.length}`,
63
+ ].join("\n");
64
+ }
65
+
66
+ function renderModels(models: Model[]): GeneratedFile[] {
67
+ if (models.length === 0) return [];
68
+ return [
69
+ {
70
+ path: "models.txt",
71
+ content: models.map((model) => model.name).join("\n"),
72
+ },
73
+ ];
74
+ }
75
+
76
+ function renderEnums(enums: Enum[]): GeneratedFile[] {
77
+ if (enums.length === 0) return [];
78
+ return [
79
+ {
80
+ path: "enums.txt",
81
+ content: enums.map((entry) => entry.name).join("\n"),
82
+ },
83
+ ];
84
+ }
85
+
86
+ function renderServices(services: Service[]): GeneratedFile[] {
87
+ if (services.length === 0) return [];
88
+ return [
89
+ {
90
+ path: "services.txt",
91
+ content: services.map((service) => service.name).join("\n"),
92
+ },
93
+ ];
94
+ }
95
+
96
+ export const demoEmitter: Emitter = {
97
+ language: "demo",
98
+ generateModels: (models) => renderModels(models),
99
+ generateEnums: (enums) => renderEnums(enums),
100
+ generateResources: (services) => renderServices(services),
101
+ generateClient: (spec) => [
102
+ {
103
+ path: "summary.txt",
104
+ content: renderSummary(spec),
105
+ },
106
+ ],
107
+ generateErrors: () => [],
108
+ generateConfig: () => [],
109
+ generateTypeSignatures: () => [],
110
+ generateTests: () => [],
111
+ fileHeader: () => "# Generated by oagen",
112
+ };
113
+ ```
114
+
115
+ ## 5. Generate Files
116
+
117
+ ```bash
118
+ npm run sdk:generate -- --spec ../openapi.yml --namespace DemoSdk
119
+ ```
120
+
121
+ Expected result:
122
+
123
+ - `sdk/summary.txt`
124
+ - `sdk/models.txt` when the spec has models
125
+ - `sdk/enums.txt` when the spec has enums
126
+ - `sdk/services.txt` when the spec has services
127
+
128
+ ## 6. Grow from Here
129
+
130
+ Once the minimal loop works:
131
+
132
+ 1. Replace text files with real language output.
133
+ 2. Use [`planOperation`](../../src/engine/operation-plan.ts) via `@workos/oagen` to share operation decision logic.
134
+ 3. Add emitter tests with fixture specs and golden files.
135
+ 4. Only then consider advanced workflows like `oagen verify` or compatibility overlays.
136
+
137
+ ## Next Reads
138
+
139
+ - [Reference Emitter](../../examples/reference-emitter/) — a working TypeScript emitter you can study and copy
140
+ - [Emitter Contract](../architecture/emitter-contract.md)
141
+ - [IR Type System Reference](../architecture/ir-types.md)
142
+ - [CLI Reference](../cli.md)
@@ -0,0 +1,50 @@
1
+ # /generate-sdk Workflow
2
+
3
+ ```mermaid
4
+ ---
5
+ config:
6
+ layout: elk
7
+ ---
8
+ flowchart TD
9
+ start([/generate-sdk]) --> existingSDK{Existing SDK?}
10
+
11
+ existingSDK -- "Yes: Scenario A" --> a_emitter["/generate-emitter"]
12
+ existingSDK -- "No: Scenario B" --> b_emitter["/generate-emitter"]
13
+
14
+ a_emitter --> a_extractor["/generate-extractor
15
+ extract live SDK public API
16
+ into api-surface.json"]
17
+
18
+ a_extractor --> a_compat["/verify-compat
19
+ diff generated SDK
20
+ against api-surface.json"]
21
+
22
+ a_compat --> overlay_gen
23
+
24
+ subgraph overlay loop
25
+ overlay_gen["generate with overlay"]
26
+ overlay_gen --> overlay_diff["diff against baseline"]
27
+ overlay_diff --> violations{violations?}
28
+ violations -- yes --> patch["patchOverlay"]
29
+ patch --> overlay_gen
30
+ end
31
+
32
+ violations -- no --> smoke["/generate-smoke-test
33
+ scaffold HTTP interception
34
+ + wire-level parity tests"]
35
+
36
+ b_emitter --> smoke
37
+
38
+ smoke --> loop_start
39
+
40
+ subgraph emitter-fixing loop
41
+ loop_start["oagen generate"]
42
+ loop_start --> loop_verify["oagen verify"]
43
+ loop_verify --> exitcode{exit code?}
44
+ exitcode -- "1 or 2" --> fix["read findings, fix emitter"]
45
+ fix --> loop_start
46
+ end
47
+
48
+ exitcode -- 0 --> final(["final validation
49
+ tsc + vitest + tsup + lint"])
50
+ ```
package/docs/index.md ADDED
@@ -0,0 +1,40 @@
1
+ # Docs Overview
2
+
3
+ oagen documentation is organized by adoption stage.
4
+
5
+ ## Core
6
+
7
+ Start here if you want to understand or use the framework itself:
8
+
9
+ - [Core Index](core/index.md)
10
+ - [Minimal Quickstart](core/quickstart.md)
11
+ - [CLI Reference](cli.md)
12
+ - [Emitter Contract](architecture/emitter-contract.md)
13
+ - [IR Type System Reference](architecture/ir-types.md)
14
+ - [Pipeline Architecture](architecture/pipeline.md)
15
+
16
+ ## Advanced
17
+
18
+ Read these when you need migration or verification workflows beyond basic generation:
19
+
20
+ - [Advanced Index](advanced/index.md)
21
+ - [Workflows](architecture/workflows.md)
22
+ - [Extractor Contract](architecture/extractor-contract.md)
23
+ - [Non-Additive Changes](architecture/non-additive-changes.md)
24
+
25
+ ## Agent Task Guides
26
+
27
+ Focused guides for AI agents working on specific areas of the codebase:
28
+
29
+ - [Architecture & Core Contracts](agents/architecture.md)
30
+ - [Emitter Implementation](agents/emitters.md)
31
+ - [Testing & Smoke Validation](agents/testing.md)
32
+
33
+ ## Contributor
34
+
35
+ Read these if you are maintaining oagen itself or depending on its public API surface:
36
+
37
+ - [Contributor Index](contributor/index.md)
38
+ - [Public API Policy](contributor/public-api.md)
39
+ - [Versioning and Migration](contributor/versioning.md)
40
+ - [Dependency Layers](architecture/dependency-layers.md)