@blamejs/blamejs-shop 0.2.8 → 0.2.9

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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.2.x
10
10
 
11
+ - v0.2.9 (2026-05-27) — **Storefront read pages stay fast for every visitor — the cart badge updates client-side.** Restores full edge-render speed for returning and signed-in shoppers. Every storefront read page (home, product listing, search, blog) now renders at the edge for all visitors again; the nav cart badge renders server-side and a tiny client island corrects the number from a new lightweight endpoint. The result: the fast cached page AND an accurate cart count, without sending a shopper-with-a-cart through the slower origin on every page. **Added:** *`GET /cart/count` + a cart-count island* — A new endpoint returns the current session's cart line count as JSON (`{"count": N}`), cached `no-store`, with no product hydration. A small deferred same-origin script (`assets/js/cart-count.js`) reads it on load and updates the nav badge text and its aria-label. A visitor with JavaScript off keeps the server-rendered badge. The script is a same-origin external file, so the existing `script-src 'self'` policy already permits it — no CSP change required. **Fixed:** *Fast read pages for shoppers who have a session* — A visitor carrying a cart or sign-in cookie is once again served the edge-rendered storefront pages instead of being routed to the origin container, so the home page and other read pages load quickly for returning visitors, not just first-time guests. The nav cart count stays correct via the island below.
12
+
11
13
  - v0.2.8 (2026-05-27) — **A complete shipping address at checkout, and an accurate cart count on every page.** Two storefront fixes. Checkout now collects a real, shippable address — a street line, an optional apt/suite line, and a city — alongside the region, postal code, and country it already took; a signed-in customer's default saved address pre-fills the form, the address shows on the order confirmation, and the order export carries it so fulfilment has everything it needs. Separately, the navigation cart badge now shows the correct item count on the catalog, product, search, and blog pages — not only on the cart and account pages — by rendering those pages for a shopper-with-a-cart on the path that can read their session. **Changed:** *Checkout collects a complete shipping address* — The shipping step now takes a street address (line 1, plus an optional apartment / suite / unit line) and a city in addition to the region, postal code, and country it already collected, so a placed order carries an address you can actually ship to. Street line and city are marked required for the common physical-goods path; the server treats them as optional so a digital-only order still completes. A signed-in customer's default saved address pre-fills the form. · *Shipping address on the confirmation page and in the order export* — The order confirmation now shows the ship-to address, and the order CSV / NDJSON export gains `shipping_line1`, `shipping_line2`, and `shipping_city` columns (inserted after `customer_name`) so a fulfilment handoff has the full address. Consumers that key on the header name are unaffected; a consumer that keys on absolute column position should re-map to the 27-column layout. **Fixed:** *Cart count is correct on every page* — The nav cart badge previously read zero on edge-rendered pages (home, product, search, blog) for a shopper who had items in their cart, while the cart and account pages showed the real count. A request that carries a session cookie is now rendered on the path that can unseal the session and read the cart, so the badge is consistent everywhere. Guests — who have no cart — still get the fast cached render with a count of zero, which is correct for them.
12
14
 
