print-schema-with-directives.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.makeDirectiveNodes = exports.makeDirectiveNode = exports.makeDeprecatedDirective = exports.astFromEnumValue = exports.astFromInputField = exports.astFromField = exports.astFromScalarType = exports.astFromEnumType = exports.astFromInputObjectType = exports.astFromUnionType = exports.astFromInterfaceType = exports.astFromObjectType = exports.astFromArg = exports.getDeprecatableDirectiveNodes = exports.getDirectiveNodes = exports.astFromDirective = exports.astFromSchema = exports.printSchemaWithDirectives = exports.getDocumentNodeFromSchema = void 0;
  4. const graphql_1 = require("graphql");
  5. const astFromType_js_1 = require("./astFromType.js");
  6. const get_directives_js_1 = require("./get-directives.js");
  7. const astFromValueUntyped_js_1 = require("./astFromValueUntyped.js");
  8. const helpers_js_1 = require("./helpers.js");
  9. const rootTypes_js_1 = require("./rootTypes.js");
  10. function getDocumentNodeFromSchema(schema, options = {}) {
  11. const pathToDirectivesInExtensions = options.pathToDirectivesInExtensions;
  12. const typesMap = schema.getTypeMap();
  13. const schemaNode = astFromSchema(schema, pathToDirectivesInExtensions);
  14. const definitions = schemaNode != null ? [schemaNode] : [];
  15. const directives = schema.getDirectives();
  16. for (const directive of directives) {
  17. if ((0, graphql_1.isSpecifiedDirective)(directive)) {
  18. continue;
  19. }
  20. definitions.push(astFromDirective(directive, schema, pathToDirectivesInExtensions));
  21. }
  22. for (const typeName in typesMap) {
  23. const type = typesMap[typeName];
  24. const isPredefinedScalar = (0, graphql_1.isSpecifiedScalarType)(type);
  25. const isIntrospection = (0, graphql_1.isIntrospectionType)(type);
  26. if (isPredefinedScalar || isIntrospection) {
  27. continue;
  28. }
  29. if ((0, graphql_1.isObjectType)(type)) {
  30. definitions.push(astFromObjectType(type, schema, pathToDirectivesInExtensions));
  31. }
  32. else if ((0, graphql_1.isInterfaceType)(type)) {
  33. definitions.push(astFromInterfaceType(type, schema, pathToDirectivesInExtensions));
  34. }
  35. else if ((0, graphql_1.isUnionType)(type)) {
  36. definitions.push(astFromUnionType(type, schema, pathToDirectivesInExtensions));
  37. }
  38. else if ((0, graphql_1.isInputObjectType)(type)) {
  39. definitions.push(astFromInputObjectType(type, schema, pathToDirectivesInExtensions));
  40. }
  41. else if ((0, graphql_1.isEnumType)(type)) {
  42. definitions.push(astFromEnumType(type, schema, pathToDirectivesInExtensions));
  43. }
  44. else if ((0, graphql_1.isScalarType)(type)) {
  45. definitions.push(astFromScalarType(type, schema, pathToDirectivesInExtensions));
  46. }
  47. else {
  48. throw new Error(`Unknown type ${type}.`);
  49. }
  50. }
  51. return {
  52. kind: graphql_1.Kind.DOCUMENT,
  53. definitions,
  54. };
  55. }
  56. exports.getDocumentNodeFromSchema = getDocumentNodeFromSchema;
  57. // this approach uses the default schema printer rather than a custom solution, so may be more backwards compatible
  58. // currently does not allow customization of printSchema options having to do with comments.
  59. function printSchemaWithDirectives(schema, options = {}) {
  60. const documentNode = getDocumentNodeFromSchema(schema, options);
  61. return (0, graphql_1.print)(documentNode);
  62. }
  63. exports.printSchemaWithDirectives = printSchemaWithDirectives;
  64. function astFromSchema(schema, pathToDirectivesInExtensions) {
  65. var _a, _b;
  66. const operationTypeMap = new Map([
  67. ['query', undefined],
  68. ['mutation', undefined],
  69. ['subscription', undefined],
  70. ]);
  71. const nodes = [];
  72. if (schema.astNode != null) {
  73. nodes.push(schema.astNode);
  74. }
  75. if (schema.extensionASTNodes != null) {
  76. for (const extensionASTNode of schema.extensionASTNodes) {
  77. nodes.push(extensionASTNode);
  78. }
  79. }
  80. for (const node of nodes) {
  81. if (node.operationTypes) {
  82. for (const operationTypeDefinitionNode of node.operationTypes) {
  83. operationTypeMap.set(operationTypeDefinitionNode.operation, operationTypeDefinitionNode);
  84. }
  85. }
  86. }
  87. const rootTypeMap = (0, rootTypes_js_1.getRootTypeMap)(schema);
  88. for (const [operationTypeNode, operationTypeDefinitionNode] of operationTypeMap) {
  89. const rootType = rootTypeMap.get(operationTypeNode);
  90. if (rootType != null) {
  91. const rootTypeAST = (0, astFromType_js_1.astFromType)(rootType);
  92. if (operationTypeDefinitionNode != null) {
  93. operationTypeDefinitionNode.type = rootTypeAST;
  94. }
  95. else {
  96. operationTypeMap.set(operationTypeNode, {
  97. kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
  98. operation: operationTypeNode,
  99. type: rootTypeAST,
  100. });
  101. }
  102. }
  103. }
  104. const operationTypes = [...operationTypeMap.values()].filter(helpers_js_1.isSome);
  105. const directives = getDirectiveNodes(schema, schema, pathToDirectivesInExtensions);
  106. if (!operationTypes.length && !directives.length) {
  107. return null;
  108. }
  109. const schemaNode = {
  110. kind: operationTypes != null ? graphql_1.Kind.SCHEMA_DEFINITION : graphql_1.Kind.SCHEMA_EXTENSION,
  111. operationTypes,
  112. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  113. directives: directives,
  114. };
  115. // This code is so weird because it needs to support GraphQL.js 14
  116. // In GraphQL.js 14 there is no `description` value on schemaNode
  117. schemaNode.description =
  118. ((_b = (_a = schema.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : schema.description != null)
  119. ? {
  120. kind: graphql_1.Kind.STRING,
  121. value: schema.description,
  122. block: true,
  123. }
  124. : undefined;
  125. return schemaNode;
  126. }
  127. exports.astFromSchema = astFromSchema;
  128. function astFromDirective(directive, schema, pathToDirectivesInExtensions) {
  129. var _a, _b, _c, _d;
  130. return {
  131. kind: graphql_1.Kind.DIRECTIVE_DEFINITION,
  132. description: (_b = (_a = directive.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (directive.description
  133. ? {
  134. kind: graphql_1.Kind.STRING,
  135. value: directive.description,
  136. }
  137. : undefined),
  138. name: {
  139. kind: graphql_1.Kind.NAME,
  140. value: directive.name,
  141. },
  142. arguments: (_c = directive.args) === null || _c === void 0 ? void 0 : _c.map(arg => astFromArg(arg, schema, pathToDirectivesInExtensions)),
  143. repeatable: directive.isRepeatable,
  144. locations: ((_d = directive.locations) === null || _d === void 0 ? void 0 : _d.map(location => ({
  145. kind: graphql_1.Kind.NAME,
  146. value: location,
  147. }))) || [],
  148. };
  149. }
  150. exports.astFromDirective = astFromDirective;
  151. function getDirectiveNodes(entity, schema, pathToDirectivesInExtensions) {
  152. const directivesInExtensions = (0, get_directives_js_1.getDirectivesInExtensions)(entity, pathToDirectivesInExtensions);
  153. let nodes = [];
  154. if (entity.astNode != null) {
  155. nodes.push(entity.astNode);
  156. }
  157. if ('extensionASTNodes' in entity && entity.extensionASTNodes != null) {
  158. nodes = nodes.concat(entity.extensionASTNodes);
  159. }
  160. let directives;
  161. if (directivesInExtensions != null) {
  162. directives = makeDirectiveNodes(schema, directivesInExtensions);
  163. }
  164. else {
  165. directives = [];
  166. for (const node of nodes) {
  167. if (node.directives) {
  168. directives.push(...node.directives);
  169. }
  170. }
  171. }
  172. return directives;
  173. }
  174. exports.getDirectiveNodes = getDirectiveNodes;
  175. function getDeprecatableDirectiveNodes(entity, schema, pathToDirectivesInExtensions) {
  176. var _a, _b;
  177. let directiveNodesBesidesDeprecated = [];
  178. let deprecatedDirectiveNode = null;
  179. const directivesInExtensions = (0, get_directives_js_1.getDirectivesInExtensions)(entity, pathToDirectivesInExtensions);
  180. let directives;
  181. if (directivesInExtensions != null) {
  182. directives = makeDirectiveNodes(schema, directivesInExtensions);
  183. }
  184. else {
  185. directives = (_a = entity.astNode) === null || _a === void 0 ? void 0 : _a.directives;
  186. }
  187. if (directives != null) {
  188. directiveNodesBesidesDeprecated = directives.filter(directive => directive.name.value !== 'deprecated');
  189. if (entity.deprecationReason != null) {
  190. deprecatedDirectiveNode = (_b = directives.filter(directive => directive.name.value === 'deprecated')) === null || _b === void 0 ? void 0 : _b[0];
  191. }
  192. }
  193. if (entity.deprecationReason != null &&
  194. deprecatedDirectiveNode == null) {
  195. deprecatedDirectiveNode = makeDeprecatedDirective(entity.deprecationReason);
  196. }
  197. return deprecatedDirectiveNode == null
  198. ? directiveNodesBesidesDeprecated
  199. : [deprecatedDirectiveNode].concat(directiveNodesBesidesDeprecated);
  200. }
  201. exports.getDeprecatableDirectiveNodes = getDeprecatableDirectiveNodes;
  202. function astFromArg(arg, schema, pathToDirectivesInExtensions) {
  203. var _a, _b, _c;
  204. return {
  205. kind: graphql_1.Kind.INPUT_VALUE_DEFINITION,
  206. description: (_b = (_a = arg.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (arg.description
  207. ? {
  208. kind: graphql_1.Kind.STRING,
  209. value: arg.description,
  210. block: true,
  211. }
  212. : undefined),
  213. name: {
  214. kind: graphql_1.Kind.NAME,
  215. value: arg.name,
  216. },
  217. type: (0, astFromType_js_1.astFromType)(arg.type),
  218. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  219. defaultValue: arg.defaultValue !== undefined ? (_c = (0, graphql_1.astFromValue)(arg.defaultValue, arg.type)) !== null && _c !== void 0 ? _c : undefined : undefined,
  220. directives: getDeprecatableDirectiveNodes(arg, schema, pathToDirectivesInExtensions),
  221. };
  222. }
  223. exports.astFromArg = astFromArg;
  224. function astFromObjectType(type, schema, pathToDirectivesInExtensions) {
  225. var _a, _b;
  226. return {
  227. kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
  228. description: (_b = (_a = type.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (type.description
  229. ? {
  230. kind: graphql_1.Kind.STRING,
  231. value: type.description,
  232. block: true,
  233. }
  234. : undefined),
  235. name: {
  236. kind: graphql_1.Kind.NAME,
  237. value: type.name,
  238. },
  239. fields: Object.values(type.getFields()).map(field => astFromField(field, schema, pathToDirectivesInExtensions)),
  240. interfaces: Object.values(type.getInterfaces()).map(iFace => (0, astFromType_js_1.astFromType)(iFace)),
  241. directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
  242. };
  243. }
  244. exports.astFromObjectType = astFromObjectType;
  245. function astFromInterfaceType(type, schema, pathToDirectivesInExtensions) {
  246. var _a, _b;
  247. const node = {
  248. kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
  249. description: (_b = (_a = type.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (type.description
  250. ? {
  251. kind: graphql_1.Kind.STRING,
  252. value: type.description,
  253. block: true,
  254. }
  255. : undefined),
  256. name: {
  257. kind: graphql_1.Kind.NAME,
  258. value: type.name,
  259. },
  260. fields: Object.values(type.getFields()).map(field => astFromField(field, schema, pathToDirectivesInExtensions)),
  261. directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
  262. };
  263. if ('getInterfaces' in type) {
  264. node.interfaces = Object.values(type.getInterfaces()).map(iFace => (0, astFromType_js_1.astFromType)(iFace));
  265. }
  266. return node;
  267. }
  268. exports.astFromInterfaceType = astFromInterfaceType;
  269. function astFromUnionType(type, schema, pathToDirectivesInExtensions) {
  270. var _a, _b;
  271. return {
  272. kind: graphql_1.Kind.UNION_TYPE_DEFINITION,
  273. description: (_b = (_a = type.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (type.description
  274. ? {
  275. kind: graphql_1.Kind.STRING,
  276. value: type.description,
  277. block: true,
  278. }
  279. : undefined),
  280. name: {
  281. kind: graphql_1.Kind.NAME,
  282. value: type.name,
  283. },
  284. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  285. directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
  286. types: type.getTypes().map(type => (0, astFromType_js_1.astFromType)(type)),
  287. };
  288. }
  289. exports.astFromUnionType = astFromUnionType;
  290. function astFromInputObjectType(type, schema, pathToDirectivesInExtensions) {
  291. var _a, _b;
  292. return {
  293. kind: graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION,
  294. description: (_b = (_a = type.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (type.description
  295. ? {
  296. kind: graphql_1.Kind.STRING,
  297. value: type.description,
  298. block: true,
  299. }
  300. : undefined),
  301. name: {
  302. kind: graphql_1.Kind.NAME,
  303. value: type.name,
  304. },
  305. fields: Object.values(type.getFields()).map(field => astFromInputField(field, schema, pathToDirectivesInExtensions)),
  306. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  307. directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
  308. };
  309. }
  310. exports.astFromInputObjectType = astFromInputObjectType;
  311. function astFromEnumType(type, schema, pathToDirectivesInExtensions) {
  312. var _a, _b;
  313. return {
  314. kind: graphql_1.Kind.ENUM_TYPE_DEFINITION,
  315. description: (_b = (_a = type.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (type.description
  316. ? {
  317. kind: graphql_1.Kind.STRING,
  318. value: type.description,
  319. block: true,
  320. }
  321. : undefined),
  322. name: {
  323. kind: graphql_1.Kind.NAME,
  324. value: type.name,
  325. },
  326. values: Object.values(type.getValues()).map(value => astFromEnumValue(value, schema, pathToDirectivesInExtensions)),
  327. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  328. directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
  329. };
  330. }
  331. exports.astFromEnumType = astFromEnumType;
  332. function astFromScalarType(type, schema, pathToDirectivesInExtensions) {
  333. var _a, _b, _c;
  334. const directivesInExtensions = (0, get_directives_js_1.getDirectivesInExtensions)(type, pathToDirectivesInExtensions);
  335. const directives = directivesInExtensions
  336. ? makeDirectiveNodes(schema, directivesInExtensions)
  337. : ((_a = type.astNode) === null || _a === void 0 ? void 0 : _a.directives) || [];
  338. const specifiedByValue = (type['specifiedByUrl'] || type['specifiedByURL']);
  339. if (specifiedByValue && !directives.some(directiveNode => directiveNode.name.value === 'specifiedBy')) {
  340. const specifiedByArgs = {
  341. url: specifiedByValue,
  342. };
  343. directives.push(makeDirectiveNode('specifiedBy', specifiedByArgs));
  344. }
  345. return {
  346. kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
  347. description: (_c = (_b = type.astNode) === null || _b === void 0 ? void 0 : _b.description) !== null && _c !== void 0 ? _c : (type.description
  348. ? {
  349. kind: graphql_1.Kind.STRING,
  350. value: type.description,
  351. block: true,
  352. }
  353. : undefined),
  354. name: {
  355. kind: graphql_1.Kind.NAME,
  356. value: type.name,
  357. },
  358. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  359. directives: directives,
  360. };
  361. }
  362. exports.astFromScalarType = astFromScalarType;
  363. function astFromField(field, schema, pathToDirectivesInExtensions) {
  364. var _a, _b;
  365. return {
  366. kind: graphql_1.Kind.FIELD_DEFINITION,
  367. description: (_b = (_a = field.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (field.description
  368. ? {
  369. kind: graphql_1.Kind.STRING,
  370. value: field.description,
  371. block: true,
  372. }
  373. : undefined),
  374. name: {
  375. kind: graphql_1.Kind.NAME,
  376. value: field.name,
  377. },
  378. arguments: field.args.map(arg => astFromArg(arg, schema, pathToDirectivesInExtensions)),
  379. type: (0, astFromType_js_1.astFromType)(field.type),
  380. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  381. directives: getDeprecatableDirectiveNodes(field, schema, pathToDirectivesInExtensions),
  382. };
  383. }
  384. exports.astFromField = astFromField;
  385. function astFromInputField(field, schema, pathToDirectivesInExtensions) {
  386. var _a, _b, _c;
  387. return {
  388. kind: graphql_1.Kind.INPUT_VALUE_DEFINITION,
  389. description: (_b = (_a = field.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (field.description
  390. ? {
  391. kind: graphql_1.Kind.STRING,
  392. value: field.description,
  393. block: true,
  394. }
  395. : undefined),
  396. name: {
  397. kind: graphql_1.Kind.NAME,
  398. value: field.name,
  399. },
  400. type: (0, astFromType_js_1.astFromType)(field.type),
  401. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  402. directives: getDeprecatableDirectiveNodes(field, schema, pathToDirectivesInExtensions),
  403. defaultValue: (_c = (0, graphql_1.astFromValue)(field.defaultValue, field.type)) !== null && _c !== void 0 ? _c : undefined,
  404. };
  405. }
  406. exports.astFromInputField = astFromInputField;
  407. function astFromEnumValue(value, schema, pathToDirectivesInExtensions) {
  408. var _a, _b;
  409. return {
  410. kind: graphql_1.Kind.ENUM_VALUE_DEFINITION,
  411. description: (_b = (_a = value.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : (value.description
  412. ? {
  413. kind: graphql_1.Kind.STRING,
  414. value: value.description,
  415. block: true,
  416. }
  417. : undefined),
  418. name: {
  419. kind: graphql_1.Kind.NAME,
  420. value: value.name,
  421. },
  422. // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
  423. directives: getDeprecatableDirectiveNodes(value, schema, pathToDirectivesInExtensions),
  424. };
  425. }
  426. exports.astFromEnumValue = astFromEnumValue;
  427. function makeDeprecatedDirective(deprecationReason) {
  428. return makeDirectiveNode('deprecated', { reason: deprecationReason }, graphql_1.GraphQLDeprecatedDirective);
  429. }
  430. exports.makeDeprecatedDirective = makeDeprecatedDirective;
  431. function makeDirectiveNode(name, args, directive) {
  432. const directiveArguments = [];
  433. if (directive != null) {
  434. for (const arg of directive.args) {
  435. const argName = arg.name;
  436. const argValue = args[argName];
  437. if (argValue !== undefined) {
  438. const value = (0, graphql_1.astFromValue)(argValue, arg.type);
  439. if (value) {
  440. directiveArguments.push({
  441. kind: graphql_1.Kind.ARGUMENT,
  442. name: {
  443. kind: graphql_1.Kind.NAME,
  444. value: argName,
  445. },
  446. value,
  447. });
  448. }
  449. }
  450. }
  451. }
  452. else {
  453. for (const argName in args) {
  454. const argValue = args[argName];
  455. const value = (0, astFromValueUntyped_js_1.astFromValueUntyped)(argValue);
  456. if (value) {
  457. directiveArguments.push({
  458. kind: graphql_1.Kind.ARGUMENT,
  459. name: {
  460. kind: graphql_1.Kind.NAME,
  461. value: argName,
  462. },
  463. value,
  464. });
  465. }
  466. }
  467. }
  468. return {
  469. kind: graphql_1.Kind.DIRECTIVE,
  470. name: {
  471. kind: graphql_1.Kind.NAME,
  472. value: name,
  473. },
  474. arguments: directiveArguments,
  475. };
  476. }
  477. exports.makeDirectiveNode = makeDirectiveNode;
  478. function makeDirectiveNodes(schema, directiveValues) {
  479. const directiveNodes = [];
  480. for (const directiveName in directiveValues) {
  481. const arrayOrSingleValue = directiveValues[directiveName];
  482. const directive = schema === null || schema === void 0 ? void 0 : schema.getDirective(directiveName);
  483. if (Array.isArray(arrayOrSingleValue)) {
  484. for (const value of arrayOrSingleValue) {
  485. directiveNodes.push(makeDirectiveNode(directiveName, value, directive));
  486. }
  487. }
  488. else {
  489. directiveNodes.push(makeDirectiveNode(directiveName, arrayOrSingleValue, directive));
  490. }
  491. }
  492. return directiveNodes;
  493. }
  494. exports.makeDirectiveNodes = makeDirectiveNodes;