astroidjs 0.12.0 → 0.13.0

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 (133) hide show
  1. package/README.md +42 -42
  2. package/bin/astroid.mjs +25 -25
  3. package/dist/analytics/index.d.ts +3 -3
  4. package/dist/analytics/index.js +9 -9
  5. package/dist/astro/csp.d.ts +5 -5
  6. package/dist/astro/csp.js +6 -6
  7. package/dist/astro/index.js +1 -1
  8. package/dist/auth/index.d.ts +2 -2
  9. package/dist/auth/index.js +5 -5
  10. package/dist/commerce/adapters.d.ts +6 -6
  11. package/dist/commerce/adapters.js +9 -9
  12. package/dist/commerce/checkout-scaffold.d.ts +5 -5
  13. package/dist/commerce/checkout-scaffold.js +9 -9
  14. package/dist/commerce/checkout.d.ts +12 -12
  15. package/dist/commerce/checkout.js +7 -7
  16. package/dist/commerce/loader.d.ts +2 -2
  17. package/dist/commerce/loader.js +3 -3
  18. package/dist/commerce/mirror.d.ts +4 -4
  19. package/dist/commerce/mirror.js +9 -9
  20. package/dist/commerce/roles.d.ts +10 -10
  21. package/dist/commerce/roles.js +13 -13
  22. package/dist/commerce/secrets.d.ts +9 -9
  23. package/dist/commerce/secrets.js +9 -9
  24. package/dist/commerce/sync.d.ts +7 -7
  25. package/dist/commerce/sync.js +5 -5
  26. package/dist/components/sections.d.ts +9 -9
  27. package/dist/components/sections.js +12 -12
  28. package/dist/config.d.ts +62 -62
  29. package/dist/config.js +18 -18
  30. package/dist/email/inquiry.d.ts +2 -2
  31. package/dist/email/inquiry.js +1 -1
  32. package/dist/email/send.d.ts +4 -4
  33. package/dist/email/send.js +7 -7
  34. package/dist/email/templates.js +3 -3
  35. package/dist/email/theme.d.ts +1 -1
  36. package/dist/email/theme.js +4 -4
  37. package/dist/errors.d.ts +1 -1
  38. package/dist/errors.js +1 -1
  39. package/dist/index.js +1 -1
  40. package/dist/map/pmtiles.d.ts +5 -5
  41. package/dist/map/pmtiles.js +5 -5
  42. package/dist/map/scaffold.d.ts +2 -2
  43. package/dist/map/scaffold.js +4 -4
  44. package/dist/map/style.d.ts +4 -4
  45. package/dist/map/style.js +1 -1
  46. package/dist/portal/config.d.ts +2 -2
  47. package/dist/portal/config.js +3 -3
  48. package/dist/portal/guard.d.ts +4 -4
  49. package/dist/portal/guard.js +4 -4
  50. package/dist/portal/nav.js +2 -2
  51. package/dist/portal/scaffold.d.ts +4 -4
  52. package/dist/portal/scaffold.js +6 -6
  53. package/dist/portal/session.d.ts +2 -2
  54. package/dist/portal/session.js +5 -5
  55. package/dist/portfolio/scaffold.d.ts +1 -1
  56. package/dist/portfolio/scaffold.js +4 -4
  57. package/dist/project/actions.d.ts +1 -1
  58. package/dist/project/actions.js +6 -6
  59. package/dist/project/generate.d.ts +4 -4
  60. package/dist/project/generate.js +15 -15
  61. package/dist/project/index.js +1 -1
  62. package/dist/project/scaffold.d.ts +2 -2
  63. package/dist/project/scaffold.js +11 -11
  64. package/dist/pwa/generate.d.ts +11 -11
  65. package/dist/pwa/generate.js +12 -12
  66. package/dist/queues/consumer.d.ts +3 -3
  67. package/dist/queues/consumer.js +2 -2
  68. package/dist/queues/messages.d.ts +4 -4
  69. package/dist/queues/messages.js +2 -2
  70. package/dist/queues/scaffold.d.ts +4 -4
  71. package/dist/queues/scaffold.js +8 -8
  72. package/dist/queues/webhook.d.ts +5 -5
  73. package/dist/queues/webhook.js +3 -3
  74. package/dist/realtime/scaffold.d.ts +4 -4
  75. package/dist/realtime/scaffold.js +8 -8
  76. package/dist/schema/collections.d.ts +6 -6
  77. package/dist/schema/collections.js +23 -23
  78. package/dist/schema/framework.d.ts +1 -1
  79. package/dist/schema/framework.js +2 -2
  80. package/dist/schema/generate.js +2 -2
  81. package/dist/schema/index.js +1 -1
  82. package/dist/secrets.d.ts +6 -6
  83. package/dist/secrets.js +6 -6
  84. package/dist/security/csp-origins.d.ts +1 -1
  85. package/dist/security/csp-origins.js +3 -3
  86. package/dist/security/rate-rules.d.ts +2 -2
  87. package/dist/security/rate-rules.js +8 -8
  88. package/dist/seo/resolve.d.ts +5 -5
  89. package/dist/seo/resolve.js +2 -2
  90. package/dist/seo/routes.d.ts +5 -5
  91. package/dist/seo/routes.js +3 -3
  92. package/dist/seo/structured-data.d.ts +6 -6
  93. package/dist/seo/structured-data.js +7 -7
  94. package/dist/status.d.ts +5 -5
  95. package/dist/status.js +7 -7
  96. package/dist/tenancy/index.d.ts +3 -3
  97. package/dist/tenancy/index.js +6 -6
  98. package/dist/worker/generate.d.ts +2 -2
  99. package/dist/worker/generate.js +19 -19
  100. package/dist/worker/index.js +1 -1
  101. package/dist/worker/routes.js +1 -1
  102. package/dist/workflow/advance.d.ts +3 -3
  103. package/dist/workflow/advance.js +6 -6
  104. package/dist/workflow/config.d.ts +4 -4
  105. package/dist/workflow/config.js +4 -4
  106. package/dist/workflow/generate.d.ts +2 -2
  107. package/dist/workflow/generate.js +4 -4
  108. package/package.json +5 -5
  109. package/src/components/Collection.tsx +5 -5
  110. package/src/components/Editable.astro +9 -9
  111. package/src/components/JustifiedGallery.astro +8 -8
  112. package/src/components/MediaSlot.astro +12 -12
  113. package/src/components/PortalShell.astro +4 -4
  114. package/src/components/RegisterSW.astro +3 -3
  115. package/src/components/Section.astro +8 -8
  116. package/src/components/Sections.astro +6 -6
  117. package/src/components/Seo.astro +3 -3
  118. package/src/components/StageBar.astro +3 -3
  119. package/src/components/StructuredData.astro +2 -2
  120. package/src/components/justify.ts +9 -9
  121. package/src/components/media-meta.ts +10 -10
  122. package/src/components/sections/AboutIntro.astro +1 -1
  123. package/src/components/sections/Contact.astro +1 -1
  124. package/src/components/sections/Cta.astro +1 -1
  125. package/src/components/sections/Faq.astro +1 -1
  126. package/src/components/sections/FeatureGrid.astro +2 -2
  127. package/src/components/sections/Hero.astro +1 -1
  128. package/src/components/sections/PricingTiers.astro +1 -1
  129. package/src/components/sections/ProductGrid.astro +1 -1
  130. package/src/components/sections/SplitImage.astro +1 -1
  131. package/src/components/sections/Steps.astro +1 -1
  132. package/src/components/sections/Testimonial.astro +1 -1
  133. package/src/components/sections.ts +17 -17
