includio-cms 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/API.md +58 -2
  2. package/CHANGELOG.md +105 -0
  3. package/DOCS.md +1 -1
  4. package/ROADMAP.md +8 -0
  5. package/dist/admin/auth-client.d.ts +42 -42
  6. package/dist/admin/client/admin/admin-layout.svelte +12 -2
  7. package/dist/admin/client/admin/admin-layout.svelte.d.ts +2 -1
  8. package/dist/admin/client/collection/data-table.svelte +0 -39
  9. package/dist/admin/client/collection/data-table.svelte.d.ts +0 -2
  10. package/dist/admin/client/shop/coupon-schema.d.ts +1 -1
  11. package/dist/admin/client/shop/refund-dialog.svelte +37 -1
  12. package/dist/admin/client/shop/refund-dialog.svelte.d.ts +3 -0
  13. package/dist/admin/client/shop/shop-order-detail-page.svelte +192 -0
  14. package/dist/admin/components/fields/field-renderer.svelte +6 -1
  15. package/dist/admin/components/fields/icon-field.svelte +86 -0
  16. package/dist/admin/components/fields/icon-field.svelte.d.ts +8 -0
  17. package/dist/admin/components/fields/icon-picker-dialog.svelte +174 -0
  18. package/dist/admin/components/fields/icon-picker-dialog.svelte.d.ts +11 -0
  19. package/dist/admin/components/fields/object-field.svelte +27 -7
  20. package/dist/admin/components/fields/shop-field.svelte +210 -20
  21. package/dist/admin/components/layout/layout-tabs.svelte +1 -0
  22. package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte +109 -0
  23. package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte.d.ts +9 -0
  24. package/dist/admin/helpers/build-icon-set-map.d.ts +8 -0
  25. package/dist/admin/helpers/build-icon-set-map.js +16 -0
  26. package/dist/admin/helpers/index.d.ts +2 -0
  27. package/dist/admin/helpers/index.js +2 -0
  28. package/dist/admin/remote/shop.remote.d.ts +116 -24
  29. package/dist/admin/remote/shop.remote.js +79 -6
  30. package/dist/admin/state/icon-sets.svelte.d.ts +9 -0
  31. package/dist/admin/state/icon-sets.svelte.js +20 -0
  32. package/dist/cli/scaffold/admin.js +2 -2
  33. package/dist/components/ui/checkbox/checkbox.svelte +3 -3
  34. package/dist/core/cms.d.ts +11 -2
  35. package/dist/core/cms.js +29 -0
  36. package/dist/core/fields/fieldSchemaToTs.js +7 -0
  37. package/dist/core/server/generator/fields.d.ts +2 -0
  38. package/dist/core/server/generator/fields.js +34 -1
  39. package/dist/core/server/generator/generator.js +2 -1
  40. package/dist/db-postgres/schema/shop/index.d.ts +1 -0
  41. package/dist/db-postgres/schema/shop/index.js +1 -0
  42. package/dist/db-postgres/schema/shop/invoice.d.ts +254 -0
  43. package/dist/db-postgres/schema/shop/invoice.js +27 -0
  44. package/dist/db-postgres/schema/shop/order.d.ts +107 -1
  45. package/dist/db-postgres/schema/shop/order.js +7 -1
  46. package/dist/db-postgres/schema/shop/payment.d.ts +20 -0
  47. package/dist/db-postgres/schema/shop/payment.js +4 -1
  48. package/dist/db-postgres/schema/shop/product.d.ts +20 -0
  49. package/dist/db-postgres/schema/shop/product.js +3 -1
  50. package/dist/db-postgres/schema/shop/productVariant.d.ts +12 -2
  51. package/dist/db-postgres/schema/shop/productVariant.js +22 -0
  52. package/dist/paraglide/messages/_index.d.ts +36 -3
  53. package/dist/paraglide/messages/_index.js +71 -3
  54. package/dist/paraglide/messages/en.d.ts +5 -0
  55. package/dist/paraglide/messages/en.js +14 -0
  56. package/dist/paraglide/messages/pl.d.ts +5 -0
  57. package/dist/paraglide/messages/pl.js +14 -0
  58. package/dist/shop/adapters/fakturownia/client.d.ts +28 -0
  59. package/dist/shop/adapters/fakturownia/client.js +67 -0
  60. package/dist/shop/adapters/fakturownia/index.d.ts +27 -0
  61. package/dist/shop/adapters/fakturownia/index.js +36 -0
  62. package/dist/shop/adapters/fakturownia/payload.d.ts +35 -0
  63. package/dist/shop/adapters/fakturownia/payload.js +45 -0
  64. package/dist/shop/cart/types.d.ts +1 -0
  65. package/dist/shop/client/index.d.ts +61 -0
  66. package/dist/shop/client/index.js +5 -1
  67. package/dist/shop/expiry.d.ts +35 -0
  68. package/dist/shop/expiry.js +68 -0
  69. package/dist/shop/http/balance-handler.d.ts +20 -0
  70. package/dist/shop/http/balance-handler.js +91 -0
  71. package/dist/shop/http/cart-handler.js +19 -0
  72. package/dist/shop/http/checkout-handler.js +30 -1
  73. package/dist/shop/http/index.d.ts +2 -0
  74. package/dist/shop/http/index.js +2 -0
  75. package/dist/shop/http/upcoming-handler.d.ts +16 -0
  76. package/dist/shop/http/upcoming-handler.js +65 -0
  77. package/dist/shop/http/webhook-handler.js +46 -9
  78. package/dist/shop/index.d.ts +7 -1
  79. package/dist/shop/index.js +10 -1
  80. package/dist/shop/nip.d.ts +12 -0
  81. package/dist/shop/nip.js +23 -0
  82. package/dist/shop/server/balance-payment.d.ts +40 -0
  83. package/dist/shop/server/balance-payment.js +140 -0
  84. package/dist/shop/server/cart-hydrate.js +2 -0
  85. package/dist/shop/server/init.d.ts +14 -0
  86. package/dist/shop/server/init.js +35 -0
  87. package/dist/shop/server/invoices.d.ts +64 -0
  88. package/dist/shop/server/invoices.js +237 -0
  89. package/dist/shop/server/orders.d.ts +38 -0
  90. package/dist/shop/server/orders.js +152 -2
  91. package/dist/shop/server/payment-policy.d.ts +35 -0
  92. package/dist/shop/server/payment-policy.js +55 -0
  93. package/dist/shop/server/payments.d.ts +29 -0
  94. package/dist/shop/server/payments.js +64 -0
  95. package/dist/shop/server/populate.d.ts +1 -1
  96. package/dist/shop/server/refund.d.ts +17 -12
  97. package/dist/shop/server/refund.js +96 -13
  98. package/dist/shop/server/shop-data.d.ts +4 -1
  99. package/dist/shop/server/shop-data.js +24 -2
  100. package/dist/shop/template.d.ts +13 -0
  101. package/dist/shop/template.js +98 -0
  102. package/dist/shop/types.d.ts +208 -1
  103. package/dist/shop/variant-attributes.d.ts +28 -0
  104. package/dist/shop/variant-attributes.js +69 -0
  105. package/dist/sveltekit/server/index.d.ts +1 -0
  106. package/dist/sveltekit/server/index.js +2 -0
  107. package/dist/types/cms.d.ts +4 -3
  108. package/dist/types/cms.schema.d.ts +1 -1
  109. package/dist/types/cms.schema.js +9 -0
  110. package/dist/types/fields.d.ts +21 -2
  111. package/dist/types/index.d.ts +1 -1
  112. package/dist/types/index.js +1 -1
  113. package/dist/types/plugins.d.ts +40 -0
  114. package/dist/types/plugins.js +4 -1
  115. package/dist/updates/0.26.1/index.d.ts +2 -0
  116. package/dist/updates/0.26.1/index.js +19 -0
  117. package/dist/updates/0.27.0/index.d.ts +2 -0
  118. package/dist/updates/0.27.0/index.js +50 -0
  119. package/dist/updates/0.28.0/index.d.ts +2 -0
  120. package/dist/updates/0.28.0/index.js +38 -0
  121. package/dist/updates/index.js +7 -1
  122. package/package.json +1 -1
  123. package/dist/paraglide/messages/hello_world.d.ts +0 -5
  124. package/dist/paraglide/messages/hello_world.js +0 -33
  125. package/dist/paraglide/messages/login_hello.d.ts +0 -16
  126. package/dist/paraglide/messages/login_hello.js +0 -34
  127. package/dist/paraglide/messages/login_please_login.d.ts +0 -16
  128. package/dist/paraglide/messages/login_please_login.js +0 -34
