@endora-commerce/mod-shopping-lists 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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -0
  3. package/dist/backend/entities/shopping-list-item.entity.d.ts +20 -0
  4. package/dist/backend/entities/shopping-list-item.entity.d.ts.map +1 -0
  5. package/dist/backend/entities/shopping-list-item.entity.js +70 -0
  6. package/dist/backend/entities/shopping-list-item.entity.js.map +1 -0
  7. package/dist/backend/entities/shopping-list.entity.d.ts +22 -0
  8. package/dist/backend/entities/shopping-list.entity.d.ts.map +1 -0
  9. package/dist/backend/entities/shopping-list.entity.js +68 -0
  10. package/dist/backend/entities/shopping-list.entity.js.map +1 -0
  11. package/dist/backend/index.d.ts +87 -0
  12. package/dist/backend/index.d.ts.map +1 -0
  13. package/dist/backend/index.js +74 -0
  14. package/dist/backend/index.js.map +1 -0
  15. package/dist/backend/plugin.d.ts +42 -0
  16. package/dist/backend/plugin.d.ts.map +1 -0
  17. package/dist/backend/plugin.js +15 -0
  18. package/dist/backend/plugin.js.map +1 -0
  19. package/dist/backend/routes.d.ts +19 -0
  20. package/dist/backend/routes.d.ts.map +1 -0
  21. package/dist/backend/routes.js +136 -0
  22. package/dist/backend/routes.js.map +1 -0
  23. package/dist/backend/services/shopping-list-service.d.ts +134 -0
  24. package/dist/backend/services/shopping-list-service.d.ts.map +1 -0
  25. package/dist/backend/services/shopping-list-service.js +331 -0
  26. package/dist/backend/services/shopping-list-service.js.map +1 -0
  27. package/dist/manifest.d.ts +191 -0
  28. package/dist/manifest.d.ts.map +1 -0
  29. package/dist/manifest.js +105 -0
  30. package/dist/manifest.js.map +1 -0
  31. package/dist/migrations/20260426T135443_shopping_lists_init.d.ts +18 -0
  32. package/dist/migrations/20260426T135443_shopping_lists_init.d.ts.map +1 -0
  33. package/dist/migrations/20260426T135443_shopping_lists_init.js +52 -0
  34. package/dist/migrations/20260426T135443_shopping_lists_init.js.map +1 -0
  35. package/dist/migrations/20260611T140418_shopping_lists_default.d.ts +16 -0
  36. package/dist/migrations/20260611T140418_shopping_lists_default.d.ts.map +1 -0
  37. package/dist/migrations/20260611T140418_shopping_lists_default.js +31 -0
  38. package/dist/migrations/20260611T140418_shopping_lists_default.js.map +1 -0
  39. package/dist/migrations/index.d.ts +28 -0
  40. package/dist/migrations/index.d.ts.map +1 -0
  41. package/dist/migrations/index.js +31 -0
  42. package/dist/migrations/index.js.map +1 -0
  43. package/docs/shopping_lists.md +70 -0
  44. package/i18n/en.json +4 -0
  45. package/i18n/pl.json +4 -0
  46. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ <!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
