@octalmesh/seagull-core 0.0.2 → 0.1.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 (38) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +173 -39
  3. package/dist/index.mjs +218 -152
  4. package/package.json +6 -6
  5. package/src/config/loader.test.ts +505 -0
  6. package/src/config/loader.ts +31 -12
  7. package/src/config/publishing.test.ts +92 -0
  8. package/src/config/publishing.ts +9 -5
  9. package/src/config/resolve-config-file.test.ts +60 -0
  10. package/src/config/schema.test.ts +466 -0
  11. package/src/config/schema.ts +16 -10
  12. package/src/config/spec-format.test.ts +54 -0
  13. package/src/config/spec-format.ts +48 -0
  14. package/src/config/template.test.ts +168 -0
  15. package/src/config/types.ts +3 -3
  16. package/src/generator/generator.test.ts +59 -0
  17. package/src/generator/registry.test.ts +84 -0
  18. package/src/generator/types.ts +9 -14
  19. package/src/generators/openapi-generator-cli/openapi-generator-cli.generator.test.ts +259 -0
  20. package/src/generators/openapi-generator-cli/patchers/go-module.patcher.test.ts +119 -0
  21. package/src/generators/openapi-generator-cli/patchers/maven.patcher.test.ts +141 -0
  22. package/src/generators/openapi-generator-cli/patchers/npm.patcher.test.ts +132 -0
  23. package/src/generators/openapi-typescript/openapi-typescript.generator.test.ts +190 -0
  24. package/src/git/git.test.ts +234 -0
  25. package/src/git/git.ts +50 -4
  26. package/src/index.ts +8 -0
  27. package/src/process/exec.test.ts +103 -0
  28. package/src/process/exec.ts +1 -2
  29. package/src/process/resolve-bin.test.ts +43 -0
  30. package/src/readme/default-templates.test.ts +179 -0
  31. package/src/readme/default-templates.ts +5 -10
  32. package/src/readme/readme-renderer.test.ts +121 -0
  33. package/src/readme/readme-renderer.ts +3 -7
  34. package/src/redocly/redocly-sync.test.ts +190 -0
  35. package/src/redocly/redocly-sync.ts +3 -1
  36. package/src/test-support/fixtures.ts +65 -0
  37. package/src/version/version.test.ts +93 -0
  38. package/src/version/version.ts +4 -2
