@effect-gql/core 1.0.0 → 1.1.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/builder/index.cjs +17 -2
- package/builder/index.cjs.map +1 -1
- package/builder/index.d.cts +3 -2
- package/builder/index.d.ts +3 -2
- package/builder/index.js +17 -2
- package/builder/index.js.map +1 -1
- package/index.cjs +107 -57
- package/index.cjs.map +1 -1
- package/index.d.cts +9 -3
- package/index.d.ts +9 -3
- package/index.js +109 -59
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/{schema-builder-Cvdq7Kz_.d.cts → schema-builder-DKvkzU_M.d.cts} +2 -0
- package/{schema-builder-Cvdq7Kz_.d.ts → schema-builder-DKvkzU_M.d.ts} +2 -0
- package/server/index.cjs +54 -30
- package/server/index.cjs.map +1 -1
- package/server/index.d.cts +5 -3
- package/server/index.d.ts +5 -3
- package/server/index.js +56 -32
- package/server/index.js.map +1 -1
package/index.cjs
CHANGED
|
@@ -837,7 +837,14 @@ var GraphQLSchemaBuilder = class _GraphQLSchemaBuilder {
|
|
|
837
837
|
* Register an object type from a schema
|
|
838
838
|
*/
|
|
839
839
|
objectType(config) {
|
|
840
|
-
const {
|
|
840
|
+
const {
|
|
841
|
+
schema,
|
|
842
|
+
description,
|
|
843
|
+
implements: implementsInterfaces,
|
|
844
|
+
directives,
|
|
845
|
+
cacheControl,
|
|
846
|
+
fields
|
|
847
|
+
} = config;
|
|
841
848
|
const name = config.name ?? getSchemaName(schema);
|
|
842
849
|
if (!name) {
|
|
843
850
|
throw new Error(
|
|
@@ -845,7 +852,14 @@ var GraphQLSchemaBuilder = class _GraphQLSchemaBuilder {
|
|
|
845
852
|
);
|
|
846
853
|
}
|
|
847
854
|
const newTypes = new Map(this.state.types);
|
|
848
|
-
newTypes.set(name, {
|
|
855
|
+
newTypes.set(name, {
|
|
856
|
+
name,
|
|
857
|
+
schema,
|
|
858
|
+
description,
|
|
859
|
+
implements: implementsInterfaces,
|
|
860
|
+
directives,
|
|
861
|
+
cacheControl
|
|
862
|
+
});
|
|
849
863
|
let newObjectFields = this.state.objectFields;
|
|
850
864
|
if (fields) {
|
|
851
865
|
newObjectFields = new Map(this.state.objectFields);
|
|
@@ -1214,6 +1228,7 @@ var GraphQLSchemaBuilder = class _GraphQLSchemaBuilder {
|
|
|
1214
1228
|
const implementedInterfaces = typeReg.implements?.map((name) => interfaceRegistry.get(name)).filter(Boolean) ?? [];
|
|
1215
1229
|
const graphqlType = new graphql.GraphQLObjectType({
|
|
1216
1230
|
name: typeName,
|
|
1231
|
+
description: typeReg.description,
|
|
1217
1232
|
fields: () => {
|
|
1218
1233
|
const baseFields = schemaToFields(typeReg.schema, sharedCtx);
|
|
1219
1234
|
const additionalFields = this.state.objectFields.get(typeName);
|
|
@@ -1489,7 +1504,8 @@ var LoaderRegistry = class {
|
|
|
1489
1504
|
this.Service,
|
|
1490
1505
|
effect.Effect.gen(function* () {
|
|
1491
1506
|
const instances = {};
|
|
1492
|
-
for (const
|
|
1507
|
+
for (const name of Object.keys(self.definitions)) {
|
|
1508
|
+
const def = self.definitions[name];
|
|
1493
1509
|
instances[name] = yield* createDataLoader(def);
|
|
1494
1510
|
}
|
|
1495
1511
|
return instances;
|
|
@@ -1509,6 +1525,9 @@ var LoaderRegistry = class {
|
|
|
1509
1525
|
/**
|
|
1510
1526
|
* Load a single value by key.
|
|
1511
1527
|
* This is the most common operation in resolvers.
|
|
1528
|
+
*
|
|
1529
|
+
* @internal The internal cast is safe because LoaderInstances<Defs> guarantees
|
|
1530
|
+
* that loaders[name] is a DataLoader with the correct key/value types.
|
|
1512
1531
|
*/
|
|
1513
1532
|
load(name, key) {
|
|
1514
1533
|
const self = this;
|
|
@@ -1521,6 +1540,9 @@ var LoaderRegistry = class {
|
|
|
1521
1540
|
/**
|
|
1522
1541
|
* Load multiple values by keys.
|
|
1523
1542
|
* All keys are batched into a single request.
|
|
1543
|
+
*
|
|
1544
|
+
* @internal The internal cast is safe because LoaderInstances<Defs> guarantees
|
|
1545
|
+
* that loaders[name] is a DataLoader with the correct key/value types.
|
|
1524
1546
|
*/
|
|
1525
1547
|
loadMany(name, keys) {
|
|
1526
1548
|
const self = this;
|
|
@@ -1537,35 +1559,39 @@ var LoaderRegistry = class {
|
|
|
1537
1559
|
});
|
|
1538
1560
|
}
|
|
1539
1561
|
};
|
|
1562
|
+
function createSingleDataLoader(def, context) {
|
|
1563
|
+
return new DataLoader__default.default(async (keys) => {
|
|
1564
|
+
const items = await effect.Effect.runPromise(def.batch(keys).pipe(effect.Effect.provide(context)));
|
|
1565
|
+
return keys.map((key) => {
|
|
1566
|
+
const item = items.find((i) => def.key(i) === key);
|
|
1567
|
+
if (!item) return new Error(`Not found: ${key}`);
|
|
1568
|
+
return item;
|
|
1569
|
+
});
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
function createGroupedDataLoader(def, context) {
|
|
1573
|
+
return new DataLoader__default.default(async (keys) => {
|
|
1574
|
+
const items = await effect.Effect.runPromise(def.batch(keys).pipe(effect.Effect.provide(context)));
|
|
1575
|
+
const map = /* @__PURE__ */ new Map();
|
|
1576
|
+
for (const item of items) {
|
|
1577
|
+
const key = def.groupBy(item);
|
|
1578
|
+
let arr = map.get(key);
|
|
1579
|
+
if (!arr) {
|
|
1580
|
+
arr = [];
|
|
1581
|
+
map.set(key, arr);
|
|
1582
|
+
}
|
|
1583
|
+
arr.push(item);
|
|
1584
|
+
}
|
|
1585
|
+
return keys.map((key) => map.get(key) ?? []);
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1540
1588
|
function createDataLoader(def) {
|
|
1541
1589
|
return effect.Effect.gen(function* () {
|
|
1542
1590
|
const context = yield* effect.Effect.context();
|
|
1543
1591
|
if (def._tag === "single") {
|
|
1544
|
-
|
|
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;
|
|
1592
|
+
return createSingleDataLoader(def, context);
|
|
1553
1593
|
} else {
|
|
1554
|
-
|
|
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;
|
|
1594
|
+
return createGroupedDataLoader(def, context);
|
|
1569
1595
|
}
|
|
1570
1596
|
});
|
|
1571
1597
|
}
|
|
@@ -1789,7 +1815,7 @@ var GraphQLRouterConfigFromEnv = effect.Config.all({
|
|
|
1789
1815
|
);
|
|
1790
1816
|
|
|
1791
1817
|
// src/server/graphiql.ts
|
|
1792
|
-
var graphiqlHtml = (endpoint) => `<!DOCTYPE html>
|
|
1818
|
+
var graphiqlHtml = (endpoint, subscriptionEndpoint) => `<!DOCTYPE html>
|
|
1793
1819
|
<html lang="en">
|
|
1794
1820
|
<head>
|
|
1795
1821
|
<meta charset="utf-8" />
|
|
@@ -1817,6 +1843,7 @@ var graphiqlHtml = (endpoint) => `<!DOCTYPE html>
|
|
|
1817
1843
|
<script>
|
|
1818
1844
|
const fetcher = GraphiQL.createFetcher({
|
|
1819
1845
|
url: ${JSON.stringify(endpoint)},
|
|
1846
|
+
subscriptionUrl: ${JSON.stringify(subscriptionEndpoint ?? endpoint)},
|
|
1820
1847
|
});
|
|
1821
1848
|
ReactDOM.createRoot(document.getElementById('graphiql')).render(
|
|
1822
1849
|
React.createElement(GraphiQL, { fetcher })
|
|
@@ -2492,19 +2519,32 @@ var defaultErrorHandler = (cause) => (process.env.NODE_ENV !== "production" ? ef
|
|
|
2492
2519
|
).pipe(effect.Effect.orDie)
|
|
2493
2520
|
)
|
|
2494
2521
|
);
|
|
2495
|
-
var
|
|
2522
|
+
var GraphQLRequestBodySchema = effect.Schema.Struct({
|
|
2523
|
+
query: effect.Schema.String,
|
|
2524
|
+
variables: effect.Schema.optionalWith(effect.Schema.Record({ key: effect.Schema.String, value: effect.Schema.Unknown }), {
|
|
2525
|
+
as: "Option"
|
|
2526
|
+
}),
|
|
2527
|
+
operationName: effect.Schema.optionalWith(effect.Schema.String, { as: "Option" })
|
|
2528
|
+
});
|
|
2529
|
+
var decodeRequestBody = platform.HttpIncomingMessage.schemaBodyJson(GraphQLRequestBodySchema);
|
|
2530
|
+
var parseGraphQLQuery = (query2, extensionsService) => {
|
|
2496
2531
|
try {
|
|
2497
2532
|
const document = graphql.parse(query2);
|
|
2498
|
-
return { ok: true, document };
|
|
2533
|
+
return effect.Effect.succeed({ ok: true, document });
|
|
2499
2534
|
} catch (parseError) {
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2535
|
+
return extensionsService.get().pipe(
|
|
2536
|
+
effect.Effect.flatMap(
|
|
2537
|
+
(extensionData) => platform.HttpServerResponse.json({
|
|
2538
|
+
errors: [{ message: String(parseError) }],
|
|
2539
|
+
extensions: Object.keys(extensionData).length > 0 ? extensionData : void 0
|
|
2540
|
+
}).pipe(
|
|
2541
|
+
effect.Effect.orDie,
|
|
2542
|
+
effect.Effect.map((response) => ({ ok: false, response }))
|
|
2543
|
+
)
|
|
2544
|
+
)
|
|
2545
|
+
);
|
|
2506
2546
|
}
|
|
2507
|
-
}
|
|
2547
|
+
};
|
|
2508
2548
|
var runComplexityValidation = (body, schema, fieldComplexities, complexityConfig) => {
|
|
2509
2549
|
if (!complexityConfig) {
|
|
2510
2550
|
return effect.Effect.void;
|
|
@@ -2524,8 +2564,9 @@ var runComplexityValidation = (body, schema, fieldComplexities, complexityConfig
|
|
|
2524
2564
|
)
|
|
2525
2565
|
);
|
|
2526
2566
|
};
|
|
2527
|
-
var
|
|
2528
|
-
|
|
2567
|
+
var isPromiseLike = (value) => value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
|
|
2568
|
+
var executeGraphQLQuery = (schema, document, variables, operationName, runtime) => {
|
|
2569
|
+
const tryExecute = effect.Effect.try({
|
|
2529
2570
|
try: () => graphql.execute({
|
|
2530
2571
|
schema,
|
|
2531
2572
|
document,
|
|
@@ -2535,33 +2576,34 @@ var executeGraphQLQuery = (schema, document, variables, operationName, runtime)
|
|
|
2535
2576
|
}),
|
|
2536
2577
|
catch: (error) => new Error(String(error))
|
|
2537
2578
|
});
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
()
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
})
|
|
2545
|
-
|
|
2579
|
+
return tryExecute.pipe(
|
|
2580
|
+
effect.Effect.flatMap((executeResult) => {
|
|
2581
|
+
if (isPromiseLike(executeResult)) {
|
|
2582
|
+
return effect.Effect.promise(() => executeResult);
|
|
2583
|
+
}
|
|
2584
|
+
return effect.Effect.succeed(executeResult);
|
|
2585
|
+
})
|
|
2586
|
+
);
|
|
2587
|
+
};
|
|
2588
|
+
var computeCacheControlHeader = (document, operationName, schema, cacheHints, cacheControlConfig) => {
|
|
2546
2589
|
if (cacheControlConfig?.enabled === false || cacheControlConfig?.calculateHttpHeaders === false) {
|
|
2547
|
-
return void 0;
|
|
2590
|
+
return effect.Effect.succeed(void 0);
|
|
2548
2591
|
}
|
|
2549
2592
|
const operations = document.definitions.filter(
|
|
2550
2593
|
(d) => d.kind === graphql.Kind.OPERATION_DEFINITION
|
|
2551
2594
|
);
|
|
2552
2595
|
const operation = operationName ? operations.find((o) => o.name?.value === operationName) : operations[0];
|
|
2553
2596
|
if (!operation || operation.operation === "mutation") {
|
|
2554
|
-
return void 0;
|
|
2597
|
+
return effect.Effect.succeed(void 0);
|
|
2555
2598
|
}
|
|
2556
|
-
|
|
2599
|
+
return computeCachePolicy({
|
|
2557
2600
|
document,
|
|
2558
2601
|
operation,
|
|
2559
2602
|
schema,
|
|
2560
2603
|
cacheHints,
|
|
2561
2604
|
config: cacheControlConfig ?? {}
|
|
2562
|
-
});
|
|
2563
|
-
|
|
2564
|
-
});
|
|
2605
|
+
}).pipe(effect.Effect.map(toCacheControlHeader));
|
|
2606
|
+
};
|
|
2565
2607
|
var buildGraphQLResponse = (result, extensionData, cacheControlHeader) => {
|
|
2566
2608
|
const finalResult = Object.keys(extensionData).length > 0 ? {
|
|
2567
2609
|
...result,
|
|
@@ -2599,7 +2641,12 @@ var makeGraphQLRouter = (schema, layer, options = {}) => {
|
|
|
2599
2641
|
const extensionsService = yield* makeExtensionsService();
|
|
2600
2642
|
const runtime = yield* effect.Effect.runtime();
|
|
2601
2643
|
const request = yield* platform.HttpServerRequest.HttpServerRequest;
|
|
2602
|
-
const
|
|
2644
|
+
const parsedBody = yield* decodeRequestBody(request);
|
|
2645
|
+
const body = {
|
|
2646
|
+
query: parsedBody.query,
|
|
2647
|
+
variables: parsedBody.variables._tag === "Some" ? parsedBody.variables.value : void 0,
|
|
2648
|
+
operationName: parsedBody.operationName._tag === "Some" ? parsedBody.operationName.value : void 0
|
|
2649
|
+
};
|
|
2603
2650
|
const parseResult = yield* parseGraphQLQuery(body.query, extensionsService);
|
|
2604
2651
|
if (!parseResult.ok) {
|
|
2605
2652
|
return parseResult.response;
|
|
@@ -2608,7 +2655,7 @@ var makeGraphQLRouter = (schema, layer, options = {}) => {
|
|
|
2608
2655
|
yield* runParseHooks(extensions, body.query, document).pipe(
|
|
2609
2656
|
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
2610
2657
|
);
|
|
2611
|
-
const validationRules = resolvedConfig.introspection ? void 0 :
|
|
2658
|
+
const validationRules = resolvedConfig.introspection ? void 0 : graphql.specifiedRules.concat(graphql.NoSchemaIntrospectionCustomRule);
|
|
2612
2659
|
const validationErrors = graphql.validate(schema, document, validationRules);
|
|
2613
2660
|
yield* runValidateHooks(extensions, document, validationErrors).pipe(
|
|
2614
2661
|
effect.Effect.provideService(ExtensionsService, extensionsService)
|
|
@@ -2669,9 +2716,12 @@ var makeGraphQLRouter = (schema, layer, options = {}) => {
|
|
|
2669
2716
|
platform.HttpRouter.post(resolvedConfig.path, graphqlHandler)
|
|
2670
2717
|
);
|
|
2671
2718
|
if (resolvedConfig.graphiql) {
|
|
2672
|
-
const { path, endpoint } = resolvedConfig.graphiql;
|
|
2719
|
+
const { path, endpoint, subscriptionEndpoint } = resolvedConfig.graphiql;
|
|
2673
2720
|
router = router.pipe(
|
|
2674
|
-
platform.HttpRouter.get(
|
|
2721
|
+
platform.HttpRouter.get(
|
|
2722
|
+
path,
|
|
2723
|
+
platform.HttpServerResponse.html(graphiqlHtml(endpoint, subscriptionEndpoint))
|
|
2724
|
+
)
|
|
2675
2725
|
);
|
|
2676
2726
|
}
|
|
2677
2727
|
return router;
|