package/API.md CHANGED
@@ -1,8 +1,8 @@
1
- # includio-cms — Public API v0.26.0
1
+ # includio-cms — Public API v0.28.0
2
2
 
3
3
  > Auto-generated by `scripts/generate-api-md.ts`. Do not edit by hand.
4
4
 
5
- Entry points: **18** · Stable: **413** · Experimental: **2**
5
+ Entry points: **18** · Stable: **464** · Experimental: **4**
6
6
 
7
7
  Tags:
8
8
  - `@public` — frozen for v1.0; semver-protected.
@@ -75,10 +75,14 @@ Tags:
75
75
  - `interface FormSubmission`
76
76
  - `interface FormTextareaField`
77
77
  - `interface FormTextField`
78
+ - `interface IconDefinition`
79
+ - `interface IconField`
78
80
  - `type IconName = keyof typeof iconMap`
81
+ - `interface IconSetPlugin`
79
82
  - `interface ImageFieldData`
80
83
  - `interface ImageFieldStyle`
81
84
  - `interface ImageStyle`
85
+ - `isIconSetPlugin(p: Plugin): p is IconSetPlugin` — Type guard for {@link IconSetPlugin}.
82
86
  - `type Language = 'en' | 'pl'`
83
87
  - `type Layout = LayoutPreset | LayoutNode[]`
84
88
  - `type LayoutNode = | SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode | TabsNode | TabNode`
@@ -93,6 +97,7 @@ Tags:
93
97
  - `interface NumberField`
94
98
  - `interface ObjectField`
95
99
  - `type ObjectFieldData = { _id?: string; _slug?: string; } & Record<string, unknown>`
100
+ - `type Plugin = PluginConfig | IconSetPlugin`
96
101
  - `interface RadioField`
97
102
  - `interface RelationField`
98
103
  - `type RelationFieldData = string | string[]`
@@ -132,6 +137,7 @@ Tags:
132
137
  - `const AdminLayout: LegacyComponentType`
133
138
  - `const Badge: LegacyComponentType`
134
139
  - `buildCustomFieldsMap(...plugins: PluginConfig[]): Map<string, CustomFieldDefinition>` — Build a Map<fieldType, CustomFieldDefinition> from plugin configs.
140
+ - `buildIconSetMap(...plugins: IconSetPlugin[]): Map<string, IconSetPlugin>` — Build a Map<slug, IconSetPlugin> from icon-set plugin instances.
135
141
  - `const Button: LegacyComponentType`
136
142
  - `Card`
137
143
  - `const CollectionPage: LegacyComponentType`
@@ -143,6 +149,7 @@ Tags:
143
149
  - `const FormSubmissionPage: LegacyComponentType`
144
150
  - `getContentLanguage`
145
151
  - `getCustomFields(): Map<string, CustomFieldDefinition>`
152
+ - `getIconSets(): Map<string, IconSetPlugin>`
146
153
  - `getLocalizedLabel(label: Localized | undefined, lang: InterfaceLanguage): string`
147
154
  - `getRemotes(): typeof remotes`
148
155
  - `const Input: LegacyComponentType`
@@ -152,6 +159,7 @@ Tags:
152
159
  - `const MediaPage: LegacyComponentType`
153
160
  - `const MediaSelector: LegacyComponentType`
154
161
  - `const ResetPasswordPage: LegacyComponentType`
162
+ - `resolveIconSet(slug?: string): IconSetPlugin | null` — Resolve a single icon set: explicit `slug` (from {@link IconField.set}) takes
155
163
  - `const Separator: LegacyComponentType`
156
164
  - `const ShippingMethodEditPage: LegacyComponentType`
157
165
  - `const ShippingMethodNewPage: LegacyComponentType`
@@ -193,6 +201,7 @@ Tags:
193
201
  - `const exportOrdersCsv: <inferred>`
194
202
  - `const findMediaReferences: <inferred>`
195
203
  - `const generateAltText: <inferred>`
204
+ - `const generateBalanceLinkForOrder: <inferred>`
196
205
  - `const getAltOverview: <inferred>`
197
206
  - `const getCollection: <inferred>`
198
207
  - `const getCollections: <inferred>`
@@ -214,6 +223,7 @@ Tags:
214
223
  - `const getMediaTags: <inferred>`
215
224
  - `const getMediaTagsWithCounts: <inferred>`
216
225
  - `const getOrderForAdmin: <inferred>`
226
+ - `const getOrderInvoiceAdmin: <inferred>`
217
227
  - `const getOrderRefundsAdmin: <inferred>`
218
228
  - `const getRawEntries: <inferred>`
219
229
  - `const getRawEntry: <inferred>`
@@ -227,6 +237,7 @@ Tags:
227
237
  - `const getSingles: <inferred>`
228
238
  - `const getSubmissionsOverview: <inferred>`
229
239
  - `const isAIAvailable: <inferred>`
240
+ - `const issueInvoiceCmd: <inferred>`
230
241
  - `const listCouponsAdmin: <inferred>`
231
242
  - `const listOrdersAdmin: <inferred>`
232
243
  - `const listShippingMethodsAdmin: <inferred>`
@@ -289,6 +300,7 @@ Tags:
289
300
  - `cmsLayoutLoad(event: RequestEvent): <inferred>` — Returns `cmsContext` from `event.locals` for use in a SvelteKit layout
290
301
  - `countEntries(opts: CountEntriesOptions): Promise<number>` — Count entries matching the same filters as `resolveEntries`, without
291
302
  - `type CountEntriesOptions = Omit< ResolveEntriesOptions, 'limit' | 'offset' | 'populate' | 'orderBy' | 'dataOrderBy' >`