2
+
3
+ # @endora-commerce/mod-shopping-lists
4
+
5
+ Customer-owned saved shopping lists.
6
+
7
+ ## What this is
8
+
9
+ An **Endora Commerce module package**. Its module id is `shopping_lists` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
10
+
11
+ A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
12
+
13
+ ## Entry points
14
+
15
+ | Import | Contents |
16
+ | --- | --- |
17
+ | `@endora-commerce/mod-shopping-lists` | the module manifest — its id, version, dependencies, settings and activation |
18
+ | `@endora-commerce/mod-shopping-lists/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
19
+ | `@endora-commerce/mod-shopping-lists/migrations` | the module’s own schema migrations, in the order the platform runs them |
20
+
21
+ ## Depends on
22
+
23
+ Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
24
+
25
+ **Endora packages**
26
+
27
+ - `@endora-commerce/contracts`
28
+ - `@endora-commerce/platform`
29
+
30
+ **Third-party**
31
+
32
+ - `@mikro-orm/core` ^6
33
+ - `@mikro-orm/migrations` ^6
34
+ - `@mikro-orm/postgresql` ^6
35
+ - `fastify` ^5
36
+
37
+ ## What the tarball carries
38
+
39
+ - `dist/` — the compiled JavaScript and its type declarations
40
+ - `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
41
+ - `docs/` — the package’s own pages in the Endora Commerce documentation site
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pnpm add @endora-commerce/mod-shopping-lists
47
+ ```
48
+
49
+ ## Licence
50
+
51
+ MIT — the text is in `LICENSE`, beside this file.
@@ -0,0 +1,20 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * ShoppingListItem — one (product, optional variant, quantity, optional note)
4
+ * row on a ShoppingList. The list itself is the FK target; the FK to
5
+ * `products` is intentionally a plain uuid column (no CASCADE) so a
6
+ * product archive doesn't wipe historical list rows — instead we surface
7
+ * the archived row at conversion time and let the caller skip it.
8
+ */
9
+ export declare class ShoppingListItem {
10
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'variantId' | 'note';
11
+ id: string;
12
+ shoppingListId: string;
13
+ productId: string;
14
+ variantId?: string | null;
15
+ quantity: number;
16
+ note?: string | null;
17
+ createdAt: Date;
18
+ updatedAt: Date;
19
+ }
20
+ //# sourceMappingURL=shopping-list-item.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopping-list-item.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/shopping-list-item.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;;;GAMG;AACH,qBAEa,gBAAgB;IAC3B,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;IAG1E,EAAE,EAAE,MAAM,CAAgB;IAI1B,cAAc,EAAG,MAAM,CAAC;IAIxB,SAAS,EAAG,MAAM,CAAC;IAGnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,QAAQ,EAAG,MAAM,CAAC;IAGlB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
@@ -0,0 +1,70 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * ShoppingListItem — one (product, optional variant, quantity, optional note)
15
+ * row on a ShoppingList. The list itself is the FK target; the FK to
16
+ * `products` is intentionally a plain uuid column (no CASCADE) so a
17
+ * product archive doesn't wipe historical list rows — instead we surface
18
+ * the archived row at conversion time and let the caller skip it.
19
+ */
20
+ let ShoppingListItem = class ShoppingListItem {
21
+ [OptionalProps];
22
+ id = randomUUID();
23
+ shoppingListId;
24
+ productId;
25
+ variantId;
26
+ quantity;
27
+ note;
28
+ createdAt = new Date();
29
+ updatedAt = new Date();
30
+ };
31
+ __decorate([
32
+ PrimaryKey({ type: 'uuid' }),
33
+ __metadata("design:type", String)
34
+ ], ShoppingListItem.prototype, "id", void 0);
35
+ __decorate([
36
+ Property({ type: 'uuid' }),
37
+ Index(),
38
+ __metadata("design:type", String)
39
+ ], ShoppingListItem.prototype, "shoppingListId", void 0);
40
+ __decorate([
41
+ Property({ type: 'uuid' }),
42
+ Index(),
43
+ __metadata("design:type", String)
44
+ ], ShoppingListItem.prototype, "productId", void 0);
45
+ __decorate([
46
+ Property({ type: 'uuid', nullable: true }),
47
+ __metadata("design:type", Object)
48
+ ], ShoppingListItem.prototype, "variantId", void 0);
49
+ __decorate([
50
+ Property({ type: 'integer' }),
51
+ __metadata("design:type", Number)
52
+ ], ShoppingListItem.prototype, "quantity", void 0);
53
+ __decorate([
54
+ Property({ type: 'text', nullable: true }),
55
+ __metadata("design:type", Object)
56
+ ], ShoppingListItem.prototype, "note", void 0);
57
+ __decorate([
58
+ Property({ type: 'datetime', onCreate: () => new Date() }),
59
+ __metadata("design:type", Date)
60
+ ], ShoppingListItem.prototype, "createdAt", void 0);
61
+ __decorate([
62
+ Property({ type: 'datetime', onUpdate: () => new Date() }),
63
+ __metadata("design:type", Date)
64
+ ], ShoppingListItem.prototype, "updatedAt", void 0);
65
+ ShoppingListItem = __decorate([
66
+ GlobalEntity(),
67
+ Entity({ tableName: 'shopping_list_items' })
68
+ ], ShoppingListItem);
69
+ export { ShoppingListItem };
70
+ //# sourceMappingURL=shopping-list-item.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopping-list-item.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/shopping-list-item.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;GAMG;AAGI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,CAAC,aAAa,CAAC,CAA2D;IAG1E,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,cAAc,CAAU;IAIxB,SAAS,CAAU;IAGnB,SAAS,CAAiB;IAG1B,QAAQ,CAAU;IAGlB,IAAI,CAAiB;IAGrB,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAxBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;4CACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;wDACgB;AAIxB;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;mDACW;AAGnB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDACjB;AAG1B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;kDACZ;AAGlB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACtB;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;mDAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;mDAAc;AA3BlB,gBAAgB;IAF5B,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC;GAChC,gBAAgB,CA4B5B"}
@@ -0,0 +1,22 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * ShoppingList — a per-customer named bucket of products. The (customer,
4
+ * organization) pair scopes ownership; sharing inside an organization is
5
+ * intentionally out of scope for the MVP.
6
+ */
7
+ export declare class ShoppingList {
8
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'isDefault';
9
+ id: string;
10
+ organizationId: string;
11
+ customerAccountId: string;
12
+ name: string;
13
+ /**
14
+ * The customer's default shopping list. At most one list per
15
+ * (organization, customer) carries this flag; the storefront "add to
16
+ * shopping list" affordances target it.
17
+ */
18
+ isDefault: boolean;
19
+ createdAt: Date;
20
+ updatedAt: Date;
21
+ }
22
+ //# sourceMappingURL=shopping-list.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopping-list.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/shopping-list.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;GAIG;AACH,qBAEa,YAAY;IACvB,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IAGjE,EAAE,EAAE,MAAM,CAAgB;IAI1B,cAAc,EAAG,MAAM,CAAC;IAIxB,iBAAiB,EAAG,MAAM,CAAC;IAG3B,IAAI,EAAG,MAAM,CAAC;IAEd;;;;OAIG;IAEH,SAAS,EAAE,OAAO,CAAS;IAG3B,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
@@ -0,0 +1,68 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { OrgScoped } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * ShoppingList — a per-customer named bucket of products. The (customer,
15
+ * organization) pair scopes ownership; sharing inside an organization is
16
+ * intentionally out of scope for the MVP.
17
+ */
18
+ let ShoppingList = class ShoppingList {
19
+ [OptionalProps];
20
+ id = randomUUID();
21
+ organizationId;
22
+ customerAccountId;
23
+ name;
24
+ /**
25
+ * The customer's default shopping list. At most one list per
26
+ * (organization, customer) carries this flag; the storefront "add to
27
+ * shopping list" affordances target it.
28
+ */
29
+ isDefault = false;
30
+ createdAt = new Date();
31
+ updatedAt = new Date();
32
+ };
33
+ __decorate([
34
+ PrimaryKey({ type: 'uuid' }),
35
+ __metadata("design:type", String)
36
+ ], ShoppingList.prototype, "id", void 0);
37
+ __decorate([
38
+ Property({ type: 'uuid' }),
39
+ Index(),
40
+ __metadata("design:type", String)
41
+ ], ShoppingList.prototype, "organizationId", void 0);
42
+ __decorate([
43
+ Property({ type: 'uuid' }),
44
+ Index(),
45
+ __metadata("design:type", String)
46
+ ], ShoppingList.prototype, "customerAccountId", void 0);
47
+ __decorate([
48
+ Property({ type: 'string', length: 160 }),
49
+ __metadata("design:type", String)
50
+ ], ShoppingList.prototype, "name", void 0);
51
+ __decorate([
52
+ Property({ type: 'boolean' }),
53
+ __metadata("design:type", Boolean)
54
+ ], ShoppingList.prototype, "isDefault", void 0);
55
+ __decorate([
56
+ Property({ type: 'datetime', onCreate: () => new Date() }),
57
+ __metadata("design:type", Date)
58
+ ], ShoppingList.prototype, "createdAt", void 0);
59
+ __decorate([
60
+ Property({ type: 'datetime', onUpdate: () => new Date() }),
61
+ __metadata("design:type", Date)
62
+ ], ShoppingList.prototype, "updatedAt", void 0);
63
+ ShoppingList = __decorate([
64
+ OrgScoped(),
65
+ Entity({ tableName: 'shopping_lists' })
66
+ ], ShoppingList);
67
+ export { ShoppingList };
68
+ //# sourceMappingURL=shopping-list.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopping-list.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/shopping-list.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;GAIG;AAGI,IAAM,YAAY,GAAlB,MAAM,YAAY;IACvB,CAAC,aAAa,CAAC,CAAkD;IAGjE,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,cAAc,CAAU;IAIxB,iBAAiB,CAAU;IAG3B,IAAI,CAAU;IAEd;;;;OAIG;IAEH,SAAS,GAAY,KAAK,CAAC;IAG3B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AA1BC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;oDACgB;AAIxB;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;uDACmB;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;0CAC5B;AAQd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;+CACH;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;+CAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;+CAAc;AA7BlB,YAAY;IAFxB,SAAS,EAAE;IACX,MAAM,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;GAC3B,YAAY,CA8BxB"}
@@ -0,0 +1,87 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { CartWritePort, RfqCustomerPort } from '@endora-commerce/contracts';
3
+ import type { AuditPort } from '@endora-commerce/platform/kernel';
4
+ import type { ModuleContext } from '@endora-commerce/platform/kernel';
5
+ import { shoppingListsModule, type ShoppingListsModuleOptions } from './plugin.js';
6
+ import { ShoppingListService } from './services/shopping-list-service.js';
7
+ import { ShoppingListItem } from './entities/shopping-list-item.entity.js';
8
+ import { ShoppingList } from './entities/shopping-list.entity.js';
9
+ /**
10
+ * `shopping_lists` — six optional options that decided which routes exist
11
+ * (feature 072, wave 3, T133).
12
+ *
13
+ * `requireAdmin`, `auditLog`, `getOrderService` and `resolveOneClickEnabled`
14
+ * did not merely change behaviour when omitted: each gates a *route group*, so
15
+ * absence silently produced a module with fewer endpoints. Both compositions
16
+ * passed all four, so the reduced shape was never anyone's deployment — but it
17
+ * was reachable by forgetting an argument, which is the thing these conversions
18
+ * remove.
19
+ *
20
+ * T139 took most of that with it. Six of those options — and three more —
21
+ * existed only to serve the `quick_order` surfaces this module mounted, and
22
+ * they moved to that module when it became a lifecycle participant of its own.
23
+ * What is left is a module with one route file and one service.
24
+ *
25
+ * One name stays a composition's, and it is a genuine cross-module reach this
26
+ * module must not make directly: the RFQ service it converts a list into.
27
+ *
28
+ * The third is gone. `exposeShoppingListService` was a contribution pointing
29
+ * *outward*, and T136 inverted it: `carts` owns the bridge now and this module
30
+ * provides `shoppingListService` as an ordinary port, which is what the comment
31
+ * here predicted would happen when `carts` converted.
32
+ *
33
+ * The cart write surface is read as a port for the same reason — and deleting
34
+ * the degraded copy this module used to build is the substantive half of that
35
+ * change, not the tidy half.
36
+ *
37
+ * Feature 075 Phase C finished what those port names started. Both service
38
+ * resolutions were *typed* by importing `carts`' and `quote_requests`'
39
+ * classes, so the container name was decoupled and the type was not; they name
40
+ * `CartWritePort` and `RfqCustomerPort` now. The third edge was the real one:
41
+ * `ShoppingListService` queried `catalog`'s `products` table directly, which no
42
+ * gate can reach, so a list kept accepting and converting items out of a
43
+ * `catalog` an operator had switched off.
44
+ */
45
+ /** What `shopping_lists` resolves from the container, and the names it owns. */
46
+ export interface ShoppingListsCradle {
47
+ readonly emFactory: () => EntityManager;
48
+ readonly auditLogService: AuditPort;
49
+ readonly requireCustomer: ShoppingListsModuleOptions['requireCustomer'];
50
+ readonly customerContextResolver: ShoppingListsModuleOptions['resolveCustomerContext'];
51
+ readonly rfqService: RfqCustomerPort;
52
+ /**
53
+ * The composed cart write surface. Until T136 this module built its own,
54
+ * degraded copy — no pricing, no approval re-arm, no audit row and no
55
+ * recompute-cache invalidation on any line added through save-to-list.
56
+ */
57
+ readonly cartWritePort: CartWritePort;
58
+ /** This module's one service; the subscription below reads it per event. */
59
+ readonly shoppingListService: ShoppingListService;
60
+ /** Contribution outward: `carts` reads the service through this until it converts. */
61
+ readonly shoppingListServiceSink: (service: ShoppingListService) => void;
62
+ readonly shoppingLists: ReturnType<typeof shoppingListsModule>;
63
+ }
64
+ export declare function registerModule(ctx: ModuleContext): void;
65
+ /**
66
+ * The module's persisted entity classes, on the `./backend` subpath, as one
67
+ * array and **no named class export** (D-168).
68
+ *
69
+ * This is the shape the platform reads when the package is *installed*: the
70
+ * boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
71
+ * and the static declaration reader (`scripts/lib/package-declarations.ts`),
72
+ * which is the third source of `check:module-boundary`'s `table→owner` map and
73
+ * the package pass of `check-entity-tenant-classification`. A missing array is
74
+ * answered with `[]` — zero entities registered, no error anywhere.
75
+ */
76
+ export declare const entities: (typeof ShoppingList | typeof ShoppingListItem)[];
77
+ /**
78
+ * The service type the `shoppingListServiceSink` contribution carries.
79
+ *
80
+ * The root receives the instance this module builds and hands it to `carts`'
81
+ * conversion bridge, so it has to name the shape. A relative specifier into a
82
+ * package's internal file is TS6059 under `backend/tsconfig.build.json`'s
83
+ * `rootDir`, `import type` included, so the name has to be on the published
84
+ * subpath.
85
+ */
86
+ export type { ShoppingListService } from './services/shopping-list-service.js';
87
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAA0B,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACzG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAGtE,OAAO,EAAE,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,gFAAgF;AAChF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,0BAA0B,CAAC,iBAAiB,CAAC,CAAC;IACxE,QAAQ,CAAC,uBAAuB,EAAE,0BAA0B,CAAC,wBAAwB,CAAC,CAAC;IACvF,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,sFAAsF;IACtF,QAAQ,CAAC,uBAAuB,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzE,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;CAChE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAsEvD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,mDAGpB,CAAC;AAEF;;;;;;;;GAQG;AACH,YAAY,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { lazyPort } from '@endora-commerce/platform/kernel';
2
+ import { shoppingListsModule } from './plugin.js';
3
+ import { ShoppingListService } from './services/shopping-list-service.js';
4
+ import { ShoppingListItem } from './entities/shopping-list-item.entity.js';
5
+ import { ShoppingList } from './entities/shopping-list.entity.js';
6
+ export function registerModule(ctx) {
7
+ ctx.di.register({
8
+ // Contribution point, defaulted to a no-op: a composition with no `carts`
9
+ // save-to-list bridge simply never asks for the service.
10
+ shoppingListServiceSink: ctx
11
+ .asFunction(() => () => undefined)
12
+ .singleton(),
13
+ shoppingListService: ctx
14
+ .asFunction(({ emFactory }) =>
15
+ // Three published ports, never captured: the proxies resolve per
16
+ // call, so a switched-off owner answers 503 `MODULE_DISABLED` at the
17
+ // call rather than through a gate frozen at composition time.
18
+ // `cartWritePort` replaces `cartService`, which handed out the class;
19
+ // it carries the four operations a caller outside `carts` has any
20
+ // business making.
21
+ new ShoppingListService(emFactory, lazyPort(ctx, 'cartWritePort'), lazyPort(ctx, 'rfqService'), lazyPort(ctx, 'catalogProductReadPort'),
22
+ // Issue #259 — the channel assortment gate on the save seam. A
23
+ // kernel registration, not a module's, so there is no edge to
24
+ // declare here.
25
+ lazyPort(ctx, 'salesChannelMembershipPort')))
26
+ .singleton(),
27
+ shoppingLists: ctx
28
+ .asFunction(({ emFactory, shoppingListService }) => shoppingListsModule({
29
+ emFactory,
30
+ shoppingListService,
31
+ requireCustomer: (req, reply) => ctx.cradle().requireCustomer(req, reply),
32
+ resolveCustomerContext: (req) => ctx.cradle().customerContextResolver(req),
33
+ exposeShoppingListService: (service) => {
34
+ ctx.cradle().shoppingListServiceSink(service);
35
+ },
36
+ }))
37
+ .singleton(),
38
+ });
39
+ /**
40
+ * Eagerly provision a "Default" shopping list when an org-attached customer is
41
+ * created — registration, admin direct-create, invitation accept — so the list
42
+ * exists immediately instead of only on first storefront read. `ensureDefault`
43
+ * is idempotent, so a redundant event is harmless.
44
+ *
45
+ * It was a bare `eventBus.on` inside the route registrar, so a switched-off
46
+ * `shopping_lists` still created rows in its own tables while every route that
47
+ * could show them refused (issue #107).
48
+ */
49
+ ctx.subscribe('customer_account.created.v1', async (payload) => {
50
+ const { customerAccountId, organizationId } = payload;
51
+ await ctx
52
+ .cradle()
53
+ .shoppingListService.ensureDefault({ customerAccountId, organizationId });
54
+ });
55
+ ctx.routes(async (app) => {
56
+ await ctx.cradle().shoppingLists(app);
57
+ });
58
+ }
59
+ /**
60
+ * The module's persisted entity classes, on the `./backend` subpath, as one
61
+ * array and **no named class export** (D-168).
62
+ *
63
+ * This is the shape the platform reads when the package is *installed*: the
64
+ * boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
65
+ * and the static declaration reader (`scripts/lib/package-declarations.ts`),
66
+ * which is the third source of `check:module-boundary`'s `table→owner` map and
67
+ * the package pass of `check-entity-tenant-classification`. A missing array is
68
+ * answered with `[]` — zero entities registered, no error anywhere.
69
+ */
70
+ export const entities = [
71
+ ShoppingListItem,
72
+ ShoppingList,
73
+ ];
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAAmC,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AA2DlE,MAAM,UAAU,cAAc,CAAC,GAAkB;IAC/C,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC;QACd,0EAA0E;QAC1E,yDAAyD;QACzD,uBAAuB,EAAE,GAAG;aACzB,UAAU,CAAC,GAAmD,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;aACjF,SAAS,EAAE;QAEd,mBAAmB,EAAE,GAAG;aACrB,UAAU,CACT,CAAC,EAAE,SAAS,EAAuB,EAAE,EAAE;QACrC,iEAAiE;QACjE,qEAAqE;QACrE,8DAA8D;QAC9D,sEAAsE;QACtE,kEAAkE;QAClE,mBAAmB;QACnB,IAAI,mBAAmB,CACrB,SAAS,EACT,QAAQ,CAAgB,GAAG,EAAE,eAAe,CAAC,EAC7C,QAAQ,CAAkB,GAAG,EAAE,YAAY,CAAC,EAC5C,QAAQ,CAAyB,GAAG,EAAE,wBAAwB,CAAC;QAC/D,+DAA+D;QAC/D,8DAA8D;QAC9D,gBAAgB;QAChB,QAAQ,CAA6B,GAAG,EAAE,4BAA4B,CAAC,CACxE,CACJ;aACA,SAAS,EAAE;QAEd,aAAa,EAAE,GAAG;aACf,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,mBAAmB,EAAuB,EAAE,EAAE,CACtE,mBAAmB,CAAC;YAClB,SAAS;YACT,mBAAmB;YACnB,eAAe,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAC9B,GAAG,CAAC,MAAM,EAAuB,CAAC,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC;YAC/D,sBAAsB,EAAE,CAAC,GAAmB,EAAE,EAAE,CAC9C,GAAG,CAAC,MAAM,EAAuB,CAAC,uBAAuB,CAAC,GAAG,CAAC;YAChE,yBAAyB,EAAE,CAAC,OAAO,EAAE,EAAE;gBACrC,GAAG,CAAC,MAAM,EAAuB,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;YACrE,CAAC;SACF,CAAC,CACH;aACA,SAAS,EAAE;KACf,CAAC,CAAC;IAEH;;;;;;;;;OASG;IACH,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC7D,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,GAAG,OAG7C,CAAC;QACF,MAAM,GAAG;aACN,MAAM,EAAuB;aAC7B,mBAAmB,CAAC,aAAa,CAAC,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,GAAG,CAAC,MAAM,EAAuB,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,gBAAgB;IAChB,YAAY;CACb,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { FastifyInstance, FastifyRequest } from 'fastify';
2
+ import type { EntityManager } from '@mikro-orm/postgresql';
3
+ import type { ShoppingListService } from './services/shopping-list-service.js';
4
+ /**
5
+ * Composition root for `shopping_lists`.
6
+ *
7
+ * It used to be the composition root for `quick_order` as well — two lifecycle
8
+ * participants behind one factory, so neither had presence of its own. Feature
9
+ * 072 (T139) moved that module's five route groups and four services into its
10
+ * own `backend.ts`, where three nested `if (options.…)` conditionals that
11
+ * decided which of its endpoints existed became unconditional registrations.
12
+ *
13
+ * `rfqService` is injected (built by the quote_requests module) so the
14
+ * shopping-list "convert to RFQ" flow uses the one-call `createForCustomer`
15
+ * API, with revisions, events and notifications wired in (feature 008).
16
+ */
17
+ export interface ShoppingListsModuleOptions {
18
+ emFactory: () => EntityManager;
19
+ /**
20
+ * The module's one service, built in `backend.ts` (issue #107).
21
+ *
22
+ * It used to be constructed here, inside the route registrar, which is why the
23
+ * `customer_account.created.v1` reaction had to be a bare `eventBus.on`: this
24
+ * was the only place holding the instance. It is a container registration now,
25
+ * so the subscription can live at the seam that gates it.
26
+ */
27
+ shoppingListService: ShoppingListService;
28
+ requireCustomer: (req: FastifyRequest, reply: unknown) => Promise<void>;
29
+ resolveCustomerContext: (req: FastifyRequest) => {
30
+ customerAccountId: string;
31
+ organizationId: string;
32
+ };
33
+ /**
34
+ * Feature 027 — exposes the ShoppingListService back to commerceModule so
35
+ * its `/api/v1/cart/items/:itemId/save-to-shopping-list` endpoint can
36
+ * push lines into a list (cross-module call through this public
37
+ * service, not via direct entity access).
38
+ */
39
+ exposeShoppingListService?: (service: ShoppingListService) => void;
40
+ }
41
+ export declare function shoppingListsModule(options: ShoppingListsModuleOptions): (app: FastifyInstance) => Promise<void>;
42
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/backend/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAG/E;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B;;;;;;;OAOG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,eAAe,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,sBAAsB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK;QAC/C,iBAAiB,EAAE,MAAM,CAAC;QAC1B,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAOpE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,IACvD,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CAWnD"}
@@ -0,0 +1,15 @@
1
+ import { registerShoppingListRoutes } from './routes.js';
2
+ export function shoppingListsModule(options) {
3
+ return async (app) => {
4
+ const shoppingListService = options.shoppingListService;
5
+ if (options.exposeShoppingListService)
6
+ options.exposeShoppingListService(shoppingListService);
7
+ await registerShoppingListRoutes(app, {
8
+ service: shoppingListService,
9
+ emFactory: options.emFactory,
10
+ requireCustomer: options.requireCustomer,
11
+ resolveCustomerContext: options.resolveCustomerContext,
12
+ });
13
+ };
14
+ }
15
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/backend/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AA+CzD,MAAM,UAAU,mBAAmB,CAAC,OAAmC;IACrE,OAAO,KAAK,EAAE,GAAoB,EAAiB,EAAE;QACnD,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QACxD,IAAI,OAAO,CAAC,yBAAyB;YAAE,OAAO,CAAC,yBAAyB,CAAC,mBAAmB,CAAC,CAAC;QAE9F,MAAM,0BAA0B,CAAC,GAAG,EAAE;YACpC,OAAO,EAAE,mBAAmB;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB;SACvD,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { FastifyInstance, FastifyRequest } from 'fastify';
2
+ import type { EntityManager } from '@mikro-orm/postgresql';
3
+ import type { ShoppingListService } from './services/shopping-list-service.js';
4
+ /**
5
+ * Shopping list routes (T204). All endpoints require an authenticated
6
+ * customer session; ownership is enforced by the service via
7
+ * (organization_id, customer_account_id).
8
+ */
9
+ export interface ShoppingListsRoutesDeps {
10
+ service: ShoppingListService;
11
+ emFactory: () => EntityManager;
12
+ requireCustomer: (req: FastifyRequest, reply: unknown) => Promise<void>;
13
+ resolveCustomerContext: (req: FastifyRequest) => {
14
+ customerAccountId: string;
15
+ organizationId: string;
16
+ };
17
+ }
18
+ export declare function registerShoppingListRoutes(app: FastifyInstance, deps: ShoppingListsRoutesDeps): Promise<void>;
19
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/backend/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAQ/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAI/E;;;;GAIG;AAEH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,eAAe,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,sBAAsB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK;QAC/C,iBAAiB,EAAE,MAAM,CAAC;QAC1B,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA+Kf"}