From 84f2a815ea1e25b46086869a9099659fd46a3640 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 24 Jun 2023 11:25:23 -0300 Subject: infra: refactor relations tree processing, new 'query' step Finally putting the 'step' in 'data-steps'! --- src/content-function.js | 180 +++++++++++++++++-------------- src/write/build-modes/live-dev-server.js | 19 ++-- src/write/build-modes/static-build.js | 19 ++-- 3 files changed, 115 insertions(+), 103 deletions(-) diff --git a/src/content-function.js b/src/content-function.js index 70e7be38..9d6f6af9 100644 --- a/src/content-function.js +++ b/src/content-function.js @@ -12,6 +12,7 @@ export default function contentFunction({ slots, sprawl, + query, relations, data, generate, @@ -49,6 +50,7 @@ export default function contentFunction({ return expectDependencies({ slots, sprawl, + query, relations, data, generate, @@ -68,6 +70,7 @@ contentFunction.identifyingSymbol = Symbol(`Is a content function?`); export function expectDependencies({ slots, sprawl, + query, relations, data, generate, @@ -81,6 +84,7 @@ export function expectDependencies({ fulfilledDependencies, }) { const hasSprawlFunction = !!sprawl; + const hasQueryFunction = !!query; const hasRelationsFunction = !!relations; const hasDataFunction = !!data; const hasSlotsDescription = !!slots; @@ -174,6 +178,10 @@ export function expectDependencies({ wrappedGenerate.sprawl = sprawl; } + if (hasQueryFunction) { + wrappedGenerate.query = query; + } + if (hasRelationsFunction) { wrappedGenerate.relations = relations; } @@ -209,6 +217,7 @@ export function expectDependencies({ return expectDependencies({ slots, sprawl, + query, relations, data, generate, @@ -300,6 +309,26 @@ export function fulfillDependencies(dependencies, { } } +export function getArgsForRelationsAndData(contentFunction, wikiData, ...args) { + const insertArgs = []; + + if (contentFunction.sprawl) { + insertArgs.push(contentFunction.sprawl(wikiData, ...args)); + } + + if (contentFunction.query) { + insertArgs.unshift(contentFunction.query(...insertArgs, ...args)); + } + + // Note: Query is generally intended to "filter" the provided args/sprawl, + // so in most cases it shouldn't be necessary to access the original args + // or sprawl afterwards. These are left available for now (as the second + // and later arguments in relations/data), but if they don't find any use, + // we can refactor this step to remove them. + + return [...insertArgs, ...args]; +} + export function getRelationsTree(dependencies, contentFunctionName, wikiData, ...args) { const relationIdentifier = Symbol('Relation'); @@ -309,96 +338,88 @@ export function getRelationsTree(dependencies, contentFunctionName, wikiData, .. throw new Error(`Couldn't find dependency ${contentFunctionName}`); } - if (!contentFunction.relations) { - return null; - } - - const listedDependencies = new Set(contentFunction.contentDependencies); - - // TODO: Evaluating a sprawl might belong somewhere better than here, lol... - const sprawl = - (contentFunction.sprawl - ? contentFunction.sprawl(wikiData, ...args) - : null) + // TODO: It's a bit awkward to pair this list of arguments with the output of + // getRelationsTree, but we do need to evaluate it right away (for the upcoming + // call to relations), and we're going to be reusing the same results for a + // later call to data (outside of getRelationsTree). There might be a nicer way + // of handling this. + const argsForRelationsAndData = + getArgsForRelationsAndData( + contentFunction, + wikiData, + ...args); + + const result = { + name: contentFunctionName, + args: argsForRelationsAndData, + }; - const relationSlots = {}; + if (contentFunction.relations) { + const listedDependencies = new Set(contentFunction.contentDependencies); - const relationSymbolMessage = (() => { - let num = 1; - return name => `#${num++} ${name}`; - })(); + const relationSlots = {}; - const relationFunction = (name, ...args) => { - if (!listedDependencies.has(name)) { - throw new Error(`Called relation('${name}') but ${contentFunctionName} doesn't list that dependency`); - } + const relationSymbolMessage = (() => { + let num = 1; + return name => `#${num++} ${name}`; + })(); - const relationSymbol = Symbol(relationSymbolMessage(name)); - relationSlots[relationSymbol] = {name, args}; - return {[relationIdentifier]: relationSymbol}; - }; + const relationFunction = (name, ...args) => { + if (!listedDependencies.has(name)) { + throw new Error(`Called relation('${name}') but ${contentFunctionName} doesn't list that dependency`); + } - const relationsLayout = - (sprawl - ? contentFunction.relations(relationFunction, sprawl, ...args) - : contentFunction.relations(relationFunction, ...args)) + const relationSymbol = Symbol(relationSymbolMessage(name)); + relationSlots[relationSymbol] = {name, args}; + return {[relationIdentifier]: relationSymbol}; + }; - const relationsTree = Object.fromEntries( - Object.getOwnPropertySymbols(relationSlots) - .map(symbol => [symbol, relationSlots[symbol]]) - .map(([symbol, {name, args}]) => [ - symbol, - recursive(name, ...args), - ])); + const relationsLayout = + contentFunction.relations(relationFunction, ...argsForRelationsAndData); + + const relationsTree = Object.fromEntries( + Object.getOwnPropertySymbols(relationSlots) + .map(symbol => [symbol, relationSlots[symbol]]) + .map(([symbol, {name, args}]) => [ + symbol, + recursive(name, ...args), + ])); + + result.relations = { + layout: relationsLayout, + slots: relationSlots, + tree: relationsTree, + }; + } - return { - layout: relationsLayout, - slots: relationSlots, - tree: relationsTree, - }; + return result; } - const relationsTree = recursive(contentFunctionName, ...args); + const root = recursive(contentFunctionName, ...args); - return { - root: { - name: contentFunctionName, - args, - relations: relationsTree?.layout, - }, - - relationIdentifier, - relationsTree, - }; + return {root, relationIdentifier}; } -export function flattenRelationsTree({ - root, - relationIdentifier, - relationsTree, -}) { +export function flattenRelationsTree({root, relationIdentifier}) { const flatRelationSlots = {}; - function recursive({layout, slots, tree}) { - for (const slot of Object.getOwnPropertySymbols(slots)) { - if (tree[slot]) { - recursive(tree[slot]); + function recursive(node) { + if (node.relations) { + const {tree, slots} = node.relations; + for (const slot of Object.getOwnPropertySymbols(slots)) { + flatRelationSlots[slot] = recursive(tree[slot]); } - - flatRelationSlots[slot] = { - name: slots[slot].name, - args: slots[slot].args, - relations: tree[slot]?.layout ?? null, - }; } - } - if (relationsTree) { - recursive(relationsTree); + return { + name: node.name, + args: node.args, + relations: node.relations?.layout ?? null, + }; } return { - root, + root: recursive(root), relationIdentifier, flatRelationSlots, }; @@ -537,25 +558,22 @@ export function quickEvaluate({ const slotResults = {}; - function runContentFunction({name, args, relations: flatRelations}) { + function runContentFunction({name, args, relations: layout}) { const contentFunction = fulfilledContentDependencies[name]; if (!contentFunction) { throw new Error(`Content function ${name} unfulfilled or not listed`); } - const sprawl = - contentFunction.sprawl?.(allExtraDependencies.wikiData, ...args); - - const relations = - fillRelationsLayoutFromSlotResults(relationIdentifier, slotResults, flatRelations); + const generateArgs = []; - const data = - (sprawl - ? contentFunction.data?.(sprawl, ...args) - : contentFunction.data?.(...args)); + if (contentFunction.data) { + generateArgs.push(contentFunction.data(...args)); + } - const generateArgs = [data, relations].filter(Boolean); + if (layout) { + generateArgs.push(fillRelationsLayoutFromSlotResults(relationIdentifier, slotResults, layout)); + } return contentFunction(...generateArgs); } diff --git a/src/write/build-modes/live-dev-server.js b/src/write/build-modes/live-dev-server.js index e3ab21d5..8af37d3a 100644 --- a/src/write/build-modes/live-dev-server.js +++ b/src/write/build-modes/live-dev-server.js @@ -428,25 +428,22 @@ export async function go({ const slotResults = {}; - function runContentFunction({name, args, relations: flatRelations}) { + function runContentFunction({name, args, relations: layout}) { const contentFunction = fulfilledContentDependencies[name]; if (!contentFunction) { throw new Error(`Content function ${name} unfulfilled or not listed`); } - const sprawl = - contentFunction.sprawl?.(allExtraDependencies.wikiData, ...args); + const generateArgs = []; - const relations = - fillRelationsLayoutFromSlotResults(relationIdentifier, slotResults, flatRelations); - - const data = - (sprawl - ? contentFunction.data?.(sprawl, ...args) - : contentFunction.data?.(...args)); + if (contentFunction.data) { + generateArgs.push(contentFunction.data(...args)); + } - const generateArgs = [data, relations].filter(Boolean); + if (layout) { + generateArgs.push(fillRelationsLayoutFromSlotResults(relationIdentifier, slotResults, layout)); + } return contentFunction(...generateArgs); } diff --git a/src/write/build-modes/static-build.js b/src/write/build-modes/static-build.js index e0b4ab16..67a4df67 100644 --- a/src/write/build-modes/static-build.js +++ b/src/write/build-modes/static-build.js @@ -390,25 +390,22 @@ export async function go({ const slotResults = {}; - function runContentFunction({name, args, relations: flatRelations}) { + function runContentFunction({name, args, relations: layout}) { const contentFunction = fulfilledContentDependencies[name]; if (!contentFunction) { throw new Error(`Content function ${name} unfulfilled or not listed`); } - const sprawl = - contentFunction.sprawl?.(allExtraDependencies.wikiData, ...args); + const generateArgs = []; - const relations = - fillRelationsLayoutFromSlotResults(relationIdentifier, slotResults, flatRelations); - - const data = - (sprawl - ? contentFunction.data?.(sprawl, ...args) - : contentFunction.data?.(...args)); + if (contentFunction.data) { + generateArgs.push(contentFunction.data(...args)); + } - const generateArgs = [data, relations].filter(Boolean); + if (layout) { + generateArgs.push(fillRelationsLayoutFromSlotResults(relationIdentifier, slotResults, layout)); + } return contentFunction(...generateArgs); } -- cgit 1.3.0-6-gf8a5