@distilled.cloud/fly-io 1.0.0-rc.13 → 1.0.0-rc.14
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 +2 -2
- package/lib/credentials.d.ts.map +1 -1
- package/lib/credentials.js +2 -2
- 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/protocol.d.ts +3 -3
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +37 -52
- package/lib/protocol.js.map +1 -1
- package/lib/protocol.test.js +5 -4
- package/lib/protocol.test.js.map +1 -1
- 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/addons.d.ts +58 -8
- package/lib/services/addons.d.ts.map +1 -1
- package/lib/services/addons.js +40 -85
- package/lib/services/addons.js.map +1 -1
- package/lib/services/machines.d.ts +14 -3
- package/lib/services/machines.d.ts.map +1 -1
- package/lib/services/machines.js +179 -679
- package/lib/services/machines.js.map +1 -1
- package/lib/services/mpg.d.ts +2 -2
- package/lib/services/mpg.d.ts.map +1 -1
- package/lib/services/mpg.js +37 -153
- package/lib/services/mpg.js.map +1 -1
- package/lib/services/sprites.d.ts +687 -144
- package/lib/services/sprites.d.ts.map +1 -1
- package/lib/services/sprites.js +667 -183
- package/lib/services/sprites.js.map +1 -1
- package/lib/sprites-mint.test.js +3 -4
- package/lib/sprites-mint.test.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 +8 -12
- package/src/errors.ts +6 -10
- package/src/protocol.test.ts +12 -32
- package/src/protocol.ts +80 -125
- package/src/retry.ts +2 -8
- package/src/services/addons.ts +135 -154
- package/src/services/machines.ts +338 -1189
- package/src/services/mpg.ts +59 -217
- package/src/services/sprites.ts +1573 -354
- package/src/sprites-mint.test.ts +23 -65
- 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 -32
- package/lib/response-validation.test.js.map +0 -1
- package/src/response-validation.test.ts +0 -46
package/src/protocol.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
import * as API from "@distilled.cloud/core/api";
|
|
2
|
+
import {
|
|
3
|
+
HTTP_STATUS_MAP,
|
|
4
|
+
InternalServerError,
|
|
5
|
+
type ConfigError,
|
|
6
|
+
} from "@distilled.cloud/core/errors";
|
|
7
|
+
import {
|
|
8
|
+
buildRequest,
|
|
9
|
+
getAnn,
|
|
10
|
+
mapKeys,
|
|
11
|
+
matchTypedError,
|
|
12
|
+
} from "@distilled.cloud/core/protocol-http";
|
|
13
|
+
import {
|
|
14
|
+
makeRestProtocol,
|
|
15
|
+
unwrapRedactedDeep,
|
|
16
|
+
wrapSensitive,
|
|
17
|
+
} from "@distilled.cloud/core/protocol-rest";
|
|
18
|
+
import { failIfStrict, validateResponse } from "@distilled.cloud/core/response-validation";
|
|
19
|
+
import { parseRetryAfterForStatus } from "@distilled.cloud/core/retry-after";
|
|
1
20
|
/**
|
|
2
21
|
* Fly.io protocols — Machines REST, UI-EX REST (MPG), GraphQL add-ons, and
|
|
3
22
|
* Sprites REST.
|
|
@@ -22,37 +41,16 @@ import * as Context from "effect/Context";
|
|
|
22
41
|
import * as Deferred from "effect/Deferred";
|
|
23
42
|
import * as Effect from "effect/Effect";
|
|
24
43
|
import * as Exit from "effect/Exit";
|
|
44
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
45
|
+
import type * as HttpClientError from "effect/http/HttpClientError";
|
|
46
|
+
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
47
|
+
import type * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
25
48
|
import * as Layer from "effect/Layer";
|
|
49
|
+
import * as MutableHashMap from "effect/MutableHashMap";
|
|
26
50
|
import * as Option from "effect/Option";
|
|
27
51
|
import * as Redacted from "effect/Redacted";
|
|
28
52
|
import * as Schema from "effect/Schema";
|
|
29
53
|
import type * as AST from "effect/SchemaAST";
|
|
30
|
-
import * as HttpClient from "effect/http/HttpClient";
|
|
31
|
-
import type * as HttpClientError from "effect/http/HttpClientError";
|
|
32
|
-
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
33
|
-
import type * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
34
|
-
import * as API from "@distilled.cloud/core/api";
|
|
35
|
-
import {
|
|
36
|
-
makeRestProtocol,
|
|
37
|
-
unwrapRedactedDeep,
|
|
38
|
-
wrapSensitive,
|
|
39
|
-
} from "@distilled.cloud/core/protocol-rest";
|
|
40
|
-
import {
|
|
41
|
-
buildRequest,
|
|
42
|
-
getAnn,
|
|
43
|
-
mapKeys,
|
|
44
|
-
matchTypedError,
|
|
45
|
-
} from "@distilled.cloud/core/protocol-http";
|
|
46
|
-
import {
|
|
47
|
-
HTTP_STATUS_MAP,
|
|
48
|
-
InternalServerError,
|
|
49
|
-
type ConfigError,
|
|
50
|
-
} from "@distilled.cloud/core/errors";
|
|
51
|
-
import {
|
|
52
|
-
failIfStrict,
|
|
53
|
-
validateResponse,
|
|
54
|
-
} from "@distilled.cloud/core/response-validation";
|
|
55
|
-
import { parseRetryAfterForStatus } from "@distilled.cloud/core/retry-after";
|
|
56
54
|
import {
|
|
57
55
|
Credentials,
|
|
58
56
|
DEFAULT_FLY_API_BASE_URL,
|
|
@@ -101,15 +99,10 @@ const flyErrorEnvelope = (body: unknown) => {
|
|
|
101
99
|
if (body === null || typeof body !== "object") return undefined;
|
|
102
100
|
const b = body as Record<string, unknown>;
|
|
103
101
|
const errors = b.errors as Record<string, unknown> | undefined;
|
|
104
|
-
const detail =
|
|
105
|
-
errors && typeof errors.detail === "string" ? errors.detail : undefined;
|
|
102
|
+
const detail = errors && typeof errors.detail === "string" ? errors.detail : undefined;
|
|
106
103
|
return {
|
|
107
104
|
message:
|
|
108
|
-
typeof b.error === "string"
|
|
109
|
-
? b.error
|
|
110
|
-
: typeof b.message === "string"
|
|
111
|
-
? b.message
|
|
112
|
-
: detail,
|
|
105
|
+
typeof b.error === "string" ? b.error : typeof b.message === "string" ? b.message : detail,
|
|
113
106
|
};
|
|
114
107
|
};
|
|
115
108
|
|
|
@@ -118,15 +111,8 @@ const spritesErrorEnvelope = (body: unknown) => {
|
|
|
118
111
|
if (body === null || typeof body !== "object") return undefined;
|
|
119
112
|
const b = body as Record<string, unknown>;
|
|
120
113
|
const message =
|
|
121
|
-
typeof b.message === "string"
|
|
122
|
-
|
|
123
|
-
: typeof b.error === "string"
|
|
124
|
-
? b.error
|
|
125
|
-
: undefined;
|
|
126
|
-
const code =
|
|
127
|
-
typeof b.error === "string" && typeof b.message === "string"
|
|
128
|
-
? b.error
|
|
129
|
-
: undefined;
|
|
114
|
+
typeof b.message === "string" ? b.message : typeof b.error === "string" ? b.error : undefined;
|
|
115
|
+
const code = typeof b.error === "string" && typeof b.message === "string" ? b.error : undefined;
|
|
130
116
|
return { message, code };
|
|
131
117
|
};
|
|
132
118
|
|
|
@@ -177,18 +163,16 @@ export const FlyIoProtocol: Layer.Layer<API.Protocol> = Layer.effect(
|
|
|
177
163
|
).pipe(Layer.provide(FlyIoProtocolRest));
|
|
178
164
|
|
|
179
165
|
/** MPG UI-EX REST at `https://api.fly.io` with the Machines bearer token. */
|
|
180
|
-
export const FlyApiProtocol: Layer.Layer<API.Protocol> =
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
parseError: ({ body, cause }) => new FlyIoParseError({ body, cause }),
|
|
191
|
-
});
|
|
166
|
+
export const FlyApiProtocol: Layer.Layer<API.Protocol> = makeRestProtocol<Config>({
|
|
167
|
+
credentials: resolveFlyCreds,
|
|
168
|
+
baseUrl: () => DEFAULT_FLY_API_BASE_URL,
|
|
169
|
+
headers: (creds) => ({
|
|
170
|
+
Authorization: `Bearer ${Redacted.value(creds.apiKey)}`,
|
|
171
|
+
}),
|
|
172
|
+
errorEnvelope: flyErrorEnvelope,
|
|
173
|
+
unknownError: ({ message, body }) => new UnknownFlyIoError({ message, body }),
|
|
174
|
+
parseError: ({ body, cause }) => new FlyIoParseError({ body, cause }),
|
|
175
|
+
});
|
|
192
176
|
|
|
193
177
|
const parseMaybeNdjson = (body: unknown): unknown => {
|
|
194
178
|
if (typeof body !== "string") return body;
|
|
@@ -234,8 +218,7 @@ const parseSpritesExecFrames = (
|
|
|
234
218
|
return { stdout, stderr, exit_code };
|
|
235
219
|
};
|
|
236
220
|
|
|
237
|
-
const fail = (e: unknown): Effect.Effect<never> =>
|
|
238
|
-
Effect.fail(e) as Effect.Effect<never>;
|
|
221
|
+
const fail = (e: unknown): Effect.Effect<never> => Effect.fail(e) as Effect.Effect<never>;
|
|
239
222
|
|
|
240
223
|
/** Strip a leading `FlyV1` / `Bearer` scheme so we can re-prefix `FlyV1`. */
|
|
241
224
|
const stripFlyAuthScheme = (token: string): string => {
|
|
@@ -256,9 +239,7 @@ const isMintOp = (http: HttpTrait | undefined): boolean =>
|
|
|
256
239
|
|
|
257
240
|
const SPRITES_NOT_ENABLED = /sprites not enabled/i;
|
|
258
241
|
|
|
259
|
-
const readResponseText = (
|
|
260
|
-
response: HttpClientResponse.HttpClientResponse,
|
|
261
|
-
): Effect.Effect<string> =>
|
|
242
|
+
const readResponseText = (response: HttpClientResponse.HttpClientResponse): Effect.Effect<string> =>
|
|
262
243
|
response.text.pipe(
|
|
263
244
|
Effect.orDie,
|
|
264
245
|
Effect.map((text) => text ?? ""),
|
|
@@ -293,8 +274,7 @@ const failHttp = (
|
|
|
293
274
|
headers: Record<string, string | undefined>,
|
|
294
275
|
): Effect.Effect<never> => {
|
|
295
276
|
const env = errorEnv(body);
|
|
296
|
-
const message =
|
|
297
|
-
env.message ?? (text.trim().length > 0 ? text.trim() : `HTTP ${status}`);
|
|
277
|
+
const message = env.message ?? (text.trim().length > 0 ? text.trim() : `HTTP ${status}`);
|
|
298
278
|
if (status === 401 && SPRITES_NOT_ENABLED.test(haystackOf(body, message))) {
|
|
299
279
|
return fail(new SpritesNotEnabled({ message }));
|
|
300
280
|
}
|
|
@@ -335,13 +315,11 @@ const orgFromGraphql = (body: unknown): string | undefined => {
|
|
|
335
315
|
if (data === null || typeof data !== "object") return undefined;
|
|
336
316
|
const viewer = (data as { viewer?: unknown }).viewer;
|
|
337
317
|
const root = viewer !== null && typeof viewer === "object" ? viewer : data;
|
|
338
|
-
const personal = (root as { personalOrganization?: { slug?: unknown } })
|
|
339
|
-
.personalOrganization;
|
|
318
|
+
const personal = (root as { personalOrganization?: { slug?: unknown } }).personalOrganization;
|
|
340
319
|
if (typeof personal?.slug === "string" && personal.slug.length > 0) {
|
|
341
320
|
return personal.slug;
|
|
342
321
|
}
|
|
343
|
-
const nodes = (root as { organizations?: { nodes?: unknown } }).organizations
|
|
344
|
-
?.nodes;
|
|
322
|
+
const nodes = (root as { organizations?: { nodes?: unknown } }).organizations?.nodes;
|
|
345
323
|
if (Array.isArray(nodes)) {
|
|
346
324
|
for (const node of nodes) {
|
|
347
325
|
if (
|
|
@@ -360,13 +338,10 @@ const orgFromGraphql = (body: unknown): string | undefined => {
|
|
|
360
338
|
const discoverOrgSlug = (fly: Config) =>
|
|
361
339
|
Effect.gen(function* () {
|
|
362
340
|
const http = yield* HttpClient.HttpClient;
|
|
363
|
-
const token = Redacted.value(fly.apiKey);
|
|
364
341
|
const machinesRoot = fly.apiBaseUrl.replace(/\/+$/, "");
|
|
365
|
-
const currentReq = HttpClientRequest.make("GET")(
|
|
366
|
-
`${machinesRoot}/v1/tokens/current`,
|
|
367
|
-
).pipe(
|
|
342
|
+
const currentReq = HttpClientRequest.make("GET")(`${machinesRoot}/v1/tokens/current`).pipe(
|
|
368
343
|
HttpClientRequest.setHeaders({
|
|
369
|
-
Authorization: `Bearer ${
|
|
344
|
+
Authorization: `Bearer ${Redacted.value(fly.apiKey)}`,
|
|
370
345
|
Accept: "application/json",
|
|
371
346
|
}),
|
|
372
347
|
);
|
|
@@ -378,16 +353,13 @@ const discoverOrgSlug = (fly: Config) =>
|
|
|
378
353
|
if (slug !== undefined) return slug;
|
|
379
354
|
}
|
|
380
355
|
|
|
381
|
-
const gqlReq = HttpClientRequest.make("POST")(
|
|
382
|
-
`${DEFAULT_FLY_API_BASE_URL}/graphql`,
|
|
383
|
-
).pipe(
|
|
356
|
+
const gqlReq = HttpClientRequest.make("POST")(`${DEFAULT_FLY_API_BASE_URL}/graphql`).pipe(
|
|
384
357
|
HttpClientRequest.setHeaders({
|
|
385
|
-
Authorization: `Bearer ${
|
|
358
|
+
Authorization: `Bearer ${Redacted.value(fly.apiKey)}`,
|
|
386
359
|
Accept: "application/json",
|
|
387
360
|
}),
|
|
388
361
|
HttpClientRequest.bodyJsonUnsafe({
|
|
389
|
-
query:
|
|
390
|
-
"{ viewer { personalOrganization { slug } organizations { nodes { slug } } } }",
|
|
362
|
+
query: "{ viewer { personalOrganization { slug } organizations { nodes { slug } } } }",
|
|
391
363
|
}),
|
|
392
364
|
);
|
|
393
365
|
const gqlRes = yield* http.execute(gqlReq);
|
|
@@ -399,8 +371,7 @@ const discoverOrgSlug = (fly: Config) =>
|
|
|
399
371
|
}
|
|
400
372
|
|
|
401
373
|
return yield* new FlyConfigError({
|
|
402
|
-
message:
|
|
403
|
-
"Could not discover a Fly organization slug from /tokens/current or GraphQL",
|
|
374
|
+
message: "Could not discover a Fly organization slug from /tokens/current or GraphQL",
|
|
404
375
|
});
|
|
405
376
|
});
|
|
406
377
|
|
|
@@ -429,9 +400,7 @@ const mintOnce = (fly: Config) =>
|
|
|
429
400
|
return yield* failHttp(response.status, json, text, headers);
|
|
430
401
|
}
|
|
431
402
|
const token =
|
|
432
|
-
json !== null && typeof json === "object"
|
|
433
|
-
? (json as { token?: unknown }).token
|
|
434
|
-
: undefined;
|
|
403
|
+
json !== null && typeof json === "object" ? (json as { token?: unknown }).token : undefined;
|
|
435
404
|
if (typeof token !== "string" || token.length === 0) {
|
|
436
405
|
return yield* fail(
|
|
437
406
|
new FlyIoParseError({
|
|
@@ -440,36 +409,40 @@ const mintOnce = (fly: Config) =>
|
|
|
440
409
|
}),
|
|
441
410
|
);
|
|
442
411
|
}
|
|
443
|
-
|
|
444
|
-
return token;
|
|
412
|
+
return Redacted.make(token);
|
|
445
413
|
});
|
|
446
414
|
|
|
447
|
-
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
415
|
+
// Keyed by the Fly token itself: `Redacted` hashes and compares by value.
|
|
416
|
+
const mintedTokens = MutableHashMap.empty<Redacted.Redacted<string>, Redacted.Redacted<string>>();
|
|
417
|
+
const mintInFlight = MutableHashMap.empty<
|
|
418
|
+
Redacted.Redacted<string>,
|
|
419
|
+
Deferred.Deferred<Redacted.Redacted<string>, Effect.Error<ReturnType<typeof mintOnce>>>
|
|
451
420
|
>();
|
|
452
421
|
|
|
453
422
|
/** Mint (and process-wide cache) a Sprites bearer from `FLY_API_TOKEN`. */
|
|
454
423
|
const mintSpritesToken = (fly: Config) =>
|
|
455
424
|
Effect.uninterruptibleMask((restore) =>
|
|
456
425
|
Effect.suspend(() => {
|
|
457
|
-
const key =
|
|
458
|
-
const hit =
|
|
459
|
-
if (hit
|
|
460
|
-
const pending =
|
|
461
|
-
if (
|
|
426
|
+
const key = fly.apiKey;
|
|
427
|
+
const hit = MutableHashMap.get(mintedTokens, key);
|
|
428
|
+
if (Option.isSome(hit)) return Effect.succeed(hit.value);
|
|
429
|
+
const pending = MutableHashMap.get(mintInFlight, key);
|
|
430
|
+
if (Option.isSome(pending)) {
|
|
431
|
+
return restore(Deferred.await(pending.value));
|
|
432
|
+
}
|
|
462
433
|
const result = Deferred.makeUnsafe<
|
|
463
|
-
string
|
|
434
|
+
Redacted.Redacted<string>,
|
|
464
435
|
Effect.Error<ReturnType<typeof mintOnce>>
|
|
465
436
|
>();
|
|
466
|
-
|
|
437
|
+
MutableHashMap.set(mintInFlight, key, result);
|
|
467
438
|
return restore(mintOnce(fly)).pipe(
|
|
468
439
|
Effect.onExit((exit) =>
|
|
469
440
|
Effect.gen(function* () {
|
|
470
|
-
if (Exit.isSuccess(exit))
|
|
441
|
+
if (Exit.isSuccess(exit)) {
|
|
442
|
+
MutableHashMap.set(mintedTokens, key, exit.value);
|
|
443
|
+
}
|
|
471
444
|
// Release all waiters, including on defects and owner interruption.
|
|
472
|
-
|
|
445
|
+
MutableHashMap.remove(mintInFlight, key);
|
|
473
446
|
yield* Deferred.done(result, exit);
|
|
474
447
|
}),
|
|
475
448
|
),
|
|
@@ -493,7 +466,7 @@ const encodeSpritesRequest = ({
|
|
|
493
466
|
authorization = `FlyV1 ${stripFlyAuthScheme(Redacted.value(fly.apiKey))}`;
|
|
494
467
|
} else {
|
|
495
468
|
const token = yield* mintSpritesToken(fly);
|
|
496
|
-
authorization = `Bearer ${token}`;
|
|
469
|
+
authorization = `Bearer ${Redacted.value(token)}`;
|
|
497
470
|
}
|
|
498
471
|
return buildRequest({
|
|
499
472
|
input: unwrapRedactedDeep(input),
|
|
@@ -516,9 +489,7 @@ const decodeSpritesResponse = ({
|
|
|
516
489
|
readonly errors: ReadonlyArray<unknown>;
|
|
517
490
|
}) =>
|
|
518
491
|
Effect.gen(function* () {
|
|
519
|
-
const buffer = yield* response.arrayBuffer.pipe(
|
|
520
|
-
Effect.map((bytes) => new Uint8Array(bytes)),
|
|
521
|
-
);
|
|
492
|
+
const buffer = yield* response.arrayBuffer.pipe(Effect.map((bytes) => new Uint8Array(bytes)));
|
|
522
493
|
const text = new TextDecoder().decode(buffer);
|
|
523
494
|
const execFrames = parseSpritesExecFrames(buffer);
|
|
524
495
|
let json: unknown;
|
|
@@ -535,12 +506,8 @@ const decodeSpritesResponse = ({
|
|
|
535
506
|
|
|
536
507
|
if (status >= 400) {
|
|
537
508
|
const env = nonJson ? {} : errorEnv(json);
|
|
538
|
-
const message =
|
|
539
|
-
|
|
540
|
-
(nonJson && text.trim() ? text.trim() : `HTTP ${status}`);
|
|
541
|
-
if (
|
|
542
|
-
SPRITES_NOT_ENABLED.test(haystackOf(nonJson ? text : json, message))
|
|
543
|
-
) {
|
|
509
|
+
const message = env.message ?? (nonJson && text.trim() ? text.trim() : `HTTP ${status}`);
|
|
510
|
+
if (SPRITES_NOT_ENABLED.test(haystackOf(nonJson ? text : json, message))) {
|
|
544
511
|
return yield* fail(new SpritesNotEnabled({ message }));
|
|
545
512
|
}
|
|
546
513
|
const typed = matchTypedError(
|
|
@@ -556,9 +523,7 @@ const decodeSpritesResponse = ({
|
|
|
556
523
|
);
|
|
557
524
|
if (typed !== undefined) return yield* fail(typed);
|
|
558
525
|
|
|
559
|
-
const StatusErrorClass = (HTTP_STATUS_MAP as Record<number, unknown>)[
|
|
560
|
-
status
|
|
561
|
-
] as
|
|
526
|
+
const StatusErrorClass = (HTTP_STATUS_MAP as Record<number, unknown>)[status] as
|
|
562
527
|
| (new (args: {
|
|
563
528
|
message: string;
|
|
564
529
|
retryAfter?: ReturnType<typeof parseRetryAfterForStatus>;
|
|
@@ -590,8 +555,7 @@ const decodeSpritesResponse = ({
|
|
|
590
555
|
|
|
591
556
|
// Strict mode checks the mapped body (or parsed exec frames) against the
|
|
592
557
|
// output schema.
|
|
593
|
-
const body: unknown =
|
|
594
|
-
execFrames ?? parseMaybeNdjson(nonJson ? text : (json ?? {}));
|
|
558
|
+
const body: unknown = execFrames ?? parseMaybeNdjson(nonJson ? text : (json ?? {}));
|
|
595
559
|
const mapped = yield* validateResponse(
|
|
596
560
|
outputAst,
|
|
597
561
|
mapKeys(outputAst, body, "decode"),
|
|
@@ -609,9 +573,7 @@ export const SpritesProtocol: Layer.Layer<API.Protocol> = Layer.succeed(
|
|
|
609
573
|
API.Protocol,
|
|
610
574
|
API.Protocol.of({
|
|
611
575
|
encode: (args) =>
|
|
612
|
-
encodeSpritesRequest(
|
|
613
|
-
args,
|
|
614
|
-
) as Effect.Effect<HttpClientRequest.HttpClientRequest>,
|
|
576
|
+
encodeSpritesRequest(args) as Effect.Effect<HttpClientRequest.HttpClientRequest>,
|
|
615
577
|
decode: (args) => decodeSpritesResponse(args) as Effect.Effect<unknown>,
|
|
616
578
|
}),
|
|
617
579
|
);
|
|
@@ -652,9 +614,7 @@ const matchGraphqlError = (
|
|
|
652
614
|
headers,
|
|
653
615
|
});
|
|
654
616
|
if (typed !== undefined) return fail(typed);
|
|
655
|
-
if (
|
|
656
|
-
/not authorized to access this createextensiontosagreement/i.test(message)
|
|
657
|
-
) {
|
|
617
|
+
if (/not authorized to access this createextensiontosagreement/i.test(message)) {
|
|
658
618
|
return fail(new CreateExtensionTosAgreementNotAuthorized({ message }));
|
|
659
619
|
}
|
|
660
620
|
const StatusClass = (HTTP_STATUS_MAP as Record<number, unknown>)[status] as
|
|
@@ -713,9 +673,7 @@ const graphqlEncode = ({
|
|
|
713
673
|
}
|
|
714
674
|
const http = getAnn(inputAst, httpSymbol) as HttpTrait | undefined;
|
|
715
675
|
const variables: Record<string, unknown> = {};
|
|
716
|
-
for (const [k, v] of Object.entries(
|
|
717
|
-
(input ?? {}) as Record<string, unknown>,
|
|
718
|
-
)) {
|
|
676
|
+
for (const [k, v] of Object.entries((input ?? {}) as Record<string, unknown>)) {
|
|
719
677
|
if (v !== undefined) variables[k] = v;
|
|
720
678
|
}
|
|
721
679
|
const url = `${DEFAULT_FLY_API_BASE_URL}${http?.uri ?? "/graphql"}`;
|
|
@@ -783,9 +741,7 @@ const graphqlDecode = ({
|
|
|
783
741
|
|
|
784
742
|
const path = getAnn(outputAst, responsePathSymbol) as string | undefined;
|
|
785
743
|
let payload: unknown =
|
|
786
|
-
envelope !== null && typeof envelope === "object"
|
|
787
|
-
? envelope.data
|
|
788
|
-
: undefined;
|
|
744
|
+
envelope !== null && typeof envelope === "object" ? envelope.data : undefined;
|
|
789
745
|
if (path !== undefined) {
|
|
790
746
|
for (const seg of path.split(".")) {
|
|
791
747
|
payload =
|
|
@@ -806,8 +762,7 @@ const graphqlDecode = ({
|
|
|
806
762
|
export const FlyGraphqlProtocol: Layer.Layer<API.Protocol> = Layer.succeed(
|
|
807
763
|
API.Protocol,
|
|
808
764
|
API.Protocol.of({
|
|
809
|
-
encode: (args) =>
|
|
810
|
-
graphqlEncode(args) as Effect.Effect<HttpClientRequest.HttpClientRequest>,
|
|
765
|
+
encode: (args) => graphqlEncode(args) as Effect.Effect<HttpClientRequest.HttpClientRequest>,
|
|
811
766
|
decode: graphqlDecode,
|
|
812
767
|
}),
|
|
813
768
|
);
|
package/src/retry.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Policy, throttlingFactory, transientFactory } from "@distilled.cloud/core/retry";
|
|
1
2
|
/**
|
|
2
3
|
* FlyIo 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);
|