@sponson/adapters 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 (132) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +4 -2
  3. package/dist/algolia.d.ts +6 -0
  4. package/dist/algolia.js +151 -0
  5. package/dist/algolia.js.map +1 -0
  6. package/dist/clerk.d.ts +8 -0
  7. package/dist/clerk.js +107 -0
  8. package/dist/clerk.js.map +1 -0
  9. package/dist/cloudflare.d.ts +25 -0
  10. package/dist/cloudflare.js +310 -0
  11. package/dist/cloudflare.js.map +1 -0
  12. package/dist/common.d.ts +73 -0
  13. package/dist/common.js +140 -0
  14. package/dist/common.js.map +1 -0
  15. package/dist/digest.d.ts +46 -0
  16. package/dist/digest.js +129 -0
  17. package/dist/digest.js.map +1 -0
  18. package/dist/digitalocean.d.ts +5 -0
  19. package/dist/digitalocean.js +243 -0
  20. package/dist/digitalocean.js.map +1 -0
  21. package/dist/http-adapter-action.d.ts +63 -0
  22. package/dist/http-adapter-action.js +369 -0
  23. package/dist/http-adapter-action.js.map +1 -0
  24. package/dist/http-adapter-auth.d.ts +88 -0
  25. package/dist/http-adapter-auth.js +437 -0
  26. package/dist/http-adapter-auth.js.map +1 -0
  27. package/dist/http-adapter-client.d.ts +51 -0
  28. package/dist/http-adapter-client.js +156 -0
  29. package/dist/http-adapter-client.js.map +1 -0
  30. package/dist/http-adapter-graphql.d.ts +39 -0
  31. package/dist/http-adapter-graphql.js +157 -0
  32. package/dist/http-adapter-graphql.js.map +1 -0
  33. package/dist/http-adapter-list.d.ts +33 -0
  34. package/dist/http-adapter-list.js +421 -0
  35. package/dist/http-adapter-list.js.map +1 -0
  36. package/dist/http-adapter-resource.d.ts +29 -0
  37. package/dist/http-adapter-resource.js +462 -0
  38. package/dist/http-adapter-resource.js.map +1 -0
  39. package/dist/http-adapter-spec.d.ts +216 -0
  40. package/dist/http-adapter-spec.js +660 -0
  41. package/dist/http-adapter-spec.js.map +1 -0
  42. package/dist/http-adapter.d.ts +16 -0
  43. package/dist/http-adapter.js +28 -0
  44. package/dist/http-adapter.js.map +1 -0
  45. package/dist/http.d.ts +179 -0
  46. package/dist/http.js +352 -0
  47. package/dist/http.js.map +1 -0
  48. package/dist/index.d.ts +28 -0
  49. package/dist/index.js +45 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/launchdarkly.d.ts +15 -0
  52. package/dist/launchdarkly.js +337 -0
  53. package/dist/launchdarkly.js.map +1 -0
  54. package/dist/manual.d.ts +13 -0
  55. package/dist/manual.js +201 -0
  56. package/dist/manual.js.map +1 -0
  57. package/dist/neon.d.ts +8 -0
  58. package/dist/neon.js +167 -0
  59. package/dist/neon.js.map +1 -0
  60. package/dist/netlify.d.ts +18 -0
  61. package/dist/netlify.js +436 -0
  62. package/dist/netlify.js.map +1 -0
  63. package/dist/planetscale.d.ts +10 -0
  64. package/dist/planetscale.js +311 -0
  65. package/dist/planetscale.js.map +1 -0
  66. package/dist/providers.d.ts +26 -0
  67. package/dist/providers.js +36 -0
  68. package/dist/providers.js.map +1 -0
  69. package/dist/recipes.d.ts +167 -0
  70. package/dist/recipes.js +246 -0
  71. package/dist/recipes.js.map +1 -0
  72. package/dist/secrets.d.ts +72 -0
  73. package/dist/secrets.js +476 -0
  74. package/dist/secrets.js.map +1 -0
  75. package/dist/sigv4.d.ts +56 -0
  76. package/dist/sigv4.js +118 -0
  77. package/dist/sigv4.js.map +1 -0
  78. package/dist/supabase.d.ts +9 -0
  79. package/dist/supabase.js +385 -0
  80. package/dist/supabase.js.map +1 -0
  81. package/dist/vercel.d.ts +8 -0
  82. package/dist/vercel.js +475 -0
  83. package/dist/vercel.js.map +1 -0
  84. package/dist/xata.d.ts +8 -0
  85. package/dist/xata.js +142 -0
  86. package/dist/xata.js.map +1 -0
  87. package/dist/xml.d.ts +25 -0
  88. package/dist/xml.js +211 -0
  89. package/dist/xml.js.map +1 -0
  90. package/package.json +58 -3
  91. package/recipes/amplify.yaml +147 -0
  92. package/recipes/auth0.yaml +178 -0
  93. package/recipes/azure_swa.yaml +116 -0
  94. package/recipes/cloud_run.yaml +97 -0
  95. package/recipes/cloudflare.yaml +108 -0
  96. package/recipes/cockroachdb.yaml +132 -0
  97. package/recipes/configcat.yaml +123 -0
  98. package/recipes/datadog.yaml +136 -0
  99. package/recipes/firebase.yaml +84 -0
  100. package/recipes/flagsmith.yaml +98 -0
  101. package/recipes/fly.yaml +97 -0
  102. package/recipes/fly_machines.yaml +67 -0
  103. package/recipes/gcs.yaml +102 -0
  104. package/recipes/github.yaml +123 -0
  105. package/recipes/growthbook.yaml +124 -0
  106. package/recipes/heroku.yaml +98 -0
  107. package/recipes/honeycomb.yaml +89 -0
  108. package/recipes/inngest.yaml +97 -0
  109. package/recipes/kinde.yaml +120 -0
  110. package/recipes/mongodb_atlas.yaml +119 -0
  111. package/recipes/okta.yaml +177 -0
  112. package/recipes/posthog.yaml +127 -0
  113. package/recipes/postmark.yaml +105 -0
  114. package/recipes/postmark_server.yaml +93 -0
  115. package/recipes/prisma.yaml +150 -0
  116. package/recipes/qstash.yaml +134 -0
  117. package/recipes/railway.yaml +130 -0
  118. package/recipes/render.yaml +103 -0
  119. package/recipes/resend.yaml +130 -0
  120. package/recipes/s3.yaml +108 -0
  121. package/recipes/sendgrid.yaml +165 -0
  122. package/recipes/sentry.yaml +158 -0
  123. package/recipes/split.yaml +121 -0
  124. package/recipes/statsig.yaml +124 -0
  125. package/recipes/stripe.yaml +310 -0
  126. package/recipes/stytch.yaml +113 -0
  127. package/recipes/svix.yaml +109 -0
  128. package/recipes/turso.yaml +98 -0
  129. package/recipes/unleash.yaml +149 -0
  130. package/recipes/upstash.yaml +130 -0
  131. package/recipes/vercel.yaml +116 -0
  132. package/recipes/workos.yaml +70 -0
