@effect-gql/core 0.1.0 → 1.0.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.
- package/README.md +100 -0
- package/builder/index.cjs +1431 -0
- package/builder/index.cjs.map +1 -0
- package/builder/index.d.cts +259 -0
- package/{dist/builder/pipe-api.d.ts → builder/index.d.ts} +49 -21
- package/builder/index.js +1390 -0
- package/builder/index.js.map +1 -0
- package/index.cjs +3419 -0
- package/index.cjs.map +1 -0
- package/index.d.cts +523 -0
- package/index.d.ts +523 -0
- package/index.js +3242 -0
- package/index.js.map +1 -0
- package/package.json +19 -28
- package/schema-builder-Cvdq7Kz_.d.cts +963 -0
- package/schema-builder-Cvdq7Kz_.d.ts +963 -0
- package/server/index.cjs +1555 -0
- package/server/index.cjs.map +1 -0
- package/server/index.d.cts +680 -0
- package/server/index.d.ts +680 -0
- package/server/index.js +1524 -0
- package/server/index.js.map +1 -0
- package/dist/analyzer-extension.d.ts +0 -105
- package/dist/analyzer-extension.d.ts.map +0 -1
- package/dist/analyzer-extension.js +0 -137
- package/dist/analyzer-extension.js.map +0 -1
- package/dist/builder/execute.d.ts +0 -26
- package/dist/builder/execute.d.ts.map +0 -1
- package/dist/builder/execute.js +0 -104
- package/dist/builder/execute.js.map +0 -1
- package/dist/builder/field-builders.d.ts +0 -30
- package/dist/builder/field-builders.d.ts.map +0 -1
- package/dist/builder/field-builders.js +0 -200
- package/dist/builder/field-builders.js.map +0 -1
- package/dist/builder/index.d.ts +0 -7
- package/dist/builder/index.d.ts.map +0 -1
- package/dist/builder/index.js +0 -31
- package/dist/builder/index.js.map +0 -1
- package/dist/builder/pipe-api.d.ts.map +0 -1
- package/dist/builder/pipe-api.js +0 -151
- package/dist/builder/pipe-api.js.map +0 -1
- package/dist/builder/schema-builder.d.ts +0 -301
- package/dist/builder/schema-builder.d.ts.map +0 -1
- package/dist/builder/schema-builder.js +0 -566
- package/dist/builder/schema-builder.js.map +0 -1
- package/dist/builder/type-registry.d.ts +0 -80
- package/dist/builder/type-registry.d.ts.map +0 -1
- package/dist/builder/type-registry.js +0 -505
- package/dist/builder/type-registry.js.map +0 -1
- package/dist/builder/types.d.ts +0 -283
- package/dist/builder/types.d.ts.map +0 -1
- package/dist/builder/types.js +0 -3
- package/dist/builder/types.js.map +0 -1
- package/dist/cli/generate-schema.d.ts +0 -29
- package/dist/cli/generate-schema.d.ts.map +0 -1
- package/dist/cli/generate-schema.js +0 -233
- package/dist/cli/generate-schema.js.map +0 -1
- package/dist/cli/index.d.ts +0 -19
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -24
- package/dist/cli/index.js.map +0 -1
- package/dist/context.d.ts +0 -18
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -11
- package/dist/context.js.map +0 -1
- package/dist/error.d.ts +0 -45
- package/dist/error.d.ts.map +0 -1
- package/dist/error.js +0 -29
- package/dist/error.js.map +0 -1
- package/dist/extensions.d.ts +0 -130
- package/dist/extensions.d.ts.map +0 -1
- package/dist/extensions.js +0 -78
- package/dist/extensions.js.map +0 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -47
- package/dist/index.js.map +0 -1
- package/dist/loader.d.ts +0 -169
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js +0 -237
- package/dist/loader.js.map +0 -1
- package/dist/resolver-context.d.ts +0 -154
- package/dist/resolver-context.d.ts.map +0 -1
- package/dist/resolver-context.js +0 -184
- package/dist/resolver-context.js.map +0 -1
- package/dist/schema-mapping.d.ts +0 -30
- package/dist/schema-mapping.d.ts.map +0 -1
- package/dist/schema-mapping.js +0 -280
- package/dist/schema-mapping.js.map +0 -1
- package/dist/server/cache-control.d.ts +0 -96
- package/dist/server/cache-control.d.ts.map +0 -1
- package/dist/server/cache-control.js +0 -308
- package/dist/server/cache-control.js.map +0 -1
- package/dist/server/complexity.d.ts +0 -165
- package/dist/server/complexity.d.ts.map +0 -1
- package/dist/server/complexity.js +0 -433
- package/dist/server/complexity.js.map +0 -1
- package/dist/server/config.d.ts +0 -66
- package/dist/server/config.d.ts.map +0 -1
- package/dist/server/config.js +0 -104
- package/dist/server/config.js.map +0 -1
- package/dist/server/graphiql.d.ts +0 -5
- package/dist/server/graphiql.d.ts.map +0 -1
- package/dist/server/graphiql.js +0 -43
- package/dist/server/graphiql.js.map +0 -1
- package/dist/server/index.d.ts +0 -18
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -48
- package/dist/server/index.js.map +0 -1
- package/dist/server/router.d.ts +0 -79
- package/dist/server/router.d.ts.map +0 -1
- package/dist/server/router.js +0 -232
- package/dist/server/router.js.map +0 -1
- package/dist/server/schema-builder-extensions.d.ts +0 -42
- package/dist/server/schema-builder-extensions.d.ts.map +0 -1
- package/dist/server/schema-builder-extensions.js +0 -48
- package/dist/server/schema-builder-extensions.js.map +0 -1
- package/dist/server/sse-adapter.d.ts +0 -64
- package/dist/server/sse-adapter.d.ts.map +0 -1
- package/dist/server/sse-adapter.js +0 -227
- package/dist/server/sse-adapter.js.map +0 -1
- package/dist/server/sse-types.d.ts +0 -192
- package/dist/server/sse-types.d.ts.map +0 -1
- package/dist/server/sse-types.js +0 -63
- package/dist/server/sse-types.js.map +0 -1
- package/dist/server/ws-adapter.d.ts +0 -39
- package/dist/server/ws-adapter.d.ts.map +0 -1
- package/dist/server/ws-adapter.js +0 -247
- package/dist/server/ws-adapter.js.map +0 -1
- package/dist/server/ws-types.d.ts +0 -169
- package/dist/server/ws-types.d.ts.map +0 -1
- package/dist/server/ws-types.js +0 -11
- package/dist/server/ws-types.js.map +0 -1
- package/dist/server/ws-utils.d.ts +0 -42
- package/dist/server/ws-utils.d.ts.map +0 -1
- package/dist/server/ws-utils.js +0 -99
- package/dist/server/ws-utils.js.map +0 -1
- package/src/analyzer-extension.ts +0 -254
- package/src/builder/execute.ts +0 -153
- package/src/builder/field-builders.ts +0 -322
- package/src/builder/index.ts +0 -48
- package/src/builder/pipe-api.ts +0 -312
- package/src/builder/schema-builder.ts +0 -970
- package/src/builder/type-registry.ts +0 -670
- package/src/builder/types.ts +0 -305
- package/src/context.ts +0 -23
- package/src/error.ts +0 -32
- package/src/extensions.ts +0 -240
- package/src/index.ts +0 -32
- package/src/loader.ts +0 -363
- package/src/resolver-context.ts +0 -253
- package/src/schema-mapping.ts +0 -307
- package/src/server/cache-control.ts +0 -590
- package/src/server/complexity.ts +0 -774
- package/src/server/config.ts +0 -174
- package/src/server/graphiql.ts +0 -38
- package/src/server/index.ts +0 -96
- package/src/server/router.ts +0 -432
- package/src/server/schema-builder-extensions.ts +0 -51
- package/src/server/sse-adapter.ts +0 -327
- package/src/server/sse-types.ts +0 -234
- package/src/server/ws-adapter.ts +0 -355
- package/src/server/ws-types.ts +0 -192
- package/src/server/ws-utils.ts +0 -136
package/index.cjs
ADDED
|
@@ -0,0 +1,3419 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var graphql = require('graphql');
|
|
4
|
+
var effect = require('effect');
|
|
5
|
+
var S2 = require('effect/Schema');
|
|
6
|
+
var AST = require('effect/SchemaAST');
|
|
7
|
+
var DataLoader = require('dataloader');
|
|
8
|
+
var platform = require('@effect/platform');
|
|
9
|
+
var graphqlWs = require('graphql-ws');
|
|
10
|
+
|
|
11
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
|
|
13
|
+
function _interopNamespace(e) {
|
|
14
|
+
if (e && e.__esModule) return e;
|
|
15
|
+
var n = Object.create(null);
|
|
16
|
+
if (e) {
|
|
17
|
+
Object.keys(e).forEach(function (k) {
|
|
18
|
+
if (k !== 'default') {
|
|
19
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
20
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return e[k]; }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
n.default = e;
|
|
28
|
+
return Object.freeze(n);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var S2__namespace = /*#__PURE__*/_interopNamespace(S2);
|
|
32
|
+
var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
|
|
33
|
+
var DataLoader__default = /*#__PURE__*/_interopDefault(DataLoader);
|
|
34
|
+
|
|
35
|
+
// src/builder/index.ts
|
|
36
|
+
var isIntegerType = (ast) => {
|
|
37
|
+
if (ast._tag === "Refinement") {
|
|
38
|
+
const refinement = ast;
|
|
39
|
+
const annotations = refinement.annotations;
|
|
40
|
+
if (annotations) {
|
|
41
|
+
const identifier = AST__namespace.getIdentifierAnnotation(refinement);
|
|
42
|
+
if (identifier._tag === "Some" && identifier.value === "Int") {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return isIntegerType(refinement.from);
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
var toGraphQLType = (schema) => {
|
|
51
|
+
const ast = schema.ast;
|
|
52
|
+
if (ast._tag === "StringKeyword") return graphql.GraphQLString;
|
|
53
|
+
if (ast._tag === "NumberKeyword") return graphql.GraphQLFloat;
|
|
54
|
+
if (ast._tag === "BooleanKeyword") return graphql.GraphQLBoolean;
|
|
55
|
+
if (ast._tag === "Refinement") {
|
|
56
|
+
if (isIntegerType(ast)) {
|
|
57
|
+
return graphql.GraphQLInt;
|
|
58
|
+
}
|
|
59
|
+
return toGraphQLType(S2__namespace.make(ast.from));
|
|
60
|
+
}
|
|
61
|
+
if (ast._tag === "Literal") {
|
|
62
|
+
if (typeof ast.literal === "string") return graphql.GraphQLString;
|
|
63
|
+
if (typeof ast.literal === "number") {
|
|
64
|
+
return Number.isInteger(ast.literal) ? graphql.GraphQLInt : graphql.GraphQLFloat;
|
|
65
|
+
}
|
|
66
|
+
if (typeof ast.literal === "boolean") return graphql.GraphQLBoolean;
|
|
67
|
+
}
|
|
68
|
+
if (ast._tag === "TupleType") {
|
|
69
|
+
const elements = ast.elements;
|
|
70
|
+
if (elements.length > 0) {
|
|
71
|
+
const elementSchema = S2__namespace.make(elements[0].type);
|
|
72
|
+
return new graphql.GraphQLList(toGraphQLType(elementSchema));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (ast._tag === "TypeLiteral") {
|
|
76
|
+
const fields = {};
|
|
77
|
+
for (const field2 of ast.propertySignatures) {
|
|
78
|
+
const fieldName = String(field2.name);
|
|
79
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
80
|
+
let fieldType = toGraphQLType(fieldSchema);
|
|
81
|
+
if (!field2.isOptional) {
|
|
82
|
+
fieldType = new graphql.GraphQLNonNull(fieldType);
|
|
83
|
+
}
|
|
84
|
+
fields[fieldName] = { type: fieldType };
|
|
85
|
+
}
|
|
86
|
+
const typeName = schema.annotations?.identifier || `Object_${Math.random().toString(36).slice(2, 11)}`;
|
|
87
|
+
return new graphql.GraphQLObjectType({
|
|
88
|
+
name: typeName,
|
|
89
|
+
fields
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (ast._tag === "Transformation") {
|
|
93
|
+
return toGraphQLType(S2__namespace.make(ast.to));
|
|
94
|
+
}
|
|
95
|
+
if (ast._tag === "Union") {
|
|
96
|
+
const types = ast.types;
|
|
97
|
+
if (types.length > 0) {
|
|
98
|
+
return toGraphQLType(S2__namespace.make(types[0]));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (ast._tag === "Suspend") {
|
|
102
|
+
const innerAst = ast.f();
|
|
103
|
+
return toGraphQLType(S2__namespace.make(innerAst));
|
|
104
|
+
}
|
|
105
|
+
return graphql.GraphQLString;
|
|
106
|
+
};
|
|
107
|
+
var toGraphQLInputType = (schema) => {
|
|
108
|
+
const ast = schema.ast;
|
|
109
|
+
if (ast._tag === "StringKeyword") return graphql.GraphQLString;
|
|
110
|
+
if (ast._tag === "NumberKeyword") return graphql.GraphQLFloat;
|
|
111
|
+
if (ast._tag === "BooleanKeyword") return graphql.GraphQLBoolean;
|
|
112
|
+
if (ast._tag === "Refinement") {
|
|
113
|
+
if (isIntegerType(ast)) {
|
|
114
|
+
return graphql.GraphQLInt;
|
|
115
|
+
}
|
|
116
|
+
return toGraphQLInputType(S2__namespace.make(ast.from));
|
|
117
|
+
}
|
|
118
|
+
if (ast._tag === "Literal") {
|
|
119
|
+
if (typeof ast.literal === "string") return graphql.GraphQLString;
|
|
120
|
+
if (typeof ast.literal === "number") {
|
|
121
|
+
return Number.isInteger(ast.literal) ? graphql.GraphQLInt : graphql.GraphQLFloat;
|
|
122
|
+
}
|
|
123
|
+
if (typeof ast.literal === "boolean") return graphql.GraphQLBoolean;
|
|
124
|
+
}
|
|
125
|
+
if (ast._tag === "TupleType") {
|
|
126
|
+
const elements = ast.elements;
|
|
127
|
+
if (elements.length > 0) {
|
|
128
|
+
const elementSchema = S2__namespace.make(elements[0].type);
|
|
129
|
+
return new graphql.GraphQLList(toGraphQLInputType(elementSchema));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (ast._tag === "TypeLiteral") {
|
|
133
|
+
const fields = {};
|
|
134
|
+
for (const field2 of ast.propertySignatures) {
|
|
135
|
+
const fieldName = String(field2.name);
|
|
136
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
137
|
+
let fieldType = toGraphQLInputType(fieldSchema);
|
|
138
|
+
if (!field2.isOptional) {
|
|
139
|
+
fieldType = new graphql.GraphQLNonNull(fieldType);
|
|
140
|
+
}
|
|
141
|
+
fields[fieldName] = { type: fieldType };
|
|
142
|
+
}
|
|
143
|
+
const typeName = schema.annotations?.identifier || `Input_${Math.random().toString(36).slice(2, 11)}`;
|
|
144
|
+
return new graphql.GraphQLInputObjectType({
|
|
145
|
+
name: typeName,
|
|
146
|
+
fields
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (ast._tag === "Transformation") {
|
|
150
|
+
return toGraphQLInputType(S2__namespace.make(ast.from));
|
|
151
|
+
}
|
|
152
|
+
if (ast._tag === "Union") {
|
|
153
|
+
const types = ast.types;
|
|
154
|
+
if (types.length > 0) {
|
|
155
|
+
return toGraphQLInputType(S2__namespace.make(types[0]));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (ast._tag === "Suspend") {
|
|
159
|
+
const innerAst = ast.f();
|
|
160
|
+
return toGraphQLInputType(S2__namespace.make(innerAst));
|
|
161
|
+
}
|
|
162
|
+
return graphql.GraphQLString;
|
|
163
|
+
};
|
|
164
|
+
var toGraphQLObjectType = (name, schema, additionalFields) => {
|
|
165
|
+
const ast = schema.ast;
|
|
166
|
+
if (ast._tag === "TypeLiteral") {
|
|
167
|
+
const fields = {};
|
|
168
|
+
for (const field2 of ast.propertySignatures) {
|
|
169
|
+
const fieldName = String(field2.name);
|
|
170
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
171
|
+
let fieldType = toGraphQLType(fieldSchema);
|
|
172
|
+
if (!field2.isOptional) {
|
|
173
|
+
fieldType = new graphql.GraphQLNonNull(fieldType);
|
|
174
|
+
}
|
|
175
|
+
fields[fieldName] = { type: fieldType };
|
|
176
|
+
}
|
|
177
|
+
if (additionalFields) {
|
|
178
|
+
for (const [fieldName, fieldConfig] of Object.entries(additionalFields)) {
|
|
179
|
+
fields[fieldName] = {
|
|
180
|
+
type: fieldConfig.type,
|
|
181
|
+
args: fieldConfig.args,
|
|
182
|
+
description: fieldConfig.description,
|
|
183
|
+
// Note: resolve will be set later when runtime is available
|
|
184
|
+
resolve: fieldConfig.resolve
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return new graphql.GraphQLObjectType({
|
|
189
|
+
name,
|
|
190
|
+
fields
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
throw new Error(`Schema must be an object type to convert to GraphQLObjectType`);
|
|
194
|
+
};
|
|
195
|
+
var toGraphQLArgs = (schema) => {
|
|
196
|
+
const ast = schema.ast;
|
|
197
|
+
if (ast._tag === "TypeLiteral") {
|
|
198
|
+
const args = {};
|
|
199
|
+
for (const field2 of ast.propertySignatures) {
|
|
200
|
+
const fieldName = String(field2.name);
|
|
201
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
202
|
+
let fieldType = toGraphQLInputType(fieldSchema);
|
|
203
|
+
if (!field2.isOptional) {
|
|
204
|
+
fieldType = new graphql.GraphQLNonNull(fieldType);
|
|
205
|
+
}
|
|
206
|
+
args[fieldName] = { type: fieldType };
|
|
207
|
+
}
|
|
208
|
+
return args;
|
|
209
|
+
}
|
|
210
|
+
throw new Error(`Schema must be an object type to convert to GraphQL arguments`);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// src/builder/type-registry.ts
|
|
214
|
+
function getSchemaName(schema) {
|
|
215
|
+
const ast = schema.ast;
|
|
216
|
+
if (ast._tag === "Transformation") {
|
|
217
|
+
const identifier = AST__namespace.getIdentifierAnnotation(ast.to);
|
|
218
|
+
if (identifier._tag === "Some") {
|
|
219
|
+
return identifier.value;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (ast._tag === "TypeLiteral") {
|
|
223
|
+
const tagProp = ast.propertySignatures.find((p) => String(p.name) === "_tag");
|
|
224
|
+
if (tagProp && tagProp.type._tag === "Literal" && typeof tagProp.type.literal === "string") {
|
|
225
|
+
return tagProp.type.literal;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return void 0;
|
|
229
|
+
}
|
|
230
|
+
function buildReverseLookups(ctx) {
|
|
231
|
+
if (!ctx.schemaToTypeName) {
|
|
232
|
+
ctx.schemaToTypeName = /* @__PURE__ */ new Map();
|
|
233
|
+
ctx.astToTypeName = /* @__PURE__ */ new Map();
|
|
234
|
+
for (const [typeName, typeReg] of ctx.types) {
|
|
235
|
+
ctx.schemaToTypeName.set(typeReg.schema, typeName);
|
|
236
|
+
ctx.astToTypeName.set(typeReg.schema.ast, typeName);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (!ctx.schemaToInterfaceName) {
|
|
240
|
+
ctx.schemaToInterfaceName = /* @__PURE__ */ new Map();
|
|
241
|
+
ctx.astToInterfaceName = /* @__PURE__ */ new Map();
|
|
242
|
+
for (const [interfaceName, interfaceReg] of ctx.interfaces) {
|
|
243
|
+
ctx.schemaToInterfaceName.set(interfaceReg.schema, interfaceName);
|
|
244
|
+
ctx.astToInterfaceName.set(interfaceReg.schema.ast, interfaceName);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (!ctx.schemaToInputName) {
|
|
248
|
+
ctx.schemaToInputName = /* @__PURE__ */ new Map();
|
|
249
|
+
ctx.astToInputName = /* @__PURE__ */ new Map();
|
|
250
|
+
for (const [inputName, inputReg] of ctx.inputs) {
|
|
251
|
+
ctx.schemaToInputName.set(inputReg.schema, inputName);
|
|
252
|
+
ctx.astToInputName.set(inputReg.schema.ast, inputName);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (!ctx.enumSortedValues) {
|
|
256
|
+
ctx.enumSortedValues = /* @__PURE__ */ new Map();
|
|
257
|
+
ctx.literalToEnumName = /* @__PURE__ */ new Map();
|
|
258
|
+
for (const [enumName, enumReg] of ctx.enums) {
|
|
259
|
+
ctx.enumSortedValues.set(enumName, [...enumReg.values].sort());
|
|
260
|
+
for (const value of enumReg.values) {
|
|
261
|
+
ctx.literalToEnumName.set(value, enumName);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (!ctx.unionSortedTypes) {
|
|
266
|
+
ctx.unionSortedTypes = /* @__PURE__ */ new Map();
|
|
267
|
+
for (const [unionName, unionReg] of ctx.unions) {
|
|
268
|
+
ctx.unionSortedTypes.set(unionName, [...unionReg.types].sort());
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
var nonNullCache = /* @__PURE__ */ new WeakMap();
|
|
273
|
+
function getNonNull(type) {
|
|
274
|
+
let cached = nonNullCache.get(type);
|
|
275
|
+
if (!cached) {
|
|
276
|
+
cached = new graphql.GraphQLNonNull(type);
|
|
277
|
+
nonNullCache.set(type, cached);
|
|
278
|
+
}
|
|
279
|
+
return cached;
|
|
280
|
+
}
|
|
281
|
+
function toGraphQLTypeWithRegistry(schema, ctx) {
|
|
282
|
+
buildReverseLookups(ctx);
|
|
283
|
+
const ast = schema.ast;
|
|
284
|
+
const registeredType = findRegisteredType(schema, ast, ctx);
|
|
285
|
+
if (registeredType) return registeredType;
|
|
286
|
+
const registeredInterface = findRegisteredInterface(schema, ast, ctx);
|
|
287
|
+
if (registeredInterface) return registeredInterface;
|
|
288
|
+
if (ast._tag === "Transformation") {
|
|
289
|
+
return handleTransformationAST(ast, ctx);
|
|
290
|
+
}
|
|
291
|
+
if (ast._tag === "Union") {
|
|
292
|
+
return handleUnionAST(ast, ctx);
|
|
293
|
+
}
|
|
294
|
+
if (ast._tag === "Literal") {
|
|
295
|
+
const enumType2 = findEnumForLiteral(ast, ctx);
|
|
296
|
+
if (enumType2) return enumType2;
|
|
297
|
+
}
|
|
298
|
+
if (ast._tag === "TupleType") {
|
|
299
|
+
return handleTupleTypeAST(ast, ctx);
|
|
300
|
+
}
|
|
301
|
+
if (ast._tag === "Suspend") {
|
|
302
|
+
const innerAst = ast.f();
|
|
303
|
+
return toGraphQLTypeWithRegistry(S2__namespace.make(innerAst), ctx);
|
|
304
|
+
}
|
|
305
|
+
return toGraphQLType(schema);
|
|
306
|
+
}
|
|
307
|
+
function findRegisteredType(schema, ast, ctx) {
|
|
308
|
+
const typeName = ctx.schemaToTypeName?.get(schema) ?? ctx.astToTypeName?.get(ast);
|
|
309
|
+
if (typeName) {
|
|
310
|
+
return ctx.typeRegistry.get(typeName);
|
|
311
|
+
}
|
|
312
|
+
return void 0;
|
|
313
|
+
}
|
|
314
|
+
function findRegisteredInterface(schema, ast, ctx) {
|
|
315
|
+
const interfaceName = ctx.schemaToInterfaceName?.get(schema) ?? ctx.astToInterfaceName?.get(ast);
|
|
316
|
+
if (interfaceName) {
|
|
317
|
+
return ctx.interfaceRegistry.get(interfaceName);
|
|
318
|
+
}
|
|
319
|
+
return void 0;
|
|
320
|
+
}
|
|
321
|
+
function handleTransformationAST(ast, ctx) {
|
|
322
|
+
const toAst = ast.to;
|
|
323
|
+
if (toAst._tag === "TupleType") {
|
|
324
|
+
if (toAst.rest && toAst.rest.length > 0) {
|
|
325
|
+
const elementSchema = S2__namespace.make(toAst.rest[0].type);
|
|
326
|
+
const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
|
|
327
|
+
return new graphql.GraphQLList(elementType);
|
|
328
|
+
} else if (toAst.elements.length > 0) {
|
|
329
|
+
const elementSchema = S2__namespace.make(toAst.elements[0].type);
|
|
330
|
+
const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
|
|
331
|
+
return new graphql.GraphQLList(elementType);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return toGraphQLTypeWithRegistry(S2__namespace.make(ast.to), ctx);
|
|
335
|
+
}
|
|
336
|
+
function handleUnionAST(ast, ctx) {
|
|
337
|
+
const allLiterals = ast.types.every((t) => t._tag === "Literal");
|
|
338
|
+
if (allLiterals) {
|
|
339
|
+
const enumType2 = findEnumForLiteralUnion(ast.types, ctx);
|
|
340
|
+
if (enumType2) return enumType2;
|
|
341
|
+
} else {
|
|
342
|
+
const unionType2 = findRegisteredUnion(ast.types, ctx);
|
|
343
|
+
if (unionType2) return unionType2;
|
|
344
|
+
}
|
|
345
|
+
if (ast.types.length > 0) {
|
|
346
|
+
return toGraphQLTypeWithRegistry(S2__namespace.make(ast.types[0]), ctx);
|
|
347
|
+
}
|
|
348
|
+
return toGraphQLType(S2__namespace.make(ast));
|
|
349
|
+
}
|
|
350
|
+
function findEnumForLiteralUnion(types, ctx) {
|
|
351
|
+
const literalValues = types.map((t) => String(t.literal)).sort();
|
|
352
|
+
for (const [enumName] of ctx.enums) {
|
|
353
|
+
const enumValues = ctx.enumSortedValues?.get(enumName);
|
|
354
|
+
if (enumValues && literalValues.length === enumValues.length && literalValues.every((v, i) => v === enumValues[i])) {
|
|
355
|
+
return ctx.enumRegistry.get(enumName);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return void 0;
|
|
359
|
+
}
|
|
360
|
+
function findRegisteredUnion(types, ctx) {
|
|
361
|
+
const memberTags = [];
|
|
362
|
+
for (const memberAst of types) {
|
|
363
|
+
if (memberAst._tag === "TypeLiteral") {
|
|
364
|
+
const tagProp = memberAst.propertySignatures.find((p) => String(p.name) === "_tag");
|
|
365
|
+
if (tagProp && tagProp.type._tag === "Literal") {
|
|
366
|
+
memberTags.push(String(tagProp.type.literal));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (memberTags.length === types.length) {
|
|
371
|
+
const sortedTags = memberTags.sort();
|
|
372
|
+
for (const [unionName] of ctx.unions) {
|
|
373
|
+
const unionTypes = ctx.unionSortedTypes?.get(unionName);
|
|
374
|
+
if (unionTypes && sortedTags.length === unionTypes.length && sortedTags.every((tag, i) => tag === unionTypes[i])) {
|
|
375
|
+
return ctx.unionRegistry.get(unionName);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return void 0;
|
|
380
|
+
}
|
|
381
|
+
function findEnumForLiteral(ast, ctx) {
|
|
382
|
+
const literalValue = String(ast.literal);
|
|
383
|
+
const enumName = ctx.literalToEnumName?.get(literalValue);
|
|
384
|
+
if (enumName) {
|
|
385
|
+
return ctx.enumRegistry.get(enumName);
|
|
386
|
+
}
|
|
387
|
+
return void 0;
|
|
388
|
+
}
|
|
389
|
+
function handleTupleTypeAST(ast, ctx) {
|
|
390
|
+
if (ast.rest && ast.rest.length > 0) {
|
|
391
|
+
const elementSchema = S2__namespace.make(ast.rest[0].type);
|
|
392
|
+
const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
|
|
393
|
+
return new graphql.GraphQLList(elementType);
|
|
394
|
+
} else if (ast.elements && ast.elements.length > 0) {
|
|
395
|
+
const elementSchema = S2__namespace.make(ast.elements[0].type);
|
|
396
|
+
const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
|
|
397
|
+
return new graphql.GraphQLList(elementType);
|
|
398
|
+
}
|
|
399
|
+
return toGraphQLType(S2__namespace.make(ast));
|
|
400
|
+
}
|
|
401
|
+
function schemaToFields(schema, ctx) {
|
|
402
|
+
let ast = schema.ast;
|
|
403
|
+
if (ast._tag === "Transformation") {
|
|
404
|
+
ast = ast.to;
|
|
405
|
+
}
|
|
406
|
+
if (ast._tag === "Declaration") {
|
|
407
|
+
const typeParams = ast.typeParameters;
|
|
408
|
+
if (typeParams && typeParams.length > 0 && typeParams[0]._tag === "TypeLiteral") {
|
|
409
|
+
ast = typeParams[0];
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (ast._tag === "TypeLiteral") {
|
|
413
|
+
const fields = {};
|
|
414
|
+
for (const field2 of ast.propertySignatures) {
|
|
415
|
+
const fieldName = String(field2.name);
|
|
416
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
417
|
+
let fieldType = toGraphQLTypeWithRegistry(fieldSchema, ctx);
|
|
418
|
+
if (!field2.isOptional) {
|
|
419
|
+
fieldType = getNonNull(fieldType);
|
|
420
|
+
}
|
|
421
|
+
fields[fieldName] = { type: fieldType };
|
|
422
|
+
}
|
|
423
|
+
return fields;
|
|
424
|
+
}
|
|
425
|
+
return {};
|
|
426
|
+
}
|
|
427
|
+
function schemaToInputFields(schema, enumRegistry, inputRegistry, inputs, enums, cache) {
|
|
428
|
+
const ast = schema.ast;
|
|
429
|
+
if (ast._tag === "TypeLiteral") {
|
|
430
|
+
const fields = {};
|
|
431
|
+
for (const field2 of ast.propertySignatures) {
|
|
432
|
+
const fieldName = String(field2.name);
|
|
433
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
434
|
+
let fieldType = toGraphQLInputTypeWithRegistry(
|
|
435
|
+
fieldSchema,
|
|
436
|
+
enumRegistry,
|
|
437
|
+
inputRegistry,
|
|
438
|
+
inputs,
|
|
439
|
+
enums,
|
|
440
|
+
cache
|
|
441
|
+
);
|
|
442
|
+
if (!field2.isOptional) {
|
|
443
|
+
fieldType = getNonNull(fieldType);
|
|
444
|
+
}
|
|
445
|
+
fields[fieldName] = { type: fieldType };
|
|
446
|
+
}
|
|
447
|
+
return fields;
|
|
448
|
+
}
|
|
449
|
+
return {};
|
|
450
|
+
}
|
|
451
|
+
function buildInputTypeLookupCache(inputs, enums) {
|
|
452
|
+
const cache = {
|
|
453
|
+
schemaToInputName: /* @__PURE__ */ new Map(),
|
|
454
|
+
astToInputName: /* @__PURE__ */ new Map(),
|
|
455
|
+
literalToEnumName: /* @__PURE__ */ new Map(),
|
|
456
|
+
enumSortedValues: /* @__PURE__ */ new Map()
|
|
457
|
+
};
|
|
458
|
+
for (const [inputName, inputReg] of inputs) {
|
|
459
|
+
cache.schemaToInputName.set(inputReg.schema, inputName);
|
|
460
|
+
cache.astToInputName.set(inputReg.schema.ast, inputName);
|
|
461
|
+
}
|
|
462
|
+
for (const [enumName, enumReg] of enums) {
|
|
463
|
+
cache.enumSortedValues.set(enumName, [...enumReg.values].sort());
|
|
464
|
+
for (const value of enumReg.values) {
|
|
465
|
+
cache.literalToEnumName.set(value, enumName);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return cache;
|
|
469
|
+
}
|
|
470
|
+
function toGraphQLInputTypeWithRegistry(schema, enumRegistry, inputRegistry, inputs, enums, cache) {
|
|
471
|
+
const ast = schema.ast;
|
|
472
|
+
if (ast._tag === "Transformation") {
|
|
473
|
+
const toAst = ast.to;
|
|
474
|
+
return toGraphQLInputTypeWithRegistry(
|
|
475
|
+
S2__namespace.make(toAst),
|
|
476
|
+
enumRegistry,
|
|
477
|
+
inputRegistry,
|
|
478
|
+
inputs,
|
|
479
|
+
enums,
|
|
480
|
+
cache
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
if (cache?.schemaToInputName || cache?.astToInputName) {
|
|
484
|
+
const inputName = cache.schemaToInputName?.get(schema) ?? cache.astToInputName?.get(ast);
|
|
485
|
+
if (inputName) {
|
|
486
|
+
const result = inputRegistry.get(inputName);
|
|
487
|
+
if (result) return result;
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
for (const [inputName, inputReg] of inputs) {
|
|
491
|
+
if (inputReg.schema.ast === ast || inputReg.schema === schema) {
|
|
492
|
+
const result = inputRegistry.get(inputName);
|
|
493
|
+
if (result) return result;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (ast._tag === "Union") {
|
|
498
|
+
const unionAst = ast;
|
|
499
|
+
const nonUndefinedTypes = unionAst.types.filter((t) => t._tag !== "UndefinedKeyword");
|
|
500
|
+
if (nonUndefinedTypes.length === 1 && nonUndefinedTypes[0]._tag === "Union") {
|
|
501
|
+
return toGraphQLInputTypeWithRegistry(
|
|
502
|
+
S2__namespace.make(nonUndefinedTypes[0]),
|
|
503
|
+
enumRegistry,
|
|
504
|
+
inputRegistry,
|
|
505
|
+
inputs,
|
|
506
|
+
enums,
|
|
507
|
+
cache
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
if (nonUndefinedTypes.length === 1 && nonUndefinedTypes[0]._tag === "TypeLiteral") {
|
|
511
|
+
return toGraphQLInputTypeWithRegistry(
|
|
512
|
+
S2__namespace.make(nonUndefinedTypes[0]),
|
|
513
|
+
enumRegistry,
|
|
514
|
+
inputRegistry,
|
|
515
|
+
inputs,
|
|
516
|
+
enums,
|
|
517
|
+
cache
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
const allLiterals = unionAst.types.every((t) => t._tag === "Literal");
|
|
521
|
+
if (allLiterals) {
|
|
522
|
+
const literalValues = unionAst.types.map((t) => String(t.literal)).sort();
|
|
523
|
+
for (const [enumName] of enums) {
|
|
524
|
+
const enumValues = cache?.enumSortedValues?.get(enumName) ?? [...enums.get(enumName).values].sort();
|
|
525
|
+
if (literalValues.length === enumValues.length && literalValues.every((v, i) => v === enumValues[i])) {
|
|
526
|
+
const result = enumRegistry.get(enumName);
|
|
527
|
+
if (result) return result;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (ast._tag === "Literal") {
|
|
533
|
+
const literalValue = String(ast.literal);
|
|
534
|
+
if (cache?.literalToEnumName) {
|
|
535
|
+
const enumName = cache.literalToEnumName.get(literalValue);
|
|
536
|
+
if (enumName) {
|
|
537
|
+
const result = enumRegistry.get(enumName);
|
|
538
|
+
if (result) return result;
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
for (const [enumName, enumReg] of enums) {
|
|
542
|
+
if (enumReg.values.includes(literalValue)) {
|
|
543
|
+
const result = enumRegistry.get(enumName);
|
|
544
|
+
if (result) return result;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (ast._tag === "Suspend") {
|
|
550
|
+
const innerAst = ast.f();
|
|
551
|
+
return toGraphQLInputTypeWithRegistry(
|
|
552
|
+
S2__namespace.make(innerAst),
|
|
553
|
+
enumRegistry,
|
|
554
|
+
inputRegistry,
|
|
555
|
+
inputs,
|
|
556
|
+
enums,
|
|
557
|
+
cache
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
return toGraphQLInputType(schema);
|
|
561
|
+
}
|
|
562
|
+
function toGraphQLArgsWithRegistry(schema, enumRegistry, inputRegistry, inputs, enums, cache) {
|
|
563
|
+
const ast = schema.ast;
|
|
564
|
+
if (ast._tag === "TypeLiteral") {
|
|
565
|
+
const args = {};
|
|
566
|
+
for (const field2 of ast.propertySignatures) {
|
|
567
|
+
const fieldName = String(field2.name);
|
|
568
|
+
const fieldSchema = S2__namespace.make(field2.type);
|
|
569
|
+
let fieldType = toGraphQLInputTypeWithRegistry(
|
|
570
|
+
fieldSchema,
|
|
571
|
+
enumRegistry,
|
|
572
|
+
inputRegistry,
|
|
573
|
+
inputs,
|
|
574
|
+
enums,
|
|
575
|
+
cache
|
|
576
|
+
);
|
|
577
|
+
if (!field2.isOptional) {
|
|
578
|
+
fieldType = getNonNull(fieldType);
|
|
579
|
+
}
|
|
580
|
+
args[fieldName] = { type: fieldType };
|
|
581
|
+
}
|
|
582
|
+
return args;
|
|
583
|
+
}
|
|
584
|
+
return toGraphQLArgs(schema);
|
|
585
|
+
}
|
|
586
|
+
function applyDirectives(effect, directives, directiveRegistrations) {
|
|
587
|
+
if (!directives) return effect;
|
|
588
|
+
let wrapped = effect;
|
|
589
|
+
for (const directiveApp of directives) {
|
|
590
|
+
const directiveReg = directiveRegistrations.get(directiveApp.name);
|
|
591
|
+
if (directiveReg?.apply) {
|
|
592
|
+
wrapped = directiveReg.apply(directiveApp.args ?? {})(wrapped);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return wrapped;
|
|
596
|
+
}
|
|
597
|
+
function applyMiddleware(effect, context, middlewares) {
|
|
598
|
+
if (middlewares.length === 0) return effect;
|
|
599
|
+
let wrapped = effect;
|
|
600
|
+
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
601
|
+
const middleware2 = middlewares[i];
|
|
602
|
+
if (middleware2.match && !middleware2.match(context.info)) {
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
wrapped = middleware2.apply(wrapped, context);
|
|
606
|
+
}
|
|
607
|
+
return wrapped;
|
|
608
|
+
}
|
|
609
|
+
function buildField(config, ctx) {
|
|
610
|
+
const fieldConfig = {
|
|
611
|
+
type: toGraphQLTypeWithRegistry(config.type, ctx),
|
|
612
|
+
resolve: async (_parent, args, context, info) => {
|
|
613
|
+
let effect$1 = applyDirectives(
|
|
614
|
+
config.resolve(args),
|
|
615
|
+
config.directives,
|
|
616
|
+
ctx.directiveRegistrations
|
|
617
|
+
);
|
|
618
|
+
const middlewareContext = { parent: _parent, args, info };
|
|
619
|
+
effect$1 = applyMiddleware(effect$1, middlewareContext, ctx.middlewares);
|
|
620
|
+
return await effect.Runtime.runPromise(context.runtime)(effect$1);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
if (config.args) {
|
|
624
|
+
fieldConfig.args = toGraphQLArgsWithRegistry(
|
|
625
|
+
config.args,
|
|
626
|
+
ctx.enumRegistry,
|
|
627
|
+
ctx.inputRegistry,
|
|
628
|
+
ctx.inputs,
|
|
629
|
+
ctx.enums,
|
|
630
|
+
ctx.inputTypeLookupCache
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
if (config.description) {
|
|
634
|
+
fieldConfig.description = config.description;
|
|
635
|
+
}
|
|
636
|
+
return fieldConfig;
|
|
637
|
+
}
|
|
638
|
+
function buildObjectField(config, ctx) {
|
|
639
|
+
const fieldConfig = {
|
|
640
|
+
type: toGraphQLTypeWithRegistry(config.type, ctx),
|
|
641
|
+
resolve: async (parent, args, context, info) => {
|
|
642
|
+
let effect$1 = applyDirectives(
|
|
643
|
+
config.resolve(parent, args),
|
|
644
|
+
config.directives,
|
|
645
|
+
ctx.directiveRegistrations
|
|
646
|
+
);
|
|
647
|
+
const middlewareContext = { parent, args, info };
|
|
648
|
+
effect$1 = applyMiddleware(effect$1, middlewareContext, ctx.middlewares);
|
|
649
|
+
return await effect.Runtime.runPromise(context.runtime)(effect$1);
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
if (config.args) {
|
|
653
|
+
fieldConfig.args = toGraphQLArgsWithRegistry(
|
|
654
|
+
config.args,
|
|
655
|
+
ctx.enumRegistry,
|
|
656
|
+
ctx.inputRegistry,
|
|
657
|
+
ctx.inputs,
|
|
658
|
+
ctx.enums,
|
|
659
|
+
ctx.inputTypeLookupCache
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
if (config.description) {
|
|
663
|
+
fieldConfig.description = config.description;
|
|
664
|
+
}
|
|
665
|
+
return fieldConfig;
|
|
666
|
+
}
|
|
667
|
+
function buildSubscriptionField(config, ctx) {
|
|
668
|
+
const fieldConfig = {
|
|
669
|
+
type: toGraphQLTypeWithRegistry(config.type, ctx),
|
|
670
|
+
// The subscribe function returns an AsyncIterator
|
|
671
|
+
subscribe: async (_parent, args, context, info) => {
|
|
672
|
+
let subscribeEffect = config.subscribe(args);
|
|
673
|
+
subscribeEffect = applyDirectives(
|
|
674
|
+
subscribeEffect,
|
|
675
|
+
config.directives,
|
|
676
|
+
ctx.directiveRegistrations
|
|
677
|
+
);
|
|
678
|
+
const middlewareContext = { parent: _parent, args, info };
|
|
679
|
+
subscribeEffect = applyMiddleware(subscribeEffect, middlewareContext, ctx.middlewares);
|
|
680
|
+
const stream = await effect.Runtime.runPromise(context.runtime)(subscribeEffect);
|
|
681
|
+
return streamToAsyncIterator(stream, context.runtime);
|
|
682
|
+
},
|
|
683
|
+
// The resolve function transforms each yielded value
|
|
684
|
+
// If no custom resolve is provided, return the payload directly
|
|
685
|
+
resolve: config.resolve ? async (value, args, context, info) => {
|
|
686
|
+
let effect$1 = config.resolve(value, args);
|
|
687
|
+
const middlewareContext = { parent: value, args, info };
|
|
688
|
+
effect$1 = applyMiddleware(effect$1, middlewareContext, ctx.middlewares);
|
|
689
|
+
return await effect.Runtime.runPromise(context.runtime)(effect$1);
|
|
690
|
+
} : (value) => value
|
|
691
|
+
};
|
|
692
|
+
if (config.args) {
|
|
693
|
+
fieldConfig.args = toGraphQLArgsWithRegistry(
|
|
694
|
+
config.args,
|
|
695
|
+
ctx.enumRegistry,
|
|
696
|
+
ctx.inputRegistry,
|
|
697
|
+
ctx.inputs,
|
|
698
|
+
ctx.enums,
|
|
699
|
+
ctx.inputTypeLookupCache
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
if (config.description) {
|
|
703
|
+
fieldConfig.description = config.description;
|
|
704
|
+
}
|
|
705
|
+
return fieldConfig;
|
|
706
|
+
}
|
|
707
|
+
function streamToAsyncIterator(stream, runtime) {
|
|
708
|
+
let queue;
|
|
709
|
+
let fiber;
|
|
710
|
+
let initialized = false;
|
|
711
|
+
let done = false;
|
|
712
|
+
const initialize = async () => {
|
|
713
|
+
if (initialized) return;
|
|
714
|
+
initialized = true;
|
|
715
|
+
queue = await effect.Runtime.runPromise(runtime)(effect.Queue.unbounded());
|
|
716
|
+
fiber = effect.Runtime.runFork(runtime)(
|
|
717
|
+
effect.Effect.ensuring(
|
|
718
|
+
effect.Stream.runForEach(stream, (value) => effect.Queue.offer(queue, effect.Option.some(value))),
|
|
719
|
+
// Signal completion by pushing None
|
|
720
|
+
effect.Queue.offer(queue, effect.Option.none())
|
|
721
|
+
)
|
|
722
|
+
);
|
|
723
|
+
};
|
|
724
|
+
return {
|
|
725
|
+
[Symbol.asyncIterator]() {
|
|
726
|
+
return this;
|
|
727
|
+
},
|
|
728
|
+
async next() {
|
|
729
|
+
await initialize();
|
|
730
|
+
if (done) {
|
|
731
|
+
return { done: true, value: void 0 };
|
|
732
|
+
}
|
|
733
|
+
try {
|
|
734
|
+
const optionValue = await effect.Runtime.runPromise(runtime)(effect.Queue.take(queue));
|
|
735
|
+
if (effect.Option.isNone(optionValue)) {
|
|
736
|
+
done = true;
|
|
737
|
+
return { done: true, value: void 0 };
|
|
738
|
+
}
|
|
739
|
+
return { done: false, value: optionValue.value };
|
|
740
|
+
} catch (error) {
|
|
741
|
+
done = true;
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
async return() {
|
|
746
|
+
done = true;
|
|
747
|
+
if (initialized) {
|
|
748
|
+
try {
|
|
749
|
+
await effect.Runtime.runPromise(runtime)(
|
|
750
|
+
effect.Fiber.interrupt(fiber)
|
|
751
|
+
);
|
|
752
|
+
await effect.Runtime.runPromise(runtime)(effect.Queue.shutdown(queue));
|
|
753
|
+
} catch {
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return { done: true, value: void 0 };
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// src/builder/schema-builder.ts
|
|
762
|
+
function updateState(state, key, value) {
|
|
763
|
+
return { ...state, [key]: value };
|
|
764
|
+
}
|
|
765
|
+
var GraphQLSchemaBuilder = class _GraphQLSchemaBuilder {
|
|
766
|
+
constructor(state) {
|
|
767
|
+
this.state = state;
|
|
768
|
+
}
|
|
769
|
+
pipe() {
|
|
770
|
+
return effect.Pipeable.pipeArguments(this, arguments);
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Create an empty schema builder
|
|
774
|
+
*/
|
|
775
|
+
static empty = new _GraphQLSchemaBuilder({
|
|
776
|
+
types: /* @__PURE__ */ new Map(),
|
|
777
|
+
interfaces: /* @__PURE__ */ new Map(),
|
|
778
|
+
enums: /* @__PURE__ */ new Map(),
|
|
779
|
+
unions: /* @__PURE__ */ new Map(),
|
|
780
|
+
inputs: /* @__PURE__ */ new Map(),
|
|
781
|
+
directives: /* @__PURE__ */ new Map(),
|
|
782
|
+
middlewares: [],
|
|
783
|
+
extensions: [],
|
|
784
|
+
queries: /* @__PURE__ */ new Map(),
|
|
785
|
+
mutations: /* @__PURE__ */ new Map(),
|
|
786
|
+
subscriptions: /* @__PURE__ */ new Map(),
|
|
787
|
+
objectFields: /* @__PURE__ */ new Map()
|
|
788
|
+
});
|
|
789
|
+
/**
|
|
790
|
+
* Create a new builder with updated state
|
|
791
|
+
*/
|
|
792
|
+
with(newState) {
|
|
793
|
+
return new _GraphQLSchemaBuilder(newState);
|
|
794
|
+
}
|
|
795
|
+
// ============================================================================
|
|
796
|
+
// Registration Methods
|
|
797
|
+
// ============================================================================
|
|
798
|
+
/**
|
|
799
|
+
* Add a query field
|
|
800
|
+
*/
|
|
801
|
+
query(name, config) {
|
|
802
|
+
const newQueries = new Map(this.state.queries);
|
|
803
|
+
newQueries.set(name, config);
|
|
804
|
+
return this.with(updateState(this.state, "queries", newQueries));
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Add a mutation field
|
|
808
|
+
*/
|
|
809
|
+
mutation(name, config) {
|
|
810
|
+
const newMutations = new Map(this.state.mutations);
|
|
811
|
+
newMutations.set(name, config);
|
|
812
|
+
return this.with(updateState(this.state, "mutations", newMutations));
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Add a subscription field
|
|
816
|
+
*
|
|
817
|
+
* Subscriptions return a Stream that yields values over time.
|
|
818
|
+
* The subscribe function returns an Effect that produces a Stream.
|
|
819
|
+
*
|
|
820
|
+
* @example
|
|
821
|
+
* ```typescript
|
|
822
|
+
* builder.subscription("userCreated", {
|
|
823
|
+
* type: User,
|
|
824
|
+
* subscribe: Effect.gen(function*() {
|
|
825
|
+
* const pubsub = yield* PubSubService
|
|
826
|
+
* return pubsub.subscribe("USER_CREATED")
|
|
827
|
+
* }),
|
|
828
|
+
* })
|
|
829
|
+
* ```
|
|
830
|
+
*/
|
|
831
|
+
subscription(name, config) {
|
|
832
|
+
const newSubscriptions = new Map(this.state.subscriptions);
|
|
833
|
+
newSubscriptions.set(name, config);
|
|
834
|
+
return this.with(updateState(this.state, "subscriptions", newSubscriptions));
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Register an object type from a schema
|
|
838
|
+
*/
|
|
839
|
+
objectType(config) {
|
|
840
|
+
const { schema, implements: implementsInterfaces, directives, cacheControl, fields } = config;
|
|
841
|
+
const name = config.name ?? getSchemaName(schema);
|
|
842
|
+
if (!name) {
|
|
843
|
+
throw new Error(
|
|
844
|
+
"objectType requires a name. Either provide one explicitly or use a TaggedStruct/TaggedClass/Schema.Class"
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
const newTypes = new Map(this.state.types);
|
|
848
|
+
newTypes.set(name, { name, schema, implements: implementsInterfaces, directives, cacheControl });
|
|
849
|
+
let newObjectFields = this.state.objectFields;
|
|
850
|
+
if (fields) {
|
|
851
|
+
newObjectFields = new Map(this.state.objectFields);
|
|
852
|
+
const typeFields = /* @__PURE__ */ new Map();
|
|
853
|
+
for (const [fieldName, fieldConfig] of Object.entries(fields)) {
|
|
854
|
+
typeFields.set(fieldName, fieldConfig);
|
|
855
|
+
}
|
|
856
|
+
newObjectFields.set(name, typeFields);
|
|
857
|
+
}
|
|
858
|
+
return this.with({
|
|
859
|
+
...this.state,
|
|
860
|
+
types: newTypes,
|
|
861
|
+
objectFields: newObjectFields
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Register an interface type from a schema
|
|
866
|
+
*/
|
|
867
|
+
interfaceType(config) {
|
|
868
|
+
const { schema, resolveType, directives } = config;
|
|
869
|
+
const name = config.name ?? getSchemaName(schema);
|
|
870
|
+
if (!name) {
|
|
871
|
+
throw new Error(
|
|
872
|
+
"interfaceType requires a name. Either provide one explicitly or use a TaggedStruct/TaggedClass/Schema.Class"
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
const newInterfaces = new Map(this.state.interfaces);
|
|
876
|
+
newInterfaces.set(name, {
|
|
877
|
+
name,
|
|
878
|
+
schema,
|
|
879
|
+
resolveType: resolveType ?? ((value) => value._tag),
|
|
880
|
+
directives
|
|
881
|
+
});
|
|
882
|
+
return this.with(updateState(this.state, "interfaces", newInterfaces));
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Register an enum type
|
|
886
|
+
*/
|
|
887
|
+
enumType(config) {
|
|
888
|
+
const { name, values, description, directives } = config;
|
|
889
|
+
const newEnums = new Map(this.state.enums);
|
|
890
|
+
newEnums.set(name, { name, values, description, directives });
|
|
891
|
+
return this.with(updateState(this.state, "enums", newEnums));
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Register a union type
|
|
895
|
+
*/
|
|
896
|
+
unionType(config) {
|
|
897
|
+
const { name, types, resolveType, directives } = config;
|
|
898
|
+
const newUnions = new Map(this.state.unions);
|
|
899
|
+
newUnions.set(name, {
|
|
900
|
+
name,
|
|
901
|
+
types,
|
|
902
|
+
resolveType: resolveType ?? ((value) => value._tag),
|
|
903
|
+
directives
|
|
904
|
+
});
|
|
905
|
+
return this.with(updateState(this.state, "unions", newUnions));
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Register an input type
|
|
909
|
+
*/
|
|
910
|
+
inputType(config) {
|
|
911
|
+
const { schema, description, directives } = config;
|
|
912
|
+
const name = config.name ?? getSchemaName(schema);
|
|
913
|
+
if (!name) {
|
|
914
|
+
throw new Error(
|
|
915
|
+
"inputType requires a name. Either provide one explicitly or use a TaggedStruct/TaggedClass/Schema.Class"
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
const newInputs = new Map(this.state.inputs);
|
|
919
|
+
newInputs.set(name, { name, schema, description, directives });
|
|
920
|
+
return this.with(updateState(this.state, "inputs", newInputs));
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Register a directive
|
|
924
|
+
*/
|
|
925
|
+
directive(config) {
|
|
926
|
+
const newDirectives = new Map(this.state.directives);
|
|
927
|
+
newDirectives.set(config.name, config);
|
|
928
|
+
return this.with(updateState(this.state, "directives", newDirectives));
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Register a middleware
|
|
932
|
+
*
|
|
933
|
+
* Middleware wraps all resolvers (or those matching a pattern) and executes
|
|
934
|
+
* in an "onion" model - first registered middleware is the outermost layer.
|
|
935
|
+
*
|
|
936
|
+
* @param config.name - Middleware name (for debugging/logging)
|
|
937
|
+
* @param config.description - Optional description
|
|
938
|
+
* @param config.match - Optional predicate to filter which fields this applies to
|
|
939
|
+
* @param config.apply - Function that transforms the resolver Effect
|
|
940
|
+
*
|
|
941
|
+
* @example
|
|
942
|
+
* ```typescript
|
|
943
|
+
* builder.middleware({
|
|
944
|
+
* name: "logging",
|
|
945
|
+
* apply: (effect, ctx) => Effect.gen(function*() {
|
|
946
|
+
* yield* Effect.logInfo(`Resolving ${ctx.info.fieldName}`)
|
|
947
|
+
* const start = Date.now()
|
|
948
|
+
* const result = yield* effect
|
|
949
|
+
* yield* Effect.logInfo(`Resolved in ${Date.now() - start}ms`)
|
|
950
|
+
* return result
|
|
951
|
+
* })
|
|
952
|
+
* })
|
|
953
|
+
* ```
|
|
954
|
+
*/
|
|
955
|
+
middleware(config) {
|
|
956
|
+
const newMiddlewares = [...this.state.middlewares, config];
|
|
957
|
+
return this.with({ ...this.state, middlewares: newMiddlewares });
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Register an extension
|
|
961
|
+
*
|
|
962
|
+
* Extensions provide lifecycle hooks that run at each phase of request processing
|
|
963
|
+
* (parse, validate, execute) and can contribute data to the response's extensions field.
|
|
964
|
+
*
|
|
965
|
+
* @param config.name - Extension name (for debugging/logging)
|
|
966
|
+
* @param config.description - Optional description
|
|
967
|
+
* @param config.onParse - Called after query parsing
|
|
968
|
+
* @param config.onValidate - Called after validation
|
|
969
|
+
* @param config.onExecuteStart - Called before execution begins
|
|
970
|
+
* @param config.onExecuteEnd - Called after execution completes
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* ```typescript
|
|
974
|
+
* builder.extension({
|
|
975
|
+
* name: "tracing",
|
|
976
|
+
* onExecuteStart: () => Effect.gen(function*() {
|
|
977
|
+
* const ext = yield* ExtensionsService
|
|
978
|
+
* yield* ext.set("tracing", { startTime: Date.now() })
|
|
979
|
+
* }),
|
|
980
|
+
* onExecuteEnd: () => Effect.gen(function*() {
|
|
981
|
+
* const ext = yield* ExtensionsService
|
|
982
|
+
* yield* ext.merge("tracing", { endTime: Date.now() })
|
|
983
|
+
* }),
|
|
984
|
+
* })
|
|
985
|
+
* ```
|
|
986
|
+
*/
|
|
987
|
+
extension(config) {
|
|
988
|
+
const newExtensions = [...this.state.extensions, config];
|
|
989
|
+
return this.with({ ...this.state, extensions: newExtensions });
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Get the registered extensions for use by the execution layer
|
|
993
|
+
*/
|
|
994
|
+
getExtensions() {
|
|
995
|
+
return this.state.extensions;
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Add a computed/relational field to an object type
|
|
999
|
+
*/
|
|
1000
|
+
field(typeName, fieldName, config) {
|
|
1001
|
+
const newObjectFields = new Map(this.state.objectFields);
|
|
1002
|
+
const typeFields = newObjectFields.get(typeName) || /* @__PURE__ */ new Map();
|
|
1003
|
+
typeFields.set(fieldName, config);
|
|
1004
|
+
newObjectFields.set(typeName, typeFields);
|
|
1005
|
+
return this.with(updateState(this.state, "objectFields", newObjectFields));
|
|
1006
|
+
}
|
|
1007
|
+
// ============================================================================
|
|
1008
|
+
// Schema Building
|
|
1009
|
+
// ============================================================================
|
|
1010
|
+
/**
|
|
1011
|
+
* Get the field complexity map for use in complexity validation.
|
|
1012
|
+
* Maps "TypeName.fieldName" to the complexity value or function.
|
|
1013
|
+
*/
|
|
1014
|
+
getFieldComplexities() {
|
|
1015
|
+
const complexities = /* @__PURE__ */ new Map();
|
|
1016
|
+
for (const [name, config] of this.state.queries) {
|
|
1017
|
+
if (config.complexity !== void 0) {
|
|
1018
|
+
complexities.set(`Query.${name}`, config.complexity);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
for (const [name, config] of this.state.mutations) {
|
|
1022
|
+
if (config.complexity !== void 0) {
|
|
1023
|
+
complexities.set(`Mutation.${name}`, config.complexity);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
for (const [name, config] of this.state.subscriptions) {
|
|
1027
|
+
if (config.complexity !== void 0) {
|
|
1028
|
+
complexities.set(`Subscription.${name}`, config.complexity);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
for (const [typeName, fields] of this.state.objectFields) {
|
|
1032
|
+
for (const [fieldName, config] of fields) {
|
|
1033
|
+
if (config.complexity !== void 0) {
|
|
1034
|
+
complexities.set(`${typeName}.${fieldName}`, config.complexity);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
return complexities;
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Get the cache hint map for use in cache control calculation.
|
|
1042
|
+
* Maps "TypeName.fieldName" to the cache hint for field-level hints,
|
|
1043
|
+
* or "TypeName" to the cache hint for type-level hints.
|
|
1044
|
+
*/
|
|
1045
|
+
getCacheHints() {
|
|
1046
|
+
const hints = /* @__PURE__ */ new Map();
|
|
1047
|
+
for (const [typeName, typeReg] of this.state.types) {
|
|
1048
|
+
if (typeReg.cacheControl !== void 0) {
|
|
1049
|
+
hints.set(typeName, typeReg.cacheControl);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
for (const [name, config] of this.state.queries) {
|
|
1053
|
+
if (config.cacheControl !== void 0) {
|
|
1054
|
+
hints.set(`Query.${name}`, config.cacheControl);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
for (const [name, config] of this.state.subscriptions) {
|
|
1058
|
+
if (config.cacheControl !== void 0) {
|
|
1059
|
+
hints.set(`Subscription.${name}`, config.cacheControl);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
for (const [typeName, fields] of this.state.objectFields) {
|
|
1063
|
+
for (const [fieldName, config] of fields) {
|
|
1064
|
+
if (config.cacheControl !== void 0) {
|
|
1065
|
+
hints.set(`${typeName}.${fieldName}`, config.cacheControl);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
return hints;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Build the GraphQL schema (no services required)
|
|
1073
|
+
*/
|
|
1074
|
+
buildSchema() {
|
|
1075
|
+
const directiveRegistry = this.buildDirectiveRegistry();
|
|
1076
|
+
const enumRegistry = this.buildEnumRegistry();
|
|
1077
|
+
const inputRegistry = this.buildInputRegistry(enumRegistry);
|
|
1078
|
+
const interfaceRegistry = this.buildInterfaceRegistry(enumRegistry);
|
|
1079
|
+
const { typeRegistry, unionRegistry } = this.buildTypeAndUnionRegistries(
|
|
1080
|
+
enumRegistry,
|
|
1081
|
+
interfaceRegistry
|
|
1082
|
+
);
|
|
1083
|
+
const fieldCtx = this.createFieldBuilderContext(
|
|
1084
|
+
typeRegistry,
|
|
1085
|
+
interfaceRegistry,
|
|
1086
|
+
enumRegistry,
|
|
1087
|
+
unionRegistry,
|
|
1088
|
+
inputRegistry
|
|
1089
|
+
);
|
|
1090
|
+
const queryFields = this.buildQueryFields(fieldCtx);
|
|
1091
|
+
const mutationFields = this.buildMutationFields(fieldCtx);
|
|
1092
|
+
const subscriptionFields = this.buildSubscriptionFields(fieldCtx);
|
|
1093
|
+
return this.assembleSchema({
|
|
1094
|
+
directiveRegistry,
|
|
1095
|
+
enumRegistry,
|
|
1096
|
+
inputRegistry,
|
|
1097
|
+
interfaceRegistry,
|
|
1098
|
+
typeRegistry,
|
|
1099
|
+
unionRegistry,
|
|
1100
|
+
queryFields,
|
|
1101
|
+
mutationFields,
|
|
1102
|
+
subscriptionFields
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
buildDirectiveRegistry() {
|
|
1106
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1107
|
+
const cache = buildInputTypeLookupCache(this.state.inputs, this.state.enums);
|
|
1108
|
+
for (const [name, reg] of this.state.directives) {
|
|
1109
|
+
const graphqlDirective = new graphql.GraphQLDirective({
|
|
1110
|
+
name,
|
|
1111
|
+
description: reg.description,
|
|
1112
|
+
locations: [...reg.locations],
|
|
1113
|
+
args: reg.args ? toGraphQLArgsWithRegistry(
|
|
1114
|
+
reg.args,
|
|
1115
|
+
/* @__PURE__ */ new Map(),
|
|
1116
|
+
/* @__PURE__ */ new Map(),
|
|
1117
|
+
this.state.inputs,
|
|
1118
|
+
this.state.enums,
|
|
1119
|
+
cache
|
|
1120
|
+
) : void 0
|
|
1121
|
+
});
|
|
1122
|
+
registry.set(name, graphqlDirective);
|
|
1123
|
+
}
|
|
1124
|
+
return registry;
|
|
1125
|
+
}
|
|
1126
|
+
buildEnumRegistry() {
|
|
1127
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1128
|
+
for (const [name, reg] of this.state.enums) {
|
|
1129
|
+
const enumValues = {};
|
|
1130
|
+
for (const value of reg.values) {
|
|
1131
|
+
enumValues[value] = { value };
|
|
1132
|
+
}
|
|
1133
|
+
registry.set(
|
|
1134
|
+
name,
|
|
1135
|
+
new graphql.GraphQLEnumType({
|
|
1136
|
+
name,
|
|
1137
|
+
values: enumValues,
|
|
1138
|
+
description: reg.description,
|
|
1139
|
+
extensions: reg.directives ? { directives: reg.directives } : void 0
|
|
1140
|
+
})
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
return registry;
|
|
1144
|
+
}
|
|
1145
|
+
buildInputRegistry(enumRegistry) {
|
|
1146
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1147
|
+
const cache = buildInputTypeLookupCache(this.state.inputs, this.state.enums);
|
|
1148
|
+
for (const [name, reg] of this.state.inputs) {
|
|
1149
|
+
const inputType2 = new graphql.GraphQLInputObjectType({
|
|
1150
|
+
name,
|
|
1151
|
+
description: reg.description,
|
|
1152
|
+
fields: () => schemaToInputFields(
|
|
1153
|
+
reg.schema,
|
|
1154
|
+
enumRegistry,
|
|
1155
|
+
registry,
|
|
1156
|
+
this.state.inputs,
|
|
1157
|
+
this.state.enums,
|
|
1158
|
+
cache
|
|
1159
|
+
),
|
|
1160
|
+
extensions: reg.directives ? { directives: reg.directives } : void 0
|
|
1161
|
+
});
|
|
1162
|
+
registry.set(name, inputType2);
|
|
1163
|
+
}
|
|
1164
|
+
return registry;
|
|
1165
|
+
}
|
|
1166
|
+
buildInterfaceRegistry(enumRegistry) {
|
|
1167
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1168
|
+
const typeRegistry = /* @__PURE__ */ new Map();
|
|
1169
|
+
const unionRegistry = /* @__PURE__ */ new Map();
|
|
1170
|
+
const sharedCtx = {
|
|
1171
|
+
types: this.state.types,
|
|
1172
|
+
interfaces: this.state.interfaces,
|
|
1173
|
+
enums: this.state.enums,
|
|
1174
|
+
unions: this.state.unions,
|
|
1175
|
+
inputs: this.state.inputs,
|
|
1176
|
+
typeRegistry,
|
|
1177
|
+
interfaceRegistry: registry,
|
|
1178
|
+
enumRegistry,
|
|
1179
|
+
unionRegistry};
|
|
1180
|
+
buildReverseLookups(sharedCtx);
|
|
1181
|
+
for (const [name, reg] of this.state.interfaces) {
|
|
1182
|
+
const interfaceType2 = new graphql.GraphQLInterfaceType({
|
|
1183
|
+
name,
|
|
1184
|
+
fields: () => schemaToFields(reg.schema, sharedCtx),
|
|
1185
|
+
resolveType: reg.resolveType,
|
|
1186
|
+
extensions: reg.directives ? { directives: reg.directives } : void 0
|
|
1187
|
+
});
|
|
1188
|
+
registry.set(name, interfaceType2);
|
|
1189
|
+
}
|
|
1190
|
+
return registry;
|
|
1191
|
+
}
|
|
1192
|
+
buildTypeAndUnionRegistries(enumRegistry, interfaceRegistry) {
|
|
1193
|
+
const typeRegistry = /* @__PURE__ */ new Map();
|
|
1194
|
+
const unionRegistry = /* @__PURE__ */ new Map();
|
|
1195
|
+
const sharedCtx = {
|
|
1196
|
+
types: this.state.types,
|
|
1197
|
+
interfaces: this.state.interfaces,
|
|
1198
|
+
enums: this.state.enums,
|
|
1199
|
+
unions: this.state.unions,
|
|
1200
|
+
inputs: this.state.inputs,
|
|
1201
|
+
typeRegistry,
|
|
1202
|
+
interfaceRegistry,
|
|
1203
|
+
enumRegistry,
|
|
1204
|
+
unionRegistry};
|
|
1205
|
+
buildReverseLookups(sharedCtx);
|
|
1206
|
+
const sharedFieldCtx = this.createFieldBuilderContext(
|
|
1207
|
+
typeRegistry,
|
|
1208
|
+
interfaceRegistry,
|
|
1209
|
+
enumRegistry,
|
|
1210
|
+
unionRegistry,
|
|
1211
|
+
/* @__PURE__ */ new Map()
|
|
1212
|
+
);
|
|
1213
|
+
for (const [typeName, typeReg] of this.state.types) {
|
|
1214
|
+
const implementedInterfaces = typeReg.implements?.map((name) => interfaceRegistry.get(name)).filter(Boolean) ?? [];
|
|
1215
|
+
const graphqlType = new graphql.GraphQLObjectType({
|
|
1216
|
+
name: typeName,
|
|
1217
|
+
fields: () => {
|
|
1218
|
+
const baseFields = schemaToFields(typeReg.schema, sharedCtx);
|
|
1219
|
+
const additionalFields = this.state.objectFields.get(typeName);
|
|
1220
|
+
if (additionalFields) {
|
|
1221
|
+
for (const [fieldName, fieldConfig] of additionalFields) {
|
|
1222
|
+
baseFields[fieldName] = buildObjectField(fieldConfig, sharedFieldCtx);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
return baseFields;
|
|
1226
|
+
},
|
|
1227
|
+
interfaces: implementedInterfaces.length > 0 ? implementedInterfaces : void 0,
|
|
1228
|
+
extensions: typeReg.directives ? { directives: typeReg.directives } : void 0
|
|
1229
|
+
});
|
|
1230
|
+
typeRegistry.set(typeName, graphqlType);
|
|
1231
|
+
}
|
|
1232
|
+
for (const [name, reg] of this.state.unions) {
|
|
1233
|
+
const unionType2 = new graphql.GraphQLUnionType({
|
|
1234
|
+
name,
|
|
1235
|
+
types: () => reg.types.map((typeName) => typeRegistry.get(typeName)).filter(Boolean),
|
|
1236
|
+
resolveType: reg.resolveType,
|
|
1237
|
+
extensions: reg.directives ? { directives: reg.directives } : void 0
|
|
1238
|
+
});
|
|
1239
|
+
unionRegistry.set(name, unionType2);
|
|
1240
|
+
}
|
|
1241
|
+
return { typeRegistry, unionRegistry };
|
|
1242
|
+
}
|
|
1243
|
+
createFieldBuilderContext(typeRegistry, interfaceRegistry, enumRegistry, unionRegistry, inputRegistry) {
|
|
1244
|
+
const inputTypeLookupCache = buildInputTypeLookupCache(this.state.inputs, this.state.enums);
|
|
1245
|
+
return {
|
|
1246
|
+
types: this.state.types,
|
|
1247
|
+
interfaces: this.state.interfaces,
|
|
1248
|
+
enums: this.state.enums,
|
|
1249
|
+
unions: this.state.unions,
|
|
1250
|
+
inputs: this.state.inputs,
|
|
1251
|
+
typeRegistry,
|
|
1252
|
+
interfaceRegistry,
|
|
1253
|
+
enumRegistry,
|
|
1254
|
+
unionRegistry,
|
|
1255
|
+
inputRegistry,
|
|
1256
|
+
directiveRegistrations: this.state.directives,
|
|
1257
|
+
middlewares: this.state.middlewares,
|
|
1258
|
+
inputTypeLookupCache
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
buildQueryFields(ctx) {
|
|
1262
|
+
const fields = {};
|
|
1263
|
+
for (const [name, config] of this.state.queries) {
|
|
1264
|
+
fields[name] = buildField(config, ctx);
|
|
1265
|
+
}
|
|
1266
|
+
return fields;
|
|
1267
|
+
}
|
|
1268
|
+
buildMutationFields(ctx) {
|
|
1269
|
+
const fields = {};
|
|
1270
|
+
for (const [name, config] of this.state.mutations) {
|
|
1271
|
+
fields[name] = buildField(config, ctx);
|
|
1272
|
+
}
|
|
1273
|
+
return fields;
|
|
1274
|
+
}
|
|
1275
|
+
buildSubscriptionFields(ctx) {
|
|
1276
|
+
const fields = {};
|
|
1277
|
+
for (const [name, config] of this.state.subscriptions) {
|
|
1278
|
+
fields[name] = buildSubscriptionField(config, ctx);
|
|
1279
|
+
}
|
|
1280
|
+
return fields;
|
|
1281
|
+
}
|
|
1282
|
+
assembleSchema(registries) {
|
|
1283
|
+
const schemaConfig = {
|
|
1284
|
+
types: [
|
|
1285
|
+
...Array.from(registries.enumRegistry.values()),
|
|
1286
|
+
...Array.from(registries.inputRegistry.values()),
|
|
1287
|
+
...Array.from(registries.interfaceRegistry.values()),
|
|
1288
|
+
...Array.from(registries.typeRegistry.values()),
|
|
1289
|
+
...Array.from(registries.unionRegistry.values())
|
|
1290
|
+
],
|
|
1291
|
+
directives: registries.directiveRegistry.size > 0 ? [...Array.from(registries.directiveRegistry.values())] : void 0
|
|
1292
|
+
};
|
|
1293
|
+
if (Object.keys(registries.queryFields).length > 0) {
|
|
1294
|
+
schemaConfig.query = new graphql.GraphQLObjectType({
|
|
1295
|
+
name: "Query",
|
|
1296
|
+
fields: registries.queryFields
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
if (Object.keys(registries.mutationFields).length > 0) {
|
|
1300
|
+
schemaConfig.mutation = new graphql.GraphQLObjectType({
|
|
1301
|
+
name: "Mutation",
|
|
1302
|
+
fields: registries.mutationFields
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
if (Object.keys(registries.subscriptionFields).length > 0) {
|
|
1306
|
+
schemaConfig.subscription = new graphql.GraphQLObjectType({
|
|
1307
|
+
name: "Subscription",
|
|
1308
|
+
fields: registries.subscriptionFields
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
return new graphql.GraphQLSchema(schemaConfig);
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
|
|
1315
|
+
// src/builder/pipe-api.ts
|
|
1316
|
+
var objectType = (config) => (builder) => builder.objectType(config);
|
|
1317
|
+
var interfaceType = (config) => (builder) => builder.interfaceType(config);
|
|
1318
|
+
var enumType = (config) => (builder) => builder.enumType(config);
|
|
1319
|
+
var unionType = (config) => (builder) => builder.unionType(config);
|
|
1320
|
+
var inputType = (config) => (builder) => builder.inputType(config);
|
|
1321
|
+
var directive = (config) => (builder) => builder.directive(config);
|
|
1322
|
+
var middleware = (config) => (builder) => builder.middleware(config);
|
|
1323
|
+
var extension = (config) => (builder) => builder.extension(config);
|
|
1324
|
+
var query = (name, config) => (builder) => builder.query(name, config);
|
|
1325
|
+
var mutation = (name, config) => (builder) => builder.mutation(name, config);
|
|
1326
|
+
var subscription = (name, config) => (builder) => builder.subscription(name, config);
|
|
1327
|
+
var field = (typeName, fieldName, config) => (builder) => builder.field(typeName, fieldName, config);
|
|
1328
|
+
var compose = (...operations) => (builder) => operations.reduce((b, op) => op(b), builder);
|
|
1329
|
+
var ExtensionsService = effect.Context.GenericTag(
|
|
1330
|
+
"@effect-gql/ExtensionsService"
|
|
1331
|
+
);
|
|
1332
|
+
function deepMerge(target, source) {
|
|
1333
|
+
const result = { ...target };
|
|
1334
|
+
for (const key of Object.keys(source)) {
|
|
1335
|
+
const sourceValue = source[key];
|
|
1336
|
+
const targetValue = result[key];
|
|
1337
|
+
if (typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
|
|
1338
|
+
result[key] = deepMerge(
|
|
1339
|
+
targetValue,
|
|
1340
|
+
sourceValue
|
|
1341
|
+
);
|
|
1342
|
+
} else {
|
|
1343
|
+
result[key] = sourceValue;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return result;
|
|
1347
|
+
}
|
|
1348
|
+
var makeExtensionsService = () => effect.Effect.gen(function* () {
|
|
1349
|
+
const ref = yield* effect.Ref.make({});
|
|
1350
|
+
return ExtensionsService.of({
|
|
1351
|
+
set: (key, value) => effect.Ref.update(ref, (current) => ({ ...current, [key]: value })),
|
|
1352
|
+
merge: (key, value) => effect.Ref.update(ref, (current) => {
|
|
1353
|
+
const existing = current[key];
|
|
1354
|
+
if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
|
|
1355
|
+
return {
|
|
1356
|
+
...current,
|
|
1357
|
+
[key]: deepMerge(existing, value)
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
return { ...current, [key]: value };
|
|
1361
|
+
}),
|
|
1362
|
+
get: () => effect.Ref.get(ref)
|
|
1363
|
+
});
|
|
1364
|
+
});
|
|
1365
|
+
var runExtensionHooks = (extensions, hookName, getHookEffect) => effect.Effect.forEach(
|
|
1366
|
+
extensions.filter((ext) => ext[hookName] !== void 0),
|
|
1367
|
+
(ext) => getHookEffect(ext).pipe(
|
|
1368
|
+
effect.Effect.catchAllCause(
|
|
1369
|
+
(cause) => effect.Effect.logWarning(`Extension "${ext.name}" ${String(hookName)} hook failed`, cause)
|
|
1370
|
+
)
|
|
1371
|
+
),
|
|
1372
|
+
{ discard: true }
|
|
1373
|
+
);
|
|
1374
|
+
var runParseHooks = (extensions, source, document) => runExtensionHooks(extensions, "onParse", (ext) => ext.onParse(source, document));
|
|
1375
|
+
var runValidateHooks = (extensions, document, errors) => runExtensionHooks(extensions, "onValidate", (ext) => ext.onValidate(document, errors));
|
|
1376
|
+
var runExecuteStartHooks = (extensions, args) => runExtensionHooks(extensions, "onExecuteStart", (ext) => ext.onExecuteStart(args));
|
|
1377
|
+
var runExecuteEndHooks = (extensions, result) => runExtensionHooks(extensions, "onExecuteEnd", (ext) => ext.onExecuteEnd(result));
|
|
1378
|
+
|
|
1379
|
+
// src/builder/execute.ts
|
|
1380
|
+
var execute = (schema, layer, extensions = [], fieldComplexities = /* @__PURE__ */ new Map()) => (source, variableValues, operationName) => effect.Effect.gen(function* () {
|
|
1381
|
+
const extensionsService = yield* makeExtensionsService();
|
|
1382
|
+
const runtime = yield* effect.Effect.runtime();
|
|
1383
|
+
let document;
|
|
1384
|
+
try {
|
|
1385
|
+
document = graphql.parse(source);
|
|
1386
|
+
} catch (parseError) {
|
|
1387
|
+
const extensionData2 = yield* extensionsService.get();
|
|
1388
|
+
return {
|
|
1389
|
+
errors: [
|
|
1390
|
+
parseError instanceof graphql.GraphQLError ? parseError : new graphql.GraphQLError(String(parseError))
|
|
1391
|
+
],
|
|
1392
|
+
extensions: Object.keys(extensionData2).length > 0 ? extensionData2 : void 0
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
yield* runParseHooks(extensions, source, document).pipe(
|
|
1396
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
1397
|
+
);
|
|
1398
|
+
const validationErrors = graphql.validate(schema, document);
|
|
1399
|
+
yield* runValidateHooks(extensions, document, validationErrors).pipe(
|
|
1400
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
1401
|
+
);
|
|
1402
|
+
if (validationErrors.length > 0) {
|
|
1403
|
+
const extensionData2 = yield* extensionsService.get();
|
|
1404
|
+
return {
|
|
1405
|
+
errors: validationErrors,
|
|
1406
|
+
extensions: Object.keys(extensionData2).length > 0 ? extensionData2 : void 0
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
const executionArgs = {
|
|
1410
|
+
source,
|
|
1411
|
+
document,
|
|
1412
|
+
variableValues,
|
|
1413
|
+
operationName,
|
|
1414
|
+
schema,
|
|
1415
|
+
fieldComplexities
|
|
1416
|
+
};
|
|
1417
|
+
yield* runExecuteStartHooks(extensions, executionArgs).pipe(
|
|
1418
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
1419
|
+
);
|
|
1420
|
+
const executeResult = yield* effect.Effect.try({
|
|
1421
|
+
try: () => graphql.execute({
|
|
1422
|
+
schema,
|
|
1423
|
+
document,
|
|
1424
|
+
variableValues,
|
|
1425
|
+
operationName,
|
|
1426
|
+
contextValue: { runtime }
|
|
1427
|
+
}),
|
|
1428
|
+
catch: (error) => new Error(String(error))
|
|
1429
|
+
});
|
|
1430
|
+
const resolvedResult = executeResult && typeof executeResult === "object" && "then" in executeResult ? yield* effect.Effect.promise(() => executeResult) : executeResult;
|
|
1431
|
+
yield* runExecuteEndHooks(extensions, resolvedResult).pipe(
|
|
1432
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
1433
|
+
);
|
|
1434
|
+
const extensionData = yield* extensionsService.get();
|
|
1435
|
+
if (Object.keys(extensionData).length > 0) {
|
|
1436
|
+
return {
|
|
1437
|
+
...resolvedResult,
|
|
1438
|
+
extensions: {
|
|
1439
|
+
...resolvedResult.extensions,
|
|
1440
|
+
...extensionData
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
return resolvedResult;
|
|
1445
|
+
}).pipe(effect.Effect.provide(layer));
|
|
1446
|
+
var GraphQLError2 = class extends effect.Data.TaggedError("GraphQLError") {
|
|
1447
|
+
};
|
|
1448
|
+
var ValidationError = class extends effect.Data.TaggedError("ValidationError") {
|
|
1449
|
+
};
|
|
1450
|
+
var AuthorizationError = class extends effect.Data.TaggedError("AuthorizationError") {
|
|
1451
|
+
};
|
|
1452
|
+
var NotFoundError = class extends effect.Data.TaggedError("NotFoundError") {
|
|
1453
|
+
};
|
|
1454
|
+
var GraphQLRequestContext = effect.Context.GenericTag("GraphQLRequestContext");
|
|
1455
|
+
var makeRequestContextLayer = (context) => effect.Layer.succeed(GraphQLRequestContext, context);
|
|
1456
|
+
function single(config) {
|
|
1457
|
+
return {
|
|
1458
|
+
_tag: "single",
|
|
1459
|
+
batch: config.batch,
|
|
1460
|
+
key: config.key
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1463
|
+
function grouped(config) {
|
|
1464
|
+
return {
|
|
1465
|
+
_tag: "grouped",
|
|
1466
|
+
batch: config.batch,
|
|
1467
|
+
groupBy: config.groupBy
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
var LoaderRegistry = class {
|
|
1471
|
+
constructor(definitions) {
|
|
1472
|
+
this.definitions = definitions;
|
|
1473
|
+
this.Service = effect.Context.GenericTag(
|
|
1474
|
+
`DataLoaders(${Object.keys(definitions).join(", ")})`
|
|
1475
|
+
);
|
|
1476
|
+
}
|
|
1477
|
+
_tag = "LoaderRegistry";
|
|
1478
|
+
/**
|
|
1479
|
+
* The Effect service tag for this loader registry
|
|
1480
|
+
*/
|
|
1481
|
+
Service;
|
|
1482
|
+
/**
|
|
1483
|
+
* Create a Layer that provides fresh DataLoader instances.
|
|
1484
|
+
* Call this once per request to get request-scoped loaders.
|
|
1485
|
+
*/
|
|
1486
|
+
toLayer() {
|
|
1487
|
+
const self = this;
|
|
1488
|
+
return effect.Layer.effect(
|
|
1489
|
+
this.Service,
|
|
1490
|
+
effect.Effect.gen(function* () {
|
|
1491
|
+
const instances = {};
|
|
1492
|
+
for (const [name, def] of Object.entries(self.definitions)) {
|
|
1493
|
+
instances[name] = yield* createDataLoader(def);
|
|
1494
|
+
}
|
|
1495
|
+
return instances;
|
|
1496
|
+
})
|
|
1497
|
+
);
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Helper to use loaders in a resolver with a callback.
|
|
1501
|
+
*/
|
|
1502
|
+
use(fn) {
|
|
1503
|
+
const self = this;
|
|
1504
|
+
return effect.Effect.gen(function* () {
|
|
1505
|
+
const loaders = yield* self.Service;
|
|
1506
|
+
return yield* effect.Effect.promise(() => fn(loaders));
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Load a single value by key.
|
|
1511
|
+
* This is the most common operation in resolvers.
|
|
1512
|
+
*/
|
|
1513
|
+
load(name, key) {
|
|
1514
|
+
const self = this;
|
|
1515
|
+
return effect.Effect.gen(function* () {
|
|
1516
|
+
const loaders = yield* self.Service;
|
|
1517
|
+
const loader = loaders[name];
|
|
1518
|
+
return yield* effect.Effect.promise(() => loader.load(key));
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Load multiple values by keys.
|
|
1523
|
+
* All keys are batched into a single request.
|
|
1524
|
+
*/
|
|
1525
|
+
loadMany(name, keys) {
|
|
1526
|
+
const self = this;
|
|
1527
|
+
return effect.Effect.gen(function* () {
|
|
1528
|
+
const loaders = yield* self.Service;
|
|
1529
|
+
const loader = loaders[name];
|
|
1530
|
+
const results = yield* effect.Effect.promise(() => loader.loadMany(keys));
|
|
1531
|
+
for (const result of results) {
|
|
1532
|
+
if (result instanceof Error) {
|
|
1533
|
+
return yield* effect.Effect.fail(result);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
return results;
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
};
|
|
1540
|
+
function createDataLoader(def) {
|
|
1541
|
+
return effect.Effect.gen(function* () {
|
|
1542
|
+
const context = yield* effect.Effect.context();
|
|
1543
|
+
if (def._tag === "single") {
|
|
1544
|
+
const loader = new DataLoader__default.default(async (keys) => {
|
|
1545
|
+
const items = await effect.Effect.runPromise(def.batch(keys).pipe(effect.Effect.provide(context)));
|
|
1546
|
+
return keys.map((key) => {
|
|
1547
|
+
const item = items.find((i) => def.key(i) === key);
|
|
1548
|
+
if (!item) return new Error(`Not found: ${key}`);
|
|
1549
|
+
return item;
|
|
1550
|
+
});
|
|
1551
|
+
});
|
|
1552
|
+
return loader;
|
|
1553
|
+
} else {
|
|
1554
|
+
const loader = new DataLoader__default.default(async (keys) => {
|
|
1555
|
+
const items = await effect.Effect.runPromise(def.batch(keys).pipe(effect.Effect.provide(context)));
|
|
1556
|
+
const map = /* @__PURE__ */ new Map();
|
|
1557
|
+
for (const item of items) {
|
|
1558
|
+
const key = def.groupBy(item);
|
|
1559
|
+
let arr = map.get(key);
|
|
1560
|
+
if (!arr) {
|
|
1561
|
+
arr = [];
|
|
1562
|
+
map.set(key, arr);
|
|
1563
|
+
}
|
|
1564
|
+
arr.push(item);
|
|
1565
|
+
}
|
|
1566
|
+
return keys.map((key) => map.get(key) ?? []);
|
|
1567
|
+
});
|
|
1568
|
+
return loader;
|
|
1569
|
+
}
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
function define(definitions) {
|
|
1573
|
+
return new LoaderRegistry(definitions);
|
|
1574
|
+
}
|
|
1575
|
+
function mapByKey(keys, items, keyFn) {
|
|
1576
|
+
const map = /* @__PURE__ */ new Map();
|
|
1577
|
+
for (const item of items) {
|
|
1578
|
+
map.set(keyFn(item), item);
|
|
1579
|
+
}
|
|
1580
|
+
return keys.map((key) => map.get(key) ?? new Error(`Not found: ${key}`));
|
|
1581
|
+
}
|
|
1582
|
+
function groupByKey(keys, items, keyFn) {
|
|
1583
|
+
const map = /* @__PURE__ */ new Map();
|
|
1584
|
+
for (const key of keys) {
|
|
1585
|
+
map.set(key, []);
|
|
1586
|
+
}
|
|
1587
|
+
for (const item of items) {
|
|
1588
|
+
const key = keyFn(item);
|
|
1589
|
+
const arr = map.get(key);
|
|
1590
|
+
if (arr) arr.push(item);
|
|
1591
|
+
}
|
|
1592
|
+
return map;
|
|
1593
|
+
}
|
|
1594
|
+
var Loader = {
|
|
1595
|
+
define,
|
|
1596
|
+
single,
|
|
1597
|
+
grouped,
|
|
1598
|
+
mapByKey,
|
|
1599
|
+
groupByKey
|
|
1600
|
+
};
|
|
1601
|
+
var MissingResolverContextError = class extends Error {
|
|
1602
|
+
constructor(contextName) {
|
|
1603
|
+
super(
|
|
1604
|
+
`Resolver context "${contextName}" was not provided. Ensure a parent resolver or directive provides this context.`
|
|
1605
|
+
);
|
|
1606
|
+
this.contextName = contextName;
|
|
1607
|
+
this.name = "MissingResolverContextError";
|
|
1608
|
+
}
|
|
1609
|
+
_tag = "MissingResolverContextError";
|
|
1610
|
+
};
|
|
1611
|
+
var ResolverContextStore = effect.Context.GenericTag(
|
|
1612
|
+
"effect-gql/ResolverContextStore"
|
|
1613
|
+
);
|
|
1614
|
+
var makeStoreLayer = () => effect.Effect.map(
|
|
1615
|
+
effect.Ref.make(effect.HashMap.empty()),
|
|
1616
|
+
(ref) => effect.Layer.succeed(ResolverContextStore, { ref })
|
|
1617
|
+
);
|
|
1618
|
+
var storeLayer = effect.Layer.effect(
|
|
1619
|
+
ResolverContextStore,
|
|
1620
|
+
effect.Effect.map(effect.Ref.make(effect.HashMap.empty()), (ref) => ({ ref }))
|
|
1621
|
+
);
|
|
1622
|
+
var make3 = (name) => ({
|
|
1623
|
+
_tag: "ResolverContextSlot",
|
|
1624
|
+
name,
|
|
1625
|
+
_A: void 0
|
|
1626
|
+
});
|
|
1627
|
+
var get = (slot) => effect.Effect.flatMap(
|
|
1628
|
+
ResolverContextStore,
|
|
1629
|
+
(store) => effect.Effect.flatMap(effect.Ref.get(store.ref), (map) => {
|
|
1630
|
+
const value = effect.HashMap.get(map, slot.name);
|
|
1631
|
+
return effect.Option.match(value, {
|
|
1632
|
+
onNone: () => effect.Effect.fail(new MissingResolverContextError(slot.name)),
|
|
1633
|
+
onSome: (v) => effect.Effect.succeed(v)
|
|
1634
|
+
});
|
|
1635
|
+
})
|
|
1636
|
+
);
|
|
1637
|
+
var getOption = (slot) => effect.Effect.flatMap(
|
|
1638
|
+
ResolverContextStore,
|
|
1639
|
+
(store) => effect.Effect.map(effect.Ref.get(store.ref), (map) => effect.HashMap.get(map, slot.name))
|
|
1640
|
+
);
|
|
1641
|
+
var set = (slot, value) => effect.Effect.flatMap(
|
|
1642
|
+
ResolverContextStore,
|
|
1643
|
+
(store) => effect.Ref.update(store.ref, (map) => effect.HashMap.set(map, slot.name, value))
|
|
1644
|
+
);
|
|
1645
|
+
var setMany = (values) => effect.Effect.flatMap(
|
|
1646
|
+
ResolverContextStore,
|
|
1647
|
+
(store) => effect.Ref.update(store.ref, (map) => {
|
|
1648
|
+
let result = map;
|
|
1649
|
+
for (const [slot, value] of values) {
|
|
1650
|
+
result = effect.HashMap.set(result, slot.name, value);
|
|
1651
|
+
}
|
|
1652
|
+
return result;
|
|
1653
|
+
})
|
|
1654
|
+
);
|
|
1655
|
+
var has = (slot) => effect.Effect.flatMap(
|
|
1656
|
+
ResolverContextStore,
|
|
1657
|
+
(store) => effect.Effect.map(effect.Ref.get(store.ref), (map) => effect.HashMap.has(map, slot.name))
|
|
1658
|
+
);
|
|
1659
|
+
var getOrElse = (slot, orElse) => effect.Effect.flatMap(
|
|
1660
|
+
ResolverContextStore,
|
|
1661
|
+
(store) => effect.Effect.map(
|
|
1662
|
+
effect.Ref.get(store.ref),
|
|
1663
|
+
(map) => effect.Option.getOrElse(effect.HashMap.get(map, slot.name), orElse)
|
|
1664
|
+
)
|
|
1665
|
+
);
|
|
1666
|
+
var scoped = (slot, value) => (effect$1) => effect.Effect.flatMap(
|
|
1667
|
+
ResolverContextStore,
|
|
1668
|
+
(store) => effect.Effect.acquireUseRelease(
|
|
1669
|
+
// Acquire: save current value and set new one
|
|
1670
|
+
effect.Effect.flatMap(effect.Ref.get(store.ref), (map) => {
|
|
1671
|
+
const previous = effect.HashMap.get(map, slot.name);
|
|
1672
|
+
return effect.Effect.as(effect.Ref.set(store.ref, effect.HashMap.set(map, slot.name, value)), previous);
|
|
1673
|
+
}),
|
|
1674
|
+
// Use: run the effect
|
|
1675
|
+
() => effect$1,
|
|
1676
|
+
// Release: restore previous value
|
|
1677
|
+
(previous) => effect.Ref.update(
|
|
1678
|
+
store.ref,
|
|
1679
|
+
(map) => effect.Option.match(previous, {
|
|
1680
|
+
onNone: () => effect.HashMap.remove(map, slot.name),
|
|
1681
|
+
onSome: (v) => effect.HashMap.set(map, slot.name, v)
|
|
1682
|
+
})
|
|
1683
|
+
)
|
|
1684
|
+
)
|
|
1685
|
+
);
|
|
1686
|
+
var ResolverContext = {
|
|
1687
|
+
make: make3,
|
|
1688
|
+
get,
|
|
1689
|
+
getOption,
|
|
1690
|
+
set,
|
|
1691
|
+
setMany,
|
|
1692
|
+
has,
|
|
1693
|
+
getOrElse,
|
|
1694
|
+
scoped,
|
|
1695
|
+
storeLayer,
|
|
1696
|
+
makeStoreLayer,
|
|
1697
|
+
Store: ResolverContextStore,
|
|
1698
|
+
MissingResolverContextError
|
|
1699
|
+
};
|
|
1700
|
+
var defaultConfig = {
|
|
1701
|
+
path: "/graphql",
|
|
1702
|
+
graphiql: false,
|
|
1703
|
+
complexity: void 0,
|
|
1704
|
+
introspection: true,
|
|
1705
|
+
cacheControl: void 0
|
|
1706
|
+
};
|
|
1707
|
+
var normalizeConfig = (input = {}) => {
|
|
1708
|
+
const path = input.path ?? defaultConfig.path;
|
|
1709
|
+
let graphiql = false;
|
|
1710
|
+
if (input.graphiql === true) {
|
|
1711
|
+
graphiql = { path: "/graphiql", endpoint: path };
|
|
1712
|
+
} else if (input.graphiql && typeof input.graphiql === "object") {
|
|
1713
|
+
graphiql = {
|
|
1714
|
+
path: input.graphiql.path ?? "/graphiql",
|
|
1715
|
+
endpoint: input.graphiql.endpoint ?? path
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
return {
|
|
1719
|
+
path,
|
|
1720
|
+
graphiql,
|
|
1721
|
+
complexity: input.complexity,
|
|
1722
|
+
introspection: input.introspection ?? true,
|
|
1723
|
+
cacheControl: input.cacheControl
|
|
1724
|
+
};
|
|
1725
|
+
};
|
|
1726
|
+
var GraphQLRouterConfigFromEnv = effect.Config.all({
|
|
1727
|
+
path: effect.Config.string("GRAPHQL_PATH").pipe(effect.Config.withDefault("/graphql")),
|
|
1728
|
+
introspection: effect.Config.boolean("GRAPHQL_INTROSPECTION").pipe(effect.Config.withDefault(true)),
|
|
1729
|
+
graphiqlEnabled: effect.Config.boolean("GRAPHIQL_ENABLED").pipe(effect.Config.withDefault(false)),
|
|
1730
|
+
graphiqlPath: effect.Config.string("GRAPHIQL_PATH").pipe(effect.Config.withDefault("/graphiql")),
|
|
1731
|
+
graphiqlEndpoint: effect.Config.string("GRAPHIQL_ENDPOINT").pipe(effect.Config.option),
|
|
1732
|
+
maxDepth: effect.Config.number("GRAPHQL_MAX_DEPTH").pipe(effect.Config.option),
|
|
1733
|
+
maxComplexity: effect.Config.number("GRAPHQL_MAX_COMPLEXITY").pipe(effect.Config.option),
|
|
1734
|
+
maxAliases: effect.Config.number("GRAPHQL_MAX_ALIASES").pipe(effect.Config.option),
|
|
1735
|
+
maxFields: effect.Config.number("GRAPHQL_MAX_FIELDS").pipe(effect.Config.option),
|
|
1736
|
+
defaultFieldComplexity: effect.Config.number("GRAPHQL_DEFAULT_FIELD_COMPLEXITY").pipe(
|
|
1737
|
+
effect.Config.withDefault(1)
|
|
1738
|
+
),
|
|
1739
|
+
cacheControlEnabled: effect.Config.boolean("GRAPHQL_CACHE_CONTROL_ENABLED").pipe(
|
|
1740
|
+
effect.Config.withDefault(false)
|
|
1741
|
+
),
|
|
1742
|
+
cacheControlDefaultMaxAge: effect.Config.number("GRAPHQL_CACHE_CONTROL_DEFAULT_MAX_AGE").pipe(
|
|
1743
|
+
effect.Config.withDefault(0)
|
|
1744
|
+
),
|
|
1745
|
+
cacheControlDefaultScope: effect.Config.string("GRAPHQL_CACHE_CONTROL_DEFAULT_SCOPE").pipe(
|
|
1746
|
+
effect.Config.withDefault("PUBLIC")
|
|
1747
|
+
)
|
|
1748
|
+
}).pipe(
|
|
1749
|
+
effect.Config.map(
|
|
1750
|
+
({
|
|
1751
|
+
path,
|
|
1752
|
+
introspection,
|
|
1753
|
+
graphiqlEnabled,
|
|
1754
|
+
graphiqlPath,
|
|
1755
|
+
graphiqlEndpoint,
|
|
1756
|
+
maxDepth,
|
|
1757
|
+
maxComplexity,
|
|
1758
|
+
maxAliases,
|
|
1759
|
+
maxFields,
|
|
1760
|
+
defaultFieldComplexity,
|
|
1761
|
+
cacheControlEnabled,
|
|
1762
|
+
cacheControlDefaultMaxAge,
|
|
1763
|
+
cacheControlDefaultScope
|
|
1764
|
+
}) => {
|
|
1765
|
+
const hasComplexity = effect.Option.isSome(maxDepth) || effect.Option.isSome(maxComplexity) || effect.Option.isSome(maxAliases) || effect.Option.isSome(maxFields);
|
|
1766
|
+
return {
|
|
1767
|
+
path,
|
|
1768
|
+
introspection,
|
|
1769
|
+
graphiql: graphiqlEnabled ? {
|
|
1770
|
+
path: graphiqlPath,
|
|
1771
|
+
endpoint: effect.Option.isSome(graphiqlEndpoint) ? graphiqlEndpoint.value : path
|
|
1772
|
+
} : false,
|
|
1773
|
+
complexity: hasComplexity ? {
|
|
1774
|
+
maxDepth: effect.Option.getOrUndefined(maxDepth),
|
|
1775
|
+
maxComplexity: effect.Option.getOrUndefined(maxComplexity),
|
|
1776
|
+
maxAliases: effect.Option.getOrUndefined(maxAliases),
|
|
1777
|
+
maxFields: effect.Option.getOrUndefined(maxFields),
|
|
1778
|
+
defaultFieldComplexity
|
|
1779
|
+
} : void 0,
|
|
1780
|
+
cacheControl: cacheControlEnabled ? {
|
|
1781
|
+
enabled: true,
|
|
1782
|
+
defaultMaxAge: cacheControlDefaultMaxAge,
|
|
1783
|
+
defaultScope: cacheControlDefaultScope === "PRIVATE" ? "PRIVATE" : "PUBLIC",
|
|
1784
|
+
calculateHttpHeaders: true
|
|
1785
|
+
} : void 0
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1788
|
+
)
|
|
1789
|
+
);
|
|
1790
|
+
|
|
1791
|
+
// src/server/graphiql.ts
|
|
1792
|
+
var graphiqlHtml = (endpoint) => `<!DOCTYPE html>
|
|
1793
|
+
<html lang="en">
|
|
1794
|
+
<head>
|
|
1795
|
+
<meta charset="utf-8" />
|
|
1796
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1797
|
+
<title>GraphiQL</title>
|
|
1798
|
+
<link
|
|
1799
|
+
rel="stylesheet"
|
|
1800
|
+
href="https://unpkg.com/graphiql@3/graphiql.min.css"
|
|
1801
|
+
/>
|
|
1802
|
+
</head>
|
|
1803
|
+
<body style="margin: 0; overflow: hidden;">
|
|
1804
|
+
<div id="graphiql" style="height: 100vh;"></div>
|
|
1805
|
+
<script
|
|
1806
|
+
crossorigin
|
|
1807
|
+
src="https://unpkg.com/react@18/umd/react.production.min.js"
|
|
1808
|
+
></script>
|
|
1809
|
+
<script
|
|
1810
|
+
crossorigin
|
|
1811
|
+
src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"
|
|
1812
|
+
></script>
|
|
1813
|
+
<script
|
|
1814
|
+
crossorigin
|
|
1815
|
+
src="https://unpkg.com/graphiql@3/graphiql.min.js"
|
|
1816
|
+
></script>
|
|
1817
|
+
<script>
|
|
1818
|
+
const fetcher = GraphiQL.createFetcher({
|
|
1819
|
+
url: ${JSON.stringify(endpoint)},
|
|
1820
|
+
});
|
|
1821
|
+
ReactDOM.createRoot(document.getElementById('graphiql')).render(
|
|
1822
|
+
React.createElement(GraphiQL, { fetcher })
|
|
1823
|
+
);
|
|
1824
|
+
</script>
|
|
1825
|
+
</body>
|
|
1826
|
+
</html>`;
|
|
1827
|
+
var ComplexityLimitExceededError = class extends effect.Data.TaggedError("ComplexityLimitExceededError") {
|
|
1828
|
+
};
|
|
1829
|
+
var ComplexityAnalysisError = class extends effect.Data.TaggedError("ComplexityAnalysisError") {
|
|
1830
|
+
};
|
|
1831
|
+
var defaultComplexityCalculator = (defaultCost = 1) => {
|
|
1832
|
+
return (info) => effect.Effect.try({
|
|
1833
|
+
try: () => {
|
|
1834
|
+
const fragments = /* @__PURE__ */ new Map();
|
|
1835
|
+
for (const definition of info.document.definitions) {
|
|
1836
|
+
if (definition.kind === graphql.Kind.FRAGMENT_DEFINITION) {
|
|
1837
|
+
fragments.set(definition.name.value, definition);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
const rootType = getRootType(info.schema, info.operation.operation);
|
|
1841
|
+
if (!rootType) {
|
|
1842
|
+
throw new Error(`No root type found for operation: ${info.operation.operation}`);
|
|
1843
|
+
}
|
|
1844
|
+
const result = analyzeSelectionSet(
|
|
1845
|
+
info.operation.selectionSet,
|
|
1846
|
+
rootType,
|
|
1847
|
+
info.schema,
|
|
1848
|
+
fragments,
|
|
1849
|
+
info.fieldComplexities,
|
|
1850
|
+
info.variables ?? {},
|
|
1851
|
+
defaultCost,
|
|
1852
|
+
1,
|
|
1853
|
+
// Starting depth
|
|
1854
|
+
/* @__PURE__ */ new Set()
|
|
1855
|
+
// Visited fragments to prevent infinite loops
|
|
1856
|
+
);
|
|
1857
|
+
return result;
|
|
1858
|
+
},
|
|
1859
|
+
catch: (error) => new ComplexityAnalysisError({
|
|
1860
|
+
message: `Failed to analyze query complexity: ${error}`,
|
|
1861
|
+
cause: error
|
|
1862
|
+
})
|
|
1863
|
+
});
|
|
1864
|
+
};
|
|
1865
|
+
function getRootType(schema, operation) {
|
|
1866
|
+
switch (operation) {
|
|
1867
|
+
case "query":
|
|
1868
|
+
return schema.getQueryType() ?? null;
|
|
1869
|
+
case "mutation":
|
|
1870
|
+
return schema.getMutationType() ?? null;
|
|
1871
|
+
case "subscription":
|
|
1872
|
+
return schema.getSubscriptionType() ?? null;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
function getNamedType(type) {
|
|
1876
|
+
if (type instanceof graphql.GraphQLNonNull || type instanceof graphql.GraphQLList) {
|
|
1877
|
+
return getNamedType(type.ofType);
|
|
1878
|
+
}
|
|
1879
|
+
if (type instanceof graphql.GraphQLObjectType) {
|
|
1880
|
+
return type;
|
|
1881
|
+
}
|
|
1882
|
+
return null;
|
|
1883
|
+
}
|
|
1884
|
+
function accumulateResult(acc, result) {
|
|
1885
|
+
acc.maxDepth = Math.max(acc.maxDepth, result.depth);
|
|
1886
|
+
acc.complexity += result.complexity;
|
|
1887
|
+
acc.fieldCount += result.fieldCount;
|
|
1888
|
+
acc.aliasCount += result.aliasCount;
|
|
1889
|
+
}
|
|
1890
|
+
function analyzeSelectionSet(selectionSet, parentType, schema, fragments, fieldComplexities, variables, defaultCost, currentDepth, visitedFragments) {
|
|
1891
|
+
const ctx = { schema, fragments, fieldComplexities, variables, defaultCost };
|
|
1892
|
+
const acc = { maxDepth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
|
|
1893
|
+
for (const selection of selectionSet.selections) {
|
|
1894
|
+
const result = analyzeSelection(selection, parentType, ctx, currentDepth, visitedFragments);
|
|
1895
|
+
accumulateResult(acc, result);
|
|
1896
|
+
}
|
|
1897
|
+
return {
|
|
1898
|
+
depth: acc.maxDepth,
|
|
1899
|
+
complexity: acc.complexity,
|
|
1900
|
+
fieldCount: acc.fieldCount,
|
|
1901
|
+
aliasCount: acc.aliasCount
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
function analyzeSelection(selection, parentType, ctx, currentDepth, visitedFragments) {
|
|
1905
|
+
switch (selection.kind) {
|
|
1906
|
+
case graphql.Kind.FIELD:
|
|
1907
|
+
return analyzeField(selection, parentType, ctx, currentDepth, visitedFragments);
|
|
1908
|
+
case graphql.Kind.FRAGMENT_SPREAD:
|
|
1909
|
+
return analyzeFragmentSpread(selection, ctx, currentDepth, visitedFragments);
|
|
1910
|
+
case graphql.Kind.INLINE_FRAGMENT:
|
|
1911
|
+
return analyzeInlineFragment(selection, parentType, ctx, currentDepth, visitedFragments);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
function analyzeField(field2, parentType, ctx, currentDepth, visitedFragments) {
|
|
1915
|
+
const fieldName = field2.name.value;
|
|
1916
|
+
const aliasCount = field2.alias ? 1 : 0;
|
|
1917
|
+
if (fieldName.startsWith("__")) {
|
|
1918
|
+
return { depth: currentDepth, complexity: 0, fieldCount: 1, aliasCount };
|
|
1919
|
+
}
|
|
1920
|
+
const schemaField = parentType.getFields()[fieldName];
|
|
1921
|
+
if (!schemaField) {
|
|
1922
|
+
return { depth: currentDepth, complexity: ctx.defaultCost, fieldCount: 1, aliasCount };
|
|
1923
|
+
}
|
|
1924
|
+
const args = resolveFieldArguments(field2, ctx.variables);
|
|
1925
|
+
const complexityKey = `${parentType.name}.${fieldName}`;
|
|
1926
|
+
const fieldComplexity = ctx.fieldComplexities.get(complexityKey);
|
|
1927
|
+
const cost = fieldComplexity !== void 0 ? typeof fieldComplexity === "function" ? fieldComplexity(args) : fieldComplexity : ctx.defaultCost;
|
|
1928
|
+
if (field2.selectionSet) {
|
|
1929
|
+
const fieldType = getNamedType(schemaField.type);
|
|
1930
|
+
if (fieldType) {
|
|
1931
|
+
const nestedResult = analyzeSelectionSet(
|
|
1932
|
+
field2.selectionSet,
|
|
1933
|
+
fieldType,
|
|
1934
|
+
ctx.schema,
|
|
1935
|
+
ctx.fragments,
|
|
1936
|
+
ctx.fieldComplexities,
|
|
1937
|
+
ctx.variables,
|
|
1938
|
+
ctx.defaultCost,
|
|
1939
|
+
currentDepth + 1,
|
|
1940
|
+
visitedFragments
|
|
1941
|
+
);
|
|
1942
|
+
return {
|
|
1943
|
+
depth: nestedResult.depth,
|
|
1944
|
+
complexity: cost + nestedResult.complexity,
|
|
1945
|
+
fieldCount: 1 + nestedResult.fieldCount,
|
|
1946
|
+
aliasCount: aliasCount + nestedResult.aliasCount
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
return { depth: currentDepth, complexity: cost, fieldCount: 1, aliasCount };
|
|
1951
|
+
}
|
|
1952
|
+
function analyzeFragmentSpread(spread, ctx, currentDepth, visitedFragments) {
|
|
1953
|
+
const fragmentName = spread.name.value;
|
|
1954
|
+
if (visitedFragments.has(fragmentName)) {
|
|
1955
|
+
return { depth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
|
|
1956
|
+
}
|
|
1957
|
+
const fragment = ctx.fragments.get(fragmentName);
|
|
1958
|
+
if (!fragment) {
|
|
1959
|
+
return { depth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
|
|
1960
|
+
}
|
|
1961
|
+
const fragmentType = ctx.schema.getType(fragment.typeCondition.name.value);
|
|
1962
|
+
if (!(fragmentType instanceof graphql.GraphQLObjectType)) {
|
|
1963
|
+
return { depth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
|
|
1964
|
+
}
|
|
1965
|
+
const newVisited = new Set(visitedFragments);
|
|
1966
|
+
newVisited.add(fragmentName);
|
|
1967
|
+
return analyzeSelectionSet(
|
|
1968
|
+
fragment.selectionSet,
|
|
1969
|
+
fragmentType,
|
|
1970
|
+
ctx.schema,
|
|
1971
|
+
ctx.fragments,
|
|
1972
|
+
ctx.fieldComplexities,
|
|
1973
|
+
ctx.variables,
|
|
1974
|
+
ctx.defaultCost,
|
|
1975
|
+
currentDepth,
|
|
1976
|
+
newVisited
|
|
1977
|
+
);
|
|
1978
|
+
}
|
|
1979
|
+
function analyzeInlineFragment(fragment, parentType, ctx, currentDepth, visitedFragments) {
|
|
1980
|
+
let targetType = parentType;
|
|
1981
|
+
if (fragment.typeCondition) {
|
|
1982
|
+
const conditionType = ctx.schema.getType(fragment.typeCondition.name.value);
|
|
1983
|
+
if (conditionType instanceof graphql.GraphQLObjectType) {
|
|
1984
|
+
targetType = conditionType;
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
return analyzeSelectionSet(
|
|
1988
|
+
fragment.selectionSet,
|
|
1989
|
+
targetType,
|
|
1990
|
+
ctx.schema,
|
|
1991
|
+
ctx.fragments,
|
|
1992
|
+
ctx.fieldComplexities,
|
|
1993
|
+
ctx.variables,
|
|
1994
|
+
ctx.defaultCost,
|
|
1995
|
+
currentDepth,
|
|
1996
|
+
visitedFragments
|
|
1997
|
+
);
|
|
1998
|
+
}
|
|
1999
|
+
function resolveFieldArguments(field2, variables) {
|
|
2000
|
+
const args = {};
|
|
2001
|
+
if (!field2.arguments) {
|
|
2002
|
+
return args;
|
|
2003
|
+
}
|
|
2004
|
+
for (const arg of field2.arguments) {
|
|
2005
|
+
const value = arg.value;
|
|
2006
|
+
switch (value.kind) {
|
|
2007
|
+
case graphql.Kind.VARIABLE:
|
|
2008
|
+
args[arg.name.value] = variables[value.name.value];
|
|
2009
|
+
break;
|
|
2010
|
+
case graphql.Kind.INT:
|
|
2011
|
+
args[arg.name.value] = parseInt(value.value, 10);
|
|
2012
|
+
break;
|
|
2013
|
+
case graphql.Kind.FLOAT:
|
|
2014
|
+
args[arg.name.value] = parseFloat(value.value);
|
|
2015
|
+
break;
|
|
2016
|
+
case graphql.Kind.STRING:
|
|
2017
|
+
args[arg.name.value] = value.value;
|
|
2018
|
+
break;
|
|
2019
|
+
case graphql.Kind.BOOLEAN:
|
|
2020
|
+
args[arg.name.value] = value.value;
|
|
2021
|
+
break;
|
|
2022
|
+
case graphql.Kind.NULL:
|
|
2023
|
+
args[arg.name.value] = null;
|
|
2024
|
+
break;
|
|
2025
|
+
case graphql.Kind.ENUM:
|
|
2026
|
+
args[arg.name.value] = value.value;
|
|
2027
|
+
break;
|
|
2028
|
+
case graphql.Kind.LIST:
|
|
2029
|
+
args[arg.name.value] = [];
|
|
2030
|
+
break;
|
|
2031
|
+
case graphql.Kind.OBJECT:
|
|
2032
|
+
args[arg.name.value] = {};
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
return args;
|
|
2037
|
+
}
|
|
2038
|
+
var validateComplexity = (query2, operationName, variables, schema, fieldComplexities, config) => effect.Effect.gen(function* () {
|
|
2039
|
+
const document = yield* effect.Effect.try({
|
|
2040
|
+
try: () => graphql.parse(query2),
|
|
2041
|
+
catch: (error) => new ComplexityAnalysisError({
|
|
2042
|
+
message: `Failed to parse query: ${error}`,
|
|
2043
|
+
cause: error
|
|
2044
|
+
})
|
|
2045
|
+
});
|
|
2046
|
+
const operation = yield* effect.Effect.try({
|
|
2047
|
+
try: () => {
|
|
2048
|
+
const operations = document.definitions.filter(
|
|
2049
|
+
(d) => d.kind === graphql.Kind.OPERATION_DEFINITION
|
|
2050
|
+
);
|
|
2051
|
+
if (operations.length === 0) {
|
|
2052
|
+
throw new Error("No operation found in query");
|
|
2053
|
+
}
|
|
2054
|
+
if (operationName) {
|
|
2055
|
+
const op = operations.find((o) => o.name?.value === operationName);
|
|
2056
|
+
if (!op) {
|
|
2057
|
+
throw new Error(`Operation "${operationName}" not found`);
|
|
2058
|
+
}
|
|
2059
|
+
return op;
|
|
2060
|
+
}
|
|
2061
|
+
if (operations.length > 1) {
|
|
2062
|
+
throw new Error("Multiple operations found - operationName required");
|
|
2063
|
+
}
|
|
2064
|
+
return operations[0];
|
|
2065
|
+
},
|
|
2066
|
+
catch: (error) => new ComplexityAnalysisError({
|
|
2067
|
+
message: String(error),
|
|
2068
|
+
cause: error
|
|
2069
|
+
})
|
|
2070
|
+
});
|
|
2071
|
+
const calculator = config.calculator ?? defaultComplexityCalculator(config.defaultFieldComplexity ?? 1);
|
|
2072
|
+
const result = yield* calculator({
|
|
2073
|
+
document,
|
|
2074
|
+
operation,
|
|
2075
|
+
variables,
|
|
2076
|
+
schema,
|
|
2077
|
+
fieldComplexities
|
|
2078
|
+
});
|
|
2079
|
+
const checkLimit = (limitType, limit, actual) => effect.Effect.gen(function* () {
|
|
2080
|
+
if (limit !== void 0 && actual > limit) {
|
|
2081
|
+
const exceededInfo = {
|
|
2082
|
+
result,
|
|
2083
|
+
exceededLimit: limitType,
|
|
2084
|
+
limit,
|
|
2085
|
+
actual,
|
|
2086
|
+
query: query2,
|
|
2087
|
+
operationName
|
|
2088
|
+
};
|
|
2089
|
+
if (config.onExceeded) {
|
|
2090
|
+
yield* config.onExceeded(exceededInfo);
|
|
2091
|
+
}
|
|
2092
|
+
yield* effect.Effect.fail(
|
|
2093
|
+
new ComplexityLimitExceededError({
|
|
2094
|
+
message: `Query ${limitType} of ${actual} exceeds maximum allowed ${limitType} of ${limit}`,
|
|
2095
|
+
limit,
|
|
2096
|
+
actual,
|
|
2097
|
+
limitType
|
|
2098
|
+
})
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
});
|
|
2102
|
+
yield* checkLimit("depth", config.maxDepth, result.depth);
|
|
2103
|
+
yield* checkLimit("complexity", config.maxComplexity, result.complexity);
|
|
2104
|
+
yield* checkLimit("aliases", config.maxAliases, result.aliasCount);
|
|
2105
|
+
yield* checkLimit("fields", config.maxFields, result.fieldCount);
|
|
2106
|
+
return result;
|
|
2107
|
+
});
|
|
2108
|
+
var ComplexityConfigFromEnv = effect.Config.all({
|
|
2109
|
+
maxDepth: effect.Config.number("GRAPHQL_MAX_DEPTH").pipe(effect.Config.option),
|
|
2110
|
+
maxComplexity: effect.Config.number("GRAPHQL_MAX_COMPLEXITY").pipe(effect.Config.option),
|
|
2111
|
+
maxAliases: effect.Config.number("GRAPHQL_MAX_ALIASES").pipe(effect.Config.option),
|
|
2112
|
+
maxFields: effect.Config.number("GRAPHQL_MAX_FIELDS").pipe(effect.Config.option),
|
|
2113
|
+
defaultFieldComplexity: effect.Config.number("GRAPHQL_DEFAULT_FIELD_COMPLEXITY").pipe(
|
|
2114
|
+
effect.Config.withDefault(1)
|
|
2115
|
+
)
|
|
2116
|
+
}).pipe(
|
|
2117
|
+
effect.Config.map(({ maxDepth, maxComplexity, maxAliases, maxFields, defaultFieldComplexity }) => ({
|
|
2118
|
+
maxDepth: effect.Option.getOrUndefined(maxDepth),
|
|
2119
|
+
maxComplexity: effect.Option.getOrUndefined(maxComplexity),
|
|
2120
|
+
maxAliases: effect.Option.getOrUndefined(maxAliases),
|
|
2121
|
+
maxFields: effect.Option.getOrUndefined(maxFields),
|
|
2122
|
+
defaultFieldComplexity
|
|
2123
|
+
}))
|
|
2124
|
+
);
|
|
2125
|
+
var depthOnlyCalculator = (info) => effect.Effect.try({
|
|
2126
|
+
try: () => {
|
|
2127
|
+
const fragments = /* @__PURE__ */ new Map();
|
|
2128
|
+
for (const definition of info.document.definitions) {
|
|
2129
|
+
if (definition.kind === graphql.Kind.FRAGMENT_DEFINITION) {
|
|
2130
|
+
fragments.set(definition.name.value, definition);
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
const depth = calculateMaxDepth(info.operation.selectionSet, fragments, 1, /* @__PURE__ */ new Set());
|
|
2134
|
+
return {
|
|
2135
|
+
depth,
|
|
2136
|
+
complexity: 0,
|
|
2137
|
+
fieldCount: 0,
|
|
2138
|
+
aliasCount: 0
|
|
2139
|
+
};
|
|
2140
|
+
},
|
|
2141
|
+
catch: (error) => new ComplexityAnalysisError({
|
|
2142
|
+
message: `Failed to analyze query depth: ${error}`,
|
|
2143
|
+
cause: error
|
|
2144
|
+
})
|
|
2145
|
+
});
|
|
2146
|
+
function calculateMaxDepth(selectionSet, fragments, currentDepth, visitedFragments) {
|
|
2147
|
+
let maxDepth = currentDepth;
|
|
2148
|
+
for (const selection of selectionSet.selections) {
|
|
2149
|
+
switch (selection.kind) {
|
|
2150
|
+
case graphql.Kind.FIELD:
|
|
2151
|
+
if (selection.selectionSet) {
|
|
2152
|
+
const nestedDepth = calculateMaxDepth(
|
|
2153
|
+
selection.selectionSet,
|
|
2154
|
+
fragments,
|
|
2155
|
+
currentDepth + 1,
|
|
2156
|
+
visitedFragments
|
|
2157
|
+
);
|
|
2158
|
+
maxDepth = Math.max(maxDepth, nestedDepth);
|
|
2159
|
+
}
|
|
2160
|
+
break;
|
|
2161
|
+
case graphql.Kind.FRAGMENT_SPREAD: {
|
|
2162
|
+
const fragmentName = selection.name.value;
|
|
2163
|
+
if (!visitedFragments.has(fragmentName)) {
|
|
2164
|
+
const fragment = fragments.get(fragmentName);
|
|
2165
|
+
if (fragment) {
|
|
2166
|
+
const newVisited = new Set(visitedFragments);
|
|
2167
|
+
newVisited.add(fragmentName);
|
|
2168
|
+
const fragmentDepth = calculateMaxDepth(
|
|
2169
|
+
fragment.selectionSet,
|
|
2170
|
+
fragments,
|
|
2171
|
+
currentDepth,
|
|
2172
|
+
newVisited
|
|
2173
|
+
);
|
|
2174
|
+
maxDepth = Math.max(maxDepth, fragmentDepth);
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
break;
|
|
2178
|
+
}
|
|
2179
|
+
case graphql.Kind.INLINE_FRAGMENT: {
|
|
2180
|
+
const inlineDepth = calculateMaxDepth(
|
|
2181
|
+
selection.selectionSet,
|
|
2182
|
+
fragments,
|
|
2183
|
+
currentDepth,
|
|
2184
|
+
visitedFragments
|
|
2185
|
+
);
|
|
2186
|
+
maxDepth = Math.max(maxDepth, inlineDepth);
|
|
2187
|
+
break;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
return maxDepth;
|
|
2192
|
+
}
|
|
2193
|
+
var combineCalculators = (...calculators) => {
|
|
2194
|
+
return (info) => effect.Effect.gen(function* () {
|
|
2195
|
+
let maxDepth = 0;
|
|
2196
|
+
let maxComplexity = 0;
|
|
2197
|
+
let maxFieldCount = 0;
|
|
2198
|
+
let maxAliasCount = 0;
|
|
2199
|
+
for (const calculator of calculators) {
|
|
2200
|
+
const result = yield* calculator(info);
|
|
2201
|
+
maxDepth = Math.max(maxDepth, result.depth);
|
|
2202
|
+
maxComplexity = Math.max(maxComplexity, result.complexity);
|
|
2203
|
+
maxFieldCount = Math.max(maxFieldCount, result.fieldCount);
|
|
2204
|
+
maxAliasCount = Math.max(maxAliasCount, result.aliasCount);
|
|
2205
|
+
}
|
|
2206
|
+
return {
|
|
2207
|
+
depth: maxDepth,
|
|
2208
|
+
complexity: maxComplexity,
|
|
2209
|
+
fieldCount: maxFieldCount,
|
|
2210
|
+
aliasCount: maxAliasCount
|
|
2211
|
+
};
|
|
2212
|
+
});
|
|
2213
|
+
};
|
|
2214
|
+
var computeCachePolicy = (info) => effect.Effect.sync(() => {
|
|
2215
|
+
const fragments = /* @__PURE__ */ new Map();
|
|
2216
|
+
for (const definition of info.document.definitions) {
|
|
2217
|
+
if (definition.kind === graphql.Kind.FRAGMENT_DEFINITION) {
|
|
2218
|
+
fragments.set(definition.name.value, definition);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
const rootType = getRootType2(info.schema, info.operation.operation);
|
|
2222
|
+
if (!rootType) {
|
|
2223
|
+
return { maxAge: 0, scope: "PUBLIC" };
|
|
2224
|
+
}
|
|
2225
|
+
const defaultMaxAge = info.config.defaultMaxAge ?? 0;
|
|
2226
|
+
const defaultScope = info.config.defaultScope ?? "PUBLIC";
|
|
2227
|
+
const result = analyzeSelectionSet2(
|
|
2228
|
+
info.operation.selectionSet,
|
|
2229
|
+
rootType,
|
|
2230
|
+
info.schema,
|
|
2231
|
+
fragments,
|
|
2232
|
+
info.cacheHints,
|
|
2233
|
+
defaultMaxAge,
|
|
2234
|
+
defaultScope,
|
|
2235
|
+
void 0,
|
|
2236
|
+
// No parent maxAge for root
|
|
2237
|
+
/* @__PURE__ */ new Set()
|
|
2238
|
+
);
|
|
2239
|
+
return result;
|
|
2240
|
+
});
|
|
2241
|
+
var computeCachePolicyFromQuery = (query2, operationName, schema, cacheHints, config = {}) => effect.Effect.gen(function* () {
|
|
2242
|
+
const document = yield* effect.Effect.try({
|
|
2243
|
+
try: () => graphql.parse(query2),
|
|
2244
|
+
catch: (error) => new Error(`Failed to parse query: ${error}`)
|
|
2245
|
+
});
|
|
2246
|
+
const operation = yield* effect.Effect.try({
|
|
2247
|
+
try: () => {
|
|
2248
|
+
const operations = document.definitions.filter(
|
|
2249
|
+
(d) => d.kind === graphql.Kind.OPERATION_DEFINITION
|
|
2250
|
+
);
|
|
2251
|
+
if (operations.length === 0) {
|
|
2252
|
+
throw new Error("No operation found in query");
|
|
2253
|
+
}
|
|
2254
|
+
if (operationName) {
|
|
2255
|
+
const op = operations.find((o) => o.name?.value === operationName);
|
|
2256
|
+
if (!op) {
|
|
2257
|
+
throw new Error(`Operation "${operationName}" not found`);
|
|
2258
|
+
}
|
|
2259
|
+
return op;
|
|
2260
|
+
}
|
|
2261
|
+
if (operations.length > 1) {
|
|
2262
|
+
throw new Error("Multiple operations found - operationName required");
|
|
2263
|
+
}
|
|
2264
|
+
return operations[0];
|
|
2265
|
+
},
|
|
2266
|
+
catch: (error) => error
|
|
2267
|
+
});
|
|
2268
|
+
return yield* computeCachePolicy({
|
|
2269
|
+
document,
|
|
2270
|
+
operation,
|
|
2271
|
+
schema,
|
|
2272
|
+
cacheHints,
|
|
2273
|
+
config
|
|
2274
|
+
});
|
|
2275
|
+
});
|
|
2276
|
+
var toCacheControlHeader = (policy) => {
|
|
2277
|
+
if (policy.maxAge === 0) {
|
|
2278
|
+
return "no-store";
|
|
2279
|
+
}
|
|
2280
|
+
const directives = [];
|
|
2281
|
+
directives.push(policy.scope === "PRIVATE" ? "private" : "public");
|
|
2282
|
+
directives.push(`max-age=${policy.maxAge}`);
|
|
2283
|
+
return directives.join(", ");
|
|
2284
|
+
};
|
|
2285
|
+
function getRootType2(schema, operation) {
|
|
2286
|
+
switch (operation) {
|
|
2287
|
+
case "query":
|
|
2288
|
+
return schema.getQueryType() ?? null;
|
|
2289
|
+
case "mutation":
|
|
2290
|
+
return schema.getMutationType() ?? null;
|
|
2291
|
+
case "subscription":
|
|
2292
|
+
return schema.getSubscriptionType() ?? null;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
function getNamedType2(type) {
|
|
2296
|
+
if (type instanceof graphql.GraphQLNonNull || type instanceof graphql.GraphQLList) {
|
|
2297
|
+
return getNamedType2(type.ofType);
|
|
2298
|
+
}
|
|
2299
|
+
if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLScalarType || type instanceof graphql.GraphQLEnumType) {
|
|
2300
|
+
return type;
|
|
2301
|
+
}
|
|
2302
|
+
return null;
|
|
2303
|
+
}
|
|
2304
|
+
function isLeafType(type) {
|
|
2305
|
+
const namedType = getNamedType2(type);
|
|
2306
|
+
return namedType instanceof graphql.GraphQLScalarType || namedType instanceof graphql.GraphQLEnumType;
|
|
2307
|
+
}
|
|
2308
|
+
function aggregatePolicy(acc, policy) {
|
|
2309
|
+
if (acc.minMaxAge === void 0) {
|
|
2310
|
+
acc.minMaxAge = policy.maxAge;
|
|
2311
|
+
} else {
|
|
2312
|
+
acc.minMaxAge = Math.min(acc.minMaxAge, policy.maxAge);
|
|
2313
|
+
}
|
|
2314
|
+
if (policy.scope === "PRIVATE") {
|
|
2315
|
+
acc.hasPrivate = true;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
function analyzeFragmentSpread2(fragmentName, ctx, parentMaxAge, visitedFragments) {
|
|
2319
|
+
if (visitedFragments.has(fragmentName)) {
|
|
2320
|
+
return void 0;
|
|
2321
|
+
}
|
|
2322
|
+
const fragment = ctx.fragments.get(fragmentName);
|
|
2323
|
+
if (!fragment) {
|
|
2324
|
+
return void 0;
|
|
2325
|
+
}
|
|
2326
|
+
const fragmentType = ctx.schema.getType(fragment.typeCondition.name.value);
|
|
2327
|
+
if (!(fragmentType instanceof graphql.GraphQLObjectType)) {
|
|
2328
|
+
return void 0;
|
|
2329
|
+
}
|
|
2330
|
+
const newVisited = new Set(visitedFragments);
|
|
2331
|
+
newVisited.add(fragmentName);
|
|
2332
|
+
return analyzeSelectionSet2(fragment.selectionSet, fragmentType, ctx, parentMaxAge, newVisited);
|
|
2333
|
+
}
|
|
2334
|
+
function analyzeInlineFragment2(selection, parentType, ctx, parentMaxAge, visitedFragments) {
|
|
2335
|
+
let targetType = parentType;
|
|
2336
|
+
if (selection.typeCondition) {
|
|
2337
|
+
const conditionType = ctx.schema.getType(selection.typeCondition.name.value);
|
|
2338
|
+
if (conditionType instanceof graphql.GraphQLObjectType) {
|
|
2339
|
+
targetType = conditionType;
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
return analyzeSelectionSet2(
|
|
2343
|
+
selection.selectionSet,
|
|
2344
|
+
targetType,
|
|
2345
|
+
ctx,
|
|
2346
|
+
parentMaxAge,
|
|
2347
|
+
visitedFragments
|
|
2348
|
+
);
|
|
2349
|
+
}
|
|
2350
|
+
function lookupEffectiveCacheHint(parentTypeName, fieldName, returnType, cacheHints) {
|
|
2351
|
+
const fieldKey = `${parentTypeName}.${fieldName}`;
|
|
2352
|
+
const fieldHint = cacheHints.get(fieldKey);
|
|
2353
|
+
if (fieldHint) return fieldHint;
|
|
2354
|
+
const namedType = getNamedType2(returnType);
|
|
2355
|
+
return namedType ? cacheHints.get(namedType.name) : void 0;
|
|
2356
|
+
}
|
|
2357
|
+
function computeFieldMaxAge(hint, fieldType, parentMaxAge, defaultMaxAge) {
|
|
2358
|
+
if (hint) {
|
|
2359
|
+
if (hint.inheritMaxAge && parentMaxAge !== void 0) {
|
|
2360
|
+
return parentMaxAge;
|
|
2361
|
+
}
|
|
2362
|
+
if (hint.maxAge !== void 0) {
|
|
2363
|
+
return hint.maxAge;
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
if (isLeafType(fieldType) && parentMaxAge !== void 0) {
|
|
2367
|
+
return parentMaxAge;
|
|
2368
|
+
}
|
|
2369
|
+
return defaultMaxAge;
|
|
2370
|
+
}
|
|
2371
|
+
function analyzeSelectionSet2(selectionSet, parentType, schemaOrCtx, fragmentsOrParentMaxAge, cacheHintsOrVisited, defaultMaxAge, defaultScope, parentMaxAge, visitedFragments) {
|
|
2372
|
+
let ctx;
|
|
2373
|
+
let actualParentMaxAge;
|
|
2374
|
+
let actualVisitedFragments;
|
|
2375
|
+
if (schemaOrCtx instanceof graphql.GraphQLSchema) {
|
|
2376
|
+
ctx = {
|
|
2377
|
+
schema: schemaOrCtx,
|
|
2378
|
+
fragments: fragmentsOrParentMaxAge,
|
|
2379
|
+
cacheHints: cacheHintsOrVisited,
|
|
2380
|
+
defaultMaxAge,
|
|
2381
|
+
defaultScope
|
|
2382
|
+
};
|
|
2383
|
+
actualParentMaxAge = parentMaxAge;
|
|
2384
|
+
actualVisitedFragments = visitedFragments;
|
|
2385
|
+
} else {
|
|
2386
|
+
ctx = schemaOrCtx;
|
|
2387
|
+
actualParentMaxAge = fragmentsOrParentMaxAge;
|
|
2388
|
+
actualVisitedFragments = cacheHintsOrVisited;
|
|
2389
|
+
}
|
|
2390
|
+
const acc = { minMaxAge: void 0, hasPrivate: false };
|
|
2391
|
+
for (const selection of selectionSet.selections) {
|
|
2392
|
+
let fieldPolicy;
|
|
2393
|
+
switch (selection.kind) {
|
|
2394
|
+
case graphql.Kind.FIELD:
|
|
2395
|
+
fieldPolicy = analyzeField2(
|
|
2396
|
+
selection,
|
|
2397
|
+
parentType,
|
|
2398
|
+
ctx,
|
|
2399
|
+
actualParentMaxAge,
|
|
2400
|
+
actualVisitedFragments
|
|
2401
|
+
);
|
|
2402
|
+
break;
|
|
2403
|
+
case graphql.Kind.FRAGMENT_SPREAD:
|
|
2404
|
+
fieldPolicy = analyzeFragmentSpread2(
|
|
2405
|
+
selection.name.value,
|
|
2406
|
+
ctx,
|
|
2407
|
+
actualParentMaxAge,
|
|
2408
|
+
actualVisitedFragments
|
|
2409
|
+
);
|
|
2410
|
+
break;
|
|
2411
|
+
case graphql.Kind.INLINE_FRAGMENT:
|
|
2412
|
+
fieldPolicy = analyzeInlineFragment2(
|
|
2413
|
+
selection,
|
|
2414
|
+
parentType,
|
|
2415
|
+
ctx,
|
|
2416
|
+
actualParentMaxAge,
|
|
2417
|
+
actualVisitedFragments
|
|
2418
|
+
);
|
|
2419
|
+
break;
|
|
2420
|
+
}
|
|
2421
|
+
if (fieldPolicy) {
|
|
2422
|
+
aggregatePolicy(acc, fieldPolicy);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
return {
|
|
2426
|
+
maxAge: acc.minMaxAge ?? ctx.defaultMaxAge,
|
|
2427
|
+
scope: acc.hasPrivate ? "PRIVATE" : ctx.defaultScope
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
function analyzeField2(field2, parentType, ctx, parentMaxAge, visitedFragments) {
|
|
2431
|
+
const fieldName = field2.name.value;
|
|
2432
|
+
if (fieldName.startsWith("__")) {
|
|
2433
|
+
return { maxAge: Infinity, scope: "PUBLIC" };
|
|
2434
|
+
}
|
|
2435
|
+
const schemaField = parentType.getFields()[fieldName];
|
|
2436
|
+
if (!schemaField) {
|
|
2437
|
+
return { maxAge: ctx.defaultMaxAge, scope: ctx.defaultScope };
|
|
2438
|
+
}
|
|
2439
|
+
const effectiveHint = lookupEffectiveCacheHint(
|
|
2440
|
+
parentType.name,
|
|
2441
|
+
fieldName,
|
|
2442
|
+
schemaField.type,
|
|
2443
|
+
ctx.cacheHints
|
|
2444
|
+
);
|
|
2445
|
+
const fieldMaxAge = computeFieldMaxAge(
|
|
2446
|
+
effectiveHint,
|
|
2447
|
+
schemaField.type,
|
|
2448
|
+
parentMaxAge,
|
|
2449
|
+
ctx.defaultMaxAge
|
|
2450
|
+
);
|
|
2451
|
+
const fieldScope = effectiveHint?.scope ?? ctx.defaultScope;
|
|
2452
|
+
const namedType = getNamedType2(schemaField.type);
|
|
2453
|
+
if (field2.selectionSet && namedType instanceof graphql.GraphQLObjectType) {
|
|
2454
|
+
const nestedPolicy = analyzeSelectionSet2(
|
|
2455
|
+
field2.selectionSet,
|
|
2456
|
+
namedType,
|
|
2457
|
+
ctx,
|
|
2458
|
+
fieldMaxAge,
|
|
2459
|
+
visitedFragments
|
|
2460
|
+
);
|
|
2461
|
+
return {
|
|
2462
|
+
maxAge: Math.min(fieldMaxAge, nestedPolicy.maxAge),
|
|
2463
|
+
scope: fieldScope === "PRIVATE" || nestedPolicy.scope === "PRIVATE" ? "PRIVATE" : "PUBLIC"
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
return { maxAge: fieldMaxAge, scope: fieldScope };
|
|
2467
|
+
}
|
|
2468
|
+
var CacheControlConfigFromEnv = effect.Config.all({
|
|
2469
|
+
enabled: effect.Config.boolean("GRAPHQL_CACHE_CONTROL_ENABLED").pipe(effect.Config.withDefault(true)),
|
|
2470
|
+
defaultMaxAge: effect.Config.number("GRAPHQL_CACHE_CONTROL_DEFAULT_MAX_AGE").pipe(effect.Config.withDefault(0)),
|
|
2471
|
+
defaultScope: effect.Config.string("GRAPHQL_CACHE_CONTROL_DEFAULT_SCOPE").pipe(
|
|
2472
|
+
effect.Config.withDefault("PUBLIC"),
|
|
2473
|
+
effect.Config.map((s) => s === "PRIVATE" ? "PRIVATE" : "PUBLIC")
|
|
2474
|
+
),
|
|
2475
|
+
calculateHttpHeaders: effect.Config.boolean("GRAPHQL_CACHE_CONTROL_HTTP_HEADERS").pipe(
|
|
2476
|
+
effect.Config.withDefault(true)
|
|
2477
|
+
)
|
|
2478
|
+
});
|
|
2479
|
+
|
|
2480
|
+
// src/server/router.ts
|
|
2481
|
+
var defaultErrorHandler = (cause) => (process.env.NODE_ENV !== "production" ? effect.Effect.logError("GraphQL error", cause) : effect.Effect.void).pipe(
|
|
2482
|
+
effect.Effect.andThen(
|
|
2483
|
+
platform.HttpServerResponse.json(
|
|
2484
|
+
{
|
|
2485
|
+
errors: [
|
|
2486
|
+
{
|
|
2487
|
+
message: "An error occurred processing your request"
|
|
2488
|
+
}
|
|
2489
|
+
]
|
|
2490
|
+
},
|
|
2491
|
+
{ status: 500 }
|
|
2492
|
+
).pipe(effect.Effect.orDie)
|
|
2493
|
+
)
|
|
2494
|
+
);
|
|
2495
|
+
var parseGraphQLQuery = (query2, extensionsService) => effect.Effect.gen(function* () {
|
|
2496
|
+
try {
|
|
2497
|
+
const document = graphql.parse(query2);
|
|
2498
|
+
return { ok: true, document };
|
|
2499
|
+
} catch (parseError) {
|
|
2500
|
+
const extensionData = yield* extensionsService.get();
|
|
2501
|
+
const response = yield* platform.HttpServerResponse.json({
|
|
2502
|
+
errors: [{ message: String(parseError) }],
|
|
2503
|
+
extensions: Object.keys(extensionData).length > 0 ? extensionData : void 0
|
|
2504
|
+
}).pipe(effect.Effect.orDie);
|
|
2505
|
+
return { ok: false, response };
|
|
2506
|
+
}
|
|
2507
|
+
});
|
|
2508
|
+
var runComplexityValidation = (body, schema, fieldComplexities, complexityConfig) => {
|
|
2509
|
+
if (!complexityConfig) {
|
|
2510
|
+
return effect.Effect.void;
|
|
2511
|
+
}
|
|
2512
|
+
return validateComplexity(
|
|
2513
|
+
body.query,
|
|
2514
|
+
body.operationName,
|
|
2515
|
+
body.variables,
|
|
2516
|
+
schema,
|
|
2517
|
+
fieldComplexities,
|
|
2518
|
+
complexityConfig
|
|
2519
|
+
).pipe(
|
|
2520
|
+
effect.Effect.catchTag("ComplexityLimitExceededError", (error) => effect.Effect.fail(error)),
|
|
2521
|
+
effect.Effect.catchTag(
|
|
2522
|
+
"ComplexityAnalysisError",
|
|
2523
|
+
(error) => effect.Effect.logWarning("Complexity analysis failed", error)
|
|
2524
|
+
)
|
|
2525
|
+
);
|
|
2526
|
+
};
|
|
2527
|
+
var executeGraphQLQuery = (schema, document, variables, operationName, runtime) => effect.Effect.gen(function* () {
|
|
2528
|
+
const executeResult = yield* effect.Effect.try({
|
|
2529
|
+
try: () => graphql.execute({
|
|
2530
|
+
schema,
|
|
2531
|
+
document,
|
|
2532
|
+
variableValues: variables,
|
|
2533
|
+
operationName,
|
|
2534
|
+
contextValue: { runtime }
|
|
2535
|
+
}),
|
|
2536
|
+
catch: (error) => new Error(String(error))
|
|
2537
|
+
});
|
|
2538
|
+
if (executeResult && typeof executeResult === "object" && "then" in executeResult) {
|
|
2539
|
+
return yield* effect.Effect.promise(
|
|
2540
|
+
() => executeResult
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
return executeResult;
|
|
2544
|
+
});
|
|
2545
|
+
var computeCacheControlHeader = (document, operationName, schema, cacheHints, cacheControlConfig) => effect.Effect.gen(function* () {
|
|
2546
|
+
if (cacheControlConfig?.enabled === false || cacheControlConfig?.calculateHttpHeaders === false) {
|
|
2547
|
+
return void 0;
|
|
2548
|
+
}
|
|
2549
|
+
const operations = document.definitions.filter(
|
|
2550
|
+
(d) => d.kind === graphql.Kind.OPERATION_DEFINITION
|
|
2551
|
+
);
|
|
2552
|
+
const operation = operationName ? operations.find((o) => o.name?.value === operationName) : operations[0];
|
|
2553
|
+
if (!operation || operation.operation === "mutation") {
|
|
2554
|
+
return void 0;
|
|
2555
|
+
}
|
|
2556
|
+
const cachePolicy = yield* computeCachePolicy({
|
|
2557
|
+
document,
|
|
2558
|
+
operation,
|
|
2559
|
+
schema,
|
|
2560
|
+
cacheHints,
|
|
2561
|
+
config: cacheControlConfig ?? {}
|
|
2562
|
+
});
|
|
2563
|
+
return toCacheControlHeader(cachePolicy);
|
|
2564
|
+
});
|
|
2565
|
+
var buildGraphQLResponse = (result, extensionData, cacheControlHeader) => {
|
|
2566
|
+
const finalResult = Object.keys(extensionData).length > 0 ? {
|
|
2567
|
+
...result,
|
|
2568
|
+
extensions: {
|
|
2569
|
+
...result.extensions,
|
|
2570
|
+
...extensionData
|
|
2571
|
+
}
|
|
2572
|
+
} : result;
|
|
2573
|
+
const responseHeaders = cacheControlHeader ? { "cache-control": cacheControlHeader } : void 0;
|
|
2574
|
+
return platform.HttpServerResponse.json(finalResult, { headers: responseHeaders }).pipe(effect.Effect.orDie);
|
|
2575
|
+
};
|
|
2576
|
+
var handleComplexityError = (error) => platform.HttpServerResponse.json(
|
|
2577
|
+
{
|
|
2578
|
+
errors: [
|
|
2579
|
+
{
|
|
2580
|
+
message: error.message,
|
|
2581
|
+
extensions: {
|
|
2582
|
+
code: "COMPLEXITY_LIMIT_EXCEEDED",
|
|
2583
|
+
limitType: error.limitType,
|
|
2584
|
+
limit: error.limit,
|
|
2585
|
+
actual: error.actual
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
]
|
|
2589
|
+
},
|
|
2590
|
+
{ status: 400 }
|
|
2591
|
+
).pipe(effect.Effect.orDie);
|
|
2592
|
+
var makeGraphQLRouter = (schema, layer, options = {}) => {
|
|
2593
|
+
const resolvedConfig = normalizeConfig(options);
|
|
2594
|
+
const fieldComplexities = options.fieldComplexities ?? /* @__PURE__ */ new Map();
|
|
2595
|
+
const cacheHints = options.cacheHints ?? /* @__PURE__ */ new Map();
|
|
2596
|
+
const extensions = options.extensions ?? [];
|
|
2597
|
+
const errorHandler = options.errorHandler ?? defaultErrorHandler;
|
|
2598
|
+
const graphqlHandler = effect.Effect.gen(function* () {
|
|
2599
|
+
const extensionsService = yield* makeExtensionsService();
|
|
2600
|
+
const runtime = yield* effect.Effect.runtime();
|
|
2601
|
+
const request = yield* platform.HttpServerRequest.HttpServerRequest;
|
|
2602
|
+
const body = yield* request.json;
|
|
2603
|
+
const parseResult = yield* parseGraphQLQuery(body.query, extensionsService);
|
|
2604
|
+
if (!parseResult.ok) {
|
|
2605
|
+
return parseResult.response;
|
|
2606
|
+
}
|
|
2607
|
+
const document = parseResult.document;
|
|
2608
|
+
yield* runParseHooks(extensions, body.query, document).pipe(
|
|
2609
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
2610
|
+
);
|
|
2611
|
+
const validationRules = resolvedConfig.introspection ? void 0 : [...graphql.specifiedRules, graphql.NoSchemaIntrospectionCustomRule];
|
|
2612
|
+
const validationErrors = graphql.validate(schema, document, validationRules);
|
|
2613
|
+
yield* runValidateHooks(extensions, document, validationErrors).pipe(
|
|
2614
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
2615
|
+
);
|
|
2616
|
+
if (validationErrors.length > 0) {
|
|
2617
|
+
const extensionData2 = yield* extensionsService.get();
|
|
2618
|
+
return yield* platform.HttpServerResponse.json(
|
|
2619
|
+
{
|
|
2620
|
+
errors: validationErrors.map((e) => ({
|
|
2621
|
+
message: e.message,
|
|
2622
|
+
locations: e.locations,
|
|
2623
|
+
path: e.path
|
|
2624
|
+
})),
|
|
2625
|
+
extensions: Object.keys(extensionData2).length > 0 ? extensionData2 : void 0
|
|
2626
|
+
},
|
|
2627
|
+
{ status: 400 }
|
|
2628
|
+
);
|
|
2629
|
+
}
|
|
2630
|
+
yield* runComplexityValidation(body, schema, fieldComplexities, resolvedConfig.complexity);
|
|
2631
|
+
yield* runExecuteStartHooks(extensions, {
|
|
2632
|
+
source: body.query,
|
|
2633
|
+
document,
|
|
2634
|
+
variableValues: body.variables,
|
|
2635
|
+
operationName: body.operationName,
|
|
2636
|
+
schema,
|
|
2637
|
+
fieldComplexities
|
|
2638
|
+
}).pipe(effect.Effect.provideService(ExtensionsService, extensionsService));
|
|
2639
|
+
const result = yield* executeGraphQLQuery(
|
|
2640
|
+
schema,
|
|
2641
|
+
document,
|
|
2642
|
+
body.variables,
|
|
2643
|
+
body.operationName,
|
|
2644
|
+
runtime
|
|
2645
|
+
);
|
|
2646
|
+
yield* runExecuteEndHooks(extensions, result).pipe(
|
|
2647
|
+
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
2648
|
+
);
|
|
2649
|
+
const extensionData = yield* extensionsService.get();
|
|
2650
|
+
const cacheControlHeader = yield* computeCacheControlHeader(
|
|
2651
|
+
document,
|
|
2652
|
+
body.operationName,
|
|
2653
|
+
schema,
|
|
2654
|
+
cacheHints,
|
|
2655
|
+
resolvedConfig.cacheControl
|
|
2656
|
+
);
|
|
2657
|
+
return yield* buildGraphQLResponse(result, extensionData, cacheControlHeader);
|
|
2658
|
+
}).pipe(
|
|
2659
|
+
effect.Effect.provide(layer),
|
|
2660
|
+
effect.Effect.catchAll((error) => {
|
|
2661
|
+
if (error instanceof ComplexityLimitExceededError) {
|
|
2662
|
+
return handleComplexityError(error);
|
|
2663
|
+
}
|
|
2664
|
+
return effect.Effect.fail(error);
|
|
2665
|
+
}),
|
|
2666
|
+
effect.Effect.catchAllCause(errorHandler)
|
|
2667
|
+
);
|
|
2668
|
+
let router = platform.HttpRouter.empty.pipe(
|
|
2669
|
+
platform.HttpRouter.post(resolvedConfig.path, graphqlHandler)
|
|
2670
|
+
);
|
|
2671
|
+
if (resolvedConfig.graphiql) {
|
|
2672
|
+
const { path, endpoint } = resolvedConfig.graphiql;
|
|
2673
|
+
router = router.pipe(
|
|
2674
|
+
platform.HttpRouter.get(path, platform.HttpServerResponse.html(graphiqlHtml(endpoint)))
|
|
2675
|
+
);
|
|
2676
|
+
}
|
|
2677
|
+
return router;
|
|
2678
|
+
};
|
|
2679
|
+
|
|
2680
|
+
// src/server/schema-builder-extensions.ts
|
|
2681
|
+
var toRouter = (builder, layer, options) => {
|
|
2682
|
+
const schema = builder.buildSchema();
|
|
2683
|
+
const fieldComplexities = builder.getFieldComplexities();
|
|
2684
|
+
const cacheHints = builder.getCacheHints();
|
|
2685
|
+
return makeGraphQLRouter(schema, layer, { ...options, fieldComplexities, cacheHints });
|
|
2686
|
+
};
|
|
2687
|
+
var WebSocketError = class extends effect.Data.TaggedError("WebSocketError") {
|
|
2688
|
+
};
|
|
2689
|
+
var createConnectionContext = (extra) => ({
|
|
2690
|
+
runtime: extra.runtime,
|
|
2691
|
+
connectionParams: extra.connectionParams,
|
|
2692
|
+
socket: extra.socket
|
|
2693
|
+
});
|
|
2694
|
+
var makeOnConnectHandler = (options) => {
|
|
2695
|
+
if (!options?.onConnect) return void 0;
|
|
2696
|
+
return async (ctx) => {
|
|
2697
|
+
const extra = ctx.extra;
|
|
2698
|
+
try {
|
|
2699
|
+
const result = await effect.Runtime.runPromise(extra.runtime)(
|
|
2700
|
+
options.onConnect(ctx.connectionParams ?? {})
|
|
2701
|
+
);
|
|
2702
|
+
if (typeof result === "object" && result !== null) {
|
|
2703
|
+
Object.assign(extra.connectionParams, result);
|
|
2704
|
+
}
|
|
2705
|
+
return result !== false;
|
|
2706
|
+
} catch {
|
|
2707
|
+
return false;
|
|
2708
|
+
}
|
|
2709
|
+
};
|
|
2710
|
+
};
|
|
2711
|
+
var makeOnDisconnectHandler = (options) => {
|
|
2712
|
+
if (!options?.onDisconnect) return void 0;
|
|
2713
|
+
return async (ctx) => {
|
|
2714
|
+
const extra = ctx.extra;
|
|
2715
|
+
await effect.Runtime.runPromise(extra.runtime)(
|
|
2716
|
+
options.onDisconnect(createConnectionContext(extra))
|
|
2717
|
+
).catch(() => {
|
|
2718
|
+
});
|
|
2719
|
+
};
|
|
2720
|
+
};
|
|
2721
|
+
var makeOnSubscribeHandler = (options, schema, complexityConfig, fieldComplexities) => {
|
|
2722
|
+
return async (ctx, id, payload) => {
|
|
2723
|
+
const extra = ctx.extra;
|
|
2724
|
+
const connectionCtx = createConnectionContext(extra);
|
|
2725
|
+
if (complexityConfig) {
|
|
2726
|
+
const validationEffect = validateComplexity(
|
|
2727
|
+
payload.query,
|
|
2728
|
+
payload.operationName ?? void 0,
|
|
2729
|
+
payload.variables ?? void 0,
|
|
2730
|
+
schema,
|
|
2731
|
+
fieldComplexities,
|
|
2732
|
+
complexityConfig
|
|
2733
|
+
).pipe(
|
|
2734
|
+
effect.Effect.catchAll((error) => {
|
|
2735
|
+
if (error._tag === "ComplexityLimitExceededError") {
|
|
2736
|
+
throw new graphql.GraphQLError(error.message, {
|
|
2737
|
+
extensions: {
|
|
2738
|
+
code: "COMPLEXITY_LIMIT_EXCEEDED",
|
|
2739
|
+
limitType: error.limitType,
|
|
2740
|
+
limit: error.limit,
|
|
2741
|
+
actual: error.actual
|
|
2742
|
+
}
|
|
2743
|
+
});
|
|
2744
|
+
}
|
|
2745
|
+
return effect.Effect.logWarning("Complexity analysis failed for subscription", error);
|
|
2746
|
+
})
|
|
2747
|
+
);
|
|
2748
|
+
await effect.Effect.runPromise(validationEffect);
|
|
2749
|
+
}
|
|
2750
|
+
if (options?.onSubscribe) {
|
|
2751
|
+
await effect.Runtime.runPromise(extra.runtime)(
|
|
2752
|
+
options.onSubscribe(connectionCtx, {
|
|
2753
|
+
id,
|
|
2754
|
+
payload: {
|
|
2755
|
+
query: payload.query,
|
|
2756
|
+
variables: payload.variables ?? void 0,
|
|
2757
|
+
operationName: payload.operationName ?? void 0,
|
|
2758
|
+
extensions: payload.extensions ?? void 0
|
|
2759
|
+
}
|
|
2760
|
+
})
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2764
|
+
};
|
|
2765
|
+
var makeOnCompleteHandler = (options) => {
|
|
2766
|
+
if (!options?.onComplete) return void 0;
|
|
2767
|
+
return async (ctx, id, _payload) => {
|
|
2768
|
+
const extra = ctx.extra;
|
|
2769
|
+
await effect.Runtime.runPromise(extra.runtime)(
|
|
2770
|
+
options.onComplete(createConnectionContext(extra), { id })
|
|
2771
|
+
).catch(() => {
|
|
2772
|
+
});
|
|
2773
|
+
};
|
|
2774
|
+
};
|
|
2775
|
+
var makeOnErrorHandler = (options) => {
|
|
2776
|
+
if (!options?.onError) return void 0;
|
|
2777
|
+
return async (ctx, _id, _payload, errors) => {
|
|
2778
|
+
const extra = ctx.extra;
|
|
2779
|
+
await effect.Runtime.runPromise(extra.runtime)(
|
|
2780
|
+
options.onError(createConnectionContext(extra), errors)
|
|
2781
|
+
).catch(() => {
|
|
2782
|
+
});
|
|
2783
|
+
};
|
|
2784
|
+
};
|
|
2785
|
+
var createGraphqlWsSocketAdapter = (socket, runtime) => {
|
|
2786
|
+
let messageCallback = null;
|
|
2787
|
+
return {
|
|
2788
|
+
adapter: {
|
|
2789
|
+
protocol: socket.protocol,
|
|
2790
|
+
send: (data) => effect.Runtime.runPromise(runtime)(
|
|
2791
|
+
socket.send(data).pipe(effect.Effect.catchAll((error) => effect.Effect.logError("WebSocket send error", error)))
|
|
2792
|
+
),
|
|
2793
|
+
close: (code, reason) => {
|
|
2794
|
+
effect.Runtime.runPromise(runtime)(socket.close(code, reason)).catch(() => {
|
|
2795
|
+
});
|
|
2796
|
+
},
|
|
2797
|
+
onMessage: (cb) => {
|
|
2798
|
+
messageCallback = cb;
|
|
2799
|
+
},
|
|
2800
|
+
onPong: (_payload) => {
|
|
2801
|
+
}
|
|
2802
|
+
},
|
|
2803
|
+
dispatchMessage: async (message) => {
|
|
2804
|
+
if (messageCallback) {
|
|
2805
|
+
await messageCallback(message);
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
};
|
|
2809
|
+
};
|
|
2810
|
+
var runConnectionLifecycle = (socket, wsServer, extra) => effect.Effect.gen(function* () {
|
|
2811
|
+
const messageQueue = yield* effect.Queue.unbounded();
|
|
2812
|
+
const closedDeferred = yield* effect.Deferred.make();
|
|
2813
|
+
const messageFiber = yield* effect.Effect.fork(
|
|
2814
|
+
effect.Stream.runForEach(socket.messages, (msg) => effect.Queue.offer(messageQueue, msg)).pipe(
|
|
2815
|
+
effect.Effect.catchAll((error) => effect.Deferred.fail(closedDeferred, error))
|
|
2816
|
+
)
|
|
2817
|
+
);
|
|
2818
|
+
const closeFiber = yield* effect.Effect.fork(
|
|
2819
|
+
socket.closed.pipe(
|
|
2820
|
+
effect.Effect.tap((event) => effect.Deferred.succeed(closedDeferred, event)),
|
|
2821
|
+
effect.Effect.catchAll((error) => effect.Deferred.fail(closedDeferred, error))
|
|
2822
|
+
)
|
|
2823
|
+
);
|
|
2824
|
+
const { adapter, dispatchMessage } = createGraphqlWsSocketAdapter(socket, extra.runtime);
|
|
2825
|
+
const closedHandler = wsServer.opened(adapter, extra);
|
|
2826
|
+
const processMessagesFiber = yield* effect.Effect.fork(
|
|
2827
|
+
effect.Effect.gen(function* () {
|
|
2828
|
+
while (true) {
|
|
2829
|
+
const message = yield* effect.Queue.take(messageQueue);
|
|
2830
|
+
yield* effect.Effect.tryPromise({
|
|
2831
|
+
try: () => dispatchMessage(message),
|
|
2832
|
+
catch: (error) => error
|
|
2833
|
+
}).pipe(effect.Effect.catchAll(() => effect.Effect.void));
|
|
2834
|
+
}
|
|
2835
|
+
})
|
|
2836
|
+
);
|
|
2837
|
+
yield* effect.Deferred.await(closedDeferred).pipe(
|
|
2838
|
+
effect.Effect.catchAll(() => effect.Effect.succeed({ code: 1e3, reason: "Error" }))
|
|
2839
|
+
);
|
|
2840
|
+
closedHandler(1e3, "Connection closed");
|
|
2841
|
+
yield* effect.Fiber.interrupt(messageFiber);
|
|
2842
|
+
yield* effect.Fiber.interrupt(closeFiber);
|
|
2843
|
+
yield* effect.Fiber.interrupt(processMessagesFiber);
|
|
2844
|
+
yield* effect.Queue.shutdown(messageQueue);
|
|
2845
|
+
}).pipe(
|
|
2846
|
+
effect.Effect.catchAllCause(() => effect.Effect.void),
|
|
2847
|
+
effect.Effect.scoped
|
|
2848
|
+
);
|
|
2849
|
+
var makeGraphQLWSHandler = (schema, layer, options) => {
|
|
2850
|
+
const complexityConfig = options?.complexity;
|
|
2851
|
+
const fieldComplexities = options?.fieldComplexities ?? /* @__PURE__ */ new Map();
|
|
2852
|
+
const serverOptions = {
|
|
2853
|
+
schema,
|
|
2854
|
+
context: async (ctx) => {
|
|
2855
|
+
const extra = ctx.extra;
|
|
2856
|
+
return {
|
|
2857
|
+
runtime: extra.runtime,
|
|
2858
|
+
...extra.connectionParams
|
|
2859
|
+
};
|
|
2860
|
+
},
|
|
2861
|
+
subscribe: async (args) => graphql.subscribe(args),
|
|
2862
|
+
onConnect: makeOnConnectHandler(options),
|
|
2863
|
+
onDisconnect: makeOnDisconnectHandler(options),
|
|
2864
|
+
onSubscribe: makeOnSubscribeHandler(options, schema, complexityConfig, fieldComplexities),
|
|
2865
|
+
onComplete: makeOnCompleteHandler(options),
|
|
2866
|
+
onError: makeOnErrorHandler(options)
|
|
2867
|
+
};
|
|
2868
|
+
const wsServer = graphqlWs.makeServer(serverOptions);
|
|
2869
|
+
return (socket) => effect.Effect.gen(function* () {
|
|
2870
|
+
const runtime = yield* effect.Effect.provide(effect.Effect.runtime(), layer);
|
|
2871
|
+
const extra = {
|
|
2872
|
+
socket,
|
|
2873
|
+
runtime,
|
|
2874
|
+
connectionParams: {}
|
|
2875
|
+
};
|
|
2876
|
+
yield* runConnectionLifecycle(socket, wsServer, extra);
|
|
2877
|
+
}).pipe(
|
|
2878
|
+
effect.Effect.catchAllCause(() => effect.Effect.void),
|
|
2879
|
+
effect.Effect.scoped
|
|
2880
|
+
);
|
|
2881
|
+
};
|
|
2882
|
+
var WS_CLOSED = 3;
|
|
2883
|
+
var toEffectWebSocketFromWs = (ws) => {
|
|
2884
|
+
const messagesEffect = effect.Effect.gen(function* () {
|
|
2885
|
+
const queue = yield* effect.Queue.unbounded();
|
|
2886
|
+
const closed = yield* effect.Deferred.make();
|
|
2887
|
+
ws.on("message", (data) => {
|
|
2888
|
+
const message = data.toString();
|
|
2889
|
+
effect.Effect.runPromise(effect.Queue.offer(queue, message)).catch(() => {
|
|
2890
|
+
});
|
|
2891
|
+
});
|
|
2892
|
+
ws.on("error", (error) => {
|
|
2893
|
+
effect.Effect.runPromise(effect.Deferred.fail(closed, new WebSocketError({ cause: error }))).catch(() => {
|
|
2894
|
+
});
|
|
2895
|
+
});
|
|
2896
|
+
ws.on("close", (code, reason) => {
|
|
2897
|
+
effect.Effect.runPromise(
|
|
2898
|
+
effect.Queue.shutdown(queue).pipe(
|
|
2899
|
+
effect.Effect.andThen(effect.Deferred.succeed(closed, { code, reason: reason.toString() }))
|
|
2900
|
+
)
|
|
2901
|
+
).catch(() => {
|
|
2902
|
+
});
|
|
2903
|
+
});
|
|
2904
|
+
return { queue, closed };
|
|
2905
|
+
});
|
|
2906
|
+
const messages = effect.Stream.unwrap(
|
|
2907
|
+
messagesEffect.pipe(
|
|
2908
|
+
effect.Effect.map(({ queue }) => effect.Stream.fromQueue(queue).pipe(effect.Stream.catchAll(() => effect.Stream.empty)))
|
|
2909
|
+
)
|
|
2910
|
+
);
|
|
2911
|
+
return {
|
|
2912
|
+
protocol: ws.protocol || "graphql-transport-ws",
|
|
2913
|
+
send: (data) => effect.Effect.async((resume) => {
|
|
2914
|
+
ws.send(data, (error) => {
|
|
2915
|
+
if (error) {
|
|
2916
|
+
resume(effect.Effect.fail(new WebSocketError({ cause: error })));
|
|
2917
|
+
} else {
|
|
2918
|
+
resume(effect.Effect.succeed(void 0));
|
|
2919
|
+
}
|
|
2920
|
+
});
|
|
2921
|
+
}),
|
|
2922
|
+
close: (code, reason) => effect.Effect.sync(() => {
|
|
2923
|
+
ws.close(code ?? 1e3, reason ?? "");
|
|
2924
|
+
}),
|
|
2925
|
+
messages,
|
|
2926
|
+
closed: effect.Effect.async((resume) => {
|
|
2927
|
+
if (ws.readyState === WS_CLOSED) {
|
|
2928
|
+
resume(effect.Effect.succeed({ code: 1e3, reason: "" }));
|
|
2929
|
+
return;
|
|
2930
|
+
}
|
|
2931
|
+
const onClose = (code, reason) => {
|
|
2932
|
+
cleanup();
|
|
2933
|
+
resume(effect.Effect.succeed({ code, reason: reason.toString() }));
|
|
2934
|
+
};
|
|
2935
|
+
const onError = (error) => {
|
|
2936
|
+
cleanup();
|
|
2937
|
+
resume(effect.Effect.fail(new WebSocketError({ cause: error })));
|
|
2938
|
+
};
|
|
2939
|
+
const cleanup = () => {
|
|
2940
|
+
ws.removeListener("close", onClose);
|
|
2941
|
+
ws.removeListener("error", onError);
|
|
2942
|
+
};
|
|
2943
|
+
ws.on("close", onClose);
|
|
2944
|
+
ws.on("error", onError);
|
|
2945
|
+
return effect.Effect.sync(cleanup);
|
|
2946
|
+
})
|
|
2947
|
+
};
|
|
2948
|
+
};
|
|
2949
|
+
var SSE_HEADERS = {
|
|
2950
|
+
"Content-Type": "text/event-stream",
|
|
2951
|
+
"Cache-Control": "no-cache",
|
|
2952
|
+
Connection: "keep-alive",
|
|
2953
|
+
"X-Accel-Buffering": "no"
|
|
2954
|
+
// Disable nginx buffering
|
|
2955
|
+
};
|
|
2956
|
+
var SSEError = class extends effect.Data.TaggedError("SSEError") {
|
|
2957
|
+
};
|
|
2958
|
+
var formatNextEvent = (result) => ({
|
|
2959
|
+
event: "next",
|
|
2960
|
+
data: JSON.stringify(result)
|
|
2961
|
+
});
|
|
2962
|
+
var formatErrorEvent = (errors) => ({
|
|
2963
|
+
event: "error",
|
|
2964
|
+
data: JSON.stringify({ errors })
|
|
2965
|
+
});
|
|
2966
|
+
var formatCompleteEvent = () => ({
|
|
2967
|
+
event: "complete",
|
|
2968
|
+
data: ""
|
|
2969
|
+
});
|
|
2970
|
+
var formatSSEMessage = (event) => {
|
|
2971
|
+
const lines = [`event: ${event.event}`];
|
|
2972
|
+
if (event.data) {
|
|
2973
|
+
lines.push(`data: ${event.data}`);
|
|
2974
|
+
}
|
|
2975
|
+
lines.push("", "");
|
|
2976
|
+
return lines.join("\n");
|
|
2977
|
+
};
|
|
2978
|
+
var makeSSESubscriptionStream = (schema, layer, request, headers, options) => {
|
|
2979
|
+
const complexityConfig = options?.complexity;
|
|
2980
|
+
const fieldComplexities = options?.fieldComplexities ?? /* @__PURE__ */ new Map();
|
|
2981
|
+
return effect.Stream.unwrap(
|
|
2982
|
+
effect.Effect.gen(function* () {
|
|
2983
|
+
const runtime = yield* effect.Effect.provide(effect.Effect.runtime(), layer);
|
|
2984
|
+
let connectionContext = {};
|
|
2985
|
+
if (options?.onConnect) {
|
|
2986
|
+
try {
|
|
2987
|
+
connectionContext = yield* effect.Effect.provide(options.onConnect(request, headers), layer);
|
|
2988
|
+
} catch {
|
|
2989
|
+
return effect.Stream.make(
|
|
2990
|
+
formatErrorEvent([
|
|
2991
|
+
new graphql.GraphQLError("Subscription connection rejected", {
|
|
2992
|
+
extensions: { code: "CONNECTION_REJECTED" }
|
|
2993
|
+
})
|
|
2994
|
+
]),
|
|
2995
|
+
formatCompleteEvent()
|
|
2996
|
+
);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
let document;
|
|
3000
|
+
try {
|
|
3001
|
+
document = graphql.parse(request.query);
|
|
3002
|
+
} catch (syntaxError) {
|
|
3003
|
+
return effect.Stream.make(formatErrorEvent([syntaxError]), formatCompleteEvent());
|
|
3004
|
+
}
|
|
3005
|
+
const validationErrors = graphql.validate(schema, document);
|
|
3006
|
+
if (validationErrors.length > 0) {
|
|
3007
|
+
return effect.Stream.make(formatErrorEvent(validationErrors), formatCompleteEvent());
|
|
3008
|
+
}
|
|
3009
|
+
const operations = document.definitions.filter(
|
|
3010
|
+
(d) => d.kind === graphql.Kind.OPERATION_DEFINITION
|
|
3011
|
+
);
|
|
3012
|
+
const operation = request.operationName ? operations.find((o) => o.name?.value === request.operationName) : operations[0];
|
|
3013
|
+
if (!operation) {
|
|
3014
|
+
return effect.Stream.make(
|
|
3015
|
+
formatErrorEvent([new graphql.GraphQLError("No operation found in query")]),
|
|
3016
|
+
formatCompleteEvent()
|
|
3017
|
+
);
|
|
3018
|
+
}
|
|
3019
|
+
if (operation.operation !== "subscription") {
|
|
3020
|
+
return effect.Stream.make(
|
|
3021
|
+
formatErrorEvent([
|
|
3022
|
+
new graphql.GraphQLError(
|
|
3023
|
+
`SSE endpoint only supports subscriptions, received: ${operation.operation}`,
|
|
3024
|
+
{ extensions: { code: "OPERATION_NOT_SUPPORTED" } }
|
|
3025
|
+
)
|
|
3026
|
+
]),
|
|
3027
|
+
formatCompleteEvent()
|
|
3028
|
+
);
|
|
3029
|
+
}
|
|
3030
|
+
if (complexityConfig) {
|
|
3031
|
+
const complexityResult = yield* validateComplexity(
|
|
3032
|
+
request.query,
|
|
3033
|
+
request.operationName,
|
|
3034
|
+
request.variables,
|
|
3035
|
+
schema,
|
|
3036
|
+
fieldComplexities,
|
|
3037
|
+
complexityConfig
|
|
3038
|
+
).pipe(
|
|
3039
|
+
effect.Effect.map(() => null),
|
|
3040
|
+
effect.Effect.catchAll((error) => {
|
|
3041
|
+
if (error._tag === "ComplexityLimitExceededError") {
|
|
3042
|
+
return effect.Effect.succeed(
|
|
3043
|
+
new graphql.GraphQLError(error.message, {
|
|
3044
|
+
extensions: {
|
|
3045
|
+
code: "COMPLEXITY_LIMIT_EXCEEDED",
|
|
3046
|
+
limitType: error.limitType,
|
|
3047
|
+
limit: error.limit,
|
|
3048
|
+
actual: error.actual
|
|
3049
|
+
}
|
|
3050
|
+
})
|
|
3051
|
+
);
|
|
3052
|
+
}
|
|
3053
|
+
return effect.Effect.logWarning("Complexity analysis failed for SSE subscription", error).pipe(
|
|
3054
|
+
effect.Effect.map(() => null)
|
|
3055
|
+
);
|
|
3056
|
+
})
|
|
3057
|
+
);
|
|
3058
|
+
if (complexityResult) {
|
|
3059
|
+
return effect.Stream.make(formatErrorEvent([complexityResult]), formatCompleteEvent());
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
const ctx = {
|
|
3063
|
+
runtime,
|
|
3064
|
+
request,
|
|
3065
|
+
connectionContext
|
|
3066
|
+
};
|
|
3067
|
+
if (options?.onSubscribe) {
|
|
3068
|
+
yield* effect.Effect.provide(options.onSubscribe(ctx), layer).pipe(
|
|
3069
|
+
effect.Effect.catchAll(() => effect.Effect.void)
|
|
3070
|
+
);
|
|
3071
|
+
}
|
|
3072
|
+
const graphqlContext = {
|
|
3073
|
+
runtime,
|
|
3074
|
+
...connectionContext
|
|
3075
|
+
};
|
|
3076
|
+
const subscriptionResult = yield* effect.Effect.tryPromise({
|
|
3077
|
+
try: () => graphql.subscribe({
|
|
3078
|
+
schema,
|
|
3079
|
+
document,
|
|
3080
|
+
variableValues: request.variables,
|
|
3081
|
+
operationName: request.operationName ?? void 0,
|
|
3082
|
+
contextValue: graphqlContext
|
|
3083
|
+
}),
|
|
3084
|
+
catch: (error) => new SSEError({ cause: error })
|
|
3085
|
+
});
|
|
3086
|
+
if (!isAsyncIterable(subscriptionResult)) {
|
|
3087
|
+
const result = subscriptionResult;
|
|
3088
|
+
if (result.errors) {
|
|
3089
|
+
return effect.Stream.make(formatErrorEvent(result.errors), formatCompleteEvent());
|
|
3090
|
+
}
|
|
3091
|
+
return effect.Stream.make(formatNextEvent(result), formatCompleteEvent());
|
|
3092
|
+
}
|
|
3093
|
+
const asyncIterator = subscriptionResult[Symbol.asyncIterator]();
|
|
3094
|
+
const eventStream = effect.Stream.async((emit) => {
|
|
3095
|
+
let done = false;
|
|
3096
|
+
const iterate = async () => {
|
|
3097
|
+
try {
|
|
3098
|
+
while (!done) {
|
|
3099
|
+
const result = await asyncIterator.next();
|
|
3100
|
+
if (result.done) {
|
|
3101
|
+
emit.end();
|
|
3102
|
+
break;
|
|
3103
|
+
}
|
|
3104
|
+
emit.single(formatNextEvent(result.value));
|
|
3105
|
+
}
|
|
3106
|
+
} catch (error) {
|
|
3107
|
+
if (!done) {
|
|
3108
|
+
emit.single(
|
|
3109
|
+
formatErrorEvent([
|
|
3110
|
+
error instanceof graphql.GraphQLError ? error : new graphql.GraphQLError(
|
|
3111
|
+
error instanceof Error ? error.message : "Subscription error",
|
|
3112
|
+
{ extensions: { code: "SUBSCRIPTION_ERROR" } }
|
|
3113
|
+
)
|
|
3114
|
+
])
|
|
3115
|
+
);
|
|
3116
|
+
emit.end();
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
};
|
|
3120
|
+
iterate();
|
|
3121
|
+
return effect.Effect.sync(() => {
|
|
3122
|
+
done = true;
|
|
3123
|
+
asyncIterator.return?.();
|
|
3124
|
+
});
|
|
3125
|
+
});
|
|
3126
|
+
return eventStream.pipe(
|
|
3127
|
+
effect.Stream.onDone(
|
|
3128
|
+
() => effect.Effect.gen(function* () {
|
|
3129
|
+
yield* effect.Effect.sync(() => {
|
|
3130
|
+
});
|
|
3131
|
+
}).pipe(effect.Effect.asVoid)
|
|
3132
|
+
),
|
|
3133
|
+
effect.Stream.concat(effect.Stream.make(formatCompleteEvent())),
|
|
3134
|
+
effect.Stream.onDone(() => {
|
|
3135
|
+
if (options?.onComplete) {
|
|
3136
|
+
return effect.Effect.provide(options.onComplete(ctx), layer).pipe(
|
|
3137
|
+
effect.Effect.catchAll(() => effect.Effect.void)
|
|
3138
|
+
);
|
|
3139
|
+
}
|
|
3140
|
+
return effect.Effect.void;
|
|
3141
|
+
})
|
|
3142
|
+
);
|
|
3143
|
+
}).pipe(
|
|
3144
|
+
effect.Effect.catchAll(
|
|
3145
|
+
(error) => effect.Effect.succeed(
|
|
3146
|
+
effect.Stream.make(
|
|
3147
|
+
formatErrorEvent([
|
|
3148
|
+
new graphql.GraphQLError(error instanceof Error ? error.message : "Internal error", {
|
|
3149
|
+
extensions: { code: "INTERNAL_ERROR" }
|
|
3150
|
+
})
|
|
3151
|
+
]),
|
|
3152
|
+
formatCompleteEvent()
|
|
3153
|
+
)
|
|
3154
|
+
)
|
|
3155
|
+
)
|
|
3156
|
+
)
|
|
3157
|
+
);
|
|
3158
|
+
};
|
|
3159
|
+
var makeGraphQLSSEHandler = (schema, layer, options) => {
|
|
3160
|
+
return (request, headers) => makeSSESubscriptionStream(schema, layer, request, headers, options);
|
|
3161
|
+
};
|
|
3162
|
+
function isAsyncIterable(value) {
|
|
3163
|
+
return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
|
|
3164
|
+
}
|
|
3165
|
+
var createAnalyzerExtension = (config = {}) => {
|
|
3166
|
+
const {
|
|
3167
|
+
includeComplexity = true,
|
|
3168
|
+
includeDepth = true,
|
|
3169
|
+
includeFieldCount = false,
|
|
3170
|
+
includeAliasCount = false,
|
|
3171
|
+
key = "analyzer",
|
|
3172
|
+
thresholds,
|
|
3173
|
+
defaultFieldComplexity = 1,
|
|
3174
|
+
fieldComplexities: configFieldComplexities
|
|
3175
|
+
} = config;
|
|
3176
|
+
return {
|
|
3177
|
+
name: "analyzer",
|
|
3178
|
+
description: "Reports query complexity metrics in response extensions",
|
|
3179
|
+
onExecuteStart: (args) => effect.Effect.gen(function* () {
|
|
3180
|
+
const ext = yield* ExtensionsService;
|
|
3181
|
+
const operation = findOperation(args);
|
|
3182
|
+
if (!operation) {
|
|
3183
|
+
return;
|
|
3184
|
+
}
|
|
3185
|
+
const fieldComplexities = configFieldComplexities ?? args.fieldComplexities;
|
|
3186
|
+
const calculator = defaultComplexityCalculator(defaultFieldComplexity);
|
|
3187
|
+
const result = yield* calculator({
|
|
3188
|
+
document: args.document,
|
|
3189
|
+
operation,
|
|
3190
|
+
variables: args.variableValues,
|
|
3191
|
+
schema: args.schema,
|
|
3192
|
+
fieldComplexities
|
|
3193
|
+
}).pipe(
|
|
3194
|
+
effect.Effect.catchAll(
|
|
3195
|
+
(error) => effect.Effect.logWarning("Analyzer extension: complexity calculation failed", error).pipe(
|
|
3196
|
+
effect.Effect.as(null)
|
|
3197
|
+
)
|
|
3198
|
+
)
|
|
3199
|
+
);
|
|
3200
|
+
if (!result) {
|
|
3201
|
+
return;
|
|
3202
|
+
}
|
|
3203
|
+
yield* checkThresholds(result, thresholds);
|
|
3204
|
+
const output = {};
|
|
3205
|
+
if (includeComplexity) {
|
|
3206
|
+
output.complexity = result.complexity;
|
|
3207
|
+
}
|
|
3208
|
+
if (includeDepth) {
|
|
3209
|
+
output.depth = result.depth;
|
|
3210
|
+
}
|
|
3211
|
+
if (includeFieldCount) {
|
|
3212
|
+
output.fieldCount = result.fieldCount;
|
|
3213
|
+
}
|
|
3214
|
+
if (includeAliasCount) {
|
|
3215
|
+
output.aliasCount = result.aliasCount;
|
|
3216
|
+
}
|
|
3217
|
+
yield* ext.set(key, output);
|
|
3218
|
+
})
|
|
3219
|
+
};
|
|
3220
|
+
};
|
|
3221
|
+
function findOperation(args) {
|
|
3222
|
+
const operations = args.document.definitions.filter(
|
|
3223
|
+
(d) => d.kind === graphql.Kind.OPERATION_DEFINITION
|
|
3224
|
+
);
|
|
3225
|
+
if (operations.length === 0) {
|
|
3226
|
+
return null;
|
|
3227
|
+
}
|
|
3228
|
+
if (args.operationName) {
|
|
3229
|
+
return operations.find((o) => o.name?.value === args.operationName) ?? null;
|
|
3230
|
+
}
|
|
3231
|
+
return operations[0];
|
|
3232
|
+
}
|
|
3233
|
+
function checkThresholds(result, thresholds) {
|
|
3234
|
+
if (!thresholds) {
|
|
3235
|
+
return effect.Effect.void;
|
|
3236
|
+
}
|
|
3237
|
+
const warnings = [];
|
|
3238
|
+
if (thresholds.depth !== void 0 && result.depth > thresholds.depth) {
|
|
3239
|
+
warnings.push(`Query depth ${result.depth} exceeds threshold ${thresholds.depth}`);
|
|
3240
|
+
}
|
|
3241
|
+
if (thresholds.complexity !== void 0 && result.complexity > thresholds.complexity) {
|
|
3242
|
+
warnings.push(
|
|
3243
|
+
`Query complexity ${result.complexity} exceeds threshold ${thresholds.complexity}`
|
|
3244
|
+
);
|
|
3245
|
+
}
|
|
3246
|
+
if (thresholds.fieldCount !== void 0 && result.fieldCount > thresholds.fieldCount) {
|
|
3247
|
+
warnings.push(
|
|
3248
|
+
`Query field count ${result.fieldCount} exceeds threshold ${thresholds.fieldCount}`
|
|
3249
|
+
);
|
|
3250
|
+
}
|
|
3251
|
+
if (thresholds.aliasCount !== void 0 && result.aliasCount > thresholds.aliasCount) {
|
|
3252
|
+
warnings.push(
|
|
3253
|
+
`Query alias count ${result.aliasCount} exceeds threshold ${thresholds.aliasCount}`
|
|
3254
|
+
);
|
|
3255
|
+
}
|
|
3256
|
+
if (warnings.length > 0) {
|
|
3257
|
+
return effect.Effect.logWarning("Analyzer extension: thresholds exceeded", {
|
|
3258
|
+
warnings,
|
|
3259
|
+
result
|
|
3260
|
+
});
|
|
3261
|
+
}
|
|
3262
|
+
return effect.Effect.void;
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
Object.defineProperty(exports, "DirectiveLocation", {
|
|
3266
|
+
enumerable: true,
|
|
3267
|
+
get: function () { return graphql.DirectiveLocation; }
|
|
3268
|
+
});
|
|
3269
|
+
Object.defineProperty(exports, "GraphQLBoolean", {
|
|
3270
|
+
enumerable: true,
|
|
3271
|
+
get: function () { return graphql.GraphQLBoolean; }
|
|
3272
|
+
});
|
|
3273
|
+
Object.defineProperty(exports, "GraphQLEnumType", {
|
|
3274
|
+
enumerable: true,
|
|
3275
|
+
get: function () { return graphql.GraphQLEnumType; }
|
|
3276
|
+
});
|
|
3277
|
+
Object.defineProperty(exports, "GraphQLFloat", {
|
|
3278
|
+
enumerable: true,
|
|
3279
|
+
get: function () { return graphql.GraphQLFloat; }
|
|
3280
|
+
});
|
|
3281
|
+
Object.defineProperty(exports, "GraphQLID", {
|
|
3282
|
+
enumerable: true,
|
|
3283
|
+
get: function () { return graphql.GraphQLID; }
|
|
3284
|
+
});
|
|
3285
|
+
Object.defineProperty(exports, "GraphQLInputObjectType", {
|
|
3286
|
+
enumerable: true,
|
|
3287
|
+
get: function () { return graphql.GraphQLInputObjectType; }
|
|
3288
|
+
});
|
|
3289
|
+
Object.defineProperty(exports, "GraphQLInt", {
|
|
3290
|
+
enumerable: true,
|
|
3291
|
+
get: function () { return graphql.GraphQLInt; }
|
|
3292
|
+
});
|
|
3293
|
+
Object.defineProperty(exports, "GraphQLInterfaceType", {
|
|
3294
|
+
enumerable: true,
|
|
3295
|
+
get: function () { return graphql.GraphQLInterfaceType; }
|
|
3296
|
+
});
|
|
3297
|
+
Object.defineProperty(exports, "GraphQLList", {
|
|
3298
|
+
enumerable: true,
|
|
3299
|
+
get: function () { return graphql.GraphQLList; }
|
|
3300
|
+
});
|
|
3301
|
+
Object.defineProperty(exports, "GraphQLNonNull", {
|
|
3302
|
+
enumerable: true,
|
|
3303
|
+
get: function () { return graphql.GraphQLNonNull; }
|
|
3304
|
+
});
|
|
3305
|
+
Object.defineProperty(exports, "GraphQLObjectType", {
|
|
3306
|
+
enumerable: true,
|
|
3307
|
+
get: function () { return graphql.GraphQLObjectType; }
|
|
3308
|
+
});
|
|
3309
|
+
Object.defineProperty(exports, "GraphQLScalarType", {
|
|
3310
|
+
enumerable: true,
|
|
3311
|
+
get: function () { return graphql.GraphQLScalarType; }
|
|
3312
|
+
});
|
|
3313
|
+
Object.defineProperty(exports, "GraphQLSchema", {
|
|
3314
|
+
enumerable: true,
|
|
3315
|
+
get: function () { return graphql.GraphQLSchema; }
|
|
3316
|
+
});
|
|
3317
|
+
Object.defineProperty(exports, "GraphQLString", {
|
|
3318
|
+
enumerable: true,
|
|
3319
|
+
get: function () { return graphql.GraphQLString; }
|
|
3320
|
+
});
|
|
3321
|
+
Object.defineProperty(exports, "GraphQLUnionType", {
|
|
3322
|
+
enumerable: true,
|
|
3323
|
+
get: function () { return graphql.GraphQLUnionType; }
|
|
3324
|
+
});
|
|
3325
|
+
Object.defineProperty(exports, "Kind", {
|
|
3326
|
+
enumerable: true,
|
|
3327
|
+
get: function () { return graphql.Kind; }
|
|
3328
|
+
});
|
|
3329
|
+
Object.defineProperty(exports, "graphql", {
|
|
3330
|
+
enumerable: true,
|
|
3331
|
+
get: function () { return graphql.graphql; }
|
|
3332
|
+
});
|
|
3333
|
+
Object.defineProperty(exports, "lexicographicSortSchema", {
|
|
3334
|
+
enumerable: true,
|
|
3335
|
+
get: function () { return graphql.lexicographicSortSchema; }
|
|
3336
|
+
});
|
|
3337
|
+
Object.defineProperty(exports, "printSchema", {
|
|
3338
|
+
enumerable: true,
|
|
3339
|
+
get: function () { return graphql.printSchema; }
|
|
3340
|
+
});
|
|
3341
|
+
exports.AuthorizationError = AuthorizationError;
|
|
3342
|
+
exports.CacheControlConfigFromEnv = CacheControlConfigFromEnv;
|
|
3343
|
+
exports.ComplexityAnalysisError = ComplexityAnalysisError;
|
|
3344
|
+
exports.ComplexityConfigFromEnv = ComplexityConfigFromEnv;
|
|
3345
|
+
exports.ComplexityLimitExceededError = ComplexityLimitExceededError;
|
|
3346
|
+
exports.ExtensionsService = ExtensionsService;
|
|
3347
|
+
exports.GraphQLError = GraphQLError2;
|
|
3348
|
+
exports.GraphQLRequestContext = GraphQLRequestContext;
|
|
3349
|
+
exports.GraphQLRouterConfigFromEnv = GraphQLRouterConfigFromEnv;
|
|
3350
|
+
exports.GraphQLSchemaBuilder = GraphQLSchemaBuilder;
|
|
3351
|
+
exports.Loader = Loader;
|
|
3352
|
+
exports.MissingResolverContextError = MissingResolverContextError;
|
|
3353
|
+
exports.NotFoundError = NotFoundError;
|
|
3354
|
+
exports.ResolverContext = ResolverContext;
|
|
3355
|
+
exports.ResolverContextStore = ResolverContextStore;
|
|
3356
|
+
exports.SSEError = SSEError;
|
|
3357
|
+
exports.SSE_HEADERS = SSE_HEADERS;
|
|
3358
|
+
exports.ValidationError = ValidationError;
|
|
3359
|
+
exports.WS_CLOSED = WS_CLOSED;
|
|
3360
|
+
exports.WebSocketError = WebSocketError;
|
|
3361
|
+
exports.combineCalculators = combineCalculators;
|
|
3362
|
+
exports.compose = compose;
|
|
3363
|
+
exports.computeCachePolicy = computeCachePolicy;
|
|
3364
|
+
exports.computeCachePolicyFromQuery = computeCachePolicyFromQuery;
|
|
3365
|
+
exports.createAnalyzerExtension = createAnalyzerExtension;
|
|
3366
|
+
exports.defaultComplexityCalculator = defaultComplexityCalculator;
|
|
3367
|
+
exports.defaultConfig = defaultConfig;
|
|
3368
|
+
exports.defaultErrorHandler = defaultErrorHandler;
|
|
3369
|
+
exports.depthOnlyCalculator = depthOnlyCalculator;
|
|
3370
|
+
exports.directive = directive;
|
|
3371
|
+
exports.enumType = enumType;
|
|
3372
|
+
exports.execute = execute;
|
|
3373
|
+
exports.extension = extension;
|
|
3374
|
+
exports.field = field;
|
|
3375
|
+
exports.formatCompleteEvent = formatCompleteEvent;
|
|
3376
|
+
exports.formatErrorEvent = formatErrorEvent;
|
|
3377
|
+
exports.formatNextEvent = formatNextEvent;
|
|
3378
|
+
exports.formatSSEMessage = formatSSEMessage;
|
|
3379
|
+
exports.get = get;
|
|
3380
|
+
exports.getOption = getOption;
|
|
3381
|
+
exports.getOrElse = getOrElse;
|
|
3382
|
+
exports.getSchemaName = getSchemaName;
|
|
3383
|
+
exports.graphiqlHtml = graphiqlHtml;
|
|
3384
|
+
exports.has = has;
|
|
3385
|
+
exports.inputType = inputType;
|
|
3386
|
+
exports.interfaceType = interfaceType;
|
|
3387
|
+
exports.make = make3;
|
|
3388
|
+
exports.makeExtensionsService = makeExtensionsService;
|
|
3389
|
+
exports.makeGraphQLRouter = makeGraphQLRouter;
|
|
3390
|
+
exports.makeGraphQLSSEHandler = makeGraphQLSSEHandler;
|
|
3391
|
+
exports.makeGraphQLWSHandler = makeGraphQLWSHandler;
|
|
3392
|
+
exports.makeRequestContextLayer = makeRequestContextLayer;
|
|
3393
|
+
exports.makeSSESubscriptionStream = makeSSESubscriptionStream;
|
|
3394
|
+
exports.makeStoreLayer = makeStoreLayer;
|
|
3395
|
+
exports.middleware = middleware;
|
|
3396
|
+
exports.mutation = mutation;
|
|
3397
|
+
exports.normalizeConfig = normalizeConfig;
|
|
3398
|
+
exports.objectType = objectType;
|
|
3399
|
+
exports.query = query;
|
|
3400
|
+
exports.runExecuteEndHooks = runExecuteEndHooks;
|
|
3401
|
+
exports.runExecuteStartHooks = runExecuteStartHooks;
|
|
3402
|
+
exports.runParseHooks = runParseHooks;
|
|
3403
|
+
exports.runValidateHooks = runValidateHooks;
|
|
3404
|
+
exports.scoped = scoped;
|
|
3405
|
+
exports.set = set;
|
|
3406
|
+
exports.setMany = setMany;
|
|
3407
|
+
exports.storeLayer = storeLayer;
|
|
3408
|
+
exports.subscription = subscription;
|
|
3409
|
+
exports.toCacheControlHeader = toCacheControlHeader;
|
|
3410
|
+
exports.toEffectWebSocketFromWs = toEffectWebSocketFromWs;
|
|
3411
|
+
exports.toGraphQLArgs = toGraphQLArgs;
|
|
3412
|
+
exports.toGraphQLInputType = toGraphQLInputType;
|
|
3413
|
+
exports.toGraphQLObjectType = toGraphQLObjectType;
|
|
3414
|
+
exports.toGraphQLType = toGraphQLType;
|
|
3415
|
+
exports.toRouter = toRouter;
|
|
3416
|
+
exports.unionType = unionType;
|
|
3417
|
+
exports.validateComplexity = validateComplexity;
|
|
3418
|
+
//# sourceMappingURL=index.cjs.map
|
|
3419
|
+
//# sourceMappingURL=index.cjs.map
|