astroidjs 0.12.1 → 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 +3 -4
  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
@@ -4,28 +4,28 @@
4
4
  //
5
5
  // The obvious model is one commerce provider per site. It's wrong, and the
6
6
  // toolkit's own clients prove it: `louise-toolkit/commerce/stripe` has no
7
- // catalog API whatsoever — it exposes invoices, customers, and payment intents.
7
+ // catalog API whatsoever—it exposes invoices, customers, and payment intents.
8
8
  // `fourthwall` is the mirror image: a catalog and a cart, no invoicing. Square
9
9
  // happens to do both. A single `CommerceProvider` abstraction that assumed
10
10
  // catalog + checkout would therefore have a permanent hole wherever Stripe sits.
11
11
  //
12
12
  // That's not hypothetical. themidwestartist.com runs Stripe for **invoicing**
13
- // (commissions, originals) alongside Fourthwall for the **storefront** (merch) —
14
- // two providers, one site, each doing the half it can do.
13
+ // (commissions, originals) alongside Fourthwall for the **storefront**
14
+ // (merch)—two providers, one site, each doing the half it can do.
15
15
  //
16
16
  // So a project assigns providers to roles, and Astroid validates the assignment
17
17
  // against what each provider's client can actually serve.
18
18
  import { AstroidConfigError } from "../errors.js";
19
19
  /**
20
20
  * Which roles each provider can serve, derived from the surface its
21
- * `louise-toolkit/commerce/*` client actually exposes — not from what the
21
+ * `louise-toolkit/commerce/*` client actually exposes—not from what the
22
22
  * vendor's full API could theoretically do.
23
23
  *
24
24
  * square catalog + orders + payments, `createInvoice`/`publishInvoice`,
25
25
  * AND locations + per-location price overrides + inventory counts
26
26
  * stripe invoices + payment intents; NO catalog
27
- * fourthwall catalog + cart; NO invoicing, and NO locations or inventory —
28
- * its Platform API is create-only for products, so it cannot
27
+ * fourthwall catalog + cart; NO invoicing, and NO locations or inventory—*
28
+ its Platform API is create-only for products, so it cannot
29
29
  * model stock held at a place
30
30
  *
31
31
  * Square alone can serve `pos`, and that is a fact about the clients rather than
@@ -40,8 +40,8 @@ export const PROVIDER_ROLES = {
40
40
  /**
41
41
  * Resolve a `commerce` block into role assignments.
42
42
  *
43
- * The `provider` shorthand assigns to the provider's *natural* role — the one it
44
- * can serve — so `{ provider: "square" }` is a storefront and
43
+ * The `provider` shorthand assigns to the provider's *natural* role—the one it
44
+ * can serve—so `{ provider: "square" }` is a storefront and
45
45
  * `{ provider: "stripe" }` is invoicing. Guessing "storefront" for both would
46
46
  * produce a storefront with no catalog API behind it.
47
47
  */
@@ -69,17 +69,17 @@ export function astroidCommerceProviders(commerce) {
69
69
  return [...new Set([storefront, invoicing, pos].filter((p) => !!p))];
70
70
  }
71
71
  /**
72
- * True when this project sells in person — the switch for locations,
72
+ * True when this project sells in person—the switch for locations,
73
73
  * per-location pricing and inventory.
74
74
  */
75
75
  export const hasPos = (commerce) => Boolean(astroidCommerceRoles(commerce).pos);
76
76
  /**
77
- * True when Square is used with more than one Location, i.e. the location id
77
+ * True when Square is used with more than one Location, that is, the location id
78
78
  * comes from the request rather than the environment.
79
79
  *
80
80
  * Deliberately independent of which ROLE Square fills: a project could run
81
- * multi-location invoicing without a `pos` storefront, and the consequence —
82
- * no ambient `SQUARE_LOCATION_ID` — is the same either way.
81
+ * multi-location invoicing without a `pos` storefront, and the consequence—no
82
+ * ambient `SQUARE_LOCATION_ID`—is the same either way.
83
83
  */
