@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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/admin/api/sales-channels-client.d.ts +69 -0
  4. package/dist/admin/api/sales-channels-client.d.ts.map +1 -0
  5. package/dist/admin/api/sales-channels-client.js +74 -0
  6. package/dist/admin/api/sales-channels-client.js.map +1 -0
  7. package/dist/admin/components/ChannelIdentityForm.d.ts +24 -0
  8. package/dist/admin/components/ChannelIdentityForm.d.ts.map +1 -0
  9. package/dist/admin/components/ChannelIdentityForm.js +147 -0
  10. package/dist/admin/components/ChannelIdentityForm.js.map +1 -0
  11. package/dist/admin/components/DefaultChannelBadge.d.ts +21 -0
  12. package/dist/admin/components/DefaultChannelBadge.d.ts.map +1 -0
  13. package/dist/admin/components/DefaultChannelBadge.js +26 -0
  14. package/dist/admin/components/DefaultChannelBadge.js.map +1 -0
  15. package/dist/admin/components/EntityChannelMembership.d.ts +52 -0
  16. package/dist/admin/components/EntityChannelMembership.d.ts.map +1 -0
  17. package/dist/admin/components/EntityChannelMembership.js +98 -0
  18. package/dist/admin/components/EntityChannelMembership.js.map +1 -0
  19. package/dist/admin/index.d.ts +44 -0
  20. package/dist/admin/index.d.ts.map +1 -0
  21. package/dist/admin/index.js +148 -0
  22. package/dist/admin/index.js.map +1 -0
  23. package/dist/admin/pages/SalesChannelEditPage.d.ts +25 -0
  24. package/dist/admin/pages/SalesChannelEditPage.d.ts.map +1 -0
  25. package/dist/admin/pages/SalesChannelEditPage.js +185 -0
  26. package/dist/admin/pages/SalesChannelEditPage.js.map +1 -0
  27. package/dist/admin/pages/SalesChannelsListPage.d.ts +25 -0
  28. package/dist/admin/pages/SalesChannelsListPage.d.ts.map +1 -0
  29. package/dist/admin/pages/SalesChannelsListPage.js +91 -0
  30. package/dist/admin/pages/SalesChannelsListPage.js.map +1 -0
  31. package/dist/admin/zones/OrganizationChannelMembership.d.ts +34 -0
  32. package/dist/admin/zones/OrganizationChannelMembership.d.ts.map +1 -0
  33. package/dist/admin/zones/OrganizationChannelMembership.js +11 -0
  34. package/dist/admin/zones/OrganizationChannelMembership.js.map +1 -0
  35. package/dist/admin/zones/ProductChannelMembership.d.ts +23 -0
  36. package/dist/admin/zones/ProductChannelMembership.d.ts.map +1 -0
  37. package/dist/admin/zones/ProductChannelMembership.js +11 -0
  38. package/dist/admin/zones/ProductChannelMembership.js.map +1 -0
  39. package/dist/backend/commands/set-default.command.d.ts +53 -0
  40. package/dist/backend/commands/set-default.command.d.ts.map +1 -0
  41. package/dist/backend/commands/set-default.command.js +87 -0
  42. package/dist/backend/commands/set-default.command.js.map +1 -0
  43. package/dist/backend/index.d.ts +71 -0
  44. package/dist/backend/index.d.ts.map +1 -0
  45. package/dist/backend/index.js +81 -0
  46. package/dist/backend/index.js.map +1 -0
  47. package/dist/backend/routes.admin.d.ts +12 -0
  48. package/dist/backend/routes.admin.d.ts.map +1 -0
  49. package/dist/backend/routes.admin.js +302 -0
  50. package/dist/backend/routes.admin.js.map +1 -0
  51. package/dist/backend/routes.storefront.d.ts +36 -0
  52. package/dist/backend/routes.storefront.d.ts.map +1 -0
  53. package/dist/backend/routes.storefront.js +58 -0
  54. package/dist/backend/routes.storefront.js.map +1 -0
  55. package/dist/backend/services/index.d.ts +2 -0
  56. package/dist/backend/services/index.d.ts.map +1 -0
  57. package/dist/backend/services/index.js +2 -0
  58. package/dist/backend/services/index.js.map +1 -0
  59. package/dist/backend/services/sales-channel-attribution-registry.d.ts +28 -0
  60. package/dist/backend/services/sales-channel-attribution-registry.d.ts.map +1 -0
  61. package/dist/backend/services/sales-channel-attribution-registry.js +50 -0
  62. package/dist/backend/services/sales-channel-attribution-registry.js.map +1 -0
  63. package/dist/backend/services/sales-channels.service.d.ts +247 -0
  64. package/dist/backend/services/sales-channels.service.d.ts.map +1 -0
  65. package/dist/backend/services/sales-channels.service.js +535 -0
  66. package/dist/backend/services/sales-channels.service.js.map +1 -0
  67. package/dist/manifest.d.ts +185 -0
  68. package/dist/manifest.d.ts.map +1 -0
  69. package/dist/manifest.js +204 -0
  70. package/dist/manifest.js.map +1 -0
  71. package/docs/sales_channels/admin-usage.md +77 -0
  72. package/docs/sales_channels/developer-guide.md +107 -0
  73. package/docs/sales_channels/index.md +95 -0
  74. package/i18n/en.json +75 -0
  75. package/i18n/pl.json +75 -0
  76. package/package.json +88 -0
  77. package/tailwind.css +14 -0
