@graphql-mesh/compose-cli 0.4.0 → 0.4.1-alpha-20240626143434-7cd2ddcf1e46bd3f52ea1e6276c1d9beeb5171a4

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.
@@ -1,9 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getComposedSchemaFromConfig = void 0;
3
+ exports.getComposedSchemaFromConfig = getComposedSchemaFromConfig;
4
+ const graphql_1 = require("graphql");
4
5
  const fusion_composition_1 = require("@graphql-mesh/fusion-composition");
5
6
  const graphql_file_loader_1 = require("@graphql-tools/graphql-file-loader");
6
7
  const load_1 = require("@graphql-tools/load");
8
+ const schema_1 = require("@graphql-tools/schema");
9
+ const utils_1 = require("@graphql-tools/utils");
7
10
  const fetch_1 = require("@whatwg-node/fetch");
8
11
  async function getComposedSchemaFromConfig(config, logger) {
9
12
  const ctx = {
@@ -20,7 +23,8 @@ async function getComposedSchemaFromConfig(config, logger) {
20
23
  subgraphSchema = await schema$;
21
24
  }
22
25
  catch (e) {
23
- throw new Error(`Failed to load subgraph ${subgraphName} - ${e.stack}`);
26
+ log.error(`Failed to load subgraph ${subgraphName}`);
27
+ throw e;
24
28
  }
25
29
  return {
26
30
  name: subgraphName,
@@ -38,15 +42,41 @@ async function getComposedSchemaFromConfig(config, logger) {
38
42
  });
39
43
  additionalTypeDefs = result.map(r => r.document || r.rawSDL);
40
44
  }
41
- let composedSchema = (0, fusion_composition_1.composeSubgraphs)(subgraphConfigsForComposition, {
42
- typeDefs: additionalTypeDefs,
43
- });
44
- if (config.transforms?.length) {
45
- logger.info('Applying transforms');
46
- for (const transform of config.transforms) {
47
- composedSchema = transform(composedSchema);
45
+ const result = (0, fusion_composition_1.composeSubgraphs)(subgraphConfigsForComposition);
46
+ if (result.errors?.length) {
47
+ throw new Error(`Failed to compose subgraphs; \n${result.errors.map(e => `- ${e.message}`).join('\n')}`);
48
+ }
49
+ if (config.subgraph) {
50
+ const subgraph = result.annotatedSubgraphs.find(sg => sg.name === config.subgraph);
51
+ if (!subgraph) {
52
+ throw new Error(`Subgraph ${config.subgraph} not found`);
48
53
  }
54
+ return (0, graphql_1.print)(subgraph.typeDefs);
55
+ }
56
+ if (!result.supergraphSdl) {
57
+ throw new Error(`Unknown error: composed schema is empty`);
49
58
  }
50
- return composedSchema;
59
+ if (additionalTypeDefs?.length || config.transforms?.length) {
60
+ let composedSchema = (0, graphql_1.buildSchema)(result.supergraphSdl, {
61
+ noLocation: true,
62
+ assumeValid: true,
63
+ assumeValidSDL: true,
64
+ });
65
+ if (additionalTypeDefs?.length) {
66
+ composedSchema = (0, schema_1.mergeSchemas)({
67
+ schemas: [composedSchema],
68
+ typeDefs: additionalTypeDefs,
69
+ assumeValid: true,
70
+ assumeValidSDL: true,
71
+ });
72
+ }
73
+ if (config.transforms?.length) {
74
+ logger.info('Applying transforms');
75
+ for (const transform of config.transforms) {
76
+ composedSchema = transform(composedSchema);
77
+ }
78
+ }
79
+ return (0, utils_1.printSchemaWithDirectives)(composedSchema);
80
+ }
81
+ return result.supergraphSdl;
51
82
  }
52
- exports.getComposedSchemaFromConfig = getComposedSchemaFromConfig;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadGraphQLHTTPSubgraph = void 0;
3
+ exports.loadGraphQLHTTPSubgraph = loadGraphQLHTTPSubgraph;
4
4
  const graphql_1 = require("graphql");
5
- function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, spec = false, transportKind = 'http', }) {
5
+ function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, federation = false, transportKind = 'http', }) {
6
6
  return (ctx) => {
7
7
  let schema$;
8
8
  function handleFetchedSchema(schema) {
@@ -10,7 +10,7 @@ function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQuer
10
10
  kind: transportKind,
11
11
  subgraph: subgraphName,
12
12
  location: endpoint,
13
- headers: operationHeaders,
13
+ headers: operationHeaders ? Object.entries(operationHeaders) : undefined,
14
14
  options: {
15
15
  method,
16
16
  useGETForQueries,
@@ -35,7 +35,7 @@ function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQuer
35
35
  kind: transportKind,
36
36
  subgraph: subgraphName,
37
37
  location: endpoint,
38
- headers: operationHeaders,
38
+ headers: operationHeaders ? Object.entries(operationHeaders) : undefined,
39
39
  options: {
40
40
  method,
41
41
  useGETForQueries,
@@ -46,50 +46,58 @@ function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQuer
46
46
  }, schema));
47
47
  }
48
48
  else {
49
- switch (spec) {
50
- case false:
51
- schema$ = ctx
52
- .fetch(endpoint, {
53
- method: method || (useGETForQueries ? 'GET' : 'POST'),
54
- headers: {
55
- 'Content-Type': 'application/json',
56
- },
57
- body: JSON.stringify({
58
- query: (0, graphql_1.getIntrospectionQuery)(),
59
- }),
60
- })
61
- .then(res => {
62
- assertResponseOk(res);
63
- return res.json();
64
- })
65
- .then((result) => (0, graphql_1.buildClientSchema)(result.data, {
66
- assumeValid: true,
67
- }));
68
- break;
69
- case 'federation':
70
- schema$ = ctx
71
- .fetch(endpoint, {
72
- method: method || (useGETForQueries ? 'GET' : 'POST'),
73
- headers: {
74
- 'Content-Type': 'application/json',
75
- },
76
- body: JSON.stringify({
77
- query: federationIntrospectionQuery,
78
- }),
79
- })
80
- .then(res => {
81
- assertResponseOk(res);
82
- return res.text();
83
- })
84
- .then(sdl => (0, graphql_1.buildSchema)(sdl, {
85
- assumeValidSDL: true,
86
- assumeValid: true,
87
- noLocation: true,
88
- }));
89
- break;
90
- default:
91
- throw new Error(`Unsupported spec: ${spec}`);
92
- }
49
+ const fetchAsRegular = () => ctx
50
+ .fetch(endpoint, {
51
+ method: method || (useGETForQueries ? 'GET' : 'POST'),
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ },
55
+ body: JSON.stringify({
56
+ query: (0, graphql_1.getIntrospectionQuery)(),
57
+ }),
58
+ })
59
+ .then(res => {
60
+ assertResponseOk(res);
61
+ return res.json();
62
+ })
63
+ .then((result) => (0, graphql_1.buildClientSchema)(result.data, {
64
+ assumeValid: true,
65
+ }))
66
+ .then(schema => {
67
+ const queryType = schema.getQueryType();
68
+ const queryFields = queryType?.getFields();
69
+ if (queryFields._service) {
70
+ const serviceType = (0, graphql_1.getNamedType)(queryFields._service.type);
71
+ if ((0, graphql_1.isObjectType)(serviceType)) {
72
+ const serviceTypeFields = serviceType.getFields();
73
+ if (serviceTypeFields.sdl) {
74
+ return fetchAsFederation();
75
+ }
76
+ }
77
+ }
78
+ return schema;
79
+ });
80
+ const fetchAsFederation = () => ctx
81
+ .fetch(endpoint, {
82
+ method: method || (useGETForQueries ? 'GET' : 'POST'),
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ body: JSON.stringify({
87
+ query: federationIntrospectionQuery,
88
+ }),
89
+ })
90
+ .then(res => {
91
+ assertResponseOk(res);
92
+ return res.json();
93
+ })
94
+ .then((result) => result?.data?._service?.sdl)
95
+ .then(sdl => (0, graphql_1.buildSchema)(sdl, {
96
+ assumeValidSDL: true,
97
+ assumeValid: true,
98
+ noLocation: true,
99
+ }));
100
+ schema$ = federation ? fetchAsFederation() : fetchAsRegular();
93
101
  }
