@stapel/categories-react 0.1.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/CHANGELOG.md +1 -0
- package/MODULE.md +194 -0
- package/README.md +191 -0
- package/dist/api/categoriesApi.d.ts +121 -0
- package/dist/api/categoriesApi.d.ts.map +1 -0
- package/dist/api/categoriesApi.js +48 -0
- package/dist/api/categoriesApi.js.map +1 -0
- package/dist/api/generated/schema.d.ts +2321 -0
- package/dist/api/generated/schema.d.ts.map +1 -0
- package/dist/api/generated/schema.js +2 -0
- package/dist/api/generated/schema.js.map +1 -0
- package/dist/api/types.d.ts +92 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/catalog/labels.d.ts +103 -0
- package/dist/catalog/labels.d.ts.map +1 -0
- package/dist/catalog/labels.js +56 -0
- package/dist/catalog/labels.js.map +1 -0
- package/dist/catalog/pks.d.ts +25 -0
- package/dist/catalog/pks.d.ts.map +1 -0
- package/dist/catalog/pks.js +38 -0
- package/dist/catalog/pks.js.map +1 -0
- package/dist/catalog/sync.d.ts +103 -0
- package/dist/catalog/sync.d.ts.map +1 -0
- package/dist/catalog/sync.js +114 -0
- package/dist/catalog/sync.js.map +1 -0
- package/dist/catalog/tree.d.ts +119 -0
- package/dist/catalog/tree.d.ts.map +1 -0
- package/dist/catalog/tree.js +166 -0
- package/dist/catalog/tree.js.map +1 -0
- package/dist/default/CatalogPage.d.ts +16 -0
- package/dist/default/CatalogPage.d.ts.map +1 -0
- package/dist/default/CatalogPage.js +13 -0
- package/dist/default/CatalogPage.js.map +1 -0
- package/dist/default/CategoryBreadcrumbsBar.d.ts +20 -0
- package/dist/default/CategoryBreadcrumbsBar.d.ts.map +1 -0
- package/dist/default/CategoryBreadcrumbsBar.js +35 -0
- package/dist/default/CategoryBreadcrumbsBar.js.map +1 -0
- package/dist/default/CategoryCarouselStrip.d.ts +22 -0
- package/dist/default/CategoryCarouselStrip.d.ts.map +1 -0
- package/dist/default/CategoryCarouselStrip.js +24 -0
- package/dist/default/CategoryCarouselStrip.js.map +1 -0
- package/dist/default/CategoryFeatureList.d.ts +23 -0
- package/dist/default/CategoryFeatureList.d.ts.map +1 -0
- package/dist/default/CategoryFeatureList.js +28 -0
- package/dist/default/CategoryFeatureList.js.map +1 -0
- package/dist/default/CategoryPage.d.ts +43 -0
- package/dist/default/CategoryPage.d.ts.map +1 -0
- package/dist/default/CategoryPage.js +21 -0
- package/dist/default/CategoryPage.js.map +1 -0
- package/dist/default/CategoryPickerField.d.ts +26 -0
- package/dist/default/CategoryPickerField.d.ts.map +1 -0
- package/dist/default/CategoryPickerField.js +40 -0
- package/dist/default/CategoryPickerField.js.map +1 -0
- package/dist/default/CategoryTreePane.d.ts +28 -0
- package/dist/default/CategoryTreePane.d.ts.map +1 -0
- package/dist/default/CategoryTreePane.js +25 -0
- package/dist/default/CategoryTreePane.js.map +1 -0
- package/dist/default/ErrorAlert.d.ts +9 -0
- package/dist/default/ErrorAlert.d.ts.map +1 -0
- package/dist/default/ErrorAlert.js +27 -0
- package/dist/default/ErrorAlert.js.map +1 -0
- package/dist/default/index.d.ts +37 -0
- package/dist/default/index.d.ts.map +1 -0
- package/dist/default/index.js +28 -0
- package/dist/default/index.js.map +1 -0
- package/dist/default/theme.d.ts +25 -0
- package/dist/default/theme.d.ts.map +1 -0
- package/dist/default/theme.js +40 -0
- package/dist/default/theme.js.map +1 -0
- package/dist/default/types.d.ts +12 -0
- package/dist/default/types.d.ts.map +1 -0
- package/dist/default/types.js +2 -0
- package/dist/default/types.js.map +1 -0
- package/dist/headless/CategoriesProvider.d.ts +19 -0
- package/dist/headless/CategoriesProvider.d.ts.map +1 -0
- package/dist/headless/CategoriesProvider.js +15 -0
- package/dist/headless/CategoriesProvider.js.map +1 -0
- package/dist/headless/CategoryBreadcrumbs.d.ts +40 -0
- package/dist/headless/CategoryBreadcrumbs.d.ts.map +1 -0
- package/dist/headless/CategoryBreadcrumbs.js +42 -0
- package/dist/headless/CategoryBreadcrumbs.js.map +1 -0
- package/dist/headless/CategoryCarousel.d.ts +48 -0
- package/dist/headless/CategoryCarousel.d.ts.map +1 -0
- package/dist/headless/CategoryCarousel.js +34 -0
- package/dist/headless/CategoryCarousel.js.map +1 -0
- package/dist/headless/CategoryFeatures.d.ts +67 -0
- package/dist/headless/CategoryFeatures.d.ts.map +1 -0
- package/dist/headless/CategoryFeatures.js +46 -0
- package/dist/headless/CategoryFeatures.js.map +1 -0
- package/dist/headless/CategoryPicker.d.ts +69 -0
- package/dist/headless/CategoryPicker.d.ts.map +1 -0
- package/dist/headless/CategoryPicker.js +86 -0
- package/dist/headless/CategoryPicker.js.map +1 -0
- package/dist/headless/CategoryTree.d.ts +55 -0
- package/dist/headless/CategoryTree.d.ts.map +1 -0
- package/dist/headless/CategoryTree.js +51 -0
- package/dist/headless/CategoryTree.js.map +1 -0
- package/dist/i18n/errorsMap.d.ts +22 -0
- package/dist/i18n/errorsMap.d.ts.map +1 -0
- package/dist/i18n/errorsMap.js +31 -0
- package/dist/i18n/errorsMap.js.map +1 -0
- package/dist/i18n/es.d.ts +25 -0
- package/dist/i18n/es.d.ts.map +1 -0
- package/dist/i18n/es.js +74 -0
- package/dist/i18n/es.js.map +1 -0
- package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
- package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.es.gen.js +58 -0
- package/dist/i18n/generated/errors.es.gen.js.map +1 -0
- package/dist/i18n/generated/errors.gen.d.ts +407 -0
- package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.gen.js +207 -0
- package/dist/i18n/generated/errors.gen.js.map +1 -0
- package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
- package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.ru.gen.js +58 -0
- package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
- package/dist/i18n/keys.d.ts +89 -0
- package/dist/i18n/keys.d.ts.map +1 -0
- package/dist/i18n/keys.js +134 -0
- package/dist/i18n/keys.js.map +1 -0
- package/dist/i18n/ru.d.ts +41 -0
- package/dist/i18n/ru.d.ts.map +1 -0
- package/dist/i18n/ru.js +90 -0
- package/dist/i18n/ru.js.map +1 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/model/catalogStore.d.ts +23 -0
- package/dist/model/catalogStore.d.ts.map +1 -0
- package/dist/model/catalogStore.js +85 -0
- package/dist/model/catalogStore.js.map +1 -0
- package/dist/model/catalogSync.d.ts +49 -0
- package/dist/model/catalogSync.d.ts.map +1 -0
- package/dist/model/catalogSync.js +64 -0
- package/dist/model/catalogSync.js.map +1 -0
- package/dist/model/context.d.ts +11 -0
- package/dist/model/context.d.ts.map +1 -0
- package/dist/model/context.js +16 -0
- package/dist/model/context.js.map +1 -0
- package/dist/model/queries.d.ts +124 -0
- package/dist/model/queries.d.ts.map +1 -0
- package/dist/model/queries.js +147 -0
- package/dist/model/queries.js.map +1 -0
- package/dist/model/queryKeys.d.ts +30 -0
- package/dist/model/queryKeys.d.ts.map +1 -0
- package/dist/model/queryKeys.js +16 -0
- package/dist/model/queryKeys.js.map +1 -0
- package/dist/model/runtime.d.ts +31 -0
- package/dist/model/runtime.d.ts.map +1 -0
- package/dist/model/runtime.js +6 -0
- package/dist/model/runtime.js.map +1 -0
- package/dist/nav/manifest.d.ts +31 -0
- package/dist/nav/manifest.d.ts.map +1 -0
- package/dist/nav/manifest.js +37 -0
- package/dist/nav/manifest.js.map +1 -0
- package/llms.txt +125 -0
- package/manifest.json +918 -0
- package/nav-manifest.json +44 -0
- package/package.json +119 -0
- package/src/analytics/generated/events.json +7 -0
- package/src/api/categoriesApi.ts +179 -0
- package/src/api/generated/schema.ts +2323 -0
- package/src/api/types.ts +99 -0
- package/src/catalog/labels.ts +129 -0
- package/src/catalog/pks.ts +35 -0
- package/src/catalog/sync.ts +169 -0
- package/src/catalog/tree.ts +242 -0
- package/src/default/CatalogPage.tsx +40 -0
- package/src/default/CategoryBreadcrumbsBar.tsx +93 -0
- package/src/default/CategoryCarouselStrip.tsx +102 -0
- package/src/default/CategoryFeatureList.tsx +125 -0
- package/src/default/CategoryPage.tsx +114 -0
- package/src/default/CategoryPickerField.tsx +173 -0
- package/src/default/CategoryTreePane.tsx +134 -0
- package/src/default/ErrorAlert.tsx +46 -0
- package/src/default/index.ts +36 -0
- package/src/default/theme.tsx +67 -0
- package/src/default/types.ts +12 -0
- package/src/headless/CategoriesProvider.tsx +20 -0
- package/src/headless/CategoryBreadcrumbs.tsx +78 -0
- package/src/headless/CategoryCarousel.tsx +80 -0
- package/src/headless/CategoryFeatures.tsx +100 -0
- package/src/headless/CategoryPicker.tsx +173 -0
- package/src/headless/CategoryTree.tsx +115 -0
- package/src/i18n/errorsMap.ts +46 -0
- package/src/i18n/es.ts +92 -0
- package/src/i18n/generated/errors.es.gen.ts +64 -0
- package/src/i18n/generated/errors.gen.ts +238 -0
- package/src/i18n/generated/errors.json +495 -0
- package/src/i18n/generated/errors.ru.gen.ts +64 -0
- package/src/i18n/keys.ts +156 -0
- package/src/i18n/ru.ts +110 -0
- package/src/index.ts +191 -0
- package/src/model/catalogStore.ts +102 -0
- package/src/model/catalogSync.ts +115 -0
- package/src/model/context.tsx +28 -0
- package/src/model/queries.ts +226 -0
- package/src/model/queryKeys.ts +50 -0
- package/src/model/runtime.ts +39 -0
- package/src/nav/manifest.ts +66 -0
- package/tsconfig.json +26 -0
package/dist/i18n/ru.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { categoriesErrorBundleRu } from "./generated/errors.ru.gen.js";
|
|
2
|
+
export { categoriesErrorBundleRu } from "./generated/errors.ru.gen.js";
|
|
3
|
+
/**
|
|
4
|
+
* Russian bundle for categories-react — the `@stapel/categories-react/i18n/ru`
|
|
5
|
+
* subpath (i18n-shipping.md §2) so the locale is opt-in: hosts that do not
|
|
6
|
+
* register it never carry these strings (the main entry does not import this
|
|
7
|
+
* module — gated by size-limit + the bundle-purity test).
|
|
8
|
+
*
|
|
9
|
+
* This is the storefront's DEFAULT language (darom-storefront verdict F1:
|
|
10
|
+
* ru-first).
|
|
11
|
+
*
|
|
12
|
+
* ── What comes from where ──────────────────────────────────────────────────
|
|
13
|
+
*
|
|
14
|
+
* `stapel-categories` ships **no `translations/` directory at all**, so 20 of
|
|
15
|
+
* the 62 registry codes can never come from an upstream catalogue. They split
|
|
16
|
+
* by owner, and the split is the whole point:
|
|
17
|
+
*
|
|
18
|
+
* - the 42 cross-cutting `stapel_core` codes are GENERATED, merged in from
|
|
19
|
+
* stapel-core's own catalogue by `pnpm gen:errors` (spread first below);
|
|
20
|
+
* - the **8 `stapel_categories` codes** are authored here — and when upstream
|
|
21
|
+
* ships a catalogue, eight lines are deleted and no key or text moves;
|
|
22
|
+
* - the **12 `stapel_attributes` codes** are NOT here. They belong to
|
|
23
|
+
* `@stapel/attributes-react`, which already translates them and which is a
|
|
24
|
+
* peer of this pair anyway. Two pairs must not give one refusal two
|
|
25
|
+
* sentences (§13.2 note 3). A host registers both bundles;
|
|
26
|
+
* `test/i18n.test.ts` proves the union covers the registry.
|
|
27
|
+
*
|
|
28
|
+
* PROVENANCE, stated rather than implied: the core catalogue ships
|
|
29
|
+
* `origin=seed:authored` and is UNREVIEWED; the pair-authored strings below
|
|
30
|
+
* are the same grade. Neither is a claim of review.
|
|
31
|
+
*
|
|
32
|
+
* And once more, because it is the fact this pair exists to be honest about:
|
|
33
|
+
* **no category name is translated here.** Category and feature names arrive
|
|
34
|
+
* as translation KEYS (`catalog/labels.ts`) and belong in the deployment's own
|
|
35
|
+
* bundle, not in a library's.
|
|
36
|
+
*/
|
|
37
|
+
export const categoriesI18nBundleRu = {
|
|
38
|
+
...categoriesErrorBundleRu,
|
|
39
|
+
// ── the 8 stapel_categories-owned codes, pair-authored ───────────────────
|
|
40
|
+
"error.400.categories_config_required": "Требуется объект config.",
|
|
41
|
+
"error.400.categories_database_error": "Ошибка базы данных при сохранении изменений.",
|
|
42
|
+
"error.400.categories_duplicate_slug": "Характеристика со слагом «{slug}» уже существует.",
|
|
43
|
+
"error.400.categories_expected_list": "Ожидался список объектов.",
|
|
44
|
+
"error.400.categories_feature_editor_invalid": "Некорректный запрос редактора характеристик: {reason}",
|
|
45
|
+
"error.400.categories_invalid_conversion": "Недопустимое преобразование типа (поддерживается только select ↔ string).",
|
|
46
|
+
"error.400.categories_not_deleted": "Категория не удалена.",
|
|
47
|
+
"error.409.categories_feature_editor_conflict": "Категорию изменил другой редактор (ожидалась ревизия {expected}, сейчас {actual}); перезагрузите страницу и повторите.",
|
|
48
|
+
"categories.error.unknown": "Что-то пошло не так с каталогом.",
|
|
49
|
+
"categories.catalog.title": "Каталог",
|
|
50
|
+
"categories.catalog.loading": "Загружаем каталог…",
|
|
51
|
+
"categories.catalog.load_failed": "Не удалось загрузить каталог.",
|
|
52
|
+
"categories.catalog.empty": "В каталоге пока нет категорий.",
|
|
53
|
+
"categories.catalog.retry": "Повторить",
|
|
54
|
+
"categories.catalog.truncated": "Каталог загружен не полностью. Категории, которой здесь нет, ещё не прочитали — её не удаляли.",
|
|
55
|
+
"categories.catalog.refreshing": "Проверяем изменения в каталоге…",
|
|
56
|
+
"categories.catalog.as_of": "Каталог на ревизию {revision}",
|
|
57
|
+
"categories.category.title": "Категория",
|
|
58
|
+
"categories.category.unknown_slug": "По этому адресу нет категории.",
|
|
59
|
+
"categories.category.subcategories": "Подкатегории",
|
|
60
|
+
"categories.category.no_subcategories": "У этой категории нет подкатегорий.",
|
|
61
|
+
"categories.category.open": "Открыть",
|
|
62
|
+
"categories.breadcrumbs.root": "Все категории",
|
|
63
|
+
"categories.breadcrumbs.label": "Вы здесь",
|
|
64
|
+
"categories.carousel.title": "Категории",
|
|
65
|
+
"categories.carousel.loading": "Загружаем категории…",
|
|
66
|
+
"categories.carousel.load_failed": "Не удалось загрузить категории.",
|
|
67
|
+
"categories.carousel.empty": "Сейчас ни одна категория не вынесена на витрину.",
|
|
68
|
+
"categories.picker.title": "Категория",
|
|
69
|
+
"categories.picker.search": "Поиск по категориям",
|
|
70
|
+
"categories.picker.loading": "Загружаем категории…",
|
|
71
|
+
"categories.picker.load_failed": "Не удалось загрузить категории.",
|
|
72
|
+
"categories.picker.no_matches": "Ни одна категория не подходит.",
|
|
73
|
+
"categories.picker.up": "На уровень выше",
|
|
74
|
+
"categories.picker.selected": "Выбрано: {category}",
|
|
75
|
+
"categories.picker.blocked.nothing_selected": "Сначала выберите категорию.",
|
|
76
|
+
"categories.picker.blocked.not_a_leaf": "Выберите категорию точнее — у этой есть подкатегории, а от них зависит, какие характеристики спросят.",
|
|
77
|
+
"categories.features.title": "Характеристики в этой категории",
|
|
78
|
+
"categories.features.loading": "Загружаем характеристики…",
|
|
79
|
+
"categories.features.load_failed": "Не удалось загрузить характеристики.",
|
|
80
|
+
"categories.features.empty": "В этой категории не нужно заполнять дополнительные характеристики.",
|
|
81
|
+
"categories.features.mandatory": "Обязательно",
|
|
82
|
+
"categories.features.type": "{type}",
|
|
83
|
+
"categories.features.untyped": "У этой характеристики нет типа, показать её нельзя.",
|
|
84
|
+
};
|
|
85
|
+
/** Register the `ru` bundle. Call AFTER `registerCategoriesI18n` so it
|
|
86
|
+
* overrides the English floor. */
|
|
87
|
+
export function registerCategoriesI18nRu(engine, locale = "ru") {
|
|
88
|
+
engine.registerBundle(locale, categoriesI18nBundleRu);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ru.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ru.js","sourceRoot":"","sources":["../../src/i18n/ru.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAmB;IACpD,GAAG,uBAAuB;IAE1B,4EAA4E;IAC5E,sCAAsC,EAAE,0BAA0B;IAClE,qCAAqC,EACnC,8CAA8C;IAChD,qCAAqC,EACnC,mDAAmD;IACrD,oCAAoC,EAAE,2BAA2B;IACjE,6CAA6C,EAC3C,uDAAuD;IACzD,yCAAyC,EACvC,2EAA2E;IAC7E,kCAAkC,EAAE,uBAAuB;IAC3D,8CAA8C,EAC5C,wHAAwH;IAE1H,0BAA0B,EAAE,kCAAkC;IAE9D,0BAA0B,EAAE,SAAS;IACrC,4BAA4B,EAAE,oBAAoB;IAClD,gCAAgC,EAAE,+BAA+B;IACjE,0BAA0B,EAAE,gCAAgC;IAC5D,0BAA0B,EAAE,WAAW;IACvC,8BAA8B,EAC5B,gGAAgG;IAClG,+BAA+B,EAAE,iCAAiC;IAClE,0BAA0B,EAAE,+BAA+B;IAE3D,2BAA2B,EAAE,WAAW;IACxC,kCAAkC,EAAE,gCAAgC;IACpE,mCAAmC,EAAE,cAAc;IACnD,sCAAsC,EAAE,oCAAoC;IAC5E,0BAA0B,EAAE,SAAS;IAErC,6BAA6B,EAAE,eAAe;IAC9C,8BAA8B,EAAE,UAAU;IAE1C,2BAA2B,EAAE,WAAW;IACxC,6BAA6B,EAAE,sBAAsB;IACrD,iCAAiC,EAAE,iCAAiC;IACpE,2BAA2B,EAAE,kDAAkD;IAE/E,yBAAyB,EAAE,WAAW;IACtC,0BAA0B,EAAE,qBAAqB;IACjD,2BAA2B,EAAE,sBAAsB;IACnD,+BAA+B,EAAE,iCAAiC;IAClE,8BAA8B,EAAE,gCAAgC;IAChE,sBAAsB,EAAE,iBAAiB;IACzC,4BAA4B,EAAE,qBAAqB;IACnD,4CAA4C,EAAE,6BAA6B;IAC3E,sCAAsC,EACpC,uGAAuG;IAEzG,2BAA2B,EAAE,iCAAiC;IAC9D,6BAA6B,EAAE,2BAA2B;IAC1D,iCAAiC,EAAE,sCAAsC;IACzE,2BAA2B,EACzB,oEAAoE;IACtE,+BAA+B,EAAE,aAAa;IAC9C,0BAA0B,EAAE,QAAQ;IACpC,6BAA6B,EAC3B,qDAAqD;CACxD,CAAC;AAEF;kCACkC;AAClC,MAAM,UAAU,wBAAwB,CAAC,MAAkB,EAAE,MAAM,GAAG,IAAI;IACxE,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;AACxD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@stapel/categories-react` — the headless React pair for stapel-categories
|
|
3
|
+
* (frontend-standard §2). Business + state only, zero visual opinion; the antd
|
|
4
|
+
* skin lives behind the `./default` subpath, so a host that renders its own
|
|
5
|
+
* catalogue chrome never carries it.
|
|
6
|
+
*
|
|
7
|
+
* ── The one-liner ──────────────────────────────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const runtime = createCategoriesRuntime({ baseUrl: "/categories/api/v1/" });
|
|
11
|
+
* <CategoriesProvider runtime={runtime}>
|
|
12
|
+
* <CatalogPage /> // or <CategoryPage slug={slug} renderListings={…} />
|
|
13
|
+
* </CategoriesProvider>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* No session, no workspace id, no auth client: every endpoint this pair calls
|
|
17
|
+
* is a SAFE method under `ReadOnlyOrStaff`, so a catalogue renders for a
|
|
18
|
+
* visitor who will never sign in.
|
|
19
|
+
*
|
|
20
|
+
* ── The four properties this pair exists to guarantee ──────────────────────
|
|
21
|
+
*
|
|
22
|
+
* 1. **The client builds the tree, because the server has none.**
|
|
23
|
+
* `GET /categories/` returns FLAT rows ordered by `revision`, with treenode
|
|
24
|
+
* ancestry as COMMA-JOINED pk strings (`"1,7,12"`, `""` for a root).
|
|
25
|
+
* `catalog/tree.ts` parses and assembles; `catalog/pks.ts` is the parser,
|
|
26
|
+
* and it exists because the spec described those columns as arrays.
|
|
27
|
+
* 2. **The catalogue is synced by delta, not refetched.** A stored snapshot
|
|
28
|
+
* (`createRepository`, `scope: "app"`) plus `?min_revision=` is the module's
|
|
29
|
+
* own documented protocol; without it every storefront page pulls the whole
|
|
30
|
+
* catalogue. Two things the documentation does not say are implemented
|
|
31
|
+
* anyway and explained where they live: `revisions.deleted_ids` is the
|
|
32
|
+
* complete tombstone channel (the `deleted: true` rows are paginated and a
|
|
33
|
+
* short walk misses them), and a multi-page walk must pin `max_revision` or
|
|
34
|
+
* a concurrent write shifts its page boundaries.
|
|
35
|
+
* 3. **A slug is resolved by the client, because the server cannot.**
|
|
36
|
+
* `lookup_field` is never overridden and the list endpoint has no slug
|
|
37
|
+
* filter, so `/c/:slug` resolves against the synced tree. That is a second,
|
|
38
|
+
* independent reason the tree is cached.
|
|
39
|
+
* 4. **Names are translation KEYS, and this pair says so.** No serializer runs
|
|
40
|
+
* the module's `DISPLAY_TRANSLATOR` seam, so `name` arrives as
|
|
41
|
+
* `category.electronics` even on a deployment with a real translator
|
|
42
|
+
* configured, and `translatable` / `translate` say per row whether a string
|
|
43
|
+
* is a key at all. `catalog/labels.ts` carries the whole answer, and the
|
|
44
|
+
* pair ships no catalogue of category names — those belong to the host.
|
|
45
|
+
*
|
|
46
|
+
* Layers: api → catalog (pure) → model → headless → i18n. Generated surfaces
|
|
47
|
+
* (the typed schema, the error map, the manifest, the nav manifest, llms.txt)
|
|
48
|
+
* are produced by the monorepo `gen:*` drivers from stapel-categories' own
|
|
49
|
+
* `docs/` artifacts and stand under drift gates.
|
|
50
|
+
*/
|
|
51
|
+
export { categoryListParams, createCategoriesApi } from "./api/categoriesApi.js";
|
|
52
|
+
export type { CategoriesApi } from "./api/categoriesApi.js";
|
|
53
|
+
export type { Category, CategoryFeature, CategoryListParams, CategoryPage as CategoryListPage, CategoryRevisions, FeatureConfig, MaxRevision, Schemas, } from "./api/types.js";
|
|
54
|
+
export { parseTreenodePks } from "./catalog/pks.js";
|
|
55
|
+
export { buildCategoryTree, categoryAncestorIds, categoryBreadcrumbs, categoryChildIds, flattenCategoryNodes, resolveCategorySlug, } from "./catalog/tree.js";
|
|
56
|
+
export type { BuildCategoryTreeOptions, CategoryIndex, CategoryNode, } from "./catalog/tree.js";
|
|
57
|
+
export { EMPTY_SNAPSHOT, applyCategoryPage, firstPageRequest, isEmptySnapshot, nextPageRequest, parseSnapshot, } from "./catalog/sync.js";
|
|
58
|
+
export type { CategorySnapshot } from "./catalog/sync.js";
|
|
59
|
+
export { categoryLabel, featureLabel, featureOptionsAreKeys, renderCategoryLabel, } from "./catalog/labels.js";
|
|
60
|
+
export type { CategoryLabel, CategoryLabelKind } from "./catalog/labels.js";
|
|
61
|
+
export { createCategoriesRuntime } from "./model/runtime.js";
|
|
62
|
+
export type { CategoriesRuntime, CreateCategoriesRuntimeOptions, } from "./model/runtime.js";
|
|
63
|
+
export { CategoriesRuntimeContext, useCategoriesAnalytics, useCategoriesApi, useCategoriesRuntime, } from "./model/context.js";
|
|
64
|
+
export { CATALOG_KEY, CATALOG_NAMESPACE, createCatalogStore, memoryCatalogStore, } from "./model/catalogStore.js";
|
|
65
|
+
export type { CatalogStore, CreateCatalogStoreOptions, } from "./model/catalogStore.js";
|
|
66
|
+
export { MAX_SYNC_PAGES, syncCatalog } from "./model/catalogSync.js";
|
|
67
|
+
export type { SyncCatalogOptions, SyncCatalogResult } from "./model/catalogSync.js";
|
|
68
|
+
export { catalogKeyOptions, categoriesQueryKeys } from "./model/queryKeys.js";
|
|
69
|
+
export type { CatalogKeyOptions } from "./model/queryKeys.js";
|
|
70
|
+
export { useCategoriesRevision, useCategoryCarousel, useCategoryCatalog, useCategoryChildren, useCategoryFeatures, } from "./model/queries.js";
|
|
71
|
+
export type { CategoryCatalog, UseCategoryCatalogOptions, } from "./model/queries.js";
|
|
72
|
+
export { CategoriesProvider } from "./headless/CategoriesProvider.js";
|
|
73
|
+
export { CategoryTree } from "./headless/CategoryTree.js";
|
|
74
|
+
export type { CategoryTreeBag, CategoryTreeProps } from "./headless/CategoryTree.js";
|
|
75
|
+
export { CategoryBreadcrumbs } from "./headless/CategoryBreadcrumbs.js";
|
|
76
|
+
export type { CategoryBreadcrumbsBag, CategoryBreadcrumbsProps, CategoryCrumb, } from "./headless/CategoryBreadcrumbs.js";
|
|
77
|
+
export { CategoryCarousel } from "./headless/CategoryCarousel.js";
|
|
78
|
+
export type { CarouselEntry, CategoryCarouselBag, CategoryCarouselProps, } from "./headless/CategoryCarousel.js";
|
|
79
|
+
export { CategoryPicker } from "./headless/CategoryPicker.js";
|
|
80
|
+
export type { CategoryOption, CategoryPickerBag, CategoryPickerBlockedReason, CategoryPickerProps, } from "./headless/CategoryPicker.js";
|
|
81
|
+
export { CategoryFeatures } from "./headless/CategoryFeatures.js";
|
|
82
|
+
export type { CategoryFeatureEntry, CategoryFeaturesBag, CategoryFeaturesProps, } from "./headless/CategoryFeatures.js";
|
|
83
|
+
export { navEntries } from "./nav/manifest.js";
|
|
84
|
+
export { CATEGORIES_I18N_KEYS, categoriesI18nBundleEn, registerCategoriesI18n, } from "./i18n/keys.js";
|
|
85
|
+
export type { CategoriesI18nKey } from "./i18n/keys.js";
|
|
86
|
+
export { CATEGORIES_ERRORS, CATEGORIES_ERROR_CODES, CATEGORIES_FEATURE_EDITOR_CONFLICT, categoriesErrorBundleEn, explainCategoriesError, } from "./i18n/errorsMap.js";
|
|
87
|
+
export type { CategoriesErrorCode, CategoriesErrorSpec, Remediation, } from "./i18n/errorsMap.js";
|
|
88
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@stapel/categories-react` — the headless React pair for stapel-categories
|
|
3
|
+
* (frontend-standard §2). Business + state only, zero visual opinion; the antd
|
|
4
|
+
* skin lives behind the `./default` subpath, so a host that renders its own
|
|
5
|
+
* catalogue chrome never carries it.
|
|
6
|
+
*
|
|
7
|
+
* ── The one-liner ──────────────────────────────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const runtime = createCategoriesRuntime({ baseUrl: "/categories/api/v1/" });
|
|
11
|
+
* <CategoriesProvider runtime={runtime}>
|
|
12
|
+
* <CatalogPage /> // or <CategoryPage slug={slug} renderListings={…} />
|
|
13
|
+
* </CategoriesProvider>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* No session, no workspace id, no auth client: every endpoint this pair calls
|
|
17
|
+
* is a SAFE method under `ReadOnlyOrStaff`, so a catalogue renders for a
|
|
18
|
+
* visitor who will never sign in.
|
|
19
|
+
*
|
|
20
|
+
* ── The four properties this pair exists to guarantee ──────────────────────
|
|
21
|
+
*
|
|
22
|
+
* 1. **The client builds the tree, because the server has none.**
|
|
23
|
+
* `GET /categories/` returns FLAT rows ordered by `revision`, with treenode
|
|
24
|
+
* ancestry as COMMA-JOINED pk strings (`"1,7,12"`, `""` for a root).
|
|
25
|
+
* `catalog/tree.ts` parses and assembles; `catalog/pks.ts` is the parser,
|
|
26
|
+
* and it exists because the spec described those columns as arrays.
|
|
27
|
+
* 2. **The catalogue is synced by delta, not refetched.** A stored snapshot
|
|
28
|
+
* (`createRepository`, `scope: "app"`) plus `?min_revision=` is the module's
|
|
29
|
+
* own documented protocol; without it every storefront page pulls the whole
|
|
30
|
+
* catalogue. Two things the documentation does not say are implemented
|
|
31
|
+
* anyway and explained where they live: `revisions.deleted_ids` is the
|
|
32
|
+
* complete tombstone channel (the `deleted: true` rows are paginated and a
|
|
33
|
+
* short walk misses them), and a multi-page walk must pin `max_revision` or
|
|
34
|
+
* a concurrent write shifts its page boundaries.
|
|
35
|
+
* 3. **A slug is resolved by the client, because the server cannot.**
|
|
36
|
+
* `lookup_field` is never overridden and the list endpoint has no slug
|
|
37
|
+
* filter, so `/c/:slug` resolves against the synced tree. That is a second,
|
|
38
|
+
* independent reason the tree is cached.
|
|
39
|
+
* 4. **Names are translation KEYS, and this pair says so.** No serializer runs
|
|
40
|
+
* the module's `DISPLAY_TRANSLATOR` seam, so `name` arrives as
|
|
41
|
+
* `category.electronics` even on a deployment with a real translator
|
|
42
|
+
* configured, and `translatable` / `translate` say per row whether a string
|
|
43
|
+
* is a key at all. `catalog/labels.ts` carries the whole answer, and the
|
|
44
|
+
* pair ships no catalogue of category names — those belong to the host.
|
|
45
|
+
*
|
|
46
|
+
* Layers: api → catalog (pure) → model → headless → i18n. Generated surfaces
|
|
47
|
+
* (the typed schema, the error map, the manifest, the nav manifest, llms.txt)
|
|
48
|
+
* are produced by the monorepo `gen:*` drivers from stapel-categories' own
|
|
49
|
+
* `docs/` artifacts and stand under drift gates.
|
|
50
|
+
*/
|
|
51
|
+
// ── api ──────────────────────────────────────────────────────────────────────
|
|
52
|
+
export { categoryListParams, createCategoriesApi } from "./api/categoriesApi.js";
|
|
53
|
+
// ── catalog (pure: no React, no fetch, no storage) ───────────────────────────
|
|
54
|
+
export { parseTreenodePks } from "./catalog/pks.js";
|
|
55
|
+
export { buildCategoryTree, categoryAncestorIds, categoryBreadcrumbs, categoryChildIds, flattenCategoryNodes, resolveCategorySlug, } from "./catalog/tree.js";
|
|
56
|
+
export { EMPTY_SNAPSHOT, applyCategoryPage, firstPageRequest, isEmptySnapshot, nextPageRequest, parseSnapshot, } from "./catalog/sync.js";
|
|
57
|
+
export { categoryLabel, featureLabel, featureOptionsAreKeys, renderCategoryLabel, } from "./catalog/labels.js";
|
|
58
|
+
// ── model (runtime wiring, persistence, sync driver, hooks) ──────────────────
|
|
59
|
+
export { createCategoriesRuntime } from "./model/runtime.js";
|
|
60
|
+
export { CategoriesRuntimeContext, useCategoriesAnalytics, useCategoriesApi, useCategoriesRuntime, } from "./model/context.js";
|
|
61
|
+
export { CATALOG_KEY, CATALOG_NAMESPACE, createCatalogStore, memoryCatalogStore, } from "./model/catalogStore.js";
|
|
62
|
+
export { MAX_SYNC_PAGES, syncCatalog } from "./model/catalogSync.js";
|
|
63
|
+
export { catalogKeyOptions, categoriesQueryKeys } from "./model/queryKeys.js";
|
|
64
|
+
export { useCategoriesRevision, useCategoryCarousel, useCategoryCatalog, useCategoryChildren, useCategoryFeatures, } from "./model/queries.js";
|
|
65
|
+
// ── headless (renderless components) ─────────────────────────────────────────
|
|
66
|
+
export { CategoriesProvider } from "./headless/CategoriesProvider.js";
|
|
67
|
+
export { CategoryTree } from "./headless/CategoryTree.js";
|
|
68
|
+
export { CategoryBreadcrumbs } from "./headless/CategoryBreadcrumbs.js";
|
|
69
|
+
export { CategoryCarousel } from "./headless/CategoryCarousel.js";
|
|
70
|
+
export { CategoryPicker } from "./headless/CategoryPicker.js";
|
|
71
|
+
export { CategoryFeatures } from "./headless/CategoryFeatures.js";
|
|
72
|
+
// ── nav manifest (the pair's public surface declaration) ─────────────────────
|
|
73
|
+
export { navEntries } from "./nav/manifest.js";
|
|
74
|
+
// ── i18n ─────────────────────────────────────────────────────────────────────
|
|
75
|
+
export { CATEGORIES_I18N_KEYS, categoriesI18nBundleEn, registerCategoriesI18n, } from "./i18n/keys.js";
|
|
76
|
+
// ── errors map (code → status/params/remediation/en; generated) ──────────────
|
|
77
|
+
export { CATEGORIES_ERRORS, CATEGORIES_ERROR_CODES, CATEGORIES_FEATURE_EDITOR_CONFLICT, categoriesErrorBundleEn, explainCategoriesError, } from "./i18n/errorsMap.js";
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,gFAAgF;AAChF,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAajF,gFAAgF;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAG7B,gFAAgF;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAK7D,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AAKjC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE9E,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAM5B,gFAAgF;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAMxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAMlE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAO9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAOlE,gFAAgF;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,gFAAgF;AAChF,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAGxB,gFAAgF;AAChF,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,kCAAkC,EAClC,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Repository } from "@stapel/core";
|
|
2
|
+
import type { CategorySnapshot } from "../catalog/sync.js";
|
|
3
|
+
/** The repository namespace. Changing it orphans every stored snapshot, which
|
|
4
|
+
* is the intended migration for a shape change too large for `version`. */
|
|
5
|
+
export declare const CATALOG_NAMESPACE = "categories.catalog";
|
|
6
|
+
/** The single key inside that namespace. */
|
|
7
|
+
export declare const CATALOG_KEY = "snapshot";
|
|
8
|
+
/** Read / write the catalogue snapshot, with every failure mode absorbed. */
|
|
9
|
+
export interface CatalogStore {
|
|
10
|
+
load(): Promise<CategorySnapshot>;
|
|
11
|
+
save(snapshot: CategorySnapshot): Promise<void>;
|
|
12
|
+
clear(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export interface CreateCatalogStoreOptions {
|
|
15
|
+
/** Inject a repository (tests, SSR, a host with its own backend). Default:
|
|
16
|
+
* an app-scoped repository under {@link CATALOG_NAMESPACE}. */
|
|
17
|
+
readonly repository?: Repository<unknown>;
|
|
18
|
+
}
|
|
19
|
+
/** A store that remembers nothing — the honest fallback when persistence is
|
|
20
|
+
* unavailable, and what a caller passes to opt out of caching entirely. */
|
|
21
|
+
export declare function memoryCatalogStore(): CatalogStore;
|
|
22
|
+
export declare function createCatalogStore(options?: CreateCatalogStoreOptions): CatalogStore;
|
|
23
|
+
//# sourceMappingURL=catalogStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogStore.d.ts","sourceRoot":"","sources":["../../src/model/catalogStore.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;2EAC2E;AAC3E,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,4CAA4C;AAC5C,eAAO,MAAM,WAAW,aAAa,CAAC;AAEtC,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC;mEAC+D;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC3C;AAED;2EAC2E;AAC3E,wBAAgB,kBAAkB,IAAI,YAAY,CAajD;AAED,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,yBAA8B,GACtC,YAAY,CAmCd"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the catalogue lives between page loads.
|
|
3
|
+
*
|
|
4
|
+
* `createRepository` is the ONE sanctioned client-side persistence primitive
|
|
5
|
+
* (`@stapel/core` `repository.ts`; direct `localStorage` outside it is a lint
|
|
6
|
+
* error, `stapel/no-raw-storage`), and the spec's verdict (§4.3) puts the tree
|
|
7
|
+
* in it with `scope: "app"`.
|
|
8
|
+
*
|
|
9
|
+
* **`scope: "app"` is a correctness choice, not a size one.** A user-scoped
|
|
10
|
+
* repository is encrypted with the per-session key and wiped on logout, with
|
|
11
|
+
* no opt-out — both of which are wrong here twice over: the category tree is
|
|
12
|
+
* a deployment's PUBLIC content, identical for every visitor and for a visitor
|
|
13
|
+
* with no session at all, and wiping it at logout would re-download the whole
|
|
14
|
+
* catalogue for somebody who just signed out of a storefront they are still
|
|
15
|
+
* browsing. App scope also means `createRepository` never asks for a
|
|
16
|
+
* `SessionManager`, so the store works on a page with no auth wired at all.
|
|
17
|
+
*
|
|
18
|
+
* A repository read can fail or return junk (a private window, cleared site
|
|
19
|
+
* data, a snapshot written by an older shape). Every read here degrades to
|
|
20
|
+
* "no snapshot" — a cold sync costs one request; a cache that throws costs
|
|
21
|
+
* the page.
|
|
22
|
+
*/
|
|
23
|
+
import { createRepository } from "@stapel/core";
|
|
24
|
+
import { EMPTY_SNAPSHOT, parseSnapshot } from "../catalog/sync.js";
|
|
25
|
+
/** The repository namespace. Changing it orphans every stored snapshot, which
|
|
26
|
+
* is the intended migration for a shape change too large for `version`. */
|
|
27
|
+
export const CATALOG_NAMESPACE = "categories.catalog";
|
|
28
|
+
/** The single key inside that namespace. */
|
|
29
|
+
export const CATALOG_KEY = "snapshot";
|
|
30
|
+
/** A store that remembers nothing — the honest fallback when persistence is
|
|
31
|
+
* unavailable, and what a caller passes to opt out of caching entirely. */
|
|
32
|
+
export function memoryCatalogStore() {
|
|
33
|
+
let held = EMPTY_SNAPSHOT;
|
|
34
|
+
return {
|
|
35
|
+
load: () => Promise.resolve(held),
|
|
36
|
+
save: (snapshot) => {
|
|
37
|
+
held = snapshot;
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
},
|
|
40
|
+
clear: () => {
|
|
41
|
+
held = EMPTY_SNAPSHOT;
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function createCatalogStore(options = {}) {
|
|
47
|
+
let repository;
|
|
48
|
+
try {
|
|
49
|
+
repository =
|
|
50
|
+
options.repository ??
|
|
51
|
+
createRepository(CATALOG_NAMESPACE, { scope: "app" });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// No storage backend at all (an exotic runtime, a locked-down origin).
|
|
55
|
+
return memoryCatalogStore();
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
async load() {
|
|
59
|
+
try {
|
|
60
|
+
return parseSnapshot(await repository.get(CATALOG_KEY)) ?? EMPTY_SNAPSHOT;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return EMPTY_SNAPSHOT;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
async save(snapshot) {
|
|
67
|
+
try {
|
|
68
|
+
await repository.set(CATALOG_KEY, snapshot);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// A full quota or a blocked origin must not fail the render that
|
|
72
|
+
// triggered the sync: the catalogue is already in memory and correct.
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
async clear() {
|
|
76
|
+
try {
|
|
77
|
+
await repository.del(CATALOG_KEY);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
/* nothing to undo */
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=catalogStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogStore.js","sourceRoot":"","sources":["../../src/model/catalogStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnE;2EAC2E;AAC3E,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAEtD,4CAA4C;AAC5C,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AAetC;2EAC2E;AAC3E,MAAM,UAAU,kBAAkB;IAChC,IAAI,IAAI,GAAqB,cAAc,CAAC;IAC5C,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;QACjC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;YACjB,IAAI,GAAG,QAAQ,CAAC;YAChB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,IAAI,GAAG,cAAc,CAAC;YACtB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,UAAqC,EAAE;IAEvC,IAAI,UAA+B,CAAC;IACpC,IAAI,CAAC;QACH,UAAU;YACR,OAAO,CAAC,UAAU;gBAClB,gBAAgB,CAAU,iBAAiB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,OAAO,kBAAkB,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI;YACR,IAAI,CAAC;gBACH,OAAO,aAAa,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,cAAc,CAAC;YAC5E,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,cAAc,CAAC;YACxB,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,QAAQ;YACjB,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC9C,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;gBACjE,sEAAsE;YACxE,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,qBAAqB;YACvB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sync walk: stored snapshot → one request or several → a fresh snapshot.
|
|
3
|
+
*
|
|
4
|
+
* Pure of React, so the same routine serves the hook, an SSR prefetch and a
|
|
5
|
+
* test. The rules it enforces are all in `catalog/sync.ts`; this is the loop
|
|
6
|
+
* that applies them, plus the two guards a loop over a paginated endpoint
|
|
7
|
+
* needs:
|
|
8
|
+
*
|
|
9
|
+
* - a **page budget**, because `has_next` is server-reported and a bug there
|
|
10
|
+
* (or a catalogue growing faster than the walk reads it) is an infinite
|
|
11
|
+
* request loop against someone's production API, not a slow render; and
|
|
12
|
+
* - **publish-on-completion**, so a walk that dies on page 3 leaves the
|
|
13
|
+
* previous catalogue intact instead of replacing it with two thirds of one.
|
|
14
|
+
*/
|
|
15
|
+
import type { CategoriesApi } from "../api/categoriesApi.js";
|
|
16
|
+
import type { CategorySnapshot } from "../catalog/sync.js";
|
|
17
|
+
/**
|
|
18
|
+
* Hard ceiling on pages per sync. At the server's max `page_size` of 1000 this
|
|
19
|
+
* is a million categories — far beyond any real catalogue, and small enough
|
|
20
|
+
* that a runaway loop stops in seconds instead of hammering a backend.
|
|
21
|
+
*/
|
|
22
|
+
export declare const MAX_SYNC_PAGES = 1000;
|
|
23
|
+
export interface SyncCatalogOptions {
|
|
24
|
+
readonly signal?: AbortSignal;
|
|
25
|
+
/** Rows per request. Server default 100, maximum 1000. */
|
|
26
|
+
readonly pageSize?: number;
|
|
27
|
+
readonly maxPages?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface SyncCatalogResult {
|
|
30
|
+
readonly snapshot: CategorySnapshot;
|
|
31
|
+
/** `true` when the walk started from nothing (a cold catalogue). */
|
|
32
|
+
readonly wasFullSync: boolean;
|
|
33
|
+
/** How many requests the walk actually made. `0` is impossible — the
|
|
34
|
+
* freshness probe is the caller's job, not this function's. */
|
|
35
|
+
readonly pages: number;
|
|
36
|
+
/** The page budget stopped the walk before `has_next` did. The snapshot is
|
|
37
|
+
* a truncated catalogue and the caller must NOT treat it as complete. */
|
|
38
|
+
readonly truncated: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Bring `stored` up to date.
|
|
42
|
+
*
|
|
43
|
+
* A cold start walks the whole catalogue into a fresh accumulator; a warm
|
|
44
|
+
* start folds the delta into the stored rows. Which one happens is decided by
|
|
45
|
+
* `firstPageRequest` and by what the accumulator starts as — there is no flag
|
|
46
|
+
* that a caller could set the wrong way (see `catalog/sync.ts`).
|
|
47
|
+
*/
|
|
48
|
+
export declare function syncCatalog(api: CategoriesApi, stored: CategorySnapshot, options?: SyncCatalogOptions): Promise<SyncCatalogResult>;
|
|
49
|
+
//# sourceMappingURL=catalogSync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogSync.d.ts","sourceRoot":"","sources":["../../src/model/catalogSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAS7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;mEAC+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;6EACyE;IACzE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAmD5B"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { EMPTY_SNAPSHOT, applyCategoryPage, firstPageRequest, isEmptySnapshot, nextPageRequest, } from "../catalog/sync.js";
|
|
2
|
+
/**
|
|
3
|
+
* Hard ceiling on pages per sync. At the server's max `page_size` of 1000 this
|
|
4
|
+
* is a million categories — far beyond any real catalogue, and small enough
|
|
5
|
+
* that a runaway loop stops in seconds instead of hammering a backend.
|
|
6
|
+
*/
|
|
7
|
+
export const MAX_SYNC_PAGES = 1000;
|
|
8
|
+
/**
|
|
9
|
+
* Bring `stored` up to date.
|
|
10
|
+
*
|
|
11
|
+
* A cold start walks the whole catalogue into a fresh accumulator; a warm
|
|
12
|
+
* start folds the delta into the stored rows. Which one happens is decided by
|
|
13
|
+
* `firstPageRequest` and by what the accumulator starts as — there is no flag
|
|
14
|
+
* that a caller could set the wrong way (see `catalog/sync.ts`).
|
|
15
|
+
*/
|
|
16
|
+
export async function syncCatalog(api, stored, options = {}) {
|
|
17
|
+
const wasFullSync = isEmptySnapshot(stored);
|
|
18
|
+
const budget = options.maxPages ?? MAX_SYNC_PAGES;
|
|
19
|
+
let request = {
|
|
20
|
+
...firstPageRequest(stored),
|
|
21
|
+
...(options.pageSize !== undefined ? { pageSize: options.pageSize } : {}),
|
|
22
|
+
};
|
|
23
|
+
// A full sync must not inherit rows the server is no longer listing, so it
|
|
24
|
+
// accumulates from empty. A delta folds into what is already known.
|
|
25
|
+
let accumulator = wasFullSync
|
|
26
|
+
? EMPTY_SNAPSHOT
|
|
27
|
+
: { ...stored };
|
|
28
|
+
let pages = 0;
|
|
29
|
+
let truncated = false;
|
|
30
|
+
while (request !== undefined) {
|
|
31
|
+
if (pages >= budget) {
|
|
32
|
+
truncated = true;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
const current = request;
|
|
36
|
+
const page = await api.list(current, {
|
|
37
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
38
|
+
});
|
|
39
|
+
pages += 1;
|
|
40
|
+
accumulator = applyCategoryPage(accumulator, page, {
|
|
41
|
+
// The walk pinned its window with `max_revision`; the cursor may not
|
|
42
|
+
// claim to have read past it.
|
|
43
|
+
...(current.maxRevision !== undefined
|
|
44
|
+
? { cursorLimit: current.maxRevision }
|
|
45
|
+
: {}),
|
|
46
|
+
});
|
|
47
|
+
request = nextPageRequest(current, page);
|
|
48
|
+
}
|
|
49
|
+
if (truncated) {
|
|
50
|
+
// The rows gathered so far are still worth showing — a partial catalogue
|
|
51
|
+
// beats a blank menu — but the CURSOR must not advance, or the next sync
|
|
52
|
+
// asks for a delta on top of a catalogue that was never fully read and the
|
|
53
|
+
// gap becomes permanent. Rewinding it here means the worst case is one
|
|
54
|
+
// repeated full walk, not a silently incomplete tree forever.
|
|
55
|
+
return {
|
|
56
|
+
snapshot: { ...accumulator, cursor: stored.cursor },
|
|
57
|
+
wasFullSync,
|
|
58
|
+
pages,
|
|
59
|
+
truncated,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { snapshot: accumulator, wasFullSync, pages, truncated };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=catalogSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogSync.js","sourceRoot":"","sources":["../../src/model/catalogSync.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAqBnC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAkB,EAClB,MAAwB,EACxB,UAA8B,EAAE;IAEhC,MAAM,WAAW,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,IAAI,cAAc,CAAC;IAElD,IAAI,OAAO,GAAmC;QAC5C,GAAG,gBAAgB,CAAC,MAAM,CAAC;QAC3B,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;IACF,2EAA2E;IAC3E,oEAAoE;IACpE,IAAI,WAAW,GAAqB,WAAW;QAC7C,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAClB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACpB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAuB,OAAO,CAAC;QAC5C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;YACnC,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpE,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;QACX,WAAW,GAAG,iBAAiB,CAAC,WAAW,EAAE,IAAI,EAAE;YACjD,qEAAqE;YACrE,8BAA8B;YAC9B,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS;gBACnC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;gBACtC,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QACH,OAAO,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,yEAAyE;QACzE,yEAAyE;QACzE,2EAA2E;QAC3E,uEAAuE;QACvE,8DAA8D;QAC9D,OAAO;YACL,QAAQ,EAAE,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YACnD,WAAW;YACX,KAAK;YACL,SAAS;SACV,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context } from "react";
|
|
2
|
+
import type { Analytics, ModuleContextKit } from "@stapel/core";
|
|
3
|
+
import type { CategoriesApi } from "../api/categoriesApi.js";
|
|
4
|
+
import type { CategoriesRuntime } from "./runtime.js";
|
|
5
|
+
export declare const CategoriesRuntimeContext: Context<CategoriesRuntime | null>;
|
|
6
|
+
export declare const useCategoriesRuntime: () => CategoriesRuntime;
|
|
7
|
+
export declare const useCategoriesApi: () => CategoriesApi;
|
|
8
|
+
export declare const useCategoriesAnalytics: () => Analytics | null;
|
|
9
|
+
/** @internal Re-exported as `<CategoriesProvider>` from `headless/`. */
|
|
10
|
+
export declare const ModuleProvider: ModuleContextKit<CategoriesRuntime>["Provider"];
|
|
11
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/model/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAYtD,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAAC,iBAAiB,GAAG,IAAI,CACnD,CAAC;AAErB,eAAO,MAAM,oBAAoB,EAAE,MAAM,iBAAkC,CAAC;AAE5E,eAAO,MAAM,gBAAgB,EAAE,MAAM,aAA0B,CAAC;AAEhE,eAAO,MAAM,sBAAsB,EAAE,MAAM,SAAS,GAAG,IAAuB,CAAC;AAE/E,wEAAwE;AACxE,eAAO,MAAM,cAAc,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,UAAU,CAC7D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createModuleContext } from "@stapel/core";
|
|
2
|
+
/**
|
|
3
|
+
* The wired CategoriesRuntime shared through React context by
|
|
4
|
+
* `<CategoriesProvider>`. Hooks in `model/` and `headless/` read the
|
|
5
|
+
* singletons from here. One reviewed copy of this plumbing lives in
|
|
6
|
+
* `@stapel/core` (`createModuleContext`, slim wave §21/S2); this module binds
|
|
7
|
+
* it under the pair's public names.
|
|
8
|
+
*/
|
|
9
|
+
const kit = createModuleContext("Categories");
|
|
10
|
+
export const CategoriesRuntimeContext = kit.RuntimeContext;
|
|
11
|
+
export const useCategoriesRuntime = kit.useRuntime;
|
|
12
|
+
export const useCategoriesApi = kit.useApi;
|
|
13
|
+
export const useCategoriesAnalytics = kit.useAnalytics;
|
|
14
|
+
/** @internal Re-exported as `<CategoriesProvider>` from `headless/`. */
|
|
15
|
+
export const ModuleProvider = kit.Provider;
|
|
16
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/model/context.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAKnD;;;;;;GAMG;AACH,MAAM,GAAG,GACP,mBAAmB,CAAoB,YAAY,CAAC,CAAC;AAEvD,MAAM,CAAC,MAAM,wBAAwB,GACnC,GAAG,CAAC,cAAc,CAAC;AAErB,MAAM,CAAC,MAAM,oBAAoB,GAA4B,GAAG,CAAC,UAAU,CAAC;AAE5E,MAAM,CAAC,MAAM,gBAAgB,GAAwB,GAAG,CAAC,MAAM,CAAC;AAEhE,MAAM,CAAC,MAAM,sBAAsB,GAA2B,GAAG,CAAC,YAAY,CAAC;AAE/E,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GACzB,GAAG,CAAC,QAAQ,CAAC"}
|