@statezero/core
Version:
The type-safe frontend client for StateZero - connect directly to your backend models with zero boilerplate
93 lines (92 loc) • 3.06 kB
JavaScript
import Handlebars from 'handlebars';
import superjson from 'superjson';
// Simple map to store temporary PK to real PK mappings
export const tempPkMap = new Map();
// Callbacks to notify when a temp pk is resolved to a real pk
const onResolveCallbacks = new Set();
/**
* Register a callback to be notified when a temp pk is resolved to a real pk
* @param {Function} callback - Called with (tempPk, realPk) when resolved
* @returns {Function} - Unsubscribe function
*/
export function onTempPkResolved(callback) {
onResolveCallbacks.add(callback);
return () => onResolveCallbacks.delete(callback);
}
/**
* Check if a string contains a temporary PK template
* @param {string} str - The string to check
* @returns {boolean} - True if the string contains a TempPK tag
*/
export function containsTempPk(str) {
return (typeof str === 'string' &&
/\{\{\s*TempPK_[^}\s]+\s*\}\}/.test(str));
}
/**
* Create a temporary PK with handlebars syntax
*/
export function createTempPk(uuid) {
const tempPk = `{{TempPK_${uuid}}}`;
return tempPk;
}
/**
* Register a real PK for a temporary PK
*/
export function setRealPk(uuid, realPk) {
const tempPk = `{{TempPK_${uuid}}}`;
const key = `"TempPK_${uuid}"`;
const value = typeof realPk === 'string' ? `"${realPk}"` : String(realPk);
tempPkMap.set(key, value);
// Notify listeners so they can migrate cache entries
for (const cb of onResolveCallbacks) {
try {
cb(tempPk, realPk);
}
catch (e) {
console.warn('[tempPk] onResolve callback error:', e);
}
}
}
/**
* Get the real PK for a temp PK if it exists in the registry
* @param {any} pk - The pk to resolve (may be temp or real)
* @returns {any} - The real pk if found, otherwise the original pk
*/
export function resolveToRealPk(pk) {
if (!containsTempPk(String(pk)))
return pk;
// Extract the uuid from {{TempPK_uuid}}
const match = String(pk).match(/\{\{\s*TempPK_([^}\s]+)\s*\}\}/);
if (!match)
return pk;
const key = `"TempPK_${match[1]}"`;
const realPkStr = tempPkMap.get(key);
if (!realPkStr)
return pk;
// Parse the real pk (remove quotes if string, parse if number)
if (realPkStr.startsWith('"') && realPkStr.endsWith('"')) {
return realPkStr.slice(1, -1);
}
return parseInt(realPkStr, 10);
}
/**
* Replace all temporary PKs in an object (or string) with their real values
*/
export function replaceTempPks(payload) {
if (tempPkMap.size === 0)
return payload;
const context = Object.fromEntries(tempPkMap);
try {
if (typeof payload === 'string') {
const template = Handlebars.compile(payload, { noEscape: true });
return template(context);
}
const str = superjson.stringify(payload);
const template = Handlebars.compile(str, { noEscape: true });
const replaced = template(context);
return superjson.parse(replaced);
}
catch (error) {
return payload;
}
}