/ utils / fetchGqlSchema.ts
fetchGqlSchema.ts
 1  import fs from 'node:fs/promises';
 2  import path from 'node:path';
 3  import { inspect } from 'node:util';
 4  import {
 5  	type ExecutionResult,
 6  	type IntrospectionQuery,
 7  	assertValidSchema,
 8  	buildClientSchema,
 9  	getIntrospectionQuery,
10  } from 'graphql';
11  import type { ObjMap } from 'graphql/jsutils/ObjMap';
12  import type { GraphQLProjectConfig } from 'graphql-config';
13  
14  import { commentsProject } from './gqlCodegen';
15  
16  (async () => {
17  	if (!process.env.VITE_COUB_COMMENTS_ORIGIN) {
18  		throw new Error('`process.env.VITE_COUB_COMMENTS_ORIGIN` is missing');
19  	}
20  	const schemaPath = getSchemaPath(commentsProject.schema);
21  
22  	const response = await fetch(`${process.env.VITE_COUB_COMMENTS_ORIGIN}/graphql`, {
23  		method: 'POST',
24  		headers: { 'Content-Type': 'application/json' },
25  		body: JSON.stringify({
26  			query: getIntrospectionQuery(),
27  		}),
28  	});
29  
30  	const data = validateResponse((await response.json()) as ExecutionResult<IntrospectionQuery>);
31  
32  	assertValidSchema(buildClientSchema(data.data));
33  
34  	await fs.mkdir(path.dirname(schemaPath), { recursive: true });
35  	await fs.writeFile(schemaPath, JSON.stringify(data, null, 2), { encoding: 'utf8' });
36  
37  	console.log('wrote', path.resolve(schemaPath));
38  })().catch(err => {
39  	console.error(err);
40  	process.exit(1);
41  });
42  
43  // helpers
44  
45  interface SuccessfulExecutionResult<TData, TExtensions = ObjMap<unknown>>
46  	extends ExecutionResult<TData, TExtensions> {
47  	errors?: never;
48  	data: TData;
49  	extensions?: TExtensions;
50  }
51  
52  function validateResponse<TData, TExtensions = ObjMap<unknown>>(
53  	data: ExecutionResult<TData, TExtensions>,
54  ): SuccessfulExecutionResult<TData, TExtensions> {
55  	if (Array.isArray(data.errors)) {
56  		// eslint-disable-next-line @typescript-eslint/no-throw-literal
57  		throw data.errors;
58  	}
59  
60  	return data as SuccessfulExecutionResult<TData, TExtensions>;
61  }
62  
63  function getSchemaPath(schema: GraphQLProjectConfig['schema']): string {
64  	if (Array.isArray(schema) && typeof schema[0] === 'string') {
65  		return schema[0];
66  	}
67  
68  	if (typeof schema === 'string') {
69  		return schema;
70  	}
71  
72  	throw new TypeError(`expected schema path to be a string: ${inspect(schema)}`);
73  }