303
+ - `createAdminApiHandler(options?: AdminApiOptions): <inferred>`
292
304
  - `const createConsentLog: <inferred>`
293
305
  - `const createFormSubmission: <inferred>`
294
306
  - `createRestApiHandler(): <inferred>` — REST API handler factory. Returns `{ GET, POST, PUT, DELETE }`
@@ -327,9 +339,13 @@ Tags:
327
339
  - `const shopCouponRedemptionsTable: <inferred>`
328
340
  - `const shopCouponsTable: <inferred>`
329
341
  - `type ShopCouponType = 'percent' | 'fixed'`
342
+ - `const shopInvoicesTable: <inferred>`
343
+ - `type ShopInvoiceStatus = 'pending' | 'issued' | 'sent' | 'failed'`
330
344
  - `const shopOrderItemsTable: <inferred>`
331
345
  - `const shopOrdersTable: <inferred>`
332
346
  - `const shopOrderStatusHistoryTable: <inferred>`
347
+ - `type ShopPaymentKind = 'full' | 'deposit' | 'balance'`
348
+ - `const shopPaymentKindEnum: <inferred>`
333
349
  - `const shopPaymentsTable: <inferred>`
334
350
  - `type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled'`
335
351
  - `const shopProductsTable: <inferred>`
@@ -365,9 +381,13 @@ Tags:
365
381
  - `const shopCouponRedemptionsTable: <inferred>`
366
382
  - `const shopCouponsTable: <inferred>`
367
383
  - `type ShopCouponType = 'percent' | 'fixed'`
384
+ - `const shopInvoicesTable: <inferred>`
385
+ - `type ShopInvoiceStatus = 'pending' | 'issued' | 'sent' | 'failed'`
368
386
  - `const shopOrderItemsTable: <inferred>`
369
387
  - `const shopOrdersTable: <inferred>`
370
388
  - `const shopOrderStatusHistoryTable: <inferred>`
389
+ - `type ShopPaymentKind = 'full' | 'deposit' | 'balance'`
390
+ - `const shopPaymentKindEnum: <inferred>`
371
391
  - `const shopPaymentsTable: <inferred>`
372
392
  - `type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled'`
373
393
  - `const shopProductsTable: <inferred>`
@@ -397,19 +417,36 @@ Tags:
397
417
  - `interface CouponRef`
398
418
  - `type Currency = 'PLN'`
399
419
  - `defineShop(config: ShopConfig): ResolvedShopConfig`
420
+ - `type DepositAmount = { type: 'percent'; value: number } | { type: 'amount'; value: number }` — Deposit amount specifier. `percent` charges `floor(base * value / 100)` of
421
+ - `fakturowniaAdapter(opts: FakturowniaAdapterOptions): InvoicingAdapter` — Invoicing adapter backed by Fakturownia (fakturownia.pl). Issues a paid VAT
422
+ - `interface FakturowniaAdapterOptions`
423
+ - `filterUpcoming(variants: T[], config: VariantExpiryConfig | null, now?: Date): T[]` — Return the subset of `variants` that have not yet expired. Order is
400
424
  - `type GeowidgetConfigPreset = 'parcelcollect' | 'parcelsend' | 'parcelcollect247' | string`
401
425
  - `type I18nText = { [lang: string]: string; }`
402
426
  - `inpostAdapter(opts: InpostAdapterOptions): CarrierAdapter`
403
427
  - `interface InpostAdapterOptions`
404
428
  - `type InpostEnvironment = 'production' | 'sandbox'` — InPost Points API — public, no auth required. Used to validate that a parcel
405
429
  - `interface InpostSenderAddress`
430
+ - `interpolateTemplate(template: string, vars: Record<string, unknown>, locale: string): string` — String interpolation engine used by `defineShop({ variantLabel.template })`
431
+ - `class InvalidVariantAttributesError`
432
+ - `interface InvoiceBuyer`
433
+ - `interface InvoiceContext`
434
+ - `interface InvoiceCreateResult`
435
+ - `type InvoiceIssuePolicy = 'b2bAndOnRequest' | 'always'` — When an invoice should be issued automatically after an order is fully paid.
436
+ - `interface InvoiceLineItem`
437
+ - `interface InvoicePayload`
438
+ - `interface InvoicingAdapter` — Adapter that issues invoices with an external provider (e.g. Fakturownia).
439
+ - `isValidNip(nip: string): boolean` — Validate a Polish NIP (tax id) — 10 digits with a weighted checksum.
440
+ - `isVariantExpired(variant: VariantLike, config: VariantExpiryConfig | null, now: Date = new Date(Date.now())): boolean` — Check whether a variant has expired under the given config. Fail-open by
406
441
  - `manualAdapter(opts: ManualPaymentAdapterOptions = {}): PaymentAdapter` — Manual payment adapter — order goes to awaitingPayment, admin marks as paid later
407
442
  - `interface OrderRef`
408
443
  - `type OrderStatus = | 'new' | 'awaitingPayment' | 'paid' | 'preparing' | 'sent' | 'done' | 'cancelled' | 'paymentReje...`
444
+ - `interface PartialPayment` — Persisted partial-payment summary on `order.partialPayment` when the order
409
445
  - `interface PaymentAdapter`
410
446
  - `interface PaymentCreateContext`
411
447
  - `interface PaymentCreateResult`
412
448
  - `interface PaymentEvent`
449
+ - `type PaymentPolicy = { type: 'full' } | { type: 'deposit'; depositAmount: DepositAmount }` — Per-product payment policy. `full` (default) charges the full order total
413
450
  - `interface PaymentRefundInput`
414
451
  - `interface PaymentRefundResult`
415
452
  - `payuAdapter(opts: PayuAdapterOptions): PaymentAdapter`
@@ -422,6 +459,18 @@ Tags:
422
459
  - `interface ShopFeatures`
423
460
  - `stripeAdapter(opts: StripeAdapterOptions): PaymentAdapter` — Stripe payment adapter (Checkout Session flow).
424
461
  - `interface StripeAdapterOptions`
462
+ - `type VariantAttribute = | VariantAttributeText | VariantAttributeNumber | VariantAttributeDatetime | VariantAttributeSele...` — Schema descriptor for one product-variant attribute (city, startsAt, …).
463
+ - `interface VariantAttributeBoolean`
464
+ - `interface VariantAttributeDatetime`
465
+ - `interface VariantAttributeEntry`
466
+ - `interface VariantAttributeImage`
467
+ - `interface VariantAttributeNumber`
468
+ - `interface VariantAttributeSelect`
469
+ - `interface VariantAttributeSlug`
470
+ - `interface VariantAttributeText`
471
+ - `class VariantExpiredError` — Thrown by `createOrderFromCart` / cart-add HTTP guard when a referenced
472
+ - `interface VariantExpiryConfig` — Opt-in storefront filter that hides variants whose datetime attribute
473
+ - `interface VariantLabelConfig` — Template used to auto-generate `variant.name` from `variantAttributes`.
425
474
 
426
475
  ### `includio-cms/shop/client`
427
476
 
