@sponson/sim 0.4.0 → 0.6.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.
- package/README.md +5 -0
- package/dist/auth.d.ts +60 -0
- package/dist/auth.js +195 -0
- package/dist/auth.js.map +1 -0
- package/dist/bin.js +9 -14
- package/dist/bin.js.map +1 -1
- package/dist/chaos.d.ts +4 -0
- package/dist/chaos.js +2 -0
- package/dist/chaos.js.map +1 -1
- package/dist/cli.d.ts +29 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/demo.d.ts +39 -0
- package/dist/demo.js +168 -0
- package/dist/demo.js.map +1 -0
- package/dist/graphql.d.ts +22 -0
- package/dist/graphql.js +36 -0
- package/dist/graphql.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +43 -4
- package/dist/provider.js +12 -6
- package/dist/provider.js.map +1 -1
- package/dist/routes/algolia.d.ts +37 -0
- package/dist/routes/algolia.js +83 -0
- package/dist/routes/algolia.js.map +1 -0
- package/dist/routes/aws.d.ts +43 -0
- package/dist/routes/aws.js +211 -0
- package/dist/routes/aws.js.map +1 -0
- package/dist/routes/cloud_run.d.ts +131 -0
- package/dist/routes/cloud_run.js +378 -0
- package/dist/routes/cloud_run.js.map +1 -0
- package/dist/routes/cloudflare.d.ts +80 -0
- package/dist/routes/cloudflare.js +176 -0
- package/dist/routes/cloudflare.js.map +1 -0
- package/dist/routes/digitalocean.d.ts +58 -0
- package/dist/routes/digitalocean.js +158 -0
- package/dist/routes/digitalocean.js.map +1 -0
- package/dist/routes/fly.d.ts +22 -0
- package/dist/routes/fly.js +113 -0
- package/dist/routes/fly.js.map +1 -0
- package/dist/routes/launchdarkly.d.ts +98 -0
- package/dist/routes/launchdarkly.js +213 -0
- package/dist/routes/launchdarkly.js.map +1 -0
- package/dist/routes/netlify.d.ts +126 -0
- package/dist/routes/netlify.js +347 -0
- package/dist/routes/netlify.js.map +1 -0
- package/dist/routes/planetscale.d.ts +95 -0
- package/dist/routes/planetscale.js +234 -0
- package/dist/routes/planetscale.js.map +1 -0
- package/dist/routes/railway.d.ts +24 -0
- package/dist/routes/railway.js +112 -0
- package/dist/routes/railway.js.map +1 -0
- package/dist/routes/rest.d.ts +138 -0
- package/dist/routes/rest.js +462 -0
- package/dist/routes/rest.js.map +1 -0
- package/dist/routes/supabase.d.ts +103 -0
- package/dist/routes/supabase.js +234 -0
- package/dist/routes/supabase.js.map +1 -0
- package/dist/routes/xata.d.ts +57 -0
- package/dist/routes/xata.js +115 -0
- package/dist/routes/xata.js.map +1 -0
- package/dist/server.js +71 -12
- package/dist/server.js.map +1 -1
- package/dist/state.d.ts +13 -0
- package/dist/state.js +14 -1
- package/dist/state.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import { digestChallenge, digestProblem, issueToken, sigV4Problem, tokenValid } from "../auth.js";
|
|
2
|
+
import { page, Reply, route, router } from "../provider.js";
|
|
3
|
+
/** Simulated generic REST API; see the assumptions at the top of this file. */
|
|
4
|
+
export const restSim = {
|
|
5
|
+
env: { token: "REST_API_TOKEN", url: "REST_API_URL", testToken: "tok_rest" },
|
|
6
|
+
defaultSeed: {
|
|
7
|
+
collections: { "/gates": [], "/flags": [], "/hooks": [] },
|
|
8
|
+
objects: { "/apps/demo": { name: "demo app", allowed_origins: [], rules: [], uri_allow_list: "", env_vars: {} } },
|
|
9
|
+
},
|
|
10
|
+
reset(core, seed) {
|
|
11
|
+
const state = emptyState(seed ?? {});
|
|
12
|
+
for (const [path, items] of Object.entries(byPath(seed?.collections ?? {}))) {
|
|
13
|
+
const field = styleOf(state, path).id_field;
|
|
14
|
+
state.collections[path] = items.map((i) => ({ ...structuredClone(i), [field]: isId(i[field]) ? i[field] : newId(core, state, path) }));
|
|
15
|
+
}
|
|
16
|
+
if (seed?.auth)
|
|
17
|
+
state.auth = { ...structuredClone(seed.auth), issued: [], nonces: [], refused: 0 };
|
|
18
|
+
return state;
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* `items.<collection path>.<id or name>`: "delete" | "recreate" (same fields, new id);
|
|
22
|
+
* `items.<collection path>.<id or name>.<field>`: a new value (JSON when it parses, else the string);
|
|
23
|
+
* `objects.<path>.<field>`: "add:<v>" / "remove:<v>" on a list of strings, else a new value as above.
|
|
24
|
+
* Paths are written as they are (`items./gates.checkout.enabled`); they must not contain dots.
|
|
25
|
+
*/
|
|
26
|
+
drift(core, state, { key, rest, value, only }) {
|
|
27
|
+
if (only !== undefined)
|
|
28
|
+
return false;
|
|
29
|
+
if (rest === "auth.revoke_tokens") {
|
|
30
|
+
if (!state.auth)
|
|
31
|
+
throw new Error(`drift ${key}: the rest sim has no auth seed`);
|
|
32
|
+
for (const t of state.auth.issued)
|
|
33
|
+
t.revoked = true;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const [kind, path, b, ...more] = rest.split(".");
|
|
37
|
+
if (kind === "items" && path && b)
|
|
38
|
+
return driftItem(core, state, path, b, more.join("."), value, key);
|
|
39
|
+
if (kind === "objects" && path && b && more.length === 0)
|
|
40
|
+
return driftObject(state, path, b, value, key);
|
|
41
|
+
return false;
|
|
42
|
+
},
|
|
43
|
+
isWrite(req, state) {
|
|
44
|
+
return !(req.method === "POST" && (req.path === "/oauth/token" || normPath(req.path) in state.reads));
|
|
45
|
+
},
|
|
46
|
+
authorized(headers, state, req) {
|
|
47
|
+
if (state.endpoints[normPath(req.url.pathname.replace(/^\/rest(?=\/)/, ""))]?.public)
|
|
48
|
+
return true;
|
|
49
|
+
if (!state.auth)
|
|
50
|
+
return authorized(headers, state.auth_headers);
|
|
51
|
+
// The token endpoint authenticates the client itself.
|
|
52
|
+
if (req.method === "POST" && req.url.pathname === "/rest/oauth/token")
|
|
53
|
+
return true;
|
|
54
|
+
if (strictlyAuthorized(headers, req, state.auth) || carriesGenerated(headers, state))
|
|
55
|
+
return true;
|
|
56
|
+
state.auth.refused += 1;
|
|
57
|
+
return state.auth.digest ? digestChallenge(state.auth.digest, state.auth, state.auth.nonces.length + 1) : false;
|
|
58
|
+
},
|
|
59
|
+
routes(core, state, req) {
|
|
60
|
+
const endpoint = state.endpoints[normPath(req.path)];
|
|
61
|
+
if (!endpoint)
|
|
62
|
+
return routes(core, state, req);
|
|
63
|
+
state.calls.push({ method: req.method, path: normPath(req.path), headers: { ...(req.headers ?? {}) }, body: structuredClone(req.body) });
|
|
64
|
+
return new Reply(endpoint.status ?? 200, structuredClone(endpoint.reply ?? {}));
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
/** The state a seed describes, before its collections get their ids. */
|
|
68
|
+
function emptyState(seed) {
|
|
69
|
+
return {
|
|
70
|
+
collections: {},
|
|
71
|
+
objects: byPath(structuredClone(seed.objects ?? {})),
|
|
72
|
+
styles: byPath(structuredClone(seed.styles ?? {})),
|
|
73
|
+
aliases: pathPairs(seed.aliases),
|
|
74
|
+
auth_headers: (seed.auth_headers ?? []).map((h) => h.toLowerCase()),
|
|
75
|
+
reads: pathPairs(seed.reads),
|
|
76
|
+
endpoints: byPath(structuredClone(seed.endpoints ?? {})),
|
|
77
|
+
calls: [],
|
|
78
|
+
deletes: bulkDeletesOf(seed.deletes),
|
|
79
|
+
generated: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** The seed's bulk-delete paths (R11), paths normalised. */
|
|
83
|
+
function bulkDeletesOf(seed) {
|
|
84
|
+
return Object.fromEntries(Object.entries(seed ?? {}).map(([p, d]) => [normPath(p), { collection: normPath(d.collection), ids: d.ids }]));
|
|
85
|
+
}
|
|
86
|
+
/** R10: the seed's `generated_header` carries a value the sim generated for an object. */
|
|
87
|
+
function carriesGenerated(headers, state) {
|
|
88
|
+
const name = state.auth?.generated_header?.toLowerCase();
|
|
89
|
+
const v = name === undefined ? undefined : headers[name];
|
|
90
|
+
return typeof v === "string" && state.generated.includes(v);
|
|
91
|
+
}
|
|
92
|
+
/** R7: the request carries one of the credentials the seed configures, valid. */
|
|
93
|
+
function strictlyAuthorized(headers, req, auth) {
|
|
94
|
+
const sets = (auth.headers ?? []).map((set) => Object.entries(set));
|
|
95
|
+
if (sets.some((set) => set.length > 0 && set.every(([name, v]) => headers[name] === v)))
|
|
96
|
+
return true;
|
|
97
|
+
const value = headers.authorization ?? "";
|
|
98
|
+
const bearer = /^Bearer\s+(\S+)$/.exec(value)?.[1];
|
|
99
|
+
if (bearer !== undefined)
|
|
100
|
+
return (auth.tokens ?? []).includes(bearer) || tokenValid({ clients: auth.clients ?? {}, ttlSeconds: 0, issued: auth.issued }, bearer);
|
|
101
|
+
if (/^Digest\s/i.test(value) && auth.digest)
|
|
102
|
+
return digestProblem(headers, req, auth.digest, auth) === null;
|
|
103
|
+
if (value.startsWith("AWS4-HMAC-SHA256") && auth.sigv4)
|
|
104
|
+
return sigV4Problem(headers, req, auth.sigv4) === null;
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
function authorized(headers, declared) {
|
|
108
|
+
const a = headers.authorization ?? "";
|
|
109
|
+
if (/^(Bearer|Basic)\s+\S+$/.test(a) || (/^\S+$/.test(a) && !/^(Bearer|Basic)$/i.test(a)))
|
|
110
|
+
return true;
|
|
111
|
+
const carries = (name) => /(^|-)(api-key|key|token)$/.test(name) || declared.includes(name);
|
|
112
|
+
return Object.entries(headers).some(([name, v]) => carries(name) && typeof v === "string" && v.trim() !== "");
|
|
113
|
+
}
|
|
114
|
+
/** The style of the collection at `path`, every default filled in. */
|
|
115
|
+
function styleOf(state, path) {
|
|
116
|
+
const s = state.styles[path] ?? {};
|
|
117
|
+
const id = s.id_field ?? "id";
|
|
118
|
+
return {
|
|
119
|
+
list_path: s.list_path ?? "/data",
|
|
120
|
+
item_path: s.item_path ?? "/data",
|
|
121
|
+
next_path: s.next_path === undefined ? "/next_cursor" : s.next_path,
|
|
122
|
+
id_field: id,
|
|
123
|
+
id_from: s.id_from ?? id,
|
|
124
|
+
numeric_ids: s.numeric_ids ?? false,
|
|
125
|
+
form_types: s.form_types ?? false,
|
|
126
|
+
once_fields: s.once_fields ?? [],
|
|
127
|
+
generated: s.generated ?? [],
|
|
128
|
+
...(s.item_query ? { item_query: s.item_query } : {}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** A form body's values typed (assumption R4): `true`/`false` and numerals become booleans and numbers. */
|
|
132
|
+
function typedForm(v) {
|
|
133
|
+
if (Array.isArray(v))
|
|
134
|
+
return v.map(typedForm);
|
|
135
|
+
if (isRecord(v))
|
|
136
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, typedForm(x)]));
|
|
137
|
+
if (v === "true" || v === "false")
|
|
138
|
+
return v === "true";
|
|
139
|
+
return typeof v === "string" && /^-?\d+(\.\d+)?$/.test(v) ? Number(v) : v;
|
|
140
|
+
}
|
|
141
|
+
/** The body as the collection at `path` reads it. */
|
|
142
|
+
function bodyFor(state, path, body, headers) {
|
|
143
|
+
const form = (headers["content-type"] ?? "").startsWith("application/x-www-form-urlencoded");
|
|
144
|
+
return form && styleOf(state, path).form_types ? typedForm(body) : body;
|
|
145
|
+
}
|
|
146
|
+
function isId(v) {
|
|
147
|
+
return (typeof v === "string" && v !== "") || typeof v === "number";
|
|
148
|
+
}
|
|
149
|
+
/** A fresh id for the collection at `path`: `it_<n>`, or an integer with `numeric_ids`. */
|
|
150
|
+
function newId(core, state, path) {
|
|
151
|
+
const id = core.nextId("it_");
|
|
152
|
+
return styleOf(state, path).numeric_ids ? Number(id.slice(3)) : id;
|
|
153
|
+
}
|
|
154
|
+
/** `value` placed at the JSON pointer `pointer` of an otherwise empty object (`""`: the value itself). */
|
|
155
|
+
function envelope(pointer, value) {
|
|
156
|
+
if (pointer === "")
|
|
157
|
+
return value;
|
|
158
|
+
const tokens = pointer.slice(1).split("/").map((t) => t.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
159
|
+
return tokens.reduceRight((v, token) => ({ [token]: v }), value);
|
|
160
|
+
}
|
|
161
|
+
/** A list answer, with its cursor when the style has one. */
|
|
162
|
+
function listBody(style, items, next) {
|
|
163
|
+
const list = envelope(style.list_path, items);
|
|
164
|
+
if (style.next_path === null || !isRecord(list))
|
|
165
|
+
return list;
|
|
166
|
+
return mergeInto(list, envelope(style.next_path, next === null ? null : String(next)));
|
|
167
|
+
}
|
|
168
|
+
function mergeInto(a, b) {
|
|
169
|
+
if (!isRecord(b))
|
|
170
|
+
return a;
|
|
171
|
+
for (const [k, v] of Object.entries(b))
|
|
172
|
+
a[k] = isRecord(v) && isRecord(a[k]) ? mergeInto(a[k], v) : v;
|
|
173
|
+
return a;
|
|
174
|
+
}
|
|
175
|
+
function driftItem(core, state, coll, which, field, value, key) {
|
|
176
|
+
const list = state.collections[coll] ?? [];
|
|
177
|
+
const idf = styleOf(state, coll).id_field;
|
|
178
|
+
const item = list.find((i) => String(i[idf]) === which || i.name === which);
|
|
179
|
+
if (!item)
|
|
180
|
+
throw new Error(`drift ${key}: no item ${which} in ${coll}`);
|
|
181
|
+
if (field) {
|
|
182
|
+
item[field] = parseValue(value);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (value !== "delete" && value !== "recreate")
|
|
186
|
+
throw new Error(`drift ${key}: only "delete" and "recreate" are supported without a field`);
|
|
187
|
+
const rest = list.filter((i) => i !== item);
|
|
188
|
+
if (value === "recreate")
|
|
189
|
+
rest.push({ ...item, [idf]: newId(core, state, coll) });
|
|
190
|
+
state.collections[coll] = rest;
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
function driftObject(state, path, field, value, key) {
|
|
194
|
+
const o = state.objects[path];
|
|
195
|
+
if (!o)
|
|
196
|
+
throw new Error(`drift ${key}: no object at ${path}`);
|
|
197
|
+
const m = /^(add|remove):(.*)$/.exec(value);
|
|
198
|
+
if (!m) {
|
|
199
|
+
o[field] = parseValue(value);
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
const list = Array.isArray(o[field]) ? o[field] : [];
|
|
203
|
+
o[field] = m[1] === "add" ? [...list, m[2]] : list.filter((x) => x !== m[2]);
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
function parseValue(v) {
|
|
207
|
+
try {
|
|
208
|
+
return JSON.parse(v);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
return v;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** A path without its trailing slash (`/releases/` and `/releases` name the same thing, assumption R3). */
|
|
215
|
+
function normPath(path) {
|
|
216
|
+
return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
217
|
+
}
|
|
218
|
+
/** A seed map of path to path, both normalised. */
|
|
219
|
+
function pathPairs(m) {
|
|
220
|
+
return Object.fromEntries(Object.entries(m ?? {}).map(([a, p]) => [normPath(a), normPath(p)]));
|
|
221
|
+
}
|
|
222
|
+
/** A seed map keyed by normalised paths. */
|
|
223
|
+
function byPath(m) {
|
|
224
|
+
return Object.fromEntries(Object.entries(m).map(([p, v]) => [normPath(p), v]));
|
|
225
|
+
}
|
|
226
|
+
/** The collection stored at `path`, or the one an alias there names (R2). */
|
|
227
|
+
function collectionAt(state, path) {
|
|
228
|
+
if (state.collections[path])
|
|
229
|
+
return path;
|
|
230
|
+
const alias = state.aliases[path];
|
|
231
|
+
return alias !== undefined && state.collections[alias] ? alias : undefined;
|
|
232
|
+
}
|
|
233
|
+
function resolve(state, raw, query) {
|
|
234
|
+
const path = state.aliases[normPath(raw)] ?? normPath(raw);
|
|
235
|
+
const object = state.objects[path];
|
|
236
|
+
if (object)
|
|
237
|
+
return { kind: "object", path, object };
|
|
238
|
+
const items = state.collections[path];
|
|
239
|
+
if (items)
|
|
240
|
+
return queriedItem(state, path, query) ?? { kind: "collection", path, items };
|
|
241
|
+
const cut = path.lastIndexOf("/");
|
|
242
|
+
const collection = collectionAt(state, path.slice(0, cut)) ?? path.slice(0, cut);
|
|
243
|
+
return itemTarget(state, collection, decodeURIComponent(path.slice(cut + 1)));
|
|
244
|
+
}
|
|
245
|
+
function itemTarget(state, collection, id) {
|
|
246
|
+
const idf = styleOf(state, collection).id_field;
|
|
247
|
+
const index = (state.collections[collection] ?? []).findIndex((i) => String(i[idf]) === id);
|
|
248
|
+
return index >= 0 ? { kind: "item", collection, index, item: state.collections[collection][index] } : { kind: "none" };
|
|
249
|
+
}
|
|
250
|
+
/** `<collection>?<item_query>=<id>`: the object it names, when the collection's style has `item_query`. */
|
|
251
|
+
function queriedItem(state, path, query) {
|
|
252
|
+
const param = styleOf(state, path).item_query;
|
|
253
|
+
const id = param ? query?.get(param) : null;
|
|
254
|
+
return id === null || id === undefined ? undefined : itemTarget(state, path, id);
|
|
255
|
+
}
|
|
256
|
+
const notFound = () => error(404, "not found");
|
|
257
|
+
/** R8: the object a read sent as a POST names, answered as a GET of it would be. */
|
|
258
|
+
function readObject(state, path) {
|
|
259
|
+
const object = state.objects[path];
|
|
260
|
+
return object ? new Reply(200, envelope(state.styles[path]?.item_path ?? "", object)) : notFound();
|
|
261
|
+
}
|
|
262
|
+
/** The fields the request's headers set, by the collection's `header_fields`. */
|
|
263
|
+
function headerFields(state, collection, headers) {
|
|
264
|
+
const map = state.styles[collection]?.header_fields ?? {};
|
|
265
|
+
return Object.fromEntries(Object.entries(map).flatMap(([h, f]) => (headers[h.toLowerCase()] === undefined ? [] : [[f, headers[h.toLowerCase()]]])));
|
|
266
|
+
}
|
|
267
|
+
/** The collection with a `suffix_field` that `path` is under, and the suffix. */
|
|
268
|
+
function suffixTarget(state, path) {
|
|
269
|
+
const collection = Object.keys(state.collections).find((c) => state.styles[c]?.suffix_field !== undefined && path.startsWith(`${c}/`));
|
|
270
|
+
return collection === undefined ? undefined : { collection, suffix: path.slice(collection.length + 1) };
|
|
271
|
+
}
|
|
272
|
+
/** POST `<collection>/<suffix>`: create, or update the object whose id the request chooses (R3, `suffix_field`). */
|
|
273
|
+
function upsertAt(core, state, at, body, headers) {
|
|
274
|
+
if (!isRecord(body))
|
|
275
|
+
return error(400, "body must be a JSON object");
|
|
276
|
+
const style = styleOf(state, at.collection);
|
|
277
|
+
const fields = { ...structuredClone(body), ...headerFields(state, at.collection, headers), [state.styles[at.collection].suffix_field]: at.suffix };
|
|
278
|
+
const list = state.collections[at.collection];
|
|
279
|
+
const chosen = isId(fields[style.id_from]) ? fields[style.id_from] : undefined;
|
|
280
|
+
const index = chosen === undefined ? -1 : list.findIndex((i) => i[style.id_field] === chosen);
|
|
281
|
+
const item = { ...(index >= 0 ? list[index] : {}), ...fields, [style.id_field]: chosen ?? newId(core, state, at.collection) };
|
|
282
|
+
if (index >= 0)
|
|
283
|
+
list[index] = item;
|
|
284
|
+
else
|
|
285
|
+
list.push(item);
|
|
286
|
+
return new Reply(200, envelope(style.item_path, item));
|
|
287
|
+
}
|
|
288
|
+
function create(core, state, path, raw, headers = {}) {
|
|
289
|
+
if (!isRecord(raw))
|
|
290
|
+
return error(400, "body must be a JSON object");
|
|
291
|
+
const body = { ...raw, ...headerFields(state, path, headers) };
|
|
292
|
+
const list = (state.collections[path] ??= []);
|
|
293
|
+
const style = styleOf(state, path);
|
|
294
|
+
const chosen = isId(body[style.id_from]) ? body[style.id_from] : undefined;
|
|
295
|
+
const clash = list.find((i) => (chosen !== undefined && i[style.id_field] === chosen) || (body.name !== undefined && i.name === body.name));
|
|
296
|
+
if (clash)
|
|
297
|
+
return error(409, `already exists: ${String(clash[style.id_field])}`);
|
|
298
|
+
const item = { ...structuredClone(body), [style.id_field]: chosen ?? newId(core, state, path) };
|
|
299
|
+
// Fields generated and stored (assumption R10): a server's token, readable afterwards.
|
|
300
|
+
for (const pointer of style.generated) {
|
|
301
|
+
const value = `${pointer.split("/")[1] ?? "field"}_sim_${core.nextId("")}`;
|
|
302
|
+
state.generated.push(value);
|
|
303
|
+
setPointer(item, pointer, value);
|
|
304
|
+
}
|
|
305
|
+
list.push(item);
|
|
306
|
+
// Fields shown once (assumption R6): in this answer only, never stored.
|
|
307
|
+
const shown = Object.fromEntries(style.once_fields.map((f) => [f, `${f}_sim_${core.nextId("")}`]));
|
|
308
|
+
return new Reply(201, envelope(style.item_path, { ...item, ...shown }));
|
|
309
|
+
}
|
|
310
|
+
/** `value` at the JSON pointer in `doc`, creating maps (and lists, for numeric tokens) on the way. */
|
|
311
|
+
function setPointer(doc, pointer, value) {
|
|
312
|
+
const tokens = pointer.slice(1).split("/");
|
|
313
|
+
let cur = doc;
|
|
314
|
+
tokens.forEach((t, i) => {
|
|
315
|
+
const last = i === tokens.length - 1;
|
|
316
|
+
const holder = cur;
|
|
317
|
+
if (last)
|
|
318
|
+
holder[t] = value;
|
|
319
|
+
else
|
|
320
|
+
cur = (holder[t] ??= /^\d+$/.test(tokens[i + 1]) ? [] : {});
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
/** POST to a `deletes` path (assumption R11): remove the objects the body names. */
|
|
324
|
+
function bulkDelete(state, spec, body) {
|
|
325
|
+
const named = spec.ids.slice(1).split("/").reduce((cur, t) => (isRecord(cur) ? cur[t] : Array.isArray(cur) ? cur[Number(t)] : undefined), body);
|
|
326
|
+
const ids = (Array.isArray(named) ? named : [named]).filter(isId).map(String);
|
|
327
|
+
const list = state.collections[spec.collection] ?? [];
|
|
328
|
+
const idf = styleOf(state, spec.collection).id_field;
|
|
329
|
+
const gone = list.filter((i) => ids.includes(String(i[idf])));
|
|
330
|
+
if (gone.length === 0)
|
|
331
|
+
return notFound();
|
|
332
|
+
state.collections[spec.collection] = list.filter((i) => !gone.includes(i));
|
|
333
|
+
return new Reply(200, { deleted: gone.map((i) => i[idf]) });
|
|
334
|
+
}
|
|
335
|
+
/** A write to the object at `path` with its style's `write_fields` stored under their read names (R2). */
|
|
336
|
+
function renamed(state, path, body) {
|
|
337
|
+
const names = state.styles[path]?.write_fields ?? {};
|
|
338
|
+
return Object.fromEntries(Object.entries(body).map(([k, v]) => [names[k] ?? k, v]));
|
|
339
|
+
}
|
|
340
|
+
function patch(state, t, body) {
|
|
341
|
+
if (!isRecord(body))
|
|
342
|
+
return error(400, "body must be a JSON object");
|
|
343
|
+
if (t.kind === "object") {
|
|
344
|
+
mergePatch(t.object, renamed(state, t.path, body));
|
|
345
|
+
return new Reply(200, t.object);
|
|
346
|
+
}
|
|
347
|
+
if (t.kind !== "item")
|
|
348
|
+
return notFound();
|
|
349
|
+
const style = styleOf(state, t.collection);
|
|
350
|
+
const id = t.item[style.id_field];
|
|
351
|
+
mergePatch(t.item, body);
|
|
352
|
+
t.item[style.id_field] = id;
|
|
353
|
+
return new Reply(200, envelope(style.item_path, t.item));
|
|
354
|
+
}
|
|
355
|
+
/** A PUT to `<collection>/<id>` that names no item: an upsert at a client-chosen key creates it (R3). */
|
|
356
|
+
function putNew(state, raw, body) {
|
|
357
|
+
const path = normPath(raw);
|
|
358
|
+
const cut = path.lastIndexOf("/");
|
|
359
|
+
const at = cut < 0 ? undefined : collectionAt(state, path.slice(0, cut));
|
|
360
|
+
if (!at)
|
|
361
|
+
return notFound();
|
|
362
|
+
const style = styleOf(state, at);
|
|
363
|
+
const id = decodeURIComponent(path.slice(cut + 1));
|
|
364
|
+
const item = { ...structuredClone(body), [style.id_field]: style.numeric_ids && /^\d+$/.test(id) ? Number(id) : id };
|
|
365
|
+
state.collections[at].push(item);
|
|
366
|
+
return new Reply(200, envelope(style.item_path, item));
|
|
367
|
+
}
|
|
368
|
+
function put(state, t, body, raw) {
|
|
369
|
+
if (!isRecord(body))
|
|
370
|
+
return error(400, "body must be a JSON object");
|
|
371
|
+
if (t.kind === "none")
|
|
372
|
+
return putNew(state, raw, body);
|
|
373
|
+
if (t.kind === "object") {
|
|
374
|
+
state.objects[t.path] = structuredClone(renamed(state, t.path, body));
|
|
375
|
+
return new Reply(200, state.objects[t.path]);
|
|
376
|
+
}
|
|
377
|
+
if (t.kind !== "item")
|
|
378
|
+
return notFound();
|
|
379
|
+
const style = styleOf(state, t.collection);
|
|
380
|
+
const next = { ...structuredClone(body), [style.id_field]: t.item[style.id_field] };
|
|
381
|
+
state.collections[t.collection][t.index] = next;
|
|
382
|
+
return new Reply(200, envelope(style.item_path, next));
|
|
383
|
+
}
|
|
384
|
+
function list(core, state, t, cursor) {
|
|
385
|
+
const style = styleOf(state, t.path);
|
|
386
|
+
const pg = style.next_path === null ? { items: t.items, next: null } : page(core, t.items, cursor);
|
|
387
|
+
return new Reply(200, listBody(style, pg.items, pg.next));
|
|
388
|
+
}
|
|
389
|
+
const routes = router([
|
|
390
|
+
route("POST", "/oauth/token", ({ state, headers, body }) => {
|
|
391
|
+
if (!state.auth?.clients)
|
|
392
|
+
return error(404, "no token endpoint: the rest sim's auth seed configures no OAuth2 clients");
|
|
393
|
+
const issued = { clients: state.auth.clients, ttlSeconds: state.auth.token_ttl ?? 3600, issued: state.auth.issued };
|
|
394
|
+
return issueToken(issued, headers, body);
|
|
395
|
+
}),
|
|
396
|
+
route("GET", "/*path", ({ core, state, params, url }) => {
|
|
397
|
+
const t = resolve(state, `/${params.path}`, url.searchParams);
|
|
398
|
+
if (t.kind === "object")
|
|
399
|
+
return new Reply(200, envelope(state.styles[t.path]?.item_path ?? "", t.object));
|
|
400
|
+
if (t.kind === "item")
|
|
401
|
+
return new Reply(200, envelope(styleOf(state, t.collection).item_path, t.item));
|
|
402
|
+
if (t.kind === "none")
|
|
403
|
+
return notFound();
|
|
404
|
+
return list(core, state, t, url.searchParams.get("cursor"));
|
|
405
|
+
}),
|
|
406
|
+
route("POST", "/*path", ({ core, state, params, body, headers }) => {
|
|
407
|
+
const read = state.reads[normPath(`/${params.path}`)];
|
|
408
|
+
if (read !== undefined)
|
|
409
|
+
return readObject(state, read);
|
|
410
|
+
const bulk = state.deletes[normPath(`/${params.path}`)];
|
|
411
|
+
if (bulk)
|
|
412
|
+
return bulkDelete(state, bulk, body);
|
|
413
|
+
const suffix = suffixTarget(state, normPath(`/${params.path}`));
|
|
414
|
+
if (suffix)
|
|
415
|
+
return upsertAt(core, state, suffix, body, headers);
|
|
416
|
+
const t = resolve(state, `/${params.path}`);
|
|
417
|
+
if (t.kind === "object")
|
|
418
|
+
return patch(state, t, body);
|
|
419
|
+
if (t.kind === "item")
|
|
420
|
+
return patch(state, t, bodyFor(state, t.collection, body, headers));
|
|
421
|
+
const raw = normPath(`/${params.path}`);
|
|
422
|
+
const path = t.kind === "collection" ? t.path : (state.aliases[raw] ?? raw);
|
|
423
|
+
return create(core, state, path, bodyFor(state, path, body, headers), headers);
|
|
424
|
+
}),
|
|
425
|
+
route("PATCH", "/*path", ({ state, params, body, headers, url }) => {
|
|
426
|
+
const t = resolve(state, `/${params.path}`, url.searchParams);
|
|
427
|
+
return patch(state, t, t.kind === "item" ? bodyFor(state, t.collection, body, headers) : body);
|
|
428
|
+
}),
|
|
429
|
+
route("PUT", "/*path", ({ state, params, body, headers, url }) => {
|
|
430
|
+
const t = resolve(state, `/${params.path}`, url.searchParams);
|
|
431
|
+
return put(state, t, t.kind === "item" ? bodyFor(state, t.collection, body, headers) : body, `/${params.path}`);
|
|
432
|
+
}),
|
|
433
|
+
route("DELETE", "/*path", ({ state, params, url }) => {
|
|
434
|
+
const t = resolve(state, `/${params.path}`, url.searchParams);
|
|
435
|
+
if (t.kind === "item") {
|
|
436
|
+
state.collections[t.collection].splice(t.index, 1);
|
|
437
|
+
return new Reply(200, { id: t.item[styleOf(state, t.collection).id_field], deleted: true });
|
|
438
|
+
}
|
|
439
|
+
if (t.kind !== "object")
|
|
440
|
+
return notFound();
|
|
441
|
+
delete state.objects[t.path];
|
|
442
|
+
return new Reply(200, { id: t.path, deleted: true });
|
|
443
|
+
}),
|
|
444
|
+
], notFound);
|
|
445
|
+
/** RFC 7396 merge patch of `target` in place: maps merge recursively, `null` deletes, anything else replaces. */
|
|
446
|
+
function mergePatch(target, patch) {
|
|
447
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
448
|
+
if (v === null)
|
|
449
|
+
delete target[k];
|
|
450
|
+
else if (isRecord(v) && isRecord(target[k]))
|
|
451
|
+
mergePatch(target[k], v);
|
|
452
|
+
else
|
|
453
|
+
target[k] = structuredClone(v);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
function isRecord(v) {
|
|
457
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
458
|
+
}
|
|
459
|
+
function error(status, message) {
|
|
460
|
+
return new Reply(status, { error: message });
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=rest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../../src/routes/rest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulated Supabase Management API (https://api.supabase.com/v1): preview branches of a project, and the project's
|
|
3
|
+
* Auth redirect allow-list.
|
|
4
|
+
*
|
|
5
|
+
* Assumptions about the real API that this fake encodes, each marked with how far it is checked. "Verified" means
|
|
6
|
+
* against Supabase's published OpenAPI document (https://api.supabase.com/api/v1-json, fetched 2026-10-11; rendered
|
|
7
|
+
* at https://supabase.com/docs/reference/api/introduction) unless another source is named; see
|
|
8
|
+
* docs/api-verification.md:
|
|
9
|
+
* S1. POST /v1/projects/{ref}/branches takes `{ branch_name }` (required, the only required field) and answers
|
|
10
|
+
* 201 with a BranchResponse: `id` (uuid), `name` (= branch_name), `project_ref` (the branch's own project),
|
|
11
|
+
* `parent_project_ref`, `is_default`, `persistent`, `status`, `created_at` (verified: CreateBranchBody,
|
|
12
|
+
* BranchResponse). That `project_ref` is known in the 201 answer, before provisioning finishes, is implied by
|
|
13
|
+
* the schema (required) but unverified.
|
|
14
|
+
* S2. GET /v1/projects/{ref}/branches answers a bare array of BranchResponse, unpaged (verified: no page
|
|
15
|
+
* parameters, `type: array`). That the list includes the project's own default branch (`is_default: true`,
|
|
16
|
+
* `project_ref` = the parent) once branching is enabled is unverified; the adapter skips `is_default` either
|
|
17
|
+
* way and never manages it.
|
|
18
|
+
* S3. A branch is provisioned asynchronously: GET /v1/branches/{ref} answers BranchDetailResponse whose `status`
|
|
19
|
+
* (the project status enum) is `COMING_UP` until it is ready and `ACTIVE_HEALTHY` after (verified: schema and
|
|
20
|
+
* enum). Here this takes chaos `supabase_ready_ms` (default 0). That the detail answers 200 (not 404) while
|
|
21
|
+
* the branch is coming up, and that `ACTIVE_HEALTHY` is the right "ready" signal, are unverified: needs a
|
|
22
|
+
* live account. The BranchResponse `status` (CREATING_PROJECT, …) is deprecated in the spec and not used.
|
|
23
|
+
* S4. The detail carries `db_host`, `db_port` (required), `db_user` and `db_pass` (optional in the spec,
|
|
24
|
+
* verified). That `db_pass` is returned to a personal access token is unverified (pinned by the contract
|
|
25
|
+
* suite). The database is `postgres` (Supabase's default database name, verified in the connection docs,
|
|
26
|
+
* https://supabase.com/docs/guides/database/connecting-to-postgres) and the API URL is
|
|
27
|
+
* `https://<ref>.supabase.co` (verified: https://supabase.com/docs/guides/api).
|
|
28
|
+
* S5. Creating a branch whose name exists in the project answers 409. Unverified: the spec documents only 201,
|
|
29
|
+
* 401, 403, 429 and 500. The adapter re-reads the list after a 409, or a 400/422, before reporting it.
|
|
30
|
+
* S6. DELETE /v1/branches/{ref} answers 200 `{ message: "ok" }` and the branch is gone from the list at once
|
|
31
|
+
* (verified: BranchDeleteResponse; "by default, deletes immediately"). An unknown ref answers 404:
|
|
32
|
+
* unverified (the spec documents no 404).
|
|
33
|
+
* S7. GET /v1/projects/{ref}/config/auth answers the auth config with `uri_allow_list`, a nullable string
|
|
34
|
+
* (verified: AuthConfigResponse, required); PATCH with `{ uri_allow_list }` alone sets that field and
|
|
35
|
+
* leaves the others, answering the whole config (verified: UpdateAuthConfigBody has no required field).
|
|
36
|
+
* PATCH offers no precondition (no ETag or version), verified by its absence from the spec.
|
|
37
|
+
* S8. The allow-list is comma-separated URLs (verified: Supabase Auth's `URI_ALLOW_LIST`, "a comma separated
|
|
38
|
+
* list of URIs", https://github.com/supabase/auth#general-config). Whitespace around commas is ignored by
|
|
39
|
+
* Auth; whether the API stores the string verbatim (here: yes) is unverified.
|
|
40
|
+
* S9. A preview branch is a project with its own Auth config, read and written through the same
|
|
41
|
+
* /v1/projects/{ref}/config/auth with the branch's ref (`project_ref` is a "Project ref" in the spec,
|
|
42
|
+
* verified; branches have "their own Supabase instance and API credentials", verified in
|
|
43
|
+
* https://supabase.com/docs/guides/deployment/branching). That the endpoint accepts a branch's ref, and
|
|
44
|
+
* what the branch's allow-list starts as (here: empty), are unverified.
|
|
45
|
+
*/
|
|
46
|
+
import { type CreatedBy, type ProviderSim, type SimCore } from "../provider.js";
|
|
47
|
+
/** One simulated Supabase branch: a project of its own (`project_ref`) under a parent project. */
|
|
48
|
+
export interface SupabaseBranch {
|
|
49
|
+
/** The branch id (a uuid in Supabase; deprecated as a path parameter). */
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
/** The branch's own project ref: its API URL, database host and the path parameter of GET/DELETE /branches. */
|
|
53
|
+
project_ref: string;
|
|
54
|
+
parent_project_ref: string;
|
|
55
|
+
/** The project's own branch (the one that is the parent project itself). */
|
|
56
|
+
is_default: boolean;
|
|
57
|
+
/** `COMING_UP` until this time, `ACTIVE_HEALTHY` after (chaos `supabase_ready_ms`). */
|
|
58
|
+
readyAt: number;
|
|
59
|
+
db_pass: string;
|
|
60
|
+
/** A branch is a project with its own Auth config (assumption S9). */
|
|
61
|
+
auth: SupabaseAuth;
|
|
62
|
+
created_at: string;
|
|
63
|
+
createdAt: number;
|
|
64
|
+
createdBy: CreatedBy;
|
|
65
|
+
}
|
|
66
|
+
/** One simulated Supabase project: its branches and its Auth config. */
|
|
67
|
+
export interface SupabaseProject {
|
|
68
|
+
branches: SupabaseBranch[];
|
|
69
|
+
auth: SupabaseAuth;
|
|
70
|
+
}
|
|
71
|
+
/** The part of a project's Auth config the sim keeps. */
|
|
72
|
+
export interface SupabaseAuth {
|
|
73
|
+
site_url: string;
|
|
74
|
+
uri_allow_list: string | null;
|
|
75
|
+
}
|
|
76
|
+
/** The simulated Supabase's state: projects by ref. */
|
|
77
|
+
export interface SupabaseState {
|
|
78
|
+
projects: Record<string, SupabaseProject>;
|
|
79
|
+
}
|
|
80
|
+
/** What a scenario or test seeds the simulated Supabase with (`seed: { supabase: … }`). */
|
|
81
|
+
export interface SupabaseSeed {
|
|
82
|
+
/** Project ref → branches that already exist (made "by a human", so unmanaged) and the Auth allow-list. */
|
|
83
|
+
projects: Record<string, {
|
|
84
|
+
branches?: Array<{
|
|
85
|
+
name: string;
|
|
86
|
+
}>;
|
|
87
|
+
uri_allow_list?: string | null;
|
|
88
|
+
site_url?: string;
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
/** The parent project the default seed creates, a ref of 20 lowercase letters like Supabase's. */
|
|
92
|
+
export declare const SUPABASE_DEMO_PROJECT = "demoprojectrefabcdef";
|
|
93
|
+
/** The simulated Supabase Management API, registered in `PROVIDERS` (packages/sim/src/state.ts), served under `/supabase`. */
|
|
94
|
+
export declare const supabaseSim: ProviderSim<SupabaseState, SupabaseSeed>;
|
|
95
|
+
/** The allow-list's entries: comma-separated, whitespace around them ignored (assumption S8). */
|
|
96
|
+
export declare function supabaseAllowList(p: SupabaseProject): string[];
|
|
97
|
+
/**
|
|
98
|
+
* A new (not yet added) branch of project `parent`, ready at once. Tests use it to seed "someone else's" branch.
|
|
99
|
+
* Refs are 20 lowercase letters, deterministic after a reset.
|
|
100
|
+
*/
|
|
101
|
+
export declare function newSupabaseBranch(core: SimCore, parent: string, name: string, createdBy: CreatedBy): SupabaseBranch;
|
|
102
|
+
/** The connection string the adapter builds from a branch's detail (assumption S4). */
|
|
103
|
+
export declare function supabaseConnectionString(b: SupabaseBranch): string;
|