Last active
January 16, 2023 06:33
-
-
Save hdodov/bbb2e380aa587a100272b298e12e493a to your computer and use it in GitHub Desktop.
Payload CMS dynamic variables with `{{` and `}}`. You can also add modifiers, e.g. `{{ my_var:millions }}` and divide the value by 1e6.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import payload from "payload"; | |
import { CollectionAfterReadHook } from "payload/types"; | |
import { Variable } from "../payload-types"; | |
const pattern = /{{\s*(.*?)\s*}}/g; | |
const modifiers: { [key: string]: (input: string) => string } = { | |
millions: (value) => Math.floor(parseInt(value) / 1e6).toString(), | |
}; | |
/** | |
* Recursively loops over all properties of the `input` object and invokes | |
* `callback` for each one of them. If the callback returns a string, the looped | |
* value is also replaced with that string. | |
*/ | |
function deepIterate( | |
input: object, | |
callback: (value: string) => void | string | |
) { | |
for (let k in input) { | |
if (!input.hasOwnProperty(k)) { | |
continue; | |
} | |
let val: string = input[k]; | |
if (typeof val === "string") { | |
let result = callback(val); | |
if (typeof result === "string") { | |
input[k] = result; | |
} | |
} else if (val && typeof val === "object") { | |
deepIterate(val, callback); | |
} | |
} | |
} | |
export const replaceVariablesHook: CollectionAfterReadHook = async ({ | |
doc, | |
req, | |
}) => { | |
// Don't do anything if `?replace` is missing from the request URL. | |
if (!req.query.replace) { | |
return doc; | |
} | |
let variables: string[] = []; | |
deepIterate(doc, (value) => { | |
for (let matches of value.matchAll(pattern)) { | |
variables.push(matches[1].split(":")[0]); | |
} | |
}); | |
const query = await payload.find<Variable>({ | |
collection: "variables", | |
limit: 0, | |
where: { | |
key: { | |
in: variables, | |
}, | |
}, | |
}); | |
deepIterate(doc, (value) => { | |
return value.replace(pattern, (_, name: string) => { | |
const parts = name.split(":"); | |
const key = parts.shift(); | |
let value = query.docs.find((doc) => doc.key === key)?.value; | |
if (!value) { | |
return ""; | |
} | |
if (parts.length) { | |
parts.forEach((modifierName) => { | |
if (modifiers[modifierName]) { | |
value = modifiers[modifierName](value); | |
} | |
}); | |
} | |
return value; | |
}); | |
}); | |
return doc; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { CollectionConfig } from "payload/types"; | |
export const Variables: CollectionConfig = { | |
slug: "variables", | |
admin: { | |
useAsTitle: "key", | |
}, | |
fields: [ | |
{ | |
name: "key", | |
type: "text", | |
}, | |
{ | |
name: "value", | |
type: "text", | |
}, | |
], | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment