@distilled.cloud/vercel 0.0.0 → 1.0.0-rc.4

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 (230) hide show
  1. package/lib/credentials.d.ts +21 -0
  2. package/lib/credentials.d.ts.map +1 -0
  3. package/lib/credentials.js +40 -0
  4. package/lib/credentials.js.map +1 -0
  5. package/lib/errors.d.ts +80 -0
  6. package/lib/errors.d.ts.map +1 -0
  7. package/lib/errors.js +50 -0
  8. package/lib/errors.js.map +1 -0
  9. package/lib/index.d.ts +15 -0
  10. package/lib/index.d.ts.map +1 -0
  11. package/lib/index.js +15 -0
  12. package/lib/index.js.map +1 -0
  13. package/lib/protocol.d.ts +18 -0
  14. package/lib/protocol.d.ts.map +1 -0
  15. package/lib/protocol.js +69 -0
  16. package/lib/protocol.js.map +1 -0
  17. package/lib/retry.d.ts +54 -0
  18. package/lib/retry.d.ts.map +1 -0
  19. package/lib/retry.js +47 -0
  20. package/lib/retry.js.map +1 -0
  21. package/lib/services/access_groups.d.ts +459 -0
  22. package/lib/services/access_groups.d.ts.map +1 -0
  23. package/lib/services/access_groups.js +453 -0
  24. package/lib/services/access_groups.js.map +1 -0
  25. package/lib/services/ai_gateway.d.ts +124 -0
  26. package/lib/services/ai_gateway.d.ts.map +1 -0
  27. package/lib/services/ai_gateway.js +126 -0
  28. package/lib/services/ai_gateway.js.map +1 -0
  29. package/lib/services/aliases.d.ts +591 -0
  30. package/lib/services/aliases.d.ts.map +1 -0
  31. package/lib/services/aliases.js +508 -0
  32. package/lib/services/aliases.js.map +1 -0
  33. package/lib/services/artifacts.d.ts +228 -0
  34. package/lib/services/artifacts.d.ts.map +1 -0
  35. package/lib/services/artifacts.js +216 -0
  36. package/lib/services/artifacts.js.map +1 -0
  37. package/lib/services/authentication.d.ts +373 -0
  38. package/lib/services/authentication.d.ts.map +1 -0
  39. package/lib/services/authentication.js +310 -0
  40. package/lib/services/authentication.js.map +1 -0
  41. package/lib/services/billing.d.ts +792 -0
  42. package/lib/services/billing.d.ts.map +1 -0
  43. package/lib/services/billing.js +616 -0
  44. package/lib/services/billing.js.map +1 -0
  45. package/lib/services/bulk_redirects.d.ts +308 -0
  46. package/lib/services/bulk_redirects.d.ts.map +1 -0
  47. package/lib/services/bulk_redirects.js +306 -0
  48. package/lib/services/bulk_redirects.js.map +1 -0
  49. package/lib/services/certs.d.ts +171 -0
  50. package/lib/services/certs.d.ts.map +1 -0
  51. package/lib/services/certs.js +165 -0
  52. package/lib/services/certs.js.map +1 -0
  53. package/lib/services/checks_v2.d.ts +1162 -0
  54. package/lib/services/checks_v2.d.ts.map +1 -0
  55. package/lib/services/checks_v2.js +1252 -0
  56. package/lib/services/checks_v2.js.map +1 -0
  57. package/lib/services/connect.d.ts +1034 -0
  58. package/lib/services/connect.d.ts.map +1 -0
  59. package/lib/services/connect.js +993 -0
  60. package/lib/services/connect.js.map +1 -0
  61. package/lib/services/deployments.d.ts +9111 -0
  62. package/lib/services/deployments.d.ts.map +1 -0
  63. package/lib/services/deployments.js +8664 -0
  64. package/lib/services/deployments.js.map +1 -0
  65. package/lib/services/dns.d.ts +279 -0
  66. package/lib/services/dns.d.ts.map +1 -0
  67. package/lib/services/dns.js +282 -0
  68. package/lib/services/dns.js.map +1 -0
  69. package/lib/services/domains.d.ts +539 -0
  70. package/lib/services/domains.d.ts.map +1 -0
  71. package/lib/services/domains.js +464 -0
  72. package/lib/services/domains.js.map +1 -0
  73. package/lib/services/domains_registrar.d.ts +798 -0
  74. package/lib/services/domains_registrar.d.ts.map +1 -0
  75. package/lib/services/domains_registrar.js +968 -0
  76. package/lib/services/domains_registrar.js.map +1 -0
  77. package/lib/services/drains.d.ts +2263 -0
  78. package/lib/services/drains.d.ts.map +1 -0
  79. package/lib/services/drains.js +2406 -0
  80. package/lib/services/drains.js.map +1 -0
  81. package/lib/services/edge_cache.d.ts +125 -0
  82. package/lib/services/edge_cache.d.ts.map +1 -0
  83. package/lib/services/edge_cache.js +140 -0
  84. package/lib/services/edge_cache.js.map +1 -0
  85. package/lib/services/environment.d.ts +1020 -0
  86. package/lib/services/environment.d.ts.map +1 -0
  87. package/lib/services/environment.js +842 -0
  88. package/lib/services/environment.js.map +1 -0
  89. package/lib/services/feature_flags.d.ts +3109 -0
  90. package/lib/services/feature_flags.d.ts.map +1 -0
  91. package/lib/services/feature_flags.js +3074 -0
  92. package/lib/services/feature_flags.js.map +1 -0
  93. package/lib/services/global_config.d.ts +618 -0
  94. package/lib/services/global_config.d.ts.map +1 -0
  95. package/lib/services/global_config.js +716 -0
  96. package/lib/services/global_config.js.map +1 -0
  97. package/lib/services/index.d.ts +39 -0
  98. package/lib/services/index.d.ts.map +1 -0
  99. package/lib/services/index.js +40 -0
  100. package/lib/services/index.js.map +1 -0
  101. package/lib/services/integrations.d.ts +2987 -0
  102. package/lib/services/integrations.d.ts.map +1 -0
  103. package/lib/services/integrations.js +2903 -0
  104. package/lib/services/integrations.js.map +1 -0
  105. package/lib/services/log_drains.d.ts +848 -0
  106. package/lib/services/log_drains.d.ts.map +1 -0
  107. package/lib/services/log_drains.js +866 -0
  108. package/lib/services/log_drains.js.map +1 -0
  109. package/lib/services/logs.d.ts +40 -0
  110. package/lib/services/logs.d.ts.map +1 -0
  111. package/lib/services/logs.js +43 -0
  112. package/lib/services/logs.js.map +1 -0
  113. package/lib/services/marketplace.d.ts +991 -0
  114. package/lib/services/marketplace.d.ts.map +1 -0
  115. package/lib/services/marketplace.js +1044 -0
  116. package/lib/services/marketplace.js.map +1 -0
  117. package/lib/services/microfrontends.d.ts +3210 -0
  118. package/lib/services/microfrontends.d.ts.map +1 -0
  119. package/lib/services/microfrontends.js +3300 -0
  120. package/lib/services/microfrontends.js.map +1 -0
  121. package/lib/services/networking.d.ts +239 -0
  122. package/lib/services/networking.d.ts.map +1 -0
  123. package/lib/services/networking.js +224 -0
  124. package/lib/services/networking.js.map +1 -0
  125. package/lib/services/observability.d.ts +168 -0
  126. package/lib/services/observability.d.ts.map +1 -0
  127. package/lib/services/observability.js +191 -0
  128. package/lib/services/observability.js.map +1 -0
  129. package/lib/services/project_members.d.ts +142 -0
  130. package/lib/services/project_members.d.ts.map +1 -0
  131. package/lib/services/project_members.js +139 -0
  132. package/lib/services/project_members.js.map +1 -0
  133. package/lib/services/project_routes.d.ts +1990 -0
  134. package/lib/services/project_routes.d.ts.map +1 -0
  135. package/lib/services/project_routes.js +2026 -0
  136. package/lib/services/project_routes.js.map +1 -0
  137. package/lib/services/projects.d.ts +23449 -0
  138. package/lib/services/projects.d.ts.map +1 -0
  139. package/lib/services/projects.js +23570 -0
  140. package/lib/services/projects.js.map +1 -0
  141. package/lib/services/rolling_release.d.ts +764 -0
  142. package/lib/services/rolling_release.d.ts.map +1 -0
  143. package/lib/services/rolling_release.js +630 -0
  144. package/lib/services/rolling_release.js.map +1 -0
  145. package/lib/services/sandboxes.d.ts +2183 -0
  146. package/lib/services/sandboxes.d.ts.map +1 -0
  147. package/lib/services/sandboxes.js +1756 -0
  148. package/lib/services/sandboxes.js.map +1 -0
  149. package/lib/services/security.d.ts +3932 -0
  150. package/lib/services/security.d.ts.map +1 -0
  151. package/lib/services/security.js +4411 -0
  152. package/lib/services/security.js.map +1 -0
  153. package/lib/services/storage.d.ts +251 -0
  154. package/lib/services/storage.d.ts.map +1 -0
  155. package/lib/services/storage.js +270 -0
  156. package/lib/services/storage.js.map +1 -0
  157. package/lib/services/teams.d.ts +1577 -0
  158. package/lib/services/teams.d.ts.map +1 -0
  159. package/lib/services/teams.js +1359 -0
  160. package/lib/services/teams.js.map +1 -0
  161. package/lib/services/user.d.ts +7972 -0
  162. package/lib/services/user.d.ts.map +1 -0
  163. package/lib/services/user.js +7093 -0
  164. package/lib/services/user.js.map +1 -0
  165. package/lib/services/vcr.d.ts +793 -0
  166. package/lib/services/vcr.d.ts.map +1 -0
  167. package/lib/services/vcr.js +882 -0
  168. package/lib/services/vcr.js.map +1 -0
  169. package/lib/services/web_analytics.d.ts +694 -0
  170. package/lib/services/web_analytics.d.ts.map +1 -0
  171. package/lib/services/web_analytics.js +695 -0
  172. package/lib/services/web_analytics.js.map +1 -0
  173. package/lib/services/webhooks.d.ts +207 -0
  174. package/lib/services/webhooks.d.ts.map +1 -0
  175. package/lib/services/webhooks.js +171 -0
  176. package/lib/services/webhooks.js.map +1 -0
  177. package/lib/traits.d.ts +10 -0
  178. package/lib/traits.d.ts.map +1 -0
  179. package/lib/traits.js +11 -0
  180. package/lib/traits.js.map +1 -0
  181. package/package.json +77 -7
  182. package/src/credentials.ts +70 -0
  183. package/src/errors.ts +93 -0
  184. package/src/index.ts +18 -0
  185. package/src/protocol.ts +98 -0
  186. package/src/retry.ts +78 -0
  187. package/src/services/access_groups.ts +1165 -0
  188. package/src/services/ai_gateway.ts +272 -0
  189. package/src/services/aliases.ts +1323 -0
  190. package/src/services/artifacts.ts +542 -0
  191. package/src/services/authentication.ts +829 -0
  192. package/src/services/billing.ts +1776 -0
  193. package/src/services/bulk_redirects.ts +748 -0
  194. package/src/services/certs.ts +377 -0
  195. package/src/services/checks_v2.ts +3136 -0
  196. package/src/services/connect.ts +2607 -0
  197. package/src/services/deployments.ts +23682 -0
  198. package/src/services/dns.ts +718 -0
  199. package/src/services/domains.ts +1209 -0
  200. package/src/services/domains_registrar.ts +2290 -0
  201. package/src/services/drains.ts +5989 -0
  202. package/src/services/edge_cache.ts +303 -0
  203. package/src/services/environment.ts +2388 -0
  204. package/src/services/feature_flags.ts +8302 -0
  205. package/src/services/global_config.ts +1668 -0
  206. package/src/services/index.ts +39 -0
  207. package/src/services/integrations.ts +8846 -0
  208. package/src/services/log_drains.ts +2413 -0
  209. package/src/services/logs.ts +78 -0
  210. package/src/services/marketplace.ts +2626 -0
  211. package/src/services/microfrontends.ts +9650 -0
  212. package/src/services/networking.ts +530 -0
  213. package/src/services/observability.ts +436 -0
  214. package/src/services/project_members.ts +328 -0
  215. package/src/services/project_routes.ts +5259 -0
  216. package/src/services/projects.ts +67377 -0
  217. package/src/services/rolling_release.ts +1869 -0
  218. package/src/services/sandboxes.ts +5259 -0
  219. package/src/services/security.ts +12408 -0
  220. package/src/services/storage.ts +849 -0
  221. package/src/services/teams.ts +3995 -0
  222. package/src/services/user.ts +21687 -0
  223. package/src/services/vcr.ts +2165 -0
  224. package/src/services/web_analytics.ts +1570 -0
  225. package/src/services/webhooks.ts +1073 -0
  226. package/src/traits.ts +44 -0
  227. package/README.md +0 -15
  228. package/bun.lock +0 -26
  229. package/index.ts +0 -1
  230. package/tsconfig.json +0 -29