94
102
  schema$ = schema$.then(handleFetchedSchema);
95
103
  return {
@@ -98,12 +106,27 @@ function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQuer
98
106
  };
99
107
  };
100
108
  }
101
- exports.loadGraphQLHTTPSubgraph = loadGraphQLHTTPSubgraph;
109
+ const transportDirective = new graphql_1.GraphQLDirective({
110
+ name: 'transport',
111
+ isRepeatable: true,
112
+ locations: [graphql_1.DirectiveLocation.SCHEMA],
113
+ args: {
114
+ kind: { type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString) },
115
+ subgraph: { type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString) },
116
+ location: { type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString) },
117
+ headers: { type: new graphql_1.GraphQLList(new graphql_1.GraphQLList(graphql_1.GraphQLString)) },
118
+ options: { type: new graphql_1.GraphQLScalarType({ name: 'TransportOptions' }) },
119
+ },
120
+ });
102
121
  function addAnnotations(transportEntry, schema) {
103
122
  const schemaExtensions = (schema.extensions ||= {});
104
123
  schemaExtensions.directives ||= {};
105
124
  schemaExtensions.directives.transport = transportEntry;
106
- return schema;
125
+ const schemaConfig = schema.toConfig();
126
+ return new graphql_1.GraphQLSchema({
127
+ ...schemaConfig,
128
+ directives: [...schemaConfig.directives, transportDirective],
129
+ });
107
130
  }