13
15
  - v0.2.7 (2026-05-27) — **Default-theme brand polish — broader favicon support and a larger logo.** Small refinements to the bundled default theme's branding. Every page head now advertises a PNG favicon and an Apple touch icon alongside the existing SVG favicon, so the site icon renders correctly on Safari / iOS home screens and on browsers that don't support SVG favicons, plus a theme-color so the mobile browser chrome matches the dark canvas. The header and footer logo are rendered larger for more presence. These affect the default theme only; a custom theme passed via the theme primitive is unchanged. **Changed:** *Fuller favicon + icon metadata* — The page head now includes a PNG favicon and an `apple-touch-icon` (Apple home-screen icons require PNG — SVG favicons aren't used there) in addition to the SVG favicon, plus a `theme-color` meta for the mobile browser UI. Emitted on every page across both the edge and container render paths. · *Larger header and footer logo* — The default theme renders the brand logo at a larger size in the header and footer for clearer presence.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.8",
2
+ "version": "0.2.9",
3
3
  "assets": {
4
4
  "css/admin.css": {
5
5
  "integrity": "sha384-FgqvXcZygYkJjjOtXAeu9xi6AtYqkchPnJKcS0OeHm8lynhd9r4RfdpoT7P7j7/l",
@@ -13,6 +13,10 @@
13
13
  "integrity": "sha384-z4zcEMn+tScoVnYRE4nEf8N/oyvpxdpaxTNrT4QO/jURChid4+qjAvWkzatCaAPq",
14
14
  "fingerprinted": "js/announcement.59eab4872d2f3b4c.js"
15
15
  },
16
+ "js/cart-count.js": {
17
+ "integrity": "sha384-K/rkm//Dzg8nuOfpaeenJvLKKl+6DEuvuJi1LLgd46BK+dd1HYmU8R7/gHHjtEsr",
18
+ "fingerprinted": "js/cart-count.bfc2eb434b19c00a.js"
19
+ },
16
20
  "js/consent.js": {
17
21
  "integrity": "sha384-KKMQ0og8HPOykRRPpUyxX7dMhTvKySfVtpGX/jGWzZwNaN/c4OykvRvXpqBHcQST",
18
22
  "fingerprinted": "js/consent.517d6ad1fbf106a1.js"
package/lib/storefront.js CHANGED
@@ -266,6 +266,7 @@ var LAYOUT =
266
266
  " </footer>\n" +
267
267
  CONSENT_BANNER +
268
268
  "RAW_CONSENT_SCRIPT" +
269
+ "RAW_CART_COUNT_SCRIPT" +
269
270
  "RAW_ANNOUNCEMENT_SCRIPT" +
270
271
  "</body>\n" +
271
272
  "</html>\n";
@@ -621,6 +622,7 @@ function _wrap(opts) {
621
622
  .replace("RAW_CSS_INTEGRITY", themeCssIntegrity)
622
623
  .replace("RAW_ANNOUNCEMENT_BAR", announcementBarHtml)
623
624
  .replace("RAW_CONSENT_SCRIPT", _islandScript("consent.js", { id: "consent-island", policy: _activeConsentPolicy }))
625
+ .replace("RAW_CART_COUNT_SCRIPT", _islandScript("cart-count.js", { id: "cart-count-island" }))
624
626
  .replace("RAW_ANNOUNCEMENT_SCRIPT", announcementScript)
625
627
  .replace("RAW_CURRENCY_SWITCHER", switcherHtml)
626
628
  .replace("RAW_LOCALE_SWITCHER", localeCtx.switcher_html || "")
@@ -5848,15 +5850,7 @@ function mount(router, deps) {
5848
5850
  }
5849
5851
  }
5850
5852
 
5851
- var sid = _readSidCookie(req);
5852
- var cartCount = 0;
5853
- if (sid) {
5854
- var c = await deps.cart.bySession(sid);
5855
- if (c) {
5856
- var lines = await deps.cart.listLines(c.id);
5857
- cartCount = lines.length;
5858
- }
5859
- }
5853
+ var cartCount = await _cartCountForReq(req);
5860
5854
  var ccy = await _currencyForReq(req);
5861
5855
  _send(res, 200, renderSearch(Object.assign({
5862
5856
  q: q,
@@ -5886,15 +5880,7 @@ function mount(router, deps) {
5886
5880
  // variant-select interaction we don't ship yet.
5887
5881
  var media = await deps.catalog.media.listForProduct(product.id);
5888
5882
  // Render cart count from the current session's cart, if any.
5889
- var sid = _readSidCookie(req);
5890
- var cartCount = 0;
5891
- if (sid) {
5892
- var c = await deps.cart.bySession(sid);
5893
- if (c) {
5894
- var lines = await deps.cart.listLines(c.id);
5895
- cartCount = lines.length;
5896
- }
5897
- }
5883
+ var cartCount = await _cartCountForReq(req);
5898
5884
  // Published reviews aggregate + list. A failed read (e.g. the
5899
5885
  // reviews table not yet migrated) degrades to the empty state
5900
5886
  // rather than 500-ing the whole PDP — reviews are supplementary
@@ -6298,6 +6284,21 @@ function mount(router, deps) {
6298
6284
  });
6299
6285
  }
6300
6286
 
6287
+ // Nav cart-badge count for the cart-count island. Every storefront
6288
+ // chrome page server-renders the badge (0 on the cookie-less edge-cached
6289
+ // render); the island fetches this on load and corrects the number for a
6290
+ // visitor whose sealed `shop_sid` the edge can't read. JSON only — one
6291
+ // session lookup, no product hydration — and never cached (a per-session
6292
+ // value must not land in a shared cache).
6293
+ router.get("/cart/count", async function (req, res) {
6294
+ var count = await _cartCountForReq(req);
6295
+ res.status(200);
6296
+ res.setHeader && res.setHeader("content-type", "application/json; charset=utf-8");
6297
+ res.setHeader && res.setHeader("cache-control", "no-store");
6298
+ var payload = JSON.stringify({ count: count });
6299
+ return res.end ? res.end(payload) : res.send(payload);
6300
+ });
6301
+
6301
6302
  router.get("/cart", async function (req, res) {
6302
6303
  var ccy = await _currencyForReq(req);
6303
6304
  var sid = _readSidCookie(req);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
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": {