feat: emit app state snapshots on all mutating workflows
This commit is contained in:
26
src/app.js
26
src/app.js
@@ -48,11 +48,28 @@ function parsePositiveInt(raw, fallback = null) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function buildApp({ config }) {
|
||||
function buildApp({ config, initialState = null, onMutation = null }) {
|
||||
const engine = new XArtAudioEngine({
|
||||
creditConfig: config.credit,
|
||||
initialState: initialState && initialState.engine ? initialState.engine : null,
|
||||
});
|
||||
|
||||
function persistMutation() {
|
||||
if (!onMutation) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
onMutation({
|
||||
version: 1,
|
||||
updatedAt: new Date().toISOString(),
|
||||
engine: engine.exportState(),
|
||||
});
|
||||
} catch {
|
||||
// avoid breaking request flow on persistence callback issues
|
||||
}
|
||||
}
|
||||
|
||||
function ensureAuth(userId, returnTo) {
|
||||
if (userId) {
|
||||
return null;
|
||||
@@ -92,6 +109,8 @@ function buildApp({ config }) {
|
||||
});
|
||||
}
|
||||
|
||||
persistMutation();
|
||||
|
||||
return json(200, {
|
||||
status: "completed",
|
||||
deduped: result.deduped,
|
||||
@@ -120,6 +139,7 @@ function buildApp({ config }) {
|
||||
|
||||
try {
|
||||
engine.topUpCredits(payload.userId, payload.credits, `polar:${payload.eventId}`);
|
||||
persistMutation();
|
||||
return json(200, { status: "credited" });
|
||||
} catch (error) {
|
||||
return json(400, { error: error.message });
|
||||
@@ -224,6 +244,7 @@ function buildApp({ config }) {
|
||||
}
|
||||
|
||||
engine.topUpCredits(userId, amount, `app-topup:${userId}:${randomUUID()}`);
|
||||
persistMutation();
|
||||
return redirect(withQuery("/app", { flash: `Added ${amount} credits` }));
|
||||
}
|
||||
|
||||
@@ -260,6 +281,7 @@ function buildApp({ config }) {
|
||||
return redirect(withQuery("/app", { flash: "Parent post is not an article" }));
|
||||
}
|
||||
|
||||
persistMutation();
|
||||
return redirect(withQuery(`/audio/${result.job.assetId}`, {
|
||||
flash: "Audiobook generated",
|
||||
}));
|
||||
@@ -277,6 +299,7 @@ function buildApp({ config }) {
|
||||
|
||||
try {
|
||||
engine.unlockAudio(assetId, userId);
|
||||
persistMutation();
|
||||
return redirect(withQuery(`/audio/${assetId}`, { flash: "Unlocked" }));
|
||||
} catch (error) {
|
||||
return redirect(withQuery(`/audio/${assetId}`, { flash: `Unlock failed: ${error.message}` }));
|
||||
@@ -330,6 +353,7 @@ function buildApp({ config }) {
|
||||
const assetId = path.slice("/api/audio/".length, -"/unlock".length);
|
||||
try {
|
||||
const result = engine.unlockAudio(assetId, userId);
|
||||
persistMutation();
|
||||
return json(200, result);
|
||||
} catch (error) {
|
||||
return json(400, { error: error.message });
|
||||
|
||||
Reference in New Issue
Block a user