@blamejs/blamejs-shop 0.0.116 → 0.0.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.0.x
10
10
 
11
+ - v0.0.118 (2026-05-24) — **Newsletter signup — missing-table resilience + per-step error attribution.** POST `/newsletter` was returning a generic 500 for every submission — valid email, invalid email, empty form, every shape. The outer try/catch was swallowing whatever the D1 INSERT threw and falling into `renderInternalError`. Sub-step attribution wasn't logged, so wrangler tail saw `edge POST /newsletter failed:` with a stack but the visitor saw the 500 page. The most likely root cause: migration `0010_newsletter_signups.sql` hasn't been applied to live D1 yet, so the INSERT throws `no such table: newsletter_signups`. This patch wraps the INSERT in its own try/catch, logs the underlying D1 message via `console.error`, and returns a clean 503 `"Newsletter signup temporarily unavailable"` with `Retry-After: 60` when the table (or a column) is missing. Unknown D1 failures (constraint conflicts, network errors) still escalate to the outer catch and the existing 500 page. The visitor gets a clear retry signal instead of a generic error; the operator sees a specific signal that migrations need to be applied. **Fixed:** *Newsletter handler degrades gracefully when D1 schema is missing* — `worker/index.js#_edgeNewsletter` wraps the INSERT in a per-step try/catch. On `"no such table"` / `"no such column"` errors, returns `503 Newsletter signup temporarily unavailable.` with `Retry-After: 60` + the framework's security headers. Other D1 failures (constraint conflicts, network errors, etc.) re-throw to the outer catch — the existing 500 page renders, the underlying message lands in `console.error` → wrangler tail / Logpush. Mirrors the missing-table-resilience pattern shipped for blog queries in v0.0.109.
12
+
13
+ - v0.0.117 (2026-05-24) — **Fix Add to Cart — `container.fetch` was auto-following 303 redirects and dropping `Set-Cookie`.** Add to Cart appeared to do nothing for visitors: the form POST returned 200 with the empty-cart page instead of the expected 303 + Set-Cookie + Location: /cart. Root cause: `_forwardToContainer` constructed the container-side Request with the Workers default `redirect: "follow"`, which auto-follows the storefront's 303 inside the Worker. The auto-followed GET /cart strips the `Set-Cookie: shop_sid=...` header from the intermediate 303 response — so the session cookie never reaches the visitor's browser, the subsequent (visible to the visitor) /cart GET arrives without the session, and the cart-line lookup keys on a fresh empty cart. End result for the visitor: the line WAS persisted to the container's session store, but every subsequent page load creates a new sessionless cart and shows it empty. Fix: `_attemptRequest` constructs the container-side Request with `redirect: "manual"` so the 303 + Set-Cookie chain passes through verbatim to the visitor's browser, which carries the cookie forward through the natural redirect navigation. Same bug affected `/cart/lines/<id>/update`, `/cart/lines/<id>/remove`, `/newsletter`, and any other server-side 303-with-cookie pattern routed through the container — all of those are fixed by the single line change. **Fixed:** *Cart-mutation 303 redirects preserve their `Set-Cookie` end-to-end* — `worker/index.js#_forwardToContainer` now constructs the container-side Request with `redirect: "manual"`. The storefront's POST handlers (`cart/lines`, `cart/lines/<id>/update`, `cart/lines/<id>/remove`, `newsletter`, future checkout submits) all reply with 303 + `Location` + `Set-Cookie: shop_sid=...` on the same response. Manual redirect handling passes that triple verbatim to the visitor's browser, which carries the cookie through the redirect navigation. Add to Cart now persists across the redirect; subsequent /cart loads show the line; the visitor sees what they expected to see when they clicked the button.
14
+
11
15
  - v0.0.116 (2026-05-24) — **Top-level Worker exception catcher — convert Cloudflare 1101 to a clean 503 warming page.** An uncaught exception in the Worker's fetch handler used to propagate to the Cloudflare runtime, which served the generic `Error 1101 — Worker threw exception` page (cf-branded interstitial referencing wrangler tail). Visitors saw a Cloudflare error instead of the framework's render. Every fetch invocation now runs inside `_withTopLevelCatch`: catches every escape, logs to `console.error` (so wrangler tail / Logpush still see the underlying cause), and serves the existing 503 warming-up page with the framework's security headers + a `Retry-After: 10` hint. Cold-start blips during deploys, sporadic D1 / R2 binding hiccups, and any other exception that would have surfaced as 1101 now serve a branded, refresh-aware page that respects the operator's CSP / Permissions-Policy / HSTS posture. **Added:** *Top-level Worker exception catcher (`_withTopLevelCatch`)* — Wraps every `fetch` invocation. On exception: logs the stack via `console.error` (Worker substrate's observability sink — surfaces in `wrangler tail` + Logpush), then returns 503 with the existing `_warmingHtml(request.url, 8)` page + the framework's full security-headers set + `Retry-After: 10` + `Cache-Control: no-store`. Cloudflare's generic 1101 page never reaches the visitor; the cf-managed `Please enable cookies` interstitial only fires when CF's edge layer (Bot Fight Mode / challenge platform) intervenes BEFORE the Worker runs, not from Worker-thrown exceptions.
12
16
 
13
17
  - v0.0.115 (2026-05-23) — **Drop `crossorigin` from the CSS preload Link header — fixes browser preload-credentials-mismatch warning.** Browsers were warning `A preload for '/assets/themes/default/css/main.css?v=0.0.0' is found, but is not used because the request credentials mode does not match. Consider taking a look at crossorigin attribute.` Root cause: the Early Hints / `Link: rel=preload` header carried `crossorigin`, but the matching `<link rel="stylesheet">` tag in the rendered HTML did not. The browser treats the preload as a CORS request, the stylesheet as a same-origin request, and the two don't share a connection — the preloaded byte stream is discarded and the stylesheet is re-fetched from scratch. The asset is genuinely same-origin (`/assets/...`), so `crossorigin` was always wrong on the preload side; removing it lets the preload and stylesheet share the request credentials mode and the browser reuses the preloaded bytes. **Fixed:** *`_earlyHintsLink` emits the CSS preload without `crossorigin`* — `worker/index.js#_earlyHintsLink` now emits `</assets/themes/default/css/main.css?v=...>; rel=preload; as=style` — no `crossorigin` token. The asset is same-origin, the stylesheet `<link>` tag carries no `crossorigin` attribute, and the browser's preload-credentials-match check passes. Devtools no longer warns `request credentials mode does not match`. Operators with per-route extras (hero image preload on PDP, etc.) inherit the same shape — extras already shipped without `crossorigin`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.0.116",
3
+ "version": "0.0.118",
4
4
  "description": "Open-source framework built on blamejs. Vendored stack, zero npm runtime deps, PQC-first crypto, security-on by default.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {