@nifrajs/graphql 4.0.0 → 5.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 +13 -2
- package/dist/http.d.ts +14 -4
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +32 -11
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -9
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +19 -0
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +110 -1
- package/dist/limits.js.map +1 -1
- package/dist/pubsub.d.ts +12 -2
- package/dist/pubsub.d.ts.map +1 -1
- package/dist/pubsub.js +41 -6
- package/dist/pubsub.js.map +1 -1
- package/dist/ws.d.ts +15 -1
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +102 -21
- package/dist/ws.js.map +1 -1
- package/package.json +2 -2
- package/src/http.ts +71 -21
- package/src/index.ts +50 -10
- package/src/limits.ts +124 -1
- package/src/pubsub.ts +55 -6
- package/src/ws.ts +148 -35
package/dist/pubsub.js
CHANGED
|
@@ -9,8 +9,23 @@
|
|
|
9
9
|
* `{ publish, subscribe }` shape over your bus and pass it in. Keeping only the in-memory impl here is
|
|
10
10
|
* the guardrail - a durable payload-carrying sink does not belong in a public package.
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
export class GraphqlPubSubOverflowError extends Error {
|
|
13
|
+
code = "graphql_pubsub_overflow";
|
|
14
|
+
constructor() {
|
|
15
|
+
super("GraphQL subscription event queue is full");
|
|
16
|
+
this.name = "GraphqlPubSubOverflowError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Create an in-memory {@link GraphqlPubSub} with finite subscriber queues. */
|
|
20
|
+
export function createPubSub(options = {}) {
|
|
21
|
+
const maxQueuedEvents = options.maxQueuedEvents ?? 1024;
|
|
22
|
+
const overflow = options.overflow ?? "error";
|
|
23
|
+
if (!Number.isSafeInteger(maxQueuedEvents) || maxQueuedEvents < 1) {
|
|
24
|
+
throw new RangeError("createPubSub maxQueuedEvents must be a positive safe integer");
|
|
25
|
+
}
|
|
26
|
+
if (overflow !== "error" && overflow !== "drop-oldest" && overflow !== "drop-newest") {
|
|
27
|
+
throw new TypeError("createPubSub overflow must be error, drop-oldest or drop-newest");
|
|
28
|
+
}
|
|
14
29
|
const topics = new Map();
|
|
15
30
|
const publish = (topic, payload) => {
|
|
16
31
|
const sinks = topics.get(topic);
|
|
@@ -26,7 +41,7 @@ export function createPubSub() {
|
|
|
26
41
|
topics.set(topic, sinks);
|
|
27
42
|
}
|
|
28
43
|
const set = sinks;
|
|
29
|
-
const sink = createSink(() => {
|
|
44
|
+
const sink = createSink(maxQueuedEvents, overflow, () => {
|
|
30
45
|
set.delete(sink);
|
|
31
46
|
if (set.size === 0)
|
|
32
47
|
topics.delete(topic);
|
|
@@ -36,10 +51,11 @@ export function createPubSub() {
|
|
|
36
51
|
};
|
|
37
52
|
return { publish, subscribe };
|
|
38
53
|
}
|
|
39
|
-
function createSink(onClose) {
|
|
54
|
+
function createSink(maxQueuedEvents, overflow, onClose) {
|
|
40
55
|
const queue = [];
|
|
41
56
|
const pulls = [];
|
|
42
57
|
let done = false;
|
|
58
|
+
let failure;
|
|
43
59
|
const push = (payload) => {
|
|
44
60
|
if (done)
|
|
45
61
|
return;
|
|
@@ -48,11 +64,22 @@ function createSink(onClose) {
|
|
|
48
64
|
pull({ value: payload, done: false });
|
|
49
65
|
return;
|
|
50
66
|
}
|
|
67
|
+
if (queue.length >= maxQueuedEvents) {
|
|
68
|
+
if (overflow === "drop-newest")
|
|
69
|
+
return;
|
|
70
|
+
if (overflow === "error") {
|
|
71
|
+
failure = new GraphqlPubSubOverflowError();
|
|
72
|
+
finish();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
queue.shift();
|
|
76
|
+
}
|
|
51
77
|
queue.push(payload);
|
|
52
78
|
};
|
|
53
79
|
const finish = () => {
|
|
54
80
|
if (!done) {
|
|
55
81
|
done = true;
|
|
82
|
+
queue.length = 0;
|
|
56
83
|
onClose();
|
|
57
84
|
for (const pull of pulls.splice(0))
|
|
58
85
|
pull({ value: undefined, done: true });
|
|
@@ -61,16 +88,24 @@ function createSink(onClose) {
|
|
|
61
88
|
};
|
|
62
89
|
const iterator = {
|
|
63
90
|
next() {
|
|
64
|
-
if (
|
|
65
|
-
|
|
91
|
+
if (failure !== undefined) {
|
|
92
|
+
const error = failure;
|
|
93
|
+
failure = undefined;
|
|
94
|
+
return Promise.reject(error);
|
|
95
|
+
}
|
|
66
96
|
if (done)
|
|
67
97
|
return Promise.resolve({ value: undefined, done: true });
|
|
98
|
+
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: a nonempty queue owns one Event; undefined is itself a valid Event payload.
|
|
99
|
+
if (queue.length > 0)
|
|
100
|
+
return Promise.resolve({ value: queue.shift(), done: false });
|
|
68
101
|
return new Promise((resolve) => pulls.push(resolve));
|
|
69
102
|
},
|
|
70
103
|
return() {
|
|
104
|
+
failure = undefined;
|
|
71
105
|
return Promise.resolve(finish());
|
|
72
106
|
},
|
|
73
107
|
throw(err) {
|
|
108
|
+
failure = undefined;
|
|
74
109
|
finish();
|
|
75
110
|
return Promise.reject(err);
|
|
76
111
|
},
|
package/dist/pubsub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../src/pubsub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../src/pubsub.ts"],"names":[],"mappings":"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"}
|
package/dist/ws.d.ts
CHANGED
|
@@ -24,12 +24,21 @@ interface GraphqlWsConnection {
|
|
|
24
24
|
/** Tear the graphql-ws connection down (graphql-ws's `opened()` return value). */
|
|
25
25
|
closed?: (code: number, reason: string) => void | Promise<void>;
|
|
26
26
|
readonly subscriptions: Set<string>;
|
|
27
|
+
/** One abort controller per running operation id, aborted by the client's complete or a close. */
|
|
28
|
+
operations?: Map<string, AbortController>;
|
|
29
|
+
/** Set once graphql-ws sends `connection_ack`, i.e. `connection_init` was admitted. */
|
|
30
|
+
acknowledged?: boolean;
|
|
27
31
|
}
|
|
28
32
|
export interface GraphqlWsOptions<Context extends Record<string, unknown> = Record<string, unknown>> {
|
|
29
33
|
/** The executable schema. */
|
|
30
34
|
readonly schema: GraphQLSchema;
|
|
31
35
|
/** Build the resolver `contextValue` from the upgrade request. Shared with the HTTP transport. */
|
|
32
36
|
readonly context?: GraphqlContextBuilder<Context>;
|
|
37
|
+
/**
|
|
38
|
+
* Admit a socket from its upgrade request, before {@link onConnect}; return `false` (or throw) to
|
|
39
|
+
* reject the connection. `mountGraphql({ subscriptions: true })` passes its HTTP `authorize` here.
|
|
40
|
+
*/
|
|
41
|
+
readonly authorize?: (request: Request) => boolean | Promise<boolean>;
|
|
33
42
|
/**
|
|
34
43
|
* Called once per connection with the client's `connection_init` payload; return `false` (or throw)
|
|
35
44
|
* to reject the connection. The seam for authenticating a socket from an init token.
|
|
@@ -44,9 +53,14 @@ export interface GraphqlWsOptions<Context extends Record<string, unknown> = Reco
|
|
|
44
53
|
readonly maxAliases?: number;
|
|
45
54
|
readonly maxComplexity?: number;
|
|
46
55
|
readonly maxOperations?: number;
|
|
56
|
+
readonly maxFieldOverlaps?: number;
|
|
47
57
|
/** Maximum concurrent subscription operation ids per connection. Default 20. */
|
|
48
58
|
readonly maxSubscriptions?: number;
|
|
49
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Maximum time for initial execute/subscribe setup. Default 10 seconds. Each operation's abort
|
|
61
|
+
* signal, which a resolver reads through `info.getAbortSignal()`, is aborted at this deadline, when
|
|
62
|
+
* the client completes the operation, and when the socket closes.
|
|
63
|
+
*/
|
|
50
64
|
readonly executionTimeoutMs?: number;
|
|
51
65
|
}
|
|
52
66
|
/**
|
package/dist/ws.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../src/ws.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAoC,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAC1F,OAAO,
|
|
1
|
+
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../src/ws.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAoC,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAC1F,OAAO,EAML,KAAK,aAAa,EAKnB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,KAAK,qBAAqB,EAI1B,KAAK,aAAa,EACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAgB,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAUvE,2EAA2E;AAC3E,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,kFAAkF;IAClF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACnC,kGAAkG;IAClG,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACzC,uFAAuF;IACvF,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAQD,MAAM,WAAW,gBAAgB,CAC/B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjE,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,kGAAkG;IAClG,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAA;IACjD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACrE;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CACnB,OAAO,EAAE,qBAAqB,CAAC,SAAS,CAAC,EACzC,OAAO,EAAE,OAAO,KACb,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/B,sFAAsF;IACtF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;IAC/C,0DAA0D;IAC1D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,gFAAgF;IAChF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CACrC;AA0KD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChG,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,GACjC,gBAAgB,CAAC,mBAAmB,CAAC,CAmKvC"}
|
package/dist/ws.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import { execute, GraphQLError, parse, specifiedRules, subscribe, validate, } from "graphql";
|
|
16
16
|
import { GRAPHQL_TRANSPORT_WS_PROTOCOL, makeServer, } from "graphql-ws";
|
|
17
17
|
import { buildContext } from "./context.js";
|
|
18
|
-
import { documentLimitError, documentMetrics, graphqlLimits, requestLimitError, } from "./limits.js";
|
|
18
|
+
import { documentLimitError, documentMetrics, graphqlLimits, overlapLimitError, requestLimitError, } from "./limits.js";
|
|
19
19
|
/** A frame is a string for JSON control messages; graphql-ws only speaks text frames. */
|
|
20
20
|
function asText(data) {
|
|
21
21
|
return typeof data === "string" ? data : new TextDecoder().decode(data);
|
|
@@ -64,11 +64,13 @@ function subscriptionFrameError(message, schema, limits) {
|
|
|
64
64
|
catch (error) {
|
|
65
65
|
return { id, message: error instanceof GraphQLError ? error.message : "Invalid GraphQL query." };
|
|
66
66
|
}
|
|
67
|
+
const limitError = documentLimitError(documentMetrics(document), limits) ?? overlapLimitError(document, limits);
|
|
68
|
+
if (limitError !== undefined)
|
|
69
|
+
return { id, message: limitError };
|
|
67
70
|
const validationErrors = validate(schema, document, specifiedRules);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return limitError === undefined ? undefined : { id, message: limitError };
|
|
71
|
+
return validationErrors.length > 0
|
|
72
|
+
? { id, message: validationErrors[0]?.message ?? "Invalid GraphQL query." }
|
|
73
|
+
: undefined;
|
|
72
74
|
}
|
|
73
75
|
function maskWsError(error) {
|
|
74
76
|
const record = recordOf(error);
|
|
@@ -85,13 +87,16 @@ function maskWsError(error) {
|
|
|
85
87
|
* so the id stops counting against `maxSubscriptions`: a client is not expected to complete an
|
|
86
88
|
* operation the server already ended.
|
|
87
89
|
*/
|
|
88
|
-
function outboundFrame(message,
|
|
90
|
+
function outboundFrame(message, connection) {
|
|
89
91
|
try {
|
|
90
92
|
const parsed = recordOf(JSON.parse(message));
|
|
91
93
|
if (parsed === undefined)
|
|
92
94
|
return message;
|
|
95
|
+
if (parsed.type === "connection_ack")
|
|
96
|
+
connection.acknowledged = true;
|
|
93
97
|
if ((parsed.type === "complete" || parsed.type === "error") && typeof parsed.id === "string") {
|
|
94
|
-
subscriptions.delete(parsed.id);
|
|
98
|
+
connection.subscriptions.delete(parsed.id);
|
|
99
|
+
connection.operations?.delete(parsed.id);
|
|
95
100
|
}
|
|
96
101
|
if (parsed.type === "next") {
|
|
97
102
|
const payload = recordOf(parsed.payload);
|
|
@@ -111,16 +116,61 @@ function outboundFrame(message, subscriptions) {
|
|
|
111
116
|
}
|
|
112
117
|
return message;
|
|
113
118
|
}
|
|
119
|
+
/** Close a result that arrived after its operation timed out, if it is a stream nobody will read. */
|
|
120
|
+
function disposeLate(result) {
|
|
121
|
+
if (typeof result !== "object" || result === null || !(Symbol.asyncIterator in result))
|
|
122
|
+
return;
|
|
123
|
+
const iterator = recordOf(result);
|
|
124
|
+
if (iterator === undefined || typeof iterator.return !== "function")
|
|
125
|
+
return;
|
|
126
|
+
Promise.resolve(iterator.return.call(result)).catch(() => { });
|
|
127
|
+
}
|
|
128
|
+
const wrappedSubscribeFields = new WeakSet();
|
|
129
|
+
/**
|
|
130
|
+
* graphql drops a subscribe resolver's result that settles after the operation's signal aborted, so
|
|
131
|
+
* a source the resolver opened anyway would stay open. Each root subscription field's resolver is
|
|
132
|
+
* wrapped once to return such a late source; with no signal, or before an abort, it is unchanged.
|
|
133
|
+
*/
|
|
134
|
+
function returnLateSources(schema) {
|
|
135
|
+
const fields = schema.getSubscriptionType()?.getFields() ?? {};
|
|
136
|
+
for (const field of Object.values(fields)) {
|
|
137
|
+
const resolver = field.subscribe;
|
|
138
|
+
if (resolver === undefined || wrappedSubscribeFields.has(field))
|
|
139
|
+
continue;
|
|
140
|
+
wrappedSubscribeFields.add(field);
|
|
141
|
+
field.subscribe = (source, args, context, info) => {
|
|
142
|
+
const result = resolver(source, args, context, info);
|
|
143
|
+
if (!(result instanceof Promise))
|
|
144
|
+
return result;
|
|
145
|
+
return result.then((value) => {
|
|
146
|
+
if (info.getAbortSignal()?.aborted === true)
|
|
147
|
+
disposeLate(value);
|
|
148
|
+
return value;
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
114
153
|
/**
|
|
115
154
|
* A timeout is that operation's error result. graphql-ws does not catch a rejected execute or
|
|
116
|
-
* subscribe, so a rejection would end the whole socket instead of the one operation.
|
|
155
|
+
* subscribe, so a rejection would end the whole socket instead of the one operation. A timeout aborts
|
|
156
|
+
* the operation's `abortSignal`, which resolvers read through `info.getAbortSignal()`, and work that
|
|
157
|
+
* settles after it is not abandoned open: a late subscription stream is returned.
|
|
117
158
|
*/
|
|
118
|
-
async function withWsTimeout(
|
|
119
|
-
|
|
159
|
+
async function withWsTimeout(start, outer, timeoutMs) {
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
const work = start(outer ? AbortSignal.any([outer, controller.signal]) : controller.signal);
|
|
162
|
+
if (!(work instanceof Promise))
|
|
120
163
|
return work;
|
|
121
164
|
let timer;
|
|
165
|
+
let timedOut = false;
|
|
122
166
|
const timeout = new Promise((resolve) => {
|
|
123
|
-
timer = setTimeout(() =>
|
|
167
|
+
timer = setTimeout(() => {
|
|
168
|
+
timedOut = true;
|
|
169
|
+
const error = new GraphQLError("Execution timed out.");
|
|
170
|
+
// Resolved first: the abort can reject the work, and the race must settle on this result.
|
|
171
|
+
resolve({ errors: [error] });
|
|
172
|
+
controller.abort(error);
|
|
173
|
+
}, timeoutMs);
|
|
124
174
|
});
|
|
125
175
|
try {
|
|
126
176
|
return await Promise.race([work, timeout]);
|
|
@@ -128,6 +178,8 @@ async function withWsTimeout(work, timeoutMs) {
|
|
|
128
178
|
finally {
|
|
129
179
|
if (timer !== undefined)
|
|
130
180
|
clearTimeout(timer);
|
|
181
|
+
if (timedOut)
|
|
182
|
+
work.then(disposeLate, () => { });
|
|
131
183
|
}
|
|
132
184
|
}
|
|
133
185
|
/**
|
|
@@ -150,8 +202,13 @@ export function graphqlWebSocket(options) {
|
|
|
150
202
|
assertWsNumber(maxSubscriptions, "maxSubscriptions", 1);
|
|
151
203
|
const executionTimeoutMs = options.executionTimeoutMs ?? 10_000;
|
|
152
204
|
assertWsNumber(executionTimeoutMs, "executionTimeoutMs", 0);
|
|
153
|
-
const executeWithTimeout = (args) =>
|
|
154
|
-
|
|
205
|
+
const executeWithTimeout = (args) => executionTimeoutMs === 0
|
|
206
|
+
? execute(args)
|
|
207
|
+
: withWsTimeout((abortSignal) => execute({ ...args, abortSignal }), args.abortSignal, executionTimeoutMs);
|
|
208
|
+
const subscribeWithTimeout = (args) => executionTimeoutMs === 0
|
|
209
|
+
? subscribe(args)
|
|
210
|
+
: withWsTimeout((abortSignal) => subscribe({ ...args, abortSignal }), args.abortSignal, executionTimeoutMs);
|
|
211
|
+
returnLateSources(options.schema);
|
|
155
212
|
const gqlServer = makeServer({
|
|
156
213
|
// Keep the raw escape hatch for auxiliary graphql-ws hooks, but make the package's safety
|
|
157
214
|
// controls authoritative: callers cannot accidentally replace the bounded execute/subscribe
|
|
@@ -160,19 +217,31 @@ export function graphqlWebSocket(options) {
|
|
|
160
217
|
schema: options.schema,
|
|
161
218
|
execute: executeWithTimeout,
|
|
162
219
|
subscribe: subscribeWithTimeout,
|
|
163
|
-
onConnect: options.onConnect
|
|
220
|
+
onConnect: options.onConnect || options.authorize
|
|
164
221
|
? async (ctx) => {
|
|
165
222
|
try {
|
|
166
|
-
|
|
223
|
+
if (options.authorize !== undefined && !(await options.authorize(ctx.extra.request)))
|
|
224
|
+
return false;
|
|
225
|
+
return ((await options.onConnect?.(ctx.connectionParams, ctx.extra.request)) ?? true);
|
|
167
226
|
}
|
|
168
227
|
catch {
|
|
169
228
|
return false;
|
|
170
229
|
}
|
|
171
230
|
}
|
|
172
231
|
: undefined,
|
|
173
|
-
context
|
|
174
|
-
|
|
175
|
-
|
|
232
|
+
// graphql-ws builds the context once per operation, just before executing it, so the operation's
|
|
233
|
+
// abort signal is attached to its execution arguments here.
|
|
234
|
+
context: async (ctx, id, _payload, args) => {
|
|
235
|
+
const controller = new AbortController();
|
|
236
|
+
ctx.extra.operations.set(id, controller);
|
|
237
|
+
args.abortSignal =
|
|
238
|
+
args.abortSignal === undefined || args.abortSignal === null
|
|
239
|
+
? controller.signal
|
|
240
|
+
: AbortSignal.any([args.abortSignal, controller.signal]);
|
|
241
|
+
return options.context === undefined
|
|
242
|
+
? undefined
|
|
243
|
+
: await buildContext(options.context, { request: ctx.extra.request });
|
|
244
|
+
},
|
|
176
245
|
});
|
|
177
246
|
return {
|
|
178
247
|
upgrade(c) {
|
|
@@ -181,10 +250,12 @@ export function graphqlWebSocket(options) {
|
|
|
181
250
|
open(ws) {
|
|
182
251
|
const protocol = ws.raw?.protocol ?? GRAPHQL_TRANSPORT_WS_PROTOCOL;
|
|
183
252
|
let onFrame;
|
|
253
|
+
const operations = new Map();
|
|
254
|
+
ws.data.operations = operations;
|
|
184
255
|
const closed = gqlServer.opened({
|
|
185
256
|
protocol,
|
|
186
257
|
send: async (data) => {
|
|
187
|
-
ws.send(outboundFrame(data, ws.data
|
|
258
|
+
ws.send(outboundFrame(data, ws.data));
|
|
188
259
|
},
|
|
189
260
|
close: (code, reason) => {
|
|
190
261
|
ws.close(code, reason);
|
|
@@ -192,7 +263,7 @@ export function graphqlWebSocket(options) {
|
|
|
192
263
|
onMessage: (cb) => {
|
|
193
264
|
onFrame = cb;
|
|
194
265
|
},
|
|
195
|
-
}, { request: ws.data.request });
|
|
266
|
+
}, { request: ws.data.request, operations });
|
|
196
267
|
ws.data.closed = closed;
|
|
197
268
|
ws.data.dispatch = async (message) => {
|
|
198
269
|
try {
|
|
@@ -211,7 +282,12 @@ export function graphqlWebSocket(options) {
|
|
|
211
282
|
// this socket - including the client's `Complete` that stops the subscription. graphql-ws drives
|
|
212
283
|
// its own sends and error frames from inside that loop; we only feed it inbound frames.
|
|
213
284
|
const message = asText(data);
|
|
214
|
-
|
|
285
|
+
// Until connection_init is admitted, graphql-ws answers a subscribe frame by closing with 4401
|
|
286
|
+
// without reading the query. Parsing or validating it here would hand an unauthenticated socket
|
|
287
|
+
// schema suggestions and synchronous validation work.
|
|
288
|
+
const rejected = ws.data.acknowledged === true
|
|
289
|
+
? subscriptionFrameError(message, options.schema, limits)
|
|
290
|
+
: undefined;
|
|
215
291
|
if (rejected !== undefined) {
|
|
216
292
|
ws.send(JSON.stringify({
|
|
217
293
|
id: rejected.id,
|
|
@@ -235,6 +311,8 @@ export function graphqlWebSocket(options) {
|
|
|
235
311
|
}
|
|
236
312
|
else if (frame?.type === "complete" && typeof frame.id === "string") {
|
|
237
313
|
ws.data.subscriptions.delete(frame.id);
|
|
314
|
+
ws.data.operations?.get(frame.id)?.abort(new GraphQLError("Operation completed."));
|
|
315
|
+
ws.data.operations?.delete(frame.id);
|
|
238
316
|
}
|
|
239
317
|
}
|
|
240
318
|
catch {
|
|
@@ -244,6 +322,9 @@ export function graphqlWebSocket(options) {
|
|
|
244
322
|
},
|
|
245
323
|
close(ws, code, reason) {
|
|
246
324
|
ws.data.subscriptions.clear();
|
|
325
|
+
for (const controller of ws.data.operations?.values() ?? [])
|
|
326
|
+
controller.abort(new GraphQLError("Socket closed."));
|
|
327
|
+
ws.data.operations?.clear();
|
|
247
328
|
// The socket is gone: a failing iterator return() or onClose hook has no one left to answer.
|
|
248
329
|
void Promise.resolve(ws.data.closed?.(code, reason)).catch(() => { });
|
|
249
330
|
},
|
package/dist/ws.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../src/ws.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../src/ws.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nifrajs/graphql",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Mount a GraphQL endpoint on a nifra app - a spec-compliant GraphQL-over-HTTP handler you mount at POST /graphql, graphql-ws subscriptions over nifra's native WebSocket lane, and typed nifra context piped straight into your resolvers. Uses graphql's own execute/subscribe; no server framework re-bundled.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"build": "tsc -p tsconfig.build.json && bun run ../../scripts/fix-dts.ts dist"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@nifrajs/core": "^
|
|
49
|
+
"@nifrajs/core": "^5.0.0",
|
|
50
50
|
"graphql": "^17.0.0",
|
|
51
51
|
"graphql-ws": "^6.0.0"
|
|
52
52
|
},
|
package/src/http.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* (`@nifrajs/core/edge-kit`'s {@link readBodyFramed}).
|
|
7
7
|
*
|
|
8
8
|
* Spec: https://graphql.github.io/graphql-over-http/draft/. POST carries `{query, operationName?,
|
|
9
|
-
* variables?, extensions?}` as `application/json
|
|
9
|
+
* variables?, extensions?}` as `application/json` (any other media type answers 415, so a cross-site
|
|
10
|
+
* form cannot post a mutation); GET carries them as query-string params and may run
|
|
10
11
|
* **queries only** (never a mutation) so it stays a safe, cacheable idempotent method. Responses use the
|
|
11
12
|
* `application/graphql-response+json` media type with spec status codes by default; set
|
|
12
13
|
* `legacyJsonResponse` for the old always-200 `application/json` shape older clients expect.
|
|
@@ -49,6 +50,7 @@ import {
|
|
|
49
50
|
documentMetrics,
|
|
50
51
|
type GraphqlLimits,
|
|
51
52
|
graphqlLimits,
|
|
53
|
+
overlapLimitError,
|
|
52
54
|
requestLimitError,
|
|
53
55
|
safeFormattedError,
|
|
54
56
|
} from "./limits.ts"
|
|
@@ -84,7 +86,16 @@ export interface GraphqlHttpOptions<Context = unknown, Env = unknown> {
|
|
|
84
86
|
readonly maxComplexity?: number
|
|
85
87
|
/** Maximum operation definitions in one document. Default 10. */
|
|
86
88
|
readonly maxOperations?: number
|
|
87
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Maximum pairs of fields sharing a response name in one selection set, counted through fragments.
|
|
91
|
+
* Validation compares every such pair, so this bounds its cost. Default 2,000.
|
|
92
|
+
*/
|
|
93
|
+
readonly maxFieldOverlaps?: number
|
|
94
|
+
/**
|
|
95
|
+
* Maximum asynchronous resolver execution time. Default 10 seconds. The execution's abort signal,
|
|
96
|
+
* which a resolver reads through `info.getAbortSignal()`, is aborted at this deadline and when the
|
|
97
|
+
* request itself is aborted.
|
|
98
|
+
*/
|
|
88
99
|
readonly executionTimeoutMs?: number
|
|
89
100
|
/** Prototype-pollution policy for the parsed JSON body. Default `"reject"`. */
|
|
90
101
|
readonly protoPoisoning?: ProtoPoisoning
|
|
@@ -96,8 +107,8 @@ export interface GraphqlHttpOptions<Context = unknown, Env = unknown> {
|
|
|
96
107
|
*/
|
|
97
108
|
readonly allowedOrigins?: readonly string[]
|
|
98
109
|
/**
|
|
99
|
-
* Per-request authorization, run after the
|
|
100
|
-
* `401` with a GraphQL error envelope
|
|
110
|
+
* Per-request authorization, run after the origin check and before the body is read or parsed; a
|
|
111
|
+
* CORS preflight (`OPTIONS`) skips it. Return `false` to answer `401` with a GraphQL error envelope.
|
|
101
112
|
*/
|
|
102
113
|
readonly authorize?: (request: Request) => boolean | Promise<boolean>
|
|
103
114
|
/** Emit the legacy always-200 `application/json` response shape instead of `application/graphql-response+json`. */
|
|
@@ -195,6 +206,12 @@ function parseVariables(raw: unknown): Record<string, unknown> | null {
|
|
|
195
206
|
return parsed as Record<string, unknown>
|
|
196
207
|
}
|
|
197
208
|
|
|
209
|
+
/** `application/json` or a structured `+json` type, parameters ignored. */
|
|
210
|
+
function isJsonMediaType(header: string | null): boolean {
|
|
211
|
+
const essence = header?.split(";", 1)[0]?.trim().toLowerCase() ?? ""
|
|
212
|
+
return essence === "application/json" || /^application\/[a-z0-9.+-]+\+json$/.test(essence)
|
|
213
|
+
}
|
|
214
|
+
|
|
198
215
|
/** Read `{query, operationName, variables}` from a parsed POST body. Throws GraphQLError when malformed. */
|
|
199
216
|
function paramsFromBody(body: unknown): GraphqlParams {
|
|
200
217
|
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
@@ -247,12 +264,10 @@ async function run<Context, Env>(
|
|
|
247
264
|
return requestError("", 400, legacy, cors, [gqlErr], opts.formatError)
|
|
248
265
|
}
|
|
249
266
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const documentLimit = documentLimitError(documentMetrics(document), limits)
|
|
267
|
+
// Every limit runs before validate(): its overlap rule is quadratic, so a small document within the
|
|
268
|
+
// byte limit can hold the event loop for seconds.
|
|
269
|
+
const documentLimit =
|
|
270
|
+
documentLimitError(documentMetrics(document), limits) ?? overlapLimitError(document, limits)
|
|
256
271
|
if (documentLimit !== undefined) {
|
|
257
272
|
return requestError(
|
|
258
273
|
documentLimit,
|
|
@@ -264,6 +279,11 @@ async function run<Context, Env>(
|
|
|
264
279
|
)
|
|
265
280
|
}
|
|
266
281
|
|
|
282
|
+
const validationErrors = validate(opts.schema, document, specifiedRules)
|
|
283
|
+
if (validationErrors.length > 0) {
|
|
284
|
+
return requestError("", 400, legacy, cors, validationErrors, opts.formatError)
|
|
285
|
+
}
|
|
286
|
+
|
|
267
287
|
// GET is idempotent and cacheable, so per the GraphQL-over-HTTP spec it may run queries only.
|
|
268
288
|
const operationAst = getOperationAST(document, params.operationName ?? undefined)
|
|
269
289
|
if (isGet && operationAst != null && operationAst.operation !== "query") {
|
|
@@ -295,15 +315,20 @@ async function run<Context, Env>(
|
|
|
295
315
|
|
|
296
316
|
let result: ExecutionResult
|
|
297
317
|
try {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
318
|
+
result = await withExecutionTimeout(
|
|
319
|
+
(abortSignal) =>
|
|
320
|
+
execute({
|
|
321
|
+
schema: opts.schema,
|
|
322
|
+
document,
|
|
323
|
+
rootValue: opts.rootValue,
|
|
324
|
+
contextValue,
|
|
325
|
+
variableValues: params.variables ?? undefined,
|
|
326
|
+
operationName: params.operationName ?? undefined,
|
|
327
|
+
abortSignal,
|
|
328
|
+
}),
|
|
329
|
+
request.signal,
|
|
330
|
+
executionTimeoutMs,
|
|
331
|
+
)
|
|
307
332
|
} catch (err) {
|
|
308
333
|
const gqlErr =
|
|
309
334
|
err instanceof GraphQLError
|
|
@@ -342,11 +367,23 @@ class ExecutionTimeoutError extends Error {
|
|
|
342
367
|
}
|
|
343
368
|
}
|
|
344
369
|
|
|
345
|
-
|
|
370
|
+
/** Run `start` under a deadline. A timeout rejects and aborts the signal resolvers were given. */
|
|
371
|
+
async function withExecutionTimeout<T>(
|
|
372
|
+
start: (abortSignal: AbortSignal) => T | Promise<T>,
|
|
373
|
+
outer: AbortSignal,
|
|
374
|
+
timeoutMs: number,
|
|
375
|
+
): Promise<T> {
|
|
376
|
+
const controller = new AbortController()
|
|
377
|
+
const work = start(AbortSignal.any([outer, controller.signal]))
|
|
346
378
|
if (!(work instanceof Promise) || timeoutMs === 0) return work
|
|
347
379
|
let timer: ReturnType<typeof setTimeout> | undefined
|
|
348
380
|
const timeout = new Promise<T>((_, reject) => {
|
|
349
|
-
timer = setTimeout(() =>
|
|
381
|
+
timer = setTimeout(() => {
|
|
382
|
+
const error = new ExecutionTimeoutError()
|
|
383
|
+
// Rejected first: the abort can reject the work, and the race must settle on the timeout.
|
|
384
|
+
reject(error)
|
|
385
|
+
controller.abort(error)
|
|
386
|
+
}, timeoutMs)
|
|
350
387
|
})
|
|
351
388
|
try {
|
|
352
389
|
return await Promise.race([work, timeout])
|
|
@@ -412,6 +449,19 @@ export async function respondGraphql<Context = unknown, Env = unknown>(
|
|
|
412
449
|
)
|
|
413
450
|
}
|
|
414
451
|
|
|
452
|
+
// Checked before the body is read: urlencoded, multipart and text/plain are what a browser sends
|
|
453
|
+
// cross-site without a preflight, so accepting one would let a form run a mutation with cookies.
|
|
454
|
+
if (!isJsonMediaType(request.headers.get("content-type"))) {
|
|
455
|
+
return requestError(
|
|
456
|
+
"Unsupported media type.",
|
|
457
|
+
415,
|
|
458
|
+
legacy,
|
|
459
|
+
cors,
|
|
460
|
+
[new GraphQLError("A POST body must be sent as application/json.")],
|
|
461
|
+
options.formatError,
|
|
462
|
+
)
|
|
463
|
+
}
|
|
464
|
+
|
|
415
465
|
// Read the JSON body through core's single bounded + proto-guarded framing lane.
|
|
416
466
|
return readBodyFramed<Response>(
|
|
417
467
|
request,
|