Prism/developer documentation/Utilities

Utilities

The services every module can use through this.prism.

Every module class gets the running Prism instance as this.prism. These are the services on it you will use most.

Console

this.prism.console.log(this.prism.console.levels.info, "Sync finished.");
this.prism.console.log(this.prism.console.levels.error, `Sync failed: ${error.message}`);
LevelUse it for
infoNormal progress.
successSomething finished.
warningSomething went wrong but Prism carries on.
errorA failure.
debugExtra detail. Only printed with Debug Logs on.
startupLoading and registration messages.
moduleA line tagged with the file that logged it.

An unknown level prints as info with a warning. Every line also goes to the dashboard's Logs page and to data/logs/<date>.log.

this.prism.console.error(error) prints a large fatal error panel. Prism uses it when it cannot keep running, so prefer log with the error level in modules.

Settings

Prism's own settings, such as LANGUAGE, SITE_NAME, THEME or CHECKOUT, plus anything you store:

const name = this.prism.settings.get("SITE_NAME");
await this.prism.settings.set("example:last_sync", Date.now());
await this.prism.settings.delete("example:last_sync");

Settings live in the database and are cached in memory. Prefix your own keys with your module ID. For admin-facing options use a config class instead.

Cache

const prices = this.prism.cache.store("example:prices", { ttl: 60000, max: 200 });

const price = await prices.remember(productId, () => this.fetchPrice(productId));
prices.delete(productId);
MethodWhat it does
get(key) / has(key)Read an entry that has not expired.
set(key, value, ttl)Store a value.
remember(key, load, ttl)Return the cached value, or run load once and cache the result. Calls made while it loads share one request.
delete(key) / clear()Remove one entry or all of them.

ttl is in milliseconds and defaults to 10 minutes. max defaults to 500 entries, after which the oldest are dropped. this.prism.cache.clear("example:") clears every store whose name starts with the prefix.

Files

this.prism.data points at Prism's data/ folder:

const folder = this.prism.data.ensure("example", "exports");
const file = this.prism.data.module("example", "exports", "items.csv");
this.prism.data.remove("example", "exports");
MethodWhat it does
path(...segments)The full path, inside data/.
module(id, ...segments)The same, starting in your module's folder.
ensure(...segments)Create the folder if needed and return its path.
exists(...segments)Whether it exists.
remove(...segments)Delete it and everything in it.

Segments are cleaned so a path can never leave data/.

Storage

this.prism.storage talks to the S3 bucket from Settings > S3 Storage: Cloudflare R2, Amazon S3 or any S3-compatible service. It signs requests itself, with no SDK.

if (!this.prism.storage.configured()) this.fail(400, this.prism.modules.lang.phrase("example", "messages", "storage_missing"));
await this.prism.storage.upload("example/report.pdf", buffer, "application/pdf");
const link = this.prism.storage.url("example/report.pdf", 300, "report.pdf");
await this.prism.storage.remove("example/report.pdf");
MethodWhat it does
configured()Whether the bucket settings are filled in.
upload(key, body, type)Store a buffer.
remove(key)Delete an object.
url(key, seconds, filename)A signed download link that expires after seconds, up to 7 days.

Prefix keys with your module ID.

Mail

this.prism.mail sends through the SMTP server from Settings > SMTP:

if (this.prism.mail.configured()) await this.prism.mail.send({ to: "[email protected]", subject: "Your report", text: "It is ready." });

send throws when SMTP is not set up. Put the subject and body in your lang files so they can be translated.

Audit Log

await this.prism.audit.record({
    type: "example",
    actor: request.actor,
    action: "item.synced",
    target: String(item.id),
    detail: { product: item.product_id }
});
FieldWhat it is
typeUsually your module ID.
actorWho did it. Leave it out for the system.
actionWhat happened.
targetWhat it happened to.
detailAny extra JSON.
successfalse for a failed attempt. Defaults to true.
ipThe request's IP address.

Inside a route, this.audit(request, action, target, detail) fills in the type, actor and IP. Entries show on the Audit Log page and fire audit.recorded.

Signing

Prism signs storefront responses with an Ed25519 key so clients can check they came from your shop. You can sign your own data with the same key:

const envelope = this.prism.signer.envelope({ id: item.id, valid: true });
const ok = this.prism.signer.verify(envelope.data, envelope.signature);
MethodWhat it does
sign(payload)Sign an object. Keys are sorted first, so the order does not matter.
verify(payload, signature)Check a signature from sign.
envelope(payload){ data, signature, algorithm: "ed25519" }.
detached(text)Sign a plain string.
publicKey()The public key as PEM, for your clients.

Events

this.prism.events.on("product.created", ({ product }) => {});
await this.prism.emitAsync("example.synced", { count });

Use event classes for listeners that belong to your module, so they are removed when it unloads.

Packages

List npm packages your module needs in its manifest under dependencies.node. Prism installs any that are missing when the module loads, with Bun or npm, without adding them to package.json. To install one yourself:

await this.prism.installPackages("csv-stringify");