@vitrine-kit/core 0.2.0 → 0.2.1

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/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # @vitrine-kit/core
2
2
 
3
- Критическая логика Vitrine: runtime слотов и адаптера, order pipeline, обработчик Stripe-вебхука.
3
+ Vitrine's critical logic: the slot and adapter runtime, the order pipeline, and the Stripe webhook handler.
4
4
 
5
- Здесь то, где «баг = инцидент у всех клиентов сразу» (§4 спеки). Поэтому это **версионируемый пакет**, а не copy-in: критфикс прилетает всем бампом версии.
6
-
7
- Скелет (M0). Наполняется в M2 (runtime) и M8 (коммерция).
5
+ This is where "a bug = an incident for every client at once" (spec §4). That's why it's a **versioned package** rather than copy-in: a critical fix reaches everyone via a version bump.
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- export { S as SlotRegistry, c as createSlotRegistry, g as getSlotMounts, r as registerSlot, s as slotRegistry } from './registry-B4Ak1hIR.js';
1
+ export { S as SlotRegistry, c as createSlotRegistry, g as getSlotMounts, r as registerSlot, s as slotRegistry } from './registry-CfORxf9H.js';
2
2
  import { Backend, SiteConfig, CatalogSource, CommerceBackend, Cart, Order, Money, CurrencyCode, OrderStatus } from '@vitrine-kit/contracts';
3
3
 
4
4
  interface AdapterFactory {
5
5
  backend: Backend;
6
6
  createCatalog(config: SiteConfig): CatalogSource;
7
- /** Отсутствует для чисто-каталожных бэкендов. */
7
+ /** Absent for catalog-only backends. */
8
8
  createCommerce?(config: SiteConfig): CommerceBackend;
9
9
  }
