grafast
Version:
Cutting edge GraphQL planning and execution engine
150 lines • 5.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoadOneStep = void 0;
exports.loadOneCallback = loadOneCallback;
exports.loadOneLoader = loadOneLoader;
exports.loadOne = loadOne;
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");
/**
* A TypeScript Identity Function to help you strongly type your
* LoadOneCallback.
*/
function loadOneCallback(load) {
return load;
}
/**
* A TypeScript Identity Function to help you strongly type your
* LoadOneLoader.
*/
function loadOneLoader(load) {
return load;
}
const idByLoad = new WeakMap();
let loadCounter = 0;
class LoadOneStep extends step_js_1.Step {
static { this.$$export = { moduleName: "grafast", exportName: "LoadOneStep" }; }
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;
const { load, shared, ioEquivalence } = loader;
this.name = loader.name || load.displayName || load.name;
this.load = load;
if (typeof this.load !== "function") {
throw new Error(`Invalid options passed to LoadOneStep - there must be a 'load' function!`);
}
this.ioEquivalence = ioEquivalence ?? null;
const $spec = (0, multistep_js_1.multistep)(lookup, "load");
this.addDependency($spec);
if (shared != null) {
const $shared = (0, multistep_js_1.multistep)(shared, "loadUnary");
this.sharedDepId = this.addUnaryDependency($shared);
}
}
toStringMeta() {
return this.name ?? null;
}
getAccessMap() {
return (this._accessMap ??= (0, _loadCommon_js_1.makeAccessMap)(this.getDep(0), this.ioEquivalence));
}
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(LoadOneStep)
.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 loadInfo
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 = `LoadOneStep|${loadId}|${this.loadInfoKey}`;
super.finalize();
}
execute(details) {
return (0, _loadCommon_js_1.executeLoad)(details, this.sharedDepId, this.paramDepIdByKey, this.loadInfo, this.load);
}
// Things that were originally in LoadedRecordStep
get(attr) {
return this.cacheStep("get", attr, () => this._getInner(attr));
}
_getInner(attr) {
if (this.operationPlan.phase === "plan") {
// Allow auto-collapsing of the waterfall by knowing keys are equivalent
const accessMap = this.getAccessMap();
const $step = accessMap[attr];
if ($step) {
return $step;
}
}
this.attributes.add(attr);
return (0, access_js_1.access)(this, attr);
}
}
exports.LoadOneStep = LoadOneStep;
/**
* Loads an individual record identified by the `lookup` using the `loader`.
*
* @param lookup - A step/multistep representing the value to look up - could be an
* identifier or combination of identifiers.
* @param loader - The function to load this, or a LoadManyLoader object containing such a function
*/
function loadOne(lookup, loader) {
if (arguments.length > 2) {
throw new Error("The signature of loadOne has changed, additional arguments should now be passed via a 'loader' object: `loadOne(lookup, loader)` where `loader` is either a `load` function or object containing it `{ load, shared?, ioEquivalence?, paginationSupport? }`");
}
return new LoadOneStep(lookup, typeof loader === "function"
? { load: loader }
: loader);
}
//# sourceMappingURL=loadOne.js.map