nitro-graphql 1.3.0 → 1.3.1

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/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { StandardSchemaV1 } from "./types/standard-schema.js";
2
- import { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions } from "./types/index.js";
2
+ import { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, FederationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions } from "./types/index.js";
3
3
  import * as nitropack0 from "nitropack";
4
4
 
5
5
  //#region src/index.d.ts
6
6
  declare const _default: nitropack0.NitroModule;
7
7
  //#endregion
8
- export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions, StandardSchemaV1, _default as default };
8
+ export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, FederationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, StandardSchemaV1, _default as default };
package/dist/index.js CHANGED
@@ -54,6 +54,7 @@ var src_default = defineNitroModule({
54
54
  },
55
55
  playground: true
56
56
  });
57
+ if (nitro.options.graphql?.federation?.enabled) consola.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
57
58
  const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
58
59
  nitro.graphql.buildDir = graphqlBuildDir;
59
60
  const watchDirs = [];
package/dist/rollup.js CHANGED
@@ -11,6 +11,7 @@ async function rollupConfig(app) {
11
11
  virtualResolvers(app);
12
12
  virtualDirectives(app);
13
13
  getGraphQLConfig(app);
14
+ virtualModuleConfig(app);
14
15
  app.hooks.hook("rollup:before", (nitro, rollupConfig$1) => {
15
16
  rollupConfig$1.plugins = rollupConfig$1.plugins || [];
16
17
  const { include = /\.(graphql|gql)$/i, exclude, validate = false } = app.options.graphql?.loader || {};
@@ -119,6 +120,13 @@ export { importedConfig }
119
120
  `;
120
121
  };
121
122
  }
123
+ function virtualModuleConfig(app) {
124
+ app.options.virtual ??= {};
125
+ app.options.virtual["#nitro-internal-virtual/module-config"] = () => {
126
+ const moduleConfig = app.options.graphql || {};
127
+ return `export const moduleConfig = ${JSON.stringify(moduleConfig, null, 2)};`;
128
+ };
129
+ }
122
130
 
123
131
  //#endregion
124
132
  export { rollupConfig };
@@ -1,6 +1,6 @@
1
1
  import * as h30 from "h3";
2
2
 
3
3
  //#region src/routes/apollo-server.d.ts
4
- declare const _default: h30.EventHandler<h30.EventHandlerRequest, any>;
4
+ declare const _default: h30.EventHandler<h30.EventHandlerRequest, Promise<any>>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -1,16 +1,30 @@
1
1
  import { startServerAndCreateH3Handler } from "../utils/apollo.js";
2
2
  import defu from "defu";
3
+ import { parse } from "graphql";
3
4
  import { mergeResolvers, mergeTypeDefs } from "@graphql-tools/merge";
4
5
  import { importedConfig } from "#nitro-internal-virtual/graphql-config";
6
+ import { moduleConfig } from "#nitro-internal-virtual/module-config";
5
7
  import { directives } from "#nitro-internal-virtual/server-directives";
6
8
  import { resolvers } from "#nitro-internal-virtual/server-resolvers";
7
9
  import { schemas } from "#nitro-internal-virtual/server-schemas";
8
10
  import { ApolloServer } from "@apollo/server";
9
11
  import { ApolloServerPluginLandingPageLocalDefault } from "@apollo/server/plugin/landingPage/default";
10
12
  import { makeExecutableSchema } from "@graphql-tools/schema";
13
+ import { defineEventHandler } from "h3";
11
14
 
12
15
  //#region src/routes/apollo-server.ts
13
- function createMergedSchema() {
16
+ let buildSubgraphSchema = null;
17
+ async function loadFederationSupport() {
18
+ if (buildSubgraphSchema !== null) return buildSubgraphSchema;
19
+ try {
20
+ const apolloSubgraph = await import("@apollo/subgraph");
21
+ buildSubgraphSchema = apolloSubgraph.buildSubgraphSchema;
22
+ } catch {
23
+ buildSubgraphSchema = false;
24
+ }
25
+ return buildSubgraphSchema;
26
+ }
27
+ async function createMergedSchema() {
14
28
  try {
15
29
  const mergedSchemas = schemas.map((schema$1) => schema$1.def).join("\n\n");
16
30
  const typeDefs = mergeTypeDefs([mergedSchemas], {
@@ -19,7 +33,24 @@ function createMergedSchema() {
19
33
  sort: true
20
34
  });
21
35
  const mergedResolvers = mergeResolvers(resolvers.map((r) => r.resolver));
22
- let schema = makeExecutableSchema({
36
+ const federationEnabled = moduleConfig.federation?.enabled;
37
+ let schema;
38
+ if (federationEnabled) {
39
+ const buildSubgraph = await loadFederationSupport();
40
+ if (buildSubgraph) {
41
+ const typeDefsDoc = typeof typeDefs === "string" ? parse(typeDefs) : typeDefs;
42
+ schema = buildSubgraph({
43
+ typeDefs: typeDefsDoc,
44
+ resolvers: mergedResolvers
45
+ });
46
+ } else {
47
+ console.warn("Federation enabled but @apollo/subgraph not available, falling back to regular schema");
48
+ schema = makeExecutableSchema({
49
+ typeDefs,
50
+ resolvers: mergedResolvers
51
+ });
52
+ }
53
+ } else schema = makeExecutableSchema({
23
54
  typeDefs,
24
55
  resolvers: mergedResolvers
25
56
  });
@@ -33,9 +64,9 @@ function createMergedSchema() {
33
64
  }
34
65
  }
35
66
  let apolloServer = null;
36
- function createApolloServer() {
67
+ async function createApolloServer() {
37
68
  if (!apolloServer) {
38
- const schema = createMergedSchema();
69
+ const schema = await createMergedSchema();
39
70
  apolloServer = new ApolloServer(defu({
40
71
  schema,
41
72
  introspection: true,
@@ -44,7 +75,13 @@ function createApolloServer() {
44
75
  }
45
76
  return apolloServer;
46
77
  }
47
- var apollo_server_default = startServerAndCreateH3Handler(apolloServer || createApolloServer, { context: async (event) => ({ event }) });
78
+ let serverPromise = null;
79
+ var apollo_server_default = defineEventHandler(async (event) => {
80
+ if (!serverPromise) serverPromise = createApolloServer();
81
+ const server = await serverPromise;
82
+ const h3Handler = startServerAndCreateH3Handler(server, { context: async () => ({ event }) });
83
+ return h3Handler(event);
84
+ });
48
85
 
49
86
  //#endregion
50
87
  export { apollo_server_default as default };
@@ -1,6 +1,8 @@
1
1
  import defu from "defu";
2
+ import { parse } from "graphql";
2
3
  import { mergeResolvers, mergeTypeDefs } from "@graphql-tools/merge";
3
4
  import { importedConfig } from "#nitro-internal-virtual/graphql-config";
5
+ import { moduleConfig } from "#nitro-internal-virtual/module-config";
4
6
  import { directives } from "#nitro-internal-virtual/server-directives";
5
7
  import { resolvers } from "#nitro-internal-virtual/server-resolvers";
6
8
  import { schemas } from "#nitro-internal-virtual/server-schemas";
@@ -9,6 +11,17 @@ import { defineEventHandler, toWebRequest } from "h3";
9
11
  import { createYoga } from "graphql-yoga";
10
12
 
11
13
  //#region src/routes/graphql-yoga.ts
14
+ let buildSubgraphSchema = null;
15
+ async function loadFederationSupport() {
16
+ if (buildSubgraphSchema !== null) return buildSubgraphSchema;
17
+ try {
18
+ const apolloSubgraph = await import("@apollo/subgraph");
19
+ buildSubgraphSchema = apolloSubgraph.buildSubgraphSchema;
20
+ } catch {
21
+ buildSubgraphSchema = false;
22
+ }
23
+ return buildSubgraphSchema;
24
+ }
12
25
  const apolloSandboxHtml = `<!DOCTYPE html>
13
26
  <html lang="en">
14
27
  <body style="margin: 0; overflow-x: hidden; overflow-y: hidden">
@@ -26,7 +39,7 @@ new window.EmbeddedSandbox({
26
39
  <\/script>
27
40
  </body>
28
41
  </html>`;
29
- function createMergedSchema() {
42
+ async function createMergedSchema() {
30
43
  try {
31
44
  const mergedSchemas = schemas.map((schema$1) => schema$1.def).join("\n\n");
32
45
  const typeDefs = mergeTypeDefs([mergedSchemas], {
@@ -35,7 +48,24 @@ function createMergedSchema() {
35
48
  sort: true
36
49
  });
37
50
  const mergedResolvers = mergeResolvers(resolvers.map((r) => r.resolver));
38
- let schema = makeExecutableSchema({
51
+ const federationEnabled = moduleConfig.federation?.enabled;
52
+ let schema;
53
+ if (federationEnabled) {
54
+ const buildSubgraph = await loadFederationSupport();
55
+ if (buildSubgraph) {
56
+ const typeDefsDoc = typeof typeDefs === "string" ? parse(typeDefs) : typeDefs;
57
+ schema = buildSubgraph({
58
+ typeDefs: typeDefsDoc,
59
+ resolvers: mergedResolvers
60
+ });
61
+ } else {
62
+ console.warn("Federation enabled but @apollo/subgraph not available, falling back to regular schema");
63
+ schema = makeExecutableSchema({
64
+ typeDefs,
65
+ resolvers: mergedResolvers
66
+ });
67
+ }
68
+ } else schema = makeExecutableSchema({
39
69
  typeDefs,
40
70
  resolvers: mergedResolvers
41
71
  });
@@ -51,7 +81,7 @@ function createMergedSchema() {
51
81
  let yoga;
52
82
  var graphql_yoga_default = defineEventHandler(async (event) => {
53
83
  if (!yoga) {
54
- const schema = createMergedSchema();
84
+ const schema = await createMergedSchema();
55
85
  yoga = createYoga(defu({
56
86
  schema,
57
87
  graphqlEndpoint: "/api/graphql",
@@ -84,6 +84,16 @@ interface ExternalGraphQLService {
84
84
  clientSDK?: GenericSdkConfig;
85
85
  };
86
86
  }
87
+ interface FederationConfig {
88
+ /** Enable Apollo Federation subgraph support */
89
+ enabled: boolean;
90
+ /** Service name for federation (used in subgraph config) */
91
+ serviceName?: string;
92
+ /** Service version for federation */
93
+ serviceVersion?: string;
94
+ /** Service URL for federation gateway */
95
+ serviceUrl?: string;
96
+ }
87
97
  interface NitroGraphQLOptions {
88
98
  framework: 'graphql-yoga' | 'apollo-server';
89
99
  endpoint?: {
@@ -105,6 +115,8 @@ interface NitroGraphQLOptions {
105
115
  };
106
116
  /** External GraphQL services to generate types and SDKs for */
107
117
  externalServices?: ExternalGraphQLService[];
118
+ /** Apollo Federation configuration */
119
+ federation?: FederationConfig;
108
120
  }
109
121
  //#endregion
110
- export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions };
122
+ export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, FederationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions };
@@ -1,7 +1,7 @@
1
- import { CodegenServerConfig } from "../types/index.js";
1
+ import { NitroGraphQLOptions } from "../types/index.js";
2
2
  import { GraphQLSchema } from "graphql";
3
3
 
4
4
  //#region src/utils/server-codegen.d.ts
5
- declare function generateTypes(selectFremework: string, schema: GraphQLSchema, config?: CodegenServerConfig, outputPath?: string): Promise<string>;
5
+ declare function generateTypes(selectFremework: string, schema: GraphQLSchema, config?: Partial<NitroGraphQLOptions>, outputPath?: string): Promise<string>;
6
6
  //#endregion
7
7
  export { generateTypes };
@@ -41,9 +41,10 @@ async function generateTypes(selectFremework, schema, config = {}, outputPath) {
41
41
  maybeValue: "T | null | undefined",
42
42
  inputMaybeValue: "T | undefined",
43
43
  declarationKind: "interface",
44
- enumsAsTypes: true
44
+ enumsAsTypes: true,
45
+ ...config.federation?.enabled && { federation: true }
45
46
  };
46
- const mergedConfig = defu$1(defaultConfig, config);
47
+ const mergedConfig = defu$1(defaultConfig, config.codegen?.server);
47
48
  const output = await codegen({
48
49
  filename: outputPath || "types.generated.ts",
49
50
  schema: parse(printSchemaWithDirectives(schema)),
@@ -193,13 +193,36 @@ async function serverTypeGeneration(app) {
193
193
  const isValid = validateNoDuplicateTypes(schemas, schemaStrings);
194
194
  if (!isValid) return;
195
195
  const mergedSchemasString = schemaStrings.join("\n\n");
196
- const mergedSchemas = mergeTypeDefs([mergedSchemasString], {
196
+ const federationEnabled = app.options.graphql?.federation?.enabled === true;
197
+ let schemaWithDirectives = mergedSchemasString;
198
+ if (federationEnabled) {
199
+ const federationDirectives = `
200
+ directive @key(fields: String!) on OBJECT | INTERFACE
201
+ directive @requires(fields: String!) on FIELD_DEFINITION
202
+ directive @provides(fields: String!) on FIELD_DEFINITION
203
+ directive @external on FIELD_DEFINITION | OBJECT
204
+ directive @tag(name: String!) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
205
+ directive @extends on OBJECT | INTERFACE
206
+ directive @shareable on FIELD_DEFINITION | OBJECT
207
+ directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
208
+ directive @override(from: String!) on FIELD_DEFINITION
209
+ directive @composeDirective(name: String!) on SCHEMA
210
+ directive @link(url: String!, as: String, for: Purpose, import: [String!]) on SCHEMA
211
+
212
+ enum Purpose {
213
+ SECURITY
214
+ EXECUTION
215
+ }
216
+ `;
217
+ schemaWithDirectives = `${federationDirectives}\n\n${mergedSchemasString}`;
218
+ }
219
+ const mergedSchemas = mergeTypeDefs([schemaWithDirectives], {
197
220
  throwOnConflict: true,
198
221
  commentDescriptions: true,
199
222
  sort: true
200
223
  });
201
224
  const schema = buildSchema(mergedSchemas);
202
- const data = await generateTypes(app.options.graphql?.framework || "graphql-yoga", schema, app.options.graphql?.codegen?.server ?? {});
225
+ const data = await generateTypes(app.options.graphql?.framework || "graphql-yoga", schema, app.options.graphql ?? {});
203
226
  const printSchema = printSchemaWithDirectives(schema);
204
227
  const schemaPath = resolve(app.graphql.buildDir, "schema.graphql");
205
228
  mkdirSync(dirname(schemaPath), { recursive: true });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nitro-graphql",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.3.1",
5
5
  "description": "GraphQL integration for Nitro",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,
@@ -56,6 +56,7 @@
56
56
  ],
57
57
  "peerDependencies": {
58
58
  "@apollo/server": "^5.0.0",
59
+ "@apollo/subgraph": "^2.0.0",
59
60
  "@apollo/utils.withrequired": "^3.0.0",
60
61
  "@as-integrations/h3": "^2.0.0",
61
62
  "graphql": "^16.11.0",
@@ -66,6 +67,9 @@
66
67
  "@apollo/server": {
67
68
  "optional": true
68
69
  },
70
+ "@apollo/subgraph": {
71
+ "optional": true
72
+ },
69
73
  "@apollo/utils.withrequired": {
70
74
  "optional": true
71
75
  },
@@ -100,6 +104,7 @@
100
104
  },
101
105
  "devDependencies": {
102
106
  "@antfu/eslint-config": "^5.2.1",
107
+ "@apollo/subgraph": "^2.11.2",
103
108
  "@nuxt/kit": "^4.0.3",
104
109
  "@nuxt/schema": "^4.0.3",
105
110
  "@types/node": "^22.18.0",