nitro-graphql 1.6.1 → 1.7.0-beta.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/dist/ecosystem/nuxt.mjs +3 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +23 -1
- package/dist/rollup.mjs +2 -2
- package/dist/routes/apollo-server-ws.d.mts +6 -0
- package/dist/routes/apollo-server-ws.mjs +298 -0
- package/dist/routes/apollo-server.d.mts +2 -2
- package/dist/routes/apollo-server.mjs +2 -2
- package/dist/routes/debug.d.mts +2 -2
- package/dist/routes/graphql-yoga-ws.d.mts +6 -0
- package/dist/routes/graphql-yoga-ws.mjs +298 -0
- package/dist/routes/graphql-yoga.d.mts +2 -2
- package/dist/subscribe/index.d.mts +146 -0
- package/dist/subscribe/index.mjs +830 -0
- package/dist/templates/subscribe-client.mjs +59 -0
- package/dist/types/index.d.mts +16 -1
- package/dist/utils/apollo.d.mts +1 -1
- package/dist/utils/apollo.mjs +1 -1
- package/dist/utils/client-codegen.d.mts +15 -1
- package/dist/utils/client-codegen.mjs +407 -8
- package/dist/utils/define.d.mts +1 -1
- package/dist/utils/type-generation.mjs +7 -3
- package/dist/utils/ws-protocol.d.mts +25 -0
- package/dist/utils/ws-protocol.mjs +99 -0
- package/dist/utils/ws-schema.d.mts +6 -0
- package/dist/utils/ws-schema.mjs +58 -0
- package/package.json +14 -9
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { parse, subscribe, validate } from "graphql";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/ws-protocol.ts
|
|
4
|
+
const isDev = process.env.NODE_ENV === "development";
|
|
5
|
+
function devLog(message, ...args) {
|
|
6
|
+
if (isDev) console.log(message, ...args);
|
|
7
|
+
}
|
|
8
|
+
function sendMessage(peer, message) {
|
|
9
|
+
peer.send(JSON.stringify(message));
|
|
10
|
+
}
|
|
11
|
+
function sendErrorMessage(peer, id, errors) {
|
|
12
|
+
sendMessage(peer, {
|
|
13
|
+
id,
|
|
14
|
+
type: "error",
|
|
15
|
+
payload: errors
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function sendNextMessage(peer, id, payload) {
|
|
19
|
+
sendMessage(peer, {
|
|
20
|
+
id,
|
|
21
|
+
type: "next",
|
|
22
|
+
payload
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function sendCompleteMessage(peer, id) {
|
|
26
|
+
sendMessage(peer, {
|
|
27
|
+
id,
|
|
28
|
+
type: "complete"
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function handleConnectionInit(peer) {
|
|
32
|
+
sendMessage(peer, { type: "connection_ack" });
|
|
33
|
+
}
|
|
34
|
+
function handlePing(peer) {
|
|
35
|
+
sendMessage(peer, { type: "pong" });
|
|
36
|
+
}
|
|
37
|
+
async function handleSubscribe(peer, msg, schema, subscriptions) {
|
|
38
|
+
if (!msg.id || !msg.payload) {
|
|
39
|
+
sendErrorMessage(peer, msg.id, [{ message: "Invalid subscribe message" }]);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const { query, variables, operationName } = msg.payload;
|
|
44
|
+
const document = typeof query === "string" ? parse(query) : query;
|
|
45
|
+
const validationErrors = validate(schema, document);
|
|
46
|
+
if (validationErrors.length > 0) {
|
|
47
|
+
sendErrorMessage(peer, msg.id, validationErrors.map((err) => ({
|
|
48
|
+
message: err.message,
|
|
49
|
+
locations: err.locations,
|
|
50
|
+
path: err.path
|
|
51
|
+
})));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const result = await subscribe({
|
|
55
|
+
schema,
|
|
56
|
+
document,
|
|
57
|
+
variableValues: variables,
|
|
58
|
+
operationName,
|
|
59
|
+
contextValue: {}
|
|
60
|
+
});
|
|
61
|
+
if (Symbol.asyncIterator in result) {
|
|
62
|
+
subscriptions.set(msg.id, result);
|
|
63
|
+
(async () => {
|
|
64
|
+
try {
|
|
65
|
+
for await (const value of result) sendNextMessage(peer, msg.id, value);
|
|
66
|
+
sendCompleteMessage(peer, msg.id);
|
|
67
|
+
subscriptions.delete(msg.id);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error("[GraphQL WS] Subscription error:", error);
|
|
70
|
+
sendErrorMessage(peer, msg.id, [{ message: error instanceof Error ? error.message : "Subscription error" }]);
|
|
71
|
+
subscriptions.delete(msg.id);
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
} else {
|
|
75
|
+
sendNextMessage(peer, msg.id, result);
|
|
76
|
+
sendCompleteMessage(peer, msg.id);
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error("[GraphQL WS] Operation error:", error);
|
|
80
|
+
sendErrorMessage(peer, msg.id, [{ message: error instanceof Error ? error.message : "Operation failed" }]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function handleComplete(msg, subscriptions) {
|
|
84
|
+
if (!msg.id) return;
|
|
85
|
+
const iterator = subscriptions.get(msg.id);
|
|
86
|
+
if (iterator && typeof iterator.return === "function") await iterator.return();
|
|
87
|
+
subscriptions.delete(msg.id);
|
|
88
|
+
}
|
|
89
|
+
async function cleanupSubscriptions(subscriptions) {
|
|
90
|
+
for (const [id, iterator] of subscriptions.entries()) if (typeof iterator.return === "function") try {
|
|
91
|
+
await iterator.return();
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`[GraphQL WS] Error cleaning up subscription ${id}:`, error);
|
|
94
|
+
}
|
|
95
|
+
subscriptions.clear();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
export { cleanupSubscriptions, devLog, handleComplete, handleConnectionInit, handlePing, handleSubscribe, sendCompleteMessage, sendErrorMessage, sendMessage, sendNextMessage };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { parse } from "graphql";
|
|
2
|
+
import { mergeResolvers, mergeTypeDefs } from "@graphql-tools/merge";
|
|
3
|
+
import { moduleConfig } from "#nitro-internal-virtual/module-config";
|
|
4
|
+
import { directives } from "#nitro-internal-virtual/server-directives";
|
|
5
|
+
import { resolvers } from "#nitro-internal-virtual/server-resolvers";
|
|
6
|
+
import { schemas } from "#nitro-internal-virtual/server-schemas";
|
|
7
|
+
import { makeExecutableSchema } from "@graphql-tools/schema";
|
|
8
|
+
|
|
9
|
+
//#region src/utils/ws-schema.ts
|
|
10
|
+
let buildSubgraphSchema = null;
|
|
11
|
+
async function loadFederationSupport() {
|
|
12
|
+
if (buildSubgraphSchema !== null) return buildSubgraphSchema;
|
|
13
|
+
try {
|
|
14
|
+
buildSubgraphSchema = (await import("@apollo/subgraph")).buildSubgraphSchema;
|
|
15
|
+
} catch {
|
|
16
|
+
buildSubgraphSchema = false;
|
|
17
|
+
}
|
|
18
|
+
return buildSubgraphSchema;
|
|
19
|
+
}
|
|
20
|
+
async function createMergedSchema() {
|
|
21
|
+
try {
|
|
22
|
+
const typeDefs = mergeTypeDefs([schemas.map((schema$1) => schema$1.def).join("\n\n")], {
|
|
23
|
+
throwOnConflict: true,
|
|
24
|
+
commentDescriptions: true,
|
|
25
|
+
sort: true
|
|
26
|
+
});
|
|
27
|
+
const mergedResolvers = mergeResolvers(resolvers.map((r) => r.resolver));
|
|
28
|
+
const federationEnabled = moduleConfig.federation?.enabled;
|
|
29
|
+
let schema;
|
|
30
|
+
if (federationEnabled) {
|
|
31
|
+
const buildSubgraph = await loadFederationSupport();
|
|
32
|
+
if (buildSubgraph) schema = buildSubgraph({
|
|
33
|
+
typeDefs: typeof typeDefs === "string" ? parse(typeDefs) : typeDefs,
|
|
34
|
+
resolvers: mergedResolvers
|
|
35
|
+
});
|
|
36
|
+
else {
|
|
37
|
+
console.warn("[GraphQL WS] Federation enabled but @apollo/subgraph not available, falling back to regular schema");
|
|
38
|
+
schema = makeExecutableSchema({
|
|
39
|
+
typeDefs,
|
|
40
|
+
resolvers: mergedResolvers
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
} else schema = makeExecutableSchema({
|
|
44
|
+
typeDefs,
|
|
45
|
+
resolvers: mergedResolvers
|
|
46
|
+
});
|
|
47
|
+
if (directives && directives.length > 0) {
|
|
48
|
+
for (const { directive } of directives) if (directive.transformer) schema = directive.transformer(schema);
|
|
49
|
+
}
|
|
50
|
+
return schema;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error("[GraphQL WS] Schema merge error:", error);
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { createMergedSchema };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-graphql",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.7.0-beta.0",
|
|
5
5
|
"description": "GraphQL integration for Nitro",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -55,6 +55,10 @@
|
|
|
55
55
|
"./nuxt": {
|
|
56
56
|
"types": "./dist/ecosystem/nuxt.d.mts",
|
|
57
57
|
"import": "./dist/ecosystem/nuxt.mjs"
|
|
58
|
+
},
|
|
59
|
+
"./subscribe": {
|
|
60
|
+
"types": "./dist/subscribe/index.d.mts",
|
|
61
|
+
"import": "./dist/subscribe/index.mjs"
|
|
58
62
|
}
|
|
59
63
|
},
|
|
60
64
|
"module": "./dist/index.mjs",
|
|
@@ -82,7 +86,7 @@
|
|
|
82
86
|
}
|
|
83
87
|
},
|
|
84
88
|
"dependencies": {
|
|
85
|
-
"@apollo/subgraph": "^2.12.
|
|
89
|
+
"@apollo/subgraph": "^2.12.2",
|
|
86
90
|
"@graphql-codegen/core": "^5.0.0",
|
|
87
91
|
"@graphql-codegen/import-types-preset": "^3.0.1",
|
|
88
92
|
"@graphql-codegen/typescript": "^5.0.6",
|
|
@@ -103,15 +107,15 @@
|
|
|
103
107
|
"graphql-scalars": "^1.25.0",
|
|
104
108
|
"knitwork": "^1.3.0",
|
|
105
109
|
"ohash": "^2.0.11",
|
|
106
|
-
"oxc-parser": "^0.
|
|
110
|
+
"oxc-parser": "^0.102.0",
|
|
107
111
|
"pathe": "^2.0.3",
|
|
108
112
|
"tinyglobby": "^0.2.15"
|
|
109
113
|
},
|
|
110
114
|
"devDependencies": {
|
|
111
|
-
"@antfu/eslint-config": "^6.
|
|
112
|
-
"@nuxt/kit": "^4.2.
|
|
113
|
-
"@nuxt/schema": "^4.2.
|
|
114
|
-
"@types/node": "^24.10.
|
|
115
|
+
"@antfu/eslint-config": "^6.6.1",
|
|
116
|
+
"@nuxt/kit": "^4.2.2",
|
|
117
|
+
"@nuxt/schema": "^4.2.2",
|
|
118
|
+
"@types/node": "^24.10.3",
|
|
115
119
|
"bumpp": "^10.3.2",
|
|
116
120
|
"changelogen": "^0.6.2",
|
|
117
121
|
"crossws": "0.3.5",
|
|
@@ -120,7 +124,7 @@
|
|
|
120
124
|
"graphql-yoga": "^5.17.1",
|
|
121
125
|
"h3": "1.15.3",
|
|
122
126
|
"nitropack": "^2.12.9",
|
|
123
|
-
"tsdown": "^0.
|
|
127
|
+
"tsdown": "^0.17.2",
|
|
124
128
|
"typescript": "^5.9.3",
|
|
125
129
|
"vitepress-plugin-llms": "^1.9.3"
|
|
126
130
|
},
|
|
@@ -139,6 +143,7 @@
|
|
|
139
143
|
"docs:build": "cd .docs && pnpm install && pnpm build",
|
|
140
144
|
"docs:preview": "cd .docs && pnpm preview",
|
|
141
145
|
"lint": "eslint .",
|
|
142
|
-
"lint:fix": "eslint . --fix"
|
|
146
|
+
"lint:fix": "eslint . --fix",
|
|
147
|
+
"typecheck": "tsc --noEmit"
|
|
143
148
|
}
|
|
144
149
|
}
|