@octalmesh/seagull 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.
- package/README.md +425 -180
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +3 -1556
- package/dist/index.mjs +4 -2
- package/package.json +32 -21
- package/dist/dist-Ou2inxGj.mjs +0 -16783
- package/dist/dist-Ou2inxGj.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,104 +1,228 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
<!--suppress HtmlDeprecatedAttribute, HtmlUnknownTarget -->
|
|
2
|
+
<div align="center">
|
|
3
|
+
<!--
|
|
4
|
+
=====================
|
|
5
|
+
HEADER
|
|
6
|
+
=====================
|
|
7
|
+
-->
|
|
8
|
+
<br />
|
|
9
|
+
<a rel="noopener noreferrer" href="https://github.com/OctalMesh/Seagull">
|
|
10
|
+
<picture>
|
|
11
|
+
<source media="(prefers-color-scheme: light)" srcset="./.github/assets/svg/seagull_logo.svg">
|
|
12
|
+
<img alt="Seagull" src="./.github/assets/svg/seagull_logo_white.svg">
|
|
13
|
+
</picture>
|
|
14
|
+
</a>
|
|
15
|
+
<br /><br /><br />
|
|
16
|
+
<!--
|
|
17
|
+
=====================
|
|
18
|
+
BADGES
|
|
19
|
+
=====================
|
|
20
|
+
-->
|
|
21
|
+
<div>
|
|
22
|
+
<!-- Repo Stars Badge -->
|
|
23
|
+
<a rel="noopener noreferrer" href="https://github.com/OctalMesh/Seagull/stargazers">
|
|
24
|
+
<picture>
|
|
25
|
+
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/stars/OctalMesh/Seagull?style=for-the-badge&logo=starship&color=363636&labelColor=464646" />
|
|
26
|
+
<img alt="Stars" src="https://img.shields.io/github/stars/OctalMesh/Seagull?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+DQogIDxwYXRoIGZpbGw9IiMzNjM2MzYiIGQ9Ik04IC4yNWEuNzUuNzUgMCAwIDEgLjY3My40MThsMS44ODIgMy44MTUgNC4yMS42MTJhLjc1Ljc1IDAgMCAxIC40MTYgMS4yNzlsLTMuMDQ2IDIuOTcuNzE5IDQuMTkyYS43NTEuNzUxIDAgMCAxLTEuMDg4Ljc5MUw4IDEyLjM0N2wtMy43NjYgMS45OGEuNzUuNzUgMCAwIDEtMS4wODgtLjc5bC43Mi00LjE5NEwuODE4IDYuMzc0YS43NS43NSAwIDAgMSAuNDE2LTEuMjhsNC4yMS0uNjExTDcuMzI3LjY2OEEuNzUuNzUgMCAwIDEgOCAuMjVabTAgMi40NDVMNi42MTUgNS41YS43NS43NSAwIDAgMS0uNTY0LjQxbC0zLjA5Ny40NSAyLjI0IDIuMTg0YS43NS43NSAwIDAgMSAuMjE2LjY2NGwtLjUyOCAzLjA4NCAyLjc2OS0xLjQ1NmEuNzUuNzUgMCAwIDEgLjY5OCAwbDIuNzcgMS40NTYtLjUzLTMuMDg0YS43NS43NSAwIDAgMSAuMjE2LS42NjRsMi4yNC0yLjE4My0zLjA5Ni0uNDVhLjc1Ljc1IDAgMCAxLS41NjQtLjQxTDggMi42OTRaIi8+DQo8L3N2Zz4=&color=fff&labelColor=eaeaea" />
|
|
27
|
+
</picture>
|
|
28
|
+
</a>
|
|
29
|
+
<!-- Repo Contributors Badge -->
|
|
30
|
+
<a rel="noopener noreferrer" href="https://github.com/OctalMesh/Seagull/contributors">
|
|
31
|
+
<picture>
|
|
32
|
+
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/contributors/OctalMesh/Seagull?style=for-the-badge&logo=githubsponsors&logoColor=fff&color=363636&labelColor=464646" />
|
|
33
|
+
<img alt="Contributors" src="https://img.shields.io/github/contributors/OctalMesh/Seagull?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+DQogIDxwYXRoIGZpbGw9IiMzNjM2MzYiIGQ9Ik0yIDUuNWEzLjUgMy41IDAgMSAxIDUuOSAyLjU1IDUuNSA1LjUgMCAwIDEgMy4wMyA0LjA4Ljc1Ljc1IDAgMSAxLTEuNDguMjQgNCA0IDAgMCAwLTcuOSAwIC43NS43NSAwIDAgMS0xLjQ4LS4yNEE1LjUgNS41IDAgMCAxIDMuMSA4LjA1IDMuNSAzLjUgMCAwIDEgMiA1LjVaTTExIDRhMyAzIDAgMCAxIDIuMjIgNS4wMiA1LjAxIDUuMDEgMCAwIDEgMi41NiAzLjAxLjc1Ljc1IDAgMCAxLS44OC45NS43NS43NSAwIDAgMS0uNTUtLjUxIDMuNSAzLjUgMCAwIDAtMi41My0yLjM3Ljc1Ljc1IDAgMCAxLS41Ny0uNzN2LS4zNWEuNzUuNzUgMCAwIDEgLjQyLS42OEExLjUgMS41IDAgMCAwIDExIDUuNS43NS43NSAwIDAgMSAxMSA0Wm0tNS41LS41YTIgMiAwIDEgMCAwIDQgMiAyIDAgMCAwIDAtNFoiLz4NCjwvc3ZnPg==&color=fff&labelColor=eaeaea" />
|
|
34
|
+
</picture>
|
|
35
|
+
</a>
|
|
36
|
+
<!-- Repo Views Badge -->
|
|
37
|
+
<a rel="noopener noreferrer" href="https://hits.sh/github.com/OctalMesh/Seagull">
|
|
38
|
+
<picture>
|
|
39
|
+
<source media="(prefers-color-scheme: light)" srcset="https://hits.sh/github.com/OctalMesh/Seagull.svg?style=for-the-badge&label=Views&logo=github&color=363636&labelColor=464646" />
|
|
40
|
+
<img alt="Views" src="https://hits.sh/github.com/OctalMesh/Seagull.svg?style=for-the-badge&label=Views&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiPjxwYXRoIGZpbGw9IiMzNjM2MzYiIGQ9Ik01MTIgMGE1MTIgNTEyIDAgMCAwLTE2MiA5OThjMjYgNCAzNS0xMSAzNS0yNXYtOTVjLTEyOSAyNC0xNjItMzEtMTczLTYwLTUtMTUtMzAtNjAtNTItNzItMTgtMTAtNDQtMzQtMS0zNCA0MS0xIDY5IDM3IDc5IDUyIDQ2IDc4IDEyMCA1NiAxNDkgNDIgNS0zMyAxOC01NSAzMy02OC0xMTQtMTMtMjMzLTU3LTIzMy0yNTMgMC01NiAyMC0xMDIgNTItMTM3LTUtMTMtMjMtNjYgNS0xMzYgMCAwIDQzLTE0IDE0MSA1MmE0NzUgNDc1IDAgMCAxIDI1NiAwYzk4LTY2IDE0MS01MiAxNDEtNTIgMjggNzAgMTAgMTIzIDUgMTM2IDMzIDM1IDUzIDgxIDUzIDEzNyAwIDE5Ny0xMjAgMjQwLTIzNCAyNTMgMTkgMTYgMzUgNDcgMzUgOTVsLTEgMTQwYzAgMTQgMTAgMzAgMzUgMjVBNTEzIDUxMyAwIDAgMCA1MTIgMFoiLz48L3N2Zz4=&color=fff&labelColor=eaeaea" />
|
|
41
|
+
</picture>
|
|
42
|
+
</a>
|
|
43
|
+
<br />
|
|
44
|
+
<!-- Version Badge -->
|
|
45
|
+
<a rel="noopener noreferrer" href="https://npmjs.com/package/@octalmesh/seagull">
|
|
46
|
+
<picture>
|
|
47
|
+
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/npm/v/@octalmesh/seagull?style=for-the-badge&label=Version&color=363636&labelColor=464646&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTEgNy44di01UTEuMiAxLjIgMi44IDFoNXEuNyAwIDEuMi41bDYuMyA2LjNhMiAyIDAgMCAxIDAgMi40bC01IDVhMiAyIDAgMCAxLTIuNSAwTDEuNSA5QTIgMiAwIDAgMSAxIDcuOG0xLjUgMFY4bDYuMyA2LjJoLjRsNS01di0uNEw4IDIuNmwtLjItLjFoLTVsLS4zLjNaTTYgNWExIDEgMCAxIDEgMCAyIDEgMSAwIDAgMSAwLTIiLz48L3N2Zz4=" />
|
|
48
|
+
<img alt="Version" src="https://img.shields.io/npm/v/@octalmesh/seagull?style=for-the-badge&label=Version&color=fff&labelColor=eaeaea&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzM2MzYzNiIgZD0iTTEgNy44di01UTEuMiAxLjIgMi44IDFoNXEuNyAwIDEuMi41bDYuMyA2LjNhMiAyIDAgMCAxIDAgMi40bC01IDVhMiAyIDAgMCAxLTIuNSAwTDEuNSA5QTIgMiAwIDAgMSAxIDcuOG0xLjUgMFY4bDYuMyA2LjJoLjRsNS01di0uNEw4IDIuNmwtLjItLjFoLTVsLS4zLjNaTTYgNWExIDEgMCAxIDEgMCAyIDEgMSAwIDAgMSAwLTIiLz48L3N2Zz4=" />
|
|
49
|
+
</picture>
|
|
50
|
+
</a>
|
|
51
|
+
<!-- NPM Downloads Badge -->
|
|
52
|
+
<a rel="noopener noreferrer" href="https://www.npmjs.com/package/@octalmesh/seagull">
|
|
53
|
+
<picture>
|
|
54
|
+
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/npm/dm/@octalmesh/seagull?style=for-the-badge&logo=npm&color=363636&labelColor=464646" />
|
|
55
|
+
<img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@octalmesh/seagull?style=for-the-badge&logo=npm&logoColor=464646&color=fff&labelColor=eaeaea" />
|
|
56
|
+
</picture>
|
|
57
|
+
</a>
|
|
58
|
+
<!-- License Badge -->
|
|
59
|
+
<a rel="noopener noreferrer" href="LICENSE.md">
|
|
60
|
+
<picture>
|
|
61
|
+
<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+" />
|
|
62
|
+
<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+" />
|
|
63
|
+
</picture>
|
|
64
|
+
</a>
|
|
65
|
+
</div>
|
|
66
|
+
<h1></h1>
|
|
67
|
+
<!--
|
|
68
|
+
=====================
|
|
69
|
+
SOURCES
|
|
70
|
+
=====================
|
|
71
|
+
-->
|
|
72
|
+
<h6>
|
|
73
|
+
<a rel="noopener noreferrer" href="CODE_OF_CONDUCT.md">Code of Conduct</a>
|
|
74
|
+
·
|
|
75
|
+
<a rel="noopener noreferrer" href="CONTRIBUTING.md">Contributing</a>
|
|
76
|
+
·
|
|
77
|
+
<a rel="noopener noreferrer" href="SECURITY.md">Security Policy</a>
|
|
78
|
+
·
|
|
79
|
+
<a rel="noopener noreferrer" href="SUPPORT.md">Support</a>
|
|
80
|
+
·
|
|
81
|
+
<a rel="noopener noreferrer" href="RELEASING.md">Releasing</a>
|
|
82
|
+
·
|
|
83
|
+
<a rel="noopener noreferrer" href="LICENSE.md">License</a>
|
|
84
|
+
·
|
|
85
|
+
<a rel="noopener noreferrer" href="examples/README.md">Examples</a>
|
|
86
|
+
</h6>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div align="justify">
|
|
90
|
+
<!--
|
|
91
|
+
=====================
|
|
92
|
+
DESCRIPTION
|
|
93
|
+
=====================
|
|
94
|
+
-->
|
|
95
|
+
<p>
|
|
96
|
+
Seagull is a contract-first OpenAPI SDK, docs, and publishing pipeline -
|
|
97
|
+
driven by a single config file. Point it at your `openapi.yaml` files, tell
|
|
98
|
+
it which SDK artifacts you want and it lints, bundles, generates, documents,
|
|
99
|
+
and publishes them.
|
|
100
|
+
</p>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div align="center">
|
|
104
|
+
<h2 id="overview">Overview</h2>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
Built to manage several services' contracts from one place - each service just
|
|
108
|
+
needs an entry in the config; each artifact is generated by a reusable,
|
|
109
|
+
shareable "recipe".
|
|
110
|
+
|
|
111
|
+
| Stage | What it does |
|
|
112
|
+
|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
113
|
+
| **Lint** | Validates every contract's OpenAPI spec for structural and style issues |
|
|
114
|
+
| **Bundle** | Dereferences and bundles each spec into `dist/specs` |
|
|
115
|
+
| **Generate** | Runs each configured "recipe" through [`openapi-generator-cli`](https://www.npmjs.com/package/@openapitools/openapi-generator-cli) or [`openapi-typescript`](https://www.npmjs.com/package/openapi-typescript) |
|
|
116
|
+
| **Document** | Builds an interactive docs site across every contract into `dist/docs` |
|
|
117
|
+
| **Publish** | Pushes generated SDKs to orphan git branches/tags, and to artifact registries |
|
|
118
|
+
|
|
119
|
+
```mermaid
|
|
120
|
+
flowchart LR
|
|
121
|
+
A["Contract"] --> B["Lint"]
|
|
122
|
+
B --> C["Bundle<br/>(spec files)"]
|
|
123
|
+
C --> D["Generate<br/>(SDK artifacts)"]
|
|
124
|
+
C --> E["Docs website"]
|
|
125
|
+
D --> F["Publish SDK<br/>(git branch + tag)"]
|
|
126
|
+
D --> G["Publish registries<br/>(npm / Maven)"]
|
|
127
|
+
|
|
128
|
+
classDef stage fill:#363636,stroke:#666,color:#fff,rx:6,ry:6
|
|
129
|
+
class A,B,C,D,E,F,G stage
|
|
130
|
+
```
|
|
31
131
|
|
|
32
|
-
|
|
132
|
+
<div align="center">
|
|
133
|
+
<h2 id="packages">Packages</h2>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
This repo is a monorepo of four packages, all versioned and published together
|
|
137
|
+
(see [`.changeset/config.json`](.changeset/config.json)'s `fixed` group and
|
|
138
|
+
[RELEASING.md](RELEASING.md)). Most people only need the first one - it bundles
|
|
139
|
+
the other three straight into its own `dist/` via [`tsdown`](https://tsdown.dev).
|
|
140
|
+
The three internal packages are published independently too, for anyone who
|
|
141
|
+
wants a smaller dependency (e.g. scripting against just
|
|
142
|
+
`@octalmesh/seagull-core`'s config loader without pulling in the CLI or the docs
|
|
143
|
+
generator).
|
|
144
|
+
|
|
145
|
+
| Package | Role |
|
|
146
|
+
|--------------------------------------------|------------------------------------------------------------------------------------------------|
|
|
147
|
+
| [`@octalmesh/seagull`](.) | The `seagull` CLI + programmatic API. What almost everyone should install. |
|
|
148
|
+
| [`@octalmesh/seagull-core`](packages/core) | Config loading, the `Generator` primitive, built-in generators, version/publishing logic, etc. |
|
|
149
|
+
| [`@octalmesh/seagull-cli`](packages/cli) | Pipeline commands (`lint`/`bundle`/`generate`/`publish`/...) + the `commander` program. |
|
|
150
|
+
| [`@octalmesh/seagull-docs`](packages/docs) | Docs-site generation from bundled specs, plus a local dev server for previewing the site. |
|
|
151
|
+
|
|
152
|
+
<div align="center">
|
|
153
|
+
<h2 id="installation">Installation</h2>
|
|
154
|
+
</div>
|
|
33
155
|
|
|
34
156
|
```bash
|
|
35
157
|
npm install -D @octalmesh/seagull
|
|
36
|
-
# or
|
|
37
|
-
pnpm add -D @octalmesh/seagull
|
|
38
158
|
```
|
|
39
159
|
|
|
40
|
-
Under the hood, `generate` shells out to
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`docs` uses [`@scalar/api-reference`](https://www.npmjs.com/package/@scalar/api-reference).
|
|
46
|
-
All four are `@octalmesh/seagull`'s own dependencies, resolved via Node's
|
|
47
|
-
module resolution (not `npx`/`pnpm exec`) - nothing extra to install, and it
|
|
48
|
-
works the same regardless of which package manager you use.
|
|
160
|
+
Under the hood, `generate` shells out to `@openapitools/openapi-generator-cli`
|
|
161
|
+
(needs a JVM on `PATH`) and `openapi-typescript`; `lint`/`bundle` and `docs`
|
|
162
|
+
each rely on their own established OpenAPI tooling under the hood. All of these
|
|
163
|
+
are `@octalmesh/seagull`'s own dependencies, resolved via Node's module
|
|
164
|
+
resolution.
|
|
49
165
|
|
|
50
|
-
|
|
166
|
+
<div align="center">
|
|
167
|
+
<h2 id="quick-start">Quick Start</h2>
|
|
168
|
+
</div>
|
|
51
169
|
|
|
52
|
-
Create a config file at the root of your contracts repo
|
|
53
|
-
`.seagull`, `.seagull.yaml`, `.seagull.yml`, `seagull.yaml`, `seagull.yml
|
|
170
|
+
Create a config file at the root of your contracts repo (any of
|
|
171
|
+
`.seagull`, `.seagull.yaml`, `.seagull.yml`, `seagull.yaml`, `seagull.yml`):
|
|
54
172
|
|
|
55
173
|
```yaml
|
|
56
|
-
#
|
|
174
|
+
# Seagull config version
|
|
57
175
|
configVersion: 1
|
|
58
176
|
|
|
59
|
-
|
|
60
|
-
owner: your-org
|
|
61
|
-
repo: your-contracts-repo
|
|
62
|
-
|
|
177
|
+
# Custom variables to use in config
|
|
63
178
|
vars:
|
|
64
|
-
org: your-
|
|
179
|
+
org: "your-npm-scope"
|
|
180
|
+
repository:
|
|
181
|
+
owner: "your-org"
|
|
182
|
+
repo: "your-contracts-repo"
|
|
65
183
|
|
|
184
|
+
# Documentation configuration
|
|
66
185
|
docs:
|
|
67
186
|
server:
|
|
68
|
-
host: localhost
|
|
187
|
+
host: "localhost"
|
|
69
188
|
port: 8080
|
|
189
|
+
|
|
70
190
|
metadata:
|
|
71
|
-
title: "API
|
|
72
|
-
description: "
|
|
73
|
-
favicon:
|
|
74
|
-
baseServerUrl: https://api.
|
|
191
|
+
title: "Your API Docs"
|
|
192
|
+
description: "Generated API documentation"
|
|
193
|
+
favicon: "/favicon.ico"
|
|
194
|
+
baseServerUrl: "https://api.example.com"
|
|
75
195
|
|
|
196
|
+
# Publishing configuration
|
|
76
197
|
publishing:
|
|
77
198
|
branch: "sdk/svc-{service}/{id}"
|
|
78
199
|
tag: "svc-{service}-{id}-v{version}"
|
|
79
|
-
repositoryUrl: "https://github.com/{
|
|
200
|
+
repositoryUrl: "https://github.com/{vars.repository.owner}/{vars.repository.repo}"
|
|
201
|
+
|
|
80
202
|
npm:
|
|
81
|
-
registry: "https://
|
|
82
|
-
access:
|
|
203
|
+
registry: "https://registry.npmjs.org"
|
|
204
|
+
access: "public"
|
|
205
|
+
|
|
83
206
|
maven:
|
|
84
|
-
repositoryId: github
|
|
85
|
-
repositoryUrl: "https://maven.pkg.github.com/{
|
|
207
|
+
repositoryId: "github"
|
|
208
|
+
repositoryUrl: "https://maven.pkg.github.com/{vars.repository.owner}/{vars.repository.repo}"
|
|
86
209
|
|
|
210
|
+
# Generators configuration used to produce SDK artifacts
|
|
87
211
|
generators:
|
|
88
212
|
ts-client:
|
|
89
|
-
tool: openapi-generator
|
|
90
|
-
generator: typescript-fetch
|
|
91
|
-
lang: typescript
|
|
92
|
-
kind: client
|
|
213
|
+
tool: "openapi-generator"
|
|
214
|
+
generator: "typescript-fetch"
|
|
215
|
+
lang: "typescript"
|
|
216
|
+
kind: "client"
|
|
93
217
|
package: "@{vars.org}/{service}-client"
|
|
94
|
-
additionalProperties:
|
|
95
|
-
supportsES6: true
|
|
96
218
|
|
|
219
|
+
# Per-service contract configuration
|
|
97
220
|
contracts:
|
|
98
|
-
- name: auth
|
|
99
|
-
title: Auth Service API
|
|
100
|
-
entrypoint: specs/auth/openapi.yaml
|
|
101
|
-
artifacts:
|
|
221
|
+
- name: "auth"
|
|
222
|
+
title: "Auth Service API"
|
|
223
|
+
entrypoint: "specs/auth/openapi.yaml"
|
|
224
|
+
artifacts:
|
|
225
|
+
- "ts-client"
|
|
102
226
|
```
|
|
103
227
|
|
|
104
228
|
Then:
|
|
@@ -110,79 +234,133 @@ npx seagull generate
|
|
|
110
234
|
npx seagull docs generate && npx seagull docs serve
|
|
111
235
|
```
|
|
112
236
|
|
|
113
|
-
|
|
237
|
+
See [`examples/`](examples/README.md) for complete, runnable configs covering
|
|
238
|
+
every generator/publishing/docs feature, plus an API walkthrough.
|
|
239
|
+
|
|
240
|
+
<div align="center">
|
|
241
|
+
<h2 id="configuration">Configuration</h2>
|
|
242
|
+
</div>
|
|
114
243
|
|
|
115
|
-
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
- **`generators:`** - reusable recipes: a `tool` (`openapi-generator` or
|
|
244
|
+
- `configVersion:` (required) - which version of the config schema this file
|
|
245
|
+
targets. Decoupled from `@octalmesh/seagull`'s own npm version on purpose:
|
|
246
|
+
this only changes if `seagull.yaml`'s shape changes in a breaking way, so an
|
|
247
|
+
old config fails with a clear "expected configVersion 1" error.
|
|
248
|
+
|
|
249
|
+
- `generators:` - reusable recipes: a `tool` (`openapi-generator` or
|
|
122
250
|
`openapi-typescript`), which `-g` template to use, and naming templates
|
|
123
251
|
for the npm package / Go module / Maven coordinates. Any string field may
|
|
124
|
-
reference `{vars.some.nested.key}
|
|
125
|
-
`
|
|
126
|
-
- **`contracts:`** - one entry per service (`name`, `title`, `entrypoint`,
|
|
127
|
-
and which `generators:` it wants under `artifacts:`, by id). Two services
|
|
128
|
-
don't need the same generators - a contract can reference a generator with
|
|
129
|
-
a per-contract override instead of duplicating the whole recipe:
|
|
252
|
+
reference `{vars.some.nested.key}` or `{service}` (the current contract's
|
|
253
|
+
`name`).
|
|
130
254
|
|
|
255
|
+
- `contracts:` - one entry per service (`name`, `title`, `entrypoint`, and which
|
|
256
|
+
`generators:` it wants under `artifacts:`, by id). Two services don't need the
|
|
257
|
+
same generators - a contract can reference a generator with a per-contract
|
|
258
|
+
override instead of duplicating the whole recipe:
|
|
131
259
|
```yaml
|
|
132
260
|
contracts:
|
|
133
|
-
- name: payment
|
|
261
|
+
- name: "payment"
|
|
134
262
|
artifacts:
|
|
135
|
-
- generator: java-client
|
|
136
|
-
as: java-client-legacy # renames this artifact's output folder/branch/tag
|
|
263
|
+
- generator: "java-client"
|
|
264
|
+
as: "java-client-legacy" # renames this artifact's output folder/branch/tag
|
|
137
265
|
overrides:
|
|
138
|
-
generator: java-legacy-template
|
|
139
|
-
additionalProperties:
|
|
266
|
+
generator: "java-legacy-template"
|
|
267
|
+
additionalProperties:
|
|
268
|
+
library: "jersey2"
|
|
140
269
|
```
|
|
141
270
|
|
|
142
|
-
-
|
|
143
|
-
|
|
144
|
-
|
|
271
|
+
- `vars:` - a free-form tree for anything used in naming templates. Nest however
|
|
272
|
+
deep is useful; every leaf is addressable as `{vars.a.b.c}`.
|
|
273
|
+
|
|
274
|
+
- `paths:` - only `dist:` is required; `specs`/`docs`/`sdk` default to
|
|
145
275
|
`<dist>/specs`, `<dist>/docs`, `<dist>/sdk` and only need to be set to
|
|
146
|
-
override that.
|
|
147
|
-
|
|
276
|
+
override that. `specFormat:` controls what format(s) `seagull bundle` writes
|
|
277
|
+
specs in - `json` (default), `yaml`, or a list of both
|
|
278
|
+
(`specFormat: [json, yaml]`) to bundle into more than one format at once;
|
|
279
|
+
Redocly infers the output format from the file extension on its own, so
|
|
280
|
+
this is a free choice, not a compatibility trade-off. When more than one
|
|
281
|
+
format is configured, the first one listed is the "primary" format SDK
|
|
282
|
+
generation and the docs site actually read from - the rest are bundled as
|
|
283
|
+
additional static artifacts alongside it.
|
|
284
|
+
|
|
285
|
+
- `docs:` - `server: { host, port }` for `docs serve`, and
|
|
148
286
|
`metadata: { title, description, favicon, baseServerUrl }` for the
|
|
149
287
|
generated docs site.
|
|
150
|
-
- **`publishing:`** (required) - see below.
|
|
151
288
|
|
|
152
|
-
|
|
153
|
-
|
|
289
|
+
- `publishing:` (required) - see below.
|
|
290
|
+
|
|
291
|
+
A typo or missing field fails immediately with a readable, path-annotated error.
|
|
292
|
+
Config is validated on every run.
|
|
293
|
+
|
|
294
|
+
`seagull.yaml` (and `redocly.base.yaml`) also support the YAML `<<: *anchor`
|
|
295
|
+
merge key, so shared fields don't need to be repeated across every entry:
|
|
296
|
+
|
|
297
|
+
```yaml
|
|
298
|
+
_defaults: &defaults
|
|
299
|
+
lang: "typescript"
|
|
300
|
+
|
|
301
|
+
generators:
|
|
302
|
+
ts-server:
|
|
303
|
+
<<: *defaults
|
|
304
|
+
tool: "openapi-typescript"
|
|
305
|
+
kind: "server"
|
|
306
|
+
package: "@{vars.org}/{service}-server"
|
|
307
|
+
|
|
308
|
+
ts-client:
|
|
309
|
+
<<: *defaults
|
|
310
|
+
tool: "openapi-generator"
|
|
311
|
+
generator: "typescript-fetch"
|
|
312
|
+
kind: "client"
|
|
313
|
+
package: "@{vars.org}/{service}-client"
|
|
314
|
+
```
|
|
154
315
|
|
|
155
|
-
|
|
316
|
+
<h3 id="publishing">Publishing</h3>
|
|
156
317
|
|
|
157
|
-
`publishing:` controls where things get published to - git branch/tag
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
318
|
+
`publishing:` controls where things get published to - git branch/tag naming,
|
|
319
|
+
and npm/Maven registry URLs. It's required at the root level: seagull has no
|
|
320
|
+
built-in convention here, so a config that omits it fails validation with a
|
|
321
|
+
message pointing at exactly what's missing, rather than silently applying an
|
|
322
|
+
opinionated default nobody chose.
|
|
162
323
|
|
|
163
324
|
```yaml
|
|
164
325
|
publishing:
|
|
165
|
-
branch: "sdk/svc-{service}/{id}"
|
|
166
|
-
tag: "svc-{service}-{id}-v{version}"
|
|
167
|
-
repositoryUrl: "https://github.com/{
|
|
326
|
+
branch: "sdk/svc-{service}/{id}" # git branch each artifact publishes to
|
|
327
|
+
tag: "svc-{service}-{id}-v{version}" # git tag - the only field where {version} is available
|
|
328
|
+
repositoryUrl: "https://github.com/{vars.repository.owner}/{vars.repository.repo}" # git remote URL for pushing branches/tags
|
|
329
|
+
|
|
168
330
|
npm:
|
|
169
331
|
registry: "https://npm.pkg.github.com"
|
|
170
|
-
access: restricted # or "public"
|
|
332
|
+
access: "restricted" # or "public"
|
|
333
|
+
|
|
171
334
|
maven:
|
|
172
|
-
repositoryId: github
|
|
173
|
-
repositoryUrl: "https://maven.pkg.github.com/{
|
|
335
|
+
repositoryId: "github"
|
|
336
|
+
repositoryUrl: "https://maven.pkg.github.com/{vars.repository.owner}/{vars.repository.repo}"
|
|
174
337
|
```
|
|
175
338
|
|
|
176
|
-
Every field is a template - the same `{...}` engine as naming templates,
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
339
|
+
Every field is a template - the same `{...}` engine as naming templates, plus
|
|
340
|
+
`{id}` (the artifact's id) and, for `tag` only, `{version}` (resolved once the
|
|
341
|
+
contract's spec is bundled, since a branch is created before a version is known
|
|
342
|
+
but a tag isn't).
|
|
180
343
|
|
|
181
344
|
Like `additionalProperties` and `readme`, `publishing:` can be overridden
|
|
182
345
|
per-generator (`generators.<id>.publishing`) or per-contract-artifact
|
|
183
346
|
(`artifacts[].overrides.publishing`) - only the fields that differ need
|
|
184
347
|
repeating, the rest fall through to the root-level config:
|
|
185
348
|
|
|
349
|
+
```mermaid
|
|
350
|
+
flowchart TD
|
|
351
|
+
A["Root config<br/>(fallback for everything)"] --> B["Generator override<br/>(per recipe)"]
|
|
352
|
+
B --> C["Artifact override<br/>(per contract)"]
|
|
353
|
+
C --> D(["Effective config<br/>for this artifact"])
|
|
354
|
+
|
|
355
|
+
classDef layer fill:#363636,stroke:#666,color:#fff,rx:6,ry:6
|
|
356
|
+
classDef result fill:#1f6feb,stroke:#1f6feb,color:#fff,rx:20,ry:20
|
|
357
|
+
class A,B,C layer
|
|
358
|
+
class D result
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
The same three-layer precedence (root -> generator -> artifact `overrides`)
|
|
362
|
+
applies to `additionalProperties` and `readme` too, not just `publishing`.
|
|
363
|
+
|
|
186
364
|
```yaml
|
|
187
365
|
generators:
|
|
188
366
|
ts-client:
|
|
@@ -192,92 +370,159 @@ generators:
|
|
|
192
370
|
registry: "https://registry.internal.example.com" # every contract's ts-client uses this registry
|
|
193
371
|
|
|
194
372
|
contracts:
|
|
195
|
-
- name: payment
|
|
373
|
+
- name: "payment"
|
|
196
374
|
artifacts:
|
|
197
|
-
- generator: ts-client
|
|
375
|
+
- generator: "ts-client"
|
|
198
376
|
overrides:
|
|
199
377
|
publishing:
|
|
200
378
|
branch: "custom/{service}-{id}-branch" # ...except payment's ts-client, which also uses a different branch
|
|
201
379
|
```
|
|
202
380
|
|
|
203
|
-
|
|
381
|
+
<h3 id="custom-readme-templates">Custom README templates</h3>
|
|
204
382
|
|
|
205
|
-
Every generated artifact gets a `README.md` - by default a sensible
|
|
206
|
-
|
|
207
|
-
|
|
383
|
+
Every generated artifact gets a `README.md` - by default a sensible built-in
|
|
384
|
+
template for its language/kind. To use your own, point `readme:` at a template
|
|
385
|
+
file (path relative to the config file):
|
|
208
386
|
|
|
209
387
|
```yaml
|
|
210
388
|
generators:
|
|
211
389
|
ts-client:
|
|
212
390
|
# ...
|
|
213
|
-
readme: readme-templates/ts-client.md
|
|
391
|
+
readme: "readme-templates/ts-client.md"
|
|
214
392
|
```
|
|
215
393
|
|
|
216
|
-
Template files support the same `{...}` placeholders as naming templates,
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
| Placeholder
|
|
220
|
-
|
|
221
|
-
| `{service}`
|
|
222
|
-
| `{title}`
|
|
223
|
-
| `{version}`
|
|
224
|
-
| `{vars.*}`
|
|
225
|
-
| `{
|
|
226
|
-
| `{artifact.
|
|
227
|
-
| `{artifact.
|
|
228
|
-
| `{artifact.
|
|
229
|
-
| `{artifact.
|
|
230
|
-
| `{artifact.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
394
|
+
Template files support the same `{...}` placeholders as naming templates, plus a
|
|
395
|
+
few more:
|
|
396
|
+
|
|
397
|
+
| Placeholder | Value |
|
|
398
|
+
|------------------------------------------------------------|--------------------------------------------------|
|
|
399
|
+
| `{service}` | The contract's `name` |
|
|
400
|
+
| `{title}` | The contract's `title` |
|
|
401
|
+
| `{version}` | The resolved SDK version |
|
|
402
|
+
| `{vars.*}` | Anything under `vars:` |
|
|
403
|
+
| `{artifact.id}` | The artifact's id (as listed under `artifacts:`) |
|
|
404
|
+
| `{artifact.package}` | Resolved npm package name (TypeScript) |
|
|
405
|
+
| `{artifact.goModule}` / `{artifact.goPackageName}` | Resolved Go naming |
|
|
406
|
+
| `{artifact.maven.groupId}` / `{artifact.maven.artifactId}` | Resolved Maven coordinates |
|
|
407
|
+
| `{artifact.branch}` / `{artifact.tag}` | Resolved publishing branch / tag |
|
|
408
|
+
| `{artifact.npmRegistry}` / `{artifact.mavenRepositoryUrl}` | Resolved registry URLs from `publishing:` |
|
|
409
|
+
|
|
410
|
+
An unresolvable placeholder fails the build loudly (a typo'd `{vesion}` won't
|
|
411
|
+
silently ship as literal text).
|
|
412
|
+
|
|
413
|
+
<div align="center">
|
|
414
|
+
<h2 id="commands">Commands</h2>
|
|
415
|
+
</div>
|
|
237
416
|
|
|
238
417
|
```
|
|
239
|
-
seagull lint
|
|
240
|
-
seagull bundle
|
|
241
|
-
seagull generate
|
|
242
|
-
seagull clean
|
|
243
|
-
seagull docs generate
|
|
244
|
-
seagull docs serve
|
|
245
|
-
seagull publish sdk [--dry-run]
|
|
246
|
-
seagull publish registries [--dry-run]
|
|
247
|
-
npm publish / mvn deploy the registry-backed artifacts
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
Every command accepts `-c, --config <path>` to point at a config file
|
|
251
|
-
outside the current directory.
|
|
252
|
-
|
|
253
|
-
## Programmatic API
|
|
254
|
-
|
|
255
|
-
```ts
|
|
256
|
-
import { loadConfig, generateSdkCommand } from "@octalmesh/seagull";
|
|
257
|
-
|
|
258
|
-
const config = loadConfig("/path/to/seagull.yaml");
|
|
259
|
-
await generateSdkCommand(config);
|
|
418
|
+
seagull lint Lint every contract's OpenAPI spec
|
|
419
|
+
seagull bundle Bundle every contract's spec into dist/specs
|
|
420
|
+
seagull generate Generate every configured SDK artifact into dist/sdk
|
|
421
|
+
seagull clean Remove the dist directory
|
|
422
|
+
seagull docs generate Generate the documentation site into dist/docs
|
|
423
|
+
seagull docs serve Serve the generated documentation site locally
|
|
424
|
+
seagull publish sdk [--dry-run] Publish generated SDKs to their git branches/tags
|
|
425
|
+
seagull publish registries [--dry-run] npm publish / mvn deploy the registry-backed artifacts
|
|
260
426
|
```
|
|
261
427
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
built-in `OpenApiGeneratorCli`/`OpenApiTypescriptGenerator` generators are
|
|
265
|
-
all exported, for anyone who wants to script against seagull directly or
|
|
266
|
-
register a custom `Generator` for another tool.
|
|
428
|
+
Every command accepts `-c, --config <path>` to point at a config file outside
|
|
429
|
+
the current directory.
|
|
267
430
|
|
|
268
|
-
|
|
431
|
+
<div align="center">
|
|
432
|
+
<h2 id="development">Development</h2>
|
|
433
|
+
</div>
|
|
269
434
|
|
|
270
435
|
```bash
|
|
271
|
-
pnpm install
|
|
272
|
-
pnpm run build
|
|
273
|
-
pnpm run typecheck
|
|
274
|
-
pnpm run lint
|
|
275
|
-
pnpm run test
|
|
436
|
+
pnpm install # install dependencies for all packages
|
|
437
|
+
pnpm run build # builds packages/* first (topological), then bundles the root package
|
|
438
|
+
pnpm run typecheck # run after build - resolves the workspace packages via their built dist/
|
|
439
|
+
pnpm run lint # lint all packages
|
|
440
|
+
pnpm run test # run all tests
|
|
276
441
|
```
|
|
277
442
|
|
|
278
|
-
See [CONTRIBUTING.md](
|
|
279
|
-
[RELEASING.md](
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
443
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for how to propose changes, and
|
|
444
|
+
[RELEASING.md](RELEASING.md) for how versioning and publishing work.
|
|
445
|
+
|
|
446
|
+
<div align="center">
|
|
447
|
+
<!--
|
|
448
|
+
=====================
|
|
449
|
+
FOOTER
|
|
450
|
+
=====================
|
|
451
|
+
-->
|
|
452
|
+
<h1></h1>
|
|
453
|
+
<br />
|
|
454
|
+
<!-- OctalMesh Logo -->
|
|
455
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com">
|
|
456
|
+
<picture>
|
|
457
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/logo/svg/octal_mesh_center.svg" />
|
|
458
|
+
<img alt="OctalMesh" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/logo/svg/octal_mesh_center_white.svg" height="48" />
|
|
459
|
+
</picture>
|
|
460
|
+
</a>
|
|
461
|
+
<br /><br />
|
|
462
|
+
<!-- Socials -->
|
|
463
|
+
<div>
|
|
464
|
+
<!-- Telegram Badge -->
|
|
465
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/telegram">
|
|
466
|
+
<picture>
|
|
467
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/telegram.svg" />
|
|
468
|
+
<img alt="Telegram" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/telegram_white.svg" width="48" />
|
|
469
|
+
</picture>
|
|
470
|
+
</a>
|
|
471
|
+
|
|
472
|
+
<!-- YouTube Badge -->
|
|
473
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/youtube">
|
|
474
|
+
<picture>
|
|
475
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/youtube.svg" />
|
|
476
|
+
<img alt="YouTube" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/youtube_white.svg" width="48" />
|
|
477
|
+
</picture>
|
|
478
|
+
</a>
|
|
479
|
+
|
|
480
|
+
<!-- TikTok Badge -->
|
|
481
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/tiktok">
|
|
482
|
+
<picture>
|
|
483
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/tiktok.svg" />
|
|
484
|
+
<img alt="TikTok" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/tiktok_white.svg" width="48" />
|
|
485
|
+
</picture>
|
|
486
|
+
</a>
|
|
487
|
+
|
|
488
|
+
<!-- Instagram Badge -->
|
|
489
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/instagram">
|
|
490
|
+
<picture>
|
|
491
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/instagram.svg" />
|
|
492
|
+
<img alt="Instagram" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/instagram_white.svg" width="48" />
|
|
493
|
+
</picture>
|
|
494
|
+
</a>
|
|
495
|
+
|
|
496
|
+
<!-- X Badge -->
|
|
497
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/x">
|
|
498
|
+
<picture>
|
|
499
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/x.svg" />
|
|
500
|
+
<img alt="X" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/x_white.svg" width="48" />
|
|
501
|
+
</picture>
|
|
502
|
+
</a>
|
|
503
|
+
|
|
504
|
+
<!-- Reddit Badge -->
|
|
505
|
+
<a rel="noopener noreferrer" target="_blank" href="https://octalmesh.com/reddit">
|
|
506
|
+
<picture>
|
|
507
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/reddit.svg" />
|
|
508
|
+
<img alt="Reddit" src="https://raw.githubusercontent.com/OctalMesh/OctalDesign/release/assets/icon/svg/reddit_white.svg" width="48" />
|
|
509
|
+
</picture>
|
|
510
|
+
</a>
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
<h6>
|
|
514
|
+
<div align="center">
|
|
515
|
+
• • •
|
|
516
|
+
<br /><br />
|
|
517
|
+
This project is licensed under the <a rel="noopener noreferrer" href="../../LICENSE.md">MIT License</a>
|
|
518
|
+
<br /><br />
|
|
519
|
+
</div>
|
|
520
|
+
<div align="justify">
|
|
521
|
+
<ul>
|
|
522
|
+
<li>Feel free to use this project for any purpose, including commercial applications.</li>
|
|
523
|
+
<li>You are permitted to modify, distribute, and include this project in any form, as long as the original copyright notice is retained.</li>
|
|
524
|
+
<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>
|
|
525
|
+
<li>This software is provided "as is", without any warranties or guarantees, as detailed in the license terms.</li>
|
|
526
|
+
</ul>
|
|
527
|
+
</div>
|
|
528
|
+
</h6>
|