diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2025-01-11 14:13:55 -0400 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2025-01-11 14:13:55 -0400 |
commit | 95cd0873ca80f05acb4100ebe08bc43e8107a429 (patch) | |
tree | 55771ce36b8aec6201b9161465505a3f62eb5605 /src/find-reverse.js | |
parent | 5b16090a206db99a266fcc006921782b37f8d1a0 (diff) |
find, reverse: factor out some common interfaces & stub reverse
no bindReverse yet
Diffstat (limited to 'src/find-reverse.js')
-rw-r--r-- | src/find-reverse.js | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/find-reverse.js b/src/find-reverse.js new file mode 100644 index 00000000..47e0e268 --- /dev/null +++ b/src/find-reverse.js @@ -0,0 +1,100 @@ +// Helpers common to #find and #reverse logic. + +import thingConstructors from '#things'; + +export function getAllSpecs({ + word, + constructorKey, + + hardcodedSpecs, + postprocessSpec, +}) { + try { + thingConstructors; + } catch (error) { + throw new Error(`Thing constructors aren't ready yet, can't get all ${word} specs`); + } + + const specs = {...hardcodedSpecs}; + + for (const thingConstructor of Object.values(thingConstructors)) { + const thingSpecs = thingConstructor[constructorKey]; + if (!thingSpecs) continue; + + for (const [key, spec] of Object.entries(thingSpecs)) { + specs[key] = + postprocessSpec(spec, { + thingConstructor, + }); + } + } + + return specs; +} + +export function findSpec(key, { + word, + constructorKey, + + hardcodedSpecs, + postprocessSpec, +}) { + if (Object.hasOwn(hardcodedSpecs, key)) { + return hardcodedSpecs[key]; + } + + try { + thingConstructors; + } catch (error) { + throw new Error(`Thing constructors aren't ready yet, can't check if "${word}.${key}" available`); + } + + for (const thingConstructor of Object.values(thingConstructors)) { + const thingSpecs = thingConstructor[constructorKey]; + if (!thingSpecs) continue; + + if (Object.hasOwn(thingSpecs, key)) { + return postprocessSpec(thingSpecs[key], { + thingConstructor, + }); + } + } + + throw new Error(`"${word}.${key}" isn't available`); +} + +export function tokenProxy({ + findSpec, + prepareBehavior, + + handle: customHandle = + (_key) => undefined, + + decorate = + (_token, _key) => {}, +}) { + return new Proxy({}, { + get: (store, key) => { + const custom = customHandle(key); + if (custom !== undefined) { + return custom; + } + + if (!Object.hasOwn(store, key)) { + let behavior = (...args) => { + // This will error if the spec isn't available... + const spec = findSpec(key); + + // ...or, if it is available, replace this function with the + // ready-for-use find function made out of that spec. + return (behavior = prepareBehavior(spec))(...args); + }; + + store[key] = (...args) => behavior(...args); + decorate(store[key], key); + } + + return store[key]; + }, + }); +} |