nitro-graphql 1.6.0 → 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.
@@ -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,6 @@
1
+ import { GraphQLSchema } from "graphql";
2
+
3
+ //#region src/utils/ws-schema.d.ts
4
+ declare function createMergedSchema(): Promise<GraphQLSchema>;
5
+ //#endregion
6
+ export { createMergedSchema };
@@ -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,8 +1,7 @@
1
1
  {
2
2
  "name": "nitro-graphql",
3
3
  "type": "module",
4
- "version": "1.6.0",
5
- "packageManager": "pnpm@10.24.0",
4
+ "version": "1.7.0-beta.0",
6
5
  "description": "GraphQL integration for Nitro",
7
6
  "license": "MIT",
8
7
  "repository": {
@@ -56,6 +55,10 @@
56
55
  "./nuxt": {
57
56
  "types": "./dist/ecosystem/nuxt.d.mts",
58
57
  "import": "./dist/ecosystem/nuxt.mjs"
58
+ },
59
+ "./subscribe": {
60
+ "types": "./dist/subscribe/index.d.mts",
61
+ "import": "./dist/subscribe/index.mjs"
59
62
  }
60
63
  },
61
64
  "module": "./dist/index.mjs",
@@ -63,21 +66,6 @@
63
66
  "files": [
64
67
  "dist"
65
68
  ],
66
- "scripts": {
67
- "prepack": "pnpm build",
68
- "build": "tsdown",
69
- "dev": "tsdown --watch",
70
- "bumpp": "bumpp package.json",
71
- "release": "pnpm build && pnpm bumpp",
72
- "playground:nitro": "cd playgrounds/nitro && pnpm install && pnpm dev",
73
- "playground:nuxt": "cd playgrounds/nuxt && pnpm install && pnpm dev",
74
- "playground:federation": "cd playgrounds/federation && pnpm install && pnpm dev",
75
- "docs:dev": "cd .docs && pnpm install && pnpm dev",
76
- "docs:build": "cd .docs && pnpm install && pnpm build",
77
- "docs:preview": "cd .docs && pnpm preview",
78
- "lint": "eslint .",
79
- "lint:fix": "eslint . --fix"
80
- },
81
69
  "peerDependencies": {
82
70
  "@apollo/server": "^5.0.0",
83
71
  "@apollo/utils.withrequired": "^3.0.0",
@@ -98,49 +86,64 @@
98
86
  }
99
87
  },
100
88
  "dependencies": {
101
- "@apollo/subgraph": "catalog:",
102
- "@graphql-codegen/core": "catalog:",
103
- "@graphql-codegen/import-types-preset": "catalog:",
104
- "@graphql-codegen/typescript": "catalog:",
105
- "@graphql-codegen/typescript-generic-sdk": "catalog:",
106
- "@graphql-codegen/typescript-operations": "catalog:",
107
- "@graphql-codegen/typescript-resolvers": "catalog:",
108
- "@graphql-tools/graphql-file-loader": "catalog:",
109
- "@graphql-tools/load": "catalog:",
110
- "@graphql-tools/load-files": "catalog:",
111
- "@graphql-tools/merge": "catalog:",
112
- "@graphql-tools/schema": "catalog:",
113
- "@graphql-tools/url-loader": "catalog:",
114
- "@graphql-tools/utils": "catalog:",
115
- "chokidar": "catalog:",
116
- "consola": "catalog:",
117
- "defu": "catalog:",
118
- "graphql-config": "catalog:",
119
- "graphql-scalars": "catalog:",
120
- "knitwork": "catalog:",
121
- "ohash": "catalog:",
122
- "oxc-parser": "catalog:",
123
- "pathe": "catalog:",
124
- "tinyglobby": "catalog:"
89
+ "@apollo/subgraph": "^2.12.2",
90
+ "@graphql-codegen/core": "^5.0.0",
91
+ "@graphql-codegen/import-types-preset": "^3.0.1",
92
+ "@graphql-codegen/typescript": "^5.0.6",
93
+ "@graphql-codegen/typescript-generic-sdk": "^4.0.2",
94
+ "@graphql-codegen/typescript-operations": "^5.0.6",
95
+ "@graphql-codegen/typescript-resolvers": "^5.1.4",
96
+ "@graphql-tools/graphql-file-loader": "^8.1.8",
97
+ "@graphql-tools/load": "^8.1.7",
98
+ "@graphql-tools/load-files": "^7.0.1",
99
+ "@graphql-tools/merge": "^9.1.6",
100
+ "@graphql-tools/schema": "^10.0.30",
101
+ "@graphql-tools/url-loader": "^9.0.5",
102
+ "@graphql-tools/utils": "^10.11.0",
103
+ "chokidar": "^5.0.0",
104
+ "consola": "^3.4.2",
105
+ "defu": "^6.1.4",
106
+ "graphql-config": "^5.1.5",
107
+ "graphql-scalars": "^1.25.0",
108
+ "knitwork": "^1.3.0",
109
+ "ohash": "^2.0.11",
110
+ "oxc-parser": "^0.102.0",
111
+ "pathe": "^2.0.3",
112
+ "tinyglobby": "^0.2.15"
125
113
  },
126
114
  "devDependencies": {
127
- "@antfu/eslint-config": "catalog:",
128
- "@nuxt/kit": "catalog:",
129
- "@nuxt/schema": "catalog:",
130
- "@types/node": "catalog:",
131
- "bumpp": "catalog:",
132
- "changelogen": "catalog:",
133
- "crossws": "catalog:",
134
- "eslint": "catalog:",
135
- "graphql": "catalog:",
136
- "graphql-yoga": "catalog:",
137
- "h3": "catalog:",
138
- "nitropack": "catalog:",
139
- "tsdown": "catalog:",
140
- "typescript": "catalog:",
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",
119
+ "bumpp": "^10.3.2",
120
+ "changelogen": "^0.6.2",
121
+ "crossws": "0.3.5",
122
+ "eslint": "^9.39.1",
123
+ "graphql": "16.11.0",
124
+ "graphql-yoga": "^5.17.1",
125
+ "h3": "1.15.3",
126
+ "nitropack": "^2.12.9",
127
+ "tsdown": "^0.17.2",
128
+ "typescript": "^5.9.3",
141
129
  "vitepress-plugin-llms": "^1.9.3"
142
130
  },
143
131
  "resolutions": {
144
132
  "nitro-graphql": "link:."
133
+ },
134
+ "scripts": {
135
+ "build": "tsdown",
136
+ "dev": "tsdown --watch",
137
+ "bumpp": "bumpp package.json",
138
+ "release": "pnpm build && pnpm bumpp",
139
+ "playground:nitro": "cd playgrounds/nitro && pnpm install && pnpm dev",
140
+ "playground:nuxt": "cd playgrounds/nuxt && pnpm install && pnpm dev",
141
+ "playground:federation": "cd playgrounds/federation && pnpm install && pnpm dev",
142
+ "docs:dev": "cd .docs && pnpm install && pnpm dev",
143
+ "docs:build": "cd .docs && pnpm install && pnpm build",
144
+ "docs:preview": "cd .docs && pnpm preview",
145
+ "lint": "eslint .",
146
+ "lint:fix": "eslint . --fix",
147
+ "typecheck": "tsc --noEmit"
145
148
  }
146
- }
149
+ }