@distilled.cloud/core 1.0.0-rc.1 → 1.0.0-rc.10
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/LICENSE +201 -0
- package/lib/api.d.ts.map +1 -1
- package/lib/api.js +16 -4
- package/lib/api.js.map +1 -1
- package/lib/category.d.ts +4 -4
- package/lib/category.js +4 -4
- package/lib/codegen/boolean-string-enums.d.ts +36 -0
- package/lib/codegen/boolean-string-enums.d.ts.map +1 -0
- package/lib/codegen/boolean-string-enums.js +94 -0
- package/lib/codegen/boolean-string-enums.js.map +1 -0
- package/lib/codegen/boolean-string-enums.test.d.ts +2 -0
- package/lib/codegen/boolean-string-enums.test.d.ts.map +1 -0
- package/lib/codegen/boolean-string-enums.test.js +147 -0
- package/lib/codegen/boolean-string-enums.test.js.map +1 -0
- package/lib/codegen/cli.d.ts +56 -6
- package/lib/codegen/cli.d.ts.map +1 -1
- package/lib/codegen/cli.js +59 -75
- package/lib/codegen/cli.js.map +1 -1
- package/lib/codegen/emit.d.ts +3 -7
- package/lib/codegen/emit.d.ts.map +1 -1
- package/lib/codegen/emit.js +6 -10
- package/lib/codegen/emit.js.map +1 -1
- package/lib/codegen/generator.d.ts.map +1 -1
- package/lib/codegen/generator.js +142 -20
- package/lib/codegen/generator.js.map +1 -1
- package/lib/codegen/graphql-client.d.ts +62 -0
- package/lib/codegen/graphql-client.d.ts.map +1 -0
- package/lib/codegen/graphql-client.js +294 -0
- package/lib/codegen/graphql-client.js.map +1 -0
- package/lib/codegen/graphql-client.test.d.ts +2 -0
- package/lib/codegen/graphql-client.test.d.ts.map +1 -0
- package/lib/codegen/graphql-client.test.js +311 -0
- package/lib/codegen/graphql-client.test.js.map +1 -0
- package/lib/codegen/graphql.d.ts +207 -0
- package/lib/codegen/graphql.d.ts.map +1 -0
- package/lib/codegen/graphql.js +799 -0
- package/lib/codegen/graphql.js.map +1 -0
- package/lib/codegen/openapi-cli.d.ts +17 -3
- package/lib/codegen/openapi-cli.d.ts.map +1 -1
- package/lib/codegen/openapi-cli.js +50 -48
- package/lib/codegen/openapi-cli.js.map +1 -1
- package/lib/codegen/openapi.d.ts +69 -6
- package/lib/codegen/openapi.d.ts.map +1 -1
- package/lib/codegen/openapi.js +173 -16
- package/lib/codegen/openapi.js.map +1 -1
- package/lib/codegen/patches.d.ts +65 -0
- package/lib/codegen/patches.d.ts.map +1 -0
- package/lib/codegen/patches.js +236 -0
- package/lib/codegen/patches.js.map +1 -0
- package/lib/codegen/patches.test.d.ts +2 -0
- package/lib/codegen/patches.test.d.ts.map +1 -0
- package/lib/codegen/patches.test.js +105 -0
- package/lib/codegen/patches.test.js.map +1 -0
- package/lib/codegen/proto.d.ts +121 -0
- package/lib/codegen/proto.d.ts.map +1 -0
- package/lib/codegen/proto.js +962 -0
- package/lib/codegen/proto.js.map +1 -0
- package/lib/codegen/rewrite-operation-ids.d.ts +131 -0
- package/lib/codegen/rewrite-operation-ids.d.ts.map +1 -0
- package/lib/codegen/rewrite-operation-ids.js +1079 -0
- package/lib/codegen/rewrite-operation-ids.js.map +1 -0
- package/lib/codegen/rewrite-operation-ids.test.d.ts +2 -0
- package/lib/codegen/rewrite-operation-ids.test.d.ts.map +1 -0
- package/lib/codegen/rewrite-operation-ids.test.js +533 -0
- package/lib/codegen/rewrite-operation-ids.test.js.map +1 -0
- package/lib/codegen/spec-path.d.ts +16 -0
- package/lib/codegen/spec-path.d.ts.map +1 -0
- package/lib/codegen/spec-path.js +101 -0
- package/lib/codegen/spec-path.js.map +1 -0
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +17 -13
- package/lib/errors.js.map +1 -1
- package/lib/graphql.d.ts +284 -0
- package/lib/graphql.d.ts.map +1 -0
- package/lib/graphql.fixture.d.ts +249 -0
- package/lib/graphql.fixture.d.ts.map +1 -0
- package/lib/graphql.fixture.js +240 -0
- package/lib/graphql.fixture.js.map +1 -0
- package/lib/graphql.js +718 -0
- package/lib/graphql.js.map +1 -0
- package/lib/graphql.test.d.ts +2 -0
- package/lib/graphql.test.d.ts.map +1 -0
- package/lib/graphql.test.js +780 -0
- package/lib/graphql.test.js.map +1 -0
- package/lib/graphql.types.d.ts +2 -0
- package/lib/graphql.types.d.ts.map +1 -0
- package/lib/graphql.types.js +45 -0
- package/lib/graphql.types.js.map +1 -0
- package/lib/json-patch.d.ts +18 -11
- package/lib/json-patch.d.ts.map +1 -1
- package/lib/json-patch.js +63 -25
- package/lib/json-patch.js.map +1 -1
- package/lib/pagination.d.ts +43 -3
- package/lib/pagination.d.ts.map +1 -1
- package/lib/pagination.js +91 -5
- package/lib/pagination.js.map +1 -1
- package/lib/protocol-http.d.ts.map +1 -1
- package/lib/protocol-http.js +62 -26
- package/lib/protocol-http.js.map +1 -1
- package/lib/protocol-http.test.d.ts +2 -0
- package/lib/protocol-http.test.d.ts.map +1 -0
- package/lib/protocol-http.test.js +88 -0
- package/lib/protocol-http.test.js.map +1 -0
- package/lib/protocol-rest.d.ts +12 -2
- package/lib/protocol-rest.d.ts.map +1 -1
- package/lib/protocol-rest.js +17 -3
- package/lib/protocol-rest.js.map +1 -1
- package/lib/retry.js +1 -1
- package/lib/schema.d.ts +1 -1
- package/lib/schema.d.ts.map +1 -1
- package/lib/schema.js +1 -1
- package/lib/schema.js.map +1 -1
- package/lib/trait.d.ts +27 -3
- package/lib/trait.d.ts.map +1 -1
- package/lib/trait.js +17 -1
- package/lib/trait.js.map +1 -1
- package/package.json +13 -10
- package/src/api.ts +18 -4
- package/src/category.ts +4 -4
- package/src/codegen/boolean-string-enums.test.ts +168 -0
- package/src/codegen/boolean-string-enums.ts +106 -0
- package/src/codegen/cli.ts +127 -110
- package/src/codegen/emit.ts +6 -10
- package/src/codegen/generator.ts +151 -21
- package/src/codegen/graphql-client.test.ts +386 -0
- package/src/codegen/graphql-client.ts +419 -0
- package/src/codegen/graphql.ts +1217 -0
- package/src/codegen/openapi-cli.ts +75 -59
- package/src/codegen/openapi.ts +255 -16
- package/src/codegen/patches.test.ts +130 -0
- package/src/codegen/patches.ts +291 -0
- package/src/codegen/proto.ts +1128 -0
- package/src/codegen/rewrite-operation-ids.test.ts +563 -0
- package/src/codegen/rewrite-operation-ids.ts +1206 -0
- package/src/codegen/spec-path.ts +115 -0
- package/src/errors.ts +20 -25
- package/src/graphql.fixture.ts +371 -0
- package/src/graphql.test.ts +974 -0
- package/src/graphql.ts +1321 -0
- package/src/graphql.types.ts +185 -0
- package/src/json-patch.ts +82 -25
- package/src/pagination.ts +134 -7
- package/src/protocol-http.test.ts +107 -0
- package/src/protocol-http.ts +67 -31
- package/src/protocol-rest.ts +28 -4
- package/src/retry.ts +1 -1
- package/src/schema.ts +2 -2
- package/src/trait.ts +39 -3
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec path resolution — the seam between a production spec mirror and a
|
|
3
|
+
* local working copy of one (dev-time only).
|
|
4
|
+
*
|
|
5
|
+
* Every SDK package reads its specs from `packages/<pkg>/specs/`. In
|
|
6
|
+
* production that directory holds a submodule of the package's mirror
|
|
7
|
+
* repository, `distilled-mirror/spec-mirror-<pkg>`, whose layout is fixed:
|
|
8
|
+
*
|
|
9
|
+
* packages/<pkg>/specs/spec-mirror-<pkg>/
|
|
10
|
+
* ├── .meta/ fetch-specs.ts + its package.json
|
|
11
|
+
* └── specs/ what the generator reads
|
|
12
|
+
*
|
|
13
|
+
* A contributor adding a provider cannot create that repository — it lives in
|
|
14
|
+
* an org they have no write access to, and it is only created once the
|
|
15
|
+
* `distilled-submodules` stack deploys on merge to main. So `pnpm specs:local
|
|
16
|
+
* <pkg>` runs the same `fetch-specs.ts` into a gitignored directory shaped
|
|
17
|
+
* exactly like the mirror:
|
|
18
|
+
*
|
|
19
|
+
* packages/<pkg>/specs/.local/
|
|
20
|
+
* ├── .meta/
|
|
21
|
+
* └── specs/
|
|
22
|
+
*
|
|
23
|
+
* Setting {@link LOCAL_ENV} then re-roots every spec read into it. Nothing in
|
|
24
|
+
* the package's source changes — the `specPath` a `convert.ts` declares stays
|
|
25
|
+
* the production one — so there is no `.local` reference that could be
|
|
26
|
+
* committed by accident, and the switch is impossible to leave on: it lives
|
|
27
|
+
* in the environment of one command, never in a file.
|
|
28
|
+
*
|
|
29
|
+
* The opt-in is deliberate rather than a fallback-when-missing. A silent
|
|
30
|
+
* fallback would regenerate an SDK from a stale `.local` copy the moment a
|
|
31
|
+
* submodule failed to check out, and the result — committed, formatted,
|
|
32
|
+
* plausible — would be indistinguishable from a real regeneration.
|
|
33
|
+
*/
|
|
34
|
+
import * as fs from "node:fs";
|
|
35
|
+
import * as path from "node:path";
|
|
36
|
+
|
|
37
|
+
/** Set to a non-empty value to read specs from `specs/.local` instead. */
|
|
38
|
+
export const LOCAL_ENV = "DISTILLED_SPECS_LOCAL";
|
|
39
|
+
|
|
40
|
+
/** The local working copy of a mirror, relative to a package root. */
|
|
41
|
+
export const LOCAL_DIR = path.join("specs", ".local");
|
|
42
|
+
|
|
43
|
+
/** Repository name of the mirror feeding `packages/<pkg>`. */
|
|
44
|
+
export const mirrorRepositoryName = (pkg: string) => `spec-mirror-${pkg}`;
|
|
45
|
+
|
|
46
|
+
/** Whether this process reads specs from `specs/.local`. */
|
|
47
|
+
export const isLocalSpecs = (): boolean =>
|
|
48
|
+
(process.env[LOCAL_ENV] ?? "").trim() !== "";
|
|
49
|
+
|
|
50
|
+
let announced = false;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The path within a mirror's `specs/` directory that `specPath` names.
|
|
54
|
+
*
|
|
55
|
+
* Spec paths take one of two shapes — `specs/<mirror>/specs/<tail>` for a
|
|
56
|
+
* submodule and `specs/<tail>` for a committed file — and in both the tail is
|
|
57
|
+
* everything after the LAST `specs` segment. That one rule covers the
|
|
58
|
+
* submodule form, the committed form, the nested forms
|
|
59
|
+
* (`specs/<mirror>/specs/models/<service>/...`) and the directory form
|
|
60
|
+
* (`specs/<mirror>/specs`, whose tail is empty — the mirror's `specs/`
|
|
61
|
+
* directory itself) without needing to know which it was handed.
|
|
62
|
+
*
|
|
63
|
+
* `undefined` means there is no `specs` segment at all, which local mode
|
|
64
|
+
* cannot interpret.
|
|
65
|
+
*/
|
|
66
|
+
const tailWithinSpecs = (specPath: string): string | undefined => {
|
|
67
|
+
const segments = specPath.split(/[/\\]/).filter((s) => s !== "" && s !== ".");
|
|
68
|
+
const last = segments.lastIndexOf("specs");
|
|
69
|
+
if (last === -1) return undefined;
|
|
70
|
+
return segments.slice(last + 1).join(path.sep);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Resolve a package-relative spec path to an absolute one.
|
|
75
|
+
*
|
|
76
|
+
* @param root absolute package root (`path.resolve(import.meta.dir, "..")`)
|
|
77
|
+
* @param specPath the production path, relative to `root` (or absolute)
|
|
78
|
+
*/
|
|
79
|
+
export const resolveSpecPath = (root: string, specPath: string): string => {
|
|
80
|
+
const production = path.resolve(root, specPath);
|
|
81
|
+
if (!isLocalSpecs() || path.isAbsolute(specPath)) return production;
|
|
82
|
+
|
|
83
|
+
const tail = tailWithinSpecs(specPath);
|
|
84
|
+
if (tail === undefined) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`${LOCAL_ENV} is set, but "${specPath}" has no \`specs/\` segment to ` +
|
|
87
|
+
`re-root. Local mode only understands paths under the package's ` +
|
|
88
|
+
`specs/ directory.`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!announced) {
|
|
93
|
+
announced = true;
|
|
94
|
+
// stderr, not stdout: generate-all captures stdout per package and only
|
|
95
|
+
// prints it on failure, and this is exactly the line you need to see on
|
|
96
|
+
// a run that succeeded against the wrong specs.
|
|
97
|
+
console.error(
|
|
98
|
+
`⚠ ${LOCAL_ENV} — reading specs from ${LOCAL_DIR}, not the mirror submodule.`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const local = path.join(root, LOCAL_DIR, "specs", tail);
|
|
103
|
+
if (!fs.existsSync(local)) {
|
|
104
|
+
// A missing local spec is a setup mistake, not a generator bug, and the
|
|
105
|
+
// ENOENT the caller would otherwise raise names a path nobody recognises.
|
|
106
|
+
throw new Error(
|
|
107
|
+
`${local} does not exist. Materialise this package's mirror first:\n` +
|
|
108
|
+
` pnpm specs:local ${path.basename(root)}\n` +
|
|
109
|
+
`If that succeeds and this path is still missing, the package's ` +
|
|
110
|
+
`declared spec path (${specPath}) is not mirror-shaped yet — it must ` +
|
|
111
|
+
`read \`specs/<mirror>/specs/<file>\` for local mode to find it.`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return local;
|
|
115
|
+
};
|
package/src/errors.ts
CHANGED
|
@@ -33,7 +33,7 @@ export const DurationSchema = Schema.declare<Duration.Duration>(
|
|
|
33
33
|
/**
|
|
34
34
|
* Unauthorized - Authentication failure (401).
|
|
35
35
|
*/
|
|
36
|
-
export class Unauthorized extends Schema.
|
|
36
|
+
export class Unauthorized extends Schema.TaggedError<Unauthorized>()(
|
|
37
37
|
"Unauthorized",
|
|
38
38
|
{ message: Schema.String },
|
|
39
39
|
).pipe(Category.withAuthError) {}
|
|
@@ -41,37 +41,35 @@ export class Unauthorized extends Schema.TaggedErrorClass<Unauthorized>()(
|
|
|
41
41
|
/**
|
|
42
42
|
* Forbidden - Access denied (403).
|
|
43
43
|
*/
|
|
44
|
-
export class Forbidden extends Schema.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
).pipe(Category.withAuthError) {}
|
|
44
|
+
export class Forbidden extends Schema.TaggedError<Forbidden>()("Forbidden", {
|
|
45
|
+
message: Schema.String,
|
|
46
|
+
}).pipe(Category.withAuthError) {}
|
|
48
47
|
|
|
49
48
|
/**
|
|
50
49
|
* NotFound - Resource not found (404).
|
|
51
50
|
*/
|
|
52
|
-
export class NotFound extends Schema.
|
|
51
|
+
export class NotFound extends Schema.TaggedError<NotFound>()("NotFound", {
|
|
53
52
|
message: Schema.String,
|
|
54
53
|
}).pipe(Category.withNotFoundError) {}
|
|
55
54
|
|
|
56
55
|
/**
|
|
57
56
|
* BadRequest - Invalid request (400).
|
|
58
57
|
*/
|
|
59
|
-
export class BadRequest extends Schema.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
).pipe(Category.withBadRequestError) {}
|
|
58
|
+
export class BadRequest extends Schema.TaggedError<BadRequest>()("BadRequest", {
|
|
59
|
+
message: Schema.String,
|
|
60
|
+
}).pipe(Category.withBadRequestError) {}
|
|
63
61
|
|
|
64
62
|
/**
|
|
65
63
|
* Conflict - Resource conflict (409).
|
|
66
64
|
*/
|
|
67
|
-
export class Conflict extends Schema.
|
|
65
|
+
export class Conflict extends Schema.TaggedError<Conflict>()("Conflict", {
|
|
68
66
|
message: Schema.String,
|
|
69
67
|
}).pipe(Category.withConflictError) {}
|
|
70
68
|
|
|
71
69
|
/**
|
|
72
70
|
* UnprocessableEntity - Validation error (422).
|
|
73
71
|
*/
|
|
74
|
-
export class UnprocessableEntity extends Schema.
|
|
72
|
+
export class UnprocessableEntity extends Schema.TaggedError<UnprocessableEntity>()(
|
|
75
73
|
"UnprocessableEntity",
|
|
76
74
|
{ message: Schema.String },
|
|
77
75
|
).pipe(Category.withBadRequestError) {}
|
|
@@ -79,7 +77,7 @@ export class UnprocessableEntity extends Schema.TaggedErrorClass<UnprocessableEn
|
|
|
79
77
|
/**
|
|
80
78
|
* TooManyRequests - Rate limited (429).
|
|
81
79
|
*/
|
|
82
|
-
export class TooManyRequests extends Schema.
|
|
80
|
+
export class TooManyRequests extends Schema.TaggedError<TooManyRequests>()(
|
|
83
81
|
"TooManyRequests",
|
|
84
82
|
{
|
|
85
83
|
message: Schema.String,
|
|
@@ -93,7 +91,7 @@ export class TooManyRequests extends Schema.TaggedErrorClass<TooManyRequests>()(
|
|
|
93
91
|
/**
|
|
94
92
|
* Locked - Resource locked (423).
|
|
95
93
|
*/
|
|
96
|
-
export class Locked extends Schema.
|
|
94
|
+
export class Locked extends Schema.TaggedError<Locked>()("Locked", {
|
|
97
95
|
message: Schema.String,
|
|
98
96
|
retryAfter: Schema.optional(DurationSchema),
|
|
99
97
|
}).pipe(Category.withLockedError, Category.withRetryable()) {}
|
|
@@ -106,7 +104,7 @@ export class Locked extends Schema.TaggedErrorClass<Locked>()("Locked", {
|
|
|
106
104
|
* 200 envelope carrying `{ code: 10002, message: "An unknown error has
|
|
107
105
|
* occurred" }` for transient backend failures on some endpoints).
|
|
108
106
|
*/
|
|
109
|
-
export class InternalServerError extends Schema.
|
|
107
|
+
export class InternalServerError extends Schema.TaggedError<InternalServerError>()(
|
|
110
108
|
"InternalServerError",
|
|
111
109
|
{
|
|
112
110
|
message: Schema.String,
|
|
@@ -118,18 +116,15 @@ export class InternalServerError extends Schema.TaggedErrorClass<InternalServerE
|
|
|
118
116
|
/**
|
|
119
117
|
* BadGateway - Bad gateway (502).
|
|
120
118
|
*/
|
|
121
|
-
export class BadGateway extends Schema.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
retryAfter: Schema.optional(DurationSchema),
|
|
126
|
-
},
|
|
127
|
-
).pipe(Category.withServerError, Category.withRetryable()) {}
|
|
119
|
+
export class BadGateway extends Schema.TaggedError<BadGateway>()("BadGateway", {
|
|
120
|
+
message: Schema.String,
|
|
121
|
+
retryAfter: Schema.optional(DurationSchema),
|
|
122
|
+
}).pipe(Category.withServerError, Category.withRetryable()) {}
|
|
128
123
|
|
|
129
124
|
/**
|
|
130
125
|
* ServiceUnavailable - Service unavailable (503).
|
|
131
126
|
*/
|
|
132
|
-
export class ServiceUnavailable extends Schema.
|
|
127
|
+
export class ServiceUnavailable extends Schema.TaggedError<ServiceUnavailable>()(
|
|
133
128
|
"ServiceUnavailable",
|
|
134
129
|
{
|
|
135
130
|
message: Schema.String,
|
|
@@ -140,7 +135,7 @@ export class ServiceUnavailable extends Schema.TaggedErrorClass<ServiceUnavailab
|
|
|
140
135
|
/**
|
|
141
136
|
* GatewayTimeout - Gateway timeout (504).
|
|
142
137
|
*/
|
|
143
|
-
export class GatewayTimeout extends Schema.
|
|
138
|
+
export class GatewayTimeout extends Schema.TaggedError<GatewayTimeout>()(
|
|
144
139
|
"GatewayTimeout",
|
|
145
140
|
{
|
|
146
141
|
message: Schema.String,
|
|
@@ -151,7 +146,7 @@ export class GatewayTimeout extends Schema.TaggedErrorClass<GatewayTimeout>()(
|
|
|
151
146
|
/**
|
|
152
147
|
* Configuration error - missing or invalid configuration.
|
|
153
148
|
*/
|
|
154
|
-
export class ConfigError extends Schema.
|
|
149
|
+
export class ConfigError extends Schema.TaggedError<ConfigError>()(
|
|
155
150
|
"ConfigError",
|
|
156
151
|
{ message: Schema.String },
|
|
157
152
|
).pipe(Category.withConfigurationError) {}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
import * as G from "./graphql.ts";
|
|
3
|
+
import type { GraphQLField, GraphQLModel } from "./codegen/graphql-client.ts";
|
|
4
|
+
|
|
5
|
+
export class ProjectNotFound extends Schema.TaggedError<ProjectNotFound>()(
|
|
6
|
+
"ProjectNotFound",
|
|
7
|
+
G.errorFields,
|
|
8
|
+
) {}
|
|
9
|
+
export class ServicesUnavailable extends Schema.TaggedError<ServicesUnavailable>()(
|
|
10
|
+
"ServicesUnavailable",
|
|
11
|
+
G.errorFields,
|
|
12
|
+
) {}
|
|
13
|
+
export class Unauthorized extends Schema.TaggedError<Unauthorized>()(
|
|
14
|
+
"Unauthorized",
|
|
15
|
+
G.errorFields,
|
|
16
|
+
) {}
|
|
17
|
+
export class ProjectDescriptionUnavailable extends Schema.TaggedError<ProjectDescriptionUnavailable>()(
|
|
18
|
+
"ProjectDescriptionUnavailable",
|
|
19
|
+
G.errorFields,
|
|
20
|
+
) {}
|
|
21
|
+
export class ServiceDescriptionUnavailable extends Schema.TaggedError<ServiceDescriptionUnavailable>()(
|
|
22
|
+
"ServiceDescriptionUnavailable",
|
|
23
|
+
G.errorFields,
|
|
24
|
+
) {}
|
|
25
|
+
export class PageInfoUnavailable extends Schema.TaggedError<PageInfoUnavailable>()(
|
|
26
|
+
"PageInfoUnavailable",
|
|
27
|
+
G.errorFields,
|
|
28
|
+
) {}
|
|
29
|
+
|
|
30
|
+
export const errorClasses = {
|
|
31
|
+
ProjectNotFound,
|
|
32
|
+
ServicesUnavailable,
|
|
33
|
+
Unauthorized,
|
|
34
|
+
ProjectDescriptionUnavailable,
|
|
35
|
+
ServiceDescriptionUnavailable,
|
|
36
|
+
PageInfoUnavailable,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type FixtureSchema = {
|
|
40
|
+
query: "Query";
|
|
41
|
+
mutation: "Mutation";
|
|
42
|
+
subscription: never;
|
|
43
|
+
globalErrors: "Unauthorized";
|
|
44
|
+
errors: {
|
|
45
|
+
ProjectNotFound: ProjectNotFound;
|
|
46
|
+
ServicesUnavailable: ServicesUnavailable;
|
|
47
|
+
Unauthorized: Unauthorized;
|
|
48
|
+
ProjectDescriptionUnavailable: ProjectDescriptionUnavailable;
|
|
49
|
+
ServiceDescriptionUnavailable: ServiceDescriptionUnavailable;
|
|
50
|
+
PageInfoUnavailable: PageInfoUnavailable;
|
|
51
|
+
};
|
|
52
|
+
scalars: {
|
|
53
|
+
ID: string;
|
|
54
|
+
String: string;
|
|
55
|
+
Int: number;
|
|
56
|
+
Boolean: boolean;
|
|
57
|
+
JSON: unknown;
|
|
58
|
+
Status: "ACTIVE" | "ARCHIVED";
|
|
59
|
+
};
|
|
60
|
+
possibleTypes: {
|
|
61
|
+
Node: "Project" | "Service";
|
|
62
|
+
SearchResult: "Project" | "Service";
|
|
63
|
+
};
|
|
64
|
+
types: {
|
|
65
|
+
Query: {
|
|
66
|
+
project: G.Field<{ id: string }, "Project", "ProjectNotFound">;
|
|
67
|
+
projects: G.Field<
|
|
68
|
+
{
|
|
69
|
+
filter?: {
|
|
70
|
+
name?: string | null;
|
|
71
|
+
statuses?: Array<"ACTIVE" | "ARCHIVED"> | null;
|
|
72
|
+
metadata?: unknown;
|
|
73
|
+
} | null;
|
|
74
|
+
},
|
|
75
|
+
"[Project]!"
|
|
76
|
+
>;
|
|
77
|
+
node: G.Field<{ id: string }, "Node">;
|
|
78
|
+
search: G.Field<{ text: string }, "[SearchResult!]!">;
|
|
79
|
+
services: G.Field<
|
|
80
|
+
{ first?: number | null; after?: string | null },
|
|
81
|
+
"ServiceConnection!",
|
|
82
|
+
"ServicesUnavailable"
|
|
83
|
+
>;
|
|
84
|
+
ping: G.Field<{}, "Boolean!">;
|
|
85
|
+
};
|
|
86
|
+
Mutation: {
|
|
87
|
+
editProject: G.Field<
|
|
88
|
+
{ id: string; name: string },
|
|
89
|
+
"Project!",
|
|
90
|
+
"ProjectNotFound"
|
|
91
|
+
>;
|
|
92
|
+
deleteProject: G.Field<{ id: string }, "Boolean!", "ProjectNotFound">;
|
|
93
|
+
};
|
|
94
|
+
Project: {
|
|
95
|
+
id: G.Field<{}, "ID!">;
|
|
96
|
+
name: G.Field<{}, "String!">;
|
|
97
|
+
description: G.Field<{}, "String", "ProjectDescriptionUnavailable">;
|
|
98
|
+
parent: G.Field<{}, "Project">;
|
|
99
|
+
services: G.Field<
|
|
100
|
+
{
|
|
101
|
+
first?: number | null;
|
|
102
|
+
after?: string | null;
|
|
103
|
+
filter?: { name?: string | null } | null;
|
|
104
|
+
},
|
|
105
|
+
"ServiceConnection",
|
|
106
|
+
"ServicesUnavailable"
|
|
107
|
+
>;
|
|
108
|
+
};
|
|
109
|
+
Service: {
|
|
110
|
+
id: G.Field<{}, "ID!">;
|
|
111
|
+
parent: G.Field<{}, "Project">;
|
|
112
|
+
name: G.Field<{}, "String!">;
|
|
113
|
+
description: G.Field<{}, "String", "ServiceDescriptionUnavailable">;
|
|
114
|
+
project: G.Field<{}, "Project!">;
|
|
115
|
+
status: G.Field<{}, "Status!">;
|
|
116
|
+
};
|
|
117
|
+
ServiceConnection: {
|
|
118
|
+
edges: G.Field<{}, "[ServiceEdge!]!">;
|
|
119
|
+
pageInfo: G.Field<{}, "PageInfo!">;
|
|
120
|
+
};
|
|
121
|
+
ServiceEdge: {
|
|
122
|
+
cursor: G.Field<{}, "String!">;
|
|
123
|
+
node: G.Field<{}, "Service!">;
|
|
124
|
+
};
|
|
125
|
+
PageInfo: {
|
|
126
|
+
endCursor: G.Field<{}, "String">;
|
|
127
|
+
hasNextPage: G.Field<{}, "Boolean!", "PageInfoUnavailable">;
|
|
128
|
+
};
|
|
129
|
+
Node: { id: G.Field<{}, "ID!">; parent: G.Field<{}, "Project"> };
|
|
130
|
+
SearchResult: {};
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const field = (
|
|
135
|
+
type: string,
|
|
136
|
+
args: Record<string, { type: string; defaultValue?: string }> = {},
|
|
137
|
+
errors: string[] = [],
|
|
138
|
+
): GraphQLField => ({ type, args, errors });
|
|
139
|
+
|
|
140
|
+
export const fixtureModel: GraphQLModel = {
|
|
141
|
+
version: 1,
|
|
142
|
+
queryType: "Query",
|
|
143
|
+
mutationType: "Mutation",
|
|
144
|
+
errors: {
|
|
145
|
+
ProjectNotFound: { matchers: [{ code: "NOT_FOUND" }] },
|
|
146
|
+
ServicesUnavailable: { matchers: [{ code: "UNAVAILABLE" }] },
|
|
147
|
+
ProjectDescriptionUnavailable: {
|
|
148
|
+
matchers: [{ code: "DESCRIPTION_UNAVAILABLE" }],
|
|
149
|
+
},
|
|
150
|
+
ServiceDescriptionUnavailable: {
|
|
151
|
+
matchers: [{ code: "DESCRIPTION_UNAVAILABLE" }],
|
|
152
|
+
},
|
|
153
|
+
PageInfoUnavailable: { matchers: [{ code: "PAGE_INFO_UNAVAILABLE" }] },
|
|
154
|
+
Unauthorized: {
|
|
155
|
+
matchers: [
|
|
156
|
+
{ code: "UNAUTHENTICATED" },
|
|
157
|
+
{ code: "INTERNAL_SERVER_ERROR", message: "Not Authorized" },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
globalErrors: ["Unauthorized"],
|
|
162
|
+
types: {
|
|
163
|
+
ID: { kind: "SCALAR", scalar: "string" },
|
|
164
|
+
String: { kind: "SCALAR", scalar: "string" },
|
|
165
|
+
Int: { kind: "SCALAR", scalar: "number" },
|
|
166
|
+
Boolean: { kind: "SCALAR", scalar: "boolean" },
|
|
167
|
+
JSON: { kind: "SCALAR", scalar: "unknown" },
|
|
168
|
+
Status: { kind: "ENUM", enumValues: ["ACTIVE", "ARCHIVED"] },
|
|
169
|
+
ProjectFilter: {
|
|
170
|
+
kind: "INPUT_OBJECT",
|
|
171
|
+
inputFields: {
|
|
172
|
+
name: { type: "String" },
|
|
173
|
+
statuses: { type: "[Status!]", defaultValue: "[ACTIVE]" },
|
|
174
|
+
metadata: { type: "JSON" },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
Query: {
|
|
178
|
+
kind: "OBJECT",
|
|
179
|
+
fields: {
|
|
180
|
+
project: field("Project", { id: { type: "ID!" } }, ["ProjectNotFound"]),
|
|
181
|
+
projects: field("[Project]!", { filter: { type: "ProjectFilter" } }),
|
|
182
|
+
node: field("Node", { id: { type: "ID!" } }),
|
|
183
|
+
search: field("[SearchResult!]!", { text: { type: "String!" } }),
|
|
184
|
+
services: field(
|
|
185
|
+
"ServiceConnection!",
|
|
186
|
+
{
|
|
187
|
+
first: { type: "Int", defaultValue: "20" },
|
|
188
|
+
after: { type: "String" },
|
|
189
|
+
},
|
|
190
|
+
["ServicesUnavailable"],
|
|
191
|
+
),
|
|
192
|
+
ping: field("Boolean!"),
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
Mutation: {
|
|
196
|
+
kind: "OBJECT",
|
|
197
|
+
fields: {
|
|
198
|
+
editProject: field(
|
|
199
|
+
"Project!",
|
|
200
|
+
{ id: { type: "ID!" }, name: { type: "String!" } },
|
|
201
|
+
["ProjectNotFound"],
|
|
202
|
+
),
|
|
203
|
+
deleteProject: field("Boolean!", { id: { type: "ID!" } }, [
|
|
204
|
+
"ProjectNotFound",
|
|
205
|
+
]),
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
Project: {
|
|
209
|
+
kind: "OBJECT",
|
|
210
|
+
interfaces: ["Node"],
|
|
211
|
+
fields: {
|
|
212
|
+
id: field("ID!"),
|
|
213
|
+
name: field("String!"),
|
|
214
|
+
description: field("String", {}, ["ProjectDescriptionUnavailable"]),
|
|
215
|
+
parent: field("Project"),
|
|
216
|
+
services: field(
|
|
217
|
+
"ServiceConnection",
|
|
218
|
+
{
|
|
219
|
+
first: { type: "Int", defaultValue: "20" },
|
|
220
|
+
after: { type: "String" },
|
|
221
|
+
filter: { type: "ProjectFilter" },
|
|
222
|
+
},
|
|
223
|
+
["ServicesUnavailable"],
|
|
224
|
+
),
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
Service: {
|
|
228
|
+
kind: "OBJECT",
|
|
229
|
+
interfaces: ["Node"],
|
|
230
|
+
fields: {
|
|
231
|
+
id: field("ID!"),
|
|
232
|
+
parent: field("Project"),
|
|
233
|
+
name: field("String!"),
|
|
234
|
+
description: field("String", {}, ["ServiceDescriptionUnavailable"]),
|
|
235
|
+
project: field("Project!"),
|
|
236
|
+
status: field("Status!"),
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
ServiceConnection: {
|
|
240
|
+
kind: "OBJECT",
|
|
241
|
+
fields: { edges: field("[ServiceEdge!]!"), pageInfo: field("PageInfo!") },
|
|
242
|
+
},
|
|
243
|
+
ServiceEdge: {
|
|
244
|
+
kind: "OBJECT",
|
|
245
|
+
fields: { cursor: field("String!"), node: field("Service!") },
|
|
246
|
+
},
|
|
247
|
+
PageInfo: {
|
|
248
|
+
kind: "OBJECT",
|
|
249
|
+
fields: {
|
|
250
|
+
endCursor: field("String"),
|
|
251
|
+
hasNextPage: field("Boolean!", {}, ["PageInfoUnavailable"]),
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
Node: {
|
|
255
|
+
kind: "INTERFACE",
|
|
256
|
+
fields: { id: field("ID!"), parent: field("Project") },
|
|
257
|
+
possibleTypes: ["Project", "Service"],
|
|
258
|
+
},
|
|
259
|
+
SearchResult: { kind: "UNION", possibleTypes: ["Project", "Service"] },
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/** A deliberately small recursive schema for GraphQL compiler/runtime tests. */
|
|
264
|
+
export const fixtureSDL = /* GraphQL */ `
|
|
265
|
+
scalar JSON
|
|
266
|
+
|
|
267
|
+
enum Status {
|
|
268
|
+
ACTIVE
|
|
269
|
+
ARCHIVED
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
input ProjectFilter {
|
|
273
|
+
name: String
|
|
274
|
+
statuses: [Status!] = [ACTIVE]
|
|
275
|
+
metadata: JSON
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
interface Node {
|
|
279
|
+
id: ID!
|
|
280
|
+
parent: Project
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
type Project implements Node {
|
|
284
|
+
id: ID!
|
|
285
|
+
name: String!
|
|
286
|
+
description: String
|
|
287
|
+
parent: Project
|
|
288
|
+
services(
|
|
289
|
+
first: Int = 20
|
|
290
|
+
after: String
|
|
291
|
+
filter: ProjectFilter
|
|
292
|
+
): ServiceConnection
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
type Service implements Node {
|
|
296
|
+
id: ID!
|
|
297
|
+
parent: Project
|
|
298
|
+
name: String!
|
|
299
|
+
description: String
|
|
300
|
+
project: Project!
|
|
301
|
+
status: Status!
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
type ServiceConnection {
|
|
305
|
+
edges: [ServiceEdge!]!
|
|
306
|
+
pageInfo: PageInfo!
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
type ServiceEdge {
|
|
310
|
+
cursor: String!
|
|
311
|
+
node: Service!
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
type PageInfo {
|
|
315
|
+
endCursor: String
|
|
316
|
+
hasNextPage: Boolean!
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
union SearchResult = Project | Service
|
|
320
|
+
|
|
321
|
+
type Query {
|
|
322
|
+
project(id: ID!): Project
|
|
323
|
+
projects(filter: ProjectFilter): [Project]!
|
|
324
|
+
node(id: ID!): Node
|
|
325
|
+
search(text: String!): [SearchResult!]!
|
|
326
|
+
services(first: Int = 20, after: String): ServiceConnection!
|
|
327
|
+
ping: Boolean!
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
type Mutation {
|
|
331
|
+
editProject(id: ID!, name: String!): Project!
|
|
332
|
+
deleteProject(id: ID!): Boolean!
|
|
333
|
+
}
|
|
334
|
+
`;
|
|
335
|
+
|
|
336
|
+
/** Includes characters that must travel in variables, never in GraphQL text. */
|
|
337
|
+
export const adversarialArgument = 'quoted "value" \\ path\nline\t\u0000 😀';
|
|
338
|
+
|
|
339
|
+
export const partialProjectEnvelope = {
|
|
340
|
+
data: {
|
|
341
|
+
project: { id: "p1", services: null },
|
|
342
|
+
ping: true,
|
|
343
|
+
},
|
|
344
|
+
errors: [
|
|
345
|
+
{
|
|
346
|
+
message: "Services temporarily unavailable",
|
|
347
|
+
path: ["project", "services"],
|
|
348
|
+
locations: [{ line: 1, column: 25 }],
|
|
349
|
+
extensions: { code: "UNAVAILABLE", incident: "incident-1" },
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
} as const;
|
|
353
|
+
|
|
354
|
+
export const multipleErrorEnvelope = {
|
|
355
|
+
data: {
|
|
356
|
+
production: null,
|
|
357
|
+
staging: { id: "p2", services: null },
|
|
358
|
+
},
|
|
359
|
+
errors: [
|
|
360
|
+
{
|
|
361
|
+
message: "Project not found",
|
|
362
|
+
path: ["production"],
|
|
363
|
+
extensions: { code: "NOT_FOUND" },
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
message: "Services temporarily unavailable",
|
|
367
|
+
path: ["staging", "services"],
|
|
368
|
+
extensions: { code: "UNAVAILABLE" },
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
} as const;
|