@@ -440,11 +489,13 @@ Tags:
440
489
  - `type OrderState = OrderStateImpl`
441
490
  - `const OrderStatus: LegacyComponentType`
442
491
  - `interface OrderStatusLabels`
492
+ - `interface PayBalanceResult` — Result of `orders.payBalance` — initiates a payment session for the
443
493
  - `interface RefreshPaymentResult`
444
494
  - `interface RetryPaymentResult`
445
495
  - `interface ShippingMethodPublic`
446
496
  - `interface ShopClient` — Headless shop SDK surface returned by `createShopClient()`.
447
497
  - `interface ShopClientOptions` — Options for `createShopClient()`.
498
+ - `interface VariantPublic` — Public-facing variant row returned by `client.products.listUpcoming`.
448
499
 
449
500
  ### `includio-cms/shop/http`
450
501
 
@@ -484,3 +535,8 @@ Tags:
484
535
 
485
536
  - `interface CustomFieldDefinition` — Defines a custom field type contributed by a plugin.
486
537
  - `interface PluginConfig` — CMS plugin configuration — register custom field types and CRUD lifecycle hooks.
538
+
539
+ ### `includio-cms/shop/http`
540
+
541
+ - `createBalanceHandler(): { GET: RequestHandler; POST: RequestHandler }`
542
+ - `createUpcomingVariantsHandler(): { GET: RequestHandler }` — Build a SvelteKit `GET` handler for upcoming variants of a single product.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,111 @@
3
3
  All notable changes to includio-cms are documented here.
4
4
  Generated from `src/lib/updates/` — do not edit manually.
5
5
 