108
131
  const federationIntrospectionQuery = /* GraphQL */ `
109
132
  query GetFederationInfo {
package/cjs/run.js CHANGED
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.run = void 0;
26
+ exports.run = run;
27
27
  require("tsx/cjs"); // support importing typescript configs in CommonJS
28
28
  require("tsx/esm"); // support importing typescript configs in ESM
29
29
  require("dotenv/config"); // inject dotenv options to process.env
@@ -34,12 +34,12 @@ const path_1 = require("path");
34
34
  const graphql_1 = require("graphql");
35
35
  const extra_typings_1 = require("@commander-js/extra-typings");
36
36
  const utils_1 = require("@graphql-mesh/utils");
37
- const utils_2 = require("@graphql-tools/utils");
38
37
  const getComposedSchemaFromConfig_js_1 = require("./getComposedSchemaFromConfig.js");
39
38
  let program = new extra_typings_1.Command()
40
39
  .addOption(new extra_typings_1.Option('-c, --config-path <path>', 'path to the configuration file')
41
40
  .env('CONFIG_PATH')
42
41
  .default('mesh.config.ts'))
42
+ .option('--subgraph <name>', 'name of the subgraph to compose')
43
43
  .option('-o, --output <path>', 'path to the output file');
44
44
  async function run({ log: rootLog = new utils_1.DefaultLogger(), productName = 'Mesh Compose', productDescription = 'compose a GraphQL federated schema from any API service(s)', binName = 'mesh-compose', version, }) {
45
45
  program = program.name(binName).description(productDescription);
@@ -76,15 +76,14 @@ async function run({ log: rootLog = new utils_1.DefaultLogger(), productName = '
76
76
  ...opts,
77
77
  };
78
78
  log.info('Composing');
79
- const fusiongraphSchema = await (0, getComposedSchemaFromConfig_js_1.getComposedSchemaFromConfig)(config, log);
80
- const fusiongraph = (0, utils_2.printSchemaWithDirectives)(fusiongraphSchema);
79
+ const supergraphSdl = await (0, getComposedSchemaFromConfig_js_1.getComposedSchemaFromConfig)(config, log);
81
80
  let output = config.output;
82
81
  if (!output) {
83
82
  if (typeof process === 'object') {
84
- process.stdout.write(fusiongraph + '\n');
83
+ process.stdout.write(supergraphSdl + '\n');
85
84
  }
86
85
  else {
87
- console.log(fusiongraph);
86
+ console.log(supergraphSdl);
88
87
  }
89
88
  log.info('Done!');
90
89
  return;
@@ -93,13 +92,13 @@ async function run({ log: rootLog = new utils_1.DefaultLogger(), productName = '
93
92
  output = (0, path_1.isAbsolute)(output) ? output : (0, path_1.join)(process.cwd(), output);
94
93
  let writtenData;
95
94
  if (output.endsWith('.json')) {
96
- writtenData = JSON.stringify((0, graphql_1.parse)(fusiongraph, { noLocation: true }), null, 2);
95
+ writtenData = JSON.stringify((0, graphql_1.parse)(supergraphSdl, { noLocation: true }), null, 2);
97
96
  }
98
97
  else if (output.endsWith('.graphql') ||
99
98
  output.endsWith('.gql') ||
100
99
  output.endsWith('.graphqls') ||
101
100
  output.endsWith('.gqls')) {
102
- writtenData = fusiongraph;
101
+ writtenData = supergraphSdl;
103
102
  }
104
103
  else if (output.endsWith('.ts') ||
105
104
  output.endsWith('.cts') ||
@@ -107,7 +106,7 @@ async function run({ log: rootLog = new utils_1.DefaultLogger(), productName = '
107
106
  output.endsWith('.js') ||
108
107
  output.endsWith('.cjs') ||
109
108
  output.endsWith('.mjs')) {
110
- writtenData = `export default ${JSON.stringify(fusiongraph)}`;
109
+ writtenData = `export default ${JSON.stringify(supergraphSdl)}`;
111
110
  }
112
111
  else {
113
112
  throw new Error(`Unsupported file extension for ${output}`);
@@ -115,4 +114,3 @@ async function run({ log: rootLog = new utils_1.DefaultLogger(), productName = '
115
114
  await fs_1.promises.writeFile(output, writtenData, 'utf8');
116
115
  log.info('Done!');
117
116
  }
118
- exports.run = run;
package/cjs/types.js CHANGED
@@ -1,10 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defineConfig = void 0;
3
+ exports.defineConfig = defineConfig;
4
4
  /**
5
5
  * Type helper for defining the config.
6
6
  */
7
7
  function defineConfig(config) {
8
8
  return config;
9
9
  }
10
- exports.defineConfig = defineConfig;
@@ -1,6 +1,9 @@
1
+ import { buildSchema, print } from 'graphql';
1
2
  import { composeSubgraphs } from '@graphql-mesh/fusion-composition';
2
3
  import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
3
4
  import { loadTypedefs } from '@graphql-tools/load';
5
+ import { mergeSchemas } from '@graphql-tools/schema';
6
+ import { printSchemaWithDirectives } from '@graphql-tools/utils';
4
7
  import { fetch as defaultFetch } from '@whatwg-node/fetch';
5
8
  export async function getComposedSchemaFromConfig(config, logger) {
6
9
  const ctx = {
@@ -17,7 +20,8 @@ export async function getComposedSchemaFromConfig(config, logger) {
17
20
  subgraphSchema = await schema$;
18
21
  }
19
22
  catch (e) {
20
- throw new Error(`Failed to load subgraph ${subgraphName} - ${e.stack}`);
23
+ log.error(`Failed to load subgraph ${subgraphName}`);
24
+ throw e;
21
25
  }
22
26
  return {
23
27
  name: subgraphName,
@@ -35,14 +39,41 @@ export async function getComposedSchemaFromConfig(config, logger) {
35
39
  });
36
40
  additionalTypeDefs = result.map(r => r.document || r.rawSDL);
37
41
  }
38
- let composedSchema = composeSubgraphs(subgraphConfigsForComposition, {
39
- typeDefs: additionalTypeDefs,
40
- });
41
- if (config.transforms?.length) {
42
- logger.info('Applying transforms');
43
- for (const transform of config.transforms) {
44
- composedSchema = transform(composedSchema);
42
+ const result = composeSubgraphs(subgraphConfigsForComposition);
43
+ if (result.errors?.length) {
44
+ throw new Error(`Failed to compose subgraphs; \n${result.errors.map(e => `- ${e.message}`).join('\n')}`);
45
+ }
46
+ if (config.subgraph) {
47
+ const subgraph = result.annotatedSubgraphs.find(sg => sg.name === config.subgraph);
48
+ if (!subgraph) {
49
+ throw new Error(`Subgraph ${config.subgraph} not found`);
50
+ }
51
+ return print(subgraph.typeDefs);
52
+ }
53
+ if (!result.supergraphSdl) {
54
+ throw new Error(`Unknown error: composed schema is empty`);
55
+ }
56
+ if (additionalTypeDefs?.length || config.transforms?.length) {
57
+ let composedSchema = buildSchema(result.supergraphSdl, {
58
+ noLocation: true,
59
+ assumeValid: true,
60
+ assumeValidSDL: true,
61
+ });
62
+ if (additionalTypeDefs?.length) {
63
+ composedSchema = mergeSchemas({
64
+ schemas: [composedSchema],
65
+ typeDefs: additionalTypeDefs,
66
+ assumeValid: true,
67
+ assumeValidSDL: true,
68
+ });
69
+ }
70
+ if (config.transforms?.length) {
71
+ logger.info('Applying transforms');
72
+ for (const transform of config.transforms) {
73
+ composedSchema = transform(composedSchema);
74
+ }
45
75
  }
76
+ return printSchemaWithDirectives(composedSchema);
46
77
  }
47
- return composedSchema;
78
+ return result.supergraphSdl;
48
79
  }
@@ -1,5 +1,5 @@
1
- import { buildClientSchema, buildSchema, getIntrospectionQuery, } from 'graphql';
2
- export function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, spec = false, transportKind = 'http', }) {
1
+ import { buildClientSchema, buildSchema, DirectiveLocation, getIntrospectionQuery, getNamedType, GraphQLDirective, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLSchema, GraphQLString, isObjectType, } from 'graphql';
2
+ export function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, federation = false, transportKind = 'http', }) {
3
3
  return (ctx) => {
4
4
  let schema$;
5
5
  function handleFetchedSchema(schema) {
@@ -7,7 +7,7 @@ export function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGET
7
7
  kind: transportKind,
8
8
  subgraph: subgraphName,
9
9
  location: endpoint,
10
- headers: operationHeaders,
10
+ headers: operationHeaders ? Object.entries(operationHeaders) : undefined,
11
11
  options: {
12
12
  method,
13
13
  useGETForQueries,
@@ -32,7 +32,7 @@ export function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGET
32
32
  kind: transportKind,
33
33
  subgraph: subgraphName,
34
34
  location: endpoint,
35
- headers: operationHeaders,
35
+ headers: operationHeaders ? Object.entries(operationHeaders) : undefined,
36
36
  options: {
37
37
  method,
38
38
  useGETForQueries,
@@ -43,50 +43,58 @@ export function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGET
43
43
  }, schema));
44
44
  }
45
45
  else {
46
- switch (spec) {
47
- case false:
48
- schema$ = ctx
49
- .fetch(endpoint, {
50
- method: method || (useGETForQueries ? 'GET' : 'POST'),
51
- headers: {
52
- 'Content-Type': 'application/json',
53
- },
54
- body: JSON.stringify({
55
- query: getIntrospectionQuery(),
56
- }),
57
- })
58
- .then(res => {
59
- assertResponseOk(res);
60
- return res.json();
61
- })
62
- .then((result) => buildClientSchema(result.data, {
63
- assumeValid: true,
64
- }));
65
- break;
66
- case 'federation':
67
- schema$ = ctx
68
- .fetch(endpoint, {
69
- method: method || (useGETForQueries ? 'GET' : 'POST'),
70
- headers: {
71
- 'Content-Type': 'application/json',
72
- },
73
- body: JSON.stringify({
74
- query: federationIntrospectionQuery,
75
- }),
76
- })
77
- .then(res => {
78
- assertResponseOk(res);
79
- return res.text();
80
- })
81
- .then(sdl => buildSchema(sdl, {
82
- assumeValidSDL: true,
83
- assumeValid: true,
84
- noLocation: true,
85
- }));
86
- break;
87
- default:
88
- throw new Error(`Unsupported spec: ${spec}`);
89
- }
46
+ const fetchAsRegular = () => ctx
47
+ .fetch(endpoint, {
48
+ method: method || (useGETForQueries ? 'GET' : 'POST'),
49
+ headers: {
50
+ 'Content-Type': 'application/json',
51
+ },
52
+ body: JSON.stringify({
53
+ query: getIntrospectionQuery(),
54
+ }),
55
+ })
56
+ .then(res => {
57
+ assertResponseOk(res);
58
+ return res.json();
59
+ })
60
+ .then((result) => buildClientSchema(result.data, {
61
+ assumeValid: true,
62
+ }))
63
+ .then(schema => {
64
+ const queryType = schema.getQueryType();
65
+ const queryFields = queryType?.getFields();
66
+ if (queryFields._service) {
67
+ const serviceType = getNamedType(queryFields._service.type);
68
+ if (isObjectType(serviceType)) {
69
+ const serviceTypeFields = serviceType.getFields();
70
+ if (serviceTypeFields.sdl) {
71
+ return fetchAsFederation();
72
+ }
73
+ }
74
+ }
75
+ return schema;
76
+ });
77
+ const fetchAsFederation = () => ctx
78
+ .fetch(endpoint, {
79
+ method: method || (useGETForQueries ? 'GET' : 'POST'),
80
+ headers: {
81
+ 'Content-Type': 'application/json',
82
+ },
83
+ body: JSON.stringify({
84
+ query: federationIntrospectionQuery,
85
+ }),
86
+ })
87
+ .then(res => {
88
+ assertResponseOk(res);
89
+ return res.json();
90
+ })
91
+ .then((result) => result?.data?._service?.sdl)
92
+ .then(sdl => buildSchema(sdl, {
93
+ assumeValidSDL: true,
94
+ assumeValid: true,
95
+ noLocation: true,
96
+ }));
97
+ schema$ = federation ? fetchAsFederation() : fetchAsRegular();
90
98
  }
91
99
  schema$ = schema$.then(handleFetchedSchema);
92
100
  return {
@@ -95,11 +103,27 @@ export function loadGraphQLHTTPSubgraph(subgraphName, { endpoint, method, useGET
95
103
  };
96
104
  };
97
105
  }
106
+ const transportDirective = new GraphQLDirective({
107
+ name: 'transport',
108
+ isRepeatable: true,
109
+ locations: [DirectiveLocation.SCHEMA],
110
+ args: {
111
+ kind: { type: new GraphQLNonNull(GraphQLString) },
112
+ subgraph: { type: new GraphQLNonNull(GraphQLString) },
113
+ location: { type: new GraphQLNonNull(GraphQLString) },
114
+ headers: { type: new GraphQLList(new GraphQLList(GraphQLString)) },
115
+ options: { type: new GraphQLScalarType({ name: 'TransportOptions' }) },
116
+ },
117
+ });
98
118
  function addAnnotations(transportEntry, schema) {
99
119
  const schemaExtensions = (schema.extensions ||= {});
100
120
  schemaExtensions.directives ||= {};
101
121
  schemaExtensions.directives.transport = transportEntry;
102
- return schema;
122
+ const schemaConfig = schema.toConfig();
123
+ return new GraphQLSchema({
124
+ ...schemaConfig,
125
+ directives: [...schemaConfig.directives, transportDirective],
126
+ });
103
127
  }
104
128
  const federationIntrospectionQuery = /* GraphQL */ `
