@panorama-industries/effect-vercel-core 0.1.0 → 0.3.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.
@@ -12,6 +12,15 @@ declare const VercelSystemEnv_base: Context.ServiceClass<VercelSystemEnv, "@effe
12
12
  readonly target: Option.Option<VercelTarget>;
13
13
  /** Deployment host name without a scheme (`VERCEL_URL`). */
14
14
  readonly url: Option.Option<string>;
15
+ /** Host name of the Git branch's preview deployment, without a scheme (`VERCEL_BRANCH_URL`). */
16
+ readonly branchUrl: Option.Option<string>;
17
+ /**
18
+ * Host name of the project's production domain, without a scheme
19
+ * (`VERCEL_PROJECT_PRODUCTION_URL`). Vercel also sets it in preview deployments.
20
+ */
21
+ readonly projectProductionUrl: Option.Option<string>;
22
+ /** True when the code runs on Vercel (`VERCEL` is `1`). */
23
+ readonly isVercel: boolean;
15
24
  /** True when `NODE_ENV` is `development`, which enables local-development behavior. */
16
25
  readonly isDevelopment: boolean;
17
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-system-env.d.ts","sourceRoot":"","sources":["../../src/contracts/vercel-system-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;;IAW1F,qDAAqD;qBACpC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAE5C,mEAAmE;2BAC5C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAElD,+DAA+D;wBAC3C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IAE5C,wCAAwC;qBACvB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAE5C,4DAA4D;kBAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAEnC,uFAAuF;4BAC/D,OAAO;IAE/B;;;OAGG;yBACkB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;;AA/B9C;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,oBA2BK;CAAG"}
1
+ {"version":3,"file":"vercel-system-env.d.ts","sourceRoot":"","sources":["../../src/contracts/vercel-system-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;;IAW1F,qDAAqD;qBACpC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAE5C,mEAAmE;2BAC5C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAElD,+DAA+D;wBAC3C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IAE5C,wCAAwC;qBACvB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAE5C,4DAA4D;kBAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAEnC,gGAAgG;wBAC5E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAEzC;;;OAGG;mCAC4B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAEpD,2DAA2D;uBACxC,OAAO;IAE1B,uFAAuF;4BAC/D,OAAO;IAE/B;;;OAGG;yBACkB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;;AA3C9C;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,oBAuCK;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-system-env.js","sourceRoot":"","sources":["../../src/contracts/vercel-system-env.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIjC;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,OAAO,EA2BjD,CAAC,qCAAqC,CAAC;CAAG"}
1
+ {"version":3,"file":"vercel-system-env.js","sourceRoot":"","sources":["../../src/contracts/vercel-system-env.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIjC;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,OAAO,EAuCjD,CAAC,qCAAqC,CAAC;CAAG"}
@@ -1,5 +1,6 @@
1
1
  import type { HttpClientError, HttpClientResponse } from "effect/http";
2
- import { Effect } from "effect";
2
+ import { Effect, Option } from "effect";
3
+ import { Headers } from "effect/http";
3
4
  import { VercelApiError } from "../contracts/vercel-api-error.ts";
4
5
  /** Identifies the failed call in a `VercelApiError`. */
5
6
  export interface VercelApiErrorOptions {
@@ -10,6 +11,31 @@ export interface VercelApiErrorOptions {
10
11
  }
11
12
  /** Reads the most useful human-readable message from an error response body. */
12
13
  export declare const responseErrorMessage: (response: HttpClientResponse.HttpClientResponse) => Effect.Effect<string, never, never>;
14
+ /** A non-2xx response whose body the caller has already read. */
15
+ export interface VercelApiErrorStatus {
16
+ /** Traced operation name stored in `VercelApiError.operation`, such as `QueueApi.send`. */
17
+ readonly operation: string;
18
+ /** HTTP status of the response. */
19
+ readonly status: number;
20
+ /** Human-readable message for the reason, usually read from the response body. */
21
+ readonly message: string;
22
+ /** Machine-readable error code found in the response header or body, if any. */
23
+ readonly errorCode: Option.Option<string>;
24
+ /** Response headers; `Retry-After` is read from them on 429. */
25
+ readonly headers: Headers.Headers;
26
+ }
27
+ /**
28
+ * Build the `VercelApiError` matching a non-2xx status, for callers that read the body themselves
29
+ * (for example to find a domain error code in JSON before falling back to `VercelApiError`).
30
+ *
31
+ * Maps 400, 401, 403, 413, 429 (with `Retry-After`) and 5xx to their `Api*` reasons and any other
32
+ * status to `ApiUnexpectedResponse`, exactly like {@link vercelApiErrorFromResponse}.
33
+ *
34
+ * @param now - Current time in epoch milliseconds (`Clock.currentTimeMillis`), used to turn an
35
+ * HTTP-date `Retry-After` into a delay.
36
+ * @returns The error value; fail with it using `yield*` or `Effect.fail`.
37
+ */
38
+ export declare const vercelApiErrorFromStatus: (response: VercelApiErrorStatus, now: number) => VercelApiError;
13
39
  /**
14
40
  * Fail with the `VercelApiError` matching a non-2xx response.
15
41
  *
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-api-errors.d.ts","sourceRoot":"","sources":["../../src/http/vercel-api-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAS,MAAM,EAAiC,MAAM,QAAQ,CAAC;AAGtE,OAAO,EASL,cAAc,EACf,MAAM,kCAAkC,CAAC;AAE1C,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACpC,2FAA2F;IAC3F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,wFAAwF;IACxF,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAmBD,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,0FAY/B,CAAC;AAQH;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,kIA2BrC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,UACrC,eAAe,CAAC,eAAe,WAC7B,qBAAqB,KAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAsBrC,CAAC"}
1
+ {"version":3,"file":"vercel-api-errors.d.ts","sourceRoot":"","sources":["../../src/http/vercel-api-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAS,MAAM,EAAS,MAAM,EAAkB,MAAM,QAAQ,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EASL,cAAc,EACf,MAAM,kCAAkC,CAAC;AAE1C,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACpC,2FAA2F;IAC3F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,wFAAwF;IACxF,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAmBD,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,0FAY/B,CAAC;AAEH,iEAAiE;AACjE,MAAM,WAAW,oBAAoB;IACnC,2FAA2F;IAC3F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,kFAAkF;IAClF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAE1C,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;CACnC;AAQD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,aACzB,oBAAoB,OACzB,MAAM,KACV,cAsBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,kIAmBrC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,UACrC,eAAe,CAAC,eAAe,WAC7B,qBAAqB,KAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAsBrC,CAAC"}
@@ -24,7 +24,27 @@ export const responseErrorMessage = Effect.fnUntraced(function* (response) {
24
24
  const trimmed = text.trim();
25
25
  return contentType.startsWith("text/") && trimmed.length > 0 ? trimmed : fallback;
26
26
  });
27
- const retryAfterOf = (response, now) => Headers.get(response.headers, "retry-after").pipe(Option.flatMap((value) => Result.getSuccess(Headers.parseRetryAfter(value))), Option.map((retryAfter) => Headers.retryAfterDelay(retryAfter, now)));
27
+ const retryAfterOf = (headers, now) => Headers.get(headers, "retry-after").pipe(Option.flatMap((value) => Result.getSuccess(Headers.parseRetryAfter(value))), Option.map((retryAfter) => Headers.retryAfterDelay(retryAfter, now)));
28
+ /**
29
+ * Build the `VercelApiError` matching a non-2xx status, for callers that read the body themselves
30
+ * (for example to find a domain error code in JSON before falling back to `VercelApiError`).
31
+ *
32
+ * Maps 400, 401, 403, 413, 429 (with `Retry-After`) and 5xx to their `Api*` reasons and any other
33
+ * status to `ApiUnexpectedResponse`, exactly like {@link vercelApiErrorFromResponse}.
34
+ *
35
+ * @param now - Current time in epoch milliseconds (`Clock.currentTimeMillis`), used to turn an
36
+ * HTTP-date `Retry-After` into a delay.
37
+ * @returns The error value; fail with it using `yield*` or `Effect.fail`.
38
+ */
39
+ export const vercelApiErrorFromStatus = (response, now) => {
40
+ const { message, status } = response;
41
+ const reason = Match.value(status).pipe(Match.when(400, () => new ApiBadRequest({ message })), Match.when(401, () => new ApiUnauthorized({ message })), Match.when(403, () => new ApiForbidden({ message })), Match.when(413, () => new ApiPayloadTooLarge({ message })), Match.when(429, () => new ApiRateLimited({ message, retryAfter: retryAfterOf(response.headers, now) })), Match.when((code) => code >= 500 && code <= 599, () => new ApiServerError({ message, status })), Match.orElse(() => new ApiUnexpectedResponse({ message, status })));
42
+ return new VercelApiError({
43
+ operation: response.operation,
44
+ errorCode: response.errorCode,
45
+ reason,
46
+ });
47
+ };
28
48
  /**
29
49
  * Fail with the `VercelApiError` matching a non-2xx response.
30
50
  *
@@ -35,15 +55,15 @@ const retryAfterOf = (response, now) => Headers.get(response.headers, "retry-aft
35
55
  export const vercelApiErrorFromResponse = Effect.fnUntraced(function* (response, options) {
36
56
  const message = yield* responseErrorMessage(response);
37
57
  const now = yield* Clock.currentTimeMillis;
38
- const status = response.status;
39
- const reason = Match.value(status).pipe(Match.when(400, () => new ApiBadRequest({ message })), Match.when(401, () => new ApiUnauthorized({ message })), Match.when(403, () => new ApiForbidden({ message })), Match.when(413, () => new ApiPayloadTooLarge({ message })), Match.when(429, () => new ApiRateLimited({ message, retryAfter: retryAfterOf(response, now) })), Match.when((code) => code >= 500 && code <= 599, () => new ApiServerError({ message, status })), Match.orElse(() => new ApiUnexpectedResponse({ message, status })));
40
- return yield* new VercelApiError({
58
+ return yield* vercelApiErrorFromStatus({
41
59
  operation: options.operation,
60
+ status: response.status,
61
+ message,
42
62
  errorCode: options.errorCodeHeader === undefined
43
63
  ? Option.none()
44
64
  : Headers.get(response.headers, options.errorCodeHeader),
45
- reason,
46
- });
65
+ headers: response.headers,
66
+ }, now);
47
67
  });
48
68
  /**
49
69
  * Fail with the `VercelApiError` matching an `HttpClientError`.
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-api-errors.js","sourceRoot":"","sources":["../../src/http/vercel-api-errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vercel-api-errors.js","sourceRoot":"","sources":["../../src/http/vercel-api-errors.ts"],"names":[],"mappings":"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"}
@@ -5,10 +5,17 @@ export interface VercelApiTransientRetryOptions {
5
5
  readonly maxAttempts?: number | undefined;
6
6
  /** First backoff delay, doubled (with jitter) on each retry. Defaults to 100 milliseconds. */
7
7
  readonly baseDelay?: Duration.Input | undefined;
8
+ /**
9
+ * Decides which failures are retried, replacing the default (`VercelApiError` with an
10
+ * `ApiNetworkFailure` or `ApiRateLimited` reason). A rate-limited failure it accepts still waits
11
+ * its `Retry-After` delay.
12
+ */
13
+ readonly isRetryable?: ((error: unknown) => boolean) | undefined;
8
14
  }
9
15
  /**
10
16
  * Retry schedule for Vercel API calls that retries only transient failures:
11
- * `VercelApiError` with an `ApiNetworkFailure` or `ApiRateLimited` reason.
17
+ * `VercelApiError` with an `ApiNetworkFailure` or `ApiRateLimited` reason, unless `isRetryable`
18
+ * says otherwise.
12
19
  *
13
20
  * Waits the `Retry-After` delay of a rate-limited response when the service sent one, otherwise
14
21
  * backs off exponentially with jitter. Use it with `Effect.retry(vercelApiTransientRetry())`.
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-api-retry.d.ts","sourceRoot":"","sources":["../../src/http/vercel-api-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA6B,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIvE,kDAAkD;AAClD,MAAM,WAAW,8BAA8B;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1C,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC;CACjD;AAYD;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,aACxB,8BAA8B,KACvC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAU9C,CAAC"}
1
+ {"version":3,"file":"vercel-api-retry.d.ts","sourceRoot":"","sources":["../../src/http/vercel-api-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA6B,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIvE,kDAAkD;AAClD,MAAM,WAAW,8BAA8B;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1C,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC;IAEhD;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAClE;AAYD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aACxB,8BAA8B,KACvC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAW9C,CAAC"}
@@ -8,13 +8,15 @@ const isTransient = (error) => error instanceof VercelApiError &&
8
8
  Predicate.isTagged(error.reason, "ApiRateLimited"));
9
9
  /**
10
10
  * Retry schedule for Vercel API calls that retries only transient failures:
11
- * `VercelApiError` with an `ApiNetworkFailure` or `ApiRateLimited` reason.
11
+ * `VercelApiError` with an `ApiNetworkFailure` or `ApiRateLimited` reason, unless `isRetryable`
12
+ * says otherwise.
12
13
  *
13
14
  * Waits the `Retry-After` delay of a rate-limited response when the service sent one, otherwise
14
15
  * backs off exponentially with jitter. Use it with `Effect.retry(vercelApiTransientRetry())`.
15
16
  */
16
17
  export const vercelApiTransientRetry = (options) => {
17
18
  const maxAttempts = options?.maxAttempts ?? 3;
18
- return Schedule.exponential(options?.baseDelay ?? "100 millis").pipe(Schedule.jittered, Schedule.setInputType(), Schedule.while(({ input, attempt }) => attempt < maxAttempts && isTransient(input)), Schedule.modifyDelay(({ input, duration }) => Effect.succeed(Option.getOrElse(retryAfterOf(input), () => duration))));
19
+ const isRetryable = options?.isRetryable ?? isTransient;
20
+ return Schedule.exponential(options?.baseDelay ?? "100 millis").pipe(Schedule.jittered, Schedule.setInputType(), Schedule.while(({ input, attempt }) => attempt < maxAttempts && isRetryable(input)), Schedule.modifyDelay(({ input, duration }) => Effect.succeed(Option.getOrElse(retryAfterOf(input), () => duration))));
19
21
  };
20
22
  //# sourceMappingURL=vercel-api-retry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-api-retry.js","sourceRoot":"","sources":["../../src/http/vercel-api-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAWlE,MAAM,YAAY,GAAG,CAAC,KAAc,EAAoC,EAAE,CACxE,KAAK,YAAY,cAAc,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC;IACnF,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU;IACzB,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAEpB,MAAM,WAAW,GAAG,CAAC,KAAc,EAAW,EAAE,CAC9C,KAAK,YAAY,cAAc;IAC/B,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB,CAAC;QACpD,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,OAAwC,EACO,EAAE;IACjD,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,CAAC,CAAC;IAC9C,OAAO,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,IAAI,YAAY,CAAC,CAAC,IAAI,CAClE,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,YAAY,EAAW,EAChC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,GAAG,WAAW,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,EACnF,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC3C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CACtE,CACF,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"vercel-api-retry.js","sourceRoot":"","sources":["../../src/http/vercel-api-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAkBlE,MAAM,YAAY,GAAG,CAAC,KAAc,EAAoC,EAAE,CACxE,KAAK,YAAY,cAAc,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC;IACnF,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU;IACzB,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAEpB,MAAM,WAAW,GAAG,CAAC,KAAc,EAAW,EAAE,CAC9C,KAAK,YAAY,cAAc;IAC/B,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB,CAAC;QACpD,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,OAAwC,EACO,EAAE;IACjD,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,WAAW,CAAC;IACxD,OAAO,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,IAAI,YAAY,CAAC,CAAC,IAAI,CAClE,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,YAAY,EAAW,EAChC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,GAAG,WAAW,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,EACnF,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC3C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CACtE,CACF,CAAC;AACJ,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-system-env-live.d.ts","sourceRoot":"","sources":["../../src/implementation/vercel-system-env-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,yDAsB/B,CAAC"}
1
+ {"version":3,"file":"vercel-system-env-live.d.ts","sourceRoot":"","sources":["../../src/implementation/vercel-system-env-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,yDA4B/B,CAAC"}
@@ -14,6 +14,9 @@ export const VercelSystemEnvLive = Layer.effect(VercelSystemEnv, Effect.gen(func
14
14
  projectId: Config.option(Config.schema(ProjectId, "VERCEL_PROJECT_ID")),
15
15
  target: Config.option(Config.schema(VercelTarget, "VERCEL_ENV")),
16
16
  url: Config.option(Config.String("VERCEL_URL")),
17
+ branchUrl: Config.option(Config.String("VERCEL_BRANCH_URL")),
18
+ projectProductionUrl: Config.option(Config.String("VERCEL_PROJECT_PRODUCTION_URL")),
19
+ vercel: Config.option(Config.String("VERCEL")),
17
20
  nodeEnv: Config.option(Config.String("NODE_ENV")),
18
21
  cliVersion: Config.option(Config.String("VERCEL_CLI_VERSION")),
19
22
  });
@@ -23,6 +26,9 @@ export const VercelSystemEnvLive = Layer.effect(VercelSystemEnv, Effect.gen(func
23
26
  projectId: env.projectId,
24
27
  target: env.target,
25
28
  url: env.url,
29
+ branchUrl: env.branchUrl,
30
+ projectProductionUrl: env.projectProductionUrl,
31
+ isVercel: Option.contains(env.vercel, "1"),
26
32
  isDevelopment: Option.contains(env.nodeEnv, "development"),
27
33
  cliVersion: env.cliVersion,
28
34
  });
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-system-env-live.js","sourceRoot":"","sources":["../../src/implementation/vercel-system-env-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC,MAAM,CAC7C,eAAe,EACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;QACnE,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;QAChF,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACvE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAChE,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACjD,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;KAC/D,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC;QAC1D,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
1
+ {"version":3,"file":"vercel-system-env-live.js","sourceRoot":"","sources":["../../src/implementation/vercel-system-env-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC,MAAM,CAC7C,eAAe,EACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;QACnE,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;QAChF,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACvE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAChE,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC/C,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC5D,oBAAoB,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACnF,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACjD,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;KAC/D,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,oBAAoB,EAAE,GAAG,CAAC,oBAAoB;QAC9C,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;QAC1C,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC;QAC1D,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { VercelSystemEnvLive } from "./implementation/vercel-system-env-live.ts"
6
6
  export { VercelOidcLive, vercelOidcFromToken } from "./implementation/vercel-oidc-live.ts";
7
7
  export { type VercelOidcRefreshingOptions, VercelOidcRefreshingLive, vercelOidcRefreshing, } from "./implementation/vercel-oidc-refreshing-live.ts";
8
8
  export { type VercelApiClientOptions, withVercelApi } from "./http/with-vercel-api.ts";
9
- export { type VercelApiErrorOptions, vercelApiErrorFromHttpClientError, vercelApiErrorFromResponse, } from "./http/vercel-api-errors.ts";
9
+ export { type VercelApiErrorOptions, type VercelApiErrorStatus, vercelApiErrorFromHttpClientError, vercelApiErrorFromResponse, vercelApiErrorFromStatus, } from "./http/vercel-api-errors.ts";
10
10
  export { type VercelApiTransientRetryOptions, vercelApiTransientRetry, } from "./http/vercel-api-retry.ts";
11
11
  export { spanLinkFromTraceparent, traceparentHeaders } from "./http/trace-context.ts";
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,EACL,KAAK,2BAA2B,EAChC,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,KAAK,sBAAsB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EACL,KAAK,qBAAqB,EAC1B,iCAAiC,EACjC,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,8BAA8B,EACnC,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,EACL,KAAK,2BAA2B,EAChC,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,KAAK,sBAAsB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,8BAA8B,EACnC,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ export { VercelSystemEnvLive } from "./implementation/vercel-system-env-live.js"
6
6
  export { VercelOidcLive, vercelOidcFromToken } from "./implementation/vercel-oidc-live.js";
7
7
  export { VercelOidcRefreshingLive, vercelOidcRefreshing, } from "./implementation/vercel-oidc-refreshing-live.js";
8
8
  export { withVercelApi } from "./http/with-vercel-api.js";
9
- export { vercelApiErrorFromHttpClientError, vercelApiErrorFromResponse, } from "./http/vercel-api-errors.js";
9
+ export { vercelApiErrorFromHttpClientError, vercelApiErrorFromResponse, vercelApiErrorFromStatus, } from "./http/vercel-api-errors.js";
10
10
  export { vercelApiTransientRetry, } from "./http/vercel-api-retry.js";
11
11
  export { spanLinkFromTraceparent, traceparentHeaders } from "./http/trace-context.js";
12
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,EAEL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAA+B,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAEL,iCAAiC,EACjC,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,EAEL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAA+B,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAGL,iCAAiC,EACjC,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "../../.vscode/schemas/package.schema.json",
3
3
  "name": "@panorama-industries/effect-vercel-core",
4
- "version": "0.1.0",
4
+ "version": "0.3.0",
5
5
  "description": "Shared Effect building blocks for Vercel service SDKs: environment, OIDC credentials, API client, errors and test utilities.",
6
6
  "keywords": [
7
7
  "effect",
@@ -28,6 +28,18 @@ export class VercelSystemEnv extends Context.Service<
28
28
  /** Deployment host name without a scheme (`VERCEL_URL`). */
29
29
  readonly url: Option.Option<string>;
30
30
 
31
+ /** Host name of the Git branch's preview deployment, without a scheme (`VERCEL_BRANCH_URL`). */
32
+ readonly branchUrl: Option.Option<string>;
33
+
34
+ /**
35
+ * Host name of the project's production domain, without a scheme
36
+ * (`VERCEL_PROJECT_PRODUCTION_URL`). Vercel also sets it in preview deployments.
37
+ */
38
+ readonly projectProductionUrl: Option.Option<string>;
39
+
40
+ /** True when the code runs on Vercel (`VERCEL` is `1`). */
41
+ readonly isVercel: boolean;
42
+
31
43
  /** True when `NODE_ENV` is `development`, which enables local-development behavior. */
32
44
  readonly isDevelopment: boolean;
33
45
 
@@ -56,46 +56,94 @@ export const responseErrorMessage = Effect.fnUntraced(function* (
56
56
  return contentType.startsWith("text/") && trimmed.length > 0 ? trimmed : fallback;
57
57
  });
58
58
 
59
- const retryAfterOf = (response: HttpClientResponse.HttpClientResponse, now: number) =>
60
- Headers.get(response.headers, "retry-after").pipe(
59
+ /** A non-2xx response whose body the caller has already read. */
60
+ export interface VercelApiErrorStatus {
61
+ /** Traced operation name stored in `VercelApiError.operation`, such as `QueueApi.send`. */
62
+ readonly operation: string;
63
+
64
+ /** HTTP status of the response. */
65
+ readonly status: number;
66
+
67
+ /** Human-readable message for the reason, usually read from the response body. */
68
+ readonly message: string;
69
+
70
+ /** Machine-readable error code found in the response header or body, if any. */
71
+ readonly errorCode: Option.Option<string>;
72
+
73
+ /** Response headers; `Retry-After` is read from them on 429. */
74
+ readonly headers: Headers.Headers;
75
+ }
76
+
77
+ const retryAfterOf = (headers: Headers.Headers, now: number) =>
78
+ Headers.get(headers, "retry-after").pipe(
61
79
  Option.flatMap((value) => Result.getSuccess(Headers.parseRetryAfter(value))),
62
80
  Option.map((retryAfter) => Headers.retryAfterDelay(retryAfter, now)),
63
81
  );
64
82
 
65
83
  /**
66
- * Fail with the `VercelApiError` matching a non-2xx response.
84
+ * Build the `VercelApiError` matching a non-2xx status, for callers that read the body themselves
85
+ * (for example to find a domain error code in JSON before falling back to `VercelApiError`).
67
86
  *
68
87
  * Maps 400, 401, 403, 413, 429 (with `Retry-After`) and 5xx to their `Api*` reasons and any other
69
- * status to `ApiUnexpectedResponse`. Handle domain statuses such as 404 before delegating here.
70
- * Consumes the response body to build the message.
88
+ * status to `ApiUnexpectedResponse`, exactly like {@link vercelApiErrorFromResponse}.
89
+ *
90
+ * @param now - Current time in epoch milliseconds (`Clock.currentTimeMillis`), used to turn an
91
+ * HTTP-date `Retry-After` into a delay.
92
+ * @returns The error value; fail with it using `yield*` or `Effect.fail`.
71
93
  */
72
- export const vercelApiErrorFromResponse = Effect.fnUntraced(function* (
73
- response: HttpClientResponse.HttpClientResponse,
74
- options: VercelApiErrorOptions,
75
- ): Effect.fn.Return<never, VercelApiError> {
76
- const message = yield* responseErrorMessage(response);
77
- const now = yield* Clock.currentTimeMillis;
78
- const status = response.status;
94
+ export const vercelApiErrorFromStatus = (
95
+ response: VercelApiErrorStatus,
96
+ now: number,
97
+ ): VercelApiError => {
98
+ const { message, status } = response;
79
99
  const reason: VercelApiError["reason"] = Match.value(status).pipe(
80
100
  Match.when(400, () => new ApiBadRequest({ message })),
81
101
  Match.when(401, () => new ApiUnauthorized({ message })),
82
102
  Match.when(403, () => new ApiForbidden({ message })),
83
103
  Match.when(413, () => new ApiPayloadTooLarge({ message })),
84
- Match.when(429, () => new ApiRateLimited({ message, retryAfter: retryAfterOf(response, now) })),
104
+ Match.when(
105
+ 429,
106
+ () => new ApiRateLimited({ message, retryAfter: retryAfterOf(response.headers, now) }),
107
+ ),
85
108
  Match.when(
86
109
  (code) => code >= 500 && code <= 599,
87
110
  () => new ApiServerError({ message, status }),
88
111
  ),
89
112
  Match.orElse(() => new ApiUnexpectedResponse({ message, status })),
90
113
  );
91
- return yield* new VercelApiError({
92
- operation: options.operation,
93
- errorCode:
94
- options.errorCodeHeader === undefined
95
- ? Option.none()
96
- : Headers.get(response.headers, options.errorCodeHeader),
114
+ return new VercelApiError({
115
+ operation: response.operation,
116
+ errorCode: response.errorCode,
97
117
  reason,
98
118
  });
119
+ };
120
+
121
+ /**
122
+ * Fail with the `VercelApiError` matching a non-2xx response.
123
+ *
124
+ * Maps 400, 401, 403, 413, 429 (with `Retry-After`) and 5xx to their `Api*` reasons and any other
125
+ * status to `ApiUnexpectedResponse`. Handle domain statuses such as 404 before delegating here.
126
+ * Consumes the response body to build the message.
127
+ */
128
+ export const vercelApiErrorFromResponse = Effect.fnUntraced(function* (
129
+ response: HttpClientResponse.HttpClientResponse,
130
+ options: VercelApiErrorOptions,
131
+ ): Effect.fn.Return<never, VercelApiError> {
132
+ const message = yield* responseErrorMessage(response);
133
+ const now = yield* Clock.currentTimeMillis;
134
+ return yield* vercelApiErrorFromStatus(
135
+ {
136
+ operation: options.operation,
137
+ status: response.status,
138
+ message,
139
+ errorCode:
140
+ options.errorCodeHeader === undefined
141
+ ? Option.none()
142
+ : Headers.get(response.headers, options.errorCodeHeader),
143
+ headers: response.headers,
144
+ },
145
+ now,
146
+ );
99
147
  });
100
148
 
101
149
  /**
@@ -9,6 +9,13 @@ export interface VercelApiTransientRetryOptions {
9
9
 
10
10
  /** First backoff delay, doubled (with jitter) on each retry. Defaults to 100 milliseconds. */
11
11
  readonly baseDelay?: Duration.Input | undefined;
12
+
13
+ /**
14
+ * Decides which failures are retried, replacing the default (`VercelApiError` with an
15
+ * `ApiNetworkFailure` or `ApiRateLimited` reason). A rate-limited failure it accepts still waits
16
+ * its `Retry-After` delay.
17
+ */
18
+ readonly isRetryable?: ((error: unknown) => boolean) | undefined;
12
19
  }
13
20
 
14
21
  const retryAfterOf = (error: unknown): Option.Option<Duration.Duration> =>
@@ -23,7 +30,8 @@ const isTransient = (error: unknown): boolean =>
23
30
 
24
31
  /**
25
32
  * Retry schedule for Vercel API calls that retries only transient failures:
26
- * `VercelApiError` with an `ApiNetworkFailure` or `ApiRateLimited` reason.
33
+ * `VercelApiError` with an `ApiNetworkFailure` or `ApiRateLimited` reason, unless `isRetryable`
34
+ * says otherwise.
27
35
  *
28
36
  * Waits the `Retry-After` delay of a rate-limited response when the service sent one, otherwise
29
37
  * backs off exponentially with jitter. Use it with `Effect.retry(vercelApiTransientRetry())`.
@@ -32,10 +40,11 @@ export const vercelApiTransientRetry = (
32
40
  options?: VercelApiTransientRetryOptions,
33
41
  ): Schedule.Schedule<Duration.Duration, unknown> => {
34
42
  const maxAttempts = options?.maxAttempts ?? 3;
43
+ const isRetryable = options?.isRetryable ?? isTransient;
35
44
  return Schedule.exponential(options?.baseDelay ?? "100 millis").pipe(
36
45
  Schedule.jittered,
37
46
  Schedule.setInputType<unknown>(),
38
- Schedule.while(({ input, attempt }) => attempt < maxAttempts && isTransient(input)),
47
+ Schedule.while(({ input, attempt }) => attempt < maxAttempts && isRetryable(input)),
39
48
  Schedule.modifyDelay(({ input, duration }) =>
40
49
  Effect.succeed(Option.getOrElse(retryAfterOf(input), () => duration)),
41
50
  ),
@@ -18,6 +18,9 @@ export const VercelSystemEnvLive = Layer.effect(
18
18
  projectId: Config.option(Config.schema(ProjectId, "VERCEL_PROJECT_ID")),
19
19
  target: Config.option(Config.schema(VercelTarget, "VERCEL_ENV")),
20
20
  url: Config.option(Config.String("VERCEL_URL")),
21
+ branchUrl: Config.option(Config.String("VERCEL_BRANCH_URL")),
22
+ projectProductionUrl: Config.option(Config.String("VERCEL_PROJECT_PRODUCTION_URL")),
23
+ vercel: Config.option(Config.String("VERCEL")),
21
24
  nodeEnv: Config.option(Config.String("NODE_ENV")),
22
25
  cliVersion: Config.option(Config.String("VERCEL_CLI_VERSION")),
23
26
  });
@@ -27,6 +30,9 @@ export const VercelSystemEnvLive = Layer.effect(
27
30
  projectId: env.projectId,
28
31
  target: env.target,
29
32
  url: env.url,
33
+ branchUrl: env.branchUrl,
34
+ projectProductionUrl: env.projectProductionUrl,
35
+ isVercel: Option.contains(env.vercel, "1"),
30
36
  isDevelopment: Option.contains(env.nodeEnv, "development"),
31
37
  cliVersion: env.cliVersion,
32
38
  });
package/src/index.ts CHANGED
@@ -12,8 +12,10 @@ export {
12
12
  export { type VercelApiClientOptions, withVercelApi } from "./http/with-vercel-api.ts";
13
13
  export {
14
14
  type VercelApiErrorOptions,
15
+ type VercelApiErrorStatus,
15
16
  vercelApiErrorFromHttpClientError,
16
17
  vercelApiErrorFromResponse,
18
+ vercelApiErrorFromStatus,
17
19
  } from "./http/vercel-api-errors.ts";
18
20
  export {
19
21
  type VercelApiTransientRetryOptions,