1 | import { addResolversToSchema } from '@graphql-tools/schema';
|
2 | import { composeResolvers } from '@graphql-tools/resolvers-composition';
|
3 | import { join, isAbsolute } from 'path';
|
4 | import { pathExists, ensureFile, writeJSON } from 'fs-extra';
|
5 | import objectHash from 'object-hash';
|
6 | import { extractResolvers } from '@graphql-mesh/utils';
|
7 |
|
8 | function computeSnapshotFilePath(options) {
|
9 | const argsHash = objectHash(options.args, { ignoreUnknown: true });
|
10 | const fileName = [options.typeName, options.fieldName, argsHash].join('_') + '.json';
|
11 | const absoluteOutputDir = isAbsolute(options.outputDir) ? options.outputDir : join(process.cwd(), options.outputDir);
|
12 | return join(absoluteOutputDir, fileName);
|
13 | }
|
14 |
|
15 | const writeFile = async (path, json) => {
|
16 | try {
|
17 | await ensureFile(path);
|
18 | await writeJSON(path, json, {
|
19 | spaces: 2,
|
20 | });
|
21 | }
|
22 | catch (e) {
|
23 | console.error(`Snapshot cannot saved to ${path}: ${e.message}`);
|
24 | }
|
25 | };
|
26 | class SnapshotTransform {
|
27 | constructor(options) {
|
28 | this.options = options;
|
29 | this.noWrap = true;
|
30 | }
|
31 | transformSchema(schema) {
|
32 | const { config } = this.options;
|
33 |
|
34 | const configIf = 'if' in config ? (typeof config.if === 'boolean' ? config.if : config.if && eval(config.if)) : true;
|
35 | if (configIf) {
|
36 | const resolvers = extractResolvers(schema);
|
37 | const resolversComposition = {};
|
38 | const outputDir = isAbsolute(config.outputDir) ? config.outputDir : join(process.cwd(), config.outputDir);
|
39 | const snapshotComposition = next => async (root, args, context, info) => {
|
40 | const snapshotFilePath = computeSnapshotFilePath({
|
41 | typeName: info.parentType.name,
|
42 | fieldName: info.fieldName,
|
43 | args,
|
44 | outputDir,
|
45 | });
|
46 | if (snapshotFilePath in require.cache || (await pathExists(snapshotFilePath))) {
|
47 | return import(snapshotFilePath);
|
48 | }
|
49 | const result = await next(root, args, context, info);
|
50 | await writeFile(snapshotFilePath, result);
|
51 | return result;
|
52 | };
|
53 | for (const field of config.apply) {
|
54 | resolversComposition[field] = snapshotComposition;
|
55 | }
|
56 | const composedResolvers = composeResolvers(resolvers, resolversComposition);
|
57 | return addResolversToSchema({
|
58 | schema,
|
59 | resolvers: composedResolvers,
|
60 | updateResolversInPlace: true,
|
61 | });
|
62 | }
|
63 | return schema;
|
64 | }
|
65 | }
|
66 |
|
67 | export default SnapshotTransform;
|
68 |
|