@lewebsimple/nuxt-graphql 0.7.9 → 0.7.11
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 +8 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +19 -6
- package/dist/runtime/server/lib/remote-executor.d.ts +15 -4
- package/dist/runtime/server/lib/remote-executor.js +4 -2
- package/dist/runtime/server/lib/yoga.js +2 -2
- package/dist/runtime/server/utils/execute-schema.js +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -381,15 +381,20 @@ export default defineRemoteExecutorHooks({
|
|
|
381
381
|
});
|
|
382
382
|
},
|
|
383
383
|
|
|
384
|
-
onResult(result, context) {
|
|
384
|
+
onResult(result, context, meta) {
|
|
385
385
|
// You can also access context in onResult
|
|
386
386
|
console.log("User from context:", context?.user);
|
|
387
387
|
console.log("Result:", result.data);
|
|
388
|
+
// Upstream HTTP response metadata (headers + status)
|
|
389
|
+
const session = meta.headers.get("woocommerce-session");
|
|
390
|
+
if (session) context?.setSession?.(session);
|
|
388
391
|
},
|
|
389
392
|
|
|
390
|
-
onError(error, context) {
|
|
393
|
+
onError(error, context, meta) {
|
|
391
394
|
// And in onError for logging/monitoring
|
|
392
|
-
|
|
395
|
+
// `meta` is undefined when the failure happened before the HTTP response
|
|
396
|
+
// (e.g. fetch/network error); defined for non-2xx or JSON parse errors.
|
|
397
|
+
console.error("Remote execution failed for user:", context?.user?.id, meta?.status);
|
|
393
398
|
},
|
|
394
399
|
});
|
|
395
400
|
```
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import zodPreset from '@lewebsimple/graphql-codegen-zod';
|
|
|
16
16
|
import { createRequire } from 'node:module';
|
|
17
17
|
import { resolveCacheConfig } from '../dist/runtime/app/lib/cache-config.js';
|
|
18
18
|
|
|
19
|
-
const version = "0.7.
|
|
19
|
+
const version = "0.7.11";
|
|
20
20
|
|
|
21
21
|
const buildCache = /* @__PURE__ */ new Map();
|
|
22
22
|
function getCachedLoader(baseKey, loader) {
|
|
@@ -340,7 +340,7 @@ function getRemoteSchemaTemplate({
|
|
|
340
340
|
const hookRefs = hooks.map((_, index) => `hook${index}`);
|
|
341
341
|
return `
|
|
342
342
|
import { getRemoteExecutor } from "#graphql/runtime/remote-executor";
|
|
343
|
-
import { buildSchema } from "graphql";
|
|
343
|
+
import { buildSchema, type GraphQLSchema } from "graphql";
|
|
344
344
|
${hookImports.join("\n")}
|
|
345
345
|
|
|
346
346
|
const executor = getRemoteExecutor({
|
|
@@ -349,8 +349,18 @@ const executor = getRemoteExecutor({
|
|
|
349
349
|
hooks: [${hookRefs.join(", ")}],
|
|
350
350
|
});
|
|
351
351
|
|
|
352
|
+
// SDL is held as a string literal and only parsed on first access. This keeps
|
|
353
|
+
// \`buildSchema\` out of the module-evaluation phase, which matters on
|
|
354
|
+
// Cloudflare Workers where the startup CPU budget is ~200ms (free) / 400ms
|
|
355
|
+
// (paid) \u2014 easy to exceed when the remote schema is large (WPGraphQL +
|
|
356
|
+
// WooCommerce + ACF, etc.).
|
|
357
|
+
const SDL = ${JSON.stringify(sdl)};
|
|
358
|
+
let _schema: GraphQLSchema | undefined;
|
|
359
|
+
|
|
352
360
|
export const schema = {
|
|
353
|
-
schema:
|
|
361
|
+
get schema(): GraphQLSchema {
|
|
362
|
+
return (_schema ??= buildSchema(SDL));
|
|
363
|
+
},
|
|
354
364
|
executor,
|
|
355
365
|
};
|
|
356
366
|
`.trim();
|
|
@@ -378,24 +388,27 @@ function getSchemaTemplate({ localPaths, remotePaths }) {
|
|
|
378
388
|
return [
|
|
379
389
|
...imports,
|
|
380
390
|
"",
|
|
381
|
-
`export const
|
|
391
|
+
`export const getSchema = () => remoteSchema0.schema;`,
|
|
382
392
|
`export const executor = remoteSchema0.executor;`
|
|
383
393
|
].join("\n");
|
|
384
394
|
}
|
|
385
395
|
let schemaRef;
|
|
386
396
|
if (schemaRefs.length === 0) {
|
|
387
|
-
imports.unshift(`import {
|
|
397
|
+
imports.unshift(`import { buildSchema, type GraphQLSchema } from "graphql";`);
|
|
388
398
|
schemaRef = `buildSchema("type Query { _empty: String }")`;
|
|
389
399
|
} else if (remoteSchemaRefs.length === 0) {
|
|
400
|
+
imports.unshift(`import type { GraphQLSchema } from "graphql";`);
|
|
390
401
|
schemaRef = schemaRefs[0];
|
|
391
402
|
} else {
|
|
392
403
|
imports.unshift(`import { stitchSchemas } from "@graphql-tools/stitch";`);
|
|
404
|
+
imports.unshift(`import type { GraphQLSchema } from "graphql";`);
|
|
393
405
|
schemaRef = `stitchSchemas({ subschemas: [${schemaRefs.join(", ")}], mergeTypes: false })`;
|
|
394
406
|
}
|
|
395
407
|
return [
|
|
396
408
|
...imports,
|
|
397
409
|
"",
|
|
398
|
-
`
|
|
410
|
+
`let _schema: GraphQLSchema | undefined;`,
|
|
411
|
+
`export const getSchema = () => (_schema ??= ${schemaRef});`,
|
|
399
412
|
`export const executor = undefined;`
|
|
400
413
|
].join("\n");
|
|
401
414
|
}
|
|
@@ -15,14 +15,25 @@ export type GraphQLRemoteExecutorRequest<TContext extends Record<string, unknown
|
|
|
15
15
|
/** Execution context. */
|
|
16
16
|
context?: TContext;
|
|
17
17
|
};
|
|
18
|
+
/** Metadata from the upstream HTTP response. */
|
|
19
|
+
export type GraphQLRemoteExecutorResponseMeta = {
|
|
20
|
+
/** Response headers from the upstream endpoint. */
|
|
21
|
+
headers: Headers;
|
|
22
|
+
/** HTTP status code from the upstream endpoint. */
|
|
23
|
+
status: number;
|
|
24
|
+
};
|
|
18
25
|
/** Remote executor hook handlers. */
|
|
19
26
|
export type GraphQLRemoteExecutorHook<TContext extends Record<string, unknown> = GraphQLContext> = {
|
|
20
27
|
/** Called before sending remote request. */
|
|
21
28
|
onRequest?: (request: GraphQLRemoteExecutorRequest<TContext>, context: TContext | undefined) => void | Promise<void>;
|
|
22
|
-
/** Called after receiving a result. */
|
|
23
|
-
onResult?: (result: unknown, context: TContext | undefined) => void | Promise<void>;
|
|
24
|
-
/**
|
|
25
|
-
|
|
29
|
+
/** Called after receiving a result, with the upstream response metadata. */
|
|
30
|
+
onResult?: (result: unknown, context: TContext | undefined, meta: GraphQLRemoteExecutorResponseMeta) => void | Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Called when execution throws. `meta` is provided when the failure happened
|
|
33
|
+
* after the HTTP response was received (non-2xx, JSON parse error, hook
|
|
34
|
+
* error); it is `undefined` for fetch/network failures.
|
|
35
|
+
*/
|
|
36
|
+
onError?: (error: unknown, context: TContext | undefined, meta?: GraphQLRemoteExecutorResponseMeta) => void | Promise<void>;
|
|
26
37
|
};
|
|
27
38
|
/** Remote executor factory input. */
|
|
28
39
|
type RemoteExecutorInput<TContext extends Record<string, unknown> = GraphQLContext> = {
|
|
@@ -6,6 +6,7 @@ export function getRemoteExecutor({
|
|
|
6
6
|
}) {
|
|
7
7
|
return async function execute(request) {
|
|
8
8
|
const context = request.context;
|
|
9
|
+
let meta;
|
|
9
10
|
try {
|
|
10
11
|
for (const hook of hooks) {
|
|
11
12
|
await hook.onRequest?.(request, context);
|
|
@@ -23,17 +24,18 @@ export function getRemoteExecutor({
|
|
|
23
24
|
operationName: request.operationName
|
|
24
25
|
})
|
|
25
26
|
});
|
|
27
|
+
meta = { headers: response.headers, status: response.status };
|
|
26
28
|
if (!response.ok) {
|
|
27
29
|
throw new Error(`GraphQL HTTP ${response.status}`);
|
|
28
30
|
}
|
|
29
31
|
const result = await response.json();
|
|
30
32
|
for (const hook of hooks) {
|
|
31
|
-
await hook.onResult?.(result, context);
|
|
33
|
+
await hook.onResult?.(result, context, meta);
|
|
32
34
|
}
|
|
33
35
|
return result;
|
|
34
36
|
} catch (error) {
|
|
35
37
|
for (const hook of hooks) {
|
|
36
|
-
await hook.onError?.(error, context);
|
|
38
|
+
await hook.onError?.(error, context, meta);
|
|
37
39
|
}
|
|
38
40
|
throw error;
|
|
39
41
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { executor,
|
|
1
|
+
import { executor, getSchema } from "#graphql/schema";
|
|
2
2
|
import { createYoga } from "graphql-yoga";
|
|
3
3
|
let yoga = null;
|
|
4
4
|
function passthroughPlugin() {
|
|
@@ -21,7 +21,7 @@ export function getYogaInstance() {
|
|
|
21
21
|
graphqlEndpoint: "/api/graphql",
|
|
22
22
|
graphiql: import.meta.dev,
|
|
23
23
|
fetchAPI: globalThis,
|
|
24
|
-
schema,
|
|
24
|
+
schema: getSchema(),
|
|
25
25
|
plugins: executor ? [passthroughPlugin()] : []
|
|
26
26
|
});
|
|
27
27
|
if (!yoga) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext } from "#graphql/context";
|
|
2
|
-
import { executor,
|
|
2
|
+
import { executor, getSchema } from "#graphql/schema";
|
|
3
3
|
import { execute } from "graphql";
|
|
4
4
|
import { normalizeError } from "../../shared/utils/error.js";
|
|
5
5
|
import {
|
|
@@ -17,7 +17,13 @@ export async function executeSchemaOperation(event, { operationName, variables }
|
|
|
17
17
|
variables: variableValues,
|
|
18
18
|
operationName,
|
|
19
19
|
context: contextValue
|
|
20
|
-
}) : await execute({
|
|
20
|
+
}) : await execute({
|
|
21
|
+
schema: getSchema(),
|
|
22
|
+
document,
|
|
23
|
+
variableValues,
|
|
24
|
+
operationName,
|
|
25
|
+
contextValue
|
|
26
|
+
});
|
|
21
27
|
if (result.errors?.length) {
|
|
22
28
|
return { data: null, error: normalizeError(result.errors) };
|
|
23
29
|
}
|