@distilled.cloud/expo-eas 1.0.0-rc.13 → 1.0.0-rc.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/credentials.d.ts.map +1 -1
- package/lib/credentials.js.map +1 -1
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +1 -1
- package/lib/errors.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/protocol.d.ts +2 -2
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +26 -15
- package/lib/protocol.js.map +1 -1
- package/lib/protocol.test.d.ts +2 -0
- package/lib/protocol.test.d.ts.map +1 -0
- package/lib/protocol.test.js +267 -0
- package/lib/protocol.test.js.map +1 -0
- package/lib/retry.d.ts +1 -1
- package/lib/retry.d.ts.map +1 -1
- package/lib/retry.js +1 -1
- package/lib/retry.js.map +1 -1
- package/lib/services/eas.d.ts +5840 -2078
- package/lib/services/eas.d.ts.map +1 -1
- package/lib/services/eas.js +8323 -7210
- package/lib/services/eas.js.map +1 -1
- package/lib/traits.d.ts.map +1 -1
- package/lib/traits.js.map +1 -1
- package/package.json +13 -11
- package/src/credentials.ts +3 -4
- package/src/errors.ts +14 -27
- package/src/index.ts +1 -5
- package/src/protocol.test.ts +362 -0
- package/src/protocol.ts +37 -38
- package/src/retry.ts +2 -8
- package/src/services/eas.ts +50589 -50427
- package/src/traits.ts +5 -12
- package/lib/response-validation.test.d.ts +0 -4
- package/lib/response-validation.test.d.ts.map +0 -1
- package/lib/response-validation.test.js +0 -39
- package/lib/response-validation.test.js.map +0 -1
- package/src/response-validation.test.ts +0 -59
package/src/protocol.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import * as API from "@distilled.cloud/core/api";
|
|
2
|
+
import { HTTP_STATUS_MAP } from "@distilled.cloud/core/errors";
|
|
3
|
+
import { getAnn } from "@distilled.cloud/core/protocol-http";
|
|
4
|
+
import { failIfStrict, validateResponse } from "@distilled.cloud/core/response-validation";
|
|
5
|
+
import { parseRetryAfterForStatus } from "@distilled.cloud/core/retry-after";
|
|
1
6
|
/**
|
|
2
7
|
* ExpoGraphqlProtocol — hand-written.
|
|
3
8
|
*
|
|
@@ -18,29 +23,21 @@
|
|
|
18
23
|
* `EAS_ERROR_CODE_MAP`, then the HTTP status map, then
|
|
19
24
|
* `UnknownEasError`.
|
|
20
25
|
* 2. HTTP status >= 400 (network/auth/proxy errors) — body
|
|
21
|
-
* usually `{ message }
|
|
22
|
-
* envelope
|
|
23
|
-
* parsing.
|
|
26
|
+
* usually `{ message }`, a plain `{ errors: [...] }`
|
|
27
|
+
* envelope, or non-JSON text (proxy HTML, plain-text 429);
|
|
28
|
+
* mapped via the status map with retry-after parsing.
|
|
24
29
|
* On success the value of `data.<responsePath>` (see
|
|
25
30
|
* `T.ResponsePath`) is returned verbatim.
|
|
26
31
|
*/
|
|
27
32
|
import * as Effect from "effect/Effect";
|
|
28
|
-
import * as Layer from "effect/Layer";
|
|
29
|
-
import * as Redacted from "effect/Redacted";
|
|
30
|
-
import * as Schema from "effect/Schema";
|
|
31
|
-
import type * as AST from "effect/SchemaAST";
|
|
32
33
|
import type * as HttpClient from "effect/http/HttpClient";
|
|
33
34
|
import type * as HttpClientError from "effect/http/HttpClientError";
|
|
34
35
|
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
35
36
|
import type * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
36
|
-
import * as
|
|
37
|
-
import
|
|
38
|
-
import
|
|
39
|
-
import
|
|
40
|
-
failIfStrict,
|
|
41
|
-
validateResponse,
|
|
42
|
-
} from "@distilled.cloud/core/response-validation";
|
|
43
|
-
import { parseRetryAfterForStatus } from "@distilled.cloud/core/retry-after";
|
|
37
|
+
import * as Layer from "effect/Layer";
|
|
38
|
+
import * as Redacted from "effect/Redacted";
|
|
39
|
+
import * as Schema from "effect/Schema";
|
|
40
|
+
import type * as AST from "effect/SchemaAST";
|
|
44
41
|
import { type Config, Credentials } from "./credentials.ts";
|
|
45
42
|
import {
|
|
46
43
|
type DefaultErrors,
|
|
@@ -75,8 +72,7 @@ export type ExpoEasOpContext = Credentials | HttpClient.HttpClient;
|
|
|
75
72
|
// EAS failures are real typed errors that the operation's explicit
|
|
76
73
|
// `ExpoEasOpError` annotation re-surfaces. Fail with the instance and erase
|
|
77
74
|
// the error type here.
|
|
78
|
-
const fail = (e: unknown): Effect.Effect<never> =>
|
|
79
|
-
Effect.fail(e) as Effect.Effect<never>;
|
|
75
|
+
const fail = (e: unknown): Effect.Effect<never> => Effect.fail(e) as Effect.Effect<never>;
|
|
80
76
|
|
|
81
77
|
// ============================================================================
|
|
82
78
|
// Error envelope parsing (ported from distilled v0's client.ts)
|
|
@@ -118,6 +114,9 @@ type StatusClass = new (args: {
|
|
|
118
114
|
retryAfter?: ReturnType<typeof parseRetryAfterForStatus>;
|
|
119
115
|
}) => unknown;
|
|
120
116
|
|
|
117
|
+
const statusClass = (status: number): StatusClass | undefined =>
|
|
118
|
+
(HTTP_STATUS_MAP as Record<number, StatusClass | undefined>)[status];
|
|
119
|
+
|
|
121
120
|
/**
|
|
122
121
|
* Match an EAS error response (GraphQL envelope or HTTP-level body) to the
|
|
123
122
|
* appropriate error class. Ported from distilled v0's `matchError`:
|
|
@@ -144,9 +143,7 @@ const matchError = (
|
|
|
144
143
|
}
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
const StatusClass = (
|
|
148
|
-
| StatusClass
|
|
149
|
-
| undefined;
|
|
146
|
+
const StatusClass = statusClass(status);
|
|
150
147
|
if (StatusClass && status >= 400) {
|
|
151
148
|
return fail(
|
|
152
149
|
new StatusClass({
|
|
@@ -165,12 +162,25 @@ const matchError = (
|
|
|
165
162
|
);
|
|
166
163
|
}
|
|
167
164
|
|
|
165
|
+
// Non-JSON body (HTML proxy page, plain-text 429/401): the trimmed text
|
|
166
|
+
// is the message.
|
|
167
|
+
if (typeof errorBody === "string") {
|
|
168
|
+
const StatusClass = statusClass(status);
|
|
169
|
+
if (StatusClass) {
|
|
170
|
+
return fail(
|
|
171
|
+
new StatusClass({
|
|
172
|
+
message: errorBody.trim() || `HTTP ${status}`,
|
|
173
|
+
retryAfter: parseRetryAfterForStatus(status, headers),
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return fail(new UnknownEasError({ body: errorBody }));
|
|
178
|
+
}
|
|
179
|
+
|
|
168
180
|
// Plain REST-ish error body
|
|
169
181
|
const rest = decodeRest(errorBody);
|
|
170
182
|
if (rest._tag === "Some") {
|
|
171
|
-
const StatusClass = (
|
|
172
|
-
| StatusClass
|
|
173
|
-
| undefined;
|
|
183
|
+
const StatusClass = statusClass(status);
|
|
174
184
|
if (StatusClass) {
|
|
175
185
|
return fail(
|
|
176
186
|
new StatusClass({
|
|
@@ -200,13 +210,7 @@ const matchError = (
|
|
|
200
210
|
// fiber's context on every request instead. The requirement is erased at this
|
|
201
211
|
// boundary (Protocol effects are typed with no requirements) and reintroduced
|
|
202
212
|
// for callers by the generated `ExpoEasOpContext` annotations.
|
|
203
|
-
const encode = ({
|
|
204
|
-
input,
|
|
205
|
-
inputAst,
|
|
206
|
-
}: {
|
|
207
|
-
readonly input: unknown;
|
|
208
|
-
readonly inputAst: AST.AST;
|
|
209
|
-
}) =>
|
|
213
|
+
const encode = ({ input, inputAst }: { readonly input: unknown; readonly inputAst: AST.AST }) =>
|
|
210
214
|
Effect.gen(function* () {
|
|
211
215
|
// The Credentials service holds an effect — resolving it here (per
|
|
212
216
|
// request) picks up rotations.
|
|
@@ -223,9 +227,7 @@ const encode = ({
|
|
|
223
227
|
// The operation's input IS the GraphQL variables object (variable names
|
|
224
228
|
// are emitted verbatim — no wire renames).
|
|
225
229
|
const variables: Record<string, unknown> = {};
|
|
226
|
-
for (const [k, v] of Object.entries(
|
|
227
|
-
(input ?? {}) as Record<string, unknown>,
|
|
228
|
-
)) {
|
|
230
|
+
for (const [k, v] of Object.entries((input ?? {}) as Record<string, unknown>)) {
|
|
229
231
|
if (v !== undefined) variables[k] = v;
|
|
230
232
|
}
|
|
231
233
|
|
|
@@ -308,9 +310,7 @@ const decode = ({
|
|
|
308
310
|
// (core/response-validation) checks it against the output schema.
|
|
309
311
|
const path = getAnn(outputAst, responsePathSymbol) as string | undefined;
|
|
310
312
|
let payload: unknown =
|
|
311
|
-
envelope !== null && typeof envelope === "object"
|
|
312
|
-
? envelope.data
|
|
313
|
-
: undefined;
|
|
313
|
+
envelope !== null && typeof envelope === "object" ? envelope.data : undefined;
|
|
314
314
|
if (path !== undefined) {
|
|
315
315
|
for (const seg of path.split(".")) {
|
|
316
316
|
payload =
|
|
@@ -333,8 +333,7 @@ export const ExpoGraphqlProtocol: Layer.Layer<API.Protocol> = Layer.succeed(
|
|
|
333
333
|
API.Protocol,
|
|
334
334
|
API.Protocol.of({
|
|
335
335
|
// Erase encode's Credentials requirement (see comment above).
|
|
336
|
-
encode: (args) =>
|
|
337
|
-
encode(args) as Effect.Effect<HttpClientRequest.HttpClientRequest>,
|
|
336
|
+
encode: (args) => encode(args) as Effect.Effect<HttpClientRequest.HttpClientRequest>,
|
|
338
337
|
decode,
|
|
339
338
|
}),
|
|
340
339
|
);
|
package/src/retry.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Policy, throttlingFactory, transientFactory } from "@distilled.cloud/core/retry";
|
|
1
2
|
/**
|
|
2
3
|
* ExpoEas retry configuration.
|
|
3
4
|
*
|
|
@@ -17,11 +18,6 @@
|
|
|
17
18
|
import * as Context from "effect/Context";
|
|
18
19
|
import * as Effect from "effect/Effect";
|
|
19
20
|
import * as Layer from "effect/Layer";
|
|
20
|
-
import {
|
|
21
|
-
type Policy,
|
|
22
|
-
throttlingFactory,
|
|
23
|
-
transientFactory,
|
|
24
|
-
} from "@distilled.cloud/core/retry";
|
|
25
21
|
|
|
26
22
|
export {
|
|
27
23
|
type Options,
|
|
@@ -44,9 +40,7 @@ export const policy = (optionsOrFactory: Policy) =>
|
|
|
44
40
|
Effect.provide(Layer.succeed(Retry, optionsOrFactory));
|
|
45
41
|
|
|
46
42
|
/** Disables all automatic retries. */
|
|
47
|
-
export const none = Effect.provide(
|
|
48
|
-
Layer.succeed(Retry, { while: () => false }),
|
|
49
|
-
);
|
|
43
|
+
export const none = Effect.provide(Layer.succeed(Retry, { while: () => false }));
|
|
50
44
|
|
|
51
45
|
/** Apply the throttling retry policy (retries throttling errors indefinitely). */
|
|
52
46
|
export const throttling = policy(throttlingFactory);
|