grafast
Version:
Cutting edge GraphQL planning and execution engine
173 lines • 6.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoadManyStep = void 0;
exports.loadManyCallback = loadManyCallback;
exports.loadManyLoader = loadManyLoader;
exports.loadMany = loadMany;
const multistep_js_1 = require("../multistep.js");
const step_js_1 = require("../step.js");
const utils_js_1 = require("../utils.js");
const _loadCommon_js_1 = require("./_loadCommon.js");
const access_js_1 = require("./access.js");
const constant_js_1 = require("./constant.js");
const loadedRecord_js_1 = require("./loadedRecord.js");
/**
* A TypeScript Identity Function to help you strongly type your
* LoadManyCallback.
*/
function loadManyCallback(load) {
return load;
}
/**
* A TypeScript Identity Function to help you strongly type your
* LoadManyLoader.
*/
function loadManyLoader(load) {
return load;
}
const idByLoad = new WeakMap();
let loadCounter = 0;
class LoadManyStep extends step_js_1.Step {
static { this.$$export = { moduleName: "grafast", exportName: "LoadManyStep" }; }
constructor(lookup, loader) {
super();
this.isSyncAndSafe = false;
this.loadInfo = null;
this.loadInfoKey = "";
this.attributes = new Set();
this.paramDepIdByKey = Object.create(null);
this.sharedDepId = null;
this._accessMap = null;
// TODO: prompt users to disable this if they don't need it.
this.cloneStreams = true;
const { load, shared, ioEquivalence, paginationSupport } = loader;
this.name = loader.name || load.displayName || load.name;
this.load = load;
if (typeof this.load !== "function") {
throw new Error(`Invalid options passed to LoadManyStep - there must be a 'load' function!`);
}
this.ioEquivalence = ioEquivalence ?? null;
const $lookup = (0, multistep_js_1.multistep)(lookup, "load");
this.addDependency($lookup);
if (shared != null) {
const $shared = (0, multistep_js_1.multistep)(shared, "loadUnary");
this.sharedDepId = this.addUnaryDependency($shared);
}
if (!paginationSupport) {
delete this.applyPagination;
}
else {
this.paginationSupport = paginationSupport;
}
}
toStringMeta() {
return this.name ?? null;
}
getAccessMap() {
return (this._accessMap ??= (0, _loadCommon_js_1.makeAccessMap)(this.getDep(0), this.ioEquivalence));
}
listItem($item) {
return new loadedRecord_js_1.LoadedRecordStep(this, $item, false, this.toStringMeta(), this.getAccessMap());
}
setParam(paramKey, value) {
this.paramDepIdByKey[paramKey] = this.addUnaryDependency(value instanceof step_js_1.Step ? value : (0, constant_js_1.constant)(value));
}
addAttributes(attributes) {
for (const attribute of attributes) {
this.attributes.add(attribute);
}
}
deduplicate(peers) {
return peers.filter((p) => p.load === this.load &&
(0, _loadCommon_js_1.ioEquivalenceMatches)(p.ioEquivalence, this.ioEquivalence) &&
(0, utils_js_1.recordsMatch)(p.paramDepIdByKey, this.paramDepIdByKey));
}
deduplicatedWith(replacement) {
for (const attr of this.attributes) {
replacement.attributes.add(attr);
}
}
getParamSignature() {
return (this._paramSig ??= (0, _loadCommon_js_1.paramSig)(this.paramDepIdByKey, (depId) => this.getDepOptions(depId).step.id));
}
finalize() {
// Find all steps of this type that use the same callback and have
// equivalent params and then match their list of attributes together.
const paramSig = this.getParamSignature();
const kin = this.operationPlan
.getStepsByStepClass(LoadManyStep)
.filter((step) => {
if (step.id === this.id)
return false;
if (step.load !== this.load)
return false;
if (step.getParamSignature() !== paramSig)
return false;
return true;
});
for (const otherStep of kin) {
for (const attr of otherStep.attributes) {
this.attributes.add(attr);
}
}
// Build the loadOptions
const attributes = [...this.attributes].sort();
this.loadInfo = { attributes };
// If the canonicalJSONStringify is the same, then we deem that the options are the same
this.loadInfoKey = (0, utils_js_1.canonicalJSONStringify)(this.loadInfo);
let loadId = idByLoad.get(this.load);
if (!loadId) {
loadId = String(++loadCounter);
idByLoad.set(this.load, loadId);
}
this.metaKey = `LoadManyStep|${loadId}|${this.loadInfoKey}`;
super.finalize();
}
execute(details) {
return (0, _loadCommon_js_1.executeLoad)(details, this.sharedDepId, this.paramDepIdByKey, this.loadInfo, this.load);
}
applyPagination($params) {
this.setParam("reverse", (0, access_js_1.access)($params, "reverse"));
this.setParam("after", (0, access_js_1.access)($params, "after"));
this.setParam("offset", (0, access_js_1.access)($params, "offset"));
this.setParam("limit", (0, access_js_1.access)($params, "limit"));
}
connectionClone() {
const lookup = this.getDep(0);
const { load, ioEquivalence } = this;
const shared = this.sharedDepId != null
? this.getDep(this.sharedDepId)
: null;
const $clone = new LoadManyStep(lookup, {
load,
shared,
ioEquivalence,
});
// Copy attributes?
for (const attr of this.attributes) {
$clone.attributes.add(attr);
}
// Clone over all params except for pagination params
for (const [key, depId] of Object.entries(this.paramDepIdByKey)) {
if (key === "reverse" ||
key === "after" ||
key === "offset" ||
key === "limit") {
// Skip pagination param
continue;
}
$clone.setParam(key, this.getDep(depId));
}
return $clone;
}
}
exports.LoadManyStep = LoadManyStep;
function loadMany(lookup, loader) {
if (arguments.length > 2) {
throw new Error("The signature of loadMany has changed, additional arguments should now be passed via a 'loader' object: `loadMany(lookup, loader)` where `loader` is either a `load` function or object containing it `{ load, shared?, ioEquivalence?, paginationSupport? }`");
}
return new LoadManyStep(lookup, typeof loader === "function"
? { load: loader }
: loader);
}
//# sourceMappingURL=loadMany.js.map