105
129
  query GetFederationInfo {
package/esm/run.js CHANGED
@@ -8,12 +8,12 @@ import { isAbsolute, join, resolve } from 'path';
8
8
  import { parse } from 'graphql';
9
9
  import { Command, Option } from '@commander-js/extra-typings';
10
10
  import { DefaultLogger } from '@graphql-mesh/utils';
11
- import { printSchemaWithDirectives } from '@graphql-tools/utils';
12
11
  import { getComposedSchemaFromConfig } from './getComposedSchemaFromConfig.js';
13
12
  let program = new Command()
14
13
  .addOption(new Option('-c, --config-path <path>', 'path to the configuration file')
15
14
  .env('CONFIG_PATH')
16
15
  .default('mesh.config.ts'))
16
+ .option('--subgraph <name>', 'name of the subgraph to compose')
17
17
  .option('-o, --output <path>', 'path to the output file');
18
18
  export async function run({ log: rootLog = new DefaultLogger(), productName = 'Mesh Compose', productDescription = 'compose a GraphQL federated schema from any API service(s)', binName = 'mesh-compose', version, }) {
19
19
  program = program.name(binName).description(productDescription);
@@ -50,15 +50,14 @@ export async function run({ log: rootLog = new DefaultLogger(), productName = 'M
50
50
  ...opts,
51
51
  };
52
52
  log.info('Composing');
53
- const fusiongraphSchema = await getComposedSchemaFromConfig(config, log);
54
- const fusiongraph = printSchemaWithDirectives(fusiongraphSchema);
53
+ const supergraphSdl = await getComposedSchemaFromConfig(config, log);
55
54
  let output = config.output;
56
55
  if (!output) {
57
56
  if (typeof process === 'object') {
58
- process.stdout.write(fusiongraph + '\n');
57
+ process.stdout.write(supergraphSdl + '\n');
59
58
  }
60
59
  else {
61
- console.log(fusiongraph);
60
+ console.log(supergraphSdl);
62
61
  }
63
62
  log.info('Done!');
64
63
  return;
@@ -67,13 +66,13 @@ export async function run({ log: rootLog = new DefaultLogger(), productName = 'M
67
66
  output = isAbsolute(output) ? output : join(process.cwd(), output);
68
67
  let writtenData;
69
68
  if (output.endsWith('.json')) {
70
- writtenData = JSON.stringify(parse(fusiongraph, { noLocation: true }), null, 2);
69
+ writtenData = JSON.stringify(parse(supergraphSdl, { noLocation: true }), null, 2);
71
70
  }
72
71
  else if (output.endsWith('.graphql') ||
73
72
  output.endsWith('.gql') ||
74
73
  output.endsWith('.graphqls') ||
75
74
  output.endsWith('.gqls')) {
76
- writtenData = fusiongraph;
75
+ writtenData = supergraphSdl;
77
76
  }
78
77
  else if (output.endsWith('.ts') ||
79
78
  output.endsWith('.cts') ||
@@ -81,7 +80,7 @@ export async function run({ log: rootLog = new DefaultLogger(), productName = 'M
81
80
  output.endsWith('.js') ||
82
81
  output.endsWith('.cjs') ||
83
82
  output.endsWith('.mjs')) {
84
- writtenData = `export default ${JSON.stringify(fusiongraph)}`;
83
+ writtenData = `export default ${JSON.stringify(supergraphSdl)}`;
85
84
  }
86
85
  else {
87
86
  throw new Error(`Unsupported file extension for ${output}`);
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@graphql-mesh/compose-cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.1-alpha-20240626143434-7cd2ddcf1e46bd3f52ea1e6276c1d9beeb5171a4",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@graphql-mesh/types": "^0.98.8",
6
+ "@graphql-mesh/types": "0.98.9-alpha-20240626143434-7cd2ddcf1e46bd3f52ea1e6276c1d9beeb5171a4",
7
7
  "graphql": "*"
8
8
  },
9
9
  "dependencies": {
10
10
  "@commander-js/extra-typings": "^12.0.1",
11
- "@graphql-mesh/fusion-composition": "^0.0.6",
12
- "@graphql-mesh/utils": "^0.98.8",
11
+ "@graphql-mesh/fusion-composition": "0.0.7-alpha-20240626143434-7cd2ddcf1e46bd3f52ea1e6276c1d9beeb5171a4",
12
+ "@graphql-mesh/utils": "0.98.9-alpha-20240626143434-7cd2ddcf1e46bd3f52ea1e6276c1d9beeb5171a4",
13
13
  "@graphql-tools/graphql-file-loader": "8.0.1",
14
14
  "@graphql-tools/load": "^8.0.1",
15
+ "@graphql-tools/schema": "^10.0.4",
15
16
  "@graphql-tools/utils": "^10.2.1",
16
17
  "@whatwg-node/fetch": "^0.9.14",
17
18
  "commander": "^12.0.0",
@@ -1,4 +1,3 @@
1
- import { GraphQLSchema } from 'graphql';
2
1
  import { Logger } from '@graphql-mesh/types';
3
2
  import { MeshComposeCLIConfig } from './types.cjs';
4
- export declare function getComposedSchemaFromConfig(config: MeshComposeCLIConfig, logger: Logger): Promise<GraphQLSchema>;
3
+ export declare function getComposedSchemaFromConfig(config: MeshComposeCLIConfig, logger: Logger): Promise<string>;
@@ -1,4 +1,3 @@
1
- import { GraphQLSchema } from 'graphql';
2
1
  import { Logger } from '@graphql-mesh/types';
3
2
  import { MeshComposeCLIConfig } from './types.js';
4
- export declare function getComposedSchemaFromConfig(config: MeshComposeCLIConfig, logger: Logger): Promise<GraphQLSchema>;
3
+ export declare function getComposedSchemaFromConfig(config: MeshComposeCLIConfig, logger: Logger): Promise<string>;
@@ -45,11 +45,11 @@ export interface GraphQLSubgraphLoaderHTTPConfiguration {
45
45
  */
46
46
  schemaHeaders?: any;
47
47
  /**
48
- * Subgraph spec
48
+ * Federation Subgraph
49
49
  *
50
50
  * @default false
51
51
  */
52
- spec?: 'federation' | 'stitching' | 'fusion' | false;
52
+ federation?: boolean;
53
53
  /**
54
54
  * Transport kind
55
55
  *
@@ -57,4 +57,4 @@ export interface GraphQLSubgraphLoaderHTTPConfiguration {
57
57
  */
58
58
  transportKind?: 'http';
59
59
  }
60
- export declare function loadGraphQLHTTPSubgraph(subgraphName: string, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, spec, transportKind, }: GraphQLSubgraphLoaderHTTPConfiguration): MeshComposeCLISourceHandlerDef;
60
+ export declare function loadGraphQLHTTPSubgraph(subgraphName: string, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, federation, transportKind, }: GraphQLSubgraphLoaderHTTPConfiguration): MeshComposeCLISourceHandlerDef;
@@ -45,11 +45,11 @@ export interface GraphQLSubgraphLoaderHTTPConfiguration {
45
45
  */
46
46
  schemaHeaders?: any;
47
47
  /**
48
- * Subgraph spec
48
+ * Federation Subgraph
49
49
  *
50
50
  * @default false
51
51
  */
52
- spec?: 'federation' | 'stitching' | 'fusion' | false;
52
+ federation?: boolean;
53
53
  /**
54
54
  * Transport kind
55
55
  *
@@ -57,4 +57,4 @@ export interface GraphQLSubgraphLoaderHTTPConfiguration {
57
57
  */
58
58
  transportKind?: 'http';
59
59
  }
60
- export declare function loadGraphQLHTTPSubgraph(subgraphName: string, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, spec, transportKind, }: GraphQLSubgraphLoaderHTTPConfiguration): MeshComposeCLISourceHandlerDef;
60
+ export declare function loadGraphQLHTTPSubgraph(subgraphName: string, { endpoint, method, useGETForQueries, operationHeaders, credentials, retry, timeout, source, schemaHeaders, federation, transportKind, }: GraphQLSubgraphLoaderHTTPConfiguration): MeshComposeCLISourceHandlerDef;
package/typings/run.d.cts CHANGED
@@ -5,6 +5,7 @@ import { Command } from '@commander-js/extra-typings';
5
5
  import { Logger } from '@graphql-mesh/types';
6
6
  declare let program: Command<[], {
7
7
  configPath?: string;
8
+ subgraph?: string;
8
9
  output?: string;
9
10
  }>;
10
11
  export interface RunOptions extends ReturnType<typeof program.opts> {
package/typings/run.d.ts CHANGED
@@ -5,6 +5,7 @@ import { Command } from '@commander-js/extra-typings';
5
5
  import { Logger } from '@graphql-mesh/types';
6
6
  declare let program: Command<[], {
7
7
  configPath?: string;
8
+ subgraph?: string;
8
9
  output?: string;
9
10
  }>;
10
11
  export interface RunOptions extends ReturnType<typeof program.opts> {
@@ -1,7 +1,8 @@
1
1
  import { DocumentNode, GraphQLSchema } from 'graphql';
2
2
  import { Logger } from '@graphql-mesh/types';
3
3
  import { fetch as defaultFetch } from '@whatwg-node/fetch';
4
- export interface MeshComposeCLIConfig {
4
+ import { ComposeSubgraphsOptions } from '@graphql-mesh/fusion-composition';
5
+ export interface MeshComposeCLIConfig extends ComposeSubgraphsOptions {
5
6
  /**
6
7
  * The output destination of the resulting composed GraphQL schema.
7
8
  * By default, the CLI will write the result to stdout.
@@ -10,6 +11,7 @@ export interface MeshComposeCLIConfig {
10
11
  subgraphs: MeshComposeCLISubgraphConfig[];
11
12
  transforms?: MeshComposeCLITransformConfig[];
12
13
  additionalTypeDefs?: string | DocumentNode | (string | DocumentNode)[];
14
+ subgraph?: string;
13
15
  fetch?: typeof defaultFetch;
14
16
  cwd?: string;
15
17
  }
@@ -1,7 +1,8 @@
1
1
  import { DocumentNode, GraphQLSchema } from 'graphql';
2
2
  import { Logger } from '@graphql-mesh/types';
3
3
  import { fetch as defaultFetch } from '@whatwg-node/fetch';
4
- export interface MeshComposeCLIConfig {
4
+ import { ComposeSubgraphsOptions } from '@graphql-mesh/fusion-composition';
5
+ export interface MeshComposeCLIConfig extends ComposeSubgraphsOptions {
5
6
  /**
6
7
  * The output destination of the resulting composed GraphQL schema.
7
8
  * By default, the CLI will write the result to stdout.
@@ -10,6 +11,7 @@ export interface MeshComposeCLIConfig {
10
11
  subgraphs: MeshComposeCLISubgraphConfig[];
11
12
  transforms?: MeshComposeCLITransformConfig[];
12
13
  additionalTypeDefs?: string | DocumentNode | (string | DocumentNode)[];
14
+ subgraph?: string;
13
15
  fetch?: typeof defaultFetch;
14
16
  cwd?: string;
15
17
  }