@graphql-mesh/config
Version: 
732 lines (727 loc) • 30.9 kB
JavaScript
import { path, process } from '@graphql-mesh/cross-helpers';
import { visit, Kind, print, parse, concatAST } from 'graphql';
import { printSchemaWithDirectives } from '@graphql-tools/utils';
import { paramCase } from 'param-case';
import { loadTypedefs, loadDocuments } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { parseWithCache, PubSub, DefaultLogger, resolveAdditionalResolvers, defaultImportFn } from '@graphql-mesh/utils';
import { fetch } from '@whatwg-node/fetch';
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
import { MeshStore, FsStoreStorageAdapter, InMemoryStoreStorageAdapter } from '@graphql-mesh/store';
import { pascalCase } from 'pascal-case';
import { camelCase } from 'camel-case';
import { useMaskedErrors, useImmediateIntrospection } from '@envelop/core';
async function getPackage({ name, type, importFn, cwd, additionalPrefixes = [], }) {
    const casedName = paramCase(name);
    const casedType = paramCase(type);
    const prefixes = ['@graphql-mesh/', ...additionalPrefixes];
    const initialPossibleNames = [casedName, `${casedName}-${casedType}`, `${casedType}-${casedName}`, casedType];
    const possibleNames = [];
    for (const prefix of prefixes) {
        for (const possibleName of initialPossibleNames) {
            possibleNames.push(`${prefix}${possibleName}`);
        }
    }
    for (const possibleName of initialPossibleNames) {
        possibleNames.push(possibleName);
    }
    if (name.includes('-')) {
        possibleNames.push(name);
    }
    const possibleModules = possibleNames.concat(path.resolve(cwd, name));
    for (const moduleName of possibleModules) {
        try {
            const exported = await importFn(moduleName, true);
            const resolved = exported.default || exported;
            return {
                moduleName,
                resolved,
            };
        }
        catch (err) {
            const error = err;
            if (!error.message.includes(`Cannot find module '${moduleName}'`) &&
                !error.message.includes(`Cannot find package '${moduleName}'`) &&
                !error.message.includes(`Could not locate module`)) {
                throw new Error(`Unable to load ${type} matching ${name}: ${error.stack}`);
            }
        }
    }
    throw new Error(`Unable to find ${type} matching ${name}`);
}
async function resolveAdditionalTypeDefs(baseDir, additionalTypeDefs) {
    if (additionalTypeDefs) {
        const sources = await loadTypedefs(additionalTypeDefs, {
            cwd: baseDir,
            loaders: [new CodeFileLoader(), new GraphQLFileLoader()],
        });
        return sources.map(source => source.document || parseWithCache(source.rawSDL || printSchemaWithDirectives(source.schema)));
    }
    return undefined;
}
async function resolveCustomFetch({ fetchConfig, importFn, cwd, cache, additionalPackagePrefixes, }) {
    let importCode = '';
    if (!fetchConfig) {
        importCode += `import { fetch as fetchFn } from '@whatwg-node/fetch';\n`;
        return {
            fetchFn: fetch,
            importCode,
            code: ``,
        };
    }
    const { moduleName, resolved: fetchFn } = await getPackage({
        name: fetchConfig,
        type: 'fetch',
        importFn,
        cwd,
        additionalPrefixes: additionalPackagePrefixes,
    });
    importCode += `import fetchFn from ${JSON.stringify(moduleName)};\n`;
    return {
        fetchFn,
        importCode,
        code: '',
    };
}
async function resolveCache(cacheConfig = {
    localforage: {},
}, importFn, rootStore, cwd, pubsub, logger, additionalPackagePrefixes) {
    const cacheName = Object.keys(cacheConfig)[0].toString();
    const config = cacheConfig[cacheName];
    const { moduleName, resolved: Cache } = await getPackage({
        name: cacheName,
        type: 'cache',
        importFn,
        cwd,
        additionalPrefixes: additionalPackagePrefixes,
    });
    const cache = new Cache({
        ...config,
        importFn,
        store: rootStore.child('cache'),
        pubsub,
        logger,
    });
    const code = `const cache = new (MeshCache as any)({
      ...(${JSON.stringify(config)} as any),
      importFn,
      store: rootStore.child('cache'),
      pubsub,
      logger,
    } as any)`;
    const importCode = `import MeshCache from ${JSON.stringify(moduleName)};`;
    return {
        cache,
        importCode,
        code,
    };
}
async function resolvePubSub(pubsubYamlConfig, importFn, cwd, additionalPackagePrefixes) {
    if (pubsubYamlConfig) {
        let pubsubName;
        let pubsubConfig;
        if (typeof pubsubYamlConfig === 'string') {
            pubsubName = pubsubYamlConfig;
        }
        else {
            pubsubName = pubsubYamlConfig.name;
            pubsubConfig = pubsubYamlConfig.config;
        }
        const { moduleName, resolved: PubSub } = await getPackage({
            name: pubsubName,
            type: 'pubsub',
            importFn,
            cwd,
            additionalPrefixes: additionalPackagePrefixes,
        });
        const pubsub = new PubSub(pubsubConfig);
        const importCode = `import PubSub from ${JSON.stringify(moduleName)}`;
        const code = `const pubsub = new PubSub(${JSON.stringify(pubsubConfig)});`;
        return {
            importCode,
            code,
            pubsub,
        };
    }
    else {
        const pubsub = new PubSub();
        const importCode = `import { PubSub } from '@graphql-mesh/utils';`;
        const code = `const pubsub = new PubSub();`;
        return {
            importCode,
            code,
            pubsub,
        };
    }
}
async function resolveDocuments(documentsConfig, cwd) {
    if (!documentsConfig) {
        return [];
    }
    return loadDocuments(documentsConfig, {
        loaders: [new CodeFileLoader(), new GraphQLFileLoader()],
        skipGraphQLImport: true,
        cwd,
    });
}
async function resolveLogger(loggerConfig, importFn, cwd, additionalPackagePrefixes, initialLoggerPrefix = '🕸️  Mesh') {
    if (typeof loggerConfig === 'string') {
        const { moduleName, resolved: logger } = await getPackage({
            name: loggerConfig,
            type: 'logger',
            importFn,
            cwd,
            additionalPrefixes: additionalPackagePrefixes,
        });
        return {
            logger,
            importCode: `import logger from ${JSON.stringify(moduleName)};`,
            code: '',
        };
    }
    const logger = new DefaultLogger(initialLoggerPrefix);
    return {
        logger,
        importCode: `import { DefaultLogger } from '@graphql-mesh/utils';`,
        code: `const logger = new DefaultLogger(${JSON.stringify(initialLoggerPrefix)});`,
    };
}
function parseObject(ast) {
    const value = Object.create(null);
    ast.fields.forEach(field => {
        // eslint-disable-next-line no-use-before-define
        value[field.name.value] = parseLiteral(field.value);
    });
    return value;
}
function parseLiteral(ast) {
    switch (ast.kind) {
        case Kind.STRING:
        case Kind.BOOLEAN:
            return ast.value;
        case Kind.INT:
        case Kind.FLOAT:
            return parseFloat(ast.value);
        case Kind.OBJECT:
            return parseObject(ast);
        case Kind.LIST:
            return ast.values.map(n => parseLiteral(n));
        case Kind.NULL:
            return null;
    }
}
function getAdditionalResolversFromTypeDefs(additionalTypeDefs) {
    const additionalResolversFromTypeDefs = [];
    function handleFieldNode(targetTypeName, fieldNode) {
        var _a;
        if ((_a = fieldNode.directives) === null || _a === void 0 ? void 0 : _a.length) {
            const resolveToDef = fieldNode.directives.find(d => d.name.value === 'resolveTo');
            if (resolveToDef != null) {
                const resolveToArgumentMap = {};
                for (const resolveToArg of resolveToDef.arguments) {
                    const resolveToArgName = resolveToArg.name.value;
                    resolveToArgumentMap[resolveToArgName] = parseLiteral(resolveToArg.value);
                }
                additionalResolversFromTypeDefs.push({
                    targetTypeName,
                    targetFieldName: fieldNode.name.value,
                    ...resolveToArgumentMap,
                });
            }
        }
    }
    additionalTypeDefs === null || additionalTypeDefs === void 0 ? void 0 : additionalTypeDefs.forEach(typeDefs => {
        visit(typeDefs, {
            ObjectTypeDefinition(objectNode) {
                var _a;
                (_a = objectNode.fields) === null || _a === void 0 ? void 0 : _a.forEach(fieldNode => handleFieldNode(objectNode.name.value, fieldNode));
            },
            ObjectTypeExtension(objectNode) {
                var _a;
                (_a = objectNode.fields) === null || _a === void 0 ? void 0 : _a.forEach(fieldNode => handleFieldNode(objectNode.name.value, fieldNode));
            },
            InterfaceTypeDefinition(interfaceNode) {
                var _a;
                (_a = interfaceNode.fields) === null || _a === void 0 ? void 0 : _a.forEach(fieldNode => handleFieldNode(interfaceNode.name.value, fieldNode));
            },
            InterfaceTypeExtension(interfaceNode) {
                var _a;
                (_a = interfaceNode.fields) === null || _a === void 0 ? void 0 : _a.forEach(fieldNode => handleFieldNode(interfaceNode.name.value, fieldNode));
            },
        });
    });
    return additionalResolversFromTypeDefs;
}
const ENVELOP_CORE_PLUGINS_MAP = {
    maskedErrors: {
        moduleName: '@envelop/core',
        importName: 'useMaskedErrors',
        pluginFactory: useMaskedErrors,
    },
    immediateIntrospection: {
        moduleName: '@envelop/core',
        importName: 'useImmediateIntrospection',
        pluginFactory: useImmediateIntrospection,
    },
};
function getDefaultMeshStore(dir, importFn, artifactsDir) {
    var _a;
    const isProd = ((_a = process.env.NODE_ENV) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'production';
    const storeStorageAdapter = isProd
        ? new FsStoreStorageAdapter({
            cwd: dir,
            importFn,
            fileType: 'ts',
        })
        : new InMemoryStoreStorageAdapter();
    return new MeshStore(path.resolve(dir, artifactsDir), storeStorageAdapter, {
        /**
         * TODO:
         * `mesh start` => { readonly: true, validate: false }
         * `mesh dev` => { readonly: false, validate: true } => validation error should show a prompt for confirmation
         * `mesh validate` => { readonly: true, validate: true } => should fetch from remote and try to update
         * readonly
         */
        readonly: isProd,
        validate: false,
    });
}
async function processConfig(config, options) {
    var _a, _b, _c;
    if (config.skipSSLValidation) {
        process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
    }
    const importCodes = new Set([
        `import type { GetMeshOptions } from '@graphql-mesh/runtime';`,
        `import type { YamlConfig } from '@graphql-mesh/types';`,
    ]);
    const codes = new Set([
        `export const rawServeConfig: YamlConfig.Config['serve'] = ${JSON.stringify(config.serve)} as any`,
        `export async function getMeshOptions(): Promise<GetMeshOptions> {`,
    ]);
    const { dir, importFn = defaultImportFn, store: providedStore, artifactsDir, additionalPackagePrefixes = [], } = options || {};
    if (config.require) {
        await Promise.all(config.require.map(mod => importFn(mod)));
        for (const mod of config.require) {
            importCodes.add(`import '${mod}';`);
        }
    }
    const rootStore = providedStore || getDefaultMeshStore(dir, importFn, artifactsDir || '.mesh');
    const { pubsub, importCode: pubsubImportCode, code: pubsubCode, } = await resolvePubSub(config.pubsub, importFn, dir, additionalPackagePrefixes);
    importCodes.add(pubsubImportCode);
    codes.add(pubsubCode);
    const sourcesStore = rootStore.child('sources');
    codes.add(`const sourcesStore = rootStore.child('sources');`);
    const { logger, importCode: loggerImportCode, code: loggerCode, } = await resolveLogger(config.logger, importFn, dir, additionalPackagePrefixes, options === null || options === void 0 ? void 0 : options.initialLoggerPrefix);
    importCodes.add(loggerImportCode);
    codes.add(loggerCode);
    const { cache, importCode: cacheImportCode, code: cacheCode, } = await resolveCache(config.cache, importFn, rootStore, dir, pubsub, logger, additionalPackagePrefixes);
    importCodes.add(cacheImportCode);
    codes.add(cacheCode);
    const { fetchFn, importCode: fetchFnImportCode, code: fetchFnCode, } = await resolveCustomFetch({
        fetchConfig: config.customFetch,
        cache,
        importFn,
        cwd: dir,
        additionalPackagePrefixes,
    });
    importCodes.add(fetchFnImportCode);
    codes.add(fetchFnCode);
    importCodes.add(`import { MeshResolvedSource } from '@graphql-mesh/runtime';`);
    codes.add(`const sources: MeshResolvedSource[] = [];`);
    importCodes.add(`import { MeshTransform, MeshPlugin } from '@graphql-mesh/types';`);
    codes.add(`const transforms: MeshTransform[] = [];`);
    codes.add(`const additionalEnvelopPlugins: MeshPlugin<any>[] = [];`);
    const [sources, transforms, additionalEnvelopPlugins, additionalTypeDefs, additionalResolvers, documents] = await Promise.all([
        Promise.all(config.sources.map(async (source, sourceIndex) => {
            const handlerName = Object.keys(source.handler)[0].toString();
            const handlerConfig = source.handler[handlerName];
            const handlerVariableName = camelCase(`${source.name}_Handler`);
            const transformsVariableName = camelCase(`${source.name}_Transforms`);
            codes.add(`const ${transformsVariableName} = [];`);
            const [handler, transforms] = await Promise.all([
                await getPackage({
                    name: handlerName,
                    type: 'handler',
                    importFn,
                    cwd: dir,
                    additionalPrefixes: additionalPackagePrefixes,
                }).then(({ resolved: HandlerCtor, moduleName }) => {
                    if (options.generateCode) {
                        const handlerImportName = pascalCase(handlerName + '_Handler');
                        importCodes.add(`import ${handlerImportName} from ${JSON.stringify(moduleName)}`);
                        codes.add(`const ${handlerVariableName} = new ${handlerImportName}({
              name: ${JSON.stringify(source.name)},
              config: ${JSON.stringify(handlerConfig)},
              baseDir,
              cache,
              pubsub,
              store: sourcesStore.child(${JSON.stringify(source.name)}),
              logger: logger.child(${JSON.stringify(source.name)}),
              importFn,
            });`);
                    }
                    return new HandlerCtor({
                        name: source.name,
                        config: handlerConfig,
                        baseDir: dir,
                        cache,
                        pubsub,
                        store: sourcesStore.child(source.name),
                        logger: logger.child(source.name),
                        importFn,
                    });
                }),
                Promise.all((source.transforms || []).map(async (t, transformIndex) => {
                    const transformName = Object.keys(t)[0].toString();
                    const transformConfig = t[transformName];
                    const { resolved: TransformCtor, moduleName } = await getPackage({
                        name: transformName,
                        type: 'transform',
                        importFn,
                        cwd: dir,
                        additionalPrefixes: additionalPackagePrefixes,
                    });
                    if (options.generateCode) {
                        const transformImportName = pascalCase(transformName + '_Transform');
                        importCodes.add(`import ${transformImportName} from ${JSON.stringify(moduleName)};`);
                        codes.add(`${transformsVariableName}[${transformIndex}] = new ${transformImportName}({
                  apiName: ${JSON.stringify(source.name)},
                  config: ${JSON.stringify(transformConfig)},
                  baseDir,
                  cache,
                  pubsub,
                  importFn
                });`);
                    }
                    return new TransformCtor({
                        apiName: source.name,
                        config: transformConfig,
                        baseDir: dir,
                        cache,
                        pubsub,
                        importFn,
                    });
                })),
            ]);
            if (options.generateCode) {
                codes.add(`sources[${sourceIndex}] = {
          name: '${source.name}',
          handler: ${handlerVariableName},
          transforms: ${transformsVariableName}
        }`);
            }
            return {
                name: source.name,
                handler,
                transforms,
            };
        })),
        Promise.all(((_a = config.transforms) === null || _a === void 0 ? void 0 : _a.map(async (t, transformIndex) => {
            const transformName = Object.keys(t)[0].toString();
            const transformConfig = t[transformName];
            const { resolved: TransformLibrary, moduleName } = await getPackage({
                name: transformName,
                type: 'transform',
                importFn,
                cwd: dir,
                additionalPrefixes: additionalPackagePrefixes,
            });
            if (options.generateCode) {
                const transformImportName = pascalCase(transformName + '_Transform');
                importCodes.add(`import ${transformImportName} from ${JSON.stringify(moduleName)};`);
                codes.add(`transforms[${transformIndex}] = new (${transformImportName} as any)({
            apiName: '',
            config: ${JSON.stringify(transformConfig)},
            baseDir,
            cache,
            pubsub,
            importFn
          })`);
            }
            return new TransformLibrary({
                apiName: '',
                config: transformConfig,
                baseDir: dir,
                cache,
                pubsub,
                importFn,
            });
        })) || []),
        Promise.all(((_b = config.plugins) === null || _b === void 0 ? void 0 : _b.map(async (p, pluginIndex) => {
            const pluginName = Object.keys(p)[0].toString();
            const pluginConfig = p[pluginName];
            if (ENVELOP_CORE_PLUGINS_MAP[pluginName] != null) {
                const { importName, moduleName, pluginFactory } = ENVELOP_CORE_PLUGINS_MAP[pluginName];
                if (options.generateCode) {
                    importCodes.add(`import { ${importName} } from ${JSON.stringify(moduleName)};`);
                    codes.add(`additionalEnvelopPlugins[${pluginIndex}] = await ${importName}(${JSON.stringify(pluginConfig, null, 2)}))`);
                }
                return pluginFactory(pluginConfig);
            }
            let importName;
            const { resolved: possiblePluginFactory, moduleName } = await getPackage({
                name: pluginName,
                type: 'plugin',
                importFn,
                cwd: dir,
                additionalPrefixes: [...additionalPackagePrefixes, '@envelop/'],
            });
            let pluginFactory;
            if (typeof possiblePluginFactory === 'function') {
                pluginFactory = possiblePluginFactory;
                if (options.generateCode) {
                    importName = pascalCase('use_' + pluginName);
                    importCodes.add(`import ${importName} from ${JSON.stringify(moduleName)};`);
                    codes.add(`additionalEnvelopPlugins[${pluginIndex}] = await ${importName}({
          ...(${JSON.stringify(pluginConfig, null, 2)}),
          logger: logger.child(${JSON.stringify(pluginName)}),
          cache,
          pubsub,
          baseDir,
          importFn,
        })`);
                }
            }
            else {
                Object.keys(possiblePluginFactory).forEach(key => {
                    if (key.toString().startsWith('use') && typeof possiblePluginFactory[key] === 'function') {
                        pluginFactory = possiblePluginFactory[key];
                        if (options.generateCode) {
                            importCodes.add(`import { ${importName} } from ${JSON.stringify(moduleName)};`);
                            codes.add(`additionalEnvelopPlugins[${pluginIndex}] = await ${importName}(${JSON.stringify(pluginConfig, null, 2)}]`);
                        }
                    }
                });
            }
            return pluginFactory({
                ...pluginConfig,
                logger: logger.child(pluginName),
                cache,
                pubsub,
                baseDir: dir,
                importFn,
            });
        })) || []),
        resolveAdditionalTypeDefs(dir, config.additionalTypeDefs).then(additionalTypeDefs => {
            if (options.generateCode) {
                codes.add(`const additionalTypeDefs = [${(additionalTypeDefs || []).map(parsedTypeDefs => `parse(${JSON.stringify(print(parsedTypeDefs))}),`)}] as any[];`);
                if (additionalTypeDefs === null || additionalTypeDefs === void 0 ? void 0 : additionalTypeDefs.length) {
                    importCodes.add(`import { parse } from 'graphql';`);
                }
            }
            return additionalTypeDefs;
        }),
        (options === null || options === void 0 ? void 0 : options.ignoreAdditionalResolvers)
            ? []
            : resolveAdditionalResolvers(dir, config.additionalResolvers, importFn, pubsub),
        resolveDocuments(config.documents, dir),
    ]);
    if (options.generateCode) {
        if ((_c = config.additionalResolvers) === null || _c === void 0 ? void 0 : _c.length) {
            codes.add(`const additionalResolvers = await Promise.all([
        ${config.additionalResolvers
                .map(additionalResolverDefinition => {
                if (typeof additionalResolverDefinition === 'string') {
                    return `import(${JSON.stringify(path.join('..', additionalResolverDefinition).split('\\').join('/'))})
            .then(m => m.resolvers || m.default || m)`;
                }
                else {
                    importCodes.add(`import { resolveAdditionalResolversWithoutImport } from '@graphql-mesh/utils';`);
                    return `resolveAdditionalResolversWithoutImport(
            ${JSON.stringify(additionalResolverDefinition, null, 2)}
          )`;
                }
            })
                .join(',\n')}
      ]);`);
        }
        else {
            codes.add(`const additionalResolvers = [] as any[]`);
        }
    }
    if (additionalTypeDefs === null || additionalTypeDefs === void 0 ? void 0 : additionalTypeDefs.length) {
        const additionalResolversConfigFromTypeDefs = getAdditionalResolversFromTypeDefs(additionalTypeDefs);
        if (additionalResolversConfigFromTypeDefs === null || additionalResolversConfigFromTypeDefs === void 0 ? void 0 : additionalResolversConfigFromTypeDefs.length) {
            const resolveToDirectiveDefinition = /* GraphQL */ `
        scalar ResolveToSourceArgs
        directive @resolveTo(
          requiredSelectionSet: String
          sourceName: String!
          sourceTypeName: String!
          sourceFieldName: String!
          sourceSelectionSet: String
          sourceArgs: ResolveToSourceArgs
          keyField: String
          keysArg: String
          pubsubTopic: String
          filterBy: String
          additionalArgs: ResolveToSourceArgs
          result: String
          resultType: String
        ) on FIELD_DEFINITION
      `;
            const resolvedAdditionalResolvers = await resolveAdditionalResolvers(dir, additionalResolversConfigFromTypeDefs, importFn, pubsub);
            additionalTypeDefs.unshift(parse(resolveToDirectiveDefinition));
            additionalResolvers.push(...resolvedAdditionalResolvers);
            if (options.generateCode && resolvedAdditionalResolvers.length) {
                importCodes.add(`import { resolveAdditionalResolvers } from '@graphql-mesh/utils';`);
                codes.add(`additionalTypeDefs.unshift(parse(/* GraphQL */\`${resolveToDirectiveDefinition}\`))`);
                codes.add(`const additionalResolversFromTypeDefs = await resolveAdditionalResolvers(
          baseDir,
          ${JSON.stringify(additionalResolversConfigFromTypeDefs)},
          importFn,
          pubsub
        );`);
                codes.add(`additionalResolvers.push(additionalResolversFromTypeDefs)`);
            }
        }
    }
    let mergerName = config.merger;
    // Decide what is the default merger
    if (!mergerName) {
        if (config.sources.length > 1) {
            mergerName = 'stitching';
        }
        else {
            // eslint-disable-next-line no-labels
            resolversLoop: for (const resolversObj of additionalResolvers || []) {
                for (const typeName in resolversObj || {}) {
                    const fieldResolvers = resolversObj[typeName];
                    if (typeof fieldResolvers === 'object') {
                        for (const fieldName in fieldResolvers) {
                            const fieldResolveObj = fieldResolvers[fieldName];
                            if (typeof fieldResolveObj === 'object') {
                                // selectionSet needs stitching merger even if there is a single source
                                if (fieldResolveObj.selectionSet != null) {
                                    mergerName = 'stitching';
                                    // eslint-disable-next-line no-labels
                                    break resolversLoop;
                                }
                            }
                        }
                    }
                }
            }
            if (!mergerName) {
                mergerName = 'bare';
            }
        }
    }
    const { resolved: Merger, moduleName: mergerModuleName } = await getPackage({
        name: mergerName,
        type: 'merger',
        importFn,
        cwd: dir,
        additionalPrefixes: additionalPackagePrefixes,
    });
    if (options.generateCode) {
        const mergerImportName = pascalCase(`${mergerName}Merger`);
        importCodes.add(`import ${mergerImportName} from ${JSON.stringify(mergerModuleName)};`);
        codes.add(`const merger = new(${mergerImportName} as any)({
        cache,
        pubsub,
        logger: logger.child('${mergerName}Merger'),
        store: rootStore.child('${mergerName}Merger')
      })`);
    }
    const merger = new Merger({
        cache,
        pubsub,
        logger: logger.child(`${mergerName}Merger`),
        store: rootStore.child(`${mergerName}Merger`),
    });
    if (config.additionalEnvelopPlugins) {
        codes.add(`const importedAdditionalEnvelopPlugins = await import(${JSON.stringify(path.join('..', config.additionalEnvelopPlugins).split('\\').join('/'))}).then(m => m.default || m);`);
        const importedAdditionalEnvelopPlugins = await importFn(path.isAbsolute(config.additionalEnvelopPlugins)
            ? config.additionalEnvelopPlugins
            : path.join(dir, config.additionalEnvelopPlugins));
        if (typeof importedAdditionalEnvelopPlugins === 'function') {
            const factoryResult = await importedAdditionalEnvelopPlugins(config);
            if (Array.isArray(factoryResult)) {
                if (options.generateCode) {
                    codes.add(`additionalEnvelopPlugins.push(...(await importedAdditionalEnvelopPlugins()));`);
                }
                additionalEnvelopPlugins.push(...factoryResult);
            }
            else {
                if (options.generateCode) {
                    codes.add(`additionalEnvelopPlugins.push(await importedAdditionalEnvelopPlugins());`);
                }
                additionalEnvelopPlugins.push(factoryResult);
            }
        }
        else {
            if (Array.isArray(importedAdditionalEnvelopPlugins)) {
                if (options.generateCode) {
                    codes.add(`additionalEnvelopPlugins.push(...importedAdditionalEnvelopPlugins)`);
                }
                additionalEnvelopPlugins.push(...importedAdditionalEnvelopPlugins);
            }
            else {
                if (options.generateCode) {
                    codes.add(`additionalEnvelopPlugins.push(importedAdditionalEnvelopPlugins)`);
                }
                additionalEnvelopPlugins.push(importedAdditionalEnvelopPlugins);
            }
        }
    }
    if (options.generateCode) {
        importCodes.add(`import { printWithCache } from '@graphql-mesh/utils';`);
        const documentVariableNames = [];
        if (documents === null || documents === void 0 ? void 0 : documents.length) {
            const allDocumentNodes = concatAST(documents.map(document => document.document || parseWithCache(document.rawSDL)));
            visit(allDocumentNodes, {
                OperationDefinition(node) {
                    documentVariableNames.push(pascalCase(node.name.value + '_Document'));
                },
            });
        }
        codes.add(`
  return {
    sources,
    transforms,
    additionalTypeDefs,
    additionalResolvers,
    cache,
    pubsub,
    merger,
    logger,
    additionalEnvelopPlugins,
    get documents() {
      return [
      ${documentVariableNames
            .map(documentVarName => `{
        document: ${documentVarName},
        get rawSDL() {
          return printWithCache(${documentVarName});
        },
        location: '${documentVarName}.graphql'
      }`)
            .join(',')}
    ];
    },
    fetchFn,
  };
}`);
    }
    return {
        sources,
        transforms,
        additionalTypeDefs,
        additionalResolvers,
        cache,
        merger,
        pubsub,
        config,
        documents,
        logger,
        store: rootStore,
        additionalEnvelopPlugins,
        includeHttpDetailsInExtensions: config.includeHttpDetailsInExtensions,
        importCodes,
        codes,
        fetchFn,
    };
}
export { getPackage, processConfig, resolveAdditionalTypeDefs, resolveCache, resolveCustomFetch, resolveDocuments, resolveLogger, resolvePubSub };