generate-graphql-types.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import { spawn } from 'child_process';
  2. import * as fs from 'fs';
  3. import { API_PATH, API_PORT } from './shared/shared-constants';
  4. // tslint:disable:no-console
  5. const API_URL = `http://localhost:${API_PORT}/${API_PATH}`;
  6. const SCHEMA_JSON_FILE = './schema.json';
  7. const CLIENT_SCHEMA_FILES = './admin-ui/src/app/data/types/client-types.graphql';
  8. const CLIENT_QUERY_FILES = '"./admin-ui/src/app/data/{queries,mutations,fragments}/**/*.ts"';
  9. const TYPESCRIPT_DEFINITIONS_FILE = './shared/generated-types.ts';
  10. main().catch(e => {
  11. console.log('Could not generate types!', e);
  12. process.exitCode = 1;
  13. });
  14. /**
  15. * This script uses apollo-codegen to generate TypeScript interfaces for all
  16. * GraphQL queries defined in the admin-ui app. Run it via the package.json
  17. * script "generate-gql-types".
  18. */
  19. async function main(): Promise<void> {
  20. try {
  21. await downloadSchemaFromApi(API_URL, SCHEMA_JSON_FILE);
  22. } catch {
  23. console.log('Could not connect to Vendure server. Attempting to build typed from existing schema.json');
  24. }
  25. await generateTypeScriptTypesFromSchema(
  26. SCHEMA_JSON_FILE,
  27. CLIENT_SCHEMA_FILES,
  28. CLIENT_QUERY_FILES,
  29. TYPESCRIPT_DEFINITIONS_FILE,
  30. );
  31. }
  32. /**
  33. * Downloads the schema from the provided GraphQL endpoint using the `apollo schema:download`
  34. * cli command and returns the result as an IntrospectionQuery object.
  35. */
  36. async function downloadSchemaFromApi(apiEndpoint: string, outputFile: string): Promise<void> {
  37. console.log(`Downloading schema from ${API_URL}`);
  38. const TEMP_API_SCHEMA = '../schema.temp.json';
  39. await runCommand('yarn', ['apollo', 'schema:download', TEMP_API_SCHEMA, `--endpoint=${API_URL}`]);
  40. console.log(`Downloaded schema from ${API_URL}`);
  41. const schemaFromApi = fs.readFileSync(TEMP_API_SCHEMA, { encoding: 'utf8' });
  42. fs.unlinkSync(TEMP_API_SCHEMA);
  43. const introspectionSchema = JSON.parse(schemaFromApi);
  44. fs.writeFileSync(
  45. SCHEMA_JSON_FILE,
  46. JSON.stringify({
  47. __schema: introspectionSchema,
  48. }),
  49. );
  50. }
  51. /**
  52. * Generates TypeScript definitions from the provided schema json file sing the `apollo codegen:generate` cli command.
  53. */
  54. async function generateTypeScriptTypesFromSchema(
  55. schemaFile: string,
  56. clientSchemaFiles: string,
  57. queryFiles: string,
  58. outputFile: string,
  59. ): Promise<number> {
  60. return runCommand('yarn', [
  61. 'apollo',
  62. 'codegen:generate',
  63. outputFile,
  64. '--addTypename',
  65. '--outputFlat',
  66. '--target=typescript',
  67. `--clientSchema=${clientSchemaFiles}`,
  68. `--queries=${queryFiles}`,
  69. `--schema=${schemaFile}`,
  70. ]);
  71. }
  72. /**
  73. * Runs a command-line command and resolves when completed.
  74. */
  75. function runCommand(command: string, args: string[]): Promise<number> {
  76. return new Promise((resolve, reject) => {
  77. const cp = spawn(command, args, { shell: true });
  78. cp.on('error', reject);
  79. cp.stdout.on('data', data => {
  80. if (4 < data.length) {
  81. console.log(`${data}`);
  82. }
  83. });
  84. cp.stderr.on('data', data => {
  85. if (4 < data.length) {
  86. console.log(`${data}`);
  87. }
  88. });
  89. cp.on('close', code => {
  90. if (code !== 0) {
  91. reject(code);
  92. }
  93. resolve(code);
  94. });
  95. });
  96. }