@graphql-codegen/graphql-modules-preset
Version:
GraphQL Code Generator preset for modularized schema
203 lines (202 loc) • 6.89 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectUsedTypes = collectUsedTypes;
exports.resolveTypeNode = resolveTypeNode;
exports.isGraphQLPrimitive = isGraphQLPrimitive;
exports.unique = unique;
exports.withQuotes = withQuotes;
exports.indent = indent;
exports.buildBlock = buildBlock;
exports.groupSourcesByModule = groupSourcesByModule;
exports.stripFilename = stripFilename;
exports.normalize = normalize;
exports.pushUnique = pushUnique;
exports.concatByKey = concatByKey;
exports.uniqueByKey = uniqueByKey;
exports.createObject = createObject;
const tslib_1 = require("tslib");
const graphql_1 = require("graphql");
const parse_filepath_1 = tslib_1.__importDefault(require("parse-filepath"));
const sep = '/';
/**
* Searches every node to collect used types
*/
function collectUsedTypes(doc) {
const used = [];
for (const node of doc.definitions) {
findRelated(node);
}
function markAsUsed(type) {
pushUnique(used, type);
}
function findRelated(node) {
if (node.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION || node.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
// Object
markAsUsed(node.name.value);
if (node.fields) {
for (const n of node.fields) {
findRelated(n);
}
}
if (node.interfaces) {
for (const n of node.interfaces) {
findRelated(n);
}
}
}
else if (node.kind === graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION || node.kind === graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION) {
// Input
markAsUsed(node.name.value);
if (node.fields) {
for (const n of node.fields) {
findRelated(n);
}
}
}
else if (node.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION || node.kind === graphql_1.Kind.INTERFACE_TYPE_EXTENSION) {
// Interface
markAsUsed(node.name.value);
if (node.fields) {
for (const n of node.fields) {
findRelated(n);
}
}
if (node.interfaces) {
for (const n of node.interfaces) {
findRelated(n);
}
}
}
else if (node.kind === graphql_1.Kind.UNION_TYPE_DEFINITION || node.kind === graphql_1.Kind.UNION_TYPE_EXTENSION) {
// Union
markAsUsed(node.name.value);
if (node.types) {
for (const n of node.types) {
findRelated(n);
}
}
}
else if (node.kind === graphql_1.Kind.ENUM_TYPE_DEFINITION || node.kind === graphql_1.Kind.ENUM_TYPE_EXTENSION) {
// Enum
markAsUsed(node.name.value);
}
else if (node.kind === graphql_1.Kind.SCALAR_TYPE_DEFINITION || node.kind === graphql_1.Kind.SCALAR_TYPE_EXTENSION) {
// Scalar
if (!isGraphQLPrimitive(node.name.value)) {
markAsUsed(node.name.value);
}
}
else if (node.kind === graphql_1.Kind.INPUT_VALUE_DEFINITION) {
// Argument
findRelated(resolveTypeNode(node.type));
}
else if (node.kind === graphql_1.Kind.FIELD_DEFINITION) {
// Field
findRelated(resolveTypeNode(node.type));
if (node.arguments) {
for (const n of node.arguments) {
findRelated(n);
}
}
}
else if (node.kind === graphql_1.Kind.NAMED_TYPE &&
// Named type
!isGraphQLPrimitive(node.name.value)) {
markAsUsed(node.name.value);
}
}
return used;
}
function resolveTypeNode(node) {
if (node.kind === graphql_1.Kind.LIST_TYPE) {
return resolveTypeNode(node.type);
}
if (node.kind === graphql_1.Kind.NON_NULL_TYPE) {
return resolveTypeNode(node.type);
}
return node;
}
function isGraphQLPrimitive(name) {
return ['String', 'Boolean', 'ID', 'Float', 'Int'].includes(name);
}
function unique(val, i, all) {
return i === all.indexOf(val);
}
function withQuotes(val) {
return `'${val}'`;
}
function indent(size) {
const space = new Array(size).fill(' ').join('');
function indentInner(val) {
return val
.split('\n')
.map(line => `${space}${line}`)
.join('\n');
}
return indentInner;
}
function buildBlock({ name, lines }) {
if (!lines.length) {
return '';
}
return [`${name} {`, ...lines.map(indent(2)), '};'].join('\n');
}
const getRelativePath = function (filepath, basePath) {
const normalizedFilepath = normalize(filepath);
const normalizedBasePath = ensureStartsWithSeparator(normalize(ensureEndsWithSeparator(basePath)));
const [, relativePath] = normalizedFilepath.split(normalizedBasePath);
return relativePath;
};
function groupSourcesByModule(sources, basePath) {
const grouped = {};
for (const source of sources) {
const relativePath = getRelativePath(source.location, basePath);
if (relativePath) {
// PERF: we could guess the module by matching source.location with a list of already resolved paths
const mod = extractModuleDirectory(source.location, basePath);
grouped[mod] ||= [];
grouped[mod].push(source);
}
}
return grouped;
}
function extractModuleDirectory(filepath, basePath) {
const relativePath = getRelativePath(filepath, basePath);
const [moduleDirectory] = relativePath.split(sep);
return moduleDirectory;
}
function stripFilename(path) {
const parsedPath = (0, parse_filepath_1.default)(path);
return normalize(parsedPath.dir);
}
function normalize(path) {
return path.replace(/\\/g, '/');
}
function ensureEndsWithSeparator(path) {
return path.endsWith(sep) ? path : path + sep;
}
function ensureStartsWithSeparator(path) {
return path.startsWith('.') ? path.replace(/^(..\/)|(.\/)/, '/') : path.startsWith('/') ? path : '/' + path;
}
/**
* Pushes an item to a list only if the list doesn't include the item
*/
function pushUnique(list, item) {
if (!list.includes(item)) {
list.push(item);
}
}
function concatByKey(left, right, key) {
// Remove duplicate, if an element is in right & left, it will be only once in the returned array.
return [...new Set([...left[key], ...right[key]])];
}
function uniqueByKey(left, right, key) {
return left[key].filter(item => !right[key].includes(item));
}
function createObject(keys, valueFn) {
const obj = {};
for (const key of keys) {
obj[key] = valueFn(key);
}
return obj;
}
;