@octalmesh/seagull 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.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OctalMesh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # seagull
2
+
3
+ Contract-first OpenAPI SDK, docs, and publishing pipeline - driven by a
4
+ single config file. Point it at your `openapi.yaml` files, tell it which SDK
5
+ artifacts you want (TypeScript client, Go server stubs, Java client, ...),
6
+ and it lints, bundles, generates, documents, and publishes them.
7
+
8
+ Built to manage **several services' contracts from one place** - each
9
+ service just needs an entry in the config; each artifact is generated by a
10
+ reusable, shareable "recipe".
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install -D @octalmesh/seagull
16
+ # or
17
+ pnpm add -D @octalmesh/seagull
18
+ ```
19
+
20
+ Under the hood, `generate` shells out to
21
+ [`@openapitools/openapi-generator-cli`](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)
22
+ (needs a JVM on `PATH`) and
23
+ [`openapi-typescript`](https://www.npmjs.com/package/openapi-typescript);
24
+ `lint`/`bundle` use [`@redocly/cli`](https://www.npmjs.com/package/@redocly/cli);
25
+ `docs` uses [`@scalar/api-reference`](https://www.npmjs.com/package/@scalar/api-reference).
26
+ All four are seagull's own dependencies - nothing extra to install.
27
+
28
+ ## Quick start
29
+
30
+ Create a config file at the root of your contracts repo - any of
31
+ `.seagull`, `.seagull.yaml`, `.seagull.yml`, `seagull.yaml`, `seagull.yml`:
32
+
33
+ ```yaml
34
+ # seagull.yaml
35
+ github:
36
+ owner: your-org
37
+ repo: your-contracts-repo
38
+
39
+ vars:
40
+ org: your-org
41
+
42
+ docs:
43
+ server:
44
+ host: localhost
45
+ port: 8080
46
+ metadata:
47
+ title: "API Reference"
48
+ description: "..."
49
+ favicon: https://your-domain.com/favicon.ico
50
+ baseServerUrl: https://api.your-domain.com
51
+
52
+ generators:
53
+ ts-client:
54
+ tool: openapi-generator
55
+ generator: typescript-fetch
56
+ lang: typescript
57
+ kind: client
58
+ package: "@{vars.org}/{service}-client"
59
+ additionalProperties:
60
+ supportsES6: true
61
+
62
+ contracts:
63
+ - name: auth
64
+ title: Auth Service API
65
+ entrypoint: specs/auth/openapi.yaml
66
+ artifacts: [ts-client]
67
+ ```
68
+
69
+ Then:
70
+
71
+ ```bash
72
+ npx seagull lint
73
+ npx seagull bundle
74
+ npx seagull generate
75
+ npx seagull docs generate && npx seagull docs serve
76
+ ```
77
+
78
+ ## Configuration
79
+
80
+ Everything lives in the one config file:
81
+
82
+ - **`generators:`** - reusable recipes: a `tool` (`openapi-generator` or
83
+ `openapi-typescript`), which `-g` template to use, and naming templates
84
+ for the npm package / Go module / Maven coordinates. Any string field may
85
+ reference `{vars.some.nested.key}`, `{github.owner}`, `{github.repo}`, or
86
+ `{service}` (the current contract's `name`).
87
+ - **`contracts:`** - one entry per service (`name`, `title`, `entrypoint`,
88
+ and which `generators:` it wants under `artifacts:`, by id). Two services
89
+ don't need the same generators - a contract can reference a generator with
90
+ a per-contract override instead of duplicating the whole recipe:
91
+
92
+ ```yaml
93
+ contracts:
94
+ - name: payment
95
+ artifacts:
96
+ - generator: java-client
97
+ as: java-client-legacy # renames this artifact's output folder/branch/tag
98
+ overrides:
99
+ generator: java-legacy-template
100
+ additionalProperties: { library: jersey2 }
101
+ ```
102
+
103
+ - **`vars:`** - a free-form tree for anything used in naming templates.
104
+ Nest however deep is useful; every leaf is addressable as `{vars.a.b.c}`.
105
+ - **`paths:`** - only `dist:` is required; `specs`/`docs`/`sdk` default to
106
+ `<dist>/specs`, `<dist>/docs`, `<dist>/sdk` and only need to be set to
107
+ override that.
108
+ - **`docs:`** - `server: { host, port }` for `docs serve`, and
109
+ `metadata: { title, description, favicon, baseServerUrl }` for the
110
+ generated Scalar site.
111
+
112
+ A typo or missing field fails immediately with a readable, path-annotated
113
+ error - config is validated with [zod](https://zod.dev) on every run.
114
+
115
+ ### Custom README templates
116
+
117
+ Every generated artifact gets a `README.md` - by default a sensible
118
+ built-in template for its language/kind. To use your own, point `readme:`
119
+ at a template file (path relative to the config file):
120
+
121
+ ```yaml
122
+ generators:
123
+ ts-client:
124
+ # ...
125
+ readme: readme-templates/ts-client.md
126
+ ```
127
+
128
+ Template files support the same `{...}` placeholders as naming templates,
129
+ plus a few more:
130
+
131
+ | Placeholder | Value |
132
+ |------------------------------------------------------------|--------------------------------------------------|
133
+ | `{service}` | The contract's `name` |
134
+ | `{title}` | The contract's `title` |
135
+ | `{version}` | The resolved SDK version |
136
+ | `{vars.*}` | Anything under `vars:` |
137
+ | `{github.owner}` / `{github.repo}` | From `github:` |
138
+ | `{artifact.id}` | The artifact's id (as listed under `artifacts:`) |
139
+ | `{artifact.package}` | Resolved npm package name (TypeScript) |
140
+ | `{artifact.goModule}` / `{artifact.goPackageName}` | Resolved Go naming |
141
+ | `{artifact.maven.groupId}` / `{artifact.maven.artifactId}` | Resolved Maven coordinates |
142
+ | `{artifact.branch}` / `{artifact.tagPrefix}` | Publishing branch/tag prefix |
143
+
144
+ An unresolvable placeholder fails the build loudly (a typo'd
145
+ `{vesion}` won't silently ship as literal text).
146
+
147
+ ## Commands
148
+
149
+ ```
150
+ seagull lint Lint every contract with Redocly
151
+ seagull bundle Bundle every contract's spec into dist/specs
152
+ seagull generate Generate every configured SDK artifact into dist/sdk
153
+ seagull clean Remove the dist directory
154
+ seagull docs generate Generate the Scalar documentation site into dist/docs
155
+ seagull docs serve Serve the generated documentation site locally
156
+ seagull publish sdk [--dry-run] Publish generated SDKs to their git branches/tags
157
+ seagull publish registries [--dry-run]
158
+ npm publish / mvn deploy the registry-backed artifacts
159
+ ```
160
+
161
+ Every command accepts `-c, --config <path>` to point at a config file
162
+ outside the current directory.
163
+
164
+ ## Programmatic API
165
+
166
+ ```ts
167
+ import { loadConfig, generateSdkCommand } from "@octalmesh/seagull";
168
+
169
+ const config = loadConfig("/path/to/seagull.yaml");
170
+ await generateSdkCommand(config);
171
+ ```
172
+
173
+ `loadConfig`, every `*Command` function, the `Generator`/`GeneratorRegistry`
174
+ primitives, and the built-in `OpenApiGeneratorCli`/`OpenApiTypescriptGenerator`
175
+ generators are all exported, for anyone who wants to script against seagull
176
+ directly or register a custom `Generator` for another tool.
177
+
178
+ ## License
179
+
180
+ MIT
package/dist/cli.mjs ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { _ as resolveConfigPath, a as generateSdkCommand, d as cleanCommand, f as bundleCommand, i as lintCommand, n as publishSdkCommand, r as publishRegistriesCommand, t as serveDocsCommand, u as generateDocsCommand, v as loadConfig } from "./serve-docs-BZaITOD0.mjs";
4
+ import { readFileSync } from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { Command } from "commander";
8
+ //#region src/cli.ts
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const pkg = JSON.parse(readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
11
+ const program = new Command();
12
+ program.name("seagull").description(pkg.description).version(pkg.version).option("-c, --config <path>", "path to the CLI config file (default: auto-detected in the current directory)");
13
+ program.command("lint").description("Lint every contract's OpenAPI spec with Redocly.").action(withErrorHandling(async () => lintCommand(resolveConfig())));
14
+ program.command("bundle").description("Bundle every contract's OpenAPI spec into dist/specs.").action(withErrorHandling(async () => bundleCommand(resolveConfig())));
15
+ program.command("generate").description("Generate every configured SDK artifact into dist/sdk.").action(withErrorHandling(async () => generateSdkCommand(resolveConfig())));
16
+ program.command("clean").description("Remove the dist output directory.").action(withErrorHandling(async () => cleanCommand(resolveConfig())));
17
+ const docs = program.command("docs").description("Documentation site commands.");
18
+ docs.command("generate").description("Generate the Scalar documentation site into dist/docs.").action(withErrorHandling(async () => generateDocsCommand(resolveConfig())));
19
+ docs.command("serve").description("Serve the generated documentation site locally.").action(withErrorHandling(async () => serveDocsCommand(resolveConfig())));
20
+ const publish = program.command("publish").description("Publishing commands.");
21
+ publish.command("sdk").description("Publish generated SDKs to their per-artifact git branches/tags.").option("--dry-run", "print what would be pushed without pushing").action(withErrorHandling(async (opts) => {
22
+ await publishSdkCommand(resolveConfig(), { dryRun: opts.dryRun });
23
+ }));
24
+ publish.command("registries").description("Publish registry-backed packages (npm publish / mvn deploy).").option("--dry-run", "print what would be published without publishing").action(withErrorHandling(async (opts) => {
25
+ await publishRegistriesCommand(resolveConfig(), { dryRun: opts.dryRun });
26
+ }));
27
+ await program.parseAsync();
28
+ /**
29
+ * Resolves and loads the config, using `--config` if given, else
30
+ * auto-discovering it in the current directory.
31
+ *
32
+ * @returns The resolved config.
33
+ */
34
+ function resolveConfig() {
35
+ const { config: configOption } = program.opts();
36
+ const configPath = configOption ? path.resolve(process.cwd(), configOption) : resolveConfigPath(process.cwd());
37
+ return loadConfig(configPath);
38
+ }
39
+ /**
40
+ * Wraps a commander action so a thrown Error prints as `seagull: <message>`
41
+ * and exits non-zero, instead of an unhandled-rejection stack trace.
42
+ *
43
+ * @param fn The action function to wrap.
44
+ * @returns A wrapped action function that handles errors.
45
+ */
46
+ function withErrorHandling(fn) {
47
+ return async (...args) => {
48
+ try {
49
+ await fn(...args);
50
+ } catch (error) {
51
+ console.error(`seagull: ${error instanceof Error ? error.message : error}`);
52
+ process.exitCode = 1;
53
+ }
54
+ };
55
+ }
56
+ //#endregion
57
+ export {};
58
+
59
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { Command } from \"commander\";\n\nimport { loadConfig } from \"@config/loader\";\nimport { resolveConfigPath } from \"@config/resolve-config-file\";\nimport type { ResolvedConfig } from \"@config/types\";\n\nimport { bundleCommand } from \"@commands/bundle\";\nimport { cleanCommand } from \"@commands/clean\";\nimport { generateDocsCommand } from \"@commands/generate-docs\";\nimport { generateSdkCommand } from \"@commands/generate-sdk\";\nimport { lintCommand } from \"@commands/lint\";\nimport { publishRegistriesCommand } from \"@commands/publish-registries\";\nimport { publishSdkCommand } from \"@commands/publish-sdk\";\nimport { serveDocsCommand } from \"@commands/serve-docs\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n readFileSync(path.join(__dirname, \"..\", \"package.json\"), \"utf8\"),\n) as { version: string; description: string };\nconst program = new Command();\n\n//<editor-fold desc=\"Commands\" defaultstate=\"collapsed\">\n\nprogram\n .name(\"seagull\")\n .description(pkg.description)\n .version(pkg.version)\n .option(\n \"-c, --config <path>\",\n \"path to the CLI config file (default: auto-detected in the current directory)\",\n );\n\nprogram\n .command(\"lint\")\n .description(\"Lint every contract's OpenAPI spec with Redocly.\")\n .action(withErrorHandling(async () => lintCommand(resolveConfig())));\n\nprogram\n .command(\"bundle\")\n .description(\"Bundle every contract's OpenAPI spec into dist/specs.\")\n .action(withErrorHandling(async () => bundleCommand(resolveConfig())));\n\nprogram\n .command(\"generate\")\n .description(\"Generate every configured SDK artifact into dist/sdk.\")\n .action(withErrorHandling(async () => generateSdkCommand(resolveConfig())));\n\nprogram\n .command(\"clean\")\n .description(\"Remove the dist output directory.\")\n .action(withErrorHandling(async () => cleanCommand(resolveConfig())));\n\nconst docs = program\n .command(\"docs\")\n .description(\"Documentation site commands.\");\n\ndocs\n .command(\"generate\")\n .description(\"Generate the Scalar documentation site into dist/docs.\")\n .action(withErrorHandling(async () => generateDocsCommand(resolveConfig())));\n\ndocs\n .command(\"serve\")\n .description(\"Serve the generated documentation site locally.\")\n .action(withErrorHandling(async () => serveDocsCommand(resolveConfig())));\n\nconst publish = program.command(\"publish\").description(\"Publishing commands.\");\n\npublish\n .command(\"sdk\")\n .description(\n \"Publish generated SDKs to their per-artifact git branches/tags.\",\n )\n .option(\"--dry-run\", \"print what would be pushed without pushing\")\n .action(\n withErrorHandling(async (opts: DryRunOptions) => {\n await publishSdkCommand(resolveConfig(), { dryRun: opts.dryRun });\n }),\n );\n\npublish\n .command(\"registries\")\n .description(\"Publish registry-backed packages (npm publish / mvn deploy).\")\n .option(\"--dry-run\", \"print what would be published without publishing\")\n .action(\n withErrorHandling(async (opts: DryRunOptions) => {\n await publishRegistriesCommand(resolveConfig(), { dryRun: opts.dryRun });\n }),\n );\n\n//</editor-fold>\n\nawait program.parseAsync();\n\ninterface DryRunOptions {\n dryRun?: boolean;\n}\n\n/**\n * Resolves and loads the config, using `--config` if given, else\n * auto-discovering it in the current directory.\n *\n * @returns The resolved config.\n */\nfunction resolveConfig(): ResolvedConfig {\n const { config: configOption } = program.opts<{ config?: string }>();\n const configPath = configOption\n ? path.resolve(process.cwd(), configOption)\n : resolveConfigPath(process.cwd());\n\n return loadConfig(configPath);\n}\n\n/**\n * Wraps a commander action so a thrown Error prints as `seagull: <message>`\n * and exits non-zero, instead of an unhandled-rejection stack trace.\n *\n * @param fn The action function to wrap.\n * @returns A wrapped action function that handles errors.\n */\nfunction withErrorHandling<Args extends unknown[]>(\n fn: (...args: Args) => Promise<void>,\n): (...args: Args) => Promise<void> {\n return async (...args: Args) => {\n try {\n await fn(...args);\n } catch (error) {\n console.error(\n `seagull: ${error instanceof Error ? error.message : error}`,\n );\n process.exitCode = 1;\n }\n };\n}\n"],"mappings":";;;;;;;;AAmBA,MAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAC7D,MAAM,MAAM,KAAK,MACf,aAAa,KAAK,KAAK,WAAW,MAAM,cAAc,GAAG,MAAM,CACjE;AACA,MAAM,UAAU,IAAI,QAAQ;AAI5B,QACG,KAAK,SAAS,CAAC,CACf,YAAY,IAAI,WAAW,CAAC,CAC5B,QAAQ,IAAI,OAAO,CAAC,CACpB,OACC,uBACA,+EACF;AAEF,QACG,QAAQ,MAAM,CAAC,CACf,YAAY,kDAAkD,CAAC,CAC/D,OAAO,kBAAkB,YAAY,YAAY,cAAc,CAAC,CAAC,CAAC;AAErE,QACG,QAAQ,QAAQ,CAAC,CACjB,YAAY,uDAAuD,CAAC,CACpE,OAAO,kBAAkB,YAAY,cAAc,cAAc,CAAC,CAAC,CAAC;AAEvE,QACG,QAAQ,UAAU,CAAC,CACnB,YAAY,uDAAuD,CAAC,CACpE,OAAO,kBAAkB,YAAY,mBAAmB,cAAc,CAAC,CAAC,CAAC;AAE5E,QACG,QAAQ,OAAO,CAAC,CAChB,YAAY,mCAAmC,CAAC,CAChD,OAAO,kBAAkB,YAAY,aAAa,cAAc,CAAC,CAAC,CAAC;AAEtE,MAAM,OAAO,QACV,QAAQ,MAAM,CAAC,CACf,YAAY,8BAA8B;AAE7C,KACG,QAAQ,UAAU,CAAC,CACnB,YAAY,wDAAwD,CAAC,CACrE,OAAO,kBAAkB,YAAY,oBAAoB,cAAc,CAAC,CAAC,CAAC;AAE7E,KACG,QAAQ,OAAO,CAAC,CAChB,YAAY,iDAAiD,CAAC,CAC9D,OAAO,kBAAkB,YAAY,iBAAiB,cAAc,CAAC,CAAC,CAAC;AAE1E,MAAM,UAAU,QAAQ,QAAQ,SAAS,CAAC,CAAC,YAAY,sBAAsB;AAE7E,QACG,QAAQ,KAAK,CAAC,CACd,YACC,iEACF,CAAC,CACA,OAAO,aAAa,4CAA4C,CAAC,CACjE,OACC,kBAAkB,OAAO,SAAwB;CAC/C,MAAM,kBAAkB,cAAc,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC;AAClE,CAAC,CACH;AAEF,QACG,QAAQ,YAAY,CAAC,CACrB,YAAY,8DAA8D,CAAC,CAC3E,OAAO,aAAa,kDAAkD,CAAC,CACvE,OACC,kBAAkB,OAAO,SAAwB;CAC/C,MAAM,yBAAyB,cAAc,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC;AACzE,CAAC,CACH;AAIF,MAAM,QAAQ,WAAW;;;;;;;AAYzB,SAAS,gBAAgC;CACvC,MAAM,EAAE,QAAQ,iBAAiB,QAAQ,KAA0B;CACnE,MAAM,aAAa,eACf,KAAK,QAAQ,QAAQ,IAAI,GAAG,YAAY,IACxC,kBAAkB,QAAQ,IAAI,CAAC;CAEnC,OAAO,WAAW,UAAU;AAC9B;;;;;;;;AASA,SAAS,kBACP,IACkC;CAClC,OAAO,OAAO,GAAG,SAAe;EAC9B,IAAI;GACF,MAAM,GAAG,GAAG,IAAI;EAClB,SAAS,OAAO;GACd,QAAQ,MACN,YAAY,iBAAiB,QAAQ,MAAM,UAAU,OACvD;GACA,QAAQ,WAAW;EACrB;CACF;AACF"}
@@ -0,0 +1,391 @@
1
+
2
+ import { z } from "zod";
3
+ //#region src/config/schema.d.ts
4
+ /**
5
+ * A free-form tree of leaf values, used for the `vars:` block in the CLI config.
6
+ * Nest however deep is useful - every leaf becomes addressable as
7
+ * `{vars.<dot.path>}` in templated fields.
8
+ */
9
+ type VarsTree = {
10
+ [key: string]: string | number | boolean | VarsTree;
11
+ };
12
+ //#endregion
13
+ //#region src/config/types.d.ts
14
+ type SdkTool = "openapi-generator" | "openapi-typescript";
15
+ type SdkLang = "typescript" | "go" | "java";
16
+ type SdkKind = "client" | "server";
17
+ /**
18
+ * A single artifact a contract generates: a generator recipe from the CLI
19
+ * config, fully resolved (templates interpolated, overrides merged, paths made
20
+ * absolute) for one specific contract.
21
+ */
22
+ interface ResolvedArtifact {
23
+ /**
24
+ * The id this artifact is known by for this contract - the key under
25
+ * `generators:` it was resolved from, or its `as` override. Used as the
26
+ * output folder segment, and to derive the publish branch/tag.
27
+ */
28
+ id: string;
29
+ tool: SdkTool;
30
+ lang: SdkLang;
31
+ kind: SdkKind;
32
+ /** `openapi-generator -g` value. Set only when `tool` is `openapi-generator`. */
33
+ generator?: string;
34
+ /** Absolute output directory: `<sdkDir>/<contract>/<id>`. */
35
+ outputDir: string;
36
+ /** `sdk/svc-<contract>/<id>` */
37
+ branch: string;
38
+ /** `svc-<contract>-<id>` */
39
+ tagPrefix: string;
40
+ additionalProperties: Record<string, string | number | boolean>;
41
+ package?: string;
42
+ goModule?: string;
43
+ goPackageName?: string;
44
+ maven?: {
45
+ groupId: string;
46
+ artifactId: string;
47
+ };
48
+ /**
49
+ * Absolute path to a custom README template, if `readme:` was set for this
50
+ * generator/artifact. Falls back to a built-in default template when unset -
51
+ * see `core/readme/readme-renderer.ts`.
52
+ */
53
+ readmeTemplate?: string;
54
+ }
55
+ interface ResolvedContract {
56
+ name: string;
57
+ title: string;
58
+ /** Absolute path to the source `openapi.yaml`. */
59
+ entrypoint: string;
60
+ /**
61
+ * Path to the source `openapi.yaml`, relative to `rootDir` - what
62
+ * `redocly.yaml`'s `apis:` section wants.
63
+ */
64
+ entrypointRelative: string;
65
+ artifacts: ResolvedArtifact[];
66
+ }
67
+ /**
68
+ * One (contract, artifact) pair - the flattened unit of work most commands
69
+ * actually iterate over.
70
+ */
71
+ interface ResolvedArtifactEntry {
72
+ contract: ResolvedContract;
73
+ artifact: ResolvedArtifact;
74
+ }
75
+ interface ResolvedConfig {
76
+ /**
77
+ * Directory containing the config file - every relative path in the config
78
+ * (entrypoints, `paths.*`, `readme` templates, ...) resolves against this.
79
+ */
80
+ rootDir: string;
81
+ paths: {
82
+ dist: string;
83
+ specs: string;
84
+ docs: string;
85
+ sdk: string;
86
+ };
87
+ github: {
88
+ owner: string;
89
+ repo: string;
90
+ };
91
+ vars: VarsTree;
92
+ docs: {
93
+ server: {
94
+ host: string;
95
+ port: number;
96
+ };
97
+ metadata: {
98
+ title: string;
99
+ description: string;
100
+ favicon: string;
101
+ baseServerUrl: string;
102
+ };
103
+ };
104
+ contracts: ResolvedContract[];
105
+ /**
106
+ * Every (contract, artifact) pair across every contract, in config order -
107
+ * the flat list most commands iterate over.
108
+ */
109
+ allArtifacts: ResolvedArtifactEntry[];
110
+ }
111
+ //#endregion
112
+ //#region src/config/loader.d.ts
113
+ /**
114
+ * Loads, validates, and fully resolves a CLI config file - the single entry
115
+ * point every command uses to get its configuration.
116
+ *
117
+ * Unlike a build tool bundled into the consumer's own repo, seagull is
118
+ * installed as a dependency, so it has no way to guess where the
119
+ * consumer's config lives on its own - `configPath` must be supplied by the
120
+ * caller (the CLI resolves it via `resolveConfigPath()` in
121
+ * `config/resolve-config-file.ts`, or `--config`).
122
+ *
123
+ * @param configPath - Absolute path to the CLI config file.
124
+ * @returns The fully resolved config.
125
+ */
126
+ declare function loadConfig(configPath: string): ResolvedConfig;
127
+ //#endregion
128
+ //#region src/config/resolve-config-file.d.ts
129
+ /**
130
+ * Config filenames CLI recognizes, checked in this order.
131
+ */
132
+ declare const CONFIG_FILENAMES: readonly [".seagull", ".seagull.yaml", ".seagull.yml", "seagull.yaml", "seagull.yml"];
133
+ /**
134
+ * Finds the CLI config file in a directory, trying each of
135
+ * {@link CONFIG_FILENAMES} in order.
136
+ *
137
+ * @param cwd - The directory to look in (typically `process.cwd()`).
138
+ * @returns The absolute path to the first matching config file.
139
+ * @throws Error if none of the candidate filenames exist in `cwd`.
140
+ *
141
+ * @see {@link CONFIG_FILENAMES} - the list of filenames checked, in order.
142
+ */
143
+ declare function resolveConfigPath(cwd: string): string;
144
+ //#endregion
145
+ //#region src/core/generator/types.d.ts
146
+ /** Passed once per tool to {@link Generator.prepare}, before any of that
147
+ * tool's {@link Generator.generate} calls run. */
148
+ interface PrepareContext {
149
+ rootDir: string;
150
+ /**
151
+ * Every (contract, artifact) pair that uses this generator's `tool`, across
152
+ * all contracts.
153
+ */
154
+ entries: ResolvedArtifactEntry[];
155
+ }
156
+ /** Passed once per artifact to {@link Generator.generate}. */
157
+ interface GenerateContext {
158
+ rootDir: string;
159
+ contract: ResolvedContract;
160
+ artifact: ResolvedArtifact;
161
+ version: string;
162
+ github: {
163
+ owner: string;
164
+ repo: string;
165
+ };
166
+ /**
167
+ * Absolute path to the contract's bundled JSON spec
168
+ * (`<specsDir>/<contract>.json`).
169
+ */
170
+ specInputPath: string;
171
+ }
172
+ //#endregion
173
+ //#region src/core/generator/generator.d.ts
174
+ /**
175
+ * The root primitive every concrete SDK generator implements.
176
+ *
177
+ * One instance per underlying tool (`openapi-generator-cli`,
178
+ * `openapi-typescript`, ...) - not one per language, since a single tool
179
+ * invocation (e.g. `openapi-generator-cli -g java`/`-g go`) already covers
180
+ * every language it supports. Language-specific behaviour (patching `go.mod`,
181
+ * `package.json`, `pom.xml`, ...) is composed in via patchers rather than
182
+ * living in per-language subclasses.
183
+ */
184
+ declare abstract class Generator {
185
+ abstract readonly tool: SdkTool;
186
+ /**
187
+ * Optional one-time setup step, run once per tool before any of that tool's
188
+ * {@link generate} calls - for tools like `openapi-typescript` that generate
189
+ * every contract's output in a single global invocation instead of one call
190
+ * per artifact.
191
+ *
192
+ * @param ctx - Every (contract, artifact) pair using this generator's tool.
193
+ */
194
+ prepare?(ctx: PrepareContext): Promise<void>;
195
+ /**
196
+ * Generates a single artifact.
197
+ *
198
+ * @param ctx - The contract, artifact, and resolved version to generate for.
199
+ */
200
+ abstract generate(ctx: GenerateContext): Promise<void>;
201
+ }
202
+ //#endregion
203
+ //#region src/core/generator/registry.d.ts
204
+ /**
205
+ * Looks up the concrete {@link Generator} implementation for a given tool name.
206
+ */
207
+ declare class GeneratorRegistry {
208
+ private readonly generators;
209
+ /**
210
+ * Registers a generator implementation under its own {@link Generator.tool}.
211
+ *
212
+ * @param generator - The generator instance to register.
213
+ * @returns `this`, for chaining.
214
+ */
215
+ register(generator: Generator): this;
216
+ /**
217
+ * Resolves the generator implementation for a given tool name.
218
+ *
219
+ * @param tool - The tool name, e.g. `"openapi-generator"`.
220
+ * @returns The registered generator.
221
+ * @throws Error if no generator is registered for that tool.
222
+ */
223
+ resolve(tool: SdkTool): Generator;
224
+ /**
225
+ * All distinct tools currently registered.
226
+ *
227
+ * @returns The registered tool names.
228
+ */
229
+ tools(): SdkTool[];
230
+ }
231
+ //#endregion
232
+ //#region src/core/process/resolve-bin.d.ts
233
+ /**
234
+ * Resolves the absolute path to an installed npm package's own CLI entrypoint
235
+ * script, using Node's standard module resolution algorithm - so it works the
236
+ * same way regardless of which package manager (npm/pnpm/yarn) installed CLI
237
+ * and its dependencies, or how deeply they get hoisted. Shelling out to
238
+ * `pnpm exec`/`npx` instead would assume a specific package manager and a
239
+ * particular install layout, which doesn't hold once CLI is just another
240
+ * dependency in someone else's project.
241
+ *
242
+ * @param pkgName - The npm package name, e.g. `"@org/cli"`.
243
+ * @param binName - Which entry to resolve from that package's `bin` field.
244
+ * Defaults to the package's own unscoped name.
245
+ * @returns The absolute path to the resolved bin script.
246
+ * @throws Error if the package or the requested bin entry can't be found.
247
+ */
248
+ declare function resolveBinPath(pkgName: string, binName?: string): string;
249
+ //#endregion
250
+ //#region src/core/process/exec.d.ts
251
+ /**
252
+ * Runs a command to completion, streaming its stdio straight through
253
+ * (`inherit`), and rejects if it exits non-zero.
254
+ *
255
+ * This is the async counterpart used for the "one long-running tool" commands
256
+ * (`redocly`, `openapi-generator-cli`, `openapi-typescript`); for short
257
+ * synchronous calls (git plumbing, `npm publish`/`mvn deploy`), see
258
+ * {@link runSync}.
259
+ *
260
+ * @param command - The executable to run.
261
+ * @param args - Arguments to pass to it.
262
+ * @param cwd - The working directory to run it in.
263
+ * @returns A promise that resolves on exit code 0, and rejects otherwise.
264
+ */
265
+ declare function run(command: string, args: string[], cwd: string): Promise<void>;
266
+ /**
267
+ * Runs a command to completion synchronously, streaming its stdio straight
268
+ * through (`inherit`).
269
+ *
270
+ * @param command - The executable to run.
271
+ * @param args - Arguments to pass to it.
272
+ * @param cwd - The working directory to run it in.
273
+ * @returns The exit status (0 on success).
274
+ */
275
+ declare function runSync(command: string, args: string[], cwd: string): number;
276
+ //#endregion
277
+ //#region src/generators/openapi-generator-cli/openapi-generator-cli.generator.d.ts
278
+ /**
279
+ * Wraps `openapi-generator-cli` - the single tool implementation behind every
280
+ * `-g` template (`typescript-fetch`, `go`, `go-server`, `java`, `spring`, ...),
281
+ * regardless of language. Language-specific output patching is delegated to a
282
+ * {@link Patcher}, selected by `artifact.lang`.
283
+ */
284
+ declare class OpenApiGeneratorCli extends Generator {
285
+ readonly tool: SdkTool;
286
+ private readonly patchers;
287
+ generate(ctx: GenerateContext): Promise<void>;
288
+ }
289
+ //#endregion
290
+ //#region src/generators/openapi-typescript/openapi-typescript.generator.d.ts
291
+ /**
292
+ * Wraps `openapi-typescript`. Unlike `openapi-generator-cli`, it isn't invoked
293
+ * once per artifact - it reads `redocly.yaml`'s `apis:` map (kept in sync with
294
+ * the CLI config by `core/redocly/redocly-sync.ts`) and writes every contract's
295
+ * `index.d.ts` to its configured `x-openapi-ts.output` path in a single run,
296
+ * so that single global invocation happens once in {@link prepare}.
297
+ * {@link generate} then only has to write each artifact's package.json` -
298
+ * `openapi-typescript` emits `index.d.ts` alone, with no package manifest of
299
+ * its own to patch.
300
+ */
301
+ declare class OpenApiTypescriptGenerator extends Generator {
302
+ readonly tool: SdkTool;
303
+ prepare({ rootDir, entries }: PrepareContext): Promise<void>;
304
+ generate({ contract, artifact, version, github }: GenerateContext): Promise<void>;
305
+ }
306
+ //#endregion
307
+ //#region src/commands/bundle.d.ts
308
+ /**
309
+ * Bundles every contract's OpenAPI spec into `dist/specs/<contract>.json`.
310
+ *
311
+ * @param config - The resolved CLI config.
312
+ */
313
+ declare function bundleCommand(config: ResolvedConfig): Promise<void>;
314
+ //#endregion
315
+ //#region src/commands/clean.d.ts
316
+ /**
317
+ * Removes the entire `dist` output directory.
318
+ *
319
+ * @param config - The resolved CLI config.
320
+ */
321
+ declare function cleanCommand(config: ResolvedConfig): Promise<void>;
322
+ //#endregion
323
+ //#region src/commands/generate-docs.d.ts
324
+ /**
325
+ * Generates the documentation website for every contract into `dist/docs`.
326
+ *
327
+ * @param config - The resolved CLI config.
328
+ */
329
+ declare function generateDocsCommand(config: ResolvedConfig): Promise<void>;
330
+ //#endregion
331
+ //#region src/commands/generate-sdk.d.ts
332
+ /**
333
+ * Generates SDK packages for every artifact of every contract in the config.
334
+ *
335
+ * @param config - The resolved config.
336
+ */
337
+ declare function generateSdkCommand(config: ResolvedConfig): Promise<void>;
338
+ //#endregion
339
+ //#region src/commands/lint.d.ts
340
+ /**
341
+ * Lints every contract's OpenAPI spec.
342
+ * Sets `process.exitCode = 1` if any contract fails.
343
+ *
344
+ * @param config - The resolved CLI config.
345
+ */
346
+ declare function lintCommand(config: ResolvedConfig): Promise<void>;
347
+ //#endregion
348
+ //#region src/commands/publish-registries.d.ts
349
+ interface PublishRegistriesOptions {
350
+ dryRun?: boolean;
351
+ }
352
+ /**
353
+ * Publishes registry-backed packages:
354
+ * - TypeScript (client and server-types) -> npm (needs a configured registry
355
+ * or auth token on the machine running this).
356
+ * - Java (client and server) -> Maven (needs `~/.m2/settings.xml` credentials
357
+ * for whichever repository `mvn deploy` resolves to).
358
+ *
359
+ * Go packages are intentionally skipped - they're consumed straight from
360
+ * their git branch/tag (see `publish-sdk.ts`), Go has no registry step.
361
+ *
362
+ * @param config - The resolved CLI config.
363
+ * @param options - `{ dryRun }` - print what would run without running it.
364
+ */
365
+ declare function publishRegistriesCommand(config: ResolvedConfig, options?: PublishRegistriesOptions): Promise<void>;
366
+ //#endregion
367
+ //#region src/commands/publish-sdk.d.ts
368
+ interface PublishSdkOptions {
369
+ dryRun?: boolean;
370
+ }
371
+ /**
372
+ * Redistributes each generated artifact's `dist/sdk/<contract>/<artifact-id>`
373
+ * into its own orphan branch (`sdk/svc-<contract>/<artifact-id>`) and tags the
374
+ * publish.
375
+ *
376
+ * @param config - The resolved CLI config.
377
+ * @param options - `{ dryRun }` - skip pushing, just report what would happen.
378
+ */
379
+ declare function publishSdkCommand(config: ResolvedConfig, options?: PublishSdkOptions): Promise<void>;
380
+ //#endregion
381
+ //#region src/commands/serve-docs.d.ts
382
+ /**
383
+ * Serves the generated documentation site (`dist/docs`) over plain HTTP for
384
+ * local previewing.
385
+ *
386
+ * @param config - The resolved CLI config.
387
+ */
388
+ declare function serveDocsCommand(config: ResolvedConfig): Promise<void>;
389
+ //#endregion
390
+ export { CONFIG_FILENAMES, type GenerateContext, Generator, GeneratorRegistry, OpenApiGeneratorCli, OpenApiTypescriptGenerator, type PrepareContext, type PublishRegistriesOptions, type PublishSdkOptions, type ResolvedArtifact, type ResolvedArtifactEntry, type ResolvedConfig, type ResolvedContract, type SdkKind, type SdkLang, type SdkTool, type VarsTree, bundleCommand, cleanCommand, generateDocsCommand, generateSdkCommand, lintCommand, loadConfig, publishRegistriesCommand, publishSdkCommand, resolveBinPath, resolveConfigPath, run, runSync, serveDocsCommand };
391
+ //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { _ as resolveConfigPath, a as generateSdkCommand, c as Generator, d as cleanCommand, f as bundleCommand, g as CONFIG_FILENAMES, h as runSync, i as lintCommand, l as GeneratorRegistry, m as run, n as publishSdkCommand, o as OpenApiTypescriptGenerator, p as resolveBinPath, r as publishRegistriesCommand, s as OpenApiGeneratorCli, t as serveDocsCommand, u as generateDocsCommand, v as loadConfig } from "./serve-docs-BZaITOD0.mjs";
4
+ export { CONFIG_FILENAMES, Generator, GeneratorRegistry, OpenApiGeneratorCli, OpenApiTypescriptGenerator, bundleCommand, cleanCommand, generateDocsCommand, generateSdkCommand, lintCommand, loadConfig, publishRegistriesCommand, publishSdkCommand, resolveBinPath, resolveConfigPath, run, runSync, serveDocsCommand };