@mohasinac/appkit 4.45.0 → 4.46.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.
- package/dist/.build-stamp.json +4 -4
- package/dist/_internal/server/features/categories/live-counts.d.ts +41 -0
- package/dist/_internal/server/features/categories/live-counts.js +72 -0
- package/dist/_internal/server/features/checkout/expand-order-items.js +17 -0
- package/dist/_internal/server/features/orders/adapters.js +29 -0
- package/dist/_internal/server/features/parts/assembly.d.ts +126 -0
- package/dist/_internal/server/features/parts/assembly.js +246 -0
- package/dist/_internal/server/features/parts/data.d.ts +65 -0
- package/dist/_internal/server/features/parts/data.js +170 -0
- package/dist/_internal/server/features/parts/og.d.ts +34 -0
- package/dist/_internal/server/features/parts/og.js +66 -0
- package/dist/_internal/server/features/search/search-everything.d.ts +75 -0
- package/dist/_internal/server/features/search/search-everything.js +120 -0
- package/dist/_internal/server/features/search/search-sources.d.ts +17 -0
- package/dist/_internal/server/features/search/search-sources.js +138 -0
- package/dist/_internal/server/jobs/core/categoryTaxonomyBackfill.d.ts +70 -0
- package/dist/_internal/server/jobs/core/categoryTaxonomyBackfill.js +302 -0
- package/dist/_internal/server/jobs/core/countersReconcile.js +128 -19
- package/dist/_internal/server/jobs/core/jobRunners.js +12 -0
- package/dist/_internal/server/jobs/core/onCategoryWrite.js +73 -3
- package/dist/_internal/server/jobs/core/onProductWrite.js +93 -43
- package/dist/_internal/server/jobs/core/productViewWindows.d.ts +2 -0
- package/dist/_internal/server/jobs/core/productViewWindows.js +173 -0
- package/dist/_internal/server/jobs/core/testDataCleanup.d.ts +1 -1
- package/dist/_internal/server/jobs/core/testDataCleanup.js +27 -1
- package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +20 -0
- package/dist/_internal/server/jobs/handlers/pageViewRollup.js +25 -1
- package/dist/_internal/shared/actions/action-registry.js +36 -0
- package/dist/_internal/shared/features/promotions/schema.d.ts +2 -2
- package/dist/_internal/shared/features/shipping/protections.d.ts +93 -1
- package/dist/_internal/shared/features/shipping/protections.js +127 -0
- package/dist/_internal/shared/search/part-aliases.d.ts +44 -0
- package/dist/_internal/shared/search/part-aliases.js +104 -0
- package/dist/constants/api-endpoints.d.ts +18 -12
- package/dist/constants/api-endpoints.js +6 -8
- package/dist/constants/field-names.d.ts +0 -2
- package/dist/constants/field-names.js +0 -2
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/core/index.d.ts +0 -3
- package/dist/core/index.js +0 -2
- package/dist/errors/messages.d.ts +0 -7
- package/dist/errors/messages.js +0 -8
- package/dist/features/admin/components/AdminSectionsView.js +83 -32
- package/dist/features/admin/components/AdminSiteSettingsView.js +6 -2
- package/dist/features/admin/components/sections/sectionTemplates.d.ts +117 -0
- package/dist/features/admin/components/sections/sectionTemplates.js +213 -0
- package/dist/features/admin/schemas/firestore.d.ts +15 -0
- package/dist/features/admin/types/index.d.ts +0 -1
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +0 -2
- package/dist/features/categories/api/[id]/description-template/route.js +40 -1
- package/dist/features/categories/components/BrandDetailPageView.js +14 -3
- package/dist/features/categories/components/CategoryDetailPageView.js +89 -14
- package/dist/features/categories/components/CategoryTemplatePicker.js +9 -1
- package/dist/features/categories/repository/categories.repository.d.ts +65 -0
- package/dist/features/categories/repository/categories.repository.js +168 -22
- package/dist/features/categories/repository/category-counts.d.ts +143 -0
- package/dist/features/categories/repository/category-counts.js +224 -0
- package/dist/features/categories/schemas/category-counts.d.ts +155 -0
- package/dist/features/categories/schemas/category-counts.js +116 -0
- package/dist/features/categories/schemas/firestore.d.ts +0 -2
- package/dist/features/categories/schemas/firestore.js +0 -1
- package/dist/features/categories/utils/breadcrumb-chain.d.ts +194 -0
- package/dist/features/categories/utils/breadcrumb-chain.js +202 -0
- package/dist/features/corporate/schemas/index.d.ts +4 -4
- package/dist/features/orders/schemas/firestore.d.ts +13 -0
- package/dist/features/orders/types/index.d.ts +30 -0
- package/dist/features/parts/components/AssemblyDrawer.d.ts +107 -0
- package/dist/features/parts/components/AssemblyDrawer.js +250 -0
- package/dist/features/parts/components/ModelCompositionPanel.d.ts +37 -0
- package/dist/features/parts/components/ModelCompositionPanel.js +34 -0
- package/dist/features/parts/components/PartDetailPageView.d.ts +48 -0
- package/dist/features/parts/components/PartDetailPageView.js +20 -0
- package/dist/features/parts/components/PartsIndexPageView.d.ts +33 -0
- package/dist/features/parts/components/PartsIndexPageView.js +17 -0
- package/dist/features/parts/schemas/firestore.d.ts +257 -0
- package/dist/features/parts/schemas/firestore.js +181 -0
- package/dist/features/parts/utils/colourway-match.d.ts +62 -0
- package/dist/features/parts/utils/colourway-match.js +98 -0
- package/dist/features/parts/utils/part-breakdown.d.ts +53 -0
- package/dist/features/parts/utils/part-breakdown.js +77 -0
- package/dist/features/products/components/ProductDetailPageView.d.ts +14 -1
- package/dist/features/products/components/ProductDetailPageView.js +22 -3
- package/dist/features/products/components/ProductTabsShell.d.ts +3 -1
- package/dist/features/products/components/ProductTabsShell.js +4 -1
- package/dist/features/products/repository/category-assignment.d.ts +132 -0
- package/dist/features/products/repository/category-assignment.js +304 -0
- package/dist/features/products/repository/products.repository.d.ts +58 -1
- package/dist/features/products/repository/products.repository.js +255 -28
- package/dist/features/products/schemas/firestore.d.ts +147 -6
- package/dist/features/products/schemas/firestore.js +49 -0
- package/dist/features/search/components/SearchResultsPageView.d.ts +33 -0
- package/dist/features/search/components/SearchResultsPageView.js +21 -0
- package/dist/features/seller/components/SellerProductsView.js +129 -3
- package/dist/features/tester/seed-data/authored/admin__site-system.js +0 -15
- package/dist/features/tester/seed-data/authored/content-discovery__parts-database.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +166 -0
- package/dist/features/tester/seed-data/authored/index.js +2 -0
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +28 -1
- package/dist/index.d.ts +11 -16
- package/dist/index.js +26 -18
- package/dist/next/routing/route-map.d.ts +6 -2
- package/dist/next/routing/route-map.js +14 -1
- package/dist/providers/db-firebase/base.repository.d.ts +31 -0
- package/dist/providers/db-firebase/base.repository.js +31 -0
- package/dist/repositories/index.d.ts +1 -2
- package/dist/repositories/index.js +0 -1
- package/dist/seed/_helpers/category-content.d.ts +29 -0
- package/dist/seed/_helpers/category-content.js +98 -1
- package/dist/seed/_helpers/category-forest.js +104 -24
- package/dist/seed/_helpers/category-parts.d.ts +9 -0
- package/dist/seed/_helpers/category-parts.js +4594 -0
- package/dist/seed/carousel-slides-seed-data.js +81 -8
- package/dist/seed/categories-seed-data.js +44 -6
- package/dist/seed/homepage-sections-seed-data.js +170 -9
- package/dist/seed/index.d.ts +2 -0
- package/dist/seed/index.js +13 -0
- package/dist/seed/model-composition-seed-data.d.ts +15 -0
- package/dist/seed/model-composition-seed-data.js +8918 -0
- package/dist/seed/part-glossary-seed-data.d.ts +15 -0
- package/dist/seed/part-glossary-seed-data.js +10729 -0
- package/dist/seed/products-standard-seed-data.js +52 -0
- package/dist/seed/seed-purpose.d.ts +103 -4
- package/dist/seed/seed-purpose.js +162 -11
- package/dist/seo/json-ld.d.ts +10 -1
- package/dist/seo/json-ld.js +9 -1
- package/dist/server.d.ts +7 -0
- package/dist/server.js +11 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/utils/id-generators.d.ts +30 -0
- package/dist/utils/id-generators.js +31 -1
- package/dist/utils/search-txt-builders.js +22 -0
- package/dist/utils/search-txt.d.ts +22 -0
- package/dist/utils/search-txt.js +17 -0
- package/dist/values/success-messages.d.ts +0 -4
- package/dist/values/success-messages.js +0 -5
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +292 -16
- package/dist/core/copilot-log.repository.d.ts +0 -44
- package/dist/core/copilot-log.repository.js +0 -61
- package/dist/features/copilot/components/AdminCopilotView.d.ts +0 -21
- package/dist/features/copilot/components/AdminCopilotView.js +0 -51
- package/dist/features/copilot/components/index.d.ts +0 -2
- package/dist/features/copilot/components/index.js +0 -1
- package/dist/features/copilot/hooks/useCopilotChat.d.ts +0 -25
- package/dist/features/copilot/hooks/useCopilotChat.js +0 -65
- package/dist/features/copilot/hooks/useCopilotFeedback.d.ts +0 -15
- package/dist/features/copilot/hooks/useCopilotFeedback.js +0 -15
- package/dist/features/copilot/index.d.ts +0 -3
- package/dist/features/copilot/index.js +0 -3
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
* @tag sideEffects:none
|
|
50
50
|
*/
|
|
51
51
|
import { MODEL_LEAVES } from "./category-models.js";
|
|
52
|
-
import {
|
|
52
|
+
import { PART_LEAVES } from "./category-parts.js";
|
|
53
|
+
import { BEY_TEMPLATES, COLLECTIBLE_TEMPLATES, PART_TEMPLATES, SEALED_TEMPLATES, accessoryDefaults, beyDefaults, diecastDefaults, figureDefaults, launcherDefaults, livingDefaults, marketBand, partDefaults, stadiumDefaults, tcgDefaults, ROOT_TAX_DEFAULTS, ROOT_AUTHENTICITY_DEFAULT, } from "./category-content.js";
|
|
53
54
|
import { seedPhoto } from "./media.js";
|
|
54
55
|
const cover = (slug) => seedPhoto(`category-image-${slug}-20260101`, 1200, 600);
|
|
55
56
|
/**
|
|
@@ -78,12 +79,27 @@ function node(id, name, description, defaults, templates, children) {
|
|
|
78
79
|
extra.productDefaults = defaults;
|
|
79
80
|
if (templates)
|
|
80
81
|
extra.descriptionTemplates = templates;
|
|
82
|
+
/*
|
|
83
|
+
* 🛑 D13 — a part-type node's children are its PART LEAVES, threaded here
|
|
84
|
+
* rather than at the 20 call sites.
|
|
85
|
+
*
|
|
86
|
+
* Same shape as `line()` and `MODEL_LEAVES`: the generated map is keyed by
|
|
87
|
+
* parent id, so a node with no entry gets `[]` and is unchanged. Doing it in
|
|
88
|
+
* the helper means adding a part classification is a generator run plus one
|
|
89
|
+
* `node(...)` line, not an edit in two places that must agree.
|
|
90
|
+
*
|
|
91
|
+
* An explicit `children` argument still wins, so a node that hand-authors
|
|
92
|
+
* its children is not silently overwritten — there is none today, and the
|
|
93
|
+
* precedence has to be decided rather than discovered.
|
|
94
|
+
*/
|
|
95
|
+
const generated = PART_LEAVES[id];
|
|
96
|
+
const kids = children ?? generated;
|
|
81
97
|
return {
|
|
82
98
|
id,
|
|
83
99
|
name,
|
|
84
100
|
description,
|
|
85
101
|
...(Object.keys(extra).length ? { extra } : {}),
|
|
86
|
-
...(
|
|
102
|
+
...(kids && kids.length ? { children: kids } : {}),
|
|
87
103
|
};
|
|
88
104
|
}
|
|
89
105
|
/** A branch node — grouping only, no products file directly under it. */
|
|
@@ -115,16 +131,27 @@ const BEYBLADE_ORIGINAL = {
|
|
|
115
131
|
},
|
|
116
132
|
children: [
|
|
117
133
|
branch("category-original-tops", "Original Tops", "Complete original-series Beyblades, from the first Spin Gear releases through HMS.", [
|
|
118
|
-
line("category-original-plastic-gen", "Plastic Generation", "The earliest 1999–2000 plastic-series releases, before the Spin Gear system was formalised.", beyDefaults("category-original-plastic-gen", "Beyblade (Original)", "Plastic Generation"),
|
|
119
|
-
line("category-original-spin-gear", "Spin Gear System", "The 2000–2001 Spin Gear releases — the system that set the Attack Ring / Weight Disk / Blade Base template.", beyDefaults("category-original-spin-gear", "Beyblade (Original)", "Spin Gear System"),
|
|
120
|
-
line("category-original-magnacore", "Magnacore System", "The 2002 V-Force Magnacore line, with magnets in the base that pull a top toward or away from the stadium centre.", beyDefaults("category-original-magnacore", "Beyblade V-Force", "Magnacore System"),
|
|
121
|
-
line("category-original-engine-gear", "Engine Gear System", "The 2003 G-Revolution Engine Gear line — a wound spring inside the top that releases mid-battle.", beyDefaults("category-original-engine-gear", "Beyblade G-Revolution", "Engine Gear System"),
|
|
122
|
-
line("category-original-hms", "Heavy Metal System", "The 2003 HMS line — metal throughout, the last and heaviest of the original generation, and the highest-value tier here.", beyDefaults("category-original-hms", "Beyblade HMS", "Heavy Metal System"),
|
|
134
|
+
line("category-original-plastic-gen", "Plastic Generation", "The earliest 1999–2000 plastic-series releases, before the Spin Gear system was formalised.", beyDefaults("category-original-plastic-gen", "Beyblade (Original)", "Plastic Generation"), BEY_TEMPLATES),
|
|
135
|
+
line("category-original-spin-gear", "Spin Gear System", "The 2000–2001 Spin Gear releases — the system that set the Attack Ring / Weight Disk / Blade Base template.", beyDefaults("category-original-spin-gear", "Beyblade (Original)", "Spin Gear System"), BEY_TEMPLATES),
|
|
136
|
+
line("category-original-magnacore", "Magnacore System", "The 2002 V-Force Magnacore line, with magnets in the base that pull a top toward or away from the stadium centre.", beyDefaults("category-original-magnacore", "Beyblade V-Force", "Magnacore System"), BEY_TEMPLATES),
|
|
137
|
+
line("category-original-engine-gear", "Engine Gear System", "The 2003 G-Revolution Engine Gear line — a wound spring inside the top that releases mid-battle.", beyDefaults("category-original-engine-gear", "Beyblade G-Revolution", "Engine Gear System"), BEY_TEMPLATES),
|
|
138
|
+
line("category-original-hms", "Heavy Metal System", "The 2003 HMS line — metal throughout, the last and heaviest of the original generation, and the highest-value tier here.", beyDefaults("category-original-hms", "Beyblade HMS", "Heavy Metal System"), BEY_TEMPLATES),
|
|
123
139
|
]),
|
|
124
140
|
branch("category-original-parts", "Original Parts", "Loose Attack Rings, Weight Disks and Blade Bases for rebuilding an original-era combo.", [
|
|
125
141
|
node("category-original-attack-rings", "Attack Rings", "The upper contact ring — what actually strikes an opponent, and the part that decides a combo's attack profile.", partDefaults("category-original-attack-rings", "Attack Ring"), PART_TEMPLATES),
|
|
126
142
|
node("category-original-weight-disks", "Weight Disks", "The metal disk between ring and base. Heavier disks buy stamina; lighter ones buy speed.", partDefaults("category-original-weight-disks", "Weight Disk"), PART_TEMPLATES),
|
|
127
143
|
node("category-original-blade-bases", "Blade Bases", "The bottom assembly — tip shape, spin gear housing and, on later systems, the magnet or engine.", partDefaults("category-original-blade-bases", "Blade Base"), PART_TEMPLATES),
|
|
144
|
+
/*
|
|
145
|
+
* D13 — five part-type nodes the forest was missing, so every one of the
|
|
146
|
+
* 20 part classifications has a home. Measured before adding: 135 of 753
|
|
147
|
+
* parts (bit chips 66, running cores 25, chrome wheels 25, spin gears 14,
|
|
148
|
+
* engine gears 5) had no node to be filed under, and a part leaf with no
|
|
149
|
+
* parent is a tier-0 orphan.
|
|
150
|
+
*/
|
|
151
|
+
node("category-original-bit-chips", "Bit Chips", "The small chip at the centre of a Plastic-Gen Attack Ring, carrying the beast art. Collected in its own right and routinely swapped.", partDefaults("category-original-bit-chips", "Bit Chip"), PART_TEMPLATES),
|
|
152
|
+
node("category-original-spin-gears", "Spin Gears", "The 2000–2001 Spin Gear module that sets spin direction and locks the Blade Base to the Weight Disk.", partDefaults("category-original-spin-gears", "Spin Gear"), PART_TEMPLATES),
|
|
153
|
+
node("category-original-engine-gears", "Engine Gears", "The G-Revolution wound-spring module that releases mid-battle. Only a handful of releases used one.", partDefaults("category-original-engine-gears", "Engine Gear"), PART_TEMPLATES),
|
|
154
|
+
node("category-original-running-cores", "Running Cores", "HMS combines the Spin Gear and Blade Base into one moulded Running Core, which is why an HMS breakdown has fewer slots than a Plastic-Gen one.", partDefaults("category-original-running-cores", "Running Core"), PART_TEMPLATES),
|
|
128
155
|
]),
|
|
129
156
|
branch("category-original-launchers", "Original Launchers", "Ripcord launchers, grips and winders for original-series tops.", [
|
|
130
157
|
node("category-original-ripcord-launchers", "Ripcord Launchers", "The classic pull-cord launchers used across the original series.", launcherDefaults("category-original-ripcord-launchers", "Beyblade (Original)"), PART_TEMPLATES),
|
|
@@ -158,11 +185,11 @@ const BEYBLADE_METAL = {
|
|
|
158
185
|
},
|
|
159
186
|
children: [
|
|
160
187
|
branch("category-metal-tops", "Metal Fight Tops", "Complete Metal Fight Beyblades across all five sub-generations.", [
|
|
161
|
-
line("category-metal-phws", "Metal System", "The 2008 debut system that preceded the Hybrid Wheel System — the first metal-weighted tops.", beyDefaults("category-metal-phws", "Beyblade: Metal Fusion", "Metal System"),
|
|
162
|
-
line("category-metal-fusion", "Metal Fusion", "The Hybrid Wheel System wave that defined the era — Face Bolt, Energy Ring, Fusion Wheel, Spin Track, Tip.", beyDefaults("category-metal-fusion", "Beyblade: Metal Fusion", "Hybrid Wheel System"),
|
|
163
|
-
line("category-metal-masters", "Metal Masters", "Later Hybrid Wheel releases with heavier wheels and tighter tolerances.", beyDefaults("category-metal-masters", "Beyblade: Metal Masters", "Hybrid Wheel System"),
|
|
164
|
-
line("category-metal-fury-4d", "Metal Fury (4D)", "The 4D System wave — multi-mode wheels and switchable bottoms, and the heaviest tops of the era.", beyDefaults("category-metal-fury-4d", "Beyblade: Metal Fury", "4D System"),
|
|
165
|
-
line("category-metal-shogun-steel", "Shogun Steel / Zero-G", "The 2012–2013 Zero-G line, built for the rocking Zero-G stadium rather than a static dish.", beyDefaults("category-metal-shogun-steel", "Beyblade: Shogun Steel", "Synchrom System"),
|
|
188
|
+
line("category-metal-phws", "Metal System", "The 2008 debut system that preceded the Hybrid Wheel System — the first metal-weighted tops.", beyDefaults("category-metal-phws", "Beyblade: Metal Fusion", "Metal System"), BEY_TEMPLATES),
|
|
189
|
+
line("category-metal-fusion", "Metal Fusion", "The Hybrid Wheel System wave that defined the era — Face Bolt, Energy Ring, Fusion Wheel, Spin Track, Tip.", beyDefaults("category-metal-fusion", "Beyblade: Metal Fusion", "Hybrid Wheel System"), BEY_TEMPLATES),
|
|
190
|
+
line("category-metal-masters", "Metal Masters", "Later Hybrid Wheel releases with heavier wheels and tighter tolerances.", beyDefaults("category-metal-masters", "Beyblade: Metal Masters", "Hybrid Wheel System"), BEY_TEMPLATES),
|
|
191
|
+
line("category-metal-fury-4d", "Metal Fury (4D)", "The 4D System wave — multi-mode wheels and switchable bottoms, and the heaviest tops of the era.", beyDefaults("category-metal-fury-4d", "Beyblade: Metal Fury", "4D System"), BEY_TEMPLATES),
|
|
192
|
+
line("category-metal-shogun-steel", "Shogun Steel / Zero-G", "The 2012–2013 Zero-G line, built for the rocking Zero-G stadium rather than a static dish.", beyDefaults("category-metal-shogun-steel", "Beyblade: Shogun Steel", "Synchrom System"), BEY_TEMPLATES),
|
|
166
193
|
]),
|
|
167
194
|
branch("category-metal-parts", "Metal Fight Parts", "The four-part system sold loose — this is where a custom Metal Fight combo gets built.", [
|
|
168
195
|
node("category-metal-face-bolts", "Face Bolts", "The screw and face sticker at the top. Mostly cosmetic, occasionally a weight tweak.", partDefaults("category-metal-face-bolts", "Face Bolt"), PART_TEMPLATES),
|
|
@@ -170,6 +197,7 @@ const BEYBLADE_METAL = {
|
|
|
170
197
|
node("category-metal-fusion-wheels", "Fusion Wheels", "The metal mass of the top — the single part that most decides whether a combo attacks or endures.", partDefaults("category-metal-fusion-wheels", "Fusion Wheel"), PART_TEMPLATES),
|
|
171
198
|
node("category-metal-spin-tracks", "Spin Tracks", "The height component. 85, 100, 105, 125, 145, 230 — taller clears a dish's slope, lower sits under an opponent.", partDefaults("category-metal-spin-tracks", "Spin Track"), PART_TEMPLATES),
|
|
172
199
|
node("category-metal-performance-tips", "Performance Tips", "The floor contact: Rubber Flat, Wide Defense, Eternal Sharp, Metal Ball and the rest of the bottom vocabulary.", partDefaults("category-metal-performance-tips", "Performance Tip"), PART_TEMPLATES),
|
|
200
|
+
node("category-metal-chrome-wheels", "Chrome Wheels", "The 4D System's upper metal wheel, sold loose and the heaviest single part in the generation.", partDefaults("category-metal-chrome-wheels", "Chrome Wheel"), PART_TEMPLATES),
|
|
173
201
|
]),
|
|
174
202
|
branch("category-metal-launchers", "Metal Fight Launchers", "String launchers, ripcord launchers and grips for the Metal Fight era.", [
|
|
175
203
|
node("category-metal-string-launchers", "String Launchers", "The pull-string launchers that replaced ripcords, giving far more consistent launch power.", launcherDefaults("category-metal-string-launchers", "Beyblade: Metal Fight"), PART_TEMPLATES),
|
|
@@ -206,13 +234,13 @@ const BEYBLADE_BURST = {
|
|
|
206
234
|
},
|
|
207
235
|
children: [
|
|
208
236
|
branch("category-burst-tops", "Burst Tops", "Complete Burst-system Beyblades across every wave.", [
|
|
209
|
-
line("category-burst-classic", "Burst Classic", "The original 2015–2017 single- and dual-layer waves, before any metal entered the Layer.", beyDefaults("category-burst-classic", "Beyblade Burst", "Burst System"),
|
|
210
|
-
line("category-burst-god", "Burst God", "The God Layer wave, which added spring-loaded Layers and the first real burst-resistance tuning.", beyDefaults("category-burst-god", "Beyblade Burst God", "God Layer System"),
|
|
211
|
-
line("category-burst-cho-z", "Cho-Z", "The metal-layer wave — heavier Layers and roughly double the burst resistance of what came before.", beyDefaults("category-burst-cho-z", "Beyblade Burst Cho-Z", "Cho-Z Layer System"),
|
|
212
|
-
line("category-burst-gt", "GT", "The Gatinko wave, with a swappable chip inside the Layer for a third tuning axis.", beyDefaults("category-burst-gt", "Beyblade Burst GT", "Gatinko Layer System"),
|
|
213
|
-
line("category-burst-superking", "Superking", "The Sparking / Superking wave and its five-sided ratchet, which changed launch dynamics entirely.", beyDefaults("category-burst-superking", "Beyblade Burst Superking", "Sparking Layer System"),
|
|
214
|
-
line("category-burst-db", "Dynamite Battle", "The DB wave — Armour Tips and the heaviest Layers Burst had shipped to that point.", beyDefaults("category-burst-db", "Beyblade Burst Dynamite Battle", "Dynamite Battle Layer System"),
|
|
215
|
-
line("category-burst-bu", "Burst Ultimate", "The final Burst wave, closing the line in 2023 before Beyblade X replaced it.", beyDefaults("category-burst-bu", "Beyblade Burst Ultimate", "Burst Ultimate Layer System"),
|
|
237
|
+
line("category-burst-classic", "Burst Classic", "The original 2015–2017 single- and dual-layer waves, before any metal entered the Layer.", beyDefaults("category-burst-classic", "Beyblade Burst", "Burst System"), BEY_TEMPLATES),
|
|
238
|
+
line("category-burst-god", "Burst God", "The God Layer wave, which added spring-loaded Layers and the first real burst-resistance tuning.", beyDefaults("category-burst-god", "Beyblade Burst God", "God Layer System"), BEY_TEMPLATES),
|
|
239
|
+
line("category-burst-cho-z", "Cho-Z", "The metal-layer wave — heavier Layers and roughly double the burst resistance of what came before.", beyDefaults("category-burst-cho-z", "Beyblade Burst Cho-Z", "Cho-Z Layer System"), BEY_TEMPLATES),
|
|
240
|
+
line("category-burst-gt", "GT", "The Gatinko wave, with a swappable chip inside the Layer for a third tuning axis.", beyDefaults("category-burst-gt", "Beyblade Burst GT", "Gatinko Layer System"), BEY_TEMPLATES),
|
|
241
|
+
line("category-burst-superking", "Superking", "The Sparking / Superking wave and its five-sided ratchet, which changed launch dynamics entirely.", beyDefaults("category-burst-superking", "Beyblade Burst Superking", "Sparking Layer System"), BEY_TEMPLATES),
|
|
242
|
+
line("category-burst-db", "Dynamite Battle", "The DB wave — Armour Tips and the heaviest Layers Burst had shipped to that point.", beyDefaults("category-burst-db", "Beyblade Burst Dynamite Battle", "Dynamite Battle Layer System"), BEY_TEMPLATES),
|
|
243
|
+
line("category-burst-bu", "Burst Ultimate", "The final Burst wave, closing the line in 2023 before Beyblade X replaced it.", beyDefaults("category-burst-bu", "Beyblade Burst Ultimate", "Burst Ultimate Layer System"), BEY_TEMPLATES),
|
|
216
244
|
]),
|
|
217
245
|
branch("category-burst-parts", "Burst Parts", "Layers, Discs, Drivers and the chips and armour that bolt onto them.", [
|
|
218
246
|
node("category-burst-layers", "Layers", "The top piece — attack profile and burst resistance. The most expensive part of a Burst build.", partDefaults("category-burst-layers", "Layer"), PART_TEMPLATES),
|
|
@@ -255,10 +283,10 @@ const BEYBLADE_X = {
|
|
|
255
283
|
},
|
|
256
284
|
children: [
|
|
257
285
|
branch("category-x-tops", "Beyblade X Tops", "Complete Beyblade X tops — starters, boosters and the X-Over reissues.", [
|
|
258
|
-
line("category-x-basic", "Basic Line", "Standard three-part X tops. The entry point into the format and the bulk of its catalogue.", beyDefaults("category-x-basic", "Beyblade X", "Xtreme Gear (Basic Line)"),
|
|
259
|
-
line("category-x-unique-ux", "Unique Line (UX)", "UX releases, each Blade carrying a mechanical gimmick the Basic Line does not have.", beyDefaults("category-x-unique-ux", "Beyblade X", "Xtreme Gear (Unique Line)"),
|
|
260
|
-
line("category-x-custom-cx", "Custom Line (CX)", "CX releases, whose Blade splits into a Lock Chip, a Main Blade and an Assist Blade.", beyDefaults("category-x-custom-cx", "Beyblade X", "Xtreme Gear (Custom Line)"),
|
|
261
|
-
line("category-x-over", "X-Over Project", "Classic designs from earlier generations reissued on Beyblade X hardware.", beyDefaults("category-x-over", "Beyblade X", "Xtreme Gear (X-Over)"),
|
|
286
|
+
line("category-x-basic", "Basic Line", "Standard three-part X tops. The entry point into the format and the bulk of its catalogue.", beyDefaults("category-x-basic", "Beyblade X", "Xtreme Gear (Basic Line)"), BEY_TEMPLATES),
|
|
287
|
+
line("category-x-unique-ux", "Unique Line (UX)", "UX releases, each Blade carrying a mechanical gimmick the Basic Line does not have.", beyDefaults("category-x-unique-ux", "Beyblade X", "Xtreme Gear (Unique Line)"), BEY_TEMPLATES),
|
|
288
|
+
line("category-x-custom-cx", "Custom Line (CX)", "CX releases, whose Blade splits into a Lock Chip, a Main Blade and an Assist Blade.", beyDefaults("category-x-custom-cx", "Beyblade X", "Xtreme Gear (Custom Line)"), BEY_TEMPLATES),
|
|
289
|
+
line("category-x-over", "X-Over Project", "Classic designs from earlier generations reissued on Beyblade X hardware.", beyDefaults("category-x-over", "Beyblade X", "Xtreme Gear (X-Over)"), BEY_TEMPLATES),
|
|
262
290
|
]),
|
|
263
291
|
branch("category-x-parts", "Beyblade X Parts", "Blades, Ratchets and Bits sold loose for custom X builds.", [
|
|
264
292
|
node("category-x-blades", "Blades", "The upper piece that defines an X combo's attack shape and its ability to hold the rail.", partDefaults("category-x-blades", "Blade"), PART_TEMPLATES),
|
|
@@ -635,6 +663,58 @@ const LIVING_COLLECTIBLES = {
|
|
|
635
663
|
]),
|
|
636
664
|
],
|
|
637
665
|
};
|
|
666
|
+
/**
|
|
667
|
+
* B6 — attach each root's tax floor HERE rather than inside six `extra` blocks.
|
|
668
|
+
*
|
|
669
|
+
* 🛑 One place, because the failure mode is an OMISSION. Six hand-edited
|
|
670
|
+
* blocks is six chances to add a seventh root with no tax code, and the symptom
|
|
671
|
+
* would be three products silently resolving `DEFAULT_GST_RATE` — exactly what
|
|
672
|
+
* was measured before this (3 of 70, at `category-spinning-tops`,
|
|
673
|
+
* `category-burst-tops` and `category-x-tops`). Here, a root missing from
|
|
674
|
+
* `ROOT_TAX_DEFAULTS` is a THROW at seed time, which is a visible failure
|
|
675
|
+
* rather than a wrong rate on an invoice.
|
|
676
|
+
*
|
|
677
|
+
* It MERGES rather than overwrites: a root that already declares
|
|
678
|
+
* `productDefaults` (none does today) keeps everything it has, and a
|
|
679
|
+
* `taxCodeId` it declared itself wins. The root value is a floor.
|
|
680
|
+
*/
|
|
681
|
+
function withRootTax(root) {
|
|
682
|
+
const tax = ROOT_TAX_DEFAULTS[root.id];
|
|
683
|
+
if (!tax) {
|
|
684
|
+
throw new Error(`category-forest: root "${root.id}" has no entry in ROOT_TAX_DEFAULTS. ` +
|
|
685
|
+
"Every root needs a tax floor, or products under it resolve DEFAULT_GST_RATE " +
|
|
686
|
+
"— which C0c defines as a triage signal, not a feature.");
|
|
687
|
+
}
|
|
688
|
+
const extra = (root.extra ?? {});
|
|
689
|
+
return {
|
|
690
|
+
...root,
|
|
691
|
+
extra: {
|
|
692
|
+
...extra,
|
|
693
|
+
productDefaults: {
|
|
694
|
+
...tax,
|
|
695
|
+
/*
|
|
696
|
+
* 🛑 `unverified` AS THE ROOT FLOOR, and the value choice is the whole
|
|
697
|
+
* point. 43 of 381 listing nodes resolved NO `defaultAuthenticity` —
|
|
698
|
+
* tier 0, tier 1 and several tier-2 branches — so a product filed
|
|
699
|
+
* there got nothing.
|
|
700
|
+
*
|
|
701
|
+
* `unverified` exists precisely for this: `ProductAuthenticity`'s own
|
|
702
|
+
* docstring records that "without it, an honest seller who does not
|
|
703
|
+
* know would have to pick 'original', and silence would be
|
|
704
|
+
* indistinguishable from a genuine claim." Defaulting to `original`
|
|
705
|
+
* would have the platform make an authenticity claim nobody checked,
|
|
706
|
+
* on a marketplace whose differentiator is that it does not do that.
|
|
707
|
+
*
|
|
708
|
+
* A more specific category still WINS — `resolveCategoryDefaults`
|
|
709
|
+
* walks nearest-first, and the 6 nodes that legitimately declare
|
|
710
|
+
* `original` keep it.
|
|
711
|
+
*/
|
|
712
|
+
defaultAuthenticity: ROOT_AUTHENTICITY_DEFAULT,
|
|
713
|
+
...(extra.productDefaults ?? {}),
|
|
714
|
+
},
|
|
715
|
+
},
|
|
716
|
+
};
|
|
717
|
+
}
|
|
638
718
|
export const CATEGORY_FOREST = [
|
|
639
719
|
SPINNING_TOPS,
|
|
640
720
|
TRADING_CARDS,
|
|
@@ -642,7 +722,7 @@ export const CATEGORY_FOREST = [
|
|
|
642
722
|
HOT_WHEELS,
|
|
643
723
|
MODEL_KITS,
|
|
644
724
|
LIVING_COLLECTIBLES,
|
|
645
|
-
];
|
|
725
|
+
].map(withRootTax);
|
|
646
726
|
/*
|
|
647
727
|
* Keeps `marketBand` honest: a band keyed on a leaf id that no longer exists is
|
|
648
728
|
* dead weight that reads as coverage. Asserted by the seed, not here, because
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CategoryTreeNode } from "./category-tree";
|
|
2
|
+
/** Part leaves, keyed by the part-type node they belong under. */
|
|
3
|
+
export declare const PART_LEAVES: Record<string, CategoryTreeNode[]>;
|
|
4
|
+
/**
|
|
5
|
+
* The part leaf id for a `partGlossary` row id, and vice versa — they are the
|
|
6
|
+
* SAME string by construction, so this map exists only to let a reader see that
|
|
7
|
+
* stated rather than inferred.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PART_LEAF_COUNT = 752;
|