package/CHANGELOG.md ADDED
@@ -0,0 +1,38 @@
1
+ # @octalmesh/seagull-core
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - ec5c83b: Add LICENSE file to individual npm packages.
8
+ - 71ab054: Expand supported Node.js and pnpm version ranges in `engines` to improve
9
+ compatibility.
10
+
11
+ ## 0.1.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 3e1d383: Restructured into a monorepo of internal, private packages
16
+ (`@octalmesh/seagull-core`, `@octalmesh/seagull-cli`, `@octalmesh/seagull-docs`)
17
+ bundled into the single published `@octalmesh/seagull` package - nothing
18
+ changes for consumers of the CLI itself.
19
+
20
+ - `seagull.yaml` now requires a top-level `configVersion: 1` field, decoupled
21
+ from the npm package's own version - it only changes when the config
22
+ schema itself changes in a breaking way. **Action required:** add
23
+ `configVersion: 1` to existing configs.
24
+ - 3e1d383: `paths.specFormat` lets bundled specs be written as `yaml` as well as (or
25
+ instead of) `json` - Redocly's `bundle` already infers its output format
26
+ from the file extension on its own, seagull just wasn't giving it the
27
+ choice. Accepts a single value (`specFormat: yaml`) or a list
28
+ (`specFormat: [json, yaml]`) to bundle into more than one format at once;
29
+ defaults to `json`, unchanged from before. When more than one format is
30
+ configured, the first one listed is the "primary" format SDK generation,
31
+ version/hash resolution, and the docs site actually read from - the rest
32
+ are bundled as additional static artifacts alongside it.
33
+
34
+ `seagull.yaml` (and `redocly.base.yaml`) now also support the YAML `<<:
35
+ *anchor` merge key, the same pattern used in Docker Compose files, so a
36
+ config can define a `defaults: &defaults {...}` block once and reuse it
37
+ across e.g. multiple `generators:` entries instead of repeating the same
38
+ fields everywhere.
package/README.md CHANGED
@@ -1,52 +1,186 @@
1
- # @octalmesh/seagull-core
2
-
3
- **Internal package** - not published to npm on its own. This is the config
4
- loading + SDK generator engine, bundled straight into
5
- [`@octalmesh/seagull`](../..) at build time (see the root `tsdown.config.ts`).
6
- It's organized as its own package for a clean internal boundary, not as a
7
- separately installable one.
8
-
9
- See the [main README](https://github.com/OctalMesh/Seagull#readme) for the
10
- full config reference (`generators:`, `contracts:`, `publishing:`, custom
11
- README templates, ...) and the [`@octalmesh/seagull`](../..) package for the
12
- actual public API surface (this package's exports, re-exported).
13
-
14
- ## What lives here
15
-
16
- - `config/` - the `seagull.yaml` schema (zod), loader, `{...}` template
17
- engine, and publishing-conventions resolution.
18
- - `generator/` - the `Generator` abstract primitive and `GeneratorRegistry`
19
- every concrete generator plugs into.
20
- - `generators/` - the built-in `openapi-generator-cli` and `openapi-typescript`
21
- generator implementations.
22
- - `readme/` - README rendering for generated SDK artifacts (custom template
23
- or built-in default, per language/kind).
24
- - `redocly/` - keeps `redocly.yaml` in sync with `seagull.yaml`.
25
- - `git/`, `process/`, `version/` - small process/git/versioning utilities
26
- used by the pipeline commands (which live in
27
- [`@octalmesh/seagull-cli`](../cli)).
28
-
29
- ## Extending seagull with a custom generator
30
-
31
- `Generator` is the root primitive every SDK generator implements -
32
- `GeneratorRegistry` looks one up by the `tool` name referenced in
33
- `generators.*.tool` in the config:
1
+ <!--suppress HtmlDeprecatedAttribute, HtmlUnknownTarget -->
2
+ <h1 id="title" align="center">@octalmesh/seagull-core</h1>
3
+
4
+ <div align="center">
5
+ <!-- Version Badge -->
6
+ <a rel="noopener noreferrer" href="https://npmjs.com/package/@octalmesh/seagull-core">
7
+ <picture>
8
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/npm/v/@octalmesh/seagull-core?style=for-the-badge&label=Version&color=363636&labelColor=464646&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTEgNy44di01UTEuMiAxLjIgMi44IDFoNXEuNyAwIDEuMi41bDYuMyA2LjNhMiAyIDAgMCAxIDAgMi40bC01IDVhMiAyIDAgMCAxLTIuNSAwTDEuNSA5QTIgMiAwIDAgMSAxIDcuOG0xLjUgMFY4bDYuMyA2LjJoLjRsNS01di0uNEw4IDIuNmwtLjItLjFoLTVsLS4zLjNaTTYgNWExIDEgMCAxIDEgMCAyIDEgMSAwIDAgMSAwLTIiLz48L3N2Zz4=" />
9
+ <img alt="Version" src="https://img.shields.io/npm/v/@octalmesh/seagull-core?style=for-the-badge&label=Version&color=fff&labelColor=eaeaea&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzM2MzYzNiIgZD0iTTEgNy44di01UTEuMiAxLjIgMi44IDFoNXEuNyAwIDEuMi41bDYuMyA2LjNhMiAyIDAgMCAxIDAgMi40bC01IDVhMiAyIDAgMCAxLTIuNSAwTDEuNSA5QTIgMiAwIDAgMSAxIDcuOG0xLjUgMFY4bDYuMyA2LjJoLjRsNS01di0uNEw4IDIuNmwtLjItLjFoLTVsLS4zLjNaTTYgNWExIDEgMCAxIDEgMCAyIDEgMSAwIDAgMSAwLTIiLz48L3N2Zz4=" />
10
+ </picture>
11
+ </a>
12
+ <!-- NPM Downloads Badge -->
13
+ <a rel="noopener noreferrer" href="https://www.npmjs.com/package/@octalmesh/seagull-core">
14
+ <picture>
15
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/npm/dm/@octalmesh/seagull-core?style=for-the-badge&logo=npm&color=363636&labelColor=464646" />
16
+ <img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@octalmesh/seagull-core?style=for-the-badge&logo=npm&logoColor=464646&color=fff&labelColor=eaeaea" />
17
+ </picture>
18
+ </a>
19
+ <!-- License Badge -->
20
+ <a rel="noopener noreferrer" href="LICENSE.md">
21
+ <picture>
22
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/license/OctalMesh/Seagull?style=for-the-badge&color=363636&labelColor=464646&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTguOC44VjJoMXEuMyAwIC44LjJsMS4zLjhoMi40YS44LjggMCAwIDEgMCAxLjVoLS41TDE2IDkuMmExIDEgMCAwIDEtLjEuOGwtLjUtLjUuNS41di4xbC0uOC40cS0uNi41LTIgLjVhNSA1IDAgMCAxLTItLjVsLS43LS40YTEgMSAwIDAgMS0uMi0xbDItNC42cS0uNiAwLTEtLjJMMTAgMy41SDguN1YxM2gyLjZhLjguOCAwIDAgMSAwIDEuNUg0LjhhLjguOCAwIDAgMSAwLTEuNWgyLjVWMy41SDZMNSA0LjNsLTEgLjIgMiA0LjdhMSAxIDAgMCAxLS4xLjhsLS41LS41LjUuNXYuMWwtLjguNHEtLjYuNS0yIC41YTUgNSAwIDAgMS0yLS41bC0uNy0uNEExIDEgMCAwIDEgMCA5bDItNC42aC0uNGEuOC44IDAgMCAxIDAtMS41aDIuNGwxLjMtLjguOS0uMmgxVi44YS44LjggMCAwIDEgMS41IDBtMi45IDguNHEuNC4zIDEuMy4zYy45IDAgMS0uMSAxLjMtLjNMMTMgNi4zWm0tMTAgMHEuNC4zIDEuMy4zYy45IDAgMS0uMSAxLjMtLjNMMyA2LjNaIi8+PC9zdmc+" />
23
+ <img alt="License" src="https://img.shields.io/github/license/OctalMesh/Seagull?style=for-the-badge&color=fff&labelColor=eaeaea&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzM2MzYzNiIgZD0iTTguOC44VjJoMXEuMyAwIC44LjJsMS4zLjhoMi40YS44LjggMCAwIDEgMCAxLjVoLS41TDE2IDkuMmExIDEgMCAwIDEtLjEuOGwtLjUtLjUuNS41di4xbC0uOC40cS0uNi41LTIgLjVhNSA1IDAgMCAxLTItLjVsLS43LS40YTEgMSAwIDAgMS0uMi0xbDItNC42cS0uNiAwLTEtLjJMMTAgMy41SDguN1YxM2gyLjZhLjguOCAwIDAgMSAwIDEuNUg0LjhhLjguOCAwIDAgMSAwLTEuNWgyLjVWMy41SDZMNSA0LjNsLTEgLjIgMiA0LjdhMSAxIDAgMCAxLS4xLjhsLS41LS41LjUuNXYuMWwtLjguNHEtLjYuNS0yIC41YTUgNSAwIDAgMS0yLS41bC0uNy0uNEExIDEgMCAwIDEgMCA5bDItNC42aC0uNGEuOC44IDAgMCAxIDAtMS41aDIuNGwxLjMtLjguOS0uMmgxVi44YS44LjggMCAwIDEgMS41IDBtMi45IDguNHEuNC4zIDEuMy4zYy45IDAgMS0uMSAxLjMtLjNMMTMgNi4zWm0tMTAgMHEuNC4zIDEuMy4zYy45IDAgMS0uMSAxLjMtLjNMMyA2LjNaIi8+PC9zdmc+" />
24
+ </picture>
25
+ </a>
26
+ </div>
27
+
28
+ <div align="center">
29
+ <h6>
30
+ <a rel="noopener noreferrer" href="../../README.md">Main Readme</a>
31
+ ·
32
+ <a rel="noopener noreferrer" href="../cli/README.md">seagull-cli</a>
33
+ ·
34
+ <a rel="noopener noreferrer" href="../docs/README.md">seagull-docs</a>
35
+ </h6>
36
+ </div>
37
+
38
+ Published independently for anyone who wants just this piece - e.g. scripting
39
+ against `loadConfig()` without pulling in the CLI's `commander` dependency or
40
+ the docs bundle. Most people should install [`@octalmesh/seagull`](../..)
41
+ instead, which bundles this package (and `-cli`/`-docs`) into one.
42
+
43
+ <div align="center">
44
+ <h2 id="what-lives-here">What lives here</h2>
45
+ </div>
46
+
47
+ | Path | What it is |
48
+ |--------------------|-----------------------------------------------------------------------------------------------------------------------------------|
49
+ | `config/` | The `seagull.yaml` zod schema, loader, `{...}` template engine, `paths.specFormat` helpers, and publishing-conventions resolution |
50
+ | `generator/` | The `Generator` abstract primitive and the `GeneratorRegistry` every concrete generator plugs into |
51
+ | `generators/` | The built-in `openapi-generator-cli` and `openapi-typescript` generator implementations |
52
+ | `readme/` | README rendering for generated SDK artifacts (custom template or built-in default, per language/kind) |
53
+ | `redocly/` | Keeps `redocly.yaml` in sync with `seagull.yaml` |
54
+ | `version/` | `hashSpec`/`resolveVersion` - content hashing and `info.version` extraction from a bundled spec |
55
+ | `git/`, `process/` | Small git/process utilities (`run`, `resolveBinPath`, `assertSafeRefName`, ...) used by the pipeline commands |
56
+
57
+ <div align="center">
58
+ <h2 id="the-generator-primitive">The Generator primitive</h2>
59
+ </div>
60
+
61
+ ```mermaid
62
+ flowchart LR
63
+ A["seagull.yaml<br/>generators.*.tool"] --> B{{"GeneratorRegistry.resolve(tool)"}}
64
+ B -->|"openapi-generator"| C["OpenApiGeneratorCli"]
65
+ B -->|"openapi-typescript"| D["OpenApiTypescriptGenerator"]
66
+ C --> E(["generate(ctx) -> dist/sdk/&lt;contract&gt;/&lt;artifact&gt;"])
67
+ D --> E
68
+
69
+ classDef node fill:#363636,stroke:#666,color:#fff,rx:6,ry:6
70
+ classDef result fill:#1f6feb,stroke:#1f6feb,color:#fff,rx:20,ry:20
71
+ class A,B,C,D node
72
+ class E result
73
+ ```
74
+
75
+ `GeneratorRegistry` looks up one `Generator` instance per **tool** (`SdkTool`,
76
+ currently `"openapi-generator" | "openapi-typescript"` - a closed union, not an
77
+ open plugin-name string) - one instance per underlying tool, not per language,
78
+ since a single `openapi-generator-cli -g java`/`-g go` invocation already covers
79
+ every language that tool supports.
34
80
 
35
81
  ```ts
36
82
  import { Generator, GeneratorRegistry } from "@octalmesh/seagull-core";
37
83
  import type { GenerateContext } from "@octalmesh/seagull-core";
38
84
 
39
- class MyGenerator extends Generator {
40
- readonly tool = "my-tool";
85
+ class MyOpenApiGeneratorCli extends Generator {
86
+ readonly tool = "openapi-generator"; // must be an existing SdkTool value
41
87
 
42
88
  async generate(ctx: GenerateContext): Promise<void> {
43
- // ...
89
+ // your own openapi-generator-cli invocation, patching, etc.
44
90
  }
45
91
  }
46
92
 
47
- const registry = new GeneratorRegistry().register(new MyGenerator());
93
+ const registry = new GeneratorRegistry().register(new MyOpenApiGeneratorCli());
48
94
  ```
49
95
 
50
- ## License
96
+ `tool` is typed `SdkTool`, so this is swapping the *implementation* behind an
97
+ existing tool name (useful if you want different generator behavior than the
98
+ built-in `OpenApiGeneratorCli`/`OpenApiTypescriptGenerator`, in your own script
99
+ built on `loadConfig()` + a custom `GeneratorRegistry`) - it's not a way to add
100
+ a brand-new third tool name to `generators.*.tool` in `seagull.yaml` itself,
101
+ since the CLI's own registry and the config schema both only know about the two
102
+ built-in values today.
51
103
 
52
- MIT
104
+ <div align="center">
105
+ <!--
106
+ =====================
107
+ FOOTER
108
+ =====================
109
+ -->
110
+ <h1></h1>
111
+ <br />
112
+ <!-- OctalMesh Logo -->
113
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com">
114
+ <picture>
115
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/logo/svg/octal_mesh_center.svg" />
116
+ <img alt="OctalMesh" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/logo/svg/octal_mesh_center_white.svg" height="48" />
117
+ </picture>
118
+ </a>
119
+ <br /><br />
120
+ <!-- Socials -->
121
+ <div>
122
+ <!-- Telegram Badge -->
123
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/telegram">
124
+ <picture>
125
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/telegram.svg" />
126
+ <img alt="Telegram" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/telegram_white.svg" width="48" />
127
+ </picture>
128
+ </a>
129
+ &nbsp;
130
+ <!-- YouTube Badge -->
131
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/youtube">
132
+ <picture>
133
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/youtube.svg" />
134
+ <img alt="YouTube" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/youtube_white.svg" width="48" />
135
+ </picture>
136
+ </a>
137
+ &nbsp;
138
+ <!-- TikTok Badge -->
139
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/tiktok">
140
+ <picture>
141
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/tiktok.svg" />
142
+ <img alt="TikTok" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/tiktok_white.svg" width="48" />
143
+ </picture>
144
+ </a>
145
+ &nbsp;
146
+ <!-- Instagram Badge -->
147
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/instagram">
148
+ <picture>
149
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/instagram.svg" />
150
+ <img alt="Instagram" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/instagram_white.svg" width="48" />
151
+ </picture>
152
+ </a>
153
+ &nbsp;
154
+ <!-- X Badge -->
155
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/x">
156
+ <picture>
157
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/x.svg" />
158
+ <img alt="X" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/x_white.svg" width="48" />
159
+ </picture>
160
+ </a>
161
+ &nbsp;
162
+ <!-- Reddit Badge -->
163
+ <a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/reddit">
164
+ <picture>
165
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/reddit.svg" />
166
+ <img alt="Reddit" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/reddit_white.svg" width="48" />
167
+ </picture>
168
+ </a>
169
+ </div>
170
+ </div>
171
+ <h6>
172
+ <div align="center">
173
+ • • •
174
+ <br /><br />
175
+ This project is licensed under the <a rel="noopener noreferrer" href="../../LICENSE.md">MIT License</a>
176
+ <br /><br />
177
+ </div>
178
+ <div align="justify">
179
+ <ul>
180
+ <li>Feel free to use this project for any purpose, including commercial applications.</li>
181
+ <li>You are permitted to modify, distribute, and include this project in any form, as long as the original copyright notice is retained.</li>
182
+ <li>If you share or publish modified versions, attribution to the original <a rel="noopener noreferrer" href="https://github.com/OctalMesh/Seagull">GitHub repository</a> is appreciated.</li>
183
+ <li>This software is provided "as is", without any warranties or guarantees, as detailed in the license terms.</li>
184
+ </ul>
185
+ </div>
186
+ </h6>