84
84
  export const hasMultiLocation = (commerce) => commerce?.square?.locations === "multi";
85
85
  /** True when this project sells anything at all. */
@@ -87,7 +87,7 @@ export const hasStorefront = (commerce) => Boolean(astroidCommerceRoles(commerce
87
87
  /**
88
88
  * Reject a role assignment the provider's client cannot serve. Called from
89
89
  * `defineAstroid`, so `invoicing: "fourthwall"` fails at config load with a
90
- * message naming the alternatives — rather than at runtime, on the first
90
+ * message naming the alternatives—rather than at runtime, on the first
91
91
  * invoice, as a missing function.
92
92
  */
93
93
  export function assertCommerceRoles(commerce) {
@@ -6,7 +6,7 @@ import { type CommerceRole } from "./roles.js";
6
6
  *
7
7
  * `credentials` is what the provider's `louise-toolkit/commerce/*` client needs
8
8
  * to make a call at all; `webhook` is the signing secret its receiver verifies
9
- * with. They're separable on purpose — a site can receive verified webhooks
9
+ * with. They're separable on purpose—a site can receive verified webhooks
10
10
  * before it has finished provisioning API access, and the reverse is the normal
11
11
  * state of a brand-new integration.
12
12
  *
@@ -32,7 +32,7 @@ export declare const COMMERCE_PROVIDER_SETUP: Record<CommerceProvider, string>;
32
32
  * Only Square varies, and only on one name. `SQUARE_LOCATION_ID` is required
33
33
  * for a single-location project because Square's orders and payments endpoints
34
34
  * refuse a request without one. Under `square.locations: "multi"` the location
35
- * is a property of the *request* — which merchant's storefront is this? — so an
35
+ * is a property of the *request*—which merchant's storefront is this?—so an
36
36
  * ambient id is not just unnecessary, it is dangerous: any code path that
37
37
  * defaulted to it would ring one merchant's sale against another merchant's
38
38
  * books, and the sale would look perfectly successful while doing it.
@@ -53,11 +53,11 @@ export declare function commerceSecretNames(commerce: CommerceConfig | undefined
53
53
  /** One provider's resolved gate. */
54
54
  export interface ProviderStatus {
55
55
  provider: CommerceProvider;
56
- /** Which role(s) this provider fills for the project. */
56
+ /** Which roles this provider fills for the project. */
57
57
  roles: CommerceRole[];
58
- /** API credentials — false means no live call can be made. */
58
+ /** API credentials—false means no live call can be made. */
59
59
  credentials: ModuleSecrets<string>;
60
- /** Webhook signing secret — false means the receiver answers 503. */
60
+ /** Webhook signing secret—false means the receiver answers 503. */
61
61
  webhook: ModuleSecrets<string>;
62
62
  /** True only when both halves resolved. */
63
63
  configured: boolean;
@@ -66,7 +66,7 @@ export interface ProviderStatus {
66
66
  export interface CommerceStatus {
67
67
  /** True when the project has commerce configured AND every provider is live. */
68
68
  configured: boolean;
69
- /** True when the project declares no commerce at all — not the same as dormant. */
69
+ /** True when the project declares no commerce at all—not the same as dormant. */
70
70
  enabled: boolean;
71
71
  providers: ProviderStatus[];
72
72
  /** Every unprovisioned secret name across all providers, in declaration order. */
@@ -93,8 +93,8 @@ export declare function resolveCommerceStatus(commerce: CommerceConfig | undefin
93
93
  *
94
94
  * `CommerceStatus.configured` is an all-or-nothing aggregate (`every`), which is
95
95
  * the right answer for "is the whole module ready" and the wrong one for gating
96
- * a single call site. A two-provider project — Fourthwall for the storefront,
97
- * Square for invoicing — reads `configured: false` the moment either half is
96
+ * a single call site. A two-provider project—Fourthwall for the storefront,
97
+ * Square for invoicing—reads `configured: false` the moment either half is
98
98
  * unprovisioned, so gating the working Fourthwall checkout on the aggregate
99
99
  * would silently simulate it because SQUARE's secrets are still placeholders.
100
100
  *
@@ -103,7 +103,7 @@ export declare function resolveCommerceStatus(commerce: CommerceConfig | undefin
103
103
  export declare function providerConfigured(status: CommerceStatus, provider: CommerceProvider): boolean;
104
104
  /**
105
105
  * Is the provider filling this ROLE live? The role-shaped question, for code
106
- * that cares about the capability rather than the vendor — "can I take a
106
+ * that cares about the capability rather than the vendor—"can I take a
107
107
  * checkout?" rather than "is Square up?".
108
108
  */
109
109
  export declare function roleConfigured(status: CommerceStatus, role: CommerceRole): boolean;
@@ -3,7 +3,7 @@
3
3
  // What each commerce provider needs before it can do anything, and the gate
4
4
  // derived from it.
5
5
  //
6
- // The rest of this module is deliberately credential-free — the adapters are
6
+ // The rest of this module is deliberately credential-free—the adapters are
7
7
  // pure, the mirror and the loader only touch D1, and `verifyCheckout` takes a
8
8
  // price lookup rather than a token. That's the right shape: it keeps the parts
9
9
  // testable and lets the caller own how the fetch happens.
@@ -13,7 +13,7 @@
13
13
  // the commerce half of the dormant-until-provisioned convention (#252): the
14
14
  // names below are the single source of truth for what a provider requires, so
15
15
  // the wrangler generator can seed them, `astroid doctor` can report them, and a
16
- // storefront can decide between a live catalog and a simulated one — all from
16
+ // storefront can decide between a live catalog and a simulated one—all from
17
17
  // one declaration instead of three hand-maintained lists.
18
18
  //
19
19
  // The webhook secret lives here too, rather than beside the verifier in
@@ -26,7 +26,7 @@ import { astroidCommerceProviders, astroidCommerceRoles, hasMultiLocation, } fro
26
26
  *
27
27
  * `credentials` is what the provider's `louise-toolkit/commerce/*` client needs
28
28
  * to make a call at all; `webhook` is the signing secret its receiver verifies
29
- * with. They're separable on purpose — a site can receive verified webhooks
29
+ * with. They're separable on purpose—a site can receive verified webhooks
30
30
  * before it has finished provisioning API access, and the reverse is the normal
31
31
  * state of a brand-new integration.
32
32
  *
@@ -39,7 +39,7 @@ export const COMMERCE_PROVIDER_SECRETS = {
39
39
  // leaves checkout broken rather than dormant. Requiring both is what makes
40
40
  // "configured" mean "can actually take money".
41
41
  //
42
- // UNLESS the project is multi-location — see `commerceProviderCredentials`.
42
+ // UNLESS the project is multi-location—see `commerceProviderCredentials`.
43
43
  square: {
44
44
  credentials: ["SQUARE_ACCESS_TOKEN", "SQUARE_LOCATION_ID"],
45
45
  webhook: "SQUARE_WEBHOOK_SECRET",
@@ -50,7 +50,7 @@ export const COMMERCE_PROVIDER_SECRETS = {
50
50
  },
51
51
  // Fourthwall's storefront token is public-safe (it's sent as a query param
52
52
  // from the browser in their own SDK), but it is still provisioned, so it
53
- // follows the same gate — an absent token means no catalog.
53
+ // follows the same gate—an absent token means no catalog.
54
54
  fourthwall: {
55
55
  credentials: ["FOURTHWALL_STOREFRONT_TOKEN"],
56
56
  webhook: "FOURTHWALL_WEBHOOK_SECRET",
@@ -75,7 +75,7 @@ export const COMMERCE_PROVIDER_SETUP = {
75
75
  * Only Square varies, and only on one name. `SQUARE_LOCATION_ID` is required
76
76
  * for a single-location project because Square's orders and payments endpoints
77
77
  * refuse a request without one. Under `square.locations: "multi"` the location
78
- * is a property of the *request* — which merchant's storefront is this? — so an
78
+ * is a property of the *request*—which merchant's storefront is this?—so an
79
79
  * ambient id is not just unnecessary, it is dangerous: any code path that
80
80
  * defaulted to it would ring one merchant's sale against another merchant's
81
81
  * books, and the sale would look perfectly successful while doing it.
@@ -157,8 +157,8 @@ export async function resolveCommerceStatus(commerce, env) {
157
157
  *
158
158
  * `CommerceStatus.configured` is an all-or-nothing aggregate (`every`), which is
159
159
  * the right answer for "is the whole module ready" and the wrong one for gating
160
- * a single call site. A two-provider project — Fourthwall for the storefront,
161
- * Square for invoicing — reads `configured: false` the moment either half is
160
+ * a single call site. A two-provider project—Fourthwall for the storefront,
161
+ * Square for invoicing—reads `configured: false` the moment either half is
162
162
  * unprovisioned, so gating the working Fourthwall checkout on the aggregate
163
163
  * would silently simulate it because SQUARE's secrets are still placeholders.
164
164
  *
@@ -169,7 +169,7 @@ export function providerConfigured(status, provider) {
169
169
  }
170
170
  /**
171
171
  * Is the provider filling this ROLE live? The role-shaped question, for code
172
- * that cares about the capability rather than the vendor — "can I take a
172
+ * that cares about the capability rather than the vendor—"can I take a
173
173
  * checkout?" rather than "is Square up?".
174
174
  */
175
175
  export function roleConfigured(status, role) {
@@ -7,7 +7,7 @@ export interface CatalogItem {
7
7
  price: number;
8
8
  images?: string[];
9
9
  variants?: unknown;
10
- /** The provider's own slug, when it has one — for re-fetching a single item. */
10
+ /** The provider's own slug, when it has one—for re-fetching a single item. */
11
11
  externalSlug?: string;
12
12
  }
13
13
  /** The D1 surface the sync needs. Structural, so a real `D1Database` fits. */
@@ -21,7 +21,7 @@ export interface SyncDatabase {
21
21
  }
22
22
  export interface CatalogSyncOptions {
23
23
  db: SyncDatabase;
24
- /** Mirror table name — must match the generated schema. */
24
+ /** Mirror table name—must match the generated schema. */
25
25
  table: string;
26
26
  /**
27
27
  * `overlay` mode writes only the key and `synced_at`: the catalog fields live
@@ -32,7 +32,7 @@ export interface CatalogSyncOptions {
32
32
  slugify?: (item: CatalogItem) => string;
33
33
  }
34
34
  export interface CatalogSyncResult {
35
- /** Rows created — new products, landing as `draft`. */
35
+ /** Rows created—new products, landing as `draft`. */
36
36
  created: number;
37
37
  /** Rows whose pulled fields were refreshed. */
38
38
  updated: number;
@@ -41,7 +41,7 @@ export interface CatalogSyncResult {
41
41
  /**
42
42
  * One error per failed item, in order, for logging.
43
43
  *
44
- * Capped — a catalog-wide failure would otherwise build an array as long as
44
+ * Capped—a catalog-wide failure would otherwise build an array as long as
45
45
  * the catalog just to describe the same fault N times.
46
46
  */
47
47
  errors: {
@@ -54,7 +54,7 @@ export declare function defaultSlug(value: string): string;
54
54
  /**
55
55
  * Upsert one item. Returns whether it created a row.
56
56
  *
57
- * The UPDATE branch lists pulled columns ONLY — see the note at the top of this
57
+ * The UPDATE branch lists pulled columns ONLY—see the note at the top of this
58
58
  * file. In `overlay` mode there are no pulled columns, so an existing row is
59
59
  * touched only to stamp `synced_at`.
60
60
  */
@@ -67,7 +67,7 @@ export declare function astroidCatalogUpsert(item: CatalogItem, options: Catalog
67
67
  * Items are written one at a time and a single failure doesn't abandon the rest:
68
68
  * a partial catalog is strictly better than a stale one, and the next cron tick
69
69
  * retries whatever didn't land. Rows whose product has vanished upstream are
70
- * left alone — deciding whether a missing item is delisted or just a failed page
70
+ * left alone—deciding whether a missing item is delisted or just a failed page
71
71
  * of an API response is the project's call, not the sync's, and unpublishing
72
72
  * someone's whole catalog on a bad response is unrecoverable.
73
73
  *
@@ -79,7 +79,7 @@ export declare function astroidCatalogUpsert(item: CatalogItem, options: Catalog
79
79
  * with nothing in `wrangler tail`. Throwing when nothing at all landed is what
80
80
  * makes the queue's retry and DLQ do their job.
81
81
  *
82
- * Partial failures do NOT throw — they come back in `failed`/`errors` for the
82
+ * Partial failures do NOT throw—they come back in `failed`/`errors` for the
83
83
  * caller to log, because retrying the whole batch to re-attempt a few rows would
84
84
  * undo the tolerance this loop exists to provide.
85
85
  */
@@ -10,7 +10,7 @@
10
10
  // the provider's own id (unique in the table) means a re-run is a no-op update
11
11
  // rather than a duplicate row.
12
12
  //
13
- // **The owned set is never in an UPDATE.** Not "usually not" — never. A sync
13
+ // **The owned set is never in an UPDATE.** Not "usually not"—never. A sync
14
14
  // that writes an owned column is a sync that silently reverts the owner's work,
15
15
  // and they find out days later when someone notices the description is back to
16
16
  // the vendor's default. So the update statement is built from the pulled set
@@ -51,7 +51,7 @@ async function allocateSlug(db, table, base, externalId) {
51
51
  /**
52
52
  * Upsert one item. Returns whether it created a row.
53
53
  *
54
- * The UPDATE branch lists pulled columns ONLY — see the note at the top of this
54
+ * The UPDATE branch lists pulled columns ONLY—see the note at the top of this
55
55
  * file. In `overlay` mode there are no pulled columns, so an existing row is
56
56
  * touched only to stamp `synced_at`.
57
57
  */
@@ -106,7 +106,7 @@ const MAX_RECORDED_ERRORS = 10;
106
106
  * Items are written one at a time and a single failure doesn't abandon the rest:
107
107
  * a partial catalog is strictly better than a stale one, and the next cron tick
108
108
  * retries whatever didn't land. Rows whose product has vanished upstream are
109
- * left alone — deciding whether a missing item is delisted or just a failed page
109
+ * left alone—deciding whether a missing item is delisted or just a failed page
110
110
  * of an API response is the project's call, not the sync's, and unpublishing
111
111
  * someone's whole catalog on a bad response is unrecoverable.
112
112
  *
@@ -118,7 +118,7 @@ const MAX_RECORDED_ERRORS = 10;
118
118
  * with nothing in `wrangler tail`. Throwing when nothing at all landed is what
119
119
  * makes the queue's retry and DLQ do their job.
120
120
  *
121
- * Partial failures do NOT throw — they come back in `failed`/`errors` for the
121
+ * Partial failures do NOT throw—they come back in `failed`/`errors` for the
122
122
  * caller to log, because retrying the whole batch to re-attempt a few rows would
123
123
  * undo the tolerance this loop exists to provide.
124
124
  */
@@ -133,7 +133,7 @@ export async function astroidCatalogSync(items, options) {
133
133
  result.updated++;
134
134
  }
135
135
  catch (cause) {
136
- // Skip this item; the next run retries it — but record it, so "nothing
136
+ // Skip this item; the next run retries it—but record it, so "nothing
137
137
  // synced" can be told apart from "nothing to sync".
138
138
  result.failed++;
139
139
  if (result.errors.length < MAX_RECORDED_ERRORS) {
@@ -31,7 +31,7 @@ export declare function alignClass(align?: string | undefined): string;
31
31
  *
32
32
  * These are closed token sets, declared as `select` (#272) so the inspector
33
33
  * renders a picker and an unknown token is rejected on write. They used to be
34
- * `text` with the valid values stuffed into `placeholder` — which meant a typo
34
+ * `text` with the valid values stuffed into `placeholder`—which meant a typo
35
35
  * wasn't a validation error at all, just a silent fallback to the default
36
36
  * inside `colorwayClass` at render time.
37
37
  */
@@ -40,8 +40,8 @@ export declare const SECTION_SETTINGS: Record<string, SectionField>;
40
40
  * What every section render component receives.
41
41
  *
42
42
  * `base` is the whole point. It is this item's path within the page's `sections`
43
- * array — `"2"` for a top-level section, `"2.blocks.0"` for a block inside it —
44
- * and every marker the component stamps is built from it. Passing it down (rather
43
+ * array—`"2"` for a top-level section, `"2.blocks.0"` for a block inside it—and
44
+ * every marker the component stamps is built from it. Passing it down (rather
45
45
  * than having each component work out its own depth) is what lets the exact same
46
46
  * component render as a section or as a block, and what keeps `data-louise-node`
47
47
  * paths correct at any nesting depth.
@@ -53,8 +53,8 @@ export interface SectionRenderProps {
53
53
  base: string;
54
54
  /** Whether to stamp edit markers. Defaults to `Astro.locals.editMode`. */
55
55
  edit?: boolean;
56
- /** Alt/caption resolved from the media registry, keyed by public URL —
57
- * looked up once for the whole page by `<Sections>`. */
56
+ /** Alt/caption resolved from the media registry, keyed by public URL—*
57
+ looked up once for the whole page by `<Sections>`. */
58
58
  mediaMeta?: MediaMeta;
59
59
  }
60
60
  /** Asset-level `alt`/`caption` from the media registry, keyed by public URL. */
@@ -78,7 +78,7 @@ export declare function itemField(row: Record<string, unknown>, key: string): st
78
78
  *
79
79
  * The precedence is the whole reason `<Sections>` does its media lookup: a
80
80
  * per-usage `alt` on the section wins, because the same photo means something
81
- * different in a hero than in a thumbnail strip — but when there isn't one, the
81
+ * different in a hero than in a thumbnail strip—but when there isn't one, the
82
82
  * alt an editor typed once in the media library is used. That's what makes
83
83
  * fixing alt text a single edit that propagates everywhere the asset appears,
84
84
  * instead of a hunt through every page that embeds it.
@@ -89,7 +89,7 @@ export declare function itemField(row: Record<string, unknown>, key: string): st
89
89
  */
90
90
  export declare function mediaAlt(mediaMeta: MediaMeta | undefined, src: string | undefined, override?: string): string;
91
91
  /** Caption for an image, same precedence as {@link mediaAlt}. Undefined when
92
- * there is none — a missing caption renders nothing, unlike a missing alt. */
92
+ * there is none—a missing caption renders nothing, unlike a missing alt. */
93
93
  export declare function mediaCaption(mediaMeta: MediaMeta | undefined, src: string | undefined, override?: string): string | undefined;
94
94
  /**
95
95
  * Every section type Astroid ships.
@@ -97,7 +97,7 @@ export declare function mediaCaption(mediaMeta: MediaMeta | undefined, src: stri
97
97
  * `satisfies` rather than a `: SectionCatalog` annotation, and it matters:
98
98
  * `SectionCatalog` is `Record<string, SectionDef>`, so annotating would widen
99
99
  * `keyof typeof` to `string` and throw away the literal keys. Those keys are
100
- * the project's whole section vocabulary — `SectionKind` is derived from them
100
+ * the project's whole section vocabulary—`SectionKind` is derived from them
101
101
  * (config.ts), `isRenderableSection` narrows to them, and `<Section>` indexes
102
102
  * its component map with them. Annotate this and all three silently degrade to
103
103
  * "any string", which is how the dispatcher lost its type safety once already.
@@ -564,7 +564,7 @@ export declare const astroidSectionCatalog: {
564
564
  settings: Record<string, SectionField>;
565
565
  };
566
566
  };
567
- /** The `_type`s with a shipped render component — derived from the catalog, so
567
+ /** The `_type`s with a shipped render component—derived from the catalog, so
568
568
  * it can't drift from what `<Section>` actually dispatches. A literal union,
569
569
  * not `string`, because the catalog is declared with `satisfies`. */
570
570
  export type RenderableSectionType = keyof typeof astroidSectionCatalog;
@@ -5,8 +5,8 @@
5
5
  //
6
6
  // This file used to define a parallel universe: a `SectionProps` union
7
7
  // discriminated on `kind`, with `colorway`/`align` as component props. Louise's
8
- // actual model — the one the on-canvas editor and the write-time validator both
9
- // read — is different in every particular, and it is the one that wins:
8
+ // actual model—the one the on-canvas editor and the write-time validator both
9
+ // read—is different in every particular, and it is the one that wins:
10
10
  //
11
11
  // • a section is a stored `SectionItem`: `{ _type, blocks?, _layout?,
12
12
  // _settings?, ...fields }`. The discriminant is `_type`, not `kind`.
@@ -16,7 +16,7 @@
16
16
  // or validated-but-uneditable.
17
17
  // • presentation choices are `_settings` / `_layout` **tokens**. Louise stores
18
18
  // the token; the site maps it to CSS. That's why COLORWAY_CLASS below stays
19
- // — it is exactly the site-owned half of that contract — while `colorway`
19
+ //: it is exactly the site-owned half of that contract—while `colorway`
20
20
  // stops being a prop and becomes a stored setting.
21
21
  //
22
22
  // ADR 0005 §2 names this file's job outright: "<Section> reads `_layout` /
@@ -26,7 +26,7 @@
26
26
  //
27
27
  // Self-contained on purpose: this module ships as SOURCE (the `.astro` files
28
28
  // beside it import it directly), so it must not reach back into astroid's built
29
- // `src/*` — only siblings and external packages. The `louise-toolkit/content`
29
+ // `src/*`—only siblings and external packages. The `louise-toolkit/content`
30
30
  // import is TYPE-ONLY, so it erases at build and never drags the validator (or
31
31
  // drizzle, which that entry pulls in) into a page bundle.
32
32
  /**
@@ -73,7 +73,7 @@ const tokenOptions = (map) => Object.keys(map).map((value) => ({ value, label: l
73
73
  *
74
74
  * These are closed token sets, declared as `select` (#272) so the inspector
75
75
  * renders a picker and an unknown token is rejected on write. They used to be
76
- * `text` with the valid values stuffed into `placeholder` — which meant a typo
76
+ * `text` with the valid values stuffed into `placeholder`—which meant a typo
77
77
  * wasn't a validation error at all, just a silent fallback to the default
78
78
  * inside `colorwayClass` at render time.
79
79
  */
@@ -83,7 +83,7 @@ export const SECTION_SETTINGS = {
83
83
  label: "Colorway",
84
84
  inline: false,
85
85
  options: tokenOptions(COLORWAY_CLASS),
86
- // An opaque hint — the schema layer doesn't know what a swatch looks like;
86
+ // An opaque hint—the schema layer doesn't know what a swatch looks like;
87
87
  // a renderer that doesn't support it just shows a normal picker.
88
88
  display: "swatch",
89
89
  },
@@ -124,7 +124,7 @@ export function itemField(row, key) {
124
124
  *
125
125
  * The precedence is the whole reason `<Sections>` does its media lookup: a
126
126
  * per-usage `alt` on the section wins, because the same photo means something
127
- * different in a hero than in a thumbnail strip — but when there isn't one, the
127
+ * different in a hero than in a thumbnail strip—but when there isn't one, the
128
128
  * alt an editor typed once in the media library is used. That's what makes
129
129
  * fixing alt text a single edit that propagates everywhere the asset appears,
130
130
  * instead of a hunt through every page that embeds it.
@@ -139,7 +139,7 @@ export function mediaAlt(mediaMeta, src, override) {
139
139
  return (src ? mediaMeta?.[src]?.alt : undefined) ?? "";
140
140
  }
141
141
  /** Caption for an image, same precedence as {@link mediaAlt}. Undefined when
142
- * there is none — a missing caption renders nothing, unlike a missing alt. */
142
+ * there is none—a missing caption renders nothing, unlike a missing alt. */
143
143
  export function mediaCaption(mediaMeta, src, override) {
144
144
  if (override !== undefined && override !== "")
145
145
  return override;
@@ -154,7 +154,7 @@ export function mediaCaption(mediaMeta, src, override) {
154
154
  * `satisfies` rather than a `: SectionCatalog` annotation, and it matters:
155
155
  * `SectionCatalog` is `Record<string, SectionDef>`, so annotating would widen
156
156
  * `keyof typeof` to `string` and throw away the literal keys. Those keys are
157
- * the project's whole section vocabulary — `SectionKind` is derived from them
157
+ * the project's whole section vocabulary—`SectionKind` is derived from them
158
158
  * (config.ts), `isRenderableSection` narrows to them, and `<Section>` indexes
159
159
  * its component map with them. Annotate this and all three silently degrade to
160
160
  * "any string", which is how the dispatcher lost its type safety once already.
@@ -167,7 +167,7 @@ export const astroidSectionCatalog = {
167
167
  heading: { type: "text", label: "Heading", validation: (r) => r.required().max(120) },
168
168
  subheading: { type: "textarea", label: "Subheading" },
169
169
  // A link URL is something you can't point at on the page, so it is not
170
- // inline — it belongs in the inspector, which is what `inline: false` says.
170
+ // inline—it belongs in the inspector, which is what `inline: false` says.
171
171
  ctaLabel: { type: "text", label: "Button label" },
172
172
  ctaHref: { type: "text", label: "Button link", inline: false },
173
173
  },
@@ -312,7 +312,7 @@ export const astroidSectionCatalog = {
312
312
  name: { type: "text", label: "Name", validation: (r) => r.required() },
313
313
  price: { type: "text", label: "Price" },
314
314
  period: { type: "text", label: "Period (e.g. /mo)" },
315
- // A list of strings isn't expressible — array items are objects — so
315
+ // A list of strings isn't expressible—array items are objects—so
316
316
  // each feature is a one-field row. That also leaves room to add an
317
317
  // `included` flag later without a data migration.
318
318
  features: {
@@ -368,7 +368,7 @@ export const astroidSectionCatalog = {
368
368
  heading: { type: "text", label: "Heading" },
369
369
  // Deliberately hand-authored rows rather than a live catalog read. A
370
370
  // section is stored content, and the commerce mirror is a separate
371
- // concern with its own loader — a site that wants the live catalog renders
371
+ // concern with its own loader—a site that wants the live catalog renders
372
372
  // `readCatalog` in its own page, not through the page-builder.
373
373
  items: {
374
374
  type: "array",