@@ -53,63 +53,147 @@ Available binaries:
5353## CLI Usage
5454
5555``` bash
56- # Bundle from a fetched upstream spec directory
56+ # Fetch from upstream and bundle (simplest usage — fetches from main)
5757camunda-schema-bundler \
58- --spec-dir external-spec/upstream/zeebe/gateway-protocol/src/main/proto/v2 \
5958 --output-spec external-spec/bundled/rest-api.bundle.json \
6059 --output-metadata external-spec/bundled/spec-metadata.json
6160
62- # For generators that can't handle path-local $refs (e.g. Microsoft.OpenApi for C#)
61+ # Fetch a specific branch/tag/SHA
62+ camunda-schema-bundler --ref stable/8.8 \
63+ --output-spec rest-api.bundle.json
64+
65+ # Auto-detect upstream ref from current git branch
66+ # (main → main, stable/* → stable/*, other → main)
67+ camunda-schema-bundler --auto-ref \
68+ --output-spec external-spec/bundled/rest-api.bundle.json
69+
70+ # Use already-fetched spec (no network)
6371camunda-schema-bundler \
6472 --spec-dir external-spec/upstream/zeebe/gateway-protocol/src/main/proto/v2 \
65- --output-spec external-spec/bundled/rest-api.bundle.json \
66- --deref-path-local
73+ --output-spec external-spec/bundled/rest-api.bundle.json
74+
75+ # Bundle with path-local deref (for C# / Microsoft.OpenApi)
76+ camunda-schema-bundler --deref-path-local \
77+ --output-spec external-spec/bundled/rest-api.bundle.json
78+
79+ # Check version
80+ camunda-schema-bundler --version
6781```
6882
6983### CLI Options
7084
7185| Option | Description |
7286| ---| ---|
73- | ` --spec-dir <path> ` | Path to the upstream spec directory (required) |
87+ | ** Modes** | |
88+ | ` --fetch ` | Fetch upstream spec before bundling (default when no ` --spec-dir ` ) |
89+ | ` --spec-dir <path> ` | Use an existing local spec directory (skip fetch) |
90+ | ** Fetch options** | |
91+ | ` --ref <ref> ` | Git ref to fetch: branch, tag, or SHA (default: ` main ` ) |
92+ | ` --auto-ref ` | Auto-detect ref from current git branch or ` SPEC_REF ` env var |
93+ | ` --repo-url <url> ` | Git repo URL (default: ` https://github.com/camunda/camunda.git ` ) |
94+ | ` --output-dir <path> ` | Local directory for fetched spec files |
95+ | ` --skip-fetch-if-exists ` | Skip fetch if the entry file already exists locally |
96+ | ** Bundle options** | |
7497| ` --entry-file <name> ` | Entry YAML file name (default: ` rest-api.yaml ` ) |
7598| ` --output-spec <path> ` | Output path for the bundled JSON spec |
7699| ` --output-metadata <path> ` | Output path for the metadata IR JSON |
77100| ` --deref-path-local ` | Inline remaining path-local ` $ref ` s (needed for Microsoft.OpenApi) |
78101| ` --allow-like-refs ` | Don't fail on surviving path-local ` $like ` refs |
102+ | ** General** | |
103+ | ` --help ` , ` -h ` | Show help |
104+ | ` --version ` , ` -v ` | Show version |
105+
106+ ### Auto-ref detection
107+
108+ The ` --auto-ref ` flag (and ` detectUpstreamRef() ` in the library API) resolves the upstream spec ref using this priority:
109+
110+ 1 . ` SPEC_REF ` environment variable (always wins)
111+ 2 . Current git branch: ` main ` → ` main ` , ` stable/X.Y ` → ` stable/X.Y `
112+ 3 . Falls back to ` main ` for other branches or if git is unavailable
79113
80114## Library API
81115
116+ ### ` bundle() ` — Bundle from a local spec directory
117+
82118``` typescript
83119import { bundle } from ' camunda-schema-bundler' ;
84120
85121const result = await bundle ({
86122 specDir: ' external-spec/upstream/zeebe/gateway-protocol/src/main/proto/v2' ,
87123 outputSpec: ' external-spec/bundled/rest-api.bundle.json' ,
88124 outputMetadata: ' external-spec/bundled/spec-metadata.json' ,
89- dereferencePathLocalRefs: false , // set true for C#
125+ dereferencePathLocalRefs: false , // set true for C# / Python
90126});
91127
92128console .log (result .stats );
93- // { pathCount: 140, schemaCount: 465, augmentedSchemaCount: 465, ... }
129+ // {
130+ // pathCount: 140, schemaCount: 511, augmentedSchemaCount: 511,
131+ // promotedInlineSchemaCount: 46, freshDedupCount: 298,
132+ // dereferencedPathLocalRefCount: 0, pathLocalLikeRefCount: 0
133+ // }
134+ ```
135+
136+ ### ` fetchAndBundle() ` — Fetch + bundle in one call
137+
138+ ``` typescript
139+ import { fetchAndBundle } from ' camunda-schema-bundler' ;
140+
141+ const result = await fetchAndBundle ({
142+ ref: ' stable/8.8' , // optional, default: "main"
143+ outputDir: ' external-spec/upstream/zeebe/gateway-protocol/src/main/proto/v2' ,
144+ outputSpec: ' external-spec/bundled/rest-api.bundle.json' ,
145+ outputMetadata: ' external-spec/bundled/spec-metadata.json' ,
146+ });
147+ ```
148+
149+ ### ` fetchSpec() ` — Fetch only
150+
151+ ``` typescript
152+ import { fetchSpec } from ' camunda-schema-bundler' ;
153+
154+ const { specDir, entryPath, fetched } = await fetchSpec ({
155+ ref: ' main' ,
156+ outputDir: ' external-spec/upstream/zeebe/gateway-protocol/src/main/proto/v2' ,
157+ skipIfExists: true , // skip if already fetched
158+ });
159+ ```
160+
161+ ### ` detectUpstreamRef() ` — Auto-detect git ref
162+
163+ ``` typescript
164+ import { detectUpstreamRef } from ' camunda-schema-bundler' ;
94165
95- console .log (result .metadata .integrity );
96- // { totalSemanticKeys: 33, totalUnions: 49, totalOperations: 168, totalEventuallyConsistent: 88 }
166+ const { ref, source, branch } = detectUpstreamRef ();
167+ // { ref: "stable/8.8", source: "branch-match", branch: "stable/8.8" }
168+ ```
169+
170+ ### Utility exports
171+
172+ ``` typescript
173+ import {
174+ hashDirectoryTree , // SHA-256 hash of a directory for drift detection
175+ listFilesRecursive , // List all files in a directory recursively
176+ findPathLocalLikeRefs , // Find surviving path-local $like refs in a spec
177+ } from ' camunda-schema-bundler' ;
97178```
98179
99180## Bundling Pipeline
100181
101- 1 . ** Bundle** — ` SwaggerParser.bundle() ` merges multi-file YAML into a single document
102- 2 . ** Augment** — Scan all upstream YAML files and add any schemas missing from the bundle
103- 3 . ** Normalize** — Rewrite path-local ` $ref ` s back to ` #/components/schemas/... ` using:
182+ 1 . ** Fetch** (optional) — Sparse git clone of [ camunda/camunda] ( https://github.com/camunda/camunda ) to extract only the OpenAPI spec directory
183+ 2 . ** Bundle** — ` SwaggerParser.bundle() ` merges multi-file YAML into a single document
184+ 3 . ** Augment** — Scan all upstream YAML files and add any schemas missing from the bundle
185+ 4 . ** Normalize** — Rewrite path-local ` $ref ` s back to ` #/components/schemas/... ` using:
104186 - Signature matching (canonical JSON comparison against known component schemas)
105- - ` $like ` → ` LikeFilter ` rewrite
187+ - ` $like ` → ` LikeFilter ` rewrite (handles both ` $like ` and ` %24like ` encoded forms)
106188 - Manual overrides for known tricky paths
107189 - Inline deduplication
108190 - ` x-semantic-type ` extension rewriting
109- 4 . ** Rewrite** — Decode URI-encoded internal refs (` %24like ` → ` $like ` )
110- 5 . ** Validate** — Fail-fast if any path-local ` $like ` refs survive (configurable)
111- 6 . ** Dereference** (optional) — Inline remaining path-local ` $ref ` s for strict generators
112- 7 . ** Extract metadata** — Build the intermediate representation
191+ 5 . ** Promote** — Inline schemas that couldn't be matched to existing components are promoted to new named component schemas
192+ 6 . ** Fresh dedup** — Iterative pass (up to 10 rounds until convergence) that deduplicates newly-promoted schemas against each other and existing components using signature matching, including resolution through intermediate ` $ref ` chains
193+ 7 . ** Rewrite** — Decode URI-encoded internal refs (` %24like ` → ` $like ` )
194+ 8 . ** Validate** — Fail-fast if any path-local ` $like ` refs survive (configurable with ` --allow-like-refs ` )
195+ 9 . ** Dereference** (optional, ` --deref-path-local ` ) — Inline remaining path-local ` $ref ` s for strict generators
196+ 10 . ** Extract metadata** — Build the intermediate representation (semantic keys, unions, operations, etc.)
113197
114198## Metadata IR
115199
0 commit comments