@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
@@ -0,0 +1,109 @@
1
+ # yaml-language-server: $schema=../../../schema/recipe.schema.json
2
+ # Svix API recipes (Svix as the webhook sender). Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md
3
+ # "Adding a recipe".
4
+ provider: svix
5
+ title: Svix
6
+ category: webhooks
7
+ verified_on: "2026-10-11"
8
+ docs:
9
+ - title: Svix API reference (OpenAPI document)
10
+ url: https://api.svix.com/api/v1/openapi.json
11
+ - title: Svix API reference
12
+ url: https://api.svix.com/docs
13
+ - title: Entities overview (ids and uids)
14
+ url: https://docs.svix.com/overview
15
+ api:
16
+ base_url: https://api.us.svix.com
17
+ base_url_env: SVIX_API_URL
18
+ auth: { bearer_env: SVIX_AUTH_TOKEN }
19
+ detect:
20
+ deps: [svix]
21
+ env: ["SVIX_*"]
22
+ starter:
23
+ - op: endpoint
24
+ values: { uid: "sponson-${ctx.env}-${ctx.scope}" }
25
+ where:
26
+ app_id: "Svix dashboard → Applications: the application (customer) the previews receive as"
27
+ url: "the preview's webhook handler: its URL plus the handler's path (a `{ from }` reference cannot carry a path)"
28
+ assumptions:
29
+ - id: SV1
30
+ verified: true
31
+ text: "`POST /api/v1/app/{app_id}/endpoint` creates an endpoint from `url` (required), `uid`, `description`, `eventTypes`, `channels`, `disabled`, `metadata` and an optional `secret`, answering 201 with the endpoint (`id` `ep_…`, `uid`, `url`, …); requests carry `Authorization: Bearer <token>`."
32
+ source: https://api.svix.com/api/v1/openapi.json
33
+ - id: SV2
34
+ verified: true
35
+ text: "`GET`, `PATCH` (partial update) and `DELETE` (204) `/api/v1/app/{app_id}/endpoint/{endpoint_id}` take the endpoint's id or its uid, and `{app_id}` takes the application's id or uid."
36
+ source: https://api.svix.com/api/v1/openapi.json
37
+ - id: SV3
38
+ verified: true
39
+ text: "A uid is 1–256 characters of letters, digits, `-`, `_` and `.`, unique among the application's endpoints, so it names the endpoint for every later request and a create whose answer was lost is found by it."
40
+ source: https://api.svix.com/api/v1/openapi.json
41
+ - id: SV4
42
+ verified: true
43
+ text: "The endpoint's signing secret is generated when `secret` is null (recommended) and is readable at any time with `GET …/endpoint/{endpoint_id}/secret` (`{ key }`): it is not a once-only value, and this recipe does not output it (an endpoint answer does not carry it)."
44
+ source: https://api.svix.com/api/v1/openapi.json
45
+ - id: SV5
46
+ verified: true
47
+ text: "The API is served per region (`api.us.svix.com`, `api.eu.svix.com`, `api.ca.svix.com`, `api.au.svix.com`), and POST requests accept an `idempotency-key` header."
48
+ source: https://api.svix.com/api/v1/openapi.json
49
+ - id: SV6
50
+ verified: false
51
+ text: "A create with a uid that exists already answers 409 (the specification lists 409 for every operation without saying when), after which the endpoint is found by its uid and claimed only if an earlier intent of the same scope named it."
52
+ - id: SV7
53
+ verified: false
54
+ text: "`description` is answered as sent (default empty), `disabled` as a boolean and `eventTypes` as the list sent, so they compare without drift on every plan; accounts outside the US region set `base_url` in the provider block."
55
+ ops:
56
+ endpoint:
57
+ kind: resource
58
+ title: Application endpoint
59
+ summary: An endpoint of a Svix application delivering to an environment's URL, named by a uid such as `preview-pr-42`. Its URL, description, event type filter and disabled flag are compared for drift; its signing secret stays readable in Svix (SV4).
60
+ covers: [svix-endpoint]
61
+ params:
62
+ app_id:
63
+ type: string
64
+ required: true
65
+ description: The application's id (`app_…`) or uid.
66
+ example: acme-customer
67
+ uid:
68
+ type: string
69
+ required: true
70
+ pattern: "^[a-zA-Z0-9\\-_.]{1,256}$"
71
+ description: The endpoint's uid, unique in the application; its identity.
72
+ example: "sponson-${ctx.env}-${ctx.scope}"
73
+ url:
74
+ type: string
75
+ required: true
76
+ pattern: "^https?://\\S+$"
77
+ description: The URL messages are delivered to.
78
+ example: "https://${ctx.scope}.preview.example.com/api/webhooks"
79
+ description:
80
+ type: string
81
+ default: ""
82
+ description: A note shown in the Svix dashboard and the application portal.
83
+ event_types:
84
+ type: list
85
+ description: Event type names to deliver (all when left out); at least one when set.
86
+ disabled:
87
+ type: boolean
88
+ default: false
89
+ description: Whether deliveries are paused.
90
+ secret:
91
+ type: string
92
+ description: "A signing secret to use instead of a generated one (`whsec_…`); sent on create only. Use `{ secret: … }`."
93
+ http:
94
+ read: { path: "/api/v1/app/{app_id}/endpoint/{uid}" }
95
+ create:
96
+ path: "/api/v1/app/{app_id}/endpoint"
97
+ body: { uid: { param: uid }, secret: { param: secret } }
98
+ idempotency_key: true
99
+ update: { method: PATCH, path: "/api/v1/app/{app_id}/endpoint/{id}" }
100
+ delete: { path: "/api/v1/app/{app_id}/endpoint/{id}" }
101
+ fields:
102
+ url: { param: url }
103
+ description: { param: description }
104
+ disabled: { param: disabled }
105
+ eventTypes: { param: event_types }
106
+ sim:
107
+ id_from: uid
108
+ live:
109
+ params: { app_id: SPONSON_LIVE_SVIX_APP_ID }
@@ -0,0 +1,98 @@
1
+ # yaml-language-server: $schema=../../../schema/recipe.schema.json
2
+ # Turso Platform API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
3
+ provider: turso
4
+ title: Turso
5
+ category: databases
6
+ verified_on: "2026-10-11"
7
+ docs:
8
+ - title: Create database
9
+ url: https://docs.turso.tech/api-reference/databases/create
10
+ - title: Retrieve database
11
+ url: https://docs.turso.tech/api-reference/databases/retrieve
12
+ - title: Delete database
13
+ url: https://docs.turso.tech/api-reference/databases/delete
14
+ - title: Branching
15
+ url: https://docs.turso.tech/features/branching
16
+ api:
17
+ base_url: https://api.turso.tech/v1
18
+ base_url_env: TURSO_API_URL
19
+ auth: { bearer_env: TURSO_API_TOKEN }
20
+ detect:
21
+ deps: ["@libsql/client", "@tursodatabase/"]
22
+ env: ["TURSO_*"]
23
+ db_hosts: [.turso.io]
24
+ starter:
25
+ - op: database_branch
26
+ values: { name: "app-${ctx.scope}" }
27
+ where:
28
+ organization: "`turso org list`"
29
+ parent: "the database to branch from: `turso db list`"
30
+ assumptions:
31
+ - id: TU1
32
+ verified: true
33
+ text: "`POST /v1/organizations/{organizationSlug}/databases` with `name`, `group` and `seed: { type: database, name: <parent> }` creates a database copied from the parent, authenticated with a Platform API token as `Authorization: Bearer`."
34
+ source: https://docs.turso.tech/api-reference/databases/create
35
+ - id: TU2
36
+ verified: true
37
+ text: "The create answers `{ database: { DbId, Hostname, Name } }` (capitalised), and 409 when a database with that name exists already."
38
+ source: https://docs.turso.tech/api-reference/databases/create
39
+ - id: TU3
40
+ verified: true
41
+ text: "`GET /v1/organizations/{organizationSlug}/databases/{databaseName}` answers `{ database: { Name, DbId, Hostname, group, … } }`, and 404 when there is none."
42
+ source: https://docs.turso.tech/api-reference/databases/retrieve
43
+ - id: TU4
44
+ verified: true
45
+ text: "`DELETE` on the same path removes the database; 404 when it is gone."
46
+ source: https://docs.turso.tech/api-reference/databases/delete
47
+ - id: TU5
48
+ verified: true
49
+ text: Database names are lower-case letters, numbers and dashes, at most 64 characters, unique in the organization; the group must exist already.
50
+ source: https://docs.turso.tech/api-reference/databases/create
51
+ - id: TU6
52
+ verified: false
53
+ text: The database is usable as soon as the create answers (no readiness to poll for a branch of a database in the same group).
54
+ ops:
55
+ database_branch:
56
+ kind: resource
57
+ title: Database branch
58
+ summary: "A database copied from a parent database (a branch), named for the scope, such as `app-pr-42` from `app`. Its hostname is an output for the app's connection URL. Only its existence is compared for drift: changing `group` or `parent` later does not move or re-copy a database that exists."
59
+ covers: [turso-database]
60
+ params:
61
+ organization:
62
+ type: string
63
+ required: true
64
+ description: The organization (or user account) slug.
65
+ example: acme
66
+ name:
67
+ type: string
68
+ required: true
69
+ pattern: "^[a-z0-9-]{1,64}$"
70
+ description: The new database's name.
71
+ example: "app-${ctx.scope}"
72
+ parent:
73
+ type: string
74
+ required: true
75
+ description: The parent database to copy.
76
+ example: app
77
+ group:
78
+ type: string
79
+ default: default
80
+ description: The group the database is placed in; it must exist.
81
+ timestamp:
82
+ type: string
83
+ description: Copy the parent as it was at this ISO 8601 time (point-in-time recovery window only).
84
+ http:
85
+ read: { path: "/organizations/{organization}/databases/{name}" }
86
+ create:
87
+ path: "/organizations/{organization}/databases"
88
+ body:
89
+ name: { param: name }
90
+ group: { param: group }
91
+ seed: { type: database, name: { param: parent }, timestamp: { param: timestamp } }
92
+ item_path: /database
93
+ id_path: /Name
94
+ outputs: { hostname: /Hostname, db_id: /DbId }
95
+ sim:
96
+ id_from: name
97
+ live:
98
+ params: { organization: SPONSON_LIVE_TURSO_ORGANIZATION, parent: SPONSON_LIVE_TURSO_DATABASE }
@@ -0,0 +1,149 @@
1
+ # yaml-language-server: $schema=../../../schema/recipe.schema.json
2
+ # Unleash Admin API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
3
+ provider: unleash
4
+ title: Unleash
5
+ category: flags
6
+ verified_on: "2026-10-11"
7
+ docs:
8
+ - title: Admin API overview (authorization, base URL)
9
+ url: https://docs.getunleash.io/reference/api/unleash
10
+ - title: Add a strategy to a flag in an environment
11
+ url: https://docs.getunleash.io/reference/api/unleash/add-feature-strategy
12
+ - title: Get feature flag strategies
13
+ url: https://docs.getunleash.io/reference/api/unleash/get-feature-strategies
14
+ - title: Update a strategy (replace)
15
+ url: https://docs.getunleash.io/reference/api/unleash/update-feature-strategy
16
+ - title: Delete a strategy
17
+ url: https://docs.getunleash.io/reference/api/unleash/delete-feature-strategy
18
+ - title: API tokens and client keys
19
+ url: https://docs.getunleash.io/reference/api-tokens-and-client-keys
20
+ # Every Unleash instance has its own URL (self-hosted, or https://<region>.app.unleash-hosted.com/<instance>):
21
+ # everything before `/api`.
22
+ base_url_example: https://unleash.example.com
23
+ api:
24
+ base_url_env: UNLEASH_API_URL
25
+ auth: { header: Authorization, value_env: UNLEASH_AUTH_TOKEN }
26
+ detect:
27
+ deps: [unleash-client, unleash-proxy-client, "@unleash/"]
28
+ env: ["UNLEASH_*"]
29
+ starter:
30
+ - op: flag_strategy
31
+ values: { title: "preview ${ctx.scope}", values: ["${ctx.scope}"] }
32
+ where:
33
+ base_url: "your Unleash instance's URL (`https://<instance>`)"
34
+ assumptions:
35
+ - id: UN1
36
+ verified: true
37
+ text: "Every request carries the token as it is in `Authorization` (`Authorization: <token>`, no `Bearer`); a personal access token or service account token (admin tokens are deprecated) reaches the Admin API. The spec also lists a Bearer scheme, but the server does not strip a `Bearer ` prefix, so the bare form is used."
38
+ source: https://docs.getunleash.io/reference/api/unleash
39
+ - id: UN2
40
+ verified: true
41
+ text: "`POST /api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/strategies` with `name`, `title`, `disabled`, `constraints` and `parameters` adds a strategy and answers it bare, with its server-assigned `id` (a UUID)."
42
+ source: https://docs.getunleash.io/reference/api/unleash/add-feature-strategy
43
+ - id: UN3
44
+ verified: true
45
+ text: "`GET` on the same path answers a bare array of the environment's strategies (the source returns `FeatureStrategySchema[]`; the docs page's schema shows a single strategy, which is wrong)."
46
+ source: https://github.com/Unleash/unleash/blob/main/src/lib/features/feature-toggle/feature-toggle-controller.ts
47
+ - id: UN4
48
+ verified: true
49
+ text: "`PUT .../strategies/{strategyId}` replaces a strategy's configuration (so it sends `name`, `title` and every compared field); `DELETE` on the same path removes it."
50
+ source: https://docs.getunleash.io/reference/api/unleash/update-feature-strategy
51
+ - id: UN5
52
+ verified: true
53
+ text: "A constraint is `{ contextName, operator, values, caseInsensitive, inverted }` (`caseInsensitive` and `inverted` default to false, and are written explicitly so the comparison does not depend on defaults); `parameters` is a map of strings (`rollout: \"100\"`)."
54
+ source: https://docs.getunleash.io/reference/api/unleash/add-feature-strategy
55
+ - id: UN6
56
+ verified: false
57
+ text: "`title` is optional and not unique on the server: the strategy is identified by its title in the environment, and two strategies with that title are PARAM_INVALID rather than a guess."
58
+ source: https://docs.getunleash.io/reference/api/unleash/add-feature-strategy
59
+ - id: UN7
60
+ verified: false
61
+ text: "A strategy is read back with `constraints` and `parameters` exactly as written (no extra keys such as `value: \"\"`); otherwise every plan shows it as changed."
62
+ - id: UN8
63
+ verified: true
64
+ text: "Deleting a strategy that is gone already answers 200 (nothing to do). Deleting the last strategy of an environment turns the flag off in that environment (the service calls `disableEnvironmentIfNoStrategies`). Adding a strategy does not turn the environment on."
65
+ source: https://github.com/Unleash/unleash/blob/main/src/lib/features/feature-toggle/feature-toggle-service.ts
66
+ - id: UN9
67
+ verified: true
68
+ text: "With change requests enabled for the environment, these writes are refused unless the caller may bypass them; the refusal fails the apply."
69
+ source: https://github.com/Unleash/unleash/blob/main/src/lib/features/feature-toggle/feature-toggle-service.ts
70
+ ops:
71
+ flag_strategy:
72
+ kind: resource
73
+ title: Flag strategy with constraints
74
+ summary: "A `flexibleRollout` strategy on a flag in one environment, constrained to the preview (such as `preview IN [pr-42]`). Located by its title in the environment's strategies; a console edit of its constraints, rollout parameters or `disabled` is drift. Destroy deletes it; if it was the environment's last strategy, Unleash turns the flag off there (UN8). The environment itself must be enabled for the flag to be served."
75
+ covers: [unleash-strategy]
76
+ params:
77
+ project:
78
+ type: string
79
+ default: default
80
+ description: The project id.
81
+ feature:
82
+ type: string
83
+ required: true
84
+ description: The flag's name; also the rollout's `groupId`.
85
+ example: new-checkout
86
+ environment:
87
+ type: string
88
+ required: true
89
+ description: The environment the strategy is added in.
90
+ example: development
91
+ title:
92
+ type: string
93
+ required: true
94
+ description: The strategy's title, unique among the environment's strategies; it identifies the strategy.
95
+ example: "preview ${ctx.scope}"
96
+ context_name:
97
+ type: string
98
+ required: true
99
+ description: The context field the constraint tests (a custom context field such as `preview`, or `environment`, `userId`, …).
100
+ example: preview
101
+ operator:
102
+ type: string
103
+ default: IN
104
+ enum: [IN, NOT_IN, STR_ENDS_WITH, STR_STARTS_WITH, STR_CONTAINS]
105
+ description: The constraint's operator.
106
+ values:
107
+ type: list
108
+ required: true
109
+ description: The values the context field is compared with.
110
+ example: ["${ctx.scope}"]
111
+ rollout:
112
+ type: string
113
+ default: "100"
114
+ pattern: "^(100|[1-9]?[0-9])$"
115
+ description: The share of matching users the strategy enables, as a string (0–100).
116
+ stickiness:
117
+ type: string
118
+ default: default
119
+ description: The rollout's stickiness (`default`, `userId`, `sessionId`, `random`, or a context field).
120
+ disabled:
121
+ type: boolean
122
+ default: false
123
+ description: Keep the strategy but switch it off.
124
+ http:
125
+ find:
126
+ path: "/api/admin/projects/{project}/features/{feature}/environments/{environment}/strategies"
127
+ match: { title: { param: title } }
128
+ create:
129
+ path: "/api/admin/projects/{project}/features/{feature}/environments/{environment}/strategies"
130
+ body: { name: flexibleRollout }
131
+ update:
132
+ method: PUT
133
+ path: "/api/admin/projects/{project}/features/{feature}/environments/{environment}/strategies/{id}"
134
+ body: { name: flexibleRollout }
135
+ delete: { path: "/api/admin/projects/{project}/features/{feature}/environments/{environment}/strategies/{id}" }
136
+ fields:
137
+ disabled: { param: disabled }
138
+ constraints:
139
+ - contextName: { param: context_name }
140
+ operator: { param: operator }
141
+ values: { param: values }
142
+ caseInsensitive: false
143
+ inverted: false
144
+ parameters:
145
+ rollout: { param: rollout }
146
+ stickiness: { param: stickiness }
147
+ groupId: { param: feature }
148
+ live:
149
+ params: { project: SPONSON_LIVE_UNLEASH_PROJECT, feature: SPONSON_LIVE_UNLEASH_FEATURE, environment: SPONSON_LIVE_UNLEASH_ENVIRONMENT }
@@ -0,0 +1,130 @@
1
+ # yaml-language-server: $schema=../../../schema/recipe.schema.json
2
+ # Upstash Developer API recipes (Redis). QStash has its own API and credential: recipes/qstash.yaml.
3
+ # Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
4
+ provider: upstash
5
+ title: Upstash Redis
6
+ category: queues
7
+ verified_on: "2026-10-11"
8
+ docs:
9
+ - title: Developer API authentication
10
+ url: https://upstash.com/docs/devops/developer-api/authentication
11
+ - title: Developer API introduction (supported accounts)
12
+ url: https://upstash.com/docs/devops/developer-api/introduction
13
+ - title: Create a Redis database (global)
14
+ url: https://upstash.com/docs/devops/developer-api/redis/create_database_global
15
+ - title: List Redis databases
16
+ url: https://upstash.com/docs/devops/developer-api/redis/list_databases
17
+ - title: Get a Redis database
18
+ url: https://upstash.com/docs/devops/developer-api/redis/get_database
19
+ - title: Delete a Redis database
20
+ url: https://upstash.com/docs/devops/developer-api/redis/delete_database
21
+ - title: Upstash CLI (UPSTASH_EMAIL, UPSTASH_API_KEY)
22
+ url: https://upstash.com/docs/agent-resources/cli
23
+ - title: Terraform upstash_redis_database (exported credentials)
24
+ url: https://upstash.com/docs/devops/terraform/resources/upstash_redis_database
25
+ api:
26
+ base_url: https://api.upstash.com/v2
27
+ base_url_env: UPSTASH_API_URL
28
+ auth: { basic: { user_env: UPSTASH_EMAIL, password_env: UPSTASH_API_KEY } }
29
+ detect:
30
+ deps: ["@upstash/redis"]
31
+ env: ["UPSTASH_REDIS_*"]
32
+ starter:
33
+ - op: redis_database
34
+ values: { name: "app-${ctx.scope}" }
35
+ assumptions:
36
+ - id: UR1
37
+ verified: true
38
+ text: "The Developer API authenticates with HTTP Basic, the account's email as user and an API key as password; the Upstash CLI reads them from `UPSTASH_EMAIL` and `UPSTASH_API_KEY`. Accounts created through Vercel or Fly cannot use it."
39
+ source: https://upstash.com/docs/devops/developer-api/authentication
40
+ - id: UR2
41
+ verified: true
42
+ text: "`POST /v2/redis/database` with `{ database_name, platform, primary_region, read_regions?, plan?, tls?, eviction? }` creates a global database and answers it bare, with `database_id`, `database_name`, `endpoint`, `port` and `state`."
43
+ source: https://upstash.com/docs/devops/developer-api/redis/create_database_global
44
+ - id: UR3
45
+ verified: true
46
+ text: "`GET /v2/redis/databases` answers every database of the account as a bare array (no paging)."
47
+ source: https://upstash.com/docs/devops/developer-api/redis/list_databases
48
+ - id: UR4
49
+ verified: false
50
+ text: "Database names are unique in the account, so `database_name` identifies one; a create whose answer was lost is found by it before another is created. (Not documented: a second database with the same name makes `find.match` ambiguous, which is refused with PARAM_INVALID rather than guessed.)"
51
+ - id: UR5
52
+ verified: true
53
+ text: "`GET /v2/redis/database/{id}` answers the database, with its credentials unless `?credentials=hide` is sent."
54
+ source: https://upstash.com/docs/devops/developer-api/redis/get_database
55
+ - id: UR6
56
+ verified: false
57
+ text: "The credentials are the fields `password` and `rest_token` (the documented schema omits them; the Terraform resource and the CLI expose them), so they are readable on every run, not only from the create: ordinary sensitive outputs, not once-only ones."
58
+ source: https://upstash.com/docs/devops/terraform/resources/upstash_redis_database
59
+ - id: UR7
60
+ verified: true
61
+ text: "`DELETE /v2/redis/database/{id}` deletes the database and answers 200 `\"OK\"`."
62
+ source: https://upstash.com/docs/devops/developer-api/redis/delete_database
63
+ - id: UR8
64
+ verified: false
65
+ text: "A database that is gone answers 404 on GET and DELETE (only 200 is documented)."
66
+ - id: UR9
67
+ verified: false
68
+ text: "The database is usable when the create answers (`state: active` in the documented example); nothing waits for it."
69
+ source: https://upstash.com/docs/devops/developer-api/redis/create_database_global
70
+ - id: UR10
71
+ verified: false
72
+ text: "`endpoint` is the database's host name (`<name>.upstash.io`); the documented example shows only its first label, so check the output before building a URL from it."
73
+ source: https://upstash.com/docs/devops/developer-api/redis/create_database_global
74
+ ops:
75
+ redis_database:
76
+ kind: resource
77
+ title: Redis database
78
+ summary: "A global Redis database per scope, such as `app-pr-42`, with its endpoint, port, password and REST token as outputs (the last two sensitive). Located by name; only its existence is compared for drift (region, plan and TLS are set on create and not compared); destroy deletes it and its data."
79
+ covers: [upstash-redis-database]
80
+ params:
81
+ name:
82
+ type: string
83
+ required: true
84
+ description: The database's name.
85
+ example: "app-${ctx.scope}"
86
+ platform:
87
+ type: string
88
+ default: aws
89
+ enum: [aws, gcp]
90
+ description: The cloud it runs on.
91
+ primary_region:
92
+ type: string
93
+ required: true
94
+ description: The primary region, such as `us-east-1` or `eu-west-1`.
95
+ example: us-east-1
96
+ read_regions:
97
+ type: list
98
+ description: Read replica regions.
99
+ plan:
100
+ type: string
101
+ description: The plan (`free`, `payg`, `fixed_…`); the account's default when left out.
102
+ tls:
103
+ type: boolean
104
+ default: true
105
+ description: Whether TLS is enabled.
106
+ eviction:
107
+ type: boolean
108
+ description: Whether keys are evicted when the database is full.
109
+ http:
110
+ find:
111
+ path: /redis/databases
112
+ match: { database_name: { param: name } }
113
+ read: { path: "/redis/database/{id}" }
114
+ create:
115
+ path: /redis/database
116
+ body:
117
+ platform: { param: platform }
118
+ primary_region: { param: primary_region }
119
+ read_regions: { param: read_regions }
120
+ plan: { param: plan }
121
+ tls: { param: tls }
122
+ eviction: { param: eviction }
123
+ id_path: /database_id
124
+ outputs:
125
+ endpoint: /endpoint
126
+ port: /port
127
+ password: { path: /password, sensitive: true }
128
+ rest_token: { path: /rest_token, sensitive: true }
129
+ live:
130
+ params: { primary_region: SPONSON_LIVE_UPSTASH_REGION }
@@ -0,0 +1,116 @@
1
+ # yaml-language-server: $schema=../../../schema/recipe.schema.json
2
+ # Vercel REST API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
3
+ # Environment variables and deployments have the first-class `vercel` adapter (vercel.env, vercel.deploy).
4
+ provider: vercel
5
+ title: Vercel
6
+ category: dns
7
+ verified_on: "2026-10-11"
8
+ docs:
9
+ - title: Add a domain to a project
10
+ url: https://vercel.com/docs/rest-api/projects/add-a-domain-to-a-project
11
+ - title: Get a project domain
12
+ url: https://vercel.com/docs/rest-api/projects/get-a-project-domain
13
+ - title: Update a project domain
14
+ url: https://vercel.com/docs/rest-api/projects/update-a-project-domain
15
+ - title: Remove a domain from a project
16
+ url: https://vercel.com/docs/rest-api/projects/remove-a-domain-from-a-project
17
+ - title: Errors
18
+ url: https://vercel.com/docs/rest-api/errors
19
+ - title: CLI global options (VERCEL_TOKEN)
20
+ url: https://vercel.com/docs/cli/global-options
21
+ - title: Working with domains (verification)
22
+ url: https://vercel.com/docs/domains/working-with-domains
23
+ api:
24
+ base_url: https://api.vercel.com
25
+ base_url_env: VERCEL_API_URL
26
+ auth: { bearer_env: VERCEL_TOKEN }
27
+ assumptions:
28
+ - id: VD1
29
+ verified: true
30
+ text: "Requests authenticate as `Authorization: Bearer <token>`; the Vercel CLI reads the token from `VERCEL_TOKEN` (the built-in `vercel` adapter uses the same variable)."
31
+ source: https://vercel.com/docs/cli/global-options
32
+ - id: VD2
33
+ verified: true
34
+ text: "`POST /v10/projects/{idOrName}/domains?teamId=` with `{ name, gitBranch, redirect, redirectStatusCode }` adds the domain to the project and answers it bare: `{ name, apexName, projectId, verified, gitBranch, redirect, redirectStatusCode, verification[] }`."
35
+ source: https://vercel.com/docs/rest-api/projects/add-a-domain-to-a-project
36
+ - id: VD3
37
+ verified: true
38
+ text: "`GET /v9/projects/{idOrName}/domains/{domain}?teamId=` answers the same shape; the domain's name identifies it within the project, so the read path names it and a create whose answer was lost is found by it."
39
+ source: https://vercel.com/docs/rest-api/projects/get-a-project-domain
40
+ - id: VD4
41
+ verified: false
42
+ text: "A domain that is not on the project answers 404 on GET and DELETE (documented with no description)."
43
+ source: https://vercel.com/docs/rest-api/projects/get-a-project-domain
44
+ - id: VD5
45
+ verified: true
46
+ text: "`PATCH /v9/projects/{idOrName}/domains/{domain}` changes `gitBranch`, `redirect` and `redirectStatusCode`; `DELETE` on the same path removes the domain from the project (200, `{}`)."
47
+ source: https://vercel.com/docs/rest-api/projects/update-a-project-domain
48
+ - id: VD6
49
+ verified: true
50
+ text: "Adding a domain that is already on a project of the account answers 409 (and, for the same project, the description says 400): someone else's domain is never taken over by name, and the conflict surfaces as an error."
51
+ source: https://vercel.com/docs/rest-api/projects/add-a-domain-to-a-project
52
+ - id: VD7
53
+ verified: true
54
+ text: "`gitBranch` and `redirect` cannot be set together, and the production branch cannot be a `gitBranch` (400)."
55
+ source: https://vercel.com/docs/rest-api/projects/add-a-domain-to-a-project
56
+ - id: VD8
57
+ verified: true
58
+ text: "A domain the account does not own answers `verified: false` with a `verification` challenge (a TXT record) that must be completed before it serves traffic; a domain bought through Vercel needs none."
59
+ source: https://vercel.com/docs/domains/working-with-domains
60
+ - id: VD9
61
+ verified: false
62
+ text: "A free `<name>.vercel.app` domain that no other project uses is verified on the spot (`verified: true`)."
63
+ - id: VD10
64
+ verified: false
65
+ text: "Every account has a team id (personal accounts are Hobby teams), so `teamId` can always be sent; the recipe requires it."
66
+ ops:
67
+ project_domain:
68
+ kind: resource
69
+ title: Branch-bound project domain
70
+ summary: "A domain on a Vercel project that serves one git branch's latest preview, such as `pr-42.preview.example.com` for `feat/x`: a stable preview hostname. Located by name; a console edit of its branch or redirect is drift; destroy removes it from the project. Its `verified` output says whether DNS verification is still needed (VD8)."
71
+ covers: [vercel-domain]
72
+ params:
73
+ project:
74
+ type: string
75
+ required: true
76
+ description: The project's id or name.
77
+ example: prj_12HKQaOmR5t5Uy6vdcQsNIiZgHGB
78
+ team_id:
79
+ type: string
80
+ required: true
81
+ pattern: "^team_[A-Za-z0-9]+$"
82
+ description: The team's id (`team_…`, under Settings → General).
83
+ example: team_1a2b3c4d5e6f7g8h9i0j1k2l
84
+ name:
85
+ type: string
86
+ required: true
87
+ pattern: "^[a-z0-9*.-]+$"
88
+ description: The domain, lower-case.
89
+ example: "${ctx.scope}.preview.example.com"
90
+ git_branch:
91
+ type: string
92
+ description: The git branch whose latest deployment the domain serves.
93
+ example: "${ctx.git.branch}"
94
+ redirect:
95
+ type: string
96
+ description: Redirect to this domain instead of serving a branch (not with `git_branch`).
97
+ redirect_status_code:
98
+ type: integer
99
+ enum: [301, 302, 307, 308]
100
+ description: The redirect's status code.
101
+ http:
102
+ read: { path: "/v9/projects/{project}/domains/{name}?teamId={team_id}" }
103
+ create:
104
+ path: "/v10/projects/{project}/domains?teamId={team_id}"
105
+ body: { name: { param: name } }
106
+ update: { method: PATCH }
107
+ id_path: /name
108
+ fields:
109
+ gitBranch: { param: git_branch }
110
+ redirect: { param: redirect }
111
+ redirectStatusCode: { param: redirect_status_code }
112
+ outputs: { verified: /verified, apex_name: /apexName }
113
+ sim:
114
+ id_from: name
115
+ live:
116
+ params: { project: SPONSON_LIVE_VERCEL_PROJECT, team_id: SPONSON_LIVE_VERCEL_TEAM_ID, name: SPONSON_LIVE_VERCEL_DOMAIN }