@mohasinac/appkit 4.45.0 → 4.47.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 (160) hide show
  1. package/dist/.build-stamp.json +4 -4
  2. package/dist/_internal/server/features/categories/live-counts.d.ts +41 -0
  3. package/dist/_internal/server/features/categories/live-counts.js +72 -0
  4. package/dist/_internal/server/features/checkout/expand-order-items.js +17 -0
  5. package/dist/_internal/server/features/orders/adapters.js +29 -0
  6. package/dist/_internal/server/features/parts/assembly.d.ts +126 -0
  7. package/dist/_internal/server/features/parts/assembly.js +246 -0
  8. package/dist/_internal/server/features/parts/data.d.ts +65 -0
  9. package/dist/_internal/server/features/parts/data.js +170 -0
  10. package/dist/_internal/server/features/parts/og.d.ts +34 -0
  11. package/dist/_internal/server/features/parts/og.js +66 -0
  12. package/dist/_internal/server/features/search/search-everything.d.ts +75 -0
  13. package/dist/_internal/server/features/search/search-everything.js +120 -0
  14. package/dist/_internal/server/features/search/search-sources.d.ts +17 -0
  15. package/dist/_internal/server/features/search/search-sources.js +138 -0
  16. package/dist/_internal/server/jobs/core/categoryTaxonomyBackfill.d.ts +70 -0
  17. package/dist/_internal/server/jobs/core/categoryTaxonomyBackfill.js +302 -0
  18. package/dist/_internal/server/jobs/core/countersReconcile.js +128 -19
  19. package/dist/_internal/server/jobs/core/jobRunners.js +12 -0
  20. package/dist/_internal/server/jobs/core/onCategoryWrite.js +73 -3
  21. package/dist/_internal/server/jobs/core/onProductWrite.js +93 -43
  22. package/dist/_internal/server/jobs/core/productViewWindows.d.ts +2 -0
  23. package/dist/_internal/server/jobs/core/productViewWindows.js +173 -0
  24. package/dist/_internal/server/jobs/core/testDataCleanup.d.ts +1 -1
  25. package/dist/_internal/server/jobs/core/testDataCleanup.js +27 -1
  26. package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +20 -0
  27. package/dist/_internal/server/jobs/handlers/pageViewRollup.js +25 -1
  28. package/dist/_internal/shared/actions/action-registry.js +36 -0
  29. package/dist/_internal/shared/features/promotions/schema.d.ts +2 -2
  30. package/dist/_internal/shared/features/shipping/protections.d.ts +93 -1
  31. package/dist/_internal/shared/features/shipping/protections.js +127 -0
  32. package/dist/_internal/shared/search/part-aliases.d.ts +44 -0
  33. package/dist/_internal/shared/search/part-aliases.js +104 -0
  34. package/dist/constants/api-endpoints.d.ts +18 -12
  35. package/dist/constants/api-endpoints.js +6 -8
  36. package/dist/constants/field-names.d.ts +0 -2
  37. package/dist/constants/field-names.js +0 -2
  38. package/dist/constants/index.d.ts +1 -1
  39. package/dist/constants/index.js +1 -1
  40. package/dist/core/index.d.ts +0 -3
  41. package/dist/core/index.js +0 -2
  42. package/dist/errors/messages.d.ts +0 -7
  43. package/dist/errors/messages.js +0 -8
  44. package/dist/features/admin/components/AdminSectionsView.js +83 -32
  45. package/dist/features/admin/components/AdminSiteSettingsView.js +6 -2
  46. package/dist/features/admin/components/sections/sectionTemplates.d.ts +117 -0
  47. package/dist/features/admin/components/sections/sectionTemplates.js +213 -0
  48. package/dist/features/admin/schemas/firestore.d.ts +15 -0
  49. package/dist/features/admin/types/index.d.ts +0 -1
  50. package/dist/features/auth/permissions/constants.d.ts +1 -1
  51. package/dist/features/auth/permissions/constants.js +0 -2
  52. package/dist/features/categories/api/[id]/description-template/route.js +40 -1
  53. package/dist/features/categories/components/BrandDetailPageView.js +14 -3
  54. package/dist/features/categories/components/BreadcrumbTrail.d.ts +24 -1
  55. package/dist/features/categories/components/BreadcrumbTrail.js +45 -4
  56. package/dist/features/categories/components/CategoryDetailPageView.js +89 -14
  57. package/dist/features/categories/components/CategoryTemplatePicker.js +9 -1
  58. package/dist/features/categories/repository/categories.repository.d.ts +65 -0
  59. package/dist/features/categories/repository/categories.repository.js +168 -22
  60. package/dist/features/categories/repository/category-counts.d.ts +143 -0
  61. package/dist/features/categories/repository/category-counts.js +224 -0
  62. package/dist/features/categories/schemas/category-counts.d.ts +155 -0
  63. package/dist/features/categories/schemas/category-counts.js +116 -0
  64. package/dist/features/categories/schemas/firestore.d.ts +0 -2
  65. package/dist/features/categories/schemas/firestore.js +0 -1
  66. package/dist/features/categories/utils/breadcrumb-chain.d.ts +194 -0
  67. package/dist/features/categories/utils/breadcrumb-chain.js +202 -0
  68. package/dist/features/corporate/schemas/index.d.ts +4 -4
  69. package/dist/features/orders/schemas/firestore.d.ts +13 -0
  70. package/dist/features/orders/types/index.d.ts +30 -0
  71. package/dist/features/parts/components/AssemblyDrawer.d.ts +107 -0
  72. package/dist/features/parts/components/AssemblyDrawer.js +250 -0
  73. package/dist/features/parts/components/ModelCompositionPanel.d.ts +37 -0
  74. package/dist/features/parts/components/ModelCompositionPanel.js +34 -0
  75. package/dist/features/parts/components/PartDetailPageView.d.ts +48 -0
  76. package/dist/features/parts/components/PartDetailPageView.js +20 -0
  77. package/dist/features/parts/components/PartsIndexPageView.d.ts +33 -0
  78. package/dist/features/parts/components/PartsIndexPageView.js +17 -0
  79. package/dist/features/parts/schemas/firestore.d.ts +257 -0
  80. package/dist/features/parts/schemas/firestore.js +181 -0
  81. package/dist/features/parts/utils/colourway-match.d.ts +62 -0
  82. package/dist/features/parts/utils/colourway-match.js +98 -0
  83. package/dist/features/parts/utils/part-breakdown.d.ts +53 -0
  84. package/dist/features/parts/utils/part-breakdown.js +77 -0
  85. package/dist/features/products/components/ProductDetailPageView.d.ts +14 -1
  86. package/dist/features/products/components/ProductDetailPageView.js +22 -3
  87. package/dist/features/products/components/ProductTabsShell.d.ts +3 -1
  88. package/dist/features/products/components/ProductTabsShell.js +4 -1
  89. package/dist/features/products/repository/category-assignment.d.ts +132 -0
  90. package/dist/features/products/repository/category-assignment.js +304 -0
  91. package/dist/features/products/repository/products.repository.d.ts +58 -1
  92. package/dist/features/products/repository/products.repository.js +255 -28
  93. package/dist/features/products/schemas/firestore.d.ts +147 -6
  94. package/dist/features/products/schemas/firestore.js +49 -0
  95. package/dist/features/search/components/SearchResultsPageView.d.ts +33 -0
  96. package/dist/features/search/components/SearchResultsPageView.js +21 -0
  97. package/dist/features/seller/components/CategoryInlineSelect.d.ts +17 -1
  98. package/dist/features/seller/components/CategoryInlineSelect.js +14 -3
  99. package/dist/features/seller/components/SellerProductShell.d.ts +26 -1
  100. package/dist/features/seller/components/SellerProductShell.js +30 -1
  101. package/dist/features/seller/components/SellerProductsView.js +129 -3
  102. package/dist/features/tester/seed-data/authored/admin__site-system.js +0 -15
  103. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.d.ts +2 -0
  104. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +166 -0
  105. package/dist/features/tester/seed-data/authored/index.js +2 -0
  106. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +28 -1
  107. package/dist/index.d.ts +11 -16
  108. package/dist/index.js +26 -18
  109. package/dist/next/routing/route-map.d.ts +6 -2
  110. package/dist/next/routing/route-map.js +14 -1
  111. package/dist/providers/db-firebase/base.repository.d.ts +31 -0
  112. package/dist/providers/db-firebase/base.repository.js +31 -0
  113. package/dist/repositories/index.d.ts +1 -2
  114. package/dist/repositories/index.js +0 -1
  115. package/dist/seed/_helpers/category-content-generated.d.ts +24 -0
  116. package/dist/seed/_helpers/category-content-generated.js +1837 -0
  117. package/dist/seed/_helpers/category-content.d.ts +29 -0
  118. package/dist/seed/_helpers/category-content.js +98 -1
  119. package/dist/seed/_helpers/category-forest.js +104 -24
  120. package/dist/seed/_helpers/category-parts.d.ts +9 -0
  121. package/dist/seed/_helpers/category-parts.js +4594 -0
  122. package/dist/seed/carousel-slides-seed-data.js +81 -8
  123. package/dist/seed/categories-seed-data.js +44 -6
  124. package/dist/seed/homepage-sections-seed-data.js +170 -9
  125. package/dist/seed/index.d.ts +2 -0
  126. package/dist/seed/index.js +13 -0
  127. package/dist/seed/model-composition-seed-data.d.ts +15 -0
  128. package/dist/seed/model-composition-seed-data.js +8918 -0
  129. package/dist/seed/part-glossary-seed-data.d.ts +15 -0
  130. package/dist/seed/part-glossary-seed-data.js +10729 -0
  131. package/dist/seed/products-standard-seed-data.js +52 -0
  132. package/dist/seed/seed-purpose.d.ts +103 -4
  133. package/dist/seed/seed-purpose.js +162 -11
  134. package/dist/seo/json-ld.d.ts +10 -1
  135. package/dist/seo/json-ld.js +9 -1
  136. package/dist/server.d.ts +7 -0
  137. package/dist/server.js +11 -0
  138. package/dist/styles.css +1 -1
  139. package/dist/tailwind-utilities.css +1 -1
  140. package/dist/utils/id-generators.d.ts +30 -0
  141. package/dist/utils/id-generators.js +31 -1
  142. package/dist/utils/search-txt-builders.js +22 -0
  143. package/dist/utils/search-txt.d.ts +22 -0
  144. package/dist/utils/search-txt.js +17 -0
  145. package/dist/values/success-messages.d.ts +0 -4
  146. package/dist/values/success-messages.js +0 -5
  147. package/package.json +1 -1
  148. package/scripts/seed-cli.mjs +292 -16
  149. package/dist/core/copilot-log.repository.d.ts +0 -44
  150. package/dist/core/copilot-log.repository.js +0 -61
  151. package/dist/features/copilot/components/AdminCopilotView.d.ts +0 -21
  152. package/dist/features/copilot/components/AdminCopilotView.js +0 -51
  153. package/dist/features/copilot/components/index.d.ts +0 -2
  154. package/dist/features/copilot/components/index.js +0 -1
  155. package/dist/features/copilot/hooks/useCopilotChat.d.ts +0 -25
  156. package/dist/features/copilot/hooks/useCopilotChat.js +0 -65
  157. package/dist/features/copilot/hooks/useCopilotFeedback.d.ts +0 -15
  158. package/dist/features/copilot/hooks/useCopilotFeedback.js +0 -15
  159. package/dist/features/copilot/index.d.ts +0 -3
  160. package/dist/features/copilot/index.js +0 -3