package/package.json CHANGED
@@ -1,15 +1,85 @@
1
1
  {
2
2
  "name": "@distilled.cloud/vercel",
3
- "version": "0.0.0",
4
- "module": "index.ts",
3
+ "version": "1.0.0-rc.4",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/alchemy-run/distilled",
7
+ "directory": "packages/vercel"
8
+ },
9
+ "license": "Apache-2.0",
5
10
  "type": "module",
11
+ "sideEffects": false,
12
+ "module": "src/index.ts",
13
+ "files": [
14
+ "lib",
15
+ "src"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "types": "./lib/index.d.ts",
20
+ "bun": "./src/index.ts",
21
+ "worker": "./src/index.ts",
22
+ "default": "./lib/index.js"
23
+ },
24
+ "./Credentials": {
25
+ "types": "./lib/credentials.d.ts",
26
+ "bun": "./src/credentials.ts",
27
+ "worker": "./src/credentials.ts",
28
+ "default": "./lib/credentials.js"
29
+ },
30
+ "./Errors": {
31
+ "types": "./lib/errors.d.ts",
32
+ "bun": "./src/errors.ts",
33
+ "worker": "./src/errors.ts",
34
+ "default": "./lib/errors.js"
35
+ },
36
+ "./Protocol": {
37
+ "types": "./lib/protocol.d.ts",
38
+ "bun": "./src/protocol.ts",
39
+ "worker": "./src/protocol.ts",
40
+ "default": "./lib/protocol.js"
41
+ },
42
+ "./Retry": {
43
+ "types": "./lib/retry.d.ts",
44
+ "bun": "./src/retry.ts",
45
+ "worker": "./src/retry.ts",
46
+ "default": "./lib/retry.js"
47
+ },
48
+ "./Traits": {
49
+ "types": "./lib/traits.d.ts",
50
+ "bun": "./src/traits.ts",
51
+ "worker": "./src/traits.ts",
52
+ "default": "./lib/traits.js"
53
+ },
54
+ "./Services": {
55
+ "types": "./lib/services/index.d.ts",
56
+ "bun": "./src/services/index.ts",
57
+ "worker": "./src/services/index.ts",
58
+ "default": "./lib/services/index.js"
59
+ },
60
+ "./*": {
61
+ "types": "./lib/services/*.d.ts",
62
+ "bun": "./src/services/*.ts",
63
+ "worker": "./src/services/*.ts",
64
+ "default": "./lib/services/*.js"
65
+ }
66
+ },
67
+ "scripts": {
68
+ "build": "tsc -b",
69
+ "convert": "bun scripts/convert.ts",
70
+ "generate": "bun scripts/generate.ts",
71
+ "typecheck": "tsc -p tsconfig.json",
72
+ "spec:download": "bun scripts/download-spec.ts"
73
+ },
74
+ "dependencies": {
75
+ "@distilled.cloud/core": "1.0.0-rc.4"
76
+ },
6
77
  "devDependencies": {
7
- "@types/bun": "latest"
78
+ "@types/bun": "latest",
79
+ "@types/node": "latest",
80
+ "@effect/platform-bun": ">=4.0.0-beta.104 || >=4.0.0"
8
81
  },
