@sponson/sim 0.0.0-stage → 0.5.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 (78) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +9 -2
  3. package/dist/auth.d.ts +60 -0
  4. package/dist/auth.js +195 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/bin.d.ts +2 -0
  7. package/dist/bin.js +16 -0
  8. package/dist/bin.js.map +1 -0
  9. package/dist/chaos.d.ts +74 -0
  10. package/dist/chaos.js +80 -0
  11. package/dist/chaos.js.map +1 -0
  12. package/dist/cli.d.ts +29 -0
  13. package/dist/cli.js +99 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/demo.d.ts +39 -0
  16. package/dist/demo.js +168 -0
  17. package/dist/demo.js.map +1 -0
  18. package/dist/graphql.d.ts +22 -0
  19. package/dist/graphql.js +36 -0
  20. package/dist/graphql.js.map +1 -0
  21. package/dist/index.d.ts +46 -0
  22. package/dist/index.js +54 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/provider.d.ts +138 -0
  25. package/dist/provider.js +68 -0
  26. package/dist/provider.js.map +1 -0
  27. package/dist/routes/algolia.d.ts +37 -0
  28. package/dist/routes/algolia.js +83 -0
  29. package/dist/routes/algolia.js.map +1 -0
  30. package/dist/routes/aws.d.ts +43 -0
  31. package/dist/routes/aws.js +211 -0
  32. package/dist/routes/aws.js.map +1 -0
  33. package/dist/routes/clerk.d.ts +33 -0
  34. package/dist/routes/clerk.js +85 -0
  35. package/dist/routes/clerk.js.map +1 -0
  36. package/dist/routes/cloudflare.d.ts +80 -0
  37. package/dist/routes/cloudflare.js +176 -0
  38. package/dist/routes/cloudflare.js.map +1 -0
  39. package/dist/routes/digitalocean.d.ts +58 -0
  40. package/dist/routes/digitalocean.js +158 -0
  41. package/dist/routes/digitalocean.js.map +1 -0
  42. package/dist/routes/fly.d.ts +22 -0
  43. package/dist/routes/fly.js +113 -0
  44. package/dist/routes/fly.js.map +1 -0
  45. package/dist/routes/launchdarkly.d.ts +98 -0
  46. package/dist/routes/launchdarkly.js +213 -0
  47. package/dist/routes/launchdarkly.js.map +1 -0
  48. package/dist/routes/neon.d.ts +73 -0
  49. package/dist/routes/neon.js +184 -0
  50. package/dist/routes/neon.js.map +1 -0
  51. package/dist/routes/netlify.d.ts +126 -0
  52. package/dist/routes/netlify.js +347 -0
  53. package/dist/routes/netlify.js.map +1 -0
  54. package/dist/routes/planetscale.d.ts +95 -0
  55. package/dist/routes/planetscale.js +234 -0
  56. package/dist/routes/planetscale.js.map +1 -0
  57. package/dist/routes/railway.d.ts +24 -0
  58. package/dist/routes/railway.js +112 -0
  59. package/dist/routes/railway.js.map +1 -0
  60. package/dist/routes/rest.d.ts +138 -0
  61. package/dist/routes/rest.js +462 -0
  62. package/dist/routes/rest.js.map +1 -0
  63. package/dist/routes/supabase.d.ts +103 -0
  64. package/dist/routes/supabase.js +234 -0
  65. package/dist/routes/supabase.js.map +1 -0
  66. package/dist/routes/vercel.d.ts +114 -0
  67. package/dist/routes/vercel.js +370 -0
  68. package/dist/routes/vercel.js.map +1 -0
  69. package/dist/routes/xata.d.ts +57 -0
  70. package/dist/routes/xata.js +115 -0
  71. package/dist/routes/xata.js.map +1 -0
  72. package/dist/server.d.ts +4 -0
  73. package/dist/server.js +189 -0
  74. package/dist/server.js.map +1 -0
  75. package/dist/state.d.ts +102 -0
  76. package/dist/state.js +121 -0
  77. package/dist/state.js.map +1 -0
  78. package/package.json +51 -3
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Simulated Netlify: site environment variables (one object per key, one value per deploy context) and deploys.
3
+ *
4
+ * Assumptions about the real API that this fake encodes. "Verified" means against Netlify's OpenAPI document
5
+ * (https://github.com/netlify/open-api/blob/master/swagger.yml, rendered at https://open-api.netlify.com/) or its
6
+ * docs (cited), fetched 2026-10-11; docs/api-verification.md has the per-call table. scenarios/contract.test.ts pins
7
+ * the risky ones against a live account (`pnpm test:live`). NL, not N: N… are Neon's.
8
+ * NL1. Base URL https://api.netlify.com/api/v1, bearer token (OpenAPI `host`, `basePath`; the API guide's
9
+ * `Authorization: Bearer`). Verified.
10
+ * NL2. Site variables live under /accounts/{account_id}/env with `?site_id=`: GET lists them (getEnvVars), POST
11
+ * creates a list of them (createEnvVars, 201), GET/PATCH/DELETE /accounts/{account_id}/env/{key} read one,
12
+ * set one context's value (setEnvVarValue, 201: "updates or creates a new value for an existing
13
+ * environment variable") and delete the variable (204); DELETE …/env/{key}/value/{id} deletes one value
14
+ * (deleteEnvVarValue, 204). Verified (OpenAPI paths, statuses; the docs' API guide). `{account_id}` may be
15
+ * the account slug (verified: the API guide). GET /sites/{site_id} carries `account_id`, `account_slug` and
16
+ * `name` (verified field names; that `name` is the `<name>.netlify.app` subdomain is the docs' example, not a
17
+ * statement: unverified, pinned).
18
+ * NL3. A variable is `{ key, scopes, values: [{ id, value, context, context_parameter }], is_secret, updated_at }`;
19
+ * `context` is all | dev | dev-server | branch-deploy | deploy-preview | production | branch, and `branch`
20
+ * needs the branch name in `context_parameter` (verified: envVar / envVarValue definitions). Omitting
21
+ * `scopes` gives all scopes (verified: "By default, environment variables apply to all scopes", env var
22
+ * overview). Unverified: that PATCH leaves the other contexts' values (and their ids) alone and keeps the id
23
+ * of the value it replaces (the sim keeps it; the adapter re-reads ids from the answer anyway).
24
+ * NL4. Secret values (`is_secret`) are write-only except in the `dev` context (verified: Secrets Controller
25
+ * docs). How a masked value is returned is not documented; the sim omits `value` (unverified; the adapter
26
+ * ignores `value` of a secret either way).
27
+ * NL5. POST of a key that already exists is refused with 400 and writes nothing (unverified: status not
28
+ * documented). A variable with an `all` value and a context value together is refused with 400
29
+ * (unverified). The adapter re-lists after a 400/409 and never writes next to an `all` value.
30
+ * NL6. A variable whose last value is deleted stays, with no values (unverified; the adapter deletes it then, and
31
+ * a 404 on the follow-up read is fine).
32
+ * NL7. GET /sites/{site_id}/deploys lists deploys newest first, `page`/`per_page` (verified: the API guide;
33
+ * order unverified, the adapter sorts by `created_at`). A deploy carries `id`, `state`, `context`,
34
+ * `commit_ref`, `review_id`, `branch`, `created_at` (verified field names); `context` is production |
35
+ * deploy-preview | branch-deploy (unverified: no enum in the spec) and `review_id` is the pull request
36
+ * number (unverified).
37
+ * NL8. Deploy states: new, pending_review, accepted, rejected, enqueued, building, uploading, uploaded,
38
+ * preparing, prepared, processing, processed, ready, error, retrying (verified: the `state` filter's enum).
39
+ * The sim uses enqueued → building → ready, or error.
40
+ * NL9. URLs: `<deploy id>--<site name>.netlify.app` is a deploy's permalink and `deploy-preview-<n>--<site
41
+ * name>.netlify.app` the Deploy Preview of pull request n (verified: deploy overview docs).
42
+ * NL10. A build reads the variable values set when it started ("Environment variable changes require a build
43
+ * and deploy to take effect": verified, env var docs); `updated_at` is when a variable's values last
44
+ * changed (verified field; that a PATCH bumps it is unverified, pinned).
45
+ * NL11. POST /sites/{site_id}/builds starts a build of the production branch, or with `?branch=` a branch deploy
46
+ * of that branch's head (verified: createSiteBuild's `branch` description). Unverified: that it works for
47
+ * a branch whose branch deploys are not enabled in the site's settings. Deploy Previews cannot be rebuilt
48
+ * through the documented API.
49
+ * NL12. A `branch` value applies to "deploy permalinks, Deploy Previews, and branch deploys for the specified
50
+ * branch" (verified: env var overview), so a pull request's Deploy Preview reads its head branch's value.
51
+ *
52
+ * The git integration is modelled by `pushes` in the seed: the first deploy list of a site deploys every push it
53
+ * has not deployed yet (a pull request push as a Deploy Preview, `main` as production, other branches as branch
54
+ * deploys), following chaos `deploy` (ok | never | fail | stale | delay:<s>) and `deploy_ms` as Vercel's sim does.
55
+ */
56
+ import { Reply, route, router } from "../provider.js";
57
+ const PRODUCTION_BRANCH = "main";
58
+ const CONTEXTS = new Set(["all", "dev", "dev-server", "branch-deploy", "deploy-preview", "production", "branch"]);
59
+ /** The simulated Netlify API (env vars, deploys), registered in `PROVIDERS` and served under `/netlify`. */
60
+ export const netlifySim = {
61
+ env: { token: "NETLIFY_AUTH_TOKEN", url: "NETLIFY_API_URL", testToken: "tok_netlify" },
62
+ defaultSeed: { sites: { site_demo: { name: "demo-site", account: "acme" } } },
63
+ reset(core, seed) {
64
+ const sites = {};
65
+ for (const [id, s] of Object.entries(seed?.sites ?? {})) {
66
+ const slug = s.account ?? "acme";
67
+ sites[id] = {
68
+ name: s.name ?? id,
69
+ accountSlug: slug,
70
+ accountId: `acct_${slug}`,
71
+ envs: (s.envs ?? []).map((e) => ({ key: e.key, is_secret: e.is_secret ?? false, values: e.values.map((v) => ({ ...v, id: core.nextId("nlv_") })), updatedAt: Date.now() - 60_000, createdBy: "sim" })),
72
+ deploys: [],
73
+ pushes: [...(s.pushes ?? [])],
74
+ built: [],
75
+ };
76
+ }
77
+ return { sites };
78
+ },
79
+ /**
80
+ * `env.<context>.<NAME>` the value of NAME in that context (any branch for `branch`)
81
+ * `env.branch@<branch>.<NAME>` the `branch` value for that branch
82
+ * Value: a new value, "delete" (the value), or "recreate" (delete it and add it again with a new id).
83
+ */
84
+ drift(core, state, { key, rest, value, only }) {
85
+ if (!rest.startsWith("env."))
86
+ return false;
87
+ const spec = rest.slice("env.".length);
88
+ const dot = spec.lastIndexOf(".");
89
+ if (dot < 0)
90
+ throw new Error(`bad drift key: ${key}`);
91
+ const [context, branch] = splitOnce(spec.slice(0, dot), "@");
92
+ const name = spec.slice(dot + 1);
93
+ let hit = false;
94
+ for (const [id, site] of Object.entries(state.sites)) {
95
+ if (only !== undefined && id !== only)
96
+ continue;
97
+ for (const e of site.envs.filter((x) => x.key === name)) {
98
+ const match = (v) => v.context === context && (branch === undefined || v.context_parameter === branch);
99
+ for (const v of e.values.filter(match)) {
100
+ hit = true;
101
+ if (value === "delete")
102
+ e.values = e.values.filter((x) => x !== v);
103
+ else if (value === "recreate")
104
+ e.values = [...e.values.filter((x) => x !== v), { ...v, id: core.nextId("nlv_") }];
105
+ else
106
+ v.value = value;
107
+ e.updatedAt = Date.now();
108
+ }
109
+ }
110
+ }
111
+ if (!hit)
112
+ throw new Error(`drift ${key}: no value matches`);
113
+ return true;
114
+ },
115
+ routes(core, state, req) {
116
+ return routes(core, state, req);
117
+ },
118
+ };
119
+ /** The site of `?site_id=` when it belongs to the account in the path (by id or slug). */
120
+ function siteFor({ state, params, url }) {
121
+ const siteId = url.searchParams.get("site_id");
122
+ const site = siteId ? state.sites[siteId] : undefined;
123
+ if (!site)
124
+ return notFound("site");
125
+ if (params.account !== site.accountId && params.account !== site.accountSlug)
126
+ return notFound("account");
127
+ return site;
128
+ }
129
+ const routes = router([
130
+ route("GET", "/sites/:site", ({ state, params }) => {
131
+ const s = state.sites[params.site];
132
+ if (!s)
133
+ return notFound("site");
134
+ return new Reply(200, { id: params.site, site_id: params.site, name: s.name, account_id: s.accountId, account_slug: s.accountSlug, url: `http://${s.name}.netlify.app`, ssl_url: `https://${s.name}.netlify.app` });
135
+ }),
136
+ route("GET", "/accounts/:account/env", (ctx) => {
137
+ const site = siteFor(ctx);
138
+ return site instanceof Reply ? site : new Reply(200, site.envs.map(publicEnv));
139
+ }),
140
+ route("POST", "/accounts/:account/env", (ctx) => {
141
+ const site = siteFor(ctx);
142
+ return site instanceof Reply ? site : createEnvs(ctx.core, site, ctx.body);
143
+ }),
144
+ route("GET", "/accounts/:account/env/:key", (ctx) => {
145
+ const site = siteFor(ctx);
146
+ if (site instanceof Reply)
147
+ return site;
148
+ const e = site.envs.find((x) => x.key === ctx.params.key);
149
+ return e ? new Reply(200, publicEnv(e)) : notFound("environment variable");
150
+ }),
151
+ route("PATCH", "/accounts/:account/env/:key", (ctx) => {
152
+ const site = siteFor(ctx);
153
+ if (site instanceof Reply)
154
+ return site;
155
+ const e = site.envs.find((x) => x.key === ctx.params.key);
156
+ if (!e)
157
+ return notFound("environment variable");
158
+ return setValue(ctx.core, e, ctx.body);
159
+ }),
160
+ route("DELETE", "/accounts/:account/env/:key", (ctx) => {
161
+ const site = siteFor(ctx);
162
+ if (site instanceof Reply)
163
+ return site;
164
+ if (!site.envs.some((x) => x.key === ctx.params.key))
165
+ return notFound("environment variable");
166
+ site.envs = site.envs.filter((x) => x.key !== ctx.params.key);
167
+ return new Reply(204, null);
168
+ }),
169
+ route("DELETE", "/accounts/:account/env/:key/value/:id", (ctx) => {
170
+ const site = siteFor(ctx);
171
+ if (site instanceof Reply)
172
+ return site;
173
+ const e = site.envs.find((x) => x.key === ctx.params.key);
174
+ if (!e?.values.some((v) => v.id === ctx.params.id))
175
+ return notFound("environment variable value");
176
+ e.values = e.values.filter((v) => v.id !== ctx.params.id);
177
+ e.updatedAt = Date.now();
178
+ return new Reply(204, null);
179
+ }),
180
+ route("GET", "/sites/:site/deploys", ({ core, state, params, url }) => {
181
+ const s = state.sites[params.site];
182
+ if (!s)
183
+ return notFound("site");
184
+ gitIntegration(core, s);
185
+ refresh(s.deploys);
186
+ const perPage = Number(url.searchParams.get("per_page") ?? 100);
187
+ const pageNo = Math.max(1, Number(url.searchParams.get("page") ?? 1));
188
+ const list = [...s.deploys].sort((a, b) => b.createdAt - a.createdAt).slice((pageNo - 1) * perPage, pageNo * perPage);
189
+ return new Reply(200, list.map((d) => publicDeploy(s, d)));
190
+ }),
191
+ route("POST", "/sites/:site/builds", ({ core, state, params, url }) => {
192
+ const s = state.sites[params.site];
193
+ if (!s)
194
+ return notFound("site");
195
+ const branch = url.searchParams.get("branch") ?? PRODUCTION_BRANCH;
196
+ const head = s.pushes.filter((p) => p.branch === branch).at(-1);
197
+ if (!head)
198
+ return new Reply(422, { code: 422, message: `branch ${branch} has no commits` });
199
+ const d = deploy(core, s, { sha: head.sha, branch }, branch === PRODUCTION_BRANCH ? "production" : "branch-deploy", Date.now());
200
+ return new Reply(200, { id: core.nextId("bld_"), deploy_id: d.id, sha: head.sha, done: false });
201
+ }),
202
+ ], () => notFound("route"));
203
+ /** One `values` item of a create or a PATCH body, validated. */
204
+ function valueInput(core, v) {
205
+ if (!v || typeof v !== "object")
206
+ return "a value must be an object";
207
+ const x = v;
208
+ if (typeof x.value !== "string" || typeof x.context !== "string" || !CONTEXTS.has(x.context))
209
+ return "a value needs `value` and a known `context`";
210
+ if (x.context === "branch" && (typeof x.context_parameter !== "string" || x.context_parameter === ""))
211
+ return "context `branch` must be provided with a value in `context_parameter`";
212
+ return { id: core.nextId("nlv_"), value: x.value, context: x.context, ...(x.context === "branch" ? { context_parameter: x.context_parameter } : {}) };
213
+ }
214
+ function sameSlot(a, b) {
215
+ return a.context === b.context && (a.context_parameter ?? "") === (b.context_parameter ?? "");
216
+ }
217
+ /** `all` cannot sit next to a context value, and no slot twice (NL5). */
218
+ function badValues(values) {
219
+ if (values.some((v) => v.context === "all") && values.length > 1)
220
+ return "a value for all contexts cannot be combined with contextual values";
221
+ if (values.some((v, i) => values.findIndex((w) => sameSlot(v, w)) !== i))
222
+ return "two values for the same context";
223
+ return undefined;
224
+ }
225
+ function createEnvs(core, site, body) {
226
+ if (!Array.isArray(body))
227
+ return badRequest("expected a list of environment variables");
228
+ const created = [];
229
+ // Validate the whole batch first: a rejected request writes nothing.
230
+ for (const item of body) {
231
+ const it = (item ?? {});
232
+ if (typeof it.key !== "string" || it.key === "" || !Array.isArray(it.values))
233
+ return badRequest("each variable needs `key` and `values`");
234
+ if (site.envs.some((e) => e.key === it.key) || created.some((e) => e.key === it.key))
235
+ return badRequest(`Environment variable ${it.key} already exists`);
236
+ const values = it.values.map((v) => valueInput(core, v));
237
+ const wrong = values.find((v) => typeof v === "string") ?? badValues(values);
238
+ if (wrong)
239
+ return badRequest(wrong);
240
+ created.push({ key: it.key, is_secret: it.is_secret === true, values: values, updatedAt: Date.now(), createdBy: "api" });
241
+ }
242
+ site.envs.push(...created);
243
+ return new Reply(201, created.map(publicEnv));
244
+ }
245
+ /** PATCH: replace the value of one context (keeping its id) or add it. */
246
+ function setValue(core, e, body) {
247
+ const v = valueInput(core, body);
248
+ if (typeof v === "string")
249
+ return badRequest(v);
250
+ const existing = e.values.find((x) => sameSlot(x, v));
251
+ const next = existing ? e.values : [...e.values, v];
252
+ const wrong = badValues(next);
253
+ if (wrong)
254
+ return badRequest(wrong);
255
+ if (existing)
256
+ existing.value = v.value;
257
+ e.values = next;
258
+ e.updatedAt = Math.max(Date.now(), e.updatedAt + 1);
259
+ return new Reply(201, publicEnv(e));
260
+ }
261
+ /** The git integration: deploy each push once, per chaos `deploy`. */
262
+ function gitIntegration(core, s) {
263
+ const mode = core.chaos.deploy;
264
+ if (mode === "never")
265
+ return;
266
+ for (const p of s.pushes) {
267
+ const id = `${p.sha} ${p.branch}`;
268
+ if (s.built.includes(id))
269
+ continue;
270
+ s.built.push(id);
271
+ const context = p.pr !== undefined ? "deploy-preview" : p.branch === PRODUCTION_BRANCH ? "production" : "branch-deploy";
272
+ const now = Date.now();
273
+ if (mode === "fail")
274
+ deploy(core, s, p, context, now, "error");
275
+ else if (mode === "stale")
276
+ deploy(core, s, p, context, now - 60_000);
277
+ else {
278
+ const delay = /^delay:(\d+(?:\.\d+)?)$/.exec(mode);
279
+ const d = deploy(core, s, p, context, now);
280
+ if (delay)
281
+ Object.assign(d, { state: "building", readyAt: now + Number(delay[1]) * 1000, finalState: "ready" });
282
+ }
283
+ }
284
+ }
285
+ function deploy(core, s, p, context, createdAt, state = "ready") {
286
+ const buildMs = core.chaos.deploy_ms;
287
+ const d = {
288
+ id: core.nextId("dpl"),
289
+ state: buildMs > 0 ? "enqueued" : state,
290
+ context,
291
+ branch: p.branch,
292
+ commit_ref: p.sha,
293
+ review_id: context === "deploy-preview" ? (p.pr ?? null) : null,
294
+ createdAt,
295
+ ...(buildMs > 0 ? { readyAt: createdAt + buildMs, finalState: state } : {}),
296
+ createdBy: "api",
297
+ };
298
+ s.deploys.push(d);
299
+ return d;
300
+ }
301
+ function refresh(list, now = Date.now()) {
302
+ for (const d of list) {
303
+ if (d.readyAt === undefined || d.finalState === undefined)
304
+ continue;
305
+ if (now >= d.readyAt) {
306
+ d.state = d.finalState;
307
+ delete d.finalState;
308
+ }
309
+ else
310
+ d.state = "building";
311
+ }
312
+ }
313
+ function publicEnv(e) {
314
+ return {
315
+ key: e.key,
316
+ scopes: ["builds", "functions", "runtime", "post-processing"],
317
+ is_secret: e.is_secret,
318
+ updated_at: new Date(e.updatedAt).toISOString(),
319
+ // A secret's values are write-only, except in `dev` (NL4).
320
+ values: e.values.map((v) => (e.is_secret && v.context !== "dev" ? { id: v.id, context: v.context, ...(v.context_parameter ? { context_parameter: v.context_parameter } : {}) } : { ...v })),
321
+ };
322
+ }
323
+ function publicDeploy(s, d) {
324
+ return {
325
+ id: d.id,
326
+ name: s.name,
327
+ state: d.state,
328
+ context: d.context,
329
+ branch: d.branch,
330
+ commit_ref: d.commit_ref,
331
+ review_id: d.review_id,
332
+ created_at: new Date(d.createdAt).toISOString(),
333
+ deploy_ssl_url: `https://${d.id}--${s.name}.netlify.app`,
334
+ };
335
+ }
336
+ /** Netlify's error body: `{ code, message }`. */
337
+ function badRequest(message) {
338
+ return new Reply(400, { code: 400, message });
339
+ }
340
+ function notFound(what) {
341
+ return new Reply(404, { code: 404, message: `${what} not found` });
342
+ }
343
+ function splitOnce(s, sep) {
344
+ const i = s.indexOf(sep);
345
+ return i < 0 ? [s, undefined] : [s.slice(0, i), s.slice(i + 1)];
346
+ }
347
+ //# sourceMappingURL=netlify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"netlify.js","sourceRoot":"","sources":["../../src/routes/netlify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Simulated PlanetScale: organizations, databases, branches and branch passwords (Vitess / MySQL databases).
3
+ *
4
+ * Assumptions about the real API that this fake encodes, each marked with how far it is checked. "Verified" means
5
+ * against PlanetScale's published OpenAPI document (https://planetscale.com/docs/openapi.yaml, fetched 2026-10-11)
6
+ * or the documentation page cited; see docs/api-verification.md, section "PlanetScale". The ones a wrong guess
7
+ * would break are pinned in scenarios/contract.test.ts.
8
+ * PS1. Authentication is `Authorization: <SERVICE_TOKEN_ID>:<SERVICE_TOKEN>`, no scheme word (verified:
9
+ * https://planetscale.com/docs/api/reference/service-tokens). The sim answers 401 to any other form,
10
+ * including `Bearer …`. The CLI's variable names, PLANETSCALE_SERVICE_TOKEN_ID and PLANETSCALE_SERVICE_TOKEN,
11
+ * are the ones the adapter reads (verified: https://planetscale.com/docs/cli/service-tokens.md).
12
+ * PS2. Every path is under `/organizations/{organization}/databases/{database}`, and branches are addressed by
13
+ * name, not id: GET and DELETE `/branches/{branch}` (verified: path parameter "The name of the branch").
14
+ * PS3. Lists (`list_branches`, `list_passwords`) are `{ data, next_page, … }`; the next page is `?page=<n>`
15
+ * and `next_page` is null on the last page; `per_page` defaults to 25 (verified). The sim pages at 25, or
16
+ * at chaos `page_size` when set.
17
+ * PS4. POST `/branches` with `{ name, parent_branch }` answers 201 with the branch (verified), which is not
18
+ * ready yet: `ready: false`, `state: "pending"` (fields and enum verified; that a new branch starts not
19
+ * ready is verified only through the CLI's `--wait`, "Wait until the branch is ready",
20
+ * https://planetscale.com/docs/cli/branch.md). How long it takes is unverified; the sim reports ready
21
+ * from the first GET, or after chaos `planetscale_ready_ms`.
22
+ * PS5. Creating a branch whose name exists answers 422 (unverified: the spec lists 401/403/404/422/429/500 and
23
+ * no 409; the body's wording is unknown). The adapter re-reads the branch by name after any 409 or 422.
24
+ * PS6. A parent branch that does not exist answers 404 here (unverified); the adapter checks the parent with
25
+ * GET first, so the exact answer does not matter to it.
26
+ * PS7. DELETE `/branches/{branch}` answers 204 (verified) and the branch is gone at once (unverified: needs a
27
+ * live account). Deleting a branch deletes its passwords (unverified).
28
+ * PS8. POST `/branches/{branch}/passwords` with `{ name, role }` answers 201 with `id`, `name`, `role`,
29
+ * `username`, `access_host_url` and `plain_text` (verified). `plain_text` is null in every other response
30
+ * (verified: "Null except in the response from the create endpoint"); the CLI docs say the password "is
31
+ * shown once … and cannot be retrieved afterwards" (https://planetscale.com/docs/cli/password.md).
32
+ * PS9. Password names are not unique (unverified: the spec calls `name` "Optional name of the password" and
33
+ * documents no uniqueness). The sim accepts duplicates; the adapter refuses to guess between two.
34
+ * PS10. A password's role cannot be changed in place: PATCH takes only `name` and `cidrs` (verified).
35
+ * PS11. DELETE `/branches/{branch}/passwords/{id}` answers 204 (verified); a password that does not exist, 404.
36
+ * PS12. Creating a password on a branch that is not ready yet is refused (unverified: the real behaviour is
37
+ * unknown, so the sim takes the strict reading and answers 422); the adapter waits for `ready` first.
38
+ * PS13. Error bodies are `{ code, message }` (unverified; not in the spec). The adapter never reads them.
39
+ * PS14. Branch names: the sim accepts any non-empty name. Which characters the real API accepts is
40
+ * unverified; the adapter's default name uses only lowercase letters, digits and dashes.
41
+ */
42
+ import { type CreatedBy, type ProviderSim, type SimCore } from "../provider.js";
43
+ /** One simulated branch password. `plainText` is sim bookkeeping: the API shows it only in the create answer. */
44
+ export interface PlanetscalePassword {
45
+ id: string;
46
+ name: string;
47
+ role: string;
48
+ username: string;
49
+ plainText: string;
50
+ createdAt: number;
51
+ createdBy: CreatedBy;
52
+ }
53
+ /** One simulated database branch. */
54
+ export interface PlanetscaleBranch {
55
+ id: string;
56
+ name: string;
57
+ parent_branch: string | null;
58
+ production: boolean;
59
+ /** `ready` is reported from this time on (PS4). */
60
+ readyAt: number;
61
+ created_at: string;
62
+ passwords: PlanetscalePassword[];
63
+ createdBy: CreatedBy;
64
+ }
65
+ /** The simulated PlanetScale's state: organization → database → branches. */
66
+ export interface PlanetscaleState {
67
+ organizations: Record<string, {
68
+ databases: Record<string, {
69
+ branches: PlanetscaleBranch[];
70
+ }>;
71
+ }>;
72
+ }
73
+ /** What a scenario or test seeds the simulated PlanetScale with (`seed: { planetscale: … }`). */
74
+ export interface PlanetscaleSeed {
75
+ /** Organization → database → branches that already exist (created "by a human", so unmanaged). */
76
+ organizations: Record<string, Record<string, Array<{
77
+ name: string;
78
+ parent?: string;
79
+ production?: boolean;
80
+ passwords?: Array<{
81
+ name: string;
82
+ role?: string;
83
+ }>;
84
+ }>>>;
85
+ }
86
+ /** The access host every simulated password hands out (the real API's `access_host_url`). */
87
+ export declare const PLANETSCALE_SIM_HOST = "aws.connect.psdb.sim";
88
+ /** The simulated PlanetScale API, registered in `PROVIDERS` (packages/sim/src/state.ts) and served under `/planetscale`. */
89
+ export declare const planetscaleSim: ProviderSim<PlanetscaleState, PlanetscaleSeed>;
90
+ /**
91
+ * Add a branch as PlanetScale would. Tests use it to seed "someone else's" branch. A seeded branch is ready at once.
92
+ */
93
+ export declare function createPsBranch(core: SimCore, branches: PlanetscaleBranch[], name: string, parent: string | null, createdBy: CreatedBy, production: boolean): PlanetscaleBranch;
94
+ /** Add a password to a branch. Its plaintext starts `pscale_pw_`, like the real ones (PS8). */
95
+ export declare function createPsPassword(core: SimCore, branch: PlanetscaleBranch, name: string, role: string, createdBy: CreatedBy): PlanetscalePassword;