← back to CelebritySignatures
chore: lint, refactor, session-close fixes, v1.0.2 → v1.0.3 (TK-10286)
0770f004b6ca5f81e8309c118ff842eb27764f2d · 2026-08-10 16:14:59 -0700 · Steve Abrams
Session-close quality gate on the Printful POD wiring:
- FIX (critical, caught by lint): submit-pod-draft.mjs now appends a SUBMITTED marker after each successful Printful POST + filters it out on the DRAFT_UNSENT read — a rerun can no longer double-submit an already-sent order (proven: rerun sends nothing)
- FIX: /wear-checkout returns 400 on unknown size (was silently falling back to sizes[0] → wrong fulfillment)
- FIX: /wear-success no longer swallows errors silently (console.error) so a paid-but-draft-write-failed case is visible in the log
- refactor: envVal() consolidated to the for-of form (behavior-identical)
- node --check clean on all; dry-run still submits nothing
Files touched
M package.jsonM scripts/submit-pod-draft.mjsM server.js
Diff
commit 0770f004b6ca5f81e8309c118ff842eb27764f2d
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 10 16:14:59 2026 -0700
chore: lint, refactor, session-close fixes, v1.0.2 → v1.0.3 (TK-10286)
Session-close quality gate on the Printful POD wiring:
- FIX (critical, caught by lint): submit-pod-draft.mjs now appends a SUBMITTED marker after each successful Printful POST + filters it out on the DRAFT_UNSENT read — a rerun can no longer double-submit an already-sent order (proven: rerun sends nothing)
- FIX: /wear-checkout returns 400 on unknown size (was silently falling back to sizes[0] → wrong fulfillment)
- FIX: /wear-success no longer swallows errors silently (console.error) so a paid-but-draft-write-failed case is visible in the log
- refactor: envVal() consolidated to the for-of form (behavior-identical)
- node --check clean on all; dry-run still submits nothing
---
package.json | 2 +-
scripts/submit-pod-draft.mjs | 16 +++++++++++-----
server.js | 5 +++--
3 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/package.json b/package.json
index 522e898..2f140a8 100644
--- a/package.json
+++ b/package.json
@@ -1 +1 @@
-{"name":"celebrity-signatures","version":"1.0.2","type":"module","private":true}
\ No newline at end of file
+{"name":"celebrity-signatures","version":"1.0.3","type":"module","private":true}
\ No newline at end of file
diff --git a/scripts/submit-pod-draft.mjs b/scripts/submit-pod-draft.mjs
index d685277..e22faf6 100644
--- a/scripts/submit-pod-draft.mjs
+++ b/scripts/submit-pod-draft.mjs
@@ -13,7 +13,7 @@
// Even when applied, orders are created with confirm=false — i.e. a DRAFT order in
// the Printful dashboard, NOT auto-fulfilled and NOT auto-charged. A human confirms
// each order in Printful. Provider: PRINTFUL (Steve's call 2026-08-10, TK-10286).
-import { readFile } from 'node:fs/promises';
+import { readFile, appendFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { join } from 'node:path';
import { readFileSync } from 'node:fs';
@@ -25,9 +25,9 @@ const PRINTFUL_ORDERS_URL = 'https://api.printful.com/orders';
function envVal(name) {
if (process.env[name]) return process.env[name];
- try { const m = readFileSync(join(ROOT, '.env'), 'utf8').match(new RegExp('^' + name + '=(.+)$', 'm')); if (m) return m[1].trim(); } catch {}
- // also read the master secrets .env if present
- try { const p = join(ROOT, '..', 'secrets-manager', '.env'); const m = readFileSync(p, 'utf8').match(new RegExp('^' + name + '=(.+)$', 'm')); if (m) return m[1].trim(); } catch {}
+ for (const p of [join(ROOT, '.env'), join(ROOT, '..', 'secrets-manager', '.env')]) {
+ try { const m = readFileSync(p, 'utf8').match(new RegExp('^' + name + '=(.+)$', 'm')); if (m) return m[1].trim(); } catch {}
+ }
return null;
}
@@ -73,7 +73,11 @@ function buildPayload(tpl, d) {
async function main() {
let lines = [];
try { lines = (await readFile(join(DATA, 'pod-order-drafts.jsonl'), 'utf8')).trim().split('\n').filter(Boolean); } catch {}
- const drafts = lines.map(l => JSON.parse(l)).filter(d => d.status === 'DRAFT_UNSENT');
+ const all = lines.map(l => JSON.parse(l));
+ // Orders already sent to Printful get a SUBMITTED marker line appended below.
+ // Exclude them so a rerun (network glitch, human re-run) NEVER double-submits.
+ const submitted = new Set(all.filter(d => d.status === 'SUBMITTED').map(d => d.orderId));
+ const drafts = all.filter(d => d.status === 'DRAFT_UNSENT' && !submitted.has(d.orderId));
const tpl = await templates();
console.log(`POD drafts pending: ${drafts.length} (provider: Printful)`);
@@ -96,6 +100,8 @@ async function main() {
});
const j = await resp.json().catch(() => ({}));
if (!resp.ok) { console.error(` PRINTFUL ERROR ${resp.status}: ${j.error?.message || j.result || 'unknown'}`); continue; }
+ // Mark this order SUBMITTED so a rerun skips it (append-only, matches the draft log).
+ await appendFile(join(DATA, 'pod-order-drafts.jsonl'), JSON.stringify({ orderId: d.orderId, status: 'SUBMITTED', printfulId: j.result?.id, submittedAt: new Date().toISOString() }) + '\n');
console.log(` ✓ Printful DRAFT order created: id=${j.result?.id} status=${j.result?.status} (confirm it in the Printful dashboard to fulfill).`);
}
diff --git a/server.js b/server.js
index fefb588..297b175 100644
--- a/server.js
+++ b/server.js
@@ -802,7 +802,8 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
const garment = (tpl.garments || []).find(g => g.id === String(b.garment || ''));
if (!garment) return sendJSON(res, 400, { ok: false, error: 'unknown garment' });
const color = (garment.colors || []).find(c => c.id === String(b.color || '')) || garment.colors[0];
- const size = (garment.sizes || []).includes(String(b.size)) ? String(b.size) : garment.sizes[0];
+ if (!(garment.sizes || []).includes(String(b.size))) return sendJSON(res, 400, { ok: false, error: 'unknown size' });
+ const size = String(b.size);
const amountCents = Math.round((garment.priceUsd || WEAR_GARMENT_DEFAULT_PRICE_USD) * 100);
const u = await currentUser(req);
const list = await load('wear-orders.json', []);
@@ -871,7 +872,7 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
await store('wear-orders.json', list);
}
}
- } catch {}
+ } catch (e) { console.error('wear-success', e.message); }
}
const body = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>${paid ? 'Order received' : 'Order'} — Celebrity Signatures</title><link rel="icon" href="/assets/favicon.png">
← 0fa8dbf wear/POD: wire Printful sender + go-live path (gated OFF) —
·
back to CelebritySignatures
·
CelebritySignatures mobile: early-game respects Difficulty + 93f7578 →