9
82
  "peerDependencies": {
10
- "typescript": "^5"
11
- },
12
- "repository": {
13
- "type": "git"
83
+ "effect": ">=4.0.0-beta.104 || >=4.0.0"
14
84
  }
15
85
  }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Vercel credentials — hand-written.
3
+ *
4
+ * The `Credentials` service resolves `{ token, apiBaseUrl }` per request; the
5
+ * protocol layer formats the `Authorization: Bearer <token>` header from it.
6
+ * The token is a Vercel access token — personal, team, or an OAuth
7
+ * integration's — the REST API accepts all of them as bearer tokens.
8
+ *
9
+ * Vercel scopes most requests to a team via the `teamId`/`slug` QUERY
10
+ * parameters, which the spec declares per operation; they stay ordinary input
11
+ * fields rather than credential state, because a single token routinely spans
12
+ * several teams.
13
+ */
14
+ import * as EffectConfig from "effect/Config";
15
+ import * as Context from "effect/Context";
16
+ import * as Effect from "effect/Effect";
17
+ import * as Layer from "effect/Layer";
18
+ import * as Redacted from "effect/Redacted";
19
+ import { ConfigError } from "@distilled.cloud/core/errors";
20
+
21
+ /** Vercel's REST API root. */
22
+ export const DEFAULT_API_BASE_URL = "https://api.vercel.com";
23
+
24
+ export interface Config {
25
+ readonly token: Redacted.Redacted<string>;
26
+ readonly apiBaseUrl: string;
27
+ }
28
+
29
+ export class Credentials extends Context.Service<
30
+ Credentials,
31
+ Effect.Effect<Config>
32
+ >()("VercelCredentials") {}
33
+
34
+ const envConfig = EffectConfig.all({
35
+ // `VERCEL_TOKEN` is what the Vercel CLI and the official SDK read.
36
+ token: EffectConfig.string("VERCEL_TOKEN"),
37
+ apiBaseUrl: EffectConfig.string("VERCEL_API_URL").pipe(
38
+ EffectConfig.withDefault(DEFAULT_API_BASE_URL),
39
+ ),
40
+ });
41
+
42
+ export const CredentialsFromEnv = Layer.succeed(
43
+ Credentials,
44
+ envConfig.pipe(
45
+ Effect.mapError(
46
+ () =>
47
+ new ConfigError({
48
+ message: "VERCEL_TOKEN environment variable is required",
49
+ }),
50
+ ),
51
+ Effect.map(({ token, apiBaseUrl }) => ({
52
+ token: Redacted.make(token),
53
+ apiBaseUrl,
54
+ })),
55
+ Effect.orDie,
56
+ ),
57
+ );
58
+
59
+ /** Convenience layer from a plain token + optional base URL. */
60
+ export const credentials = (config: {
61
+ readonly token: string;
62
+ readonly apiBaseUrl?: string;
63
+ }): Layer.Layer<Credentials> =>
64
+ Layer.succeed(
65
+ Credentials,
66
+ Effect.succeed({
67
+ token: Redacted.make(config.token),
68
+ apiBaseUrl: config.apiBaseUrl ?? DEFAULT_API_BASE_URL,
69
+ }),
70
+ );
package/src/errors.ts ADDED
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Vercel-specific error types.
3
+ *
4
+ * Re-exports the common HTTP errors from core and adds the two statuses
5
+ * Vercel uses that core's shared map has no entry for, plus the
6
+ * unknown-error and parse-error wrappers.
7
+ */
8
+ export {
9
+ BadGateway,
10
+ BadRequest,
11
+ Conflict,
12
+ ConfigError,
13
+ Forbidden,
14
+ GatewayTimeout,
15
+ InternalServerError,
16
+ Locked,
17
+ NotFound,
18
+ ServiceUnavailable,
19
+ TooManyRequests,
20
+ Unauthorized,
21
+ UnprocessableEntity,
22
+ HTTP_STATUS_MAP,
23
+ DEFAULT_ERRORS,
24
+ API_ERRORS,
25
+ } from "@distilled.cloud/core/errors";
26
+ import type { DefaultErrors as CoreDefaultErrors } from "@distilled.cloud/core/errors";
27
+
28
+ import * as Schema from "effect/Schema";
29
+ import * as Category from "@distilled.cloud/core/category";
30
+
31
+ /**
32
+ * HTTP 402 — the account cannot be billed for the request: a missing payment
33
+ * method, an unpaid invoice, or a spend cap the team has already hit (Vercel
34
+ * pauses the account at the cap until an owner disables it). Declared on the
35
+ * ~95 operations that provision billable resources; the rest reach it through
36
+ * the protocol's status map.
37
+ */
38
+ export class PaymentRequired extends Schema.TaggedError<PaymentRequired>()(
39
+ "PaymentRequired",
40
+ {
41
+ message: Schema.String,
42
+ },
43
+ ).pipe(Category.withQuotaError) {}
44
+
45
+ /**
46
+ * HTTP 410 — Vercel's "Invalid API version": the versioned path segment
47
+ * (`/v5/domains`, `/v9/projects`) is no longer served. The spec declares it on
48
+ * nearly every operation as boilerplate, so it rides the common error channel
49
+ * instead of every generated operation's error list — a 410 means the SDK's
50
+ * pinned path version was retired and needs a regeneration, not something a
51
+ * caller can branch on per operation.
52
+ */
53
+ export class Gone extends Schema.TaggedError<Gone>()("Gone", {
54
+ message: Schema.String,
55
+ }).pipe(Category.withNotFoundError) {}
56
+
57
+ /**
58
+ * Unknown Vercel error — returned when a failed response's HTTP status has no
59
+ * mapped error class. Carries the raw body for later cataloging.
60
+ */
61
+ export class UnknownVercelError extends Schema.TaggedError<UnknownVercelError>()(
62
+ "UnknownVercelError",
63
+ {
64
+ code: Schema.optional(Schema.String),
65
+ message: Schema.optional(Schema.String),
66
+ body: Schema.Unknown,
67
+ },
68
+ ).pipe(Category.withServerError) {}
69
+
70
+ /** Schema parse error wrapper. */
71
+ export class VercelParseError extends Schema.TaggedError<VercelParseError>()(
72
+ "VercelParseError",
73
+ {
74
+ body: Schema.Unknown,
75
+ cause: Schema.Unknown,
76
+ },
77
+ ).pipe(Category.withParseError) {}
78
+
79
+ /**
80
+ * Errors any Vercel operation may surface in addition to the per-operation
81
+ * typed status errors.
82
+ */
83
+ export type ClientErrors =
84
+ | UnknownVercelError
85
+ | VercelParseError
86
+ | PaymentRequired
87
+ | Gone;
88
+
89
+ /**
90
+ * Default Vercel operation errors: the shared HTTP status errors from core
91
+ * plus the client-level fallback/decode errors.
92
+ */
93
+ export type DefaultErrors = CoreDefaultErrors | ClientErrors;
package/src/index.ts ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @distilled.cloud/vercel — Vercel REST API SDK for Effect.
3
+ *
4
+ * `./services` is generated by `scripts/generate.ts` from the Smithy models in
5
+ * `.generated-specs` (written by `scripts/convert.ts` from the OpenAPI
6
+ * document `scripts/download-spec.ts` downloads into `specs/`). Everything
7
+ * else in this folder is hand-written.
8
+ */
9
+ export * from "./credentials.ts";
10
+ export * from "./errors.ts";
11
+ export * as T from "./traits.ts";
12
+ export {
13
+ VercelProtocol,
14
+ type VercelOpError,
15
+ type VercelOpContext,
16
+ } from "./protocol.ts";
17
+ export * as Retry from "./retry.ts";
18
+ export * as Services from "./services/index.ts";
@@ -0,0 +1,98 @@
1
+ /**
2
+ * VercelProtocol — the shared bearer-REST protocol instantiated for Vercel.
3
+ *
4
+ * Vercel speaks plain JSON with no success envelope: a list endpoint returns
5
+ * its collection object (`{ projects: [...], pagination: {...} }`), a single
6
+ * resource returns the object itself. FAILURES are enveloped, and uniformly
7
+ * so — `{ "error": { "code": "forbidden", "message": "Not authorized" } }` —
8
+ * with `code` a machine-readable string that error matchers can key on.
9
+ *
10
+ * The API version is part of the PATH (`/v9/projects`, `/v5/domains`), not a
11
+ * header, so each generated operation carries the version it was generated
12
+ * from; a retired version answers 410 (see `Gone` in errors.ts).
13
+ */
14
+ import * as Effect from "effect/Effect";
15
+ import type * as Layer from "effect/Layer";
16
+ import * as Redacted from "effect/Redacted";
17
+ import type * as HttpClient from "effect/unstable/http/HttpClient";
18
+ import type * as HttpClientError from "effect/unstable/http/HttpClientError";
19
+ import type * as API from "@distilled.cloud/core/api";
20
+ import type { ConfigError } from "@distilled.cloud/core/errors";
21
+ import { HTTP_STATUS_MAP } from "@distilled.cloud/core/errors";
22
+ import {
23
+ makeRestProtocol,
24
+ type RestErrorEnvelope,
25
+ } from "@distilled.cloud/core/protocol-rest";
26
+ import { Credentials, type Config } from "./credentials.ts";
27
+ import {
28
+ Gone,
29
+ PaymentRequired,
30
+ UnknownVercelError,
31
+ type DefaultErrors,
32
+ } from "./errors.ts";
33
+
34
+ /**
35
+ * Error channel shared by every generated Vercel operation. Generated service
36
+ * files annotate operations with `API.OperationMethod<I, O, VercelOpError,
37
+ * VercelOpContext>` explicitly so the compiler never infers these back out of
38
+ * the schema generics.
39
+ */
40
+ export type VercelOpError =
41
+ | DefaultErrors
42
+ | ConfigError
43
+ | HttpClientError.HttpClientError;
44
+
45
+ /** Context (requirements) shared by every generated Vercel operation. */
46
+ export type VercelOpContext = Credentials | HttpClient.HttpClient;
47
+
48
+ /**
49
+ * Vercel error bodies nest under `error`: `{ error: { code, message } }`.
50
+ * A handful of edge paths (proxy 502s, HTML error pages) answer without that
51
+ * envelope — those fall through to the protocol's `HTTP <status>` default.
52
+ */
53
+ const errorEnvelope = (body: unknown): RestErrorEnvelope | undefined => {
54
+ if (body === null || typeof body !== "object") return undefined;
55
+ const err = (body as Record<string, unknown>).error;
56
+ if (err === null || typeof err !== "object") return undefined;
57
+ const e = err as Record<string, unknown>;
58
+ return {
59
+ code: typeof e.code === "string" ? e.code : undefined,
60
+ message: typeof e.message === "string" ? e.message : undefined,
61
+ };
62
+ };
63
+
64
+ export const VercelProtocol: Layer.Layer<API.Protocol> =
65
+ makeRestProtocol<Config>({
66
+ // Resolved on the CALLING fiber per request (the layer is memoized per
67
+ // process); the Credentials service holds an effect, so a token rotated
68
+ // between calls is picked up without rebuilding the layer.
69
+ credentials: Effect.gen(function* () {
70
+ const resolve = yield* Credentials;
71
+ return yield* resolve;
72
+ }),
73
+ baseUrl: (creds) => creds.apiBaseUrl,
74
+ headers: (creds) => ({
75
+ Authorization: `Bearer ${Redacted.value(creds.token)}`,
76
+ }),
77
+ errorEnvelope,
78
+ // Core's shared map plus the two statuses Vercel uses that it doesn't
79
+ // cover: 402 (billing) and 410 (retired path version). Both are declared
80
+ // so broadly in the spec that leaving them unmapped would funnel routine
81
+ // failures into UnknownVercelError.
82
+ statusMap: {
83
+ ...HTTP_STATUS_MAP,
84
+ 402: PaymentRequired,
85
+ 410: Gone,
86
+ },
87
+ unknownError: ({ code, message, body }) =>
88
+ new UnknownVercelError({
89
+ code:
90
+ typeof code === "string"
91
+ ? code
92
+ : code !== undefined
93
+ ? String(code)
94
+ : undefined,
95
+ message,
96
+ body,
97
+ }),
98
+ });
package/src/retry.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Vercel retry surface — a veneer over `@distilled.cloud/core/retry`.
3
+ *
4
+ * The `Retry` service tag is threaded into every generated operation via
5
+ * `API.make({ retry: Retry })`, so a caller-installed policy applies to all
6
+ * Vercel calls below it and core's `makeDefault` is the fallback when none is
7
+ * provided.
8
+ *
9
+ * Vercel answers a tripped rate limit with `429` plus `Retry-After`; the REST
10
+ * protocol stamps that onto the retryable error classes, and the default
11
+ * policy honors it ahead of its own backoff.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import * as Vercel from "@distilled.cloud/vercel";
16
+ *
17
+ * myEffect.pipe(Vercel.Retry.transient);
18
+ * ```
19
+ */
20
+ import * as Context from "effect/Context";
21
+ import * as Effect from "effect/Effect";
22
+ import * as Layer from "effect/Layer";
23
+ import * as Retries from "@distilled.cloud/core/retry";
24
+
25
+ export type Options = Retries.Options;
26
+ export type Factory = Retries.Factory;
27
+ export type Policy = Retries.Policy;
28
+
29
+ /** Context tag for configuring retry behavior of Vercel API calls. */
30
+ export class Retry extends Context.Service<Retry, Policy>()("VercelRetry") {}
31
+
32
+ /** Provides a custom retry policy to every Vercel API call below it. */
33
+ export const policy: {
34
+ (
35
+ options: Options,
36
+ ): <A, E, R>(
37
+ effect: Effect.Effect<A, E, R>,
38
+ ) => Effect.Effect<A, E, Exclude<R, Retry>>;
39
+ (
40
+ factory: Factory,
41
+ ): <A, E, R>(
42
+ effect: Effect.Effect<A, E, R>,
43
+ ) => Effect.Effect<A, E, Exclude<R, Retry>>;
44
+ } = (optionsOrFactory: Options | Factory) =>
45
+ Effect.provide(Layer.succeed(Retry, optionsOrFactory));
46
+
47
+ /** Disables all automatic retries. */
48
+ export const none: <A, E, R>(
49
+ effect: Effect.Effect<A, E, R>,
50
+ ) => Effect.Effect<A, E, Exclude<R, Retry>> = Effect.provide(
51
+ Layer.succeed(Retry, { while: () => false }),
52
+ );
53
+
54
+ /**
55
+ * The default retry policy (core's): transient/throttling/retryable errors,
56
+ * capped exponential backoff with jitter, server `retryAfter` hints honored
57
+ * with precedence.
58
+ */
59
+ export const makeDefault: Factory = Retries.makeDefault;
60
+
61
+ export const jittered = Retries.jittered;
62
+ export const capped = Retries.capped;
63
+
64
+ /** Retry options that retry all throttling errors indefinitely. */
65
+ export const throttlingOptions: Options = Retries.throttlingOptions;
66
+
67
+ /** Retries all throttling errors indefinitely (honoring server hints). */
68
+ export const throttling: <A, E, R>(
69
+ effect: Effect.Effect<A, E, R>,
70
+ ) => Effect.Effect<A, E, Exclude<R, Retry>> = policy(Retries.throttlingFactory);
71
+
72
+ /** Retry options that retry all transient errors indefinitely. */
73
+ export const transientOptions: Options = Retries.transientOptions;
74
+
75
+ /** Retries all transient errors indefinitely (honoring server hints). */
76
+ export const transient: <A, E, R>(
77
+ effect: Effect.Effect<A, E, R>,
78
+ ) => Effect.Effect<A, E, Exclude<R, Retry>> = policy(Retries.transientFactory);