perseid 0.5.1 → 0.7.0

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 (3) hide show
  1. package/README.md +123 -53
  2. package/checksums.json +4 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,47 +1,58 @@
1
-
2
1
  <p align="center"><img src=".github/cover.svg" alt="perseid: OpenAPI in, idiomatic SDKs out" width="100%"></p>
3
2
 
4
3
  # perseid
5
4
 
6
- Change your OpenAPI spec, and idiomatic Rust, TypeScript, Python, Go, Java and C# SDKs regenerate
7
- and land as pull requests, in one repository or one per language.
5
+ **Idiomatic SDKs, always in sync with your OpenAPI spec.**
8
6
 
9
- One static binary, running in your CI: an open-source and headless alternative to Fern, Speakeasy and Stainless.
7
+ perseid generates Rust, TypeScript, Python, Go, Java and C# SDKs. When the spec changes, a GitHub
8
+ Action regenerates them, opens a pull request, and releases them to their registries once you
9
+ merge. It is one static binary. There is no hosted service, no account and no subscription.
10
10
 
11
- ## Get started
11
+ ## Why perseid
12
12
 
13
- ```sh
14
- # in the repository that will hold your SDKs
15
- npx perseid init # which SDKs, where they live → perseid.toml
16
- npx perseid generate # optional local preview
17
- npx perseid setup # GitHub side: workflows, releases
13
+ - **Code you would write by hand.** Resource namespaces, typed models and errors, iterators over
14
+ paginated lists. No `DefaultApi`, no `getPetsWithHttpInfo`.
15
+ - **Your CI, your repositories.** Generation runs in a GitHub Actions job you can read. SDKs live
16
+ next to your API, in one SDKs repository, or in a repository per language.
17
+ - **Releases included.** Each pull request is sized from the spec diff, so a breaking change asks
18
+ for a major bump. release-please tags each SDK and publishes it with trusted publishing.
19
+ - **Your edits survive.** perseid only rewrites or deletes files it marked `@generated`.
20
+
21
+ ## Quick start
18
22
 
19
- # spec in another repository (even private)? run there:
20
- npx perseid connect acme/acme-sdks # pushes the spec on each release or change
23
+ In the repository that holds your OpenAPI spec:
24
+
25
+ ```sh
26
+ npx perseid init # pick the languages and where the SDKs live
27
+ gh secret set PERSEID_TOKEN # paste a fine-grained token, see below
28
+ git add -A && git commit -m "ci: generate SDKs with perseid" && git push
21
29
  ```
22
30
 
23
- | Command | Runs in | Does |
24
- |---|---|---|
25
- | `init` | the SDKs repository | writes `perseid.toml`, nothing else: the spec found there, the SDKs you pick, where they live |
26
- | `generate` | the SDKs repository | writes the SDKs from `spec` (or `--spec <path\|url>`), starting each from its package skeleton |
27
- | `setup` | the SDKs repository | plans, then sets up GitHub: SDK repositories, the App, `sdks.yml`, release files |
28
- | `connect <owner/sdks-repo>` | the repository holding the spec | a deploy key and `perseid-push.yml`, pushing the spec to the SDKs repository |
31
+ The push runs the `SDKs` workflow, which opens a pull request with every SDK.
32
+
33
+ `PERSEID_TOKEN` is a [fine-grained token](https://github.com/settings/personal-access-tokens/new)
34
+ with **Contents**, **Pull requests** and **Workflows** set to read and write, on this repository
35
+ and the SDK repositories. Fine-grained tokens expire, and perseid warns 30 days before.
36
+ `npx perseid app` sets up a GitHub App instead, which doesn't expire.
37
+
38
+ To see the SDKs before pushing anything:
39
+
40
+ ```sh
41
+ npx perseid generate --out /tmp/sdks # every SDK in /tmp/sdks/<language>
42
+ ```
29
43
 
30
- With the spec and the SDKs in one repository, `connect` isn't needed. Merge the pull requests, and
31
- every spec change (or every release of your API) lands as SDK pull requests, then releases. See
32
- [repository layouts](docs/ci.md#repository-layouts). Also installable with
33
- `curl -fsSL https://sh.meteroid.com/perseid | sh` or as the `ghcr.io/meteroid-oss/perseid` image;
34
- Linux and macOS, x64 and arm64.
44
+ perseid also installs with `curl -fsSL https://sh.meteroid.com/perseid | sh`
45
+ or runs as the `ghcr.io/meteroid-oss/perseid` image. Linux and macOS, x64 and arm64.
35
46
 