@@ -0,0 +1,247 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import { type DictionaryValidator, type SalesChannelAttributionRegistryPort, type SalesChannelCreateBody, type SalesChannelUpdateBody } from '@endora-commerce/contracts';
3
+ import type { AuditPort } from '@endora-commerce/platform/kernel';
4
+ import type { CommandBus } from '@endora-commerce/platform/commands';
5
+ import type { EventBus } from '@endora-commerce/platform/events';
6
+ import { SalesChannel } from '@endora-commerce/platform/kernel';
7
+ import type { SalesChannelsCacheInvalidation } from '@endora-commerce/platform/kernel';
8
+ import { type SetSystemDefaultChannelResult } from '../commands/set-default.command.js';
9
+ /**
10
+ * SalesChannelsService — feature 005 / T017 (skeleton) + T035-T037 (US2).
11
+ *
12
+ * Admin-side CRUD + lifecycle for the Sales Channel registry. Membership
13
+ * mutations live in {@link SalesChannelMembershipService}; this service
14
+ * deals exclusively with the channel row's identity, lifecycle, and
15
+ * the FR-002 / FR-006 / FR-007 guards.
16
+ *
17
+ * Optimistic concurrency uses the `version` column. Update calls take
18
+ * an `expectedVersion` argument; mismatch raises HTTP 412
19
+ * `STALE_SALES_CHANNEL_WRITE` with the current version in the body so
20
+ * the client can refresh and retry. This matches feature 003 / 004's
21
+ * pattern.
22
+ *
23
+ * Every successful identity / lifecycle change writes one audit row
24
+ * (`sales_channel.identity.changed` / `sales_channel.lifecycle.changed`)
25
+ * synchronously, **drops the channel cache**, and then emits one EventBus
26
+ * event.
27
+ *
28
+ * That order is the whole of D-93 (issue #160). The drop used to be a
29
+ * subscriber — `attachSalesChannelsCacheInvalidator` listened for those two
30
+ * events — which made cache freshness a property of the dispatch order rather
31
+ * than of the write: `dictionaries` subscribes to the same two names and its
32
+ * Redis SCAN has already been measured pushing the invalidator past a tick
33
+ * (#101), and an emission inside an `EventBus.run` scope is buffered until the
34
+ * scope ends, so a write and a read-back in one Command could not be helped by
35
+ * any registration order at all. The events stay — other modules want them —
36
+ * and they stop being how this cache learns about this service's own write.
37
+ *
38
+ * `setDefault` is the exception and the newer pattern: it is a Command
39
+ * (feature 072 / D-51), so the Command Bus writes its audit row and buffers its
40
+ * event co-transactionally, and this class writes neither by hand.
41
+ */
42
+ export interface AdminAuditContext {
43
+ actorAdminUserId: string | null;
44
+ requestId?: string | null;
45
+ }
46
+ export interface SalesChannelsServiceListOptions {
47
+ page?: number;
48
+ pageSize?: number;
49
+ activeOnly?: boolean;
50
+ }
51
+ export interface DeleteOptions {
52
+ fallbackToDefault?: boolean;
53
+ }
54
+ /**
55
+ * The channel-bridge registry, narrowed to the half this service reads
56
+ * (feature 120, FR-015).
57
+ *
58
+ * Declared structurally rather than imported from the platform: the registry
59
+ * class is published on no barrel — it is reached by container name — and the
60
+ * shape a consumer needs is the consumer's own declaration, which is what
61
+ * `ctx.cradle<C>()` asks an author for.
62
+ */
63
+ export interface ChannelBridgeRead {
64
+ list(): ReadonlyArray<{
65
+ readonly entityType: string;
66
+ readonly table: string;
67
+ readonly entityIdColumn: string;
68
+ }>;
69
+ }
70
+ export declare class SalesChannelsService {
71
+ private readonly emFactory;
72
+ private readonly eventBus;
73
+ /**
74
+ * Required, and it was not (issue #251's shape, feature 075's occasion).
75
+ * Both roots have supplied it since feature 072 wave 2, so the absent
76
+ * branch was only ever run by tests — and what ran there was a hand-written
77
+ * `select "code" from "languages" / "currencies"`, two other modules' tables
78
+ * named in raw SQL, checking existence and not the active flag, and raising
79
+ * the 422 codes feature 017 superseded with the validator's uniform 409.
80
+ * Deleting that branch is the D-87 drain; making the argument required is
81
+ * what stops it coming back as an omission.
82
+ */
83
+ private readonly dictionaryValidator;
84
+ /**
85
+ * "Who is still attributed to this channel?", asked of the modules that
86
+ * record it (feature 075, D-87). Required for the same reason: the absent
87
+ * form of a delete guard is an open one.
88
+ */
89
+ private readonly attributionRegistry;
90
+ /**
91
+ * Which table holds each channel-scoped entity type's memberships, said by
92
+ * the module that owns that entity type (feature 120, FR-015).
93
+ *
94
+ * This class held its own copy of the platform's nine-entry map until
95
+ * D-226, justified in a comment as *"kept locally to avoid a circular
96
+ * import between the two services"*. That reason had been stale since
97
+ * feature 072's T019 moved `SalesChannelMembershipService` into the kernel:
98
+ * the platform names `packages/modules/sales_channels` in zero import
99
+ * specifiers and D-52/D-53 forbid it ever doing so. The copy was the worse
100
+ * of the two, because {@link findOrphansForChannel} runs a `select` against
101
+ * **all nine** tables on the channel-**delete** path, inside a module the
102
+ * platform refuses to switch off — so on an instance without `cms` deleting
103
+ * a channel failed on a relation that is not there.
104
+ *
105
+ * Resolved **through the container** rather than imported, by the name a
106
+ * composition root contributes off `composeSalesChannelsKernel`. A
107
+ * container resolution is not a module-graph edge, so there is nothing for
108
+ * a cycle to close; and the registry is a **kernel** registration rather
109
+ * than another module's port, so it puts nothing in this module's
110
+ * `dependencies` and makes no activation control a dead switch.
111
+ */
112
+ private readonly bridgeRegistry;
113
+ private readonly auditLogService?;
114
+ /**
115
+ * The invalidating half of the channel cache, narrowed to what a writer
116
+ * needs (D-93). A service that can only invalidate cannot seed the cache
117
+ * from the write path, which is the reader's job.
118
+ */
119
+ private readonly cache?;
120
+ /**
121
+ * Used by `setDefault` only, which is a Command (Principle XIII) rather than
122
+ * a hand-audited write like the rest of this class. Still optional — and
123
+ * `setDefault` refuses outright when it is missing, so the absence can never
124
+ * become an unaudited flag move.
125
+ */
126
+ private readonly commandBus?;
127
+ constructor(emFactory: () => EntityManager, eventBus: EventBus,
128
+ /**
129
+ * Required, and it was not (issue #251's shape, feature 075's occasion).
130
+ * Both roots have supplied it since feature 072 wave 2, so the absent
131
+ * branch was only ever run by tests — and what ran there was a hand-written
132
+ * `select "code" from "languages" / "currencies"`, two other modules' tables
133
+ * named in raw SQL, checking existence and not the active flag, and raising
134
+ * the 422 codes feature 017 superseded with the validator's uniform 409.
135
+ * Deleting that branch is the D-87 drain; making the argument required is
136
+ * what stops it coming back as an omission.
137
+ */
138
+ dictionaryValidator: DictionaryValidator,
139
+ /**
140
+ * "Who is still attributed to this channel?", asked of the modules that
141
+ * record it (feature 075, D-87). Required for the same reason: the absent
142
+ * form of a delete guard is an open one.
143
+ */
144
+ attributionRegistry: SalesChannelAttributionRegistryPort,
145
+ /**
146
+ * Which table holds each channel-scoped entity type's memberships, said by
147
+ * the module that owns that entity type (feature 120, FR-015).
148
+ *
149
+ * This class held its own copy of the platform's nine-entry map until
150
+ * D-226, justified in a comment as *"kept locally to avoid a circular
151
+ * import between the two services"*. That reason had been stale since
152
+ * feature 072's T019 moved `SalesChannelMembershipService` into the kernel:
153
+ * the platform names `packages/modules/sales_channels` in zero import
154
+ * specifiers and D-52/D-53 forbid it ever doing so. The copy was the worse
155
+ * of the two, because {@link findOrphansForChannel} runs a `select` against
156
+ * **all nine** tables on the channel-**delete** path, inside a module the
157
+ * platform refuses to switch off — so on an instance without `cms` deleting
158
+ * a channel failed on a relation that is not there.
159
+ *
160
+ * Resolved **through the container** rather than imported, by the name a
161
+ * composition root contributes off `composeSalesChannelsKernel`. A
162
+ * container resolution is not a module-graph edge, so there is nothing for
163
+ * a cycle to close; and the registry is a **kernel** registration rather
164
+ * than another module's port, so it puts nothing in this module's
165
+ * `dependencies` and makes no activation control a dead switch.
166
+ */
167
+ bridgeRegistry: ChannelBridgeRead, auditLogService?: AuditPort | undefined,
168
+ /**
169
+ * The invalidating half of the channel cache, narrowed to what a writer
170
+ * needs (D-93). A service that can only invalidate cannot seed the cache
171
+ * from the write path, which is the reader's job.
172
+ */
173
+ cache?: SalesChannelsCacheInvalidation | undefined,
174
+ /**
175
+ * Used by `setDefault` only, which is a Command (Principle XIII) rather than
176
+ * a hand-audited write like the rest of this class. Still optional — and
177
+ * `setDefault` refuses outright when it is missing, so the absence can never
178
+ * become an unaudited flag move.
179
+ */
180
+ commandBus?: CommandBus | undefined);
181
+ getByCode(code: string): Promise<SalesChannel | null>;
182
+ getById(id: string): Promise<SalesChannel | null>;
183
+ list(options?: SalesChannelsServiceListOptions): Promise<{
184
+ items: SalesChannel[];
185
+ page: number;
186
+ pageSize: number;
187
+ total: number;
188
+ }>;
189
+ create(body: SalesChannelCreateBody, context?: AdminAuditContext): Promise<SalesChannel>;
190
+ update(code: string, body: SalesChannelUpdateBody, expectedVersion: number, context?: AdminAuditContext): Promise<SalesChannel>;
191
+ deactivate(code: string, context?: AdminAuditContext): Promise<SalesChannel>;
192
+ activate(code: string, context?: AdminAuditContext): Promise<SalesChannel>;
193
+ /**
194
+ * Move the `system_default` flag to `code` — feature 072 / D-51.
195
+ *
196
+ * The write itself is a Command, so the audit row, the demote-then-promote
197
+ * ordering and the transaction all live in `commands/set-default.command.ts`.
198
+ * What belongs here is the 404 for a code nobody has, produced before the
199
+ * transaction so an operator's typo is not an aborted transaction, and the
200
+ * cache drop below.
201
+ *
202
+ * Unlike the rest of this class it writes no audit row of its own: the
203
+ * Command Bus writes exactly one, and a second would be the double-audit the
204
+ * coverage check exists to catch.
205
+ */
206
+ setDefault(code: string): Promise<SetSystemDefaultChannelResult>;
207
+ delete(code: string, options?: DeleteOptions, context?: AdminAuditContext): Promise<void>;
208
+ private requireByCode;
209
+ private assertLanguagesValid;
210
+ private assertCurrenciesValid;
211
+ private validateLanguage;
212
+ private validateCurrency;
213
+ /**
214
+ * Read through the kernel's own entity rather than the raw statement this
215
+ * replaces (feature 075, D-87). `sales_channels` is the kernel's table since
216
+ * feature 072 moved the resolution machinery there, and a module relating
217
+ * into the kernel by ORM is the sanctioned access — it was the SQL, not the
218
+ * read, that crossed a boundary nothing could see. It reads through the
219
+ * caller's `em` on purpose: this runs inside the delete path, so the
220
+ * resolver's own fork would not see that path's uncommitted state.
221
+ */
222
+ private requireSystemDefaultId;
223
+ /**
224
+ * For every M:N bridge, find the entities whose ONLY channel membership is
225
+ * `channelId`. Returned shape is the (entityType, entityId) pair so the
226
+ * delete path can either refuse with a sample list or rebind to Default.
227
+ */
228
+ private findOrphansForChannel;
229
+ private rebindOrphansToDefault;
230
+ private snapshot;
231
+ private audit;
232
+ /**
233
+ * Drop the cache, then announce (D-93).
234
+ *
235
+ * The drop runs **after the flush**, so a concurrent read cannot re-pin the
236
+ * pre-commit row, and **before the emit**, so every subscriber re-reads
237
+ * post-invalidation state. The count is deliberately unread:
238
+ * `invalidateAfterWrite` answers `null` for an unreachable shared layer, and
239
+ * the row is written and audited by the time we are here, so there is nothing
240
+ * this method could truthfully do with it. Reads stay correct meanwhile — the
241
+ * cache bypasses the marked prefix until a later drop succeeds.
242
+ */
243
+ private emitIdentityChanged;
244
+ /** Same seam as {@link emitIdentityChanged}; see its comment for the ordering. */
245
+ private emitLifecycleChanged;
246
+ }
247
+ //# sourceMappingURL=sales-channels.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sales-channels.service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/sales-channels.service.ts"],"names":[],"mappings":"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"}