mirror of
https://github.com/JamesIves/github-pages-deploy-action.git
synced 2023-12-15 20:03:39 +08:00
258 lines
11 KiB
JavaScript
258 lines
11 KiB
JavaScript
"use strict";
|
|
var __assign = (this && this.__assign) || function () {
|
|
__assign = Object.assign || function(t) {
|
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
s = arguments[i];
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
t[p] = s[p];
|
|
}
|
|
return t;
|
|
};
|
|
return __assign.apply(this, arguments);
|
|
};
|
|
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 resolveFrom = require("resolve-from");
|
|
var definition_1 = require("./definition");
|
|
var rootFields = ['Query', 'Mutation', 'Subscription'];
|
|
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 firstTypes = lodash_1.flatten(typeDefinitions).filter(function (d) {
|
|
return lodash_1.includes(rootFields, d.name.value);
|
|
});
|
|
var otherFirstTypes = typeDefinitions[0].filter(function (d) { return !lodash_1.includes(rootFields, d.name.value); });
|
|
var firstSet = firstTypes.concat(otherFirstTypes);
|
|
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 = __assign({}, 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);
|
|
}
|
|
/**
|
|
* Resolve the path of an import.
|
|
* First it will try to find a file relative from the file the import is in, if that fails it will try to resolve it as a module so imports from packages work correctly.
|
|
*
|
|
* @param filePath Path the import was made from
|
|
* @param importFrom Path given for the import
|
|
* @returns Full resolved path to a file
|
|
*/
|
|
function resolveModuleFilePath(filePath, importFrom) {
|
|
var dirname = path.dirname(filePath);
|
|
if (isFile(filePath) && isFile(importFrom)) {
|
|
try {
|
|
return fs.realpathSync(path.join(dirname, importFrom));
|
|
}
|
|
catch (e) {
|
|
if (e.code === 'ENOENT') {
|
|
return resolveFrom(dirname, importFrom);
|
|
}
|
|
}
|
|
}
|
|
return importFrom;
|
|
}
|
|
/**
|
|
* 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 Map(); }
|
|
if (typeDefinitions === void 0) { typeDefinitions = []; }
|
|
if (allDefinitions === void 0) { allDefinitions = []; }
|
|
var key = isFile(filePath) ? path.resolve(filePath) : 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, allDefinitions);
|
|
// Add typedefinitions to running total
|
|
typeDefinitions.push(currentTypeDefinitions);
|
|
// 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 = resolveModuleFilePath(filePath, m.from);
|
|
var processedFile = processedFiles.get(key);
|
|
if (!processedFile || !processedFile.find(function (rModule) { return lodash_1.isEqual(rModule, m); })) {
|
|
// Mark this specific import line as processed for this file (for cicular dependency cases)
|
|
processedFiles.set(key, processedFile ? processedFile.concat(m) : [m]);
|
|
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, allDefinitions) {
|
|
// This should do something smart with fields
|
|
if (allDefinitions === void 0) { allDefinitions = []; }
|
|
var filteredDefinitions = filterTypeDefinitions(typeDefinitions);
|
|
if (lodash_1.includes(imports, '*')) {
|
|
if (imports.length === 1 &&
|
|
imports[0] === '*' &&
|
|
allDefinitions.length > 1) {
|
|
var previousTypeDefinitions_1 = lodash_1.keyBy(lodash_1.flatten(allDefinitions.slice(0, allDefinitions.length - 1)).filter(function (def) { return !lodash_1.includes(rootFields, def.name.value); }), function (def) { return def.name.value; });
|
|
return typeDefinitions.filter(function (typeDef) {
|
|
return typeDef.kind === 'ObjectTypeDefinition' &&
|
|
previousTypeDefinitions_1[typeDef.name.value];
|
|
});
|
|
}
|
|
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
|