@@ -1,6 +1,6 @@
1
1
  // Copyright (c) 2026 BowenLabs. Astroid is MIT licensed.
2
2
  //
3
- // `astroidjs/astro` — the BUILD-TIME surface, imported from `astro.config.mjs`.
3
+ // `astroidjs/astro`—the BUILD-TIME surface, imported from `astro.config.mjs`.
4
4
  // Kept off the main entry on purpose: it reaches for `node:crypto` and
5
5
  // `solid-js/web`, neither of which belongs in the Worker bundle the generated
6
6
  // `worker.ts` produces.
@@ -1,6 +1,6 @@
1
1
  import type { AstroidConfig } from "../config.js";
2
2
  /**
3
- * The editor Better Auth instance's table prefix — `louise_user`,
3
+ * The editor Better Auth instance's table prefix—`louise_user`,
4
4
  * `louise_session`, … The unprefixed names are left free for a second (portal)
5
5
  * instance. Consumed by the generated `editorsRoute` and mirrored by the
6
6
  * scaffolded `src/auth.ts` (`getLouiseAuth({ tablePrefix })`) + its migration.
@@ -12,7 +12,7 @@ export declare const ASTROID_EDITOR_TABLE_PREFIX = "louise_";
12
12
  * reject a portal that would collide with it.
13
13
  */
14
14
  export declare const ASTROID_EDITOR_COOKIE_PREFIX = "better-auth";
15
- /** The editor's Better Auth table name for a given model (e.g. `louise_user`). */
15
+ /** The editor's Better Auth table name for a given model (for example, `louise_user`). */
16
16
  export declare function astroidEditorTable(model: string): string;
17
17
  /**
18
18
  * Reject a portal whose isolation would collide with the editor instance on the
@@ -3,12 +3,12 @@
3
3
  // Editor-auth convention + the two-instance isolation guard.
4
4
  //
5
5
  // Astroid runs up to TWO Better Auth instances on one origin: the EDITOR (the
6
- // studio — magic-link + passkey, a DB-managed admin allowlist) and, optionally, a
7
- // second PORTAL instance (customers/members/a shop account — see `portal/`). The
6
+ // studio—magic-link + passkey, a DB-managed admin allowlist) and, optionally, a
7
+ // second PORTAL instance (customers/members/a shop account—see `portal/`). The
8
8
  // editor owns Better Auth's default mount (`/api/auth`) and cookie because the
9
9
  // Louise editor client hardcodes them; its tables are namespaced with the
10
10
  // `louise_` prefix so a second instance can take the unprefixed `user`/`session`
11
- // tables without collision. The portal is the one that MOVES — a distinct mount,
11
+ // tables without collision. The portal is the one that MOVES—a distinct mount,
12
12
  // cookie prefix, and (by default) table prefix.
13
13
  //
14
14
  // The failure this guards against is subtle and intermittent: two instances that
@@ -18,7 +18,7 @@
18
18
  import { AstroidConfigError } from "../errors.js";
19
19
  import { astroidPortal } from "../portal/config.js";
20
20
  /**
21
- * The editor Better Auth instance's table prefix — `louise_user`,
21
+ * The editor Better Auth instance's table prefix—`louise_user`,
22
22
  * `louise_session`, … The unprefixed names are left free for a second (portal)
23
23
  * instance. Consumed by the generated `editorsRoute` and mirrored by the
24
24
  * scaffolded `src/auth.ts` (`getLouiseAuth({ tablePrefix })`) + its migration.
@@ -30,7 +30,7 @@ export const ASTROID_EDITOR_TABLE_PREFIX = "louise_";
30
30
  * reject a portal that would collide with it.
31
31
  */
32
32
  export const ASTROID_EDITOR_COOKIE_PREFIX = "better-auth";
33
- /** The editor's Better Auth table name for a given model (e.g. `louise_user`). */
33
+ /** The editor's Better Auth table name for a given model (for example, `louise_user`). */
34
34
  export function astroidEditorTable(model) {
35
35
  return `${ASTROID_EDITOR_TABLE_PREFIX}${model}`;
36
36
  }