6
+ ## 0.28.0 — 2026-06-01
7
+
8
+ Fakturowanie — integracja sklepu z Fakturownią: automatyczne wystawianie i wysyłka faktury po opłaceniu zamówienia. Nowy generyczny `InvoicingAdapter` (spójny z payment/carrier) + `fakturowniaAdapter()` jako pierwsza implementacja. Faktura wystawiana fire-and-forget gdy zamówienie jest w pełni opłacone (`!balanceOwed` — zaliczki czekają na dopłatę balansu), wysyłana przez Fakturownię (`send_by_email`). Trigger konfigurowalny per-adapter (`issueWhen`: `b2bAndOnRequest` domyślnie / `always`). Checkout zbiera dane B2B (NIP z twardą walidacją sumy kontrolnej, nazwa firmy, adres do faktury, opt-in „chcę fakturę"). Idempotencja przez `shop_invoices` (unikat per zamówienie); ręczny retry w adminie. Additive only — żadnych breaking zmian.
9
+
10
+ ### Added
11
+ - `defineShop({ invoicing })` (`includio-cms/shop`) — nowy opcjonalny slot adaptera fakturowania, analogiczny do `payment` / `carriers`. `InvoicingAdapter { id, issueWhen?, createInvoice(payload, ctx), send?(externalId, ctx) }` + typy payloadu (`InvoicePayload`, `InvoiceBuyer`, `InvoiceLineItem`, `InvoiceCreateResult`, `InvoiceContext`, `InvoiceIssuePolicy`) wyeksportowane jako `@public` z `includio-cms/shop`.
12
+ - `fakturowniaAdapter({ domain, apiToken, kind?, issueWhen?, sendEmail? })` (`includio-cms/shop`, `@public`) — adapter dla Fakturowni (fakturownia.pl). `createInvoice` mapuje zamówienie na fakturę VAT oznaczoną jako opłacona (`paid_date` = data potwierdzenia płatności), `send` woła `send_by_email` (domyślnie włączone). Numeracja i dane sprzedawcy zarządzane po stronie konta Fakturowni. Sekret `apiToken` przekazywany przez konsumenta z `$env/dynamic/private` (jak `STRIPE_SECRET_KEY`).
13
+ - Auto-faktura po opłaceniu — `maybeIssueInvoiceForOrder(orderId)` (`$lib/shop/server/invoices.ts`) wołane fire-and-forget z `updateOrderStatus` (przy `paid`) oraz z `markBalancePaid` (po dopłacie balansu). Fail-open: błąd providera nie blokuje webhooka płatności. Guard wystawia fakturę tylko gdy zamówienie w pełni opłacone (`status ∈ {paid, preparing, sent, done}` && `!balanceOwed`) — deposit czeka na dopłatę.
14
+ - Konfigurowalny trigger `issueWhen`: `b2bAndOnRequest` (domyślny — faktura gdy podano NIP lub zaznaczono „chcę fakturę") albo `always` (każde opłacone zamówienie, np. dla klienta wymagającego faktur również dla osób fizycznych).
15
+ - `shop_invoices` (nowa tabela) — jedna faktura per zamówienie (`order_id` UNIQUE → idempotencja). Pola `status` (`pending`/`issued`/`sent`/`failed`), `external_id`, `number`, `pdf_url`, `attempts`, `next_retry_at`, `last_error`, `raw`. Kolumny `attempts`/`next_retry_at` zarezerwowane pod przyszły automatyczny retry (obecnie tylko ręczny).
16
+ - Checkout B2B — `shop_orders` dostaje kolumny `customer_nip`, `customer_company_name`, `billing_address` (jsonb), `invoice_requested` (boolean). `createOrderFromCart` / `checkout-handler` przyjmują i zapisują te pola; `CheckoutInput` (`includio-cms/shop/client`) rozszerzony. Storefront form (pola NIP/firma/checkbox/adres) = warstwa konsumenta.
17
+ - `isValidNip(nip)` (`includio-cms/shop`, `@public`) — twarda walidacja polskiego NIP (10 cyfr + suma kontrolna, wagi `[6,5,7,2,3,4,5,6,7]`). Checkout odrzuca nieprawidłowy NIP (400) zanim trafi do bazy — Fakturownia odrzuciłaby błędny NIP, a faktura idzie dalej do KSeF, więc walidujemy u źródła.
18
+ - `getOrderInvoiceAdmin` (query) + `issueInvoiceCmd` (command) — admin remote functions (`includio-cms/admin/remote`). `shop-order-detail-page.svelte` zyskuje sekcję „Faktura": numer, link do PDF, status, przycisk „Wystaw fakturę" / „Wystaw ponownie" (ręczny retry, `force`). Auth-protected (`requireAuth`).
19
+
20
+ ### Migration
21
+
22
+ ```sql
23
+ CREATE TABLE IF NOT EXISTS shop_invoices (
24
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
25
+ order_id uuid NOT NULL UNIQUE REFERENCES shop_orders(id) ON DELETE CASCADE,
26
+ provider text NOT NULL,
27
+ external_id text,
28
+ number text,
29
+ pdf_url text,
30
+ kind text NOT NULL DEFAULT 'vat',
31
+ status text NOT NULL DEFAULT 'pending',
32
+ attempts integer NOT NULL DEFAULT 0,
33
+ next_retry_at timestamptz,
34
+ last_error text,
35
+ raw jsonb,
36
+ created_at timestamptz NOT NULL DEFAULT now(),
37
+ updated_at timestamptz NOT NULL DEFAULT now()
38
+ );
39
+
40
+ ALTER TABLE shop_orders ADD COLUMN IF NOT EXISTS customer_nip text;
41
+ ALTER TABLE shop_orders ADD COLUMN IF NOT EXISTS customer_company_name text;
42
+ ALTER TABLE shop_orders ADD COLUMN IF NOT EXISTS billing_address jsonb;
43
+ ALTER TABLE shop_orders ADD COLUMN IF NOT EXISTS invoice_requested boolean NOT NULL DEFAULT false;
44
+ ```
45
+
46
+ ## 0.27.0 — 2026-05-29
47
+
48
+ Shop platformowy — Fazy 1 + 2 + 3 + 4 + 5: schema-driven `variantAttributes` (typed `defineShop` schema, Zod walidacja, GIN index helper, ts-gen typed `variant.attributes`) + admin renderer per attribute type + `variantLabel.template` interpolacja z admin auto-prefill nazwy wariantu + `variantExpiry` opt-in (storefront filter, cart/checkout guard, admin "Zakończony" badge) + `paymentPolicy` A-lite (deposit + balance + signed token + refund per kind + admin balance link + per-kind refund dialog). Faza 6 envet pilot (consumer-side end-to-end QA: szkolenia variants + deposit flow + balance link — nie wymaga zmian w core). Post-Faza-5 hot-fixy uwzględnione w tym wydaniu (single release, nie patch): datetime walidator z offsetem, auto-detect deposit kind przy admin manual mark-paid, admin paymentPolicy UI + preserve-on-undefined w upsert. Additive only — żadnych breaking zmian. Plan: `/Users/patryk/.claude/plans/implementacja-ariacms-0-27-partitioned-kahn.md`.
49
+
50
+ ### Added
51
+ - `defineShop({ variantAttributes })` (`includio-cms/shop`) — typed schema dla atrybutów wariantu: `text | number | datetime | select | boolean | image | entry | slug` z polami `{ type, label, required?, indexable?, options?, entryCollection? }`. Zostaje jedno źródło prawdy: napędza Zod walidację, ts-gen typings, GIN index utility oraz renderer admin form.
52
+ - `VariantAttribute` + per-type interfejsy (`VariantAttributeText/Number/Datetime/Select/Boolean/Image/Entry/Slug`) wyeksportowane jako `@public` z `includio-cms/shop`.
53
+ - `InvalidVariantAttributesError` (code `INVALID_VARIANT_ATTRIBUTES`) — rzucany przez `upsertShopData` gdy `variant.attributes` nie pasują do schemy. Eksport publiczny z `includio-cms/shop`.
54
+ - `runtime/types.ts` — pole `shop` w entry typings generuje teraz typed `variant.attributes` (`{ city: string; startsAt: string; online?: boolean; level: 'basic' | 'advanced' }`) zamiast `Record<string, string>` gdy `defineShop` ma `variantAttributes`. Brak `variantAttributes` = poprzednie `Record<string, string> | null` (backwards-compatible).
55
+ - `createVariantAttributeIndexes(attrs)` w `$lib/db-postgres/schema/shop/productVariant.ts` — zwraca `CREATE INDEX IF NOT EXISTS shop_variant_attr_<key>_gin_idx ON shop_product_variants USING gin ((attributes->'<key>'))` DDL per atrybut z `indexable: true`. Wymusza safe SQL identifier dla klucza (`[A-Za-z][A-Za-z0-9_]*`).
56
+ - `applyVariantAttributeIndexes(shop, db)` w `$lib/shop/server/init.ts` — idempotentny serialized applier indeksów GIN. `initCMS()` odpala go automatycznie fire-and-forget gdy shop jest skonfigurowany (zero ręcznych hooków u konsumenta). `cms.shopInitPromise` wystawiony jako `@internal` punkt synchronizacji dla testów.
57
+ - `VariantAttributeRenderer.svelte` (NEW, `$lib/admin/components/variant-form/`) — switch po `attr.type`, deleguje do field components z `$lib/admin/components/fields/` (text/number/datetime/select/boolean) lub renderuje prosty Input dla slug/image/entry (pełny picker UI dla image/entry defer post-1.0).
58
+ - `shop-field.svelte` (admin variant editor) — variant row pokazuje siatkę atrybutów (responsywna 1/2-col) ponad legacy polami (nazwa/SKU/delta/stock) gdy `shopConfig.variantAttributes` ma wpisy. Brak attrs = legacy behavior bez zmian. Hydratacja + save propaguje `variant.attributes` jako `Record<string, unknown>`.
59
+ - `getShopConfig` remote (admin) — response zawiera teraz `variantAttributes` z `ResolvedShopConfig`, dzięki czemu `shop-field` może lokalnie renderować typed atrybuty bez dodatkowego round-tripa.
60
+ - `upsertShopDataForEntry` (admin remote command) — input schema dla `variant.attributes` zluzowany do `z.record(z.string(), z.unknown())`; typed shape egzekwowany serwerowo przez `validateVariantAttributes` (jedno źródło prawdy).
61
+ - `defineShop({ variantLabel: { template } })` (`includio-cms/shop`) — opcjonalny szablon nazwy wariantu w składni `{key|filter:arg}`. Filtry: `date` (long/medium/short), `currency` (kod waluty, domyślnie PLN), `uppercase`. Nieznany klucz → pusty string + dev warn; nieznany filtr → passthrough; malformed template → surowy template + warn.
62
+ - `interpolateTemplate(template, vars, locale)` (`includio-cms/shop`, `@public`) — silnik interpolacji wykorzystywany wewnętrznie przez admin do pre-fill `variant.name`, dostępny też publicznie dla konsumentów (np. storefront-side derived labels).
63
+ - `VariantLabelConfig` eksportowany jako `@public` typ z `includio-cms/shop`.
64
+ - `getShopConfig` remote response zawiera teraz `variantLabel: shop.variantLabel ?? null`.
65
+ - `shop-field.svelte` (admin variant editor) — gdy `variantLabel.template` zdefiniowany, pole `Nazwa` auto-wypełnia się z interpolacji `variantAttributes` (locale `pl` w 0.27; multi-locale defer post-1.0). Per-variant dirty flag: po hydratacji z niepustym `name` lock = aktywny (nie nadpisujemy editor decision); ręczna edycja w polu `Nazwa` (`oninput`) trwale wyłącza pre-fill dla wariantu w bieżącej sesji.
66
+ - `defineShop({ variantExpiry: { source, offsetDays } })` (`includio-cms/shop`, `@public`) — opt-in filtr wariantów time-bound (events, courses, szkolenia). `source` = klucz atrybutu typu `datetime`; `offsetDays` przesuwa cut-off (`0` = expire dokładnie gdy datetime hits now, `1` = jeden dzień grace, `-1` = jeden dzień przed). Globalny config — brak per-product override.
67
+ - `isVariantExpired(variant, config, now?)` + `filterUpcoming(variants, config, now?)` (`includio-cms/shop`, `@public`) — fail-open helpers: `null` config / brak source attribute / non-string / malformed datetime → variant traktowany jako upcoming (z `console.warn` dla malformed w dev). `filterUpcoming` zachowuje order; sort source-asc realizowany na poziomie HTTP / admin osobno.
68
+ - `VariantExpiredError` (code `VARIANT_EXPIRED`, `variantId`) — eksport `@public`. Rzucany przez `createOrderFromCart` w `server/orders.ts` przed stock reservation (idempotent guard).
69
+ - `POST /api/shop/cart` (add) — preflight `VARIANT_EXPIRED` guard: kiedy `variantExpiry` jest skonfigurowany i variant ma expired source attribute, response 400 JSON `{ error: "VARIANT_EXPIRED", variantId }` bez aktualizacji cart cookie.
70
+ - `createUpcomingVariantsHandler` (`includio-cms/shop/http`, `@experimental`) — nowy GET endpoint `/api/shop/products/[id]/variants/upcoming`. Zwraca `{ items: VariantPublic[] }` przefiltrowanych przez `filterUpcoming` + posortowanych ascendingly po `attributes.<source>` (Date.parse) gdy `variantExpiry` ustawiony, w insertion order gdy brak.
71
+ - `client.products.listUpcoming(productId)` + `VariantPublic` (`includio-cms/shop/client`, `@public`) — nowy namespace SDK. Zwraca upcoming variants per produkt; zero-config passthrough kiedy `variantExpiry` nieustawiony.
72
+ - `getShopConfig` remote (admin) — response zawiera teraz `variantExpiry: shop.variantExpiry ?? null`.
73
+ - `shop-field.svelte` (admin variant editor) — gdy `variantExpiry` skonfigurowany: per-variant badge "Zakończony" (greyed-out, `bg-muted text-muted-foreground` z border), checkbox filter "Pokaż zakończone (N)" w toolbarze wariantów (default off, ukryty gdy zero expired), opacity-60 na expired row, sort wariantów po source ASC (closer terms first). Brak config = zero zmian w UI.
74
+ - `PaymentPolicy` + `DepositAmount` + `PartialPayment` (`includio-cms/shop`, `@public`) — per-product policy `{ type: "full" } | { type: "deposit", depositAmount: { type: "percent" | "amount", value } }` ustawiana w `ShopFieldData.paymentPolicy`. Cart deposit-aware: order zachowuje pełen `totalGross`, `partialPayment.balanceAmount` = co zostaje do dopłaty, `balanceOwed = true` po zapłaconym depozycie. Walidacja: percent w (0, 100], amount = positive integer (minor units). `validatePaymentPolicy` wymusza to przy upsert produktu.
75
+ - `resolvePaymentAmount(policy, lineGross)` + `computeDepositAmount(spec, base)` (`$lib/shop/server/payment-policy.ts`, server-internal — nie eksportowane z publicznego entry pointu) — silnik resolver per linia. `percent` flooruje `base * value / 100`; `amount` klampuje do `base`. Null / `full` policy → pełen `lineGross`, `kind = "full"`, balance 0. 15 spec testów + 10 integration.
76
+ - `MixedPaymentPolicyError` (code `MIXED_PAYMENT_POLICY`) — `createOrderFromCart` odrzuca cart z więcej niż jednym produktem gdy którykolwiek z nich ma deposit policy. Decyzja: deposit orders span ONE product (refund-per-kind + balance link unambiguous). Cart all-`full` mixed-product nadal działa.
77
+ - `shop_orders.partial_payment jsonb + balance_owed boolean` — nowe kolumny. `shop_payments.kind enum ("full" | "deposit" | "balance")` z default `"full"` — back-compat dla istniejących płatności. `shop_products.payment_policy jsonb` przechowuje per-product policy.
78
+ - `shop_payments` zaczyna być aktywnie wypełniane: `checkout-handler` po `adapter.createPayment` insert payment row z odpowiednim `kind` (full lub deposit) + `providerRef`. Webhook handler matchuje (provider, providerRef) → branchuje per kind: `full`/`deposit` przepuszcza `updateOrderStatus(paid, paymentKind)`, `balance` bypasses status flow i woła `markBalancePaid` (stock przy depozycie już permanentnie potwierdzony).
79
+ - `createOrderFromCart` CreateOrderResult: nowe pola `amountToPay` (deposit-aware kwota do pobrania na checkout) + `paymentKind` (`"full" | "deposit"`). `checkout-handler` przekazuje `amountToPay` do adaptera przez OrderRef.totalGross override — adaptery PayU/Stripe/manual działają bez zmian.
80
+ - `generateBalanceToken` + `verifyBalanceToken` (`includio-cms/shop/server`, `@internal`) — HMAC-SHA256 nad JSON payload `{orderId, type: "balance"}`, encoding `base64url(payload).base64url(sig)`. Deterministic per (orderId, secret) — brak rotation, brak exp, server-side invalidation przez `order.balanceOwed === true`. Secret = `INCLUDIO_BALANCE_TOKEN_SECRET` env (≥16 chars, hard-fail przy brak gdy deposit policy aktywne). 8 spec testów (roundtrip, tampered, wrong orderId/secret, malformed, deterministic).
81
+ - `createBalanceSession(orderNumber, token, ctx?)` (`includio-cms/shop/server`, `@experimental`) — customer flow: verify token + `balanceOwed`, reuse `order.paymentMethod` adapter, call `adapter.createPayment` z `amount = partialPayment.balanceAmount`, insert payment row `kind: "balance"`, mirror providerRef na order. `markBalancePaid` (idempotent) clears balanceOwed + bumps `paidAmount` do `totalGross`.
82
+ - `createBalanceHandler` (`includio-cms/shop/http`, `@experimental`) — GET `/api/shop/orders/[number]/balance?token=...` zwraca minimalny widok ({orderNumber, currency, totalGross, amountToPay, paidAmount, paymentMethod, language}); POST inicjuje payment session ({status, redirectUrl, requiresPaymentRedirect}). 403 przy złym tokenie lub wyczyszczonym `balanceOwed`.
83
+ - `client.orders.payBalance(orderNumber, token)` + `PayBalanceResult` (`includio-cms/shop/client`, `@public` / `@experimental`) — REST wrapper dla customer flow dopłaty.
84
+ - `refundOrder({ kind?, releaseStock?, ... })` (`includio-cms/shop/server`) — per-kind routing. `kind: "deposit" | "balance" | "full"` matchuje konkretny payment row; kwota cap = `row.amount - prior refunds`. Domyślnie `kind` = `"full"` z heurystyką: pojedynczy paid row → użyj go, multi-row → wybierz `full`, brak rows → legacy fallback do `order.paymentProviderRef`. Refund row link do `paymentId` dla per-row audit. `getCollectedAmount` decyduje o transition do `refunded` (sum paid rows lub `totalGross` dla legacy). `releaseStock: true` (opt-in) reinkrementuje variant.stock per order item. 6 integration spec.
85
+ - `refundOrderCmd` (admin remote) dostaje `kind` + `releaseStock` w schemacie input. `refund-dialog.svelte` — radio "Która płatność?" (deposit/balance) widoczne gdy `hasPartial`, balance radio disabled gdy `balanceOwed=true` (nic do refund), checkbox "Zwolnij stan magazynowy".
86
+ - `generateBalanceLinkForOrder` (admin remote) — auth-protected, requires `INCLUDIO_BALANCE_TOKEN_SECRET`, builds URL z configured `orderViewUrl` + `?balance=1&balanceToken=...`. Zwraca `{ success, url, balanceAmount }`.
87
+ - `shop-order-detail-page.svelte` — nowa sekcja "Płatność dzielona" widoczna gdy `order.partialPayment != null`: Plum badge "Czeka na dopłatę" przy `balanceOwed=true` / success badge "Opłacone w całości" po dopłacie, paid/owed/total breakdown z `formatCentsPrice`, button "Wyślij link do dopłaty" generuje token + kopiuje URL do clipboard, wyświetla URL w `<code>` blocku jako fallback dla "skopiuj ręcznie".
88
+
89
+ ### Fixed
90
+ - `variant-attributes.ts` — `datetime` walidator używa teraz `z.string().datetime({ offset: true })`: akceptuje pełen ISO 8601 (`Z` UTC z admin `DatetimeField.toISOString()` ORAZ offset `+02:00` z importów/seedów/zewnętrznych systemów). Wcześniej tryb default odrzucał offset, blokując offsetowe wartości atrybutów.
91
+ - `updateOrderStatus` (`server/orders.ts`) — admin manual mark-paid auto-detektuje `deposit` kind: gdy `order.partialPayment.kind === "deposit"` + `!balanceOwed` + `paidAt == null`, `effectiveKind = "deposit"`. Wcześniej `updateOrderStatusCmd` (w przeciwieństwie do webhooka) nie przekazywał `paymentKind`, więc admin oznaczając deposit order jako paid pomijał deposit logic (`paidAmount` nie był bumpowany, `balanceOwed` nie był ustawiany). Pozwala testować pełny deposit flow przez manual adapter bez sandbox PayU; webhook bez zmian (zawsze pass explicit kind).
92
+ - admin `paymentPolicy` — trzy bugi powodujące kasowanie deposit policy przy każdym save naprawione razem: (1) `upsertShopData` (`server/shop-data.ts`) — `undefined` zachowuje istniejącą policy, tylko `null` kasuje (było `?? null` nadpisujące przy każdym upsert innego pola); (2) `shopDataInputSchema` (admin remote) — dodany discriminated union `paymentPolicy` (full/deposit + percent/amount), wcześniej command odrzucał pole; (3) `shop-field.svelte` — sekcja "Zasady płatności" (radio full/deposit + warunkowe inputy percent/amount + live preview kwoty depozytu), wcześniej brak UI do ustawienia deposit.
93
+
94
+ ## 0.26.1 — 2026-05-28
95
+
96
+ Nowy typ pola `icon` + IconSetPlugin (zestaw ikon dostarczany przez aplikację, dialog z gridem + search). Scaffolder fix + DataTable polish: scaffold admin używa publicznych entry points; pierwsza kolumna tabeli bez sticky-first; checkbox visual wraca do 16 px z transparent hit-area 24×24 (WCAG 2.5.5).
97
+
98
+ ### Added
99
+ - Nowy typ pola `icon` (`IconField` @public, `src/lib/types/fields.ts`) — kompaktowy kafelek 96×96 w formularzu (ikona + nazwa, X do wyczyszczenia) otwiera dialog z gridem responsive 3–6 kolumn, wyszukiwarką (filtruje po `key`, lokalizowanym `label`, opcjonalnych `keywords`) i przyciskami Anuluj / OK. Klik na kafelku w dialogu zaznacza, OK zatwierdza; dwuklik = szybki zapis. Stan "missing" (wartość w DB nieobecna w bibliotece) pokazuje placeholder + przyjazne ostrzeżenie zamiast resetować wartość — zgodne z ToV "informuj, nie strasz". i18n PL/EN, `role="listbox"`/`role="option"`/`aria-selected`, LiveRegion z liczbą wyników.
100
+ - `IconSetPlugin` / `IconDefinition` (`@public`, `src/lib/types/plugins.ts`) — nowy rodzaj pluginu rejestrujący nazwany zestaw ikon: `{ slug, type: 'icon-set', icons: Record<key, { component, label: Localized, keywords?: string[] }> }`. Komponenty Svelte (eager import, tree-shakable — np. `Brain` z `@lucide/svelte`) ŻYJĄ w pluginie, bo `cms.config.ts` jest server-only i Zod-validated. `Plugin = PluginConfig | IconSetPlugin` + `isIconSetPlugin` type guard.
101
+ - `buildIconSetMap(...plugins)` (`includio-cms/admin`) + nowy prop `iconSets?: Map<string, IconSetPlugin>` na `AdminLayout` — konsumencki `+layout.svelte` admina przekazuje plugin instancje na klienta (funkcji komponentów nie da się serializować przez SvelteKit data). `getIconSets()` / `resolveIconSet(slug?)` w `includio-cms/admin` — runtime lookup używany przez `icon-field.svelte` przez Svelte context.
102
+ - `CMS.iconSets: Map<slug, IconSetPlugin>` agregowane przy starcie z `cms.config.plugins` przez `isIconSetPlugin` guard; duplikat slug → throw. Generator TS mapuje `icon` → `string` w wygenerowanym `types.ts`; Zod runtime → `z.string()` (analogicznie do `slug` field).
103
+
104
+ ### Fixed
105
+ - `scaffold admin` generuje `src/routes/admin/api/[...path]/+server.ts` z `import { createAdminApiHandler } from 'includio-cms/sveltekit/server'`. Wcześniej generowany import `includio-cms/admin/api/handler` rzucał Vite `Missing "./admin/api/handler" specifier in "includio-cms" package` przy starcie dev/build — `admin/api/handler` nie ma w `exports` (v1.0 frozen 18 ścieżek).
106
+ - `scaffold admin` generuje `src/routes/admin/api/rest/[...restPath]/+server.ts` z `import { createRestApiHandler } from 'includio-cms/sveltekit/server'` (analogicznie — był broken w 0.20.0+ ale scaffolder nie zaktualizowany).
107
+ - `includio-cms/sveltekit/server` re-eksportuje teraz `createAdminApiHandler` (obok istniejącego `createRestApiHandler`).
108
+ - `DataTable`: revert sticky-first column (z 0.26.0 / S10c) — pierwsza kolumna scrolluje razem z resztą, bez wyróżnienia kolorystycznego. Usunięty prop `stickyFirstColumn` i powiązany CSS.
109
+ - `Checkbox` primitive: visual wraca do 16×16 px (z 24×24 w 0.26.0 / S10b), klikalny obszar utrzymany na ≥24×24 przez transparent `::after` pseudo-element (`after:-inset-1`) — WCAG 2.5.5 target-size AA dalej spełniony, lepszy wygląd zgodny z proporcjami pól tekstowych.
110
+
6
111
  ## 0.26.0 — 2026-05-26
7
112
 
8
113
  UI Normalization → release readiness: slug regex camelCase + S8 detail/edit + S9 fields a11y polish + S10 a11y final audit + S10b/S10c mobile responsiveness full pass (sticky first column DataTable, Dialog fullscreenMobile prop, media library Sheet drawers, entry hybrid preview drawer toggle, dashboard mobile layout flip). 43/43 mobile Playwright pass (3 viewports × 12 widoków, 0 critical axe).
package/DOCS.md CHANGED
@@ -1,4 +1,4 @@
1
- # Includio CMS Documentation (v0.26.0)
1
+ # Includio CMS Documentation (v0.28.0)
2
2
 
3
3
  > This file is auto-generated from the docs site. For the latest version, update the package.
4
4
 
package/ROADMAP.md CHANGED
@@ -21,6 +21,14 @@
21
21
  - [x] `[feature]` `[P0]` Faza 11.5 — Shop polish (0.25.0): Stripe adapter (Checkout Session, sig verify, idempotency), refund infra (full + partial cross-adapter), webhook idempotency table (`shop_webhook_events`), coupons (% / fixed, expiresAt, maxUses, minOrder), low-stock email alert, order export CSV, default email templates (PL/EN), SDK JSDoc + `@public`, pełna dokumentacja shopa <!-- files: src/lib/shop/adapters/stripe/, src/lib/shop/server/{refund,coupons}.ts, src/lib/db-postgres/schema/shop/{refunds,webhookEvents,coupons,couponRedemptions}.ts, src/lib/admin/client/shop/, src/lib/updates/0.25.0/ -->
22
22
  - [ ] `[fix]` `[P1]` Select field — `defaultValue` propagacja do zod schema (full repro: `ideas/post-v1/select-field-defaultvalue-bug.md`); fix planowany w Fazie 12 (RC)
23
23
  - [x] `[chore]` `[P2]` Demo orchestrator — `pnpm demo` startuje czystą instancję na tmpfs DB :5436, seeduje 12 blog postów / 6 projektów / 5 contact submissions / 8 gradient PNG-ów, włącza `demo-site` frontend pod `/demo-site`, każdy start = czysty stan <!-- files: scripts/demo.ts, scripts/seed-demo.ts, src/routes/demo-site/, docker-compose.yml, .env.demo -->
24
+ - [x] `[feature]` `[P1]` Shop platformowy 0.27.0 — schema-driven variants + booking deposit (envet pilot). Plan: 7 faz. <!-- files: docs/superpowers/specs/2026-05-28-shop-platformowy-design.md, /Users/patryk/.claude/plans/implementacja-ariacms-0-27-partitioned-kahn.md -->
25
+ - [x] Faza 1 — Schema-driven `variantAttributes` (typed `defineShop` schema, Zod builder, GIN index util, ts-gen typed `variant.attributes`, `INVALID_VARIANT_ATTRIBUTES` guard w `upsertShopData`). <!-- files: src/lib/shop/types.ts, src/lib/shop/variant-attributes.ts, src/lib/shop/server/{shop-data,init}.ts, src/lib/db-postgres/schema/shop/productVariant.ts, src/lib/core/server/generator/fields.ts -->
26
+ - [x] Faza 2 — Admin dynamic variant attribute form renderer (`VariantAttributeRenderer.svelte`, integracja w `shop-field.svelte`, `getShopConfig` remote response zwraca `variantAttributes`, auto-apply GIN indexes na `initCMS()`). <!-- files: src/lib/admin/components/variant-form/VariantAttributeRenderer.svelte, src/lib/admin/components/fields/shop-field.svelte, src/lib/admin/remote/shop.remote.ts, src/lib/core/cms.ts, src/lib/shop/server/init.ts, src/stories/fields/shop-with-attributes.stories.svelte -->
27
+ - [x] Faza 3 — `variantLabel.template` interpolation + admin pre-fill (`interpolateTemplate` engine z filtrami `date`/`currency`/`uppercase`, `ShopConfig.variantLabel`, `defineShop` przepuszcza, `getShopConfig` remote zwraca, `shop-field.svelte` auto-prefills `variant.name` per locale `pl` z per-variant dirty flag — locked po hydratacji jeśli name istnieje + po `oninput` w name). <!-- files: src/lib/shop/template.ts, src/lib/shop/types.ts, src/lib/shop/index.ts, src/lib/admin/remote/shop.remote.ts, src/lib/admin/components/fields/shop-field.svelte, src/stories/fields/shop-with-attributes-story-demo.svelte, src/stories/fields/shop-with-attributes.stories.svelte -->
28
+ - [x] Faza 4 — `variantExpiry` opt-in (storefront filter + cart-add guard + checkout guard + admin "Zakończony" badge + filter toggle + source-asc sort + upcoming HTTP endpoint + `client.products.listUpcoming` SDK). <!-- files: src/lib/shop/expiry.ts, src/lib/shop/types.ts, src/lib/shop/index.ts, src/lib/shop/server/orders.ts, src/lib/shop/http/{cart-handler,upcoming-handler,index}.ts, src/lib/shop/client/index.ts, src/lib/admin/remote/shop.remote.ts, src/lib/admin/components/fields/shop-field.svelte -->
29
+ - [x] Faza 5 — `paymentPolicy` A-lite (deposit + balance + signed token + refund per kind, admin balance link + refund-per-kind dialog, shop_payments rows tagged by kind). <!-- files: src/lib/shop/types.ts, src/lib/shop/server/{payment-policy,balance-payment,payments,orders,refund,shop-data}.ts, src/lib/shop/http/{balance-handler,checkout-handler,webhook-handler,index}.ts, src/lib/shop/client/index.ts, src/lib/db-postgres/schema/shop/{order,payment,product}.ts, src/lib/admin/{remote/shop.remote.ts,client/shop/{shop-order-detail-page,refund-dialog}.svelte} -->
30
+ - [x] Faza 6 — envet integration (pilot consumer) — szkolenia variants + deposit flow + balance link end-to-end QA. <!-- files: envet repo src/lib/cms/cms.config.ts, src/routes/api/shop/, src/routes/(website)/{szkolenia,koszyk}/, src/lib/components/{CartIcon,AddToCartModal,CoursePage}.svelte, cli/seed.ts -->
31
+ - [x] Faza 7 — Release artifacts (changelog, ROADMAP cleanup, API.md, build) — 3 post-Faza-5 hotfixy w 0.27.0 (single release). <!-- files: src/lib/updates/0.27.0/index.ts, ROADMAP.md, CHANGELOG.md, API.md, MIGRATION-... -->
24
32
  - [x] `[feature]` `[P1]` Slug first-class + SEO v1.0 freeze (0.26.0) — `resolveSeo` public (`includio-cms/core`), `seoFieldDescriptor` SSOT (Zod+TS drift-guard), admin URL un-hardcode (`slugPath.ts` pure resolver, no `seo`-field requirement), `SlugField`/`SeoField`/`SeoFieldData` `@public` v1.0-frozen <!-- files: src/lib/core/fields/slugPath.ts, src/lib/core/fields/seoFieldDescriptor.ts, src/lib/core/fields/resolveSeo.ts, src/lib/types/fields.ts, src/lib/admin/client/collection/collection-entries.svelte, src/lib/updates/0.26.0/ -->
25
33
 
26
34
  ## v1.x — Post-v1.0 deferred