@endora-commerce/mod-sales-channels 0.100.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/admin/api/sales-channels-client.d.ts +69 -0
- package/dist/admin/api/sales-channels-client.d.ts.map +1 -0
- package/dist/admin/api/sales-channels-client.js +74 -0
- package/dist/admin/api/sales-channels-client.js.map +1 -0
- package/dist/admin/components/ChannelIdentityForm.d.ts +24 -0
- package/dist/admin/components/ChannelIdentityForm.d.ts.map +1 -0
- package/dist/admin/components/ChannelIdentityForm.js +147 -0
- package/dist/admin/components/ChannelIdentityForm.js.map +1 -0
- package/dist/admin/components/DefaultChannelBadge.d.ts +21 -0
- package/dist/admin/components/DefaultChannelBadge.d.ts.map +1 -0
- package/dist/admin/components/DefaultChannelBadge.js +26 -0
- package/dist/admin/components/DefaultChannelBadge.js.map +1 -0
- package/dist/admin/components/EntityChannelMembership.d.ts +52 -0
- package/dist/admin/components/EntityChannelMembership.d.ts.map +1 -0
- package/dist/admin/components/EntityChannelMembership.js +98 -0
- package/dist/admin/components/EntityChannelMembership.js.map +1 -0
- package/dist/admin/index.d.ts +44 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +148 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/SalesChannelEditPage.d.ts +25 -0
- package/dist/admin/pages/SalesChannelEditPage.d.ts.map +1 -0
- package/dist/admin/pages/SalesChannelEditPage.js +185 -0
- package/dist/admin/pages/SalesChannelEditPage.js.map +1 -0
- package/dist/admin/pages/SalesChannelsListPage.d.ts +25 -0
- package/dist/admin/pages/SalesChannelsListPage.d.ts.map +1 -0
- package/dist/admin/pages/SalesChannelsListPage.js +91 -0
- package/dist/admin/pages/SalesChannelsListPage.js.map +1 -0
- package/dist/admin/zones/OrganizationChannelMembership.d.ts +34 -0
- package/dist/admin/zones/OrganizationChannelMembership.d.ts.map +1 -0
- package/dist/admin/zones/OrganizationChannelMembership.js +11 -0
- package/dist/admin/zones/OrganizationChannelMembership.js.map +1 -0
- package/dist/admin/zones/ProductChannelMembership.d.ts +23 -0
- package/dist/admin/zones/ProductChannelMembership.d.ts.map +1 -0
- package/dist/admin/zones/ProductChannelMembership.js +11 -0
- package/dist/admin/zones/ProductChannelMembership.js.map +1 -0
- package/dist/backend/commands/set-default.command.d.ts +53 -0
- package/dist/backend/commands/set-default.command.d.ts.map +1 -0
- package/dist/backend/commands/set-default.command.js +87 -0
- package/dist/backend/commands/set-default.command.js.map +1 -0
- package/dist/backend/index.d.ts +71 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +81 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +12 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +302 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +36 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +58 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/index.d.ts +2 -0
- package/dist/backend/services/index.d.ts.map +1 -0
- package/dist/backend/services/index.js +2 -0
- package/dist/backend/services/index.js.map +1 -0
- package/dist/backend/services/sales-channel-attribution-registry.d.ts +28 -0
- package/dist/backend/services/sales-channel-attribution-registry.d.ts.map +1 -0
- package/dist/backend/services/sales-channel-attribution-registry.js +50 -0
- package/dist/backend/services/sales-channel-attribution-registry.js.map +1 -0
- package/dist/backend/services/sales-channels.service.d.ts +247 -0
- package/dist/backend/services/sales-channels.service.d.ts.map +1 -0
- package/dist/backend/services/sales-channels.service.js +535 -0
- package/dist/backend/services/sales-channels.service.js.map +1 -0
- package/dist/manifest.d.ts +185 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +204 -0
- package/dist/manifest.js.map +1 -0
- package/docs/sales_channels/admin-usage.md +77 -0
- package/docs/sales_channels/developer-guide.md +107 -0
- package/docs/sales_channels/index.md +95 -0
- package/i18n/en.json +75 -0
- package/i18n/pl.json +75 -0
- package/package.json +88 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Sales Channels
|
|
3
|
+
sidebar_label: Sales channels
|
|
4
|
+
sidebar_position: 1
|
|
5
|
+
description: Channel registry, request resolver, bidirectional membership for every channel-scoped entity
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Sales Channels
|
|
9
|
+
|
|
10
|
+
The Sales Channels module is the platform's stable handle for "where the sale happens". Every channel-scoped piece of platform data — products, categories, customers, orders, quotes, prices, promotions, CMS pages — is bound to one or more Sales Channels and is filtered through the channel context of the incoming request. The module owns the channel registry, the bidirectional membership service, the resolver middleware that maps every HTTP request onto exactly one channel, and the lifecycle guards that keep the platform from ending up with channel-less data.
|
|
11
|
+
|
|
12
|
+
## Concepts
|
|
13
|
+
|
|
14
|
+
- **Sales Channel** — a named place of sale (web storefront, marketplace, brick-and-mortar location, distributor portal). Carries a unique `code`, a multilingual display name, an optional logo and theme code, an ordered list of supported languages with a default, an ordered list of supported currencies with a default, and an `active` flag. Exactly one channel platform-wide carries `system_default = true` (enforced by a partial unique index).
|
|
15
|
+
|
|
16
|
+
- **System default channel** — the bootstrap channel created by the boot-time reconciler. It is the implicit owner of every channel-scoped entity created without an explicit channel selection. It is non-deletable and non-deactivatable. The env var `DEFAULT_SALES_CHANNEL_CODE` (default `default`) names the channel.
|
|
17
|
+
|
|
18
|
+
- **Membership** — the M:N relationship between a channel and a channel-scoped entity. Nine entity types are tracked: `product`, `category`, `payment-method`, `delivery-method`, `organization`, `tax`, `customer`, `promotion`, `cms-page`. (`inventory-location` is reserved for when the inventory module introduces that table.)
|
|
19
|
+
|
|
20
|
+
- **Attribution** — the M:1 relationship for Orders and Quote Requests. Each row is bound to exactly one channel at placement, and the binding is immutable for audit purposes.
|
|
21
|
+
|
|
22
|
+
- **At-least-one-channel invariant** — every channel-scoped entity is bound to at least one channel at all times. Removing the last membership of an entity is refused unless the caller passes `fallbackToDefault=true`, in which case the entity is rebound to the system default in the same transaction.
|
|
23
|
+
|
|
24
|
+
## Resolver — request → channel
|
|
25
|
+
|
|
26
|
+
A Fastify `onRequest` hook runs on every `/api/v1/*` request and resolves it to exactly one channel. Resolution order:
|
|
27
|
+
|
|
28
|
+
1. **`X-Sales-Channel: <code>` header** — explicit signal, always wins.
|
|
29
|
+
2. **`?salesChannel=<code>` query parameter** — storefront / integration paths only; ignored on `/api/v1/admin/*` to prevent cross-channel admin bleed.
|
|
30
|
+
3. **Host-based mapping** — env-configured `SALES_CHANNEL_HOST_MAP` (e.g. `serwisA.com=channel-a,serwisB.com=channel-b`).
|
|
31
|
+
4. **Fallback to the system default** — for storefront / integration paths only. Admin paths refuse with `MISSING_SALES_CHANNEL_CONTEXT` when `strictAdmin` is on (off by default during the initial rollout).
|
|
32
|
+
|
|
33
|
+
If a step matches a code that doesn't exist or whose channel is `active=false`, the request is refused with `UNKNOWN_SALES_CHANNEL` / `INACTIVE_SALES_CHANNEL`. The fallback never applies in those cases.
|
|
34
|
+
|
|
35
|
+
Every response carries `X-Sales-Channel: <resolvedCode>` so HTTP caches can `Vary` on it.
|
|
36
|
+
|
|
37
|
+
## Storefront theme
|
|
38
|
+
|
|
39
|
+
A channel's `themeCode` selects which set of design tokens the storefront renders in — colour, typography, spacing, corner radius, elevation. It is chosen from a list on the channel's identity form, and the list holds the themes the storefront actually implements; a channel that names none renders in the default theme.
|
|
40
|
+
|
|
41
|
+
The storefront reads it through the public channel endpoint:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
GET /api/v1/storefront/sales-channel
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
which returns the **resolved** channel for the request — code, display name, language and currency scopes, `themeCode` and `logoUrl` — and no admin-only field (`id`, `active`, `systemDefault`, `version`). The storefront applies the theme server-side, on the first render, so the first HTML a buyer's browser parses already carries the channel's brand.
|
|
48
|
+
|
|
49
|
+
The theme changes how the storefront looks, not what it is made of: every channel renders the same pages with the same components. A per-channel page *template* is a larger question, and is deliberately not answered here.
|
|
50
|
+
|
|
51
|
+
A channel configured with a theme code the storefront does not implement renders in the default theme and logs the code it was given. The page is never refused for a buyer, and no other theme is substituted by guesswork.
|
|
52
|
+
|
|
53
|
+
## Bidirectional membership
|
|
54
|
+
|
|
55
|
+
Memberships can be managed equivalently from either side:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
GET /api/v1/admin/sales-channels/:code/:entityType
|
|
59
|
+
PUT /api/v1/admin/sales-channels/:code/:entityType/:entityId
|
|
60
|
+
DELETE /api/v1/admin/sales-channels/:code/:entityType/:entityId?fallbackToDefault=true
|
|
61
|
+
GET /api/v1/admin/sales-channels/by-entity/:entityType/:entityId
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Both sides delegate to `SalesChannelMembershipService`, which is the single mutator for every bridge table. Operators reach the same data whether they're editing a Sales Channel's membership panel or a Product's "Sales channels" widget on the entity edit page.
|
|
65
|
+
|
|
66
|
+
## Lifecycle guards
|
|
67
|
+
|
|
68
|
+
| Operation | Refused when… | Error code |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `deactivate(default)` | always | `CANNOT_MODIFY_SYSTEM_DEFAULT` |
|
|
71
|
+
| `delete(default)` | always | `CANNOT_MODIFY_SYSTEM_DEFAULT` |
|
|
72
|
+
| `delete(channel)` | any Order or Quote refers to it | `SALES_CHANNEL_HAS_ATTRIBUTIONS` |
|
|
73
|
+
| `delete(channel)` | any membership entity would orphan AND `fallbackToDefault=false` | `ENTITY_WOULD_HAVE_ZERO_CHANNELS` |
|
|
74
|
+
| `update(channel)` | submitted `expectedVersion` is stale | `STALE_SALES_CHANNEL_WRITE` |
|
|
75
|
+
| `create / update(channel)` | unknown language / currency code | `UNKNOWN_LANGUAGE_CODE` / `UNKNOWN_CURRENCY_CODE` |
|
|
76
|
+
| `create / rename(channel)` | code already in use | `DUPLICATE_SALES_CHANNEL_CODE` |
|
|
77
|
+
|
|
78
|
+
Hard-delete with `?fallbackToDefault=true` rebinds orphaned entities to the system default inside the same transaction before the channel row is removed; the bridge tables' `ON DELETE CASCADE` is the safety net for any membership that doesn't need explicit rebinding.
|
|
79
|
+
|
|
80
|
+
## Audit trail
|
|
81
|
+
|
|
82
|
+
Every identity change, lifecycle change, and membership change writes one `audit_log_entries` row synchronously inside the same transaction. The action codes live in `@endora-commerce/contracts` as `SALES_CHANNEL_AUDIT_ACTIONS`:
|
|
83
|
+
|
|
84
|
+
- `sales_channel.identity.changed` — create + update.
|
|
85
|
+
- `sales_channel.lifecycle.changed` — deactivate / activate / delete / system-default-promoted.
|
|
86
|
+
- `sales_channel.membership.changed` — add / remove (no-op writes are not audited).
|
|
87
|
+
|
|
88
|
+
## Environment variables
|
|
89
|
+
|
|
90
|
+
| Name | Default | Purpose |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `DEFAULT_SALES_CHANNEL_CODE` | `default` | Code of the channel the boot reconciler creates / promotes as `system_default = true`. |
|
|
93
|
+
| `SALES_CHANNEL_HOST_MAP` | empty | Comma-separated `host=channelCode` pairs used by the resolver when no `X-Sales-Channel` header is provided. Example: `serwisA.com=channel-a,serwisB.com=channel-b`. |
|
|
94
|
+
|
|
95
|
+
See [admin-usage](./admin-usage.md) for the day-to-day operator workflow and [developer-guide](./developer-guide.md) for cross-module integration.
|
package/i18n/en.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nav.salesChannels.label": "Sales channels",
|
|
3
|
+
"actions.openSalesChannels.label": "Sales channels",
|
|
4
|
+
"actions.openSalesChannels.description": "Storefront channels",
|
|
5
|
+
"actions.newSalesChannel.label": "New sales channel",
|
|
6
|
+
"actions.newSalesChannel.description": "Configure a new storefront sales channel",
|
|
7
|
+
"list.page.title": "Sales channels",
|
|
8
|
+
"list.page.description": "Each channel represents a place of sale (web storefront, marketplace, brick-and-mortar location). Products, customers, prices, and content are scoped to the channels they belong to. The “system default” channel is the implicit fallback for any entity created without explicit channel selection.",
|
|
9
|
+
"list.error.load": "Failed to load sales channels.",
|
|
10
|
+
"list.action.newChannel": "+ New channel",
|
|
11
|
+
"list.filter.activeOnly": "Show active channels only",
|
|
12
|
+
"list.loading": "Loading sales channels…",
|
|
13
|
+
"list.empty": "No channels match the filter.",
|
|
14
|
+
"list.column.code": "Code",
|
|
15
|
+
"list.column.name": "Name",
|
|
16
|
+
"list.column.defaultLangCurrency": "Default lang / currency",
|
|
17
|
+
"list.column.status": "Status",
|
|
18
|
+
"list.column.version": "Version",
|
|
19
|
+
"list.column.systemDefault": "System default",
|
|
20
|
+
"list.action.makeDefault": "Make default",
|
|
21
|
+
"list.action.makeDefault.confirm": "Make “{code}” the system-default sales channel? Entities created without an explicit channel, and every platform-wide fallback, will point at it from now on. “{previous}” stays exactly as it is and can be made the default again.",
|
|
22
|
+
"list.action.makeDefault.inactiveHelp": "An inactive channel cannot become the system default.",
|
|
23
|
+
"list.action.makeDefault.current": "Current default",
|
|
24
|
+
"list.error.makeDefault": "Failed to move the system default.",
|
|
25
|
+
"status.active": "Active",
|
|
26
|
+
"status.inactive": "Inactive",
|
|
27
|
+
"badge.systemDefault": "System default",
|
|
28
|
+
"edit.loading": "Loading channel…",
|
|
29
|
+
"identity.title.create": "New Sales Channel",
|
|
30
|
+
"identity.title.edit": "Identity",
|
|
31
|
+
"identity.code.label": "Code",
|
|
32
|
+
"identity.code.lockedHelp": "A channel code is set once, when the channel is created, and cannot be changed afterwards — deployment configuration, integrations and cached storefront responses all address the channel by it. To correct one, create a channel with the right code and delete this one. The display name stays editable.",
|
|
33
|
+
"identity.name.label": "Display name (en-US)",
|
|
34
|
+
"identity.name.placeholder": "Service A",
|
|
35
|
+
"identity.theme.label": "Storefront theme",
|
|
36
|
+
"identity.theme.placeholder": "e.g. nordic",
|
|
37
|
+
"identity.theme.pattern": "Lowercase letters, digits, hyphens and underscores, starting with a letter.",
|
|
38
|
+
"identity.theme.help": "The theme code the storefront renders this channel in. Leave it empty for the storefront's default theme. Which themes exist is the storefront's answer, not this one's: a code it does not provide renders in the default and is marked on the page as data-theme-requested, and this value is never changed for you.",
|
|
39
|
+
"identity.languages.label": "Languages",
|
|
40
|
+
"identity.languages.help": "Active Dictionary languages are available for new selections. Inactive stored values remain visible until removed.",
|
|
41
|
+
"identity.defaultLanguage.label": "Default language",
|
|
42
|
+
"identity.currencies.label": "Currencies",
|
|
43
|
+
"identity.currencies.help": "Active Dictionary currencies are available for new selections. Inactive stored values remain visible until removed.",
|
|
44
|
+
"identity.defaultCurrency.label": "Default currency",
|
|
45
|
+
"identity.pickOption": "Pick",
|
|
46
|
+
"identity.active": "Active",
|
|
47
|
+
"identity.cannotDeactivateDefault": "The system-default channel cannot be deactivated.",
|
|
48
|
+
"identity.action.cancel": "Cancel",
|
|
49
|
+
"identity.action.create": "Create channel",
|
|
50
|
+
"identity.action.save": "Save changes",
|
|
51
|
+
"identity.dictionary.inactive": "(inactive)",
|
|
52
|
+
"identity.dictionary.empty": "No Dictionary entries available.",
|
|
53
|
+
"membership.title": "Sales channels",
|
|
54
|
+
"membership.loading": "Loading memberships…",
|
|
55
|
+
"membership.empty": "This {entityType} is not in any channel. Add at least one to make it visible to a storefront.",
|
|
56
|
+
"membership.defaultSuffix": " (default)",
|
|
57
|
+
"membership.action.pickChannel": "Add to channel…",
|
|
58
|
+
"membership.action.add": "Add",
|
|
59
|
+
"membership.action.remove": "Remove",
|
|
60
|
+
"errors.UNKNOWN_SALES_CHANNEL": "Unknown Sales Channel.",
|
|
61
|
+
"errors.INACTIVE_SALES_CHANNEL": "This sales channel is inactive. Activate it first.",
|
|
62
|
+
"errors.MISSING_SALES_CHANNEL_CONTEXT": "Missing Sales Channel Context.",
|
|
63
|
+
"errors.DUPLICATE_SALES_CHANNEL_CODE": "Duplicate Sales Channel Code.",
|
|
64
|
+
"errors.UNKNOWN_LANGUAGE_CODE": "Unknown Language Code.",
|
|
65
|
+
"errors.UNKNOWN_CURRENCY_CODE": "Unknown Currency Code.",
|
|
66
|
+
"errors.CANNOT_MODIFY_SYSTEM_DEFAULT": "Cannot Modify System Default.",
|
|
67
|
+
"errors.SALES_CHANNEL_HAS_ATTRIBUTIONS": "Sales Channel Has Attributions.",
|
|
68
|
+
"errors.ENTITY_WOULD_HAVE_ZERO_CHANNELS": "Entity Would Have Zero Channels.",
|
|
69
|
+
"errors.STALE_SALES_CHANNEL_WRITE": "Stale Sales Channel Write.",
|
|
70
|
+
"errors.SALES_CHANNEL_ATTRIBUTION_IMMUTABLE": "Sales Channel Attribution Immutable.",
|
|
71
|
+
"errors.SALES_CHANNEL_CODE_IMMUTABLE": "A sales channel code is set when the channel is created and cannot be changed afterwards. Create a channel with the correct code and delete this one instead; the display name stays editable.",
|
|
72
|
+
"auditLog.sales_channel.lifecycle_changed": "Sales channel lifecycle changed",
|
|
73
|
+
"auditLog.sales_channel.membership_changed": "Sales channel membership changed",
|
|
74
|
+
"auditLog.sales_channel.set_default": "System-default sales channel moved"
|
|
75
|
+
}
|
package/i18n/pl.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nav.salesChannels.label": "Kanały sprzedaży",
|
|
3
|
+
"actions.openSalesChannels.label": "Kanały sprzedaży",
|
|
4
|
+
"actions.openSalesChannels.description": "Kanały sklepu",
|
|
5
|
+
"actions.newSalesChannel.label": "Nowy kanał sprzedaży",
|
|
6
|
+
"actions.newSalesChannel.description": "Skonfiguruj nowy kanał sprzedaży witryny",
|
|
7
|
+
"list.page.title": "Kanały sprzedaży",
|
|
8
|
+
"list.page.description": "Każdy kanał reprezentuje miejsce sprzedaży (sklep internetowy, marketplace, lokalizacja stacjonarna). Produkty, klienci, ceny i treści są zakresowane do kanałów, do których należą. Kanał „domyślny systemowo” jest niejawnym fallbackiem dla każdej encji utworzonej bez wyraźnego wyboru kanału.",
|
|
9
|
+
"list.error.load": "Nie udało się wczytać kanałów sprzedaży.",
|
|
10
|
+
"list.action.newChannel": "+ Nowy kanał",
|
|
11
|
+
"list.filter.activeOnly": "Pokaż tylko aktywne kanały",
|
|
12
|
+
"list.loading": "Wczytywanie kanałów sprzedaży…",
|
|
13
|
+
"list.empty": "Żaden kanał nie pasuje do filtra.",
|
|
14
|
+
"list.column.code": "Kod",
|
|
15
|
+
"list.column.name": "Nazwa",
|
|
16
|
+
"list.column.defaultLangCurrency": "Domyślny język / waluta",
|
|
17
|
+
"list.column.status": "Status",
|
|
18
|
+
"list.column.version": "Wersja",
|
|
19
|
+
"list.column.systemDefault": "Domyślny systemowo",
|
|
20
|
+
"list.action.makeDefault": "Ustaw jako domyślny",
|
|
21
|
+
"list.action.makeDefault.confirm": "Ustawić „{code}” jako domyślny systemowo kanał sprzedaży? Encje tworzone bez wskazania kanału oraz wszystkie odczyty ogólnoplatformowe będą od tej chwili wskazywać na niego. „{previous}” pozostaje bez zmian i może ponownie zostać kanałem domyślnym.",
|
|
22
|
+
"list.action.makeDefault.inactiveHelp": "Nieaktywny kanał nie może zostać kanałem domyślnym systemowo.",
|
|
23
|
+
"list.action.makeDefault.current": "Obecnie domyślny",
|
|
24
|
+
"list.error.makeDefault": "Nie udało się przenieść kanału domyślnego.",
|
|
25
|
+
"status.active": "Aktywny",
|
|
26
|
+
"status.inactive": "Nieaktywny",
|
|
27
|
+
"badge.systemDefault": "Domyślny systemowo",
|
|
28
|
+
"edit.loading": "Wczytywanie kanału…",
|
|
29
|
+
"identity.title.create": "Nowy kanał sprzedaży",
|
|
30
|
+
"identity.title.edit": "Tożsamość",
|
|
31
|
+
"identity.code.label": "Kod",
|
|
32
|
+
"identity.code.lockedHelp": "Kod kanału ustawiasz raz, przy tworzeniu kanału, i nie można go później zmienić — konfiguracja wdrożenia, integracje i zapisane w cache odpowiedzi storefrontu adresują kanał właśnie po nim. Aby poprawić kod, utwórz kanał z właściwym kodem i usuń ten. Nazwa wyświetlana pozostaje edytowalna.",
|
|
33
|
+
"identity.name.label": "Nazwa wyświetlana (en-US)",
|
|
34
|
+
"identity.name.placeholder": "Serwis A",
|
|
35
|
+
"identity.theme.label": "Motyw sklepu",
|
|
36
|
+
"identity.theme.placeholder": "np. nordic",
|
|
37
|
+
"identity.theme.pattern": "Małe litery, cyfry, myślniki i podkreślenia, zaczynając od litery.",
|
|
38
|
+
"identity.theme.help": "Kod motywu, w którym storefront renderuje ten kanał. Pozostaw puste, aby użyć motywu domyślnego. To storefront wie, jakie motywy istnieją, a nie ten ekran: kod, którego nie ma, renderuje się w motywie domyślnym i zostaje oznaczony na stronie jako data-theme-requested, a ta wartość nigdy nie jest zmieniana automatycznie.",
|
|
39
|
+
"identity.languages.label": "Języki",
|
|
40
|
+
"identity.languages.help": "Dostępne do wyboru są aktywne wpisy Słownika języków. Wartości przypisane wcześniej, ale obecnie nieaktywne, pozostają widoczne do usunięcia.",
|
|
41
|
+
"identity.defaultLanguage.label": "Język domyślny",
|
|
42
|
+
"identity.currencies.label": "Waluty",
|
|
43
|
+
"identity.currencies.help": "Dostępne do wyboru są aktywne wpisy Słownika walut. Wartości przypisane wcześniej, ale obecnie nieaktywne, pozostają widoczne do usunięcia.",
|
|
44
|
+
"identity.defaultCurrency.label": "Waluta domyślna",
|
|
45
|
+
"identity.pickOption": "Wybierz",
|
|
46
|
+
"identity.active": "Aktywny",
|
|
47
|
+
"identity.cannotDeactivateDefault": "Kanał domyślny systemowo nie może zostać dezaktywowany.",
|
|
48
|
+
"identity.action.cancel": "Anuluj",
|
|
49
|
+
"identity.action.create": "Utwórz kanał",
|
|
50
|
+
"identity.action.save": "Zapisz zmiany",
|
|
51
|
+
"identity.dictionary.inactive": "(nieaktywny)",
|
|
52
|
+
"identity.dictionary.empty": "Brak wpisów w Słowniku.",
|
|
53
|
+
"membership.title": "Kanały sprzedaży",
|
|
54
|
+
"membership.loading": "Wczytywanie przynależności…",
|
|
55
|
+
"membership.empty": "Ten {entityType} nie należy do żadnego kanału. Dodaj co najmniej jeden, aby był widoczny w sklepie.",
|
|
56
|
+
"membership.defaultSuffix": " (domyślny)",
|
|
57
|
+
"membership.action.pickChannel": "Dodaj do kanału…",
|
|
58
|
+
"membership.action.add": "Dodaj",
|
|
59
|
+
"membership.action.remove": "Usuń",
|
|
60
|
+
"errors.UNKNOWN_SALES_CHANNEL": "Błąd: unknown sales channel.",
|
|
61
|
+
"errors.INACTIVE_SALES_CHANNEL": "Ten kanał sprzedaży jest nieaktywny. Najpierw go aktywuj.",
|
|
62
|
+
"errors.MISSING_SALES_CHANNEL_CONTEXT": "Błąd: missing sales channel context.",
|
|
63
|
+
"errors.DUPLICATE_SALES_CHANNEL_CODE": "Błąd: duplicate sales channel code.",
|
|
64
|
+
"errors.UNKNOWN_LANGUAGE_CODE": "Błąd: unknown language code.",
|
|
65
|
+
"errors.UNKNOWN_CURRENCY_CODE": "Błąd: unknown currency code.",
|
|
66
|
+
"errors.CANNOT_MODIFY_SYSTEM_DEFAULT": "Błąd: cannot modify system default.",
|
|
67
|
+
"errors.SALES_CHANNEL_HAS_ATTRIBUTIONS": "Błąd: sales channel has attributions.",
|
|
68
|
+
"errors.ENTITY_WOULD_HAVE_ZERO_CHANNELS": "Błąd: entity would have zero channels.",
|
|
69
|
+
"errors.STALE_SALES_CHANNEL_WRITE": "Błąd: stale sales channel write.",
|
|
70
|
+
"errors.SALES_CHANNEL_ATTRIBUTION_IMMUTABLE": "Błąd: sales channel attribution immutable.",
|
|
71
|
+
"errors.SALES_CHANNEL_CODE_IMMUTABLE": "Kod kanału sprzedaży jest ustawiany przy tworzeniu kanału i nie może być później zmieniony. Utwórz kanał z właściwym kodem i usuń ten; nazwa wyświetlana pozostaje edytowalna.",
|
|
72
|
+
"auditLog.sales_channel.lifecycle_changed": "Zmieniono cykl życia kanału sprzedaży",
|
|
73
|
+
"auditLog.sales_channel.membership_changed": "Zmieniono przypisanie do kanału sprzedaży",
|
|
74
|
+
"auditLog.sales_channel.set_default": "Przeniesiono domyślny systemowo kanał sprzedaży"
|
|
75
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@endora-commerce/mod-sales-channels",
|
|
3
|
+
"version": "0.100.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"description": "Multi-channel storefront resolver and channel registry.",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"endora": {
|
|
9
|
+
"type": "module",
|
|
10
|
+
"id": "sales_channels"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/endora-commerce/endora-commerce.git",
|
|
15
|
+
"directory": "packages/modules/sales_channels"
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/manifest.d.ts",
|
|
23
|
+
"default": "./dist/manifest.js"
|
|
24
|
+
},
|
|
25
|
+
"./backend": {
|
|
26
|
+
"types": "./dist/backend/index.d.ts",
|
|
27
|
+
"default": "./dist/backend/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./admin": {
|
|
30
|
+
"types": "./dist/admin/index.d.ts",
|
|
31
|
+
"default": "./dist/admin/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./tailwind.css": "./tailwind.css",
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"i18n",
|
|
39
|
+
"docs",
|
|
40
|
+
"tailwind.css"
|
|
41
|
+
],
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=22.18.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@mikro-orm/core": "^6",
|
|
47
|
+
"@mikro-orm/postgresql": "^6",
|
|
48
|
+
"fastify": "^5",
|
|
49
|
+
"react": "^19",
|
|
50
|
+
"react-router-dom": "^7",
|
|
51
|
+
"zod": "^4",
|
|
52
|
+
"@endora-commerce/admin-kit": "0.100.0",
|
|
53
|
+
"@endora-commerce/contracts": "0.100.0",
|
|
54
|
+
"@endora-commerce/platform": "0.100.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"@endora-commerce/admin-kit": {
|
|
58
|
+
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"react": {
|
|
61
|
+
"optional": true
|
|
62
|
+
},
|
|
63
|
+
"react-router-dom": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@mikro-orm/core": "^6.6.13",
|
|
69
|
+
"@mikro-orm/postgresql": "^6.6.13",
|
|
70
|
+
"@types/node": "^22.9.0",
|
|
71
|
+
"@types/react": "^19.2.14",
|
|
72
|
+
"fastify": "^5.12.5",
|
|
73
|
+
"react": "^19.2.5",
|
|
74
|
+
"react-router-dom": "^7.18.2",
|
|
75
|
+
"typescript": "^5.9.3",
|
|
76
|
+
"vitest": "^4.1.11",
|
|
77
|
+
"zod": "^4.2.0",
|
|
78
|
+
"@endora-commerce/admin-kit": "0.100.0",
|
|
79
|
+
"@endora-commerce/contracts": "0.100.0",
|
|
80
|
+
"@endora-commerce/platform": "0.100.0"
|
|
81
|
+
},
|
|
82
|
+
"scripts": {
|
|
83
|
+
"build": "tsc -p tsconfig.build.json && tsc -p tsconfig.ui.json",
|
|
84
|
+
"typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.ui.json --noEmit",
|
|
85
|
+
"lint": "eslint src",
|
|
86
|
+
"test": "vitest run"
|
|
87
|
+
}
|
|
88
|
+
}
|
package/tailwind.css
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* @endora-commerce/mod-sales-channels — AUTO-GENERATED by `pnpm --filter backend run manifests:generate`.
|
|
2
|
+
*
|
|
3
|
+
* The `@source` directives this package asks its host to scan
|
|
4
|
+
* (`specs/110-instance-repository/contracts/admin-stylesheet-composition.md` R1).
|
|
5
|
+
* They resolve relative to **this file**, so they hold wherever the package is
|
|
6
|
+
* installed — a workspace link here, `node_modules` in a client's instance.
|
|
7
|
+
*
|
|
8
|
+
* The `dist` line is what a published tarball ships and is what an instance
|
|
9
|
+
* scans; the `src` line is inert there and is what keeps `pnpm --filter admin
|
|
10
|
+
* run dev` reading source in this repository. Do not edit: run
|
|
11
|
+
* `pnpm --filter backend run manifests:generate`.
|
|
12
|
+
*/
|
|
13
|
+
@source "./dist/admin";
|
|
14
|
+
@source "./src/admin";
|