@@ -9,13 +9,13 @@ export declare const applyCouponSchema: z.ZodObject<{
9
9
  code: string;
10
10
  cartTotal: number;
11
11
  isFirstTimeUser: boolean;
12
- productIds?: string[] | undefined;
13
12
  categoryIds?: string[] | undefined;
13
+ productIds?: string[] | undefined;
14
14
  }, {
15
15
  code: string;
16
16
  cartTotal: number;
17
- productIds?: string[] | undefined;
18
17
  categoryIds?: string[] | undefined;
18
+ productIds?: string[] | undefined;
19
19
  isFirstTimeUser?: boolean | undefined;
20
20
  }>;
21
21
  export declare const createCouponSchema: z.ZodObject<{
@@ -34,13 +34,95 @@
34
34
  export type ProtectionKind = "shipping" | "sale";
35
35
  export declare const PROTECTION_KINDS: readonly ProtectionKind[];
36
36
  /** Why a protection is not on offer. Rendered to the buyer, so it is copy. */
37
- export type ProtectionUnavailableReason = "platform-disabled" | "seller-not-supported" | "final-sale";
37
+ export type ProtectionUnavailableReason = "platform-disabled" | "seller-not-supported" | "final-sale" | "above-value-cap" | "excluded-category";
38
38
  export type ProtectionAvailability = {
39
39
  available: true;
40
40
  } | {
41
41
  available: false;
42
42
  reason: ProtectionUnavailableReason;
43
43
  };
44
+ /**
45
+ * C5e — the VALUE CAP on sale protection, and the categories excluded outright.
46
+ *
47
+ * The plan's standing rule was that no badge appears on a real listing until
48
+ * these exist, because *"a no-questions-asked guarantee on a Rs 40,000 graded
49
+ * slab is a different product from one on a Rs 149 spin track"*. Directed to
50
+ * "use standard from net" rather than invent them, so both the SHAPE and the
51
+ * exclusion list follow the two marketplaces that publish theirs, and the
52
+ * NUMBER follows our own measured price bands.
53
+ *
54
+ * ── Where the shape comes from ─────────────────────────────────────────────
55
+ *
56
+ * - **Amazon A-to-z** caps a claim at **$2,500 including shipping**, with a
57
+ * 90-day filing window. So a cap is normal practice, it is inclusive of
58
+ * shipping, and it is generous relative to a typical basket.
59
+ * - **eBay Money Back Guarantee** excludes whole CATEGORIES rather than
60
+ * discounting them — vehicles, real estate, services, **digitally delivered
61
+ * content**, travel vouchers, NFTs — and applies a different regime above a
62
+ * value threshold (authentication at $200 for trading cards, $500 for coins),
63
+ * after which an inspected item is **final sale** on the
64
+ * "doesn't match the listing" basis. It also SHORTENS the window for
65
+ * bullion from 30 days to 3.
66
+ *
67
+ * ── 🛑 Why the NUMBER is ours and not a converted dollar figure ────────────
68
+ *
69
+ * $2,500 is ~Rs 2.2 lakh, which is above the most expensive thing in the entire
70
+ * crawled corpus. A cap nothing can reach is not a cap. So it is set from this
71
+ * catalogue's own measured distribution instead: every band's median and p75
72
+ * sits under Rs 15,000 and the maxima are Rs 74,999 (Hot Wheels), Rs 75,000
73
+ * (TCG collection box) and Rs 1,59,102 (otakuisland's range top).
74
+ *
75
+ * **Rs 25,000 covers every median and every p75 measured**, and excludes only
76
+ * the grail tail — graded slabs, booster boxes, premium statues — which is
77
+ * exactly the tier eBay routes to authentication rather than to a blanket
78
+ * guarantee.
79
+ */
80
+ export declare const SALE_PROTECTION_MAX_VALUE = 25000;
81
+ /**
82
+ * 🛑 INCLUSIVE of shipping, following Amazon, and compared against the ITEM
83
+ * LINE's total rather than the order's.
84
+ *
85
+ * Per line, because a Rs 40,000 slab in a basket with two Rs 200 tips must not
86
+ * drag the tips out of cover, and the two Rs 200 tips must not carry the slab
87
+ * into it. The cover is a promise about an ITEM.
88
+ */
89
+ export declare const SALE_PROTECTION_VALUE_BASIS: "line-total-including-shipping";
90
+ /**
91
+ * Listing types sale protection is never offered on, and why each one.
92
+ *
93
+ * 🛑 Every entry is a case where the claim is UNADJUDICABLE, not merely
94
+ * expensive — which is the distinction that keeps this list honest and short.
95
+ * A value cap handles "expensive"; this handles "we could not tell".
96
+ */
97
+ export declare const SALE_PROTECTION_EXCLUDED_LISTING_TYPES: readonly string[];
98
+ /**
99
+ * Whether a GRADED slab is excluded.
100
+ *
101
+ * 🛑 Following eBay's own rule rather than our preference: an item inspected
102
+ * under its Authenticity Guarantee is **final sale** on the "doesn't match the
103
+ * listing" basis. A third party has already certified the grade, so a
104
+ * no-questions-asked refund would let a buyer overturn that certification by
105
+ * changing their mind — and `ProductGrading.certNumber` deep-links to the
106
+ * grader, so the buyer can verify before paying.
107
+ */
108
+ export declare const SALE_PROTECTION_EXCLUDES_GRADED = true;
109
+ /**
110
+ * Claim windows, in hours from DELIVERY.
111
+ *
112
+ * Two windows because the two covers fail on different clocks, which is the
113
+ * same argument that made them two add-ons:
114
+ *
115
+ * - **shipping** 48h — already this platform's stated damage window, in the
116
+ * seeded FAQ and in C0c's copy. Transit damage is visible on unboxing, and a
117
+ * longer window makes "damaged in transit" indistinguishable from
118
+ * "damaged afterwards".
119
+ * - **sale** 7 days — long enough to actually inspect a collectible against
120
+ * its listing (weigh a bey, check a mould, compare a photo), short enough
121
+ * that condition can still be attributed. eBay runs 30 days generally and
122
+ * **3** for bullion; Amazon runs 90. 7 sits deliberately at the strict end,
123
+ * because unlike either of them we are also underwriting the refund.
124
+ */
125
+ export declare const PROTECTION_CLAIM_WINDOW_HOURS: Record<ProtectionKind, number>;
44
126
  export interface ProtectionTierInput {
45
127
  /** TIER 1 — admin, platform-wide. `commissions.*FeeEnabled`. Default TRUE. */
46
128
  platformEnabled: boolean;
@@ -61,6 +143,16 @@ export interface ProtectionTierInput {
61
143
  * time, or the product at purchase time.
62
144
  */
63
145
  finalSale: boolean;
146
+ /**
147
+ * TIER 3 — the line's total INCLUDING shipping, for the value cap. Absent
148
+ * skips the cap check rather than failing it: a missing figure is our gap,
149
+ * and refusing cover over it would charge a fee and then decline the claim.
150
+ */
151
+ lineTotal?: number;
152
+ /** TIER 3 — the listing type, for the exclusion list. */
153
+ listingType?: string;
154
+ /** TIER 3 — whether the item carries a third-party grade. */
155
+ isGraded?: boolean;
64
156
  }
65
157
  /**
66
158
  * Is this protection on offer, and if not, why.
@@ -31,6 +31,112 @@
31
31
  * on a final-sale item, where the right answers differ (see below).
32
32
  */
33
33
  export const PROTECTION_KINDS = ["shipping", "sale"];
34
+ /**
35
+ * C5e — the VALUE CAP on sale protection, and the categories excluded outright.
36
+ *
37
+ * The plan's standing rule was that no badge appears on a real listing until
38
+ * these exist, because *"a no-questions-asked guarantee on a Rs 40,000 graded
39
+ * slab is a different product from one on a Rs 149 spin track"*. Directed to
40
+ * "use standard from net" rather than invent them, so both the SHAPE and the
41
+ * exclusion list follow the two marketplaces that publish theirs, and the
42
+ * NUMBER follows our own measured price bands.
43
+ *
44
+ * ── Where the shape comes from ─────────────────────────────────────────────
45
+ *
46
+ * - **Amazon A-to-z** caps a claim at **$2,500 including shipping**, with a
47
+ * 90-day filing window. So a cap is normal practice, it is inclusive of
48
+ * shipping, and it is generous relative to a typical basket.
49
+ * - **eBay Money Back Guarantee** excludes whole CATEGORIES rather than
50
+ * discounting them — vehicles, real estate, services, **digitally delivered
51
+ * content**, travel vouchers, NFTs — and applies a different regime above a
52
+ * value threshold (authentication at $200 for trading cards, $500 for coins),
53
+ * after which an inspected item is **final sale** on the
54
+ * "doesn't match the listing" basis. It also SHORTENS the window for
55
+ * bullion from 30 days to 3.
56
+ *
57
+ * ── 🛑 Why the NUMBER is ours and not a converted dollar figure ────────────
58
+ *
59
+ * $2,500 is ~Rs 2.2 lakh, which is above the most expensive thing in the entire
60
+ * crawled corpus. A cap nothing can reach is not a cap. So it is set from this
61
+ * catalogue's own measured distribution instead: every band's median and p75
62
+ * sits under Rs 15,000 and the maxima are Rs 74,999 (Hot Wheels), Rs 75,000
63
+ * (TCG collection box) and Rs 1,59,102 (otakuisland's range top).
64
+ *
65
+ * **Rs 25,000 covers every median and every p75 measured**, and excludes only
66
+ * the grail tail — graded slabs, booster boxes, premium statues — which is
67
+ * exactly the tier eBay routes to authentication rather than to a blanket
68
+ * guarantee.
69
+ */
70
+ export const SALE_PROTECTION_MAX_VALUE = 25000;
71
+ /**
72
+ * 🛑 INCLUSIVE of shipping, following Amazon, and compared against the ITEM
73
+ * LINE's total rather than the order's.
74
+ *
75
+ * Per line, because a Rs 40,000 slab in a basket with two Rs 200 tips must not
76
+ * drag the tips out of cover, and the two Rs 200 tips must not carry the slab
77
+ * into it. The cover is a promise about an ITEM.
78
+ */
79
+ export const SALE_PROTECTION_VALUE_BASIS = "line-total-including-shipping";
80
+ /**
81
+ * Listing types sale protection is never offered on, and why each one.
82
+ *
83
+ * 🛑 Every entry is a case where the claim is UNADJUDICABLE, not merely
84
+ * expensive — which is the distinction that keeps this list honest and short.
85
+ * A value cap handles "expensive"; this handles "we could not tell".
86
+ */
87
+ export const SALE_PROTECTION_EXCLUDED_LISTING_TYPES = [
88
+ /*
89
+ * A live animal or plant's condition on arrival cannot be adjudicated from
90
+ * photographs after the fact, and it changes by the hour. eBay excludes the
91
+ * adjacent categories outright for the same reason.
92
+ */
93
+ "live",
94
+ /*
95
+ * eBay excludes "digitally delivered content" by name. Once a code is
96
+ * revealed it cannot be returned, and whether it was already redeemed is not
97
+ * something we can establish — which is why the reveal is logged rather than
98
+ * reversible.
99
+ */
100
+ "digital-code",
101
+ /*
102
+ * A meetup sale with no shipment and no platform custody. There is nothing
103
+ * to inspect, nothing to route to a warehouse, and the buyer handled the
104
+ * item before paying — the inspection step the cover depends on has already
105
+ * happened, in person.
106
+ */
107
+ "classified",
108
+ ];
109
+ /**
110
+ * Whether a GRADED slab is excluded.
111
+ *
112
+ * 🛑 Following eBay's own rule rather than our preference: an item inspected
113
+ * under its Authenticity Guarantee is **final sale** on the "doesn't match the
114
+ * listing" basis. A third party has already certified the grade, so a
115
+ * no-questions-asked refund would let a buyer overturn that certification by
116
+ * changing their mind — and `ProductGrading.certNumber` deep-links to the
117
+ * grader, so the buyer can verify before paying.
118
+ */
119
+ export const SALE_PROTECTION_EXCLUDES_GRADED = true;
120
+ /**
121
+ * Claim windows, in hours from DELIVERY.
122
+ *
123
+ * Two windows because the two covers fail on different clocks, which is the
124
+ * same argument that made them two add-ons:
125
+ *
126
+ * - **shipping** 48h — already this platform's stated damage window, in the
127
+ * seeded FAQ and in C0c's copy. Transit damage is visible on unboxing, and a
128
+ * longer window makes "damaged in transit" indistinguishable from
129
+ * "damaged afterwards".
130
+ * - **sale** 7 days — long enough to actually inspect a collectible against
131
+ * its listing (weigh a bey, check a mould, compare a photo), short enough
132
+ * that condition can still be attributed. eBay runs 30 days generally and
133
+ * **3** for bullion; Amazon runs 90. 7 sits deliberately at the strict end,
134
+ * because unlike either of them we are also underwriting the refund.
135
+ */
136
+ export const PROTECTION_CLAIM_WINDOW_HOURS = {
137
+ shipping: 48,
138
+ sale: 24 * 7,
139
+ };
34
140
  /**
35
141
  * Is this protection on offer, and if not, why.
36
142
  *
@@ -62,6 +168,27 @@ export function protectionAvailability(kind, input) {
62
168
  if (kind === "sale" && input.finalSale) {
63
169
  return { available: false, reason: "final-sale" };
64
170
  }
171
+ /*
172
+ * C5e's value and category gates, SALE only.
173
+ *
174
+ * 🛑 Shipping protection is deliberately exempt from both. A parcel lost in
175
+ * transit was never delivered, so neither the item's value nor whether it is
176
+ * a digital code or a graded slab changes what happened — and we are the
177
+ * carrier's counterparty under escrow, so it is our claim to pursue either
178
+ * way. Applying the cap here would be withdrawing cover for the one failure
179
+ * the buyer has no part in.
180
+ */
181
+ if (kind === "sale") {
182
+ if (input.listingType && SALE_PROTECTION_EXCLUDED_LISTING_TYPES.includes(input.listingType)) {
183
+ return { available: false, reason: "excluded-category" };
184
+ }
185
+ if (SALE_PROTECTION_EXCLUDES_GRADED && input.isGraded) {
186
+ return { available: false, reason: "excluded-category" };
187
+ }
188
+ if (typeof input.lineTotal === "number" && input.lineTotal > SALE_PROTECTION_MAX_VALUE) {
189
+ return { available: false, reason: "above-value-cap" };
190
+ }
191
+ }
65
192
  return { available: true };
66
193
  }
67
194
  /**
@@ -0,0 +1,44 @@
1
+ /**
2
+ * GENERATED by `scripts/generate-part-alias-map.mjs` — do not hand-edit.
3
+ * Source: `docs/research/part-composition-2026-10/part-glossary.json` (E4b).
4
+ *
5
+ * D2 Fix 3 — the part code ⇄ name bridge, so "rubber flat" finds `RF` listings
6
+ * and `RF` finds them too. Firestore cannot fuzzy-match, but nothing stops us
7
+ * indexing MORE tokens per document, which is what this is for.
8
+ *
9
+ * 🛑 Only rows carrying BOTH a code and a distinct name can bridge: **23**
10
+ * of 759 glossary entries. The remaining 736 are name-only and already
11
+ * searchable by name, so they need no alias — that is the measured scope, not
12
+ * a shortfall.
13
+ *
14
+ * 🛑 In SOURCE rather than read from Firestore because `buildProductSearchTxt`
15
+ * is synchronous and runs on every product write; and `searchTxt` must be
16
+ * deterministic for the same input, or the app and
17
+ * `backfill-search-txt.mjs` emit different tokens for one product
18
+ * (audit-search-parity's own stated failure mode).
19
+ *
20
+ * 🛑 It shares the 600-token cap with D0's generated misspelling variants, and
21
+ * that cap TRUNCATES SILENTLY. Measured headroom at generation time: the worst
22
+ * live product carried 199 tokens, so 401 spare. Re-measure before adding a
23
+ * third token source.
24
+ */
25
+ export interface PartAlias {
26
+ /** The short code as printed on the part and in listing titles. */
27
+ code: string;
28
+ /** The spoken name — what a buyer types. */
29
+ name: string;
30
+ classification: string;
31
+ }
32
+ export declare const PART_ALIASES: readonly PartAlias[];
33
+ /**
34
+ * Tokens to add for one piece of text — the COUNTERPART of anything matched.
35
+ *
36
+ * A listing titled "Storm Pegasus 105RF" gets "rubber flat"; one titled
37
+ * "… Rubber Flat" gets "rf". Nothing is added when neither appears, so an
38
+ * unrelated product pays no tokens at all.
39
+ *
40
+ * 🛑 Word-boundary matched on the CODE. A bare `substring` test puts "quake"
41
+ * on every product containing a letter Q — codes here are 1–5 characters, so
42
+ * an unanchored match is worse than no match.
43
+ */
44
+ export declare function partAliasTokens(text: string): string[];
@@ -0,0 +1,104 @@
1
+ /**
2
+ * GENERATED by `scripts/generate-part-alias-map.mjs` — do not hand-edit.
3
+ * Source: `docs/research/part-composition-2026-10/part-glossary.json` (E4b).
4
+ *
5
+ * D2 Fix 3 — the part code ⇄ name bridge, so "rubber flat" finds `RF` listings
6
+ * and `RF` finds them too. Firestore cannot fuzzy-match, but nothing stops us
7
+ * indexing MORE tokens per document, which is what this is for.
8
+ *
9
+ * 🛑 Only rows carrying BOTH a code and a distinct name can bridge: **23**
10
+ * of 759 glossary entries. The remaining 736 are name-only and already
11
+ * searchable by name, so they need no alias — that is the measured scope, not
12
+ * a shortfall.
13
+ *
14
+ * 🛑 In SOURCE rather than read from Firestore because `buildProductSearchTxt`
15
+ * is synchronous and runs on every product write; and `searchTxt` must be
16
+ * deterministic for the same input, or the app and
17
+ * `backfill-search-txt.mjs` emit different tokens for one product
18
+ * (audit-search-parity's own stated failure mode).
19
+ *
20
+ * 🛑 It shares the 600-token cap with D0's generated misspelling variants, and
21
+ * that cap TRUNCATES SILENTLY. Measured headroom at generation time: the worst
22
+ * live product carried 199 tokens, so 401 spare. Re-measure before adding a
23
+ * third token source.
24
+ */
25
+ const CLS_PERFORMANCE_TIP = "Performance Tip";
26
+ const CLS_SPIN_TRACK = "Spin Track";
27
+ export const PART_ALIASES = [
28
+ { code: "A230", name: "Armor 230", classification: CLS_SPIN_TRACK },
29
+ { code: "CS", name: "Coat Sharp", classification: CLS_PERFORMANCE_TIP },
30
+ { code: "ED145", name: "Eternal Defense 145", classification: CLS_PERFORMANCE_TIP },
31
+ { code: "ES", name: "Eternal Sharp", classification: CLS_PERFORMANCE_TIP },
32
+ { code: "EWD", name: "Eternal Wide Defense", classification: CLS_PERFORMANCE_TIP },
33
+ { code: "F", name: "Flat", classification: CLS_PERFORMANCE_TIP },
34
+ { code: "F:D", name: "Final Drive", classification: CLS_PERFORMANCE_TIP },
35
+ { code: "FB", name: "Flat Ball", classification: CLS_PERFORMANCE_TIP },
36
+ { code: "JSB", name: "Jog Sharp Ball", classification: CLS_PERFORMANCE_TIP },
37
+ { code: "MB", name: "Metal Ball", classification: CLS_PERFORMANCE_TIP },
38
+ { code: "MS", name: "Metal Sharp", classification: CLS_PERFORMANCE_TIP },
39
+ { code: "Q", name: "Quake", classification: CLS_PERFORMANCE_TIP },
40
+ { code: "RB", name: "Rubber Ball", classification: CLS_PERFORMANCE_TIP },
41
+ { code: "RF", name: "Rubber Flat", classification: CLS_PERFORMANCE_TIP },
42
+ { code: "RS", name: "Rubber Sharp", classification: CLS_PERFORMANCE_TIP },
43
+ { code: "RSF", name: "Rubber Semi Flat", classification: CLS_PERFORMANCE_TIP },
44
+ { code: "SD", name: "Semi-Defense", classification: CLS_PERFORMANCE_TIP },
45
+ { code: "SF", name: "Semi-Flat", classification: CLS_PERFORMANCE_TIP },
46
+ { code: "SWD", name: "Sharp Wide Defense", classification: CLS_PERFORMANCE_TIP },
47
+ { code: "WB", name: "Wide Ball", classification: CLS_PERFORMANCE_TIP },
48
+ { code: "WF", name: "Wide Flat", classification: CLS_PERFORMANCE_TIP },
49
+ { code: "X:D", name: "X:Drive", classification: CLS_PERFORMANCE_TIP },
50
+ { code: "XF", name: "Extreme Flat", classification: CLS_PERFORMANCE_TIP },
51
+ ];
52
+ /**
53
+ * Tokens to add for one piece of text — the COUNTERPART of anything matched.
54
+ *
55
+ * A listing titled "Storm Pegasus 105RF" gets "rubber flat"; one titled
56
+ * "… Rubber Flat" gets "rf". Nothing is added when neither appears, so an
57
+ * unrelated product pays no tokens at all.
58
+ *
59
+ * 🛑 Word-boundary matched on the CODE. A bare `substring` test puts "quake"
60
+ * on every product containing a letter Q — codes here are 1–5 characters, so
61
+ * an unanchored match is worse than no match.
62
+ */
63
+ export function partAliasTokens(text) {
64
+ if (!text)
65
+ return [];
66
+ const words = text.toLowerCase().replace(/[^a-z0-9]+/g, " ").split(" ").filter(Boolean);
67
+ const hay = ` ${words.join(" ")} `;
68
+ const out = [];
69
+ for (const { code, name } of PART_ALIASES) {
70
+ const c = code.toLowerCase().replace(/[^a-z0-9]+/g, "");
71
+ const n = name.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
72
+ if (!c || !n)
73
+ continue;
74
+ /*
75
+ * 🛑 A CODE IS WRITTEN SUFFIXED TO ITS HEIGHT, which a word-boundary match
76
+ * misses entirely: real titles say "Storm Pegasus 105RF" and "Dran Sword
77
+ * 3-60F", never " RF ". So a digit-prefixed suffix counts as a match.
78
+ */
79
+ const suffixed = words.some((w) => {
80
+ /*
81
+ * 🛑 The code must be the WHOLE alphabetic suffix, not any suffix.
82
+ * "105rf".endsWith("f") is true, so a plain endsWith aliased every
83
+ * Rubber Flat listing to "flat" as well — a wrong second tip on a
84
+ * correct match, which is the kind of noise that makes a search feature
85
+ * read as broken rather than absent.
86
+ */
87
+ const m = /^([0-9][0-9-]*)([a-z]+)$/.exec(w);
88
+ return !!m && m[2] === c;
89
+ });
90
+ /*
91
+ * 🛑 A BARE code only counts at 2+ characters. "Dranzer F" is a MODEL
92
+ * name — F there is not the Flat tip — and single letters are common in
93
+ * model names, so a 1-character bare match would alias a large part of the
94
+ * catalogue to a tip it does not have. The digit-prefixed form above still
95
+ * catches "105F", which is where a 1-character code actually appears.
96
+ */
97
+ const bare = c.length >= 2 && hay.includes(` ${c} `);
98
+ if (suffixed || bare)
99
+ out.push(n);
100
+ if (hay.includes(` ${n} `))
101
+ out.push(c);
102
+ }
103
+ return [...new Set(out)];
104
+ }
@@ -303,10 +303,6 @@ export declare const COLLECTION_ENDPOINTS: {
303
303
  export declare const CONSULTATION_ENDPOINTS: {
304
304
  readonly LIST: "/api/consultations";
305
305
  };
306
- export declare const COPILOT_ENDPOINTS: {
307
- readonly CHAT: "/api/copilot/chat";
308
- readonly HISTORY: "/api/copilot/history";
309
- };
310
306
  export declare const CORPORATE_ENDPOINTS: {
311
307
  readonly INQUIRIES: "/api/corporate-inquiries";
312
308
  };
@@ -425,6 +421,12 @@ export declare const SELLER_ENDPOINTS: {
425
421
  readonly FEATURE_BY_ID: (id: string) => string;
426
422
  readonly PRODUCTS_BULK_LOCATION: "/api/store/products/bulk-location";
427
423
  readonly PRODUCTS_BULK_STOCK: "/api/store/products/bulk-stock";
424
+ /**
425
+ * D13 — assemble / part out. GET returns what the drawer needs (the model's
426
+ * composition and the seller's part listings); POST performs the transaction.
427
+ * One path for both because they are two sides of one operation.
428
+ */
429
+ readonly PRODUCT_ASSEMBLE: (id: string) => string;
428
430
  readonly ORDERS_BULK_LOCATION: "/api/store/orders/bulk-location";
429
431
  readonly GROUPED_LISTINGS: "/api/store/grouped-listings";
430
432
  readonly GROUPED_LISTING_BY_ID: (id: string) => string;
@@ -788,10 +790,6 @@ export declare const API_ENDPOINTS: {
788
790
  readonly CONSULTATION: {
789
791
  readonly LIST: "/api/consultations";
790
792
  };
791
- readonly COPILOT: {
792
- readonly CHAT: "/api/copilot/chat";
793
- readonly HISTORY: "/api/copilot/history";
794
- };
795
793
  readonly CORPORATE: {
796
794
  readonly INQUIRIES: "/api/corporate-inquiries";
797
795
  };
@@ -907,6 +905,12 @@ export declare const API_ENDPOINTS: {
907
905
  readonly FEATURE_BY_ID: (id: string) => string;
908
906
  readonly PRODUCTS_BULK_LOCATION: "/api/store/products/bulk-location";
909
907
  readonly PRODUCTS_BULK_STOCK: "/api/store/products/bulk-stock";
908
+ /**
909
+ * D13 — assemble / part out. GET returns what the drawer needs (the model's
910
+ * composition and the seller's part listings); POST performs the transaction.
911
+ * One path for both because they are two sides of one operation.
912
+ */
913
+ readonly PRODUCT_ASSEMBLE: (id: string) => string;
910
914
  readonly ORDERS_BULK_LOCATION: "/api/store/orders/bulk-location";
911
915
  readonly GROUPED_LISTINGS: "/api/store/grouped-listings";
912
916
  readonly GROUPED_LISTING_BY_ID: (id: string) => string;
@@ -1272,10 +1276,6 @@ export declare const API_ROUTES: {
1272
1276
  readonly CONSULTATION: {
1273
1277
  readonly LIST: "/api/consultations";
1274
1278
  };
1275
- readonly COPILOT: {
1276
- readonly CHAT: "/api/copilot/chat";
1277
- readonly HISTORY: "/api/copilot/history";
1278
- };
1279
1279
  readonly CORPORATE: {
1280
1280
  readonly INQUIRIES: "/api/corporate-inquiries";
1281
1281
  };
@@ -1391,6 +1391,12 @@ export declare const API_ROUTES: {
1391
1391
  readonly FEATURE_BY_ID: (id: string) => string;
1392
1392
  readonly PRODUCTS_BULK_LOCATION: "/api/store/products/bulk-location";
1393
1393
  readonly PRODUCTS_BULK_STOCK: "/api/store/products/bulk-stock";
1394
+ /**
1395
+ * D13 — assemble / part out. GET returns what the drawer needs (the model's
1396
+ * composition and the seller's part listings); POST performs the transaction.
1397
+ * One path for both because they are two sides of one operation.
1398
+ */
1399
+ readonly PRODUCT_ASSEMBLE: (id: string) => string;
1394
1400
  readonly ORDERS_BULK_LOCATION: "/api/store/orders/bulk-location";
1395
1401
  readonly GROUPED_LISTINGS: "/api/store/grouped-listings";
1396
1402
  readonly GROUPED_LISTING_BY_ID: (id: string) => string;
@@ -363,13 +363,6 @@ export const CONSULTATION_ENDPOINTS = {
363
363
  LIST: "/api/consultations",
364
364
  };
365
365
  // ---------------------------------------------------------------------------
366
- // Copilot
367
- // ---------------------------------------------------------------------------
368
- export const COPILOT_ENDPOINTS = {
369
- CHAT: "/api/copilot/chat",
370
- HISTORY: "/api/copilot/history",
371
- };
372
- // ---------------------------------------------------------------------------
373
366
  // Corporate
374
367
  // ---------------------------------------------------------------------------
375
368
  export const CORPORATE_ENDPOINTS = {
@@ -549,6 +542,12 @@ export const SELLER_ENDPOINTS = {
549
542
  FEATURE_BY_ID: (id) => `/api/store/features/${id}`,
550
543
  PRODUCTS_BULK_LOCATION: "/api/store/products/bulk-location",
551
544
  PRODUCTS_BULK_STOCK: "/api/store/products/bulk-stock",
545
+ /**
546
+ * D13 — assemble / part out. GET returns what the drawer needs (the model's
547
+ * composition and the seller's part listings); POST performs the transaction.
548
+ * One path for both because they are two sides of one operation.
549
+ */
550
+ PRODUCT_ASSEMBLE: (id) => `/api/store/products/${id}/assemble`,
552
551
  ORDERS_BULK_LOCATION: "/api/store/orders/bulk-location",
553
552
  GROUPED_LISTINGS: "/api/store/grouped-listings",
554
553
  GROUPED_LISTING_BY_ID: (id) => `/api/store/grouped-listings/${id}`,
@@ -678,7 +677,6 @@ export const API_ENDPOINTS = {
678
677
  PAYMENT: PAYMENT_ENDPOINTS,
679
678
  COLLECTIONS: COLLECTION_ENDPOINTS,
680
679
  CONSULTATION: CONSULTATION_ENDPOINTS,
681
- COPILOT: COPILOT_ENDPOINTS,
682
680
  CORPORATE: CORPORATE_ENDPOINTS,
683
681
  CONTACT: CONTACT_ENDPOINTS,
684
682
  ADS: AD_ENDPOINTS,
@@ -90,7 +90,6 @@ export declare const PRODUCT_FIELDS: {
90
90
  readonly SEO_TITLE: "seoTitle";
91
91
  readonly SEO_DESCRIPTION: "seoDescription";
92
92
  readonly SEO_KEYWORDS: "seoKeywords";
93
- readonly VIEW_COUNT: "viewCount";
94
93
  readonly PRIZE_REVEAL_STATUS: "prizeRevealStatus";
95
94
  readonly PRIZE_REVEAL_WINDOW_START: "prizeRevealWindowStart";
96
95
  readonly PRIZE_REVEAL_WINDOW_END: "prizeRevealWindowEnd";
@@ -523,7 +522,6 @@ export declare const CATEGORY_FIELDS: {
523
522
  readonly BUNDLE_QUERY_RESOLVED_AT: "bundleQueryResolvedAt";
524
523
  readonly BUNDLE_ORIGINAL_TOTAL: "bundleOriginalTotal";
525
524
  readonly DISPLAY: "display";
526
- readonly VIEW_COUNT: "viewCount";
527
525
  readonly CREATED_AT: "createdAt";
528
526
  readonly UPDATED_AT: "updatedAt";
529
527
  readonly CATEGORY_TYPE_VALUES: {
@@ -98,7 +98,6 @@ export const PRODUCT_FIELDS = {
98
98
  SEO_TITLE: "seoTitle",
99
99
  SEO_DESCRIPTION: "seoDescription",
100
100
  SEO_KEYWORDS: "seoKeywords",
101
- VIEW_COUNT: "viewCount",
102
101
  // Prize draw fields (SB4)
103
102
  PRIZE_REVEAL_STATUS: "prizeRevealStatus",
104
103
  PRIZE_REVEAL_WINDOW_START: "prizeRevealWindowStart",
@@ -598,7 +597,6 @@ export const CATEGORY_FIELDS = {
598
597
  BUNDLE_QUERY_RESOLVED_AT: "bundleQueryResolvedAt",
599
598
  BUNDLE_ORIGINAL_TOTAL: "bundleOriginalTotal",
600
599
  DISPLAY: "display",
601
- VIEW_COUNT: "viewCount",
602
600
  CREATED_AT: "createdAt",
603
601
  UPDATED_AT: "updatedAt",
604
602
  CATEGORY_TYPE_VALUES: {
@@ -9,7 +9,7 @@
9
9
  * import { COLLECTION_CACHE_PATHS } from "@mohasinac/appkit/constants";
10
10
  * import { resolveEndpoint } from "@mohasinac/appkit/constants";
11
11
  */
12
- export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, NOTIFICATIONS_ENDPOINTS, SITE_SETTINGS_ENDPOINTS, ADMIN_ENDPOINTS, AUCTION_ENDPOINTS, BID_ENDPOINTS, CART_ENDPOINTS, CATEGORY_ENDPOINTS, CHECKOUT_ENDPOINTS, PAYMENT_ENDPOINTS, COLLECTION_ENDPOINTS, CONSULTATION_ENDPOINTS, COPILOT_ENDPOINTS, CORPORATE_ENDPOINTS, EVENT_ENDPOINTS, FAQ_ENDPOINTS, HOMEPAGE_ENDPOINTS, LOYALTY_ENDPOINTS, ANALYTICS_ENDPOINTS, MEDIA_ENDPOINTS, ORDER_ENDPOINTS, PREORDER_ENDPOINTS, PRODUCT_ENDPOINTS, PROMOTION_ENDPOINTS, REVIEW_ENDPOINTS, SEARCH_ENDPOINTS, SELLER_ENDPOINTS, BLOG_ENDPOINTS, STORE_ENDPOINTS, WISHLIST_ENDPOINTS, PROFILE_STATS_ENDPOINTS, } from "./api-endpoints";
12
+ export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, NOTIFICATIONS_ENDPOINTS, SITE_SETTINGS_ENDPOINTS, ADMIN_ENDPOINTS, AUCTION_ENDPOINTS, BID_ENDPOINTS, CART_ENDPOINTS, CATEGORY_ENDPOINTS, CHECKOUT_ENDPOINTS, PAYMENT_ENDPOINTS, COLLECTION_ENDPOINTS, CONSULTATION_ENDPOINTS, CORPORATE_ENDPOINTS, EVENT_ENDPOINTS, FAQ_ENDPOINTS, HOMEPAGE_ENDPOINTS, LOYALTY_ENDPOINTS, ANALYTICS_ENDPOINTS, MEDIA_ENDPOINTS, ORDER_ENDPOINTS, PREORDER_ENDPOINTS, PRODUCT_ENDPOINTS, PROMOTION_ENDPOINTS, REVIEW_ENDPOINTS, SEARCH_ENDPOINTS, SELLER_ENDPOINTS, BLOG_ENDPOINTS, STORE_ENDPOINTS, WISHLIST_ENDPOINTS, PROFILE_STATS_ENDPOINTS, } from "./api-endpoints";
13
13
  export { COLLECTION_CACHE_PATHS } from "./cache-invalidation";
14
14
  export { PAGE_SIZES, MAX_PAGE_SIZE, FEATURED_LIMITS, SITEMAP_LIMITS, } from "./pagination-presets";
15
15
  export type { PageSizeKey } from "./pagination-presets";
@@ -9,7 +9,7 @@
9
9
  * import { COLLECTION_CACHE_PATHS } from "@mohasinac/appkit/constants";
10
10
  * import { resolveEndpoint } from "@mohasinac/appkit/constants";
11
11
  */
12
- export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, NOTIFICATIONS_ENDPOINTS, SITE_SETTINGS_ENDPOINTS, ADMIN_ENDPOINTS, AUCTION_ENDPOINTS, BID_ENDPOINTS, CART_ENDPOINTS, CATEGORY_ENDPOINTS, CHECKOUT_ENDPOINTS, PAYMENT_ENDPOINTS, COLLECTION_ENDPOINTS, CONSULTATION_ENDPOINTS, COPILOT_ENDPOINTS, CORPORATE_ENDPOINTS, EVENT_ENDPOINTS, FAQ_ENDPOINTS, HOMEPAGE_ENDPOINTS, LOYALTY_ENDPOINTS, ANALYTICS_ENDPOINTS, MEDIA_ENDPOINTS, ORDER_ENDPOINTS, PREORDER_ENDPOINTS, PRODUCT_ENDPOINTS, PROMOTION_ENDPOINTS, REVIEW_ENDPOINTS, SEARCH_ENDPOINTS, SELLER_ENDPOINTS, BLOG_ENDPOINTS, STORE_ENDPOINTS, WISHLIST_ENDPOINTS, PROFILE_STATS_ENDPOINTS, } from "./api-endpoints.js";
12
+ export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, NOTIFICATIONS_ENDPOINTS, SITE_SETTINGS_ENDPOINTS, ADMIN_ENDPOINTS, AUCTION_ENDPOINTS, BID_ENDPOINTS, CART_ENDPOINTS, CATEGORY_ENDPOINTS, CHECKOUT_ENDPOINTS, PAYMENT_ENDPOINTS, COLLECTION_ENDPOINTS, CONSULTATION_ENDPOINTS, CORPORATE_ENDPOINTS, EVENT_ENDPOINTS, FAQ_ENDPOINTS, HOMEPAGE_ENDPOINTS, LOYALTY_ENDPOINTS, ANALYTICS_ENDPOINTS, MEDIA_ENDPOINTS, ORDER_ENDPOINTS, PREORDER_ENDPOINTS, PRODUCT_ENDPOINTS, PROMOTION_ENDPOINTS, REVIEW_ENDPOINTS, SEARCH_ENDPOINTS, SELLER_ENDPOINTS, BLOG_ENDPOINTS, STORE_ENDPOINTS, WISHLIST_ENDPOINTS, PROFILE_STATS_ENDPOINTS, } from "./api-endpoints.js";
13
13
  export { COLLECTION_CACHE_PATHS } from "./cache-invalidation.js";
14
14
  export { PAGE_SIZES, MAX_PAGE_SIZE, FEATURED_LIMITS, SITEMAP_LIMITS, } from "./pagination-presets.js";
15
15
  export { NOTIFICATION_TYPES, NOTIFICATION_TYPE_TABS, } from "./notification-types.js";
@@ -16,9 +16,6 @@ export { CacheManager, cacheManager } from "./CacheManager";
16
16
  export type { CacheOptions, CacheEntry } from "./CacheManager";
17
17
  export { SITE_CONFIG, createSiteConfig, resolveSiteConfig, } from "./site-config";
18
18
  export type { RuntimeSiteConfig } from "./site-config";
19
- export { CopilotLogRepository, copilotLogRepository, } from "./copilot-log.repository";
20
- export type { CopilotFeedback, CopilotLogDocument, CopilotLogCreateInput, } from "./copilot-log.repository";
21
- export { COPILOT_LOGS_COLLECTION, COPILOT_LOGS_INDEXED_FIELDS, copilotLogQueryHelpers, } from "./copilot-log.repository";
22
19
  export { useSiteSettings } from "./hooks/useSiteSettings";
23
20
  export { NEWSLETTER_SUBSCRIBER_FIELDS, NEWSLETTER_SUBSCRIBERS_COLLECTION, NEWSLETTER_SUBSCRIBER_INDEXED_FIELDS, newsletterRepository, } from "./newsletter.repository";
24
21
  export type { NewsletterSubscriberDocument, NewsletterSubscriberCreateInput, NewsletterSubscriberUpdateInput, } from "./newsletter.repository";
@@ -10,8 +10,6 @@ export { StorageManager, storageManager } from "./StorageManager.js";
10
10
  export { EventBus, eventBus } from "./EventBus.js";
11
11
  export { CacheManager, cacheManager } from "./CacheManager.js";
12
12
  export { SITE_CONFIG, createSiteConfig, resolveSiteConfig, } from "./site-config.js";
13
- export { CopilotLogRepository, copilotLogRepository, } from "./copilot-log.repository.js";
14
- export { COPILOT_LOGS_COLLECTION, COPILOT_LOGS_INDEXED_FIELDS, copilotLogQueryHelpers, } from "./copilot-log.repository.js";
15
13
  export { useSiteSettings } from "./hooks/useSiteSettings.js";
16
14
  export { NEWSLETTER_SUBSCRIBER_FIELDS, NEWSLETTER_SUBSCRIBERS_COLLECTION, NEWSLETTER_SUBSCRIBER_INDEXED_FIELDS, newsletterRepository, } from "./newsletter.repository.js";
17
15
  export { CONTACT_SUBMISSIONS_COLLECTION, contactSubmissionsRepository, } from "./contact-submissions.repository.js";
@@ -432,13 +432,6 @@ export declare const ERROR_MESSAGES: {
432
432
  readonly EXPIRED: "This offer has expired and can no longer be acted on.";
433
433
  readonly PRODUCT_UNAVAILABLE: "This product is no longer available at the agreed price. Contact support.";
434
434
  };
435
- readonly COPILOT: {
436
- readonly GENERATION_FAILED: "Failed to generate AI response";
437
- readonly MODEL_UNAVAILABLE: "AI model is temporarily unavailable";
438
- readonly PROMPT_TOO_LONG: "Prompt exceeds the maximum allowed length";
439
- readonly HISTORY_FAILED: "Failed to load conversation history";
440
- readonly FEEDBACK_FAILED: "Failed to save feedback";
441
- };
442
435
  readonly CHAT: {
443
436
  readonly FETCH_FAILED: "Failed to load chat";
444
437
  readonly SEND_FAILED: "Failed to send message";
@@ -461,14 +461,6 @@ export const ERROR_MESSAGES = {
461
461
  EXPIRED: "This offer has expired and can no longer be acted on.",
462
462
  PRODUCT_UNAVAILABLE: "This product is no longer available at the agreed price. Contact support.",
463
463
  },
464
- // AI Copilot errors
465
- COPILOT: {
466
- GENERATION_FAILED: "Failed to generate AI response",
467
- MODEL_UNAVAILABLE: "AI model is temporarily unavailable",
468
- PROMPT_TOO_LONG: "Prompt exceeds the maximum allowed length",
469
- HISTORY_FAILED: "Failed to load conversation history",
470
- FEEDBACK_FAILED: "Failed to save feedback",
471
- },
472
464
  // Chat errors
473
465
  CHAT: {
474
466
  FETCH_FAILED: "Failed to load chat",