36
- What your users get:
47
+ ## What your users get
37
48
 
38
49
  ```ts
39
- const petstore = new Petstore("sk_live_...");
50
+ const petstore = new Petstore({ apiKey: "sk_live_..." });
40
51
  const pets = await petstore.pets.list({ limit: 10, status: "available" });
41
52
  ```
42
53
 
43
54
  ```python
44
- petstore = Petstore("sk_live_...")
55
+ petstore = Petstore(api_key="sk_live_...")
45
56
  pets = petstore.pets.list(limit=10, status=PetStatus.AVAILABLE)
46
57
  ```
47
58
 
@@ -50,47 +61,106 @@ using var petstore = new PetstoreClient("sk_live_...");
50
61
  var pets = await petstore.Pets.ListAsync(new() { Limit = 10, Status = PetStatus.Available });
51
62
  ```
52
63
 
53
- It powers the [Meteroid SDKs](https://github.com/meteroid-oss/meteroid-clients), and started as a fork of
54
- [Svix's openapi-codegen](https://github.com/svix/openapi-codegen).
64
+ ## Features
55
65
 
56
- ## What you get
66
+ | | |
67
+ |---|---|
68
+ | Languages | Rust, TypeScript, Python (sync and async), Go, Java, C# |
69
+ | Requests | Typed errors by status, retries with backoff and `Retry-After`, idempotency keys, per-call timeouts and headers |
70
+ | Auth | Bearer, basic, API keys, OAuth2 client credentials, token providers |
71
+ | Data | Cursor, page and offset pagination, server-sent events, file uploads |
72
+ | Models | Enums and unions that keep values the SDK does not know, unknown properties sent back |
73
+ | Webhooks | An opt-in [Standard Webhooks](https://www.standardwebhooks.com) verifier in every language |
74
+ | Docs | An `api.md` per SDK, regenerated with the code, and a README calling your API's own operations |
75
+ | Specs | OpenAPI 3.0, 3.1 and 3.2, external `$ref`s, parameter styles, nullable and recursive schemas, webhook-only specs |
76
+ | Customizing | Middleware, resource snippets, ejectable templates |
77
+ | CI | `perseid generate --check` fails when the SDKs drift from the spec |
57
78
 
58
- - **SDKs that read like handwritten code.** Typed models, tolerant enums and unions, resource
59
- namespaces with `list`/`create`/`retrieve` methods, typed errors by status, retries with
60
- `Retry-After`, per-call options, sync and async where the language has them.
61
- - **Auth, pagination and streaming.** Bearer, basic, API keys and OAuth2 tokens, iterators over
62
- paginated lists, server-sent events and file uploads.
63
- - **Your code stays yours.** Perseid only rewrites or deletes files it marked `@generated`.
64
- Middleware, resource snippets and ejectable templates cover the rest, no fork needed.
65
- - **Webhooks.** An opt-in [Standard Webhooks](https://www.standardwebhooks.com) verifier in every language.
66
- - **CI-native.** `generate --check` fails on drift, `generate --pr` opens pull requests in this
67
- repository or in dedicated SDK repositories, and every SDK is versioned and published on its own.
79
+ ## How it works
68
80
 
69
- ## In your CI
81
+ ```
82
+ openapi.json changes on main
83
+ │
84
+ ▼
85
+ sdks.yml ─ perseid generate --pr ─ oasdiff sizes the change
86
+ │
87
+ ▼
88
+ pull request "feat(api)!: update SDKs to Acme 2.0" ← you review and merge
89
+ │
90
+ ▼
91
+ sdk-release.yml ─ release-please PR ← you merge ─ tag ─ publish to npm, PyPI, crates.io…
92
+ ```
93
+
94
+ `perseid init` writes two workflows for you to commit:
95
+
96
+ - `sdks.yml` runs the `meteroid-oss/perseid` Action when the spec changes. It installs perseid
97
+ and the pinned formatters, then runs `perseid generate --pr`, which commits the SDKs to the
98
+ `perseid/update` branch and opens or updates one pull request per repository.
99
+ - `sdk-release.yml` runs release-please on merge and publishes each released SDK from the
100
+ `release` environment.
101
+
102
+ The Actions are pinned to the release line of the perseid that wrote them, such as
103
+ `meteroid-oss/perseid@v0.6`. Run `perseid init` again to refresh them.
70
104
 
71
- `perseid setup` writes the workflow for you: it runs the `meteroid-oss/perseid@v0` Action
72
- on every spec change (pushed by `perseid connect` on each release of your API, or each change),
73
- and `perseid status` tells how it fares, from either repository. To set it up by hand, or on self-hosted runners and other CIs with the
74
- `ghcr.io/meteroid-oss/perseid` image, see [CI and releases](docs/ci.md).
105
+ ## Where the SDKs live
106
+
107
+ `perseid init` asks. The answer goes in `perseid.toml`:
108
+
109
+ | Layout | `perseid.toml` | Pull requests open in |
110
+ |---|---|---|
111
+ | Next to the API | `sdks = ["typescript", "python"]` | `acme/api`, in `typescript/` and `python/` |
112
+ | One repository per language | `repo = "acme/api-{lang}"` | `acme/api-typescript`, `acme/api-python` |
113
+ | One SDKs repository | `repo = "acme/api-sdks"` | `acme/api-sdks`, a folder per language |
114
+
115
+ - perseid never creates repositories: `gh repo create acme/api-typescript`.
116
+ - Add `PERSEID_TOKEN` to each SDK repository too: its release workflow uses it.
117
+ - Spec in another repository? Run `perseid init` in the SDKs repository, then
118
+ `npx perseid connect acme/api-sdks` in the API repository. It writes a workflow pushing the
119
+ spec, with a deploy key that reaches the SDKs repository only.
120
+ - A spec served at a URL needs no `connect`: `sdks.yml` fetches it daily.
121
+
122
+ See [repository layouts](docs/ci.md#repository-layouts).
123
+
124
+ ## Commands
125
+
126
+ | Command | |
127
+ |---|---|
128
+ | `init` | Write `perseid.toml` and the workflows. Local only: nothing is sent to GitHub. |
129
+ | `generate` | Write the SDKs. `--out <dir>` previews, `--check` fails on drift, `--pr` opens pull requests. |
130
+ | `connect <owner/repo>` | In the API repository: push the spec to the SDKs repository. |
131
+ | `app` | Set up a GitHub App to open the pull requests instead of `PERSEID_TOKEN`. |
132
+ | `status` | Check the setup: secrets, workflows, last spec pushed, open pull requests, last runs. |
133
+ | `inspect` | Print the model the templates receive, as JSON. |
134
+ | `eject <lang>` | Copy the built-in templates and runtime of a language to `.perseid/` to edit them. |
135
+ | `tools list`, `tools install` | List or download the pinned formatters and oasdiff. |
136
+
137
+ `generate --pr` also takes `--bump`, `--auto-merge` and `--dispatch`, described in
138
+ [CI and releases](docs/ci.md#github-action). It runs on your machine too, without the `gh` CLI. It
139
+ signs in with `GH_TOKEN`, `GITHUB_TOKEN`, the token `gh` stores, or a browser login.
75
140
 
76
141
  ## Docs
77
142
 
78
- - [Configuration](docs/configuration.md): `perseid.toml`, per-language options, editor completion
79
- - [Customizing](docs/customizing.md): handwritten code, middleware, snippets, templates, webhooks
80
- - [Auth, pagination, streaming and encoding](docs/features.md)
143
+ - [CI and releases](docs/ci.md): the Actions, tokens, spec pushes, release-please, publishing
144
+ - [Configuration](docs/configuration.md): every key of `perseid.toml`
81
145
  - [Languages](docs/languages.md): what each SDK looks like
82
- - [CI and releases](docs/ci.md): the Action, Docker image, release automation, formatting
146
+ - [Auth, pagination, streaming, raw responses and encoding](docs/features.md)
147
+ - [Customizing](docs/customizing.md): handwritten code, middleware, snippets, templates, webhooks
148
+ - [Testing](docs/testing.md): how perseid itself is tested, for contributors
83
149
 
84
150
  ## Status
85
151
 
86
- OpenAPI 3.0 and 3.1, JSON or YAML; Swagger 2.0 must be converted first (`npx swagger2openapi`)
152
+ perseid reads OpenAPI 3.0, 3.1 and 3.2, in JSON or YAML. Convert Swagger 2.0 first, for example with
153
+ `npx swagger2openapi`.
87
154
 
88
- Used on [Meteroid's API](https://github.com/meteroid-oss/meteroid-clients);
155
+ It generates the [Meteroid SDKs](https://github.com/meteroid-oss/meteroid-clients). SDKs from the
156
+ Stripe, GitHub, OpenAI, Twilio, DigitalOcean and Linode specs compile in every language, with one
157
+ operation excluded on Stripe and on OpenAI.
89
158
 
90
- SDKs from the Stripe, GitHub, OpenAI, Twilio, DigitalOcean and Linode specs compile in every language, with one operation left out on Stripe and OpenAI.
159
+ A construct no SDK can express is skipped or typed as untyped JSON, with a warning naming the
160
+ operation or schema. Names that clash fail generation, listed together. Leave an operation out
161
+ with `exclude = ["<operation id>"]`, and open an issue with the spec attached.
91
162
 
92
- Unsupported constructs fail generation loudly, naming the operation or schema: `exclude = ["<operation id>"]` skips one, and an issue with
93
- the spec attached is the fastest way to get it supported.
163
+ perseid started as a fork of [Svix's openapi-codegen](https://github.com/svix/openapi-codegen).
94
164
 
95
165
  ## License
96
166
 
package/checksums.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "perseid-aarch64-apple-darwin.tar.gz": "76f9db64f53acde55adf957d0ce35aed90d0d656c99ad92bfb019e477384bbab",
3
- "perseid-aarch64-unknown-linux-musl.tar.gz": "d04689295ef62f832d11db41d1f63f2d05af538b22c04e900d5ed1b18d79cec7",
4
- "perseid-x86_64-apple-darwin.tar.gz": "cd927527a7d6e161ddd7eed18b41af3e1c701931780a83fa2c2a1570b7649198",
5
- "perseid-x86_64-unknown-linux-musl.tar.gz": "d3acfce3463c5cbe0ba4c3d17743731c0778b622b93eee9dd4431861d84ccd9b"
2
+ "perseid-aarch64-apple-darwin.tar.gz": "53ed922427a97e69e65d0d337b08a94f753a7324d5297e9d4e53d4bc52ebfd2e",
3
+ "perseid-aarch64-unknown-linux-musl.tar.gz": "ca51bd801ff40b253a0648bf6f7c4646c8bb97142c2a1967cf260786cdf1d35c",
4
+ "perseid-x86_64-apple-darwin.tar.gz": "81bd578a7f00216cb52ba1220120963d7a914347b3c4e3a9beb1db86516153a6",
5
+ "perseid-x86_64-unknown-linux-musl.tar.gz": "a4e12de24dd9bd8be521bcfc3c96f42c9f1b408adae6100776a10d6d03ade719"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perseid",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "OpenAPI in, idiomatic SDKs out: Rust, TypeScript, Python, Go, Java and C# from one static binary",
5
5
  "keywords": [
6
6
  "openapi",