10
10
  interface AdapterRegistry {
@@ -14,82 +14,82 @@ interface AdapterRegistry {
14
14
  clear(): void;
15
15
  }
16
16
  declare function createAdapterRegistry(): AdapterRegistry;
17
- /** Глобальный реестр адаптеров по умолчанию. */
17
+ /** The default global adapter registry. */
18
18
  declare const adapters: AdapterRegistry;
19
19
 
20
20
  interface OrderPipelineContext {
21
21
  cart: Cart;
22
- /** Заполняется шагами пайплайна (создание заказа). */
22
+ /** Filled by pipeline stages (order creation). */
23
23
  order?: Order;
24
- /** Произвольные данные шагов (платёж, резерв склада, доставка). */
24
+ /** Arbitrary stage data (payment, stock reservation, shipping). */
25
25
  meta: Record<string, unknown>;
26
26
  }
27
27
  type OrderStage<T = OrderPipelineContext> = (ctx: T) => T | Promise<T>;
28
28
  /**
29
- * Последовательно прогоняет контекст через шаги. Любая ошибка шага прерывает
30
- * пайплайн (откат/идемпотентность ответственность конкретных шагов в M8).
29
+ * Runs the context through the stages sequentially. Any stage error aborts the
30
+ * pipeline (rollback/idempotency are the responsibility of specific stages in M8).
31
31
  */
32
32
  declare function runPipeline<T>(ctx: T, stages: ReadonlyArray<OrderStage<T>>): Promise<T>;
33
33
 
34
34
  interface OrderCreationGuard {
35
- /** Статус корзины (карты Payload `carts`): 'converted' = уже оплачена. */
35
+ /** Cart status (the Payload `carts` map): 'converted' = already paid. */
36
36
  cartStatus?: string | null;
37
- /** Референс платежа текущего события (session/transaction/payment id). */
37
+ /** Payment reference of the current event (session/transaction/payment id). */
38
38
  providerRef?: string;
39
- /** paymentRef уже существующих заказов (обычно результат точечного поиска). */
39
+ /** paymentRef of existing orders (usually the result of a targeted lookup). */
40
40
  existingOrderRefs?: ReadonlyArray<string | undefined>;
41
41
  }
42
42
  /**
43
- * Создавать ли заказ для этого события. false, если корзина уже converted ИЛИ
44
- * для этого референса платежа заказ уже есть (повторная доставка/ретрай webhook).
43
+ * Whether to create an order for this event. false if the cart is already converted OR
44
+ * an order already exists for this payment reference (redelivery/retry of the webhook).
45
45
  */
46
46
  declare function shouldCreateOrder(guard: OrderCreationGuard): boolean;
47
47
 
48
- /** Совпадает с integrations.payments в site.config (контракт 4). */
48
+ /** Matches integrations.payments in site.config (contract 4). */
49
49
  type PaymentProviderName = 'stripe' | 'paddle' | 'yookassa';
50
50
  interface CreateCheckoutArgs {
51
51
  cart: Cart;
52
- /** Базовый URL витрины; success/cancel строятся относительно него. */
52
+ /** The storefront base URL; success/cancel are built relative to it. */
53
53
  baseUrl: string;
54
- /** По умолчанию '/order/success'. */
54
+ /** Defaults to '/order/success'. */
55
55
  successPath?: string;
56
- /** По умолчанию '/cart'. */
56
+ /** Defaults to '/cart'. */
57
57
  cancelPath?: string;
58
58
  }
59
59
  interface PaymentWebhookRequest {
60
60
  rawBody: string;
61
61
  headers: Record<string, string | null>;
62
62
  }
63
- /** Нормализованное событие провайдераобщий язык для роутов вебхуков. */
63
+ /** A normalized provider event the common language for webhook routes. */
64
64
  interface NormalizedPaymentEvent {
65
65
  kind: 'checkout_completed' | 'payment_failed' | 'unknown';
66
- /** Из metadata/custom_data/label провайдера. */
66
+ /** From the provider's metadata/custom_data/label. */
67
67
  cartId?: string;
68
- /** Уникальный референс платежа провайдераключ идемпотентности. */
68
+ /** The provider's unique payment reference the idempotency key. */
69
69
  providerRef?: string;
70
70
  email?: string;
71
- /** Исходный объект провайдера (на случай, если роуту нужны доп. поля). */
71
+ /** The raw provider object (in case the route needs extra fields). */
72
72
  raw: unknown;
73
73
  }
74
74
  interface PaymentProvider {
75
75
  name: PaymentProviderName;
76
- /** Создаёт hosted-checkout у провайдера → URL для редиректа. */
76
+ /** Creates a hosted checkout at the provider redirect URL. */
77
77
  createCheckout(args: CreateCheckoutArgs): Promise<{
78
78
  redirectUrl: string;
79
79
  }>;
80
- /** Верифицирует подпись/подлинность и нормализует событие. Бросает при невалидном. */
80
+ /** Verifies the signature/authenticity and normalizes the event. Throws if invalid. */
81
81
  verifyWebhook(req: PaymentWebhookRequest): Promise<NormalizedPaymentEvent>;
82
82
  }
83
83
 
84
84
  interface PaymentRegistry {
85
85
  register(provider: PaymentProvider): void;
86
- /** Активный провайдер по site.config.integrations.payments. */
86
+ /** The active provider by site.config.integrations.payments. */
87
87
  resolve(config: SiteConfig): PaymentProvider;
88
88
  get(name: PaymentProviderName): PaymentProvider | undefined;
89
89
  clear(): void;
90
90
  }
91
91
  declare function createPaymentRegistry(): PaymentRegistry;
92
- /** Глобальный реестр провайдеров по умолчанию. */
92
+ /** The default global provider registry. */
93
93
  declare const payments: PaymentRegistry;
94
94
 
95
95
  interface PaymentWebhookHandlers {
@@ -99,7 +99,7 @@ interface PaymentWebhookHandlers {
99
99
  interface PaymentWebhookResult {
100
100
  received: true;
101
101
  kind: NormalizedPaymentEvent['kind'];
102
- /** Был ли зарегистрирован обработчик для этого вида события. */
102
+ /** Whether a handler was registered for this event kind. */
103
103
  handled: boolean;
104
104
  }
105
105
  declare function handlePaymentWebhook(args: {
@@ -109,9 +109,9 @@ declare function handlePaymentWebhook(args: {
109
109
  }): Promise<PaymentWebhookResult>;
110
110
 
111
111
  declare function computeLineTotal(unitPrice: Money, quantity: number): Money;
112
- /** Пустая корзина. */
112
+ /** An empty cart. */
113
113
  declare function emptyCart(id: string, currency: CurrencyCode): Cart;
114
- /** Пересчитывает lineTotal каждой строки и итоги (subtotal/total с учётом скидки). */
114
+ /** Recomputes each line's lineTotal and the totals (subtotal/total incl. discount). */
115
115
  declare function recalcCart(cart: Cart): Cart;
116
116
  interface NewLineInput {
117
117
  id: string;
@@ -122,12 +122,12 @@ interface NewLineInput {
122
122
  quantity: number;
123
123
  image?: string;
124
124
  }
125
- /** Добавляет строку; если вариант уже в корзине увеличивает количество. */
125
+ /** Adds a line; if the variant is already in the cart, increases its quantity. */
126
126
  declare function addCartLine(cart: Cart, input: NewLineInput): Cart;
127
- /** Меняет количество строки; quantity ≤ 0 удаляет строку. */
127
+ /** Changes a line's quantity; quantity ≤ 0 removes the line. */
128
128
  declare function setCartLineQty(cart: Cart, lineId: string, quantity: number): Cart;
129
129
  declare function removeCartLine(cart: Cart, lineId: string): Cart;
130
- /** Суммарное число единиц в корзине (для индикатора в шапке). */
130
+ /** Total number of units in the cart (for the header indicator). */
131
131
  declare function cartItemCount(cart: Cart): number;
132
132
 
133
133
  interface BuildOrderOptions {
@@ -135,10 +135,10 @@ interface BuildOrderOptions {
135
135
  status?: OrderStatus;
136
136
  email?: string;
137
137
  number?: string;
138
- /** ISO-8601; по умолчанию сейчас. */
138
+ /** ISO-8601; defaults to now. */
139
139
  createdAt?: string;
140
140
  }
141
- /** Снимок корзины в заказ (после оплаты). Итоги берём из корзиныне пересчитываем. */
141
+ /** Snapshots the cart into an order (after payment). Totals come from the cart not recomputed. */
142
142
  declare function buildOrderFromCart(cart: Cart, opts: BuildOrderOptions): Order;
143
143
 
144
144
  declare const CORE_VERSION: "0.1.0";
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ function createAdapterRegistry() {
14
14
  function factoryFor(config) {
15
15
  const f = factories.get(config.backend);
16
16
  if (!f) {
17
- throw new Error(`[vitrine] \u043D\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D \u0430\u0434\u0430\u043F\u0442\u0435\u0440 \u0434\u043B\u044F backend "${config.backend}"`);
17
+ throw new Error(`[vitrine] no adapter registered for backend "${config.backend}"`);
18
18
  }
19
19
  return f;
20
20
  }
@@ -23,11 +23,11 @@ function createAdapterRegistry() {
23
23
  }
24
24
  function resolveCommerce(config) {
25
25
  if (config.tier === "catalog") {
26
- throw new Error('[vitrine] CommerceBackend \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u043D\u0430 \u0443\u0440\u043E\u0432\u043D\u0435 tier "catalog"');
26
+ throw new Error('[vitrine] CommerceBackend is unavailable at tier "catalog"');
27
27
  }
28
28
  const f = factoryFor(config);
29
29
  if (!f.createCommerce) {
30
- throw new Error(`[vitrine] backend "${config.backend}" \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u0443\u0435\u0442 CommerceBackend`);
30
+ throw new Error(`[vitrine] backend "${config.backend}" does not implement CommerceBackend`);
31
31
  }
32
32
  return f.createCommerce(config);
33
33
  }
@@ -66,12 +66,12 @@ function createPaymentRegistry() {
66
66
  const name = config.integrations.payments;
67
67
  if (!name) {
68
68
  throw new Error(
69
- "[vitrine] integrations.payments \u043D\u0435 \u0437\u0430\u0434\u0430\u043D \u0432 site.config \u2014 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0444\u0438\u0447\u0443 checkout-<provider>"
69
+ "[vitrine] integrations.payments is not set in site.config \u2014 install a checkout-<provider> feature"
70
70
  );
71
71
  }
72
72
  const provider = providers.get(name);
73
73
  if (!provider) {
74
- throw new Error(`[vitrine] \u043F\u043B\u0430\u0442\u0451\u0436\u043D\u044B\u0439 \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440 "${name}" \u043D\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D`);
74
+ throw new Error(`[vitrine] payment provider "${name}" is not registered`);
75
75
  }
76
76
  return provider;
77
77
  }
@@ -123,7 +123,7 @@ function recalcCart(cart) {
123
123
  }
124
124
  function addCartLine(cart, input) {
125
125
  if (!Number.isInteger(input.quantity) || input.quantity <= 0) {
126
- throw new Error(`[vitrine] \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0441\u0442\u0440\u043E\u043A\u0438: ${input.quantity} (\u043D\u0443\u0436\u043D\u043E \u0446\u0435\u043B\u043E\u0435 > 0)`);
126
+ throw new Error(`[vitrine] invalid line quantity: ${input.quantity} (must be an integer > 0)`);
127
127
  }
128
128
  const exists = cart.lines.some((l) => l.variantId === input.variantId);
129
129
  const lines = exists ? cart.lines.map(
@@ -145,7 +145,7 @@ function addCartLine(cart, input) {
145
145
  }
146
146
  function setCartLineQty(cart, lineId, quantity) {
147
147
  if (!Number.isInteger(quantity)) {
148
- throw new Error(`[vitrine] \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E: ${quantity} (\u043D\u0443\u0436\u043D\u043E \u0446\u0435\u043B\u043E\u0435)`);
148
+ throw new Error(`[vitrine] invalid quantity: ${quantity} (must be an integer)`);
149
149
  }
150
150
  if (quantity <= 0) return removeCartLine(cart, lineId);
151
151
  return recalcCart({
package/dist/react.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { ComponentType, ReactNode } from 'react';
2
2
  import { SlotId } from '@vitrine-kit/contracts';
3
- import { S as SlotRegistry } from './registry-B4Ak1hIR.js';
3
+ import { S as SlotRegistry } from './registry-CfORxf9H.js';
4
4
 
5
5
  type SlotComponentRegistry = SlotRegistry<ComponentType<Record<string, unknown>>>;
6
6
  interface SlotProps {
7
7
  name: SlotId;
8
- /** Реестр (по умолчанию — глобальный). Для тестов/изоляции можно передать свой. */
8
+ /** The registry (global by default). Pass your own for tests/isolation. */
9
9
  registry?: SlotComponentRegistry;
10
- /** Что рендерить, если слот пуст. */
10
+ /** What to render if the slot is empty. */
11
11
  fallback?: ReactNode;
12
- /** Остальные пропсы прокидываются в каждый смонтированный компонент. */
12
+ /** The remaining props are forwarded to each mounted component. */
13
13
  [prop: string]: unknown;
14
14
  }
15
15
  declare function Slot(props: SlotProps): ReactNode;
@@ -3,12 +3,12 @@ import { SlotMount, SlotId } from '@vitrine-kit/contracts';
3
3
  interface SlotRegistry<C = unknown> {
4
4
  register(mount: SlotMount<C>): void;
5
5
  registerMany(mounts: ReadonlyArray<SlotMount<C>>): void;
6
- /** Привязки слота, отсортированные по order (стабильно по порядку регистрации). */
6
+ /** A slot's bindings, sorted by order (stable by registration order). */
7
7
  get(slot: SlotId): SlotMount<C>[];
8
8
  clear(): void;
9
9
  }
10
10
  declare function createSlotRegistry<C = unknown>(): SlotRegistry<C>;
11
- /** Глобальный реестр по умолчанию (клиент регистрирует слоты в lib/slots.ts). */
11
+ /** The default global registry (the client registers slots in lib/slots.ts). */
12
12
  declare const slotRegistry: SlotRegistry;
13
13
  declare function registerSlot<C = unknown>(mount: SlotMount<C>): void;
14
14
  declare function getSlotMounts<C = unknown>(slot: SlotId): SlotMount<C>[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitrine-kit/core",
3
- "version": "0.2.0",
4
- "description": "Vitrine core — runtime слотов/адаптера, order pipeline, Stripe webhook. Критическая логика (баг = инцидент у всех).",
3
+ "version": "0.2.1",
4
+ "description": "Vitrine core — slot/adapter runtime, order pipeline, Stripe webhook. Critical logic (a bug = an incident for everyone).",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "types": "./dist/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "directory": "packages/core"
30
30
  },
31
31
  "dependencies": {
32
- "@vitrine-kit/contracts": "1.1.0"
32
+ "@vitrine-kit/contracts": "1.2.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "react": ">=18.0.0"