package/dist/xata.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Xata adapter (the Postgres platform): a copy-on-write branch per scope, child of a parent branch. A new branch
3
+ * takes a moment to come up, so `apply` waits for it to be healthy, then reads its credentials: the wait and the
4
+ * second request are why this is an adapter and not an `http` recipe (ADR 0017, "No polling"). The API assumptions
5
+ * it relies on are numbered XA1… at the top of packages/sim/src/routes/xata.ts.
6
+ *
7
+ * - Key: `branch:<name>`. Id: Xata's branch id. The organization and project are the provider block.
8
+ * - Hash: the name only. The parent is used when the branch is created; a branch cannot be moved to another
9
+ * parent, so changing `parent_id` later changes nothing, and a deleted branch is `missing` (re-created by the
10
+ * next apply, from the parent as it is then).
11
+ * - Outputs: the branch id, and its connection string (sensitive), read from the credentials endpoint on every run
12
+ * (XA6), so dependents in later runs get it too.
13
+ */
14
+ import { setTimeout as sleep } from "node:timers/promises";
15
+ import { SponsonError, canonicalJson, markerKind, sha256 } from "@sponson/core";
16
+ // Only the stable authoring API exported from `@sponson/adapters` (listed in CONTRIBUTING.md).
17
+ import { assertNoPending, clientFor, deleteIgnoringNotFound, optionalEnv, paramError, requireEnv, requireProvider, stringParam } from "./common.js";
18
+ import { ShapeError, isObject, records } from "./http.js";
19
+ const ADAPTER = "xata";
20
+ /** The environment Xata reads; declared once, used by the code below and by the generated docs (`about`). */
21
+ const ABOUT = { credentialEnv: "XATA_API_KEY", baseUrlEnv: "XATA_API_URL", title: "Xata", category: "databases", detect: { deps: ["@xata.io/"], env: ["XATA_*"], files: [".xatarc"] } };
22
+ /** Xata's API base URL (XA1). `XATA_API_URL` overrides it; tests and scenarios point that at the sim. */
23
+ export const XATA_DEFAULT_API_URL = "https://api.xata.tech";
24
+ /** How often a new branch is polled, and for how long (milliseconds; overridable for tests). */
25
+ const POLL_MS = { env: "SPONSON_XATA_POLL_MS", fallback: 2000 };
26
+ const READY_TIMEOUT_MS = { env: "SPONSON_XATA_READY_TIMEOUT_MS", fallback: 10 * 60 * 1000 };
27
+ function msFromEnv(env, s) {
28
+ const raw = optionalEnv(env, s.env);
29
+ const n = Number(raw);
30
+ return raw !== undefined && Number.isFinite(n) && n >= 0 ? n : s.fallback;
31
+ }
32
+ function client(actx) {
33
+ const token = requireEnv(actx.env, ABOUT.credentialEnv, ADAPTER);
34
+ const org = requireProvider(actx, "organization", ADAPTER);
35
+ const project = requireProvider(actx, "project", ADAPTER);
36
+ const api = clientFor(actx, ADAPTER, { baseUrl: optionalEnv(actx.env, ABOUT.baseUrlEnv) ?? XATA_DEFAULT_API_URL, token });
37
+ return { api, base: `/organizations/${enc(org)}/projects/${enc(project)}/branches` };
38
+ }
39
+ function enc(s) {
40
+ return encodeURIComponent(s);
41
+ }
42
+ const PREFIX = "branch:";
43
+ function branchRecord(b) {
44
+ return { key: `${PREFIX}${b.name}`, id: b.id, hash: sha256(canonicalJson({ name: b.name })), label: `Xata branch ${b.name}` };
45
+ }
46
+ /** The branch named `name`, or null (XA3: names are not unique, so more than one is refused, never guessed). */
47
+ async function findBranch(c, name) {
48
+ const list = await c.api.get(c.base, (b) => {
49
+ if (!isObject(b))
50
+ throw new ShapeError("expected `{ branches }`");
51
+ return records(b.branches, "`branches`", ["id", "name"]);
52
+ });
53
+ const hits = list.filter((b) => b.name === name);
54
+ if (hits.length > 1)
55
+ throw paramError(ADAPTER, `${hits.length} branches are named ${name} in the project; rename one or give this line another name`, "name");
56
+ return hits[0] ? { id: hits[0].id, name: hits[0].name } : null;
57
+ }
58
+ /** The connection string from the credentials endpoint (XA6). */
59
+ async function connectionString(c, id) {
60
+ return c.api.get(`${c.base}/${enc(id)}/credentials?username=xata`, (b) => {
61
+ if (!isObject(b) || typeof b.connectionString !== "string" || b.connectionString === "")
62
+ throw new ShapeError("expected `{ connectionString }`");
63
+ return b.connectionString;
64
+ });
65
+ }
66
+ async function outputsOf(c, b) {
67
+ return { branch_id: b.id, connection_string: await connectionString(c, b.id) };
68
+ }
69
+ /** `status.statusType` of a branch (XA5), or "" when the answer has none yet. */
70
+ function statusType(body) {
71
+ const status = isObject(body) ? body.status : undefined;
72
+ return isObject(status) && typeof status.statusType === "string" ? status.statusType : "";
73
+ }
74
+ /** Poll the branch until it is healthy (XA5); FAULT fails, a timeout is WAIT_TIMEOUT that the next run resumes. */
75
+ async function waitHealthy(actx, c, b) {
76
+ const deadline = Date.now() + msFromEnv(actx.env, READY_TIMEOUT_MS);
77
+ for (;;) {
78
+ const type = statusType(await c.api.get(`${c.base}/${enc(b.id)}`));
79
+ if (/HEALTHY$/.test(type))
80
+ return;
81
+ if (/FAULT$/.test(type))
82
+ throw new SponsonError("PROVIDER_INVALID", `xata: branch ${b.name} reports ${type} while coming up`, { adapter: ADAPTER, branch: b.name });
83
+ if (Date.now() > deadline) {
84
+ throw new SponsonError("WAIT_TIMEOUT", `xata: branch ${b.name} is not healthy after ${msFromEnv(actx.env, READY_TIMEOUT_MS)}ms (${READY_TIMEOUT_MS.env}); run again to keep waiting`, { adapter: ADAPTER, branch: b.name });
85
+ }
86
+ actx.log(`branch ${b.name} not healthy yet (${type || "no status"})`);
87
+ await sleep(msFromEnv(actx.env, POLL_MS));
88
+ }
89
+ }
90
+ const branch = {
91
+ outputs: { branch_id: { available: "immediate" }, connection_string: { available: "immediate", sensitive: true } },
92
+ async read(actx, params) {
93
+ if (markerKind(params.name) !== null)
94
+ return null;
95
+ const c = client(actx);
96
+ const found = await findBranch(c, stringParam(params, "name", ADAPTER));
97
+ if (!found)
98
+ return null;
99
+ return { resources: [branchRecord(found)], outputs: await outputsOf(c, found) };
100
+ },
101
+ diff(live, params) {
102
+ const name = params.name;
103
+ const key = markerKind(name) !== null ? `${PREFIX}(pending)` : `${PREFIX}${String(name)}`;
104
+ const label = `Xata branch ${String(name)}`;
105
+ if (live?.resources.some((r) => r.key === key))
106
+ return [{ key, kind: "unchanged", label }];
107
+ const parent = params.parent_id;
108
+ const after = markerKind(parent) !== null ? { state: "pending", ref: String(parent) } : { state: "literal", value: `child of ${String(parent)}` };
109
+ return [{ key, kind: "create", label, before: { state: "absent" }, after }];
110
+ },
111
+ async apply(actx, params, live) {
112
+ assertNoPending(params, ADAPTER);
113
+ const name = stringParam(params, "name", ADAPTER);
114
+ const parent = stringParam(params, "parent_id", ADAPTER);
115
+ const key = `${PREFIX}${name}`;
116
+ if (live?.resources.some((r) => r.key === key))
117
+ return { resources: live.resources, outputs: live.outputs, created: [] };
118
+ const c = client(actx);
119
+ // Announce the create before sending it; a create whose answer was lost is found by name next time (XA3).
120
+ await actx.intend([key]);
121
+ actx.log(`create branch ${name} from ${parent}`);
122
+ const created = await c.api.post(c.base, { mode: "inherit", parentID: parent, name }, (b) => {
123
+ const [r] = records([b], "the branch", ["id", "name"]);
124
+ return { id: r.id, name: r.name };
125
+ });
126
+ await waitHealthy(actx, c, created);
127
+ return { resources: [branchRecord(created)], outputs: await outputsOf(c, created), created: [key] };
128
+ },
129
+ async destroy(actx, resources) {
130
+ const c = client(actx);
131
+ // An intent the engine could not locate has no id: nothing is deleted on a guess (names are not unique, XA3).
132
+ for (const r of resources)
133
+ if (r.id !== "")
134
+ await deleteIgnoringNotFound(c.api, `${c.base}/${enc(r.id)}`);
135
+ },
136
+ };
137
+ /**
138
+ * The Xata adapter (`adapter: xata` in a plan). Registered in `createRegistry()`; needs `XATA_API_KEY` and
139
+ * `providers.xata.organization` and `.project`.
140
+ */
141
+ export const xataAdapter = { name: ADAPTER, ops: { branch }, about: ABOUT };
142
+ //# sourceMappingURL=xata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xata.js","sourceRoot":"","sources":["../src/xata.ts"],"names":[],"mappings":"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"}
package/dist/xml.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A minimal XML codec for the generic `http` adapter's `encoding: xml` (S3-style configuration documents such as a
3
+ * bucket's `CORSConfiguration`), mapping XML to the JSON shapes the adapter already works with:
4
+ *
5
+ * - an element with child elements is a map of child name → value; a child that repeats is a list of values;
6
+ * - an element with only text is that text, as a string (XML has no numbers or booleans); an empty element is "";
7
+ * - attributes are `@name` keys (`@xmlns`), and the text of an element that also has attributes is `#text`.
8
+ *
9
+ * Encoding is the inverse: the body is a map with one key (the root element), lists become repeated elements,
10
+ * `null` leaves an element out. A single repeated element therefore reads back as a value, not a list of one.
11
+ *
12
+ * Safe by construction: no DTDs (a `<!DOCTYPE` or `<!ENTITY` is refused, so no external entities and no entity
13
+ * expansion), only the five predefined entities and numeric character references, a depth limit, and no
14
+ * namespace processing (prefixed names are kept as written).
15
+ */
16
+ /** Nesting deeper than this is refused rather than recursed into. */
17
+ export declare const XML_MAX_DEPTH = 64;
18
+ /** Thrown for a document (or a body) this codec does not handle. */
19
+ export declare class XmlError extends Error {
20
+ constructor(message: string);
21
+ }
22
+ /** A body as an XML document: a map with exactly one key, the root element. */
23
+ export declare function xmlEncode(body: unknown): string;
24
+ /** An XML document as `{ <root>: <value> }`. */
25
+ export declare function xmlDecode(xml: string): Record<string, unknown>;
package/dist/xml.js ADDED
@@ -0,0 +1,211 @@
1
+ /**
2
+ * A minimal XML codec for the generic `http` adapter's `encoding: xml` (S3-style configuration documents such as a
3
+ * bucket's `CORSConfiguration`), mapping XML to the JSON shapes the adapter already works with:
4
+ *
5
+ * - an element with child elements is a map of child name → value; a child that repeats is a list of values;
6
+ * - an element with only text is that text, as a string (XML has no numbers or booleans); an empty element is "";
7
+ * - attributes are `@name` keys (`@xmlns`), and the text of an element that also has attributes is `#text`.
8
+ *
9
+ * Encoding is the inverse: the body is a map with one key (the root element), lists become repeated elements,
10
+ * `null` leaves an element out. A single repeated element therefore reads back as a value, not a list of one.
11
+ *
12
+ * Safe by construction: no DTDs (a `<!DOCTYPE` or `<!ENTITY` is refused, so no external entities and no entity
13
+ * expansion), only the five predefined entities and numeric character references, a depth limit, and no
14
+ * namespace processing (prefixed names are kept as written).
15
+ */
16
+ /** Nesting deeper than this is refused rather than recursed into. */
17
+ export const XML_MAX_DEPTH = 64;
18
+ const NAME = /^[A-Za-z_][A-Za-z0-9_.-]*(?::[A-Za-z_][A-Za-z0-9_.-]*)?$/;
19
+ /** Thrown for a document (or a body) this codec does not handle. */
20
+ export class XmlError extends Error {
21
+ constructor(message) {
22
+ super(message);
23
+ this.name = "XmlError";
24
+ }
25
+ }
26
+ function escapeText(s) {
27
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
28
+ }
29
+ function escapeAttr(s) {
30
+ return escapeText(s).replace(/"/g, "&quot;");
31
+ }
32
+ function scalar(v, name) {
33
+ if (typeof v === "string")
34
+ return v;
35
+ if (typeof v === "number" || typeof v === "boolean")
36
+ return String(v);
37
+ throw new XmlError(`\`${name}\` must be a map, a list, a string, a number or a boolean`);
38
+ }
39
+ function checkName(name) {
40
+ if (!NAME.test(name))
41
+ throw new XmlError(`\`${name}\` is not an XML element name`);
42
+ }
43
+ function element(name, v, depth) {
44
+ if (depth > XML_MAX_DEPTH)
45
+ throw new XmlError(`nested deeper than ${XML_MAX_DEPTH} elements`);
46
+ if (v === null || v === undefined)
47
+ return "";
48
+ if (Array.isArray(v))
49
+ return v.map((x) => element(name, x, depth)).join("");
50
+ checkName(name);
51
+ if (typeof v !== "object")
52
+ return `<${name}>${escapeText(scalar(v, name))}</${name}>`;
53
+ let attrs = "";
54
+ let inner = "";
55
+ for (const [k, x] of Object.entries(v)) {
56
+ if (k.startsWith("@")) {
57
+ checkName(k.slice(1));
58
+ attrs += ` ${k.slice(1)}="${escapeAttr(scalar(x, k))}"`;
59
+ }
60
+ else if (k === "#text")
61
+ inner += escapeText(scalar(x, k));
62
+ else
63
+ inner += element(k, x, depth + 1);
64
+ }
65
+ return `<${name}${attrs}>${inner}</${name}>`;
66
+ }
67
+ /** A body as an XML document: a map with exactly one key, the root element. */
68
+ export function xmlEncode(body) {
69
+ if (typeof body !== "object" || body === null || Array.isArray(body) || Object.keys(body).length !== 1) {
70
+ throw new XmlError("an XML body must be a map with exactly one key: the root element, e.g. { CORSConfiguration: { … } }");
71
+ }
72
+ const [root, value] = Object.entries(body)[0];
73
+ return `<?xml version="1.0" encoding="UTF-8"?>${element(root, value ?? "", 0)}`;
74
+ }
75
+ const ENTITIES = { lt: "<", gt: ">", amp: "&", quot: '"', apos: "'" };
76
+ /** Text with its entity and character references replaced. */
77
+ function decodeEntities(s) {
78
+ return s.replace(/&(#x[0-9A-Fa-f]+|#[0-9]+|[A-Za-z]+);/g, (_m, ref) => {
79
+ if (ref.startsWith("#x"))
80
+ return String.fromCodePoint(parseInt(ref.slice(2), 16));
81
+ if (ref.startsWith("#"))
82
+ return String.fromCodePoint(parseInt(ref.slice(1), 10));
83
+ const v = ENTITIES[ref];
84
+ if (v === undefined)
85
+ throw new XmlError(`unknown entity &${ref};`);
86
+ return v;
87
+ });
88
+ }
89
+ function valueOf(e) {
90
+ if (e.children.length === 0) {
91
+ if (Object.keys(e.attrs).length === 0)
92
+ return e.text;
93
+ return { ...prefixed(e.attrs), ...(e.text.trim() !== "" ? { "#text": e.text } : {}) };
94
+ }
95
+ const groups = new Map();
96
+ for (const [name, v] of e.children) {
97
+ const list = groups.get(name);
98
+ if (list)
99
+ list.push(v);
100
+ else
101
+ groups.set(name, [v]);
102
+ }
103
+ const out = prefixed(e.attrs);
104
+ for (const [name, values] of groups)
105
+ out[name] = values.length === 1 ? values[0] : values;
106
+ return out;
107
+ }
108
+ function prefixed(attrs) {
109
+ return Object.fromEntries(Object.entries(attrs).map(([k, v]) => [`@${k}`, v]));
110
+ }
111
+ const ATTR = /([A-Za-z_][\w.:-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
112
+ function parseAttrs(s) {
113
+ const out = {};
114
+ for (const m of s.matchAll(ATTR))
115
+ out[m[1]] = decodeEntities(m[2] ?? m[3] ?? "");
116
+ return out;
117
+ }
118
+ /** Skip a construct starting at `i` that holds no data: declaration, processing instruction, comment. */
119
+ function skipMarkup(xml, i) {
120
+ const ends = [
121
+ ["<?", "?>"],
122
+ ["<!--", "-->"],
123
+ ];
124
+ for (const [start, end] of ends) {
125
+ if (xml.startsWith(start, i)) {
126
+ const j = xml.indexOf(end, i + start.length);
127
+ if (j < 0)
128
+ throw new XmlError(`unterminated ${start}`);
129
+ return j + end.length;
130
+ }
131
+ }
132
+ return -1;
133
+ }
134
+ /** Handle a tag at `i` (`<…`); returns the index after it. */
135
+ function tag(xml, i, stack, done) {
136
+ const skipped = skipMarkup(xml, i);
137
+ if (skipped >= 0)
138
+ return skipped;
139
+ if (xml.startsWith("<!DOCTYPE", i) || xml.startsWith("<!ENTITY", i))
140
+ throw new XmlError("DTDs and entity declarations are not accepted");
141
+ if (xml.startsWith("<![CDATA[", i))
142
+ return cdata(xml, i, stack);
143
+ const end = xml.indexOf(">", i);
144
+ if (end < 0)
145
+ throw new XmlError("unterminated tag");
146
+ const body = xml.slice(i + 1, end);
147
+ if (body.startsWith("/")) {
148
+ closingTag(body.slice(1).trim(), stack, done);
149
+ return end + 1;
150
+ }
151
+ const selfClosing = body.endsWith("/");
152
+ const inner = selfClosing ? body.slice(0, -1) : body;
153
+ const name = /^[^\s/>]+/.exec(inner)?.[0] ?? "";
154
+ if (!NAME.test(name))
155
+ throw new XmlError(`\`${name}\` is not an XML element name`);
156
+ if (stack.length >= XML_MAX_DEPTH)
157
+ throw new XmlError(`nested deeper than ${XML_MAX_DEPTH} elements`);
158
+ const open = { name, attrs: parseAttrs(inner.slice(name.length)), children: [], text: "" };
159
+ if (selfClosing)
160
+ close(open, stack, done);
161
+ else
162
+ stack.push(open);
163
+ return end + 1;
164
+ }
165
+ /** A CDATA section's text, appended to the element it is in; the index after it. */
166
+ function cdata(xml, i, stack) {
167
+ const j = xml.indexOf("]]>", i);
168
+ if (j < 0 || stack.length === 0)
169
+ throw new XmlError("misplaced or unterminated CDATA section");
170
+ stack[stack.length - 1].text += xml.slice(i + 9, j);
171
+ return j + 3;
172
+ }
173
+ function closingTag(name, stack, done) {
174
+ const open = stack.pop();
175
+ if (!open || open.name !== name)
176
+ throw new XmlError(`unexpected closing tag </${name}>`);
177
+ close(open, stack, done);
178
+ }
179
+ function close(open, stack, done) {
180
+ const value = valueOf(open);
181
+ const parent = stack[stack.length - 1];
182
+ if (parent)
183
+ parent.children.push([open.name, value]);
184
+ else
185
+ done({ name: open.name, value });
186
+ }
187
+ /** An XML document as `{ <root>: <value> }`. */
188
+ export function xmlDecode(xml) {
189
+ const stack = [];
190
+ let root;
191
+ let i = 0;
192
+ while (i < xml.length) {
193
+ const lt = xml.indexOf("<", i);
194
+ const text = xml.slice(i, lt < 0 ? xml.length : lt);
195
+ if (stack.length > 0)
196
+ stack[stack.length - 1].text += decodeEntities(text);
197
+ else if (text.trim() !== "")
198
+ throw new XmlError("text outside the root element");
199
+ if (lt < 0)
200
+ break;
201
+ if (root && skipMarkup(xml, lt) < 0)
202
+ throw new XmlError("more than one root element");
203
+ i = tag(xml, lt, stack, (r) => (root = r));
204
+ }
205
+ if (stack.length > 0)
206
+ throw new XmlError(`unclosed element <${stack[stack.length - 1].name}>`);
207
+ if (!root)
208
+ throw new XmlError("no root element");
209
+ return { [root.name]: root.value };
210
+ }
211
+ //# sourceMappingURL=xml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.js","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,61 @@
1
1
  {
2
2
  "name": "@sponson/adapters",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.5.0",
4
+ "description": "The built-in resource adapters and secret sources for Sponson.",
5
+ "keywords": [
6
+ "sponson",
7
+ "release",
8
+ "preview-environments",
9
+ "deployment",
10
+ "ci",
11
+ "vercel",
12
+ "neon",
13
+ "clerk",
14
+ "adapters",
15
+ "secrets",
16
+ "recipes"
17
+ ],
18
+ "license": "Apache-2.0",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/MishaBear94/Sponson.git",
22
+ "directory": "packages/adapters"
23
+ },
24
+ "engines": {
25
+ "node": ">=22"
26
+ },
27
+ "type": "module",
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "dependencies": {
37
+ "yaml": "^2.8.1",
38
+ "@sponson/core": "0.5.0"
39
+ },
40
+ "devDependencies": {
41
+ "@sponson/sim": "0.5.0"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "!dist/.tsbuildinfo",
46
+ "recipes",
47
+ "README.md",
48
+ "LICENSE"
49
+ ],
50
+ "publishConfig": {
51
+ "access": "public",
52
+ "provenance": true
53
+ },
54
+ "homepage": "https://sponson.mintlify.site",
55
+ "bugs": {
56
+ "url": "https://github.com/MishaBear94/Sponson/issues"
57
+ },
58
+ "scripts": {
59
+ "build": "tsc -b"
60
+ }
6
61
  }
@@ -0,0 +1,147 @@
1
+ # yaml-language-server: $schema=../../../schema/recipe.schema.json
2
+ # AWS Amplify Hosting API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
3
+ provider: amplify
4
+ title: AWS Amplify Hosting
5
+ category: deploy
6
+ verified_on: "2026-10-11"
7
+ docs:
8
+ - title: CreateBranch
9
+ url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_CreateBranch.html
10
+ - title: GetBranch
11
+ url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_GetBranch.html
12
+ - title: UpdateBranch
13
+ url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateBranch.html
14
+ - title: DeleteBranch
15
+ url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_DeleteBranch.html
16
+ - title: Amplify endpoints and quotas
17
+ url: https://docs.aws.amazon.com/general/latest/gr/amplify.html
18
+ - title: Create a signed AWS API request (SigV4)
19
+ url: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
20
+ api:
21
+ base_url: https://amplify.us-east-1.amazonaws.com
22
+ base_url_env: AMPLIFY_API_URL
23
+ auth:
24
+ aws_sigv4: { region: us-east-1, service: amplify, access_key_id_env: AWS_ACCESS_KEY_ID, secret_access_key_env: AWS_SECRET_ACCESS_KEY }
25
+ detect:
26
+ files: [amplify.yml]
27
+ starter:
28
+ - op: branch_variable
29
+ values: { branch_name: "${ctx.git.branch}" }
30
+ where:
31
+ app_id: "Amplify console → your app → App settings → General → App ID (`d…`), or `aws amplify list-apps --query 'apps[].appId'`"
32
+ assumptions:
33
+ - id: AM1
34
+ verified: true
35
+ text: "The Amplify API is regional (`https://amplify.<region>.amazonaws.com`) and signed with SigV4 for the service `amplify`. The recipe defaults to `us-east-1`; an app in another region sets `base_url` and `auth` (with its `region`) in the provider block, and temporary credentials (a CI role) add `session_token_env: AWS_SESSION_TOKEN` there."
36
+ source: https://docs.aws.amazon.com/general/latest/gr/amplify.html
37
+ - id: AM2
38
+ verified: true
39
+ text: "`POST /apps/{appId}/branches` (CreateBranch) creates a branch from `branchName` (required) and optional `description`, `stage` (PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST), `enableAutoBuild`, `environmentVariables`, …; it answers 200 with `{ branch }`."
40
+ source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_CreateBranch.html
41
+ - id: AM3
42
+ verified: true
43
+ text: "`GET /apps/{appId}/branches/{branchName}` (GetBranch) answers `{ branch }` with `branchName`, `stage`, `description`, `enableAutoBuild` and `environmentVariables` (a map of string to string)."
44
+ source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_GetBranch.html
45
+ - id: AM4
46
+ verified: true
47
+ text: "`POST /apps/{appId}/branches/{branchName}` (UpdateBranch) takes the same optional fields and answers `{ branch }`; `environmentVariables` is the branch's whole map of variables."
48
+ source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateBranch.html
49
+ - id: AM5
50
+ verified: true
51
+ text: "`DELETE /apps/{appId}/branches/{branchName}` (DeleteBranch) deletes a branch; an unknown app or branch is 404 `NotFoundException`."
52
+ source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_DeleteBranch.html
53
+ - id: AM6
54
+ verified: false
55
+ text: "UpdateBranch leaves the fields it is not sent as they are (so the branch op's update does not reset the variables, and the variable op's write does not reset the branch's settings), while an `environmentVariables` it is sent replaces the whole map, as the sim models it (assumption A4 of packages/sim/src/routes/aws.ts)."
56
+ - id: AM7
57
+ verified: false
58
+ text: "A build that ran before a variable was written does not see it: Sponson does not start a new job (StartJob), so order the variable lines before the branch's first build (`enable_auto_build: false` and a CI-started job, or the branch line, then the variables, then the push). The branches Amplify's own pull request previews make are not modelled; this recipe manages a branch the plan names."
59
+ ops:
60
+ branch:
61
+ kind: resource
62
+ title: Branch
63
+ summary: "An Amplify branch named by the plan (the git branch of the pull request, `${ctx.git.branch}`), created with CreateBranch and deleted on destroy. Its `stage`, `description` and auto-build setting are compared: a console edit is drift. Variables on it are `amplify.branch_variable` lines."
64
+ covers: [amplify-branch]
65
+ params:
66
+ app_id:
67
+ type: string
68
+ required: true
69
+ pattern: "^d[a-z0-9]+$"
70
+ description: The Amplify app's id.
71
+ example: d1demo
72
+ branch_name:
73
+ type: string
74
+ required: true
75
+ description: The branch's name, as the repository names it.
76
+ example: "${ctx.scope}"
77
+ stage:
78
+ type: string
79
+ enum: [PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST]
80
+ description: The branch's stage.
81
+ example: PULL_REQUEST
82
+ description:
83
+ type: string
84
+ description: The branch's description.
85
+ example: "Preview of ${ctx.scope}"
86
+ enable_auto_build:
87
+ type: boolean
88
+ description: Build automatically on every push (false lets CI start the build after the variables are written; AM7).
89
+ http:
90
+ read: { path: "/apps/{app_id}/branches/{branch_name}" }
91
+ create:
92
+ path: "/apps/{app_id}/branches"
93
+ body: { branchName: { param: branch_name } }
94
+ update: { method: POST }
95
+ item_path: /branch
96
+ id_path: /branchName
97
+ fields:
98
+ stage: { param: stage }
99
+ description: { param: description }
100
+ enableAutoBuild: { param: enable_auto_build }
101
+ sim:
102
+ id_from: branchName
103
+ live:
104
+ params: { app_id: SPONSON_LIVE_AMPLIFY_APP_ID }
105
+ branch_variable:
106
+ kind: list_item
107
+ title: Branch environment variable
108
+ summary: "One entry of a branch's `environmentVariables`, by read-modify-write of the whole map (UpdateBranch replaces the map it is sent); other variables are left alone, and the branch is locked while Sponson writes it. A branch that is not there yet reads as having no variables, so a plan that also creates the branch shows a create. Builds started before the write do not see it (AM7)."
109
+ covers: [amplify-branch]
110
+ params:
111
+ app_id:
112
+ type: string
113
+ required: true
114
+ pattern: "^d[a-z0-9]+$"
115
+ description: The Amplify app's id.
116
+ example: d1demo
117
+ branch_name:
118
+ type: string
119
+ required: true
120
+ description: The branch's name (a `{ from }` of the `amplify.branch` line orders the two).
121
+ example: "${ctx.scope}"
122
+ name:
123
+ type: string
124
+ required: true
125
+ description: The variable's name.
126
+ example: API_URL
127
+ value:
128
+ type: string
129
+ required: true
130
+ description: The variable's value.
131
+ example: "https://api-${ctx.scope}.example.app"
132
+ http:
133
+ parent: { path: "/apps/{app_id}/branches/{branch_name}", method: POST, send: collection, item_path: /branch, if_missing: empty }
134
+ list_path: /environmentVariables
135
+ shape: map
136
+ item: { param: name }
137
+ value: { param: value }
138
+ sim:
139
+ provider: aws
140
+ base_path: /aws/amplify
141
+ seed: { amplify: { d1demo: { branches: { pr-42: { environmentVariables: { NODE_ENV: production } } } } } }
142
+ present: /amplify/d1demo/branches/pr-42/environmentVariables/API_URL
143
+ drift:
144
+ changed: { amplify.d1demo.pr-42.API_URL: "https://somewhere-else.example" }
145
+ missing: { amplify.d1demo.pr-42.API_URL: delete }
146
+ live:
147
+ params: { app_id: SPONSON_LIVE_AMPLIFY_APP_ID, branch_name: SPONSON_LIVE_AMPLIFY_BRANCH }