@@ -62,7 +62,7 @@ export interface FourthwallProductLike {
62
62
  * Is this item sold at `locationId` at all?
63
63
  *
64
64
  * Exported because a location-scoped sync needs to SKIP items the merchant
65
- * doesn't carry, and `squareToCatalogItem` can't do that for you — it returns
65
+ * doesn't carry, and `squareToCatalogItem` can't do that for you—it returns
66
66
  * one item, and "don't store this row" isn't a `CatalogItem`. Without the guard
67
67
  * an unstocked item mirrors as a $0 card with no variants, which looks like a
68
68
  * pricing bug rather than a catalog decision.
@@ -79,7 +79,7 @@ export declare function squareItemSoldAt(item: SquareItemLike, locationId: strin
79
79
  *
80
80
  * `price` is the LOWEST variation price. A Square item is a family ("Bag of
81
81
  * beans" with 12oz and 2lb variations), so a single headline number has to mean
82
- * "from" — taking the first variation's price instead would change with Square's
82
+ * "from"—taking the first variation's price instead would change with Square's
83
83
  * ordering and quietly misprice the card.
84
84
  *
85
85
  * ## Scoping to one merchant
@@ -90,22 +90,22 @@ export declare function squareItemSoldAt(item: SquareItemLike, locationId: strin
90
90
  *
91
91
  * The headline number has to be scoped for the same reason the variants are.
92
92
  * "From $8" computed over the whole catalog, on a page where the $8 size isn't
93
- * stocked, advertises a price this merchant will never honour — and because the
93
+ * stocked, advertises a price this merchant will never honour—and because the
94
94
  * dropped variation is usually the cheap one, the error runs in the direction a
95
95
  * customer notices at the till.
96
96
  *
97
97
  * Unscoped behaviour is unchanged: no `locationId` means base prices and every
98
98
  * variation, which is correct for a single-location account.
99
99
  *
100
- * An item sold nowhere at `locationId` yields no variants and a price of 0 —
101
- * filter with {@link squareItemSoldAt} before calling rather than storing that.
100
+ * An item sold nowhere at `locationId` yields no variants and a price of 0—filter
101
+ * with {@link squareItemSoldAt} before calling rather than storing that.
102
102
  */
103
103
  export declare function squareToCatalogItem(item: SquareItemLike, options?: SquareAdapterOptions): CatalogItem;
104
104
  /**
105
105
  * Fourthwall product → `CatalogItem`. Same "lowest variant wins" rule as Square,
106
106
  * for the same reason.
107
107
  *
108
- * Fourthwall already prices in major units, so there's no conversion — mirroring
108
+ * Fourthwall already prices in major units, so there's no conversion—mirroring
109
109
  * `lowestPrice` in `louise-toolkit/commerce/fourthwall`.
110
110
  */
111
111
  export declare function fourthwallToCatalogItem(product: FourthwallProductLike): CatalogItem;
@@ -4,20 +4,20 @@
4
4
  //
5
5
  // This is the file the whole module exists for. themidwestartist.com's loader
6
6
  // says it outright: coracle runs the same helper over Square, "only the
7
- // content/repo reads differ — issue: repo drift." Two sites, one intent, two
7
+ // content/repo reads differ—issue: repo drift." Two sites, one intent, two
8
8
  // hand-written translations that drifted apart. The translation is mechanical,
9
9
  // so it belongs here once.
10
10
  //
11
11
  // Each provider's client already returns a normalized-for-that-provider shape
12
12
  // (`SquareCatalogItem`, `FwProduct`); these functions take that last step to the
13
- // shape the mirror stores. Deliberately pure — they take the provider's objects,
13
+ // shape the mirror stores. Deliberately pure—they take the provider's objects,
14
14
  // not credentials or an `env`, so they're trivially testable and the caller
15
15
  // keeps control of how the fetch happens (cached, paged, rate-limited).
16
16
  /**
17
17
  * Is this object sold at `locationId`?
18
18
  *
19
19
  * Mirrors `presentAt` in `louise-toolkit/commerce/square`, but tolerant of the
20
- * fields being absent. The two lists are NOT symmetric — `presentAtLocationIds`
20
+ * fields being absent. The two lists are NOT symmetric—`presentAtLocationIds`
21
21
  * is a whitelist consulted when `presentAtAllLocations` is false,
22
22
  * `absentAtLocationIds` a blacklist consulted when it is true. Reading them the
23
23
  * other way round shows a merchant products they do not carry.
@@ -40,7 +40,7 @@ const toMajor = (cents) => Math.round(cents) / 100;
40
40
  * Is this item sold at `locationId` at all?
41
41
  *
42
42
  * Exported because a location-scoped sync needs to SKIP items the merchant
43
- * doesn't carry, and `squareToCatalogItem` can't do that for you — it returns
43
+ * doesn't carry, and `squareToCatalogItem` can't do that for you—it returns
44
44
  * one item, and "don't store this row" isn't a `CatalogItem`. Without the guard
45
45
  * an unstocked item mirrors as a $0 card with no variants, which looks like a
46
46
  * pricing bug rather than a catalog decision.
@@ -61,7 +61,7 @@ export function squareItemSoldAt(item, locationId) {
61
61
  *
62
62
  * `price` is the LOWEST variation price. A Square item is a family ("Bag of
63
63
  * beans" with 12oz and 2lb variations), so a single headline number has to mean
64
- * "from" — taking the first variation's price instead would change with Square's
64
+ * "from"—taking the first variation's price instead would change with Square's
65
65
  * ordering and quietly misprice the card.
66
66
  *
67
67
  * ## Scoping to one merchant
@@ -72,15 +72,15 @@ export function squareItemSoldAt(item, locationId) {
72
72
  *
73
73
  * The headline number has to be scoped for the same reason the variants are.
74
74
  * "From $8" computed over the whole catalog, on a page where the $8 size isn't
75
- * stocked, advertises a price this merchant will never honour — and because the
75
+ * stocked, advertises a price this merchant will never honour—and because the
76
76
  * dropped variation is usually the cheap one, the error runs in the direction a
77
77
  * customer notices at the till.
78
78
  *
79
79
  * Unscoped behaviour is unchanged: no `locationId` means base prices and every
80
80
  * variation, which is correct for a single-location account.
81
81
  *
82
- * An item sold nowhere at `locationId` yields no variants and a price of 0 —
83
- * filter with {@link squareItemSoldAt} before calling rather than storing that.
82
+ * An item sold nowhere at `locationId` yields no variants and a price of 0—filter
83
+ * with {@link squareItemSoldAt} before calling rather than storing that.
84
84
  */
85
85
  export function squareToCatalogItem(item, options = {}) {
86
86
  const locationId = options.locationId;
@@ -117,7 +117,7 @@ export function squareToCatalogItem(item, options = {}) {
117
117
  * Fourthwall product → `CatalogItem`. Same "lowest variant wins" rule as Square,
118
118
  * for the same reason.
119
119
  *
120
- * Fourthwall already prices in major units, so there's no conversion — mirroring
120
+ * Fourthwall already prices in major units, so there's no conversion—mirroring
121
121
  * `lowestPrice` in `louise-toolkit/commerce/fourthwall`.
122
122
  */
123
123
  export function fourthwallToCatalogItem(product) {
@@ -2,7 +2,7 @@ import type { AstroidConfig } from "../config.js";
2
2
  /** Does this project take card payments in-page? Square storefront only. */
3
3
  export declare function usesCardCheckout(config: AstroidConfig): boolean;
4
4
  /**
5
- * `src/pages/api/checkout.ts` — the server-authoritative payment route.
5
+ * `src/pages/api/checkout.ts`—the server-authoritative payment route.
6
6
  *
7
7
  * Scaffold-once: a real store adds shipping, tax, an order record, a receipt
8
8
  * email. What Astroid fixes is the sequence, because every step of it is a place
@@ -12,7 +12,7 @@ export declare function usesCardCheckout(config: AstroidConfig): boolean;
12
12
  */
13
13
  export declare function generateAstroidCheckoutRoute(config: AstroidConfig): string | null;
14
14
  /**
15
- * `src/components/SquareCard.astro` — the card input.
15
+ * `src/components/SquareCard.astro`—the card input.
16
16
  *
17
17
  * Square's Web Payments SDK renders the field in an iframe from their CDN and
18
18
  * hands back a single-use token, so the raw card number never touches the Worker
@@ -29,13 +29,13 @@ export declare function generateAstroidSquareCard(config: AstroidConfig): string
29
29
  * application id is shipped to the browser by design, and the environment is a
30
30
  * choice, not a credential. Putting them in `credentials` would also fold them
31
31
  * into the dormancy gate, which is about whether the module can safely CALL
32
- * Square — a different question from whether the card field can render.
32
+ * Square—a different question from whether the card field can render.
33
33
  *
34
34
  * The two vars are gated SEPARATELY, and that split is load-bearing.
35
35
  * `SQUARE_ENVIRONMENT` selects the API HOST for every Square call, so it belongs
36
36
  * to any project that talks to Square at all; `SQUARE_APP_ID` only mounts the
37
- * browser card field. Gating both on card checkout — as this did until
38
- * `invoicing: "square"` became expressible — left a site that runs Square for
37
+ * browser card field. Gating both on card checkout—as this did until
38
+ * `invoicing: "square"` became expressible—left a site that runs Square for
39
39
  * invoicing alone with no `SQUARE_ENVIRONMENT`, and `SquareConfig.environment`
40
40
  * defaults to "sandbox". Every production invoice would have been created
41
41
  * against the sandbox: no error, no warning, just money that never arrives.
@@ -1,6 +1,6 @@
1
1
  // Copyright (c) 2026 BowenLabs. Astroid is MIT licensed.
2
2
  //
3
- // The checkout SEAM — the piece that made `archetype: "storefront"` a storefront
3
+ // The checkout SEAM—the piece that made `archetype: "storefront"` a storefront
4
4
  // that couldn't take a card.
5
5
  //
6
6
  // Everything around this already existed: `verifyCheckout` re-prices server-side,
@@ -10,7 +10,7 @@
10
10
  // missing was the route in the middle, so none of it was reachable.
11
11
  //
12
12
  // SCOPE, deliberately narrow. This generates the server-authoritative PAYMENT
13
- // path and a card input — not a cart, not a checkout page, not shipping or tax.
13
+ // path and a card input—not a cart, not a checkout page, not shipping or tax.
14
14
  // Where a cart lives (localStorage, D1, a portal session), what it holds, and how
15
15
  // it renders are project decisions Astroid has no business making, and a
16
16
  // half-opinionated cart is worse than none. What is NOT a project decision is the
@@ -26,7 +26,7 @@ export function usesCardCheckout(config) {
26
26
  return astroidCommerceRoles(config.commerce).storefront === "square";
27
27
  }
28
28
  /**
29
- * `src/pages/api/checkout.ts` — the server-authoritative payment route.
29
+ * `src/pages/api/checkout.ts`—the server-authoritative payment route.
30
30
  *
31
31
  * Scaffold-once: a real store adds shipping, tax, an order record, a receipt
32
32
  * email. What Astroid fixes is the sequence, because every step of it is a place
@@ -319,7 +319,7 @@ export function generateAstroidCheckoutRoute(config) {
319
319
  .join("\n");
320
320
  }
321
321
  /**
322
- * `src/components/SquareCard.astro` — the card input.
322
+ * `src/components/SquareCard.astro`—the card input.
323
323
  *
324
324
  * Square's Web Payments SDK renders the field in an iframe from their CDN and
325
325
  * hands back a single-use token, so the raw card number never touches the Worker
@@ -417,7 +417,7 @@ export function generateAstroidSquareCard(config) {
417
417
  .filter((line) => line !== null)
418
418
  .join("\n");
419
419
  }
420
- /** Does this project talk to Square in ANY role — storefront, invoicing, or
420
+ /** Does this project talk to Square in ANY role—storefront, invoicing, or
421
421
  * otherwise? Distinct from {@link usesCardCheckout}, which asks the narrower
422
422
  * question of whether the in-page card field renders. */
423
423
  function usesSquare(config) {
@@ -430,13 +430,13 @@ function usesSquare(config) {
430
430
  * application id is shipped to the browser by design, and the environment is a
431
431
  * choice, not a credential. Putting them in `credentials` would also fold them
432
432
  * into the dormancy gate, which is about whether the module can safely CALL
433
- * Square — a different question from whether the card field can render.
433
+ * Square—a different question from whether the card field can render.
434
434
  *
435
435
  * The two vars are gated SEPARATELY, and that split is load-bearing.
436
436
  * `SQUARE_ENVIRONMENT` selects the API HOST for every Square call, so it belongs
437
437
  * to any project that talks to Square at all; `SQUARE_APP_ID` only mounts the
438
- * browser card field. Gating both on card checkout — as this did until
439
- * `invoicing: "square"` became expressible — left a site that runs Square for
438
+ * browser card field. Gating both on card checkout—as this did until
439
+ * `invoicing: "square"` became expressible—left a site that runs Square for
440
440
  * invoicing alone with no `SQUARE_ENVIRONMENT`, and `SquareConfig.environment`
441
441
  * defaults to "sandbox". Every production invoice would have been created
442
442
  * against the sandbox: no error, no warning, just money that never arrives.
@@ -459,7 +459,7 @@ export function astroidCheckoutVars(config) {
459
459
  * substitutes into `src/env.d.ts`. Empty without card checkout.
460
460
  */
461
461
  export function generateAstroidCheckoutEnv(config) {
462
- // Mirrors the gating in `astroidCheckoutVars` — the app id is card-checkout
462
+ // Mirrors the gating in `astroidCheckoutVars`—the app id is card-checkout
463
463
  // only, the environment belongs to any project that calls Square at all.
464
464
  const lines = [];
465
465
  if (usesCardCheckout(config)) {
@@ -28,13 +28,13 @@ export interface VerifiedLine {
28
28
  * worth a notify-me. Collapsing them tells someone to remove an item the shop
29
29
  * will restock on Tuesday.
30
30
  *
31
- * A lookup can only produce `"out-of-stock"` by saying so — see
32
- * {@link ScopedPriceLookup} — because a bare `Map` has no way to distinguish
31
+ * A lookup can only produce `"out-of-stock"` by saying so—see
32
+ * {@link ScopedPriceLookup}—because a bare `Map` has no way to distinguish
33
33
  * them and guessing would put the wrong sentence on the screen.
34
34
  */
35
35
  export type CheckoutRefusal = "empty" | "unavailable" | "out-of-stock" | "price-changed" | "invalid";
36
36
  /**
37
- * One way the cart disagrees with the live catalog — the toolkit's
37
+ * One way the cart disagrees with the live catalog—the toolkit's
38
38
  * `CartIssue`, less the add-on case (checkout lines carry no add-ons yet).
39
39
  * Hand the list to `repairCart` from `louise-toolkit/commerce` to fix the cart
40
40
  * in one step.
@@ -52,7 +52,7 @@ export type CheckoutVerification = {
52
52
  reason: CheckoutRefusal;
53
53
  message: string;
54
54
  /**
55
- * Every problem, in cart order, with what the catalog says now — empty
55
+ * Every problem, in cart order, with what the catalog says now—empty
56
56
  * for `"empty"` and `"invalid"`, which are about the request, not the
57
57
  * catalog.
58
58
  */
@@ -62,7 +62,7 @@ export type CheckoutVerification = {
62
62
  * map omits is treated as no longer purchasable. */
63
63
  export type PriceLookup = (variantIds: string[]) => Promise<Map<string, number>>;
64
64
  /** Where the sale is happening. Optional, and providers without a location
65
- * dimension ignore it — a single-merchant Square account or Fourthwall store
65
+ * dimension ignore it—a single-merchant Square account or Fourthwall store
66
66
  * passes nothing and behaves exactly as before. */
67
67
  export interface CheckoutScope {
68
68
  /** Provider location id (Square) or equivalent merchant key. */
@@ -86,13 +86,13 @@ export interface ScopedPrices {
86
86
  * A price lookup that knows WHERE the sale is happening.
87
87
  *
88
88
  * This is the multi-merchant checkout guard. One shared catalog sold through
89
- * several merchants carries a different price per location — each shop's
90
- * commission is absorbed in its own override — so re-pricing a cart against
89
+ * several merchants carries a different price per location—each shop's
90
+ * commission is absorbed in its own override—so re-pricing a cart against
91
91
  * base prices lets a customer pay the cheapest merchant's price at the dearest
92
92
  * merchant's storefront. That is not a rounding error; it is the same class of
93
93
  * bug as trusting the client's `unitPriceCents`, just one level further back.
94
94
  *
95
- * `scope` is optional so a {@link PriceLookup} is still assignable here — an
95
+ * `scope` is optional so a {@link PriceLookup} is still assignable here—an
96
96
  * existing single-location lookup simply ignores the extra argument, which is
97
97
  * exactly what a function of lower arity does in JavaScript.
98
98
  *
@@ -131,7 +131,7 @@ export declare function verifyCheckout(lines: unknown, lookup: ScopedPriceLookup
131
131
  /**
132
132
  * A deterministic idempotency key for one buyer's checkout attempt.
133
133
  *
134
- * Providers dedupe on this, so the same key must mean the same charge — which
134
+ * Providers dedupe on this, so the same key must mean the same charge—which
135
135
  * cuts both ways, and the second direction is the one that costs money. It is
136
136
  * derived from the verified cart *and* `identity`, not from a random value or a
137
137
  * timestamp: a customer double-clicking Pay sends the same key twice and is
@@ -141,18 +141,18 @@ export declare function verifyCheckout(lines: unknown, lookup: ScopedPriceLookup
141
141
  * **`identity` is required, and it is what makes the key safe.** Without it the
142
142
  * key was a pure function of the cart contents, so two DIFFERENT customers
143
143
  * buying the same thing for the same price produced byte-identical keys. Stripe
144
- * and Square scope idempotency keys per account and retain them for ~24h, so the
144
+ * and Square scope idempotency keys per account and retain them for about 24 hours, so the
145
145
  * provider replayed the first customer's PaymentIntent instead of creating the
146
146
  * second's: the second buyer was never charged, no second order existed, and the
147
147
  * site reported success. On a single-SKU storefront that is ordinary traffic,
148
148
  * not an edge case.
149
149
  *
150
150
  * Pass something stable across a retry of THIS attempt and distinct between
151
- * buyers — a cart id, a checkout-session id, or a portal user id. Do not pass a
151
+ * buyers—a cart id, a checkout-session id, or a portal user id. Do not pass a
152
152
  * value that varies per request (a fresh uuid defeats the dedupe and a
153
153
  * double-click charges twice), and do not pass a constant.
154
154
  *
155
- * `scope` remains the OPERATION — `"order"` vs `"refund"` — so the two can never
155
+ * `scope` remains the OPERATION—`"order"` vs `"refund"`—so the two can never
156
156
  * collide for one buyer. It is not an identity and never was.
157
157
  */
158
158
  export declare function checkoutIdempotencyKey(verified: {
@@ -3,7 +3,7 @@
3
3
  // Server-authoritative checkout.
4
4
  //
5
5
  // A cart arrives from the browser, so every number in it is a claim, not a fact.
6
- // The rule this encodes — taken from coracle.coffee's working checkout — is that
6
+ // The rule this encodes—taken from coracle.coffee's working checkout—is that
7
7
  // the client's price is a **staleness check**, never an input to the charge:
8
8
  // look the price up server-side, and if it disagrees with what the customer was
9
9
  // shown, refuse rather than silently charging a different amount. Refusing is
@@ -16,7 +16,7 @@
16
16
  // The comparison itself is the toolkit's `cartIssues`, which reports EVERY
17
17
  // stale line rather than the first: a refusal that names one problem at a time
18
18
  // is how a customer ends up fixing a line, retrying, and being refused over the
19
- // next. What this adds is the opinion — policing the untrusted body, and the
19
+ // next. What this adds is the opinion—policing the untrusted body, and the
20
20
  // sentence a customer sees.
21
21
  import { cartIssues } from "louise-toolkit/commerce";
22
22
  import { AstroidUsageError } from "../errors.js";
@@ -91,7 +91,7 @@ lookup, options = {}) {
91
91
  }
92
92
  const { prices, outOfStock } = normalizeLookup(await lookup([...new Set(parsed.map((l) => l.variantId))], options.scope));
93
93
  // No `liveModifierIds`, so the add-on check is skipped and every issue is a
94
- // variant one — which is what makes the narrowing to CheckoutIssue true.
94
+ // variant one—which is what makes the narrowing to CheckoutIssue true.
95
95
  const issues = cartIssues(parsed, { prices, outOfStock });
96
96
  const [first] = issues;
97
97
  if (first)
@@ -109,7 +109,7 @@ lookup, options = {}) {
109
109
  /**
110
110
  * A deterministic idempotency key for one buyer's checkout attempt.
111
111
  *
112
- * Providers dedupe on this, so the same key must mean the same charge — which
112
+ * Providers dedupe on this, so the same key must mean the same charge—which
113
113
  * cuts both ways, and the second direction is the one that costs money. It is
114
114
  * derived from the verified cart *and* `identity`, not from a random value or a
115
115
  * timestamp: a customer double-clicking Pay sends the same key twice and is
@@ -119,18 +119,18 @@ lookup, options = {}) {
119
119
  * **`identity` is required, and it is what makes the key safe.** Without it the
120
120
  * key was a pure function of the cart contents, so two DIFFERENT customers
121
121
  * buying the same thing for the same price produced byte-identical keys. Stripe
122
- * and Square scope idempotency keys per account and retain them for ~24h, so the
122
+ * and Square scope idempotency keys per account and retain them for about 24 hours, so the
123
123
  * provider replayed the first customer's PaymentIntent instead of creating the
124
124
  * second's: the second buyer was never charged, no second order existed, and the
125
125
  * site reported success. On a single-SKU storefront that is ordinary traffic,
126
126
  * not an edge case.
127
127
  *
128
128
  * Pass something stable across a retry of THIS attempt and distinct between
129
- * buyers — a cart id, a checkout-session id, or a portal user id. Do not pass a
129
+ * buyers—a cart id, a checkout-session id, or a portal user id. Do not pass a
130
130
  * value that varies per request (a fresh uuid defeats the dedupe and a
131
131
  * double-click charges twice), and do not pass a constant.
132
132
  *
133
- * `scope` remains the OPERATION — `"order"` vs `"refund"` — so the two can never
133
+ * `scope` remains the OPERATION—`"order"` vs `"refund"`—so the two can never
134
134
  * collide for one buyer. It is not an identity and never was.
135
135
  */
136
136
  export async function checkoutIdempotencyKey(verified, scope, identity) {
@@ -1,7 +1,7 @@
1
1
  import type { CatalogItem } from "./sync.js";
2
2
  /** A product as the site renders it: the mirror row, decoded. */
3
3
  export interface CatalogProduct extends CatalogItem {
4
- /** Public URL segment — owner-owned, stable across provider renames. */
4
+ /** Public URL segment—owner-owned, stable across provider renames. */
5
5
  slug: string;
6
6
  status: "draft" | "published";
7
7
  sortOrder: number;
@@ -55,7 +55,7 @@ export declare function readCatalogItem(slug: string, options: CatalogReadOption
55
55
  * );
56
56
  * ```
57
57
  *
58
- * Identical for every provider — which is the whole point.
58
+ * Identical for every provider—which is the whole point.
59
59
  */
60
60
  export declare function astroidCatalogLoaderConfig(options: CatalogReadOptions & {
61
61
  name?: string;
@@ -3,8 +3,8 @@
3
3
  // The catalog read, and the Live Content Collection loader over it.
4
4
  //
5
5
  // `defineCatalogLoader` (@louise-toolkit/astro) already owns the Astro-facing
6
- // plumbing. What each site then hand-wrote was the layer underneath — "read my
7
- // catalog out of D1" — and because that layer was per-site, so was the drift.
6
+ // plumbing. What each site then hand-wrote was the layer underneath—"read my
7
+ // catalog out of D1"—and because that layer was per-site, so was the drift.
8
8
  // It doesn't need to be: once the mirror table's shape is fixed (see mirror.ts),
9
9
  // reading it is the same query whatever provider filled it in.
10
10
  //
@@ -73,7 +73,7 @@ export async function readCatalogItem(slug, options) {
73
73
  * );
74
74
  * ```
75
75
  *
76
- * Identical for every provider — which is the whole point.
76
+ * Identical for every provider—which is the whole point.
77
77
  */
78
78
  export function astroidCatalogLoaderConfig(options) {
79
79
  return {
@@ -25,8 +25,8 @@ export interface CatalogMirrorConfig {
25
25
  }
26
26
  /**
27
27
  * Columns Astroid always PULLS, overwriting each sync. Fixed rather than
28
- * configurable because they're the intersection of what every provider returns —
29
- * a project that wants a provider-specific field puts it in `owned` and fills it
28
+ * configurable because they're the intersection of what every provider returns—a
29
+ * project that wants a provider-specific field puts it in `owned` and fills it
30
30
  * itself, which also stops the sync from clobbering it.
31
31
  */
32
32
  export declare const PULLED_COLUMNS: readonly ["name", "price", "images", "variants", "externalSlug", "syncedAt"];
@@ -44,7 +44,7 @@ export declare function astroidCatalogMirror(config: AstroidConfig): Required<Pi
44
44
  /**
45
45
  * Drizzle source for the catalog table.
46
46
  *
47
- * `externalId` is unique — it's the sync's idempotency key, so a webhook and the
47
+ * `externalId` is unique—it's the sync's idempotency key, so a webhook and the
48
48
  * cron re-sync racing on the same product can only ever collide into one row.
49
49
  */
50
50
  export declare function generateCatalogTable(config: AstroidConfig): string | null;
@@ -57,7 +57,7 @@ export declare function generateCatalogTable(config: AstroidConfig): string | nu
57
57
  *
58
58
  * It has to exist at all because nothing else creates this table. `--commerce`
59
59
  * put `products` in `src/schema.ts` and the queue seam told you to sync into it,
60
- * but no migration anywhere in the toolkit created it — so the first catalog
60
+ * but no migration anywhere in the toolkit created it—so the first catalog
61
61
  * sync hit a missing table, and (because `astroidCatalogSync` swallows per-item
62
62
  * errors) reported success while writing nothing. The documented fallback,
63
63
  * `drizzle-kit generate`, could not help: the template ships a hand-authored
@@ -3,7 +3,7 @@
3
3
  // The catalog mirror: an external provider is the source of truth, D1 is the
4
4
  // editable overlay on top of it.
5
5
  //
6
- // Every consuming site landed on the same split — a set of fields PULLED from
6
+ // Every consuming site landed on the same split—a set of fields PULLED from
7
7
  // the provider and overwritten on every sync, and a disjoint set the owner edits
8
8
  // which must survive every sync. Get that boundary wrong in either direction and
9
9
  // you either clobber the owner's copy on the next cron tick, or serve a price
@@ -12,13 +12,13 @@
12
12
  // What the sites did NOT agree on is how much to store, and it turns out to be
13
13
  // one primitive with two settings rather than two designs:
14
14
  //
15
- // mirror — pulled + owned columns both live in D1 (themidwestartist.com).
15
+ // mirror: pulled + owned columns both live in D1 (themidwestartist.com).
16
16
  // Reads are one local query. The catalog can be stale between syncs.
17
- // overlay — only the owned columns live in D1, keyed by the provider's id.
17
+ // overlay: only the owned columns live in D1, keyed by the provider's id.
18
18
  // The catalog is read live from the provider and joined at read
19
19
  // time: never stale, but every read costs a provider round-trip
20
20
  // (cache accordingly).
21
- // live — Astroid manages NO catalog table at all: the catalog is read live
21
+ // live: Astroid manages NO catalog table at all: the catalog is read live
22
22
  // from the provider (cached), and any owner-side overlay table is
23
23
  // the SITE's own (coracle.coffee's `product_display_meta`, declared
24
24
  // in schema.site.ts and joined in the site's loader). Use when the
@@ -28,8 +28,8 @@
28
28
  // nor migration. One generator serves all three and a project switches by one word.
29
29
  /**
30
30
  * Columns Astroid always PULLS, overwriting each sync. Fixed rather than
31
- * configurable because they're the intersection of what every provider returns —
32
- * a project that wants a provider-specific field puts it in `owned` and fills it
31
+ * configurable because they're the intersection of what every provider returns—a
32
+ * project that wants a provider-specific field puts it in `owned` and fills it
33
33
  * itself, which also stops the sync from clobbering it.
34
34
  */
35
35
  export const PULLED_COLUMNS = [
@@ -66,7 +66,7 @@ export function astroidCatalogMirror(config) {
66
66
  return {
67
67
  mode: mirror.mode ?? "mirror",
68
68
  table: mirror.table ?? "products",
69
- // Built-ins first so a project can override one (e.g. widen `status`)
69
+ // Built-ins first so a project can override one (for example, widen `status`)
70
70
  // without restating the rest.
71
71
  owned: { ...BUILT_IN_OWNED, ...mirror.owned },
72
72
  };
@@ -99,7 +99,7 @@ function ownedColumnSource(key, col) {
99
99
  /**
100
100
  * Drizzle source for the catalog table.
101
101
  *
102
- * `externalId` is unique — it's the sync's idempotency key, so a webhook and the
102
+ * `externalId` is unique—it's the sync's idempotency key, so a webhook and the
103
103
  * cron re-sync racing on the same product can only ever collide into one row.
104
104
  */
105
105
  export function generateCatalogTable(config) {
@@ -172,7 +172,7 @@ function ownedColumnSql(key, col) {
172
172
  *
173
173
  * It has to exist at all because nothing else creates this table. `--commerce`
174
174
  * put `products` in `src/schema.ts` and the queue seam told you to sync into it,
175
- * but no migration anywhere in the toolkit created it — so the first catalog
175
+ * but no migration anywhere in the toolkit created it—so the first catalog
176
176
  * sync hit a missing table, and (because `astroidCatalogSync` swallows per-item
177
177
  * errors) reported success while writing nothing. The documented fallback,
178
178
  * `drizzle-kit generate`, could not help: the template ships a hand-authored
@@ -3,14 +3,14 @@ import type { CommerceConfig, CommerceProvider } from "../config.js";
3
3
  export type CommerceRole = "storefront" | "invoicing" | "pos";
4
4
  /**
5
5
  * Which roles each provider can serve, derived from the surface its
6
- * `louise-toolkit/commerce/*` client actually exposes — not from what the
6
+ * `louise-toolkit/commerce/*` client actually exposes—not from what the
7
7
  * vendor's full API could theoretically do.
8
8
  *
9
9
  * square catalog + orders + payments, `createInvoice`/`publishInvoice`,
10
10
  * AND locations + per-location price overrides + inventory counts
11
11
  * stripe invoices + payment intents; NO catalog
12
- * fourthwall catalog + cart; NO invoicing, and NO locations or inventory —
13
- * its Platform API is create-only for products, so it cannot
12
+ * fourthwall catalog + cart; NO invoicing, and NO locations or inventory—*
13
+ its Platform API is create-only for products, so it cannot
14
14
  * model stock held at a place
15
15
  *
16
16
  * Square alone can serve `pos`, and that is a fact about the clients rather than
@@ -27,8 +27,8 @@ export interface ResolvedCommerceRoles {
27
27
  /**
28
28
  * Resolve a `commerce` block into role assignments.
29
29
  *
30
- * The `provider` shorthand assigns to the provider's *natural* role — the one it
31
- * can serve — so `{ provider: "square" }` is a storefront and
30
+ * The `provider` shorthand assigns to the provider's *natural* role—the one it
31
+ * can serve—so `{ provider: "square" }` is a storefront and
32
32
  * `{ provider: "stripe" }` is invoicing. Guessing "storefront" for both would
33
33
  * produce a storefront with no catalog API behind it.
34
34
  */
@@ -36,17 +36,17 @@ export declare function astroidCommerceRoles(commerce: CommerceConfig | undefine
36
36
  /** Every distinct provider this project talks to, in a stable order. */
37
37
  export declare function astroidCommerceProviders(commerce: CommerceConfig | undefined): CommerceProvider[];
38
38
  /**
39
- * True when this project sells in person — the switch for locations,
39
+ * True when this project sells in person—the switch for locations,
40
40
  * per-location pricing and inventory.
41
41
  */
42
42
  export declare const hasPos: (commerce: CommerceConfig | undefined) => boolean;
43
43
  /**
44
- * True when Square is used with more than one Location, i.e. the location id
44
+ * True when Square is used with more than one Location, that is, the location id
45
45
  * comes from the request rather than the environment.
46
46
  *
47
47
  * Deliberately independent of which ROLE Square fills: a project could run
48
- * multi-location invoicing without a `pos` storefront, and the consequence —
49
- * no ambient `SQUARE_LOCATION_ID` — is the same either way.
48
+ * multi-location invoicing without a `pos` storefront, and the consequence—no
49
+ * ambient `SQUARE_LOCATION_ID`—is the same either way.
50
50
  */
51
51
  export declare const hasMultiLocation: (commerce: CommerceConfig | undefined) => boolean;
52
52
  /** True when this project sells anything at all. */
@@ -54,7 +54,7 @@ export declare const hasStorefront: (commerce: CommerceConfig | undefined) => bo
54
54
  /**
55
55
  * Reject a role assignment the provider's client cannot serve. Called from
56
56
  * `defineAstroid`, so `invoicing: "fourthwall"` fails at config load with a
57
- * message naming the alternatives — rather than at runtime, on the first
57
+ * message naming the alternatives—rather than at runtime, on the first
58
58
  * invoice, as a missing function.
59
59
  */
60
60
  export declare function assertCommerceRoles(commerce: CommerceConfig | undefined): void;