feat: package continuity plugin MVP docs and receipt store

This commit is contained in:
Eve
2026-04-24 17:32:47 +08:00
parent acf83824b7
commit b9ccc3d096
6 changed files with 580 additions and 43 deletions

View File

@@ -0,0 +1,44 @@
import fs from "node:fs/promises";
import path from "node:path";
function isNonEmptyString(value) {
return typeof value === 'string' && value.trim().length > 0;
}
export function slugifyReceiptSegment(value) {
if (!isNonEmptyString(value)) return '';
return value
.trim()
.toLowerCase()
.replace(/[^a-z0-9._-]+/g, '-')
.replace(/-+/g, '-')
.replace(/^-+|-+$/g, '');
}
export function buildReceiptFilename({ planId, dispatchRunId }) {
const planIdSafe = slugifyReceiptSegment(planId);
const dispatchRunIdSafe = slugifyReceiptSegment(dispatchRunId);
return {
planIdSafe,
dispatchRunIdSafe,
filename: (planIdSafe && dispatchRunIdSafe)
? `receipt-${planIdSafe}-${dispatchRunIdSafe}.json`
: '',
};
}
export async function writeReceipt({ receiptDir, receipt }) {
if (!isNonEmptyString(receiptDir)) {
throw new Error('receiptDir: expected non-empty string');
}
const { filename, planIdSafe, dispatchRunIdSafe } = buildReceiptFilename(receipt ?? {});
if (!filename) {
throw new Error(`receipt filename segments invalid: planId=${JSON.stringify(planIdSafe)}, dispatchRunId=${JSON.stringify(dispatchRunIdSafe)}`);
}
await fs.mkdir(receiptDir, { recursive: true });
const receiptPath = path.join(receiptDir, filename);
await fs.writeFile(receiptPath, `${JSON.stringify(receipt, null, 2)}\n`, 'utf8');
return receiptPath;
}