All Downloads are FREE. Search and download functionalities are using the official Maven repository.

node_modules.graphql-import.dist.index.js Maven / Gradle / Ivy

There is a newer version: 3.3.1
Show newest version
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var graphql_1 = require("graphql");
var lodash_1 = require("lodash");
var path = require("path");
var definition_1 = require("./definition");
var read = function (schema, schemas) {
    if (isFile(schema)) {
        return fs.readFileSync(schema, { encoding: 'utf8' });
    }
    return schemas ? schemas[schema] : schema;
};
var isFile = function (f) { return f.endsWith('.graphql'); };
/**
 * Parse a single import line and extract imported types and schema filename
 *
 * @param importLine Import line
 * @returns Processed import line
 */
function parseImportLine(importLine) {
    // Apply regex to import line
    var matches = importLine.match(/^import (\*|(.*)) from ('|")(.*)('|")$/);
    if (!matches || matches.length !== 6 || !matches[4]) {
        throw new Error("Too few regex matches: " + matches);
    }
    // Extract matches into named variables
    var wildcard = matches[1], importsString = matches[2], from = matches[4];
    // Extract imported types
    var imports = wildcard === '*' ? ['*'] : importsString.split(',').map(function (d) { return d.trim(); });
    // Return information about the import line
    return { imports: imports, from: from };
}
exports.parseImportLine = parseImportLine;
/**
 * Parse a schema and analyze all import lines
 *
 * @param sdl Schema to parse
 * @returns Array with collection of imports per import line (file)
 */
function parseSDL(sdl) {
    return sdl
        .split('\n')
        .map(function (l) { return l.trim(); })
        .filter(function (l) { return l.startsWith('# import ') || l.startsWith('#import '); })
        .map(function (l) { return l.replace('#', '').trim(); })
        .map(parseImportLine);
}
exports.parseSDL = parseSDL;
/**
 * Main entry point. Recursively process all import statement in a schema
 *
 * @param filePath File path to the initial schema file
 * @returns Single bundled schema with all imported types
 */
function importSchema(schema, schemas) {
    var sdl = read(schema, schemas) || schema;
    var document = getDocumentFromSDL(sdl);
    // Recursively process the imports, starting by importing all types from the initial schema
    var _a = collectDefinitions(['*'], sdl, schema, schemas), allDefinitions = _a.allDefinitions, typeDefinitions = _a.typeDefinitions;
    // Post processing of the final schema (missing types, unused types, etc.)
    // Query, Mutation and Subscription should be merged
    // And should always be in the first set, to make sure they
    // are not filtered out.
    var typesToFilter = ['Query', 'Mutation', 'Subscription'];
    var firstTypes = lodash_1.flatten(typeDefinitions).filter(function (d) { return lodash_1.includes(typesToFilter, d.name.value); });
    var otherFirstTypes = typeDefinitions[0].filter(function (d) { return !lodash_1.includes(typesToFilter, d.name.value); });
    var firstSet = otherFirstTypes.concat(firstTypes);
    var processedTypeNames = [];
    var mergedFirstTypes = [];
    var _loop_1 = function (type) {
        if (!lodash_1.includes(processedTypeNames, type.name.value)) {
            processedTypeNames.push(type.name.value);
            mergedFirstTypes.push(type);
        }
        else {
            var existingType = mergedFirstTypes.find(function (t) { return t.name.value === type.name.value; });
            existingType.fields = existingType.fields.concat(type.fields);
        }
    };
    for (var _i = 0, firstSet_1 = firstSet; _i < firstSet_1.length; _i++) {
        var type = firstSet_1[_i];
        _loop_1(type);
    }
    document.definitions = definition_1.completeDefinitionPool(lodash_1.flatten(allDefinitions), firstSet, lodash_1.flatten(typeDefinitions));
    // Return the schema as string
    return graphql_1.print(document);
}
exports.importSchema = importSchema;
/**
 * Parses a schema into a graphql DocumentNode.
 * If the schema is empty a DocumentNode with empty definitions will be created.
 *
 * @param sdl Schema to parse
 * @returns A graphql DocumentNode with definitions of the parsed sdl.
 */
function getDocumentFromSDL(sdl) {
    if (isEmptySDL(sdl)) {
        return {
            kind: graphql_1.Kind.DOCUMENT,
            definitions: [],
        };
    }
    else {
        return graphql_1.parse(sdl, { noLocation: true });
    }
}
/**
 * Check if a schema contains any type definitions at all.
 *
 * @param sdl Schema to parse
 * @returns True if SDL only contains comments and/or whitespaces
 */
function isEmptySDL(sdl) {
    return sdl
        .split('\n')
        .map(function (l) { return l.trim(); })
        .filter(function (l) { return !(l.length === 0 || l.startsWith('#')); })
        .length === 0;
}
/**
 * Recursively process all schema files. Keeps track of both the filtered
 * type definitions, and all type definitions, because they might be needed
 * in post-processing (to add missing types)
 *
 * @param imports Types specified in the import statement
 * @param sdl Current schema
 * @param filePath File location for current schema
 * @param Tracking of processed schemas (for circular dependencies)
 * @param Tracking of imported type definitions per schema
 * @param Tracking of all type definitions per schema
 * @returns Both the collection of all type definitions, and the collection of imported type definitions
 */
function collectDefinitions(imports, sdl, filePath, schemas, processedFiles, typeDefinitions, allDefinitions) {
    if (processedFiles === void 0) { processedFiles = new Set(); }
    if (typeDefinitions === void 0) { typeDefinitions = []; }
    if (allDefinitions === void 0) { allDefinitions = []; }
    var key = isFile(filePath) ? path.resolve(filePath) : filePath;
    var dirname = path.dirname(filePath);
    // Get TypeDefinitionNodes from current schema
    var document = getDocumentFromSDL(sdl);
    // Add all definitions to running total
    allDefinitions.push(filterTypeDefinitions(document.definitions));
    // Filter TypeDefinitionNodes by type and defined imports
    var currentTypeDefinitions = filterImportedDefinitions(imports, document.definitions);
    // Add typedefinitions to running total
    typeDefinitions.push(currentTypeDefinitions);
    // Mark file as processed (for circular dependency cases)
    processedFiles.add(key);
    // Read imports from current file
    var rawModules = parseSDL(sdl);
    // Process each file (recursively)
    rawModules.forEach(function (m) {
        // If it was not yet processed (in case of circular dependencies)
        var moduleFilePath = isFile(filePath) ? path.resolve(path.join(dirname, m.from)) : m.from;
        if (!processedFiles.has(moduleFilePath)) {
            collectDefinitions(m.imports, read(moduleFilePath, schemas), moduleFilePath, schemas, processedFiles, typeDefinitions, allDefinitions);
        }
    });
    // Return the maps of type definitions from each file
    return { allDefinitions: allDefinitions, typeDefinitions: typeDefinitions };
}
/**
 * Filter the types loaded from a schema, first by relevant types,
 * then by the types specified in the import statement.
 *
 * @param imports Types specified in the import statement
 * @param typeDefinitions All definitions from a schema
 * @returns Filtered collection of type definitions
 */
function filterImportedDefinitions(imports, typeDefinitions) {
    // This should do something smart with fields
    var filteredDefinitions = filterTypeDefinitions(typeDefinitions);
    if (lodash_1.includes(imports, '*')) {
        return filteredDefinitions;
    }
    else {
        var result = filteredDefinitions.filter(function (d) { return lodash_1.includes(imports.map(function (i) { return i.split('.')[0]; }), d.name.value); });
        var fieldImports = imports
            .filter(function (i) { return i.split('.').length > 1; });
        var groupedFieldImports = lodash_1.groupBy(fieldImports, function (x) { return x.split('.')[0]; });
        var _loop_2 = function (rootType) {
            var fields = groupedFieldImports[rootType].map(function (x) { return x.split('.')[1]; });
            filteredDefinitions.find(function (def) { return def.name.value === rootType; }).fields =
                filteredDefinitions.find(function (def) { return def.name.value === rootType; }).fields
                    .filter(function (f) { return lodash_1.includes(fields, f.name.value) || lodash_1.includes(fields, '*'); });
        };
        for (var rootType in groupedFieldImports) {
            _loop_2(rootType);
        }
        return result;
    }
}
/**
 * Filter relevant definitions from schema
 *
 * @param definitions All definitions from a schema
 * @returns Relevant type definitions
 */
function filterTypeDefinitions(definitions) {
    var validKinds = [
        'DirectiveDefinition',
        'ScalarTypeDefinition',
        'ObjectTypeDefinition',
        'InterfaceTypeDefinition',
        'EnumTypeDefinition',
        'UnionTypeDefinition',
        'InputObjectTypeDefinition'
    ];
    return definitions
        .filter(function (d) { return lodash_1.includes(validKinds, d.kind); })
        .map(function (d) { return d; });
}
//# sourceMappingURL=index.js.map




© 2015 - 2025 Weber Informatics LLC | Privacy Policy