graphile-build
Version:
Build a GraphQL schema from plugins
133 lines • 6.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeAccessorPlugin = void 0;
require("graphile-config");
const grafast_1 = require("grafast");
const utils_ts_1 = require("../utils.js");
const version_ts_1 = require("../version.js");
exports.NodeAccessorPlugin = {
name: "NodeAccessorPlugin",
description: "Adds accessors for the various types registered with the Global Unique Object Identification ID (Node ID) system",
version: version_ts_1.version,
inflection: {
add: {
nodeById(options, typeName) {
return this.camelCase(typeName);
},
},
},
schema: {
hooks: {
build(build) {
const { EXPORTABLE } = build;
const nodeFetcherByTypeNameCache = EXPORTABLE(() => new Map(), [], "nodeFetcherByTypeNameCache");
const specForHandlerCache = EXPORTABLE(() => new Map(), [], "specForHandlerCache");
return build.extend(build, {
specForHandler: EXPORTABLE((markSyncAndSafe, specForHandlerCache) => function (handler) {
const existing = specForHandlerCache.get(handler);
if (existing) {
return existing;
}
const spec = markSyncAndSafe(function spec(nodeId) {
// We only want to return the specifier if it matches
// this handler; otherwise return null.
if (nodeId == null)
return null;
try {
const specifier = handler.codec.decode(nodeId);
if (handler.match(specifier)) {
return specifier;
}
}
catch {
// Ignore errors
}
return null;
}, `specifier_${handler.typeName}_${handler.codec.name}`);
specForHandlerCache.set(handler, spec);
return spec;
}, [grafast_1.markSyncAndSafe, specForHandlerCache]),
nodeFetcherByTypeName(typeName) {
const existing = nodeFetcherByTypeNameCache.get(typeName);
if (existing)
return existing;
const finalBuild = build;
const { specForHandler } = finalBuild;
if (!specForHandler)
return null;
const handler = finalBuild.getNodeIdHandler?.(typeName);
if (!handler)
return null;
const fetcher = handler.deprecationReason
? EXPORTABLE((handler, lambda, specForHandler) => {
const fn = ($nodeId) => {
const $decoded = lambda($nodeId, specForHandler(handler));
return handler.get(handler.getSpec($decoded));
};
fn.deprecationReason = handler.deprecationReason;
return fn;
}, [handler, grafast_1.lambda, specForHandler])
: EXPORTABLE((handler, lambda, specForHandler) => ($nodeId) => {
const $decoded = lambda($nodeId, specForHandler(handler));
return handler.get(handler.getSpec($decoded));
}, [handler, grafast_1.lambda, specForHandler]);
(0, utils_ts_1.exportNameHint)(fetcher, `nodeFetcher_${typeName}`);
nodeFetcherByTypeNameCache.set(typeName, fetcher);
return fetcher;
},
}, "Adding node accessor helpers");
},
GraphQLObjectType_fields(fields, build, context) {
if (!build.getNodeTypeNames) {
return fields;
}
const { graphql: { GraphQLNonNull, GraphQLID }, } = build;
const { scope: { isRootQuery }, } = context;
if (!isRootQuery) {
return fields;
}
if (!build.nodeFetcherByTypeName) {
return fields;
}
const typeNames = build.getNodeTypeNames();
const nodeIdFieldName = build.inflection.nodeIdFieldName();
const recoverableForEachType = (cb) => {
for (const typeName of typeNames) {
fields = build.recoverable(fields, () => cb(typeName));
}
return fields;
};
return recoverableForEachType((typeName) => {
// Don't add a field for 'Query'
if (typeName === build.inflection.builtin("Query")) {
return fields;
}
const fetcher = build.nodeFetcherByTypeName(typeName);
if (!fetcher) {
return fields;
}
return build.extend(fields, {
[build.inflection.nodeById(typeName)]: {
args: {
[nodeIdFieldName]: {
description: `The globally unique \`ID\` to be used in selecting a single \`${typeName}\`.`,
type: new GraphQLNonNull(GraphQLID),
},
},
type: build.getOutputTypeByName(typeName),
description: `Reads a single \`${typeName}\` using its globally unique \`ID\`.`,
plan: (0, utils_ts_1.EXPORTABLE)((fetcher, nodeIdFieldName) => function plan(_$parent, args) {
const $nodeId = args.getRaw(nodeIdFieldName);
return fetcher($nodeId);
}, [fetcher, nodeIdFieldName]),
...(fetcher.deprecationReason
? { deprecationReason: fetcher.deprecationReason }
: null),
},
}, `Adding ${typeName} by NodeId field`);
});
},
},
},
};
//# sourceMappingURL=NodeAccessorPlugin.js.map