@endora-commerce/mod-customer-accounts 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 +59 -0
- package/dist/admin/api/customer-groups-client.d.ts +27 -0
- package/dist/admin/api/customer-groups-client.d.ts.map +1 -0
- package/dist/admin/api/customer-groups-client.js +17 -0
- package/dist/admin/api/customer-groups-client.js.map +1 -0
- package/dist/admin/index.d.ts +33 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +38 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/CustomerGroupsPage.d.ts +18 -0
- package/dist/admin/pages/CustomerGroupsPage.d.ts.map +1 -0
- package/dist/admin/pages/CustomerGroupsPage.js +108 -0
- package/dist/admin/pages/CustomerGroupsPage.js.map +1 -0
- package/dist/backend/entities/customer-account.entity.d.ts +111 -0
- package/dist/backend/entities/customer-account.entity.d.ts.map +1 -0
- package/dist/backend/entities/customer-account.entity.js +230 -0
- package/dist/backend/entities/customer-account.entity.js.map +1 -0
- package/dist/backend/entities/customer-group.entity.d.ts +29 -0
- package/dist/backend/entities/customer-group.entity.d.ts.map +1 -0
- package/dist/backend/entities/customer-group.entity.js +70 -0
- package/dist/backend/entities/customer-group.entity.js.map +1 -0
- package/dist/backend/entities/password-reset-token.entity.d.ts +16 -0
- package/dist/backend/entities/password-reset-token.entity.d.ts.map +1 -0
- package/dist/backend/entities/password-reset-token.entity.js +59 -0
- package/dist/backend/entities/password-reset-token.entity.js.map +1 -0
- package/dist/backend/index.d.ts +144 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +407 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +26 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +35 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/services/audit-references.d.ts +22 -0
- package/dist/backend/services/audit-references.d.ts.map +1 -0
- package/dist/backend/services/audit-references.js +46 -0
- package/dist/backend/services/audit-references.js.map +1 -0
- package/dist/backend/services/customer-account-lifecycle-ports.d.ts +168 -0
- package/dist/backend/services/customer-account-lifecycle-ports.d.ts.map +1 -0
- package/dist/backend/services/customer-account-lifecycle-ports.js +420 -0
- package/dist/backend/services/customer-account-lifecycle-ports.js.map +1 -0
- package/dist/backend/services/customer-account-ports.d.ts +143 -0
- package/dist/backend/services/customer-account-ports.d.ts.map +1 -0
- package/dist/backend/services/customer-account-ports.js +422 -0
- package/dist/backend/services/customer-account-ports.js.map +1 -0
- package/dist/backend/services/customer-auth-service.d.ts +62 -0
- package/dist/backend/services/customer-auth-service.d.ts.map +1 -0
- package/dist/backend/services/customer-auth-service.js +105 -0
- package/dist/backend/services/customer-auth-service.js.map +1 -0
- package/dist/backend/services/customer-group-read-port.d.ts +24 -0
- package/dist/backend/services/customer-group-read-port.d.ts.map +1 -0
- package/dist/backend/services/customer-group-read-port.js +44 -0
- package/dist/backend/services/customer-group-read-port.js.map +1 -0
- package/dist/backend/services/customer-group-service.d.ts +21 -0
- package/dist/backend/services/customer-group-service.d.ts.map +1 -0
- package/dist/backend/services/customer-group-service.js +97 -0
- package/dist/backend/services/customer-group-service.js.map +1 -0
- package/dist/backend/services/customer-rollup-scope.d.ts +30 -0
- package/dist/backend/services/customer-rollup-scope.d.ts.map +1 -0
- package/dist/backend/services/customer-rollup-scope.js +42 -0
- package/dist/backend/services/customer-rollup-scope.js.map +1 -0
- package/dist/backend/services/password-reset-service.d.ts +15 -0
- package/dist/backend/services/password-reset-service.d.ts.map +1 -0
- package/dist/backend/services/password-reset-service.js +90 -0
- package/dist/backend/services/password-reset-service.js.map +1 -0
- package/dist/backend/services/role-service.d.ts +22 -0
- package/dist/backend/services/role-service.d.ts.map +1 -0
- package/dist/backend/services/role-service.js +83 -0
- package/dist/backend/services/role-service.js.map +1 -0
- package/dist/backend/services/two-factor-enrolments.d.ts +18 -0
- package/dist/backend/services/two-factor-enrolments.d.ts.map +1 -0
- package/dist/backend/services/two-factor-enrolments.js +2 -0
- package/dist/backend/services/two-factor-enrolments.js.map +1 -0
- package/dist/manifest.d.ts +169 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +212 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.d.ts +6 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.d.ts.map +1 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.js +25 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.js.map +1 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.d.ts +34 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.d.ts.map +1 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.js +43 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.js.map +1 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.d.ts +54 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.d.ts.map +1 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.js +97 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.js.map +1 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.d.ts +12 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.d.ts.map +1 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.js +16 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.js.map +1 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.d.ts +14 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.d.ts.map +1 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.js +18 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.js.map +1 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.d.ts +22 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.d.ts.map +1 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.js +26 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.js.map +1 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.d.ts +46 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.d.ts.map +1 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.js +97 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.js.map +1 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.d.ts +31 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.d.ts.map +1 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.js +35 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.js.map +1 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.d.ts +58 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.d.ts.map +1 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.js +133 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.js.map +1 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts +27 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts.map +1 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.js +44 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.js.map +1 -0
- package/dist/migrations/index.d.ts +36 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +47 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/customer_accounts.md +38 -0
- package/i18n/en.json +30 -0
- package/i18n/pl.json +30 -0
- package/package.json +94 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* D-178 — `customer_accounts.organization_id` becomes `NOT NULL`.
|
|
4
|
+
*
|
|
5
|
+
* The column was relaxed by `20260611T140351_customer_accounts_organization_optional`
|
|
6
|
+
* for feature 026 US2 ("Customer accounts may exist without an Organization"), a
|
|
7
|
+
* design feature 051 replaced and D-178 confirms is dead: every transacting
|
|
8
|
+
* customer is backed by an Organization, an individual by a single-member
|
|
9
|
+
* **personal** one, and there is no "no-organization" scoping path
|
|
10
|
+
* (Constitution XI).
|
|
11
|
+
*
|
|
12
|
+
* **The constraint is the only refusal available.** MikroORM applies its tenant
|
|
13
|
+
* filter to `SELECT` / `UPDATE` / `DELETE` and not to `INSERT`, so no guard can
|
|
14
|
+
* stop a tenant-less account being written; the column can.
|
|
15
|
+
*
|
|
16
|
+
* ## Provision, then count, then refuse — never delete
|
|
17
|
+
*
|
|
18
|
+
* These rows are customer logins: a person's credentials, the owner of their
|
|
19
|
+
* order history and the parent of their address book. A migration that deleted
|
|
20
|
+
* one to satisfy a constraint would be deleting a customer, so this one
|
|
21
|
+
* provisions instead and raises on whatever it could not provision.
|
|
22
|
+
*
|
|
23
|
+
* Feature 051's backfill
|
|
24
|
+
* (`organizations/20260717T151403_organizations_personal_organizations`) ran the
|
|
25
|
+
* same provisioning once. It closed the population as of the moment it ran and
|
|
26
|
+
* closed no write path, so three producers went on filling it: standalone
|
|
27
|
+
* registration's two-flush window, federated sign-in (which provisioned no
|
|
28
|
+
* organisation at all), and the admin "un-assign" button. All three are closed
|
|
29
|
+
* in the merge request that carries this migration — without that, the
|
|
30
|
+
* constraint would convert three silent defects into three runtime failures.
|
|
31
|
+
*
|
|
32
|
+
* Two deliberate differences from that backfill:
|
|
33
|
+
*
|
|
34
|
+
* - **Soft-deleted accounts are included.** 051 skipped them with its own
|
|
35
|
+
* `and ca."deleted_at" is null`. A soft-deleted row still has to satisfy the
|
|
36
|
+
* constraint, and `customer_account.restored` would otherwise resurrect an
|
|
37
|
+
* account the platform cannot scope.
|
|
38
|
+
* - **The insert skips an account whose personal organisation already exists**,
|
|
39
|
+
* and a second statement links it. `tax_id` is derived from the account id
|
|
40
|
+
* and is globally unique, so an account that was provisioned once and then
|
|
41
|
+
* un-assigned would otherwise collide — the migration would abort on a
|
|
42
|
+
* constraint violation rather than on the sentence it wants to say.
|
|
43
|
+
*
|
|
44
|
+
* The provisioning mirrors `PersonalOrganizationService.provisionFor`: name from
|
|
45
|
+
* the trimmed "first last" or else the e-mail local part, `tax_id` the account
|
|
46
|
+
* UUID with the dashes stripped (32 hex characters — an individual has no
|
|
47
|
+
* company tax id), `vat_status = 'vat_exempt'`, `status = 'active'`,
|
|
48
|
+
* `is_personal = true`, and the placeholder registered address the column's
|
|
49
|
+
* `not null` demands.
|
|
50
|
+
*
|
|
51
|
+
* `organizations` is a hard `dependencies` entry of this module's manifest, so
|
|
52
|
+
* that module's tables exist by the time this runs.
|
|
53
|
+
*/
|
|
54
|
+
export class Migration20260825T141659CustomerAccountsOrganizationRequired extends Migration {
|
|
55
|
+
async up() {
|
|
56
|
+
// 1. Provision a personal organisation for every account that has none and
|
|
57
|
+
// whose derived one does not already exist.
|
|
58
|
+
this.addSql(`
|
|
59
|
+
insert into "organizations" (
|
|
60
|
+
"id", "name", "tax_id", "status", "vat_status", "is_personal",
|
|
61
|
+
"registered_address", "created_at", "updated_at"
|
|
62
|
+
)
|
|
63
|
+
select
|
|
64
|
+
gen_random_uuid(),
|
|
65
|
+
coalesce(
|
|
66
|
+
nullif(trim(coalesce(ca."first_name", '') || ' ' || coalesce(ca."last_name", '')), ''),
|
|
67
|
+
split_part(ca."email", '@', 1)
|
|
68
|
+
),
|
|
69
|
+
replace(ca."id"::text, '-', ''),
|
|
70
|
+
'active',
|
|
71
|
+
'vat_exempt',
|
|
72
|
+
true,
|
|
73
|
+
'{"street":"-","city":"-","postalCode":"-","country":"PL"}'::json,
|
|
74
|
+
now(), now()
|
|
75
|
+
from "customer_accounts" ca
|
|
76
|
+
where ca."organization_id" is null
|
|
77
|
+
and not exists (
|
|
78
|
+
select 1 from "organizations" o
|
|
79
|
+
where o."tax_id" = replace(ca."id"::text, '-', '')
|
|
80
|
+
);
|
|
81
|
+
`);
|
|
82
|
+
// 2. Link every such account to it — both the ones just created and the ones
|
|
83
|
+
// whose organisation survived an earlier provisioning (the state an
|
|
84
|
+
// un-assigned account was left in before this ruling).
|
|
85
|
+
//
|
|
86
|
+
// `is_personal` is the load-bearing word. Without it, an account whose
|
|
87
|
+
// derived `tax_id` happened to be held by a **company** organisation
|
|
88
|
+
// would be linked into that company's tenant — a stranger's — silently.
|
|
89
|
+
// With it, such an account is served by neither statement and falls
|
|
90
|
+
// through to the refusal below, which is what step 3's message describes.
|
|
91
|
+
this.addSql(`
|
|
92
|
+
update "customer_accounts" ca
|
|
93
|
+
set "organization_id" = o."id"
|
|
94
|
+
from "organizations" o
|
|
95
|
+
where ca."organization_id" is null
|
|
96
|
+
and o."is_personal" = true
|
|
97
|
+
and o."tax_id" = replace(ca."id"::text, '-', '');
|
|
98
|
+
`);
|
|
99
|
+
// 3. Count what is left and refuse. It can only be non-zero if an account's
|
|
100
|
+
// provisioning failed — a `tax_id` collision with a company organisation
|
|
101
|
+
// is the plausible one, since that column is globally unique. The merge
|
|
102
|
+
// request that hits this decides what to do; deleting is never it.
|
|
103
|
+
this.addSql(`
|
|
104
|
+
do $$
|
|
105
|
+
declare
|
|
106
|
+
remaining bigint;
|
|
107
|
+
sample text;
|
|
108
|
+
begin
|
|
109
|
+
select count(*) into remaining
|
|
110
|
+
from "customer_accounts" where "organization_id" is null;
|
|
111
|
+
if remaining > 0 then
|
|
112
|
+
select string_agg(id::text, ', ') into sample from (
|
|
113
|
+
select "id" from "customer_accounts"
|
|
114
|
+
where "organization_id" is null order by "id" limit 20
|
|
115
|
+
) s;
|
|
116
|
+
raise exception
|
|
117
|
+
'D-178: % customer_accounts row(s) still have organization_id IS NULL after provisioning. First ids: %. These rows are customer logins - do not delete them. The likely cause is a tax_id collision on organizations.tax_id, which is globally unique.',
|
|
118
|
+
remaining, sample;
|
|
119
|
+
end if;
|
|
120
|
+
end $$;
|
|
121
|
+
`);
|
|
122
|
+
// 4. The constraint.
|
|
123
|
+
this.addSql(`alter table "customer_accounts" alter column "organization_id" set not null;`);
|
|
124
|
+
}
|
|
125
|
+
async down() {
|
|
126
|
+
// Re-drop the constraint, and nothing else. The NULLs this migration filled
|
|
127
|
+
// in were a defect rather than data, so there is nothing to restore — and
|
|
128
|
+
// the personal organisations it created are left in place, because an
|
|
129
|
+
// account still points at each of them.
|
|
130
|
+
this.addSql(`alter table "customer_accounts" alter column "organization_id" drop not null;`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=20260825T141659_customer_accounts_organization_required.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260825T141659_customer_accounts_organization_required.js","sourceRoot":"","sources":["../../src/migrations/20260825T141659_customer_accounts_organization_required.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,OAAO,4DAA6D,SAAQ,SAAS;IAChF,KAAK,CAAC,EAAE;QACf,2EAA2E;QAC3E,+CAA+C;QAC/C,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;KAuBX,CAAC,CAAC;QAEH,6EAA6E;QAC7E,uEAAuE;QACvE,0DAA0D;QAC1D,EAAE;QACF,0EAA0E;QAC1E,wEAAwE;QACxE,2EAA2E;QAC3E,uEAAuE;QACvE,6EAA6E;QAC7E,IAAI,CAAC,MAAM,CAAC;;;;;;;KAOX,CAAC,CAAC;QAEH,4EAA4E;QAC5E,4EAA4E;QAC5E,2EAA2E;QAC3E,sEAAsE;QACtE,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;KAkBX,CAAC,CAAC;QAEH,qBAAqB;QACrB,IAAI,CAAC,MAAM,CAAC,8EAA8E,CAAC,CAAC;IAC9F,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,4EAA4E;QAC5E,0EAA0E;QAC1E,sEAAsE;QACtE,wCAAwC;QACxC,IAAI,CAAC,MAAM,CAAC,+EAA+E,CAAC,CAAC;IAC/F,CAAC;CACF"}
|
package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* The `sales_channel_customer_accounts` sales-channel bridge — the customers a channel is visible to.
|
|
4
|
+
*
|
|
5
|
+
* It was created by the platform's frozen `Migration20260430T170044CoreSalesChannelsPromote`
|
|
6
|
+
* until `specs/120-migration-closure-bridge-ownership/` Phase 2. Under D-226 a
|
|
7
|
+
* bridge between an always-present near side (`sales_channels`, a kernel table)
|
|
8
|
+
* and a switchable far side belongs to the far side, so this module creates it:
|
|
9
|
+
* an instance that does not install `customer_accounts` no longer has a migration corpus
|
|
10
|
+
* naming a table nothing builds.
|
|
11
|
+
*
|
|
12
|
+
* `if not exists`, because every database that has already applied the frozen
|
|
13
|
+
* migration has this table. The storage keys on the class name and holds no
|
|
14
|
+
* checksum, so nothing is re-offered there and this migration is the no-op it
|
|
15
|
+
* reads as; on a fresh database it is the creation.
|
|
16
|
+
*
|
|
17
|
+
* The statements are the frozen ones verbatim — same columns, same primary key,
|
|
18
|
+
* same two foreign keys, same index — so the two paths reach one schema. Its
|
|
19
|
+
* position needs nothing declared: `sales_channels` is the kernel's and
|
|
20
|
+
* `customer_accounts` is created inside the frozen prefix, which every
|
|
21
|
+
* above-watermark migration runs after.
|
|
22
|
+
*/
|
|
23
|
+
export declare class Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts extends Migration {
|
|
24
|
+
up(): Promise<void>;
|
|
25
|
+
down(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts.map
|
package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts","sourceRoot":"","sources":["../../src/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,oEAAqE,SAAQ,SAAS;IAClF,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAGrC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* The `sales_channel_customer_accounts` sales-channel bridge — the customers a channel is visible to.
|
|
4
|
+
*
|
|
5
|
+
* It was created by the platform's frozen `Migration20260430T170044CoreSalesChannelsPromote`
|
|
6
|
+
* until `specs/120-migration-closure-bridge-ownership/` Phase 2. Under D-226 a
|
|
7
|
+
* bridge between an always-present near side (`sales_channels`, a kernel table)
|
|
8
|
+
* and a switchable far side belongs to the far side, so this module creates it:
|
|
9
|
+
* an instance that does not install `customer_accounts` no longer has a migration corpus
|
|
10
|
+
* naming a table nothing builds.
|
|
11
|
+
*
|
|
12
|
+
* `if not exists`, because every database that has already applied the frozen
|
|
13
|
+
* migration has this table. The storage keys on the class name and holds no
|
|
14
|
+
* checksum, so nothing is re-offered there and this migration is the no-op it
|
|
15
|
+
* reads as; on a fresh database it is the creation.
|
|
16
|
+
*
|
|
17
|
+
* The statements are the frozen ones verbatim — same columns, same primary key,
|
|
18
|
+
* same two foreign keys, same index — so the two paths reach one schema. Its
|
|
19
|
+
* position needs nothing declared: `sales_channels` is the kernel's and
|
|
20
|
+
* `customer_accounts` is created inside the frozen prefix, which every
|
|
21
|
+
* above-watermark migration runs after.
|
|
22
|
+
*/
|
|
23
|
+
export class Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts extends Migration {
|
|
24
|
+
async up() {
|
|
25
|
+
this.addSql(`
|
|
26
|
+
create table if not exists "sales_channel_customer_accounts" (
|
|
27
|
+
"sales_channel_id" uuid not null,
|
|
28
|
+
"customer_account_id" uuid not null,
|
|
29
|
+
constraint "sales_channel_customer_accounts_pkey"
|
|
30
|
+
primary key ("sales_channel_id", "customer_account_id"),
|
|
31
|
+
constraint "sales_channel_customer_accounts_channel_fk"
|
|
32
|
+
foreign key ("sales_channel_id") references "sales_channels" ("id") on delete cascade,
|
|
33
|
+
constraint "sales_channel_customer_accounts_customer_account_fk"
|
|
34
|
+
foreign key ("customer_account_id") references "customer_accounts" ("id") on delete cascade
|
|
35
|
+
);
|
|
36
|
+
`);
|
|
37
|
+
this.addSql('create index if not exists "sales_channel_customer_accounts_customer_account_id_index" ' +
|
|
38
|
+
'on "sales_channel_customer_accounts" ("customer_account_id");');
|
|
39
|
+
}
|
|
40
|
+
async down() {
|
|
41
|
+
this.addSql('drop table if exists "sales_channel_customer_accounts" cascade;');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=20260912T094701_customer_accounts_sales_channel_customer_accounts.js.map
|
package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260912T094701_customer_accounts_sales_channel_customer_accounts.js","sourceRoot":"","sources":["../../src/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,oEAAqE,SAAQ,SAAS;IACxF,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;KAWX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CACT,yFAAyF;YACvF,+DAA+D,CAClE,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,iEAAiE,CAAC,CAAC;IACjF,CAAC;CACF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `./migrations` subpath — every migration class this module owns, as one
|
|
3
|
+
* ordered `migrations` array.
|
|
4
|
+
*
|
|
5
|
+
* The array is what the platform reads when this module is **installed**:
|
|
6
|
+
* `src/packages/package-runtime.ts` takes `exported['migrations']` and refuses
|
|
7
|
+
* the package outright when it is absent (D-168).
|
|
8
|
+
*
|
|
9
|
+
* Listed in ascending timestamp, which orders **this module's own** migrations
|
|
10
|
+
* and nothing else (feature 081). Where the block sits relative to every other
|
|
11
|
+
* module's is decided by the manifest `dependencies` graph.
|
|
12
|
+
*
|
|
13
|
+
* The **named** exports stay, and the asymmetry with `./backend` — which
|
|
14
|
+
* publishes an array and no entity class by name (D-168) — is deliberate.
|
|
15
|
+
* `db/migrations-registry.generated.ts` imports each class by name from this
|
|
16
|
+
* specifier, and a migration class name is contract in a way an entity class
|
|
17
|
+
* name is not: `mikro_orm_migrations` persists it, so it is a string every
|
|
18
|
+
* already-migrated database holds.
|
|
19
|
+
*
|
|
20
|
+
* A class that is in neither the array nor the barrel is a migration that does
|
|
21
|
+
* not run: `migration:pending` reports nothing pending and the first symptom
|
|
22
|
+
* is a query against a table nobody created.
|
|
23
|
+
*/
|
|
24
|
+
import { Migration20260425T055041CustomerAccountsPasswordResetTokens } from './20260425T055041_customer_accounts_password_reset_tokens.js';
|
|
25
|
+
import { Migration20260611T140351CustomerAccountsOrganizationOptional } from './20260611T140351_customer_accounts_organization_optional.js';
|
|
26
|
+
import { Migration20260611T140403CustomerAccountsLifecycle } from './20260611T140403_customer_accounts_lifecycle.js';
|
|
27
|
+
import { Migration20260718T200341CustomerAccountsCustomerAccountCustomFieldValues } from './20260718T200341_customer_accounts_customer_account_custom_field_values.js';
|
|
28
|
+
import { Migration20260720T044255CustomerAccountsCustomerSubtreeRollup } from './20260720T044255_customer_accounts_customer_subtree_rollup.js';
|
|
29
|
+
import { Migration20260819T074816CustomerAccountsPasswordSetAt } from './20260819T074816_customer_accounts_password_set_at.js';
|
|
30
|
+
import { Migration20260819T142837CustomerAccountsFoldEmailCase } from './20260819T142837_customer_accounts_fold_email_case.js';
|
|
31
|
+
import { Migration20260825T124759CustomerAccountsDropLegacyTwoFactorSecret } from './20260825T124759_customer_accounts_drop_legacy_two_factor_secret.js';
|
|
32
|
+
import { Migration20260825T141659CustomerAccountsOrganizationRequired } from './20260825T141659_customer_accounts_organization_required.js';
|
|
33
|
+
import { Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts } from './20260912T094701_customer_accounts_sales_channel_customer_accounts.js';
|
|
34
|
+
export declare const migrations: (typeof Migration20260425T055041CustomerAccountsPasswordResetTokens)[];
|
|
35
|
+
export { Migration20260425T055041CustomerAccountsPasswordResetTokens, Migration20260611T140351CustomerAccountsOrganizationOptional, Migration20260611T140403CustomerAccountsLifecycle, Migration20260718T200341CustomerAccountsCustomerAccountCustomFieldValues, Migration20260720T044255CustomerAccountsCustomerSubtreeRollup, Migration20260819T074816CustomerAccountsPasswordSetAt, Migration20260819T142837CustomerAccountsFoldEmailCase, Migration20260825T124759CustomerAccountsDropLegacyTwoFactorSecret, Migration20260825T141659CustomerAccountsOrganizationRequired, Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts, };
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,2DAA2D,EAAE,MAAM,8DAA8D,CAAC;AAC3I,OAAO,EAAE,4DAA4D,EAAE,MAAM,8DAA8D,CAAC;AAC5I,OAAO,EAAE,iDAAiD,EAAE,MAAM,kDAAkD,CAAC;AACrH,OAAO,EAAE,wEAAwE,EAAE,MAAM,6EAA6E,CAAC;AACvK,OAAO,EAAE,6DAA6D,EAAE,MAAM,gEAAgE,CAAC;AAC/I,OAAO,EAAE,qDAAqD,EAAE,MAAM,wDAAwD,CAAC;AAC/H,OAAO,EAAE,qDAAqD,EAAE,MAAM,wDAAwD,CAAC;AAC/H,OAAO,EAAE,iEAAiE,EAAE,MAAM,sEAAsE,CAAC;AACzJ,OAAO,EAAE,4DAA4D,EAAE,MAAM,8DAA8D,CAAC;AAC5I,OAAO,EAAE,oEAAoE,EAAE,MAAM,wEAAwE,CAAC;AAE9J,eAAO,MAAM,UAAU,wEAWtB,CAAC;AAEF,OAAO,EACL,2DAA2D,EAC3D,4DAA4D,EAC5D,iDAAiD,EACjD,wEAAwE,EACxE,6DAA6D,EAC7D,qDAAqD,EACrD,qDAAqD,EACrD,iEAAiE,EACjE,4DAA4D,EAC5D,oEAAoE,GACrE,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `./migrations` subpath — every migration class this module owns, as one
|
|
3
|
+
* ordered `migrations` array.
|
|
4
|
+
*
|
|
5
|
+
* The array is what the platform reads when this module is **installed**:
|
|
6
|
+
* `src/packages/package-runtime.ts` takes `exported['migrations']` and refuses
|
|
7
|
+
* the package outright when it is absent (D-168).
|
|
8
|
+
*
|
|
9
|
+
* Listed in ascending timestamp, which orders **this module's own** migrations
|
|
10
|
+
* and nothing else (feature 081). Where the block sits relative to every other
|
|
11
|
+
* module's is decided by the manifest `dependencies` graph.
|
|
12
|
+
*
|
|
13
|
+
* The **named** exports stay, and the asymmetry with `./backend` — which
|
|
14
|
+
* publishes an array and no entity class by name (D-168) — is deliberate.
|
|
15
|
+
* `db/migrations-registry.generated.ts` imports each class by name from this
|
|
16
|
+
* specifier, and a migration class name is contract in a way an entity class
|
|
17
|
+
* name is not: `mikro_orm_migrations` persists it, so it is a string every
|
|
18
|
+
* already-migrated database holds.
|
|
19
|
+
*
|
|
20
|
+
* A class that is in neither the array nor the barrel is a migration that does
|
|
21
|
+
* not run: `migration:pending` reports nothing pending and the first symptom
|
|
22
|
+
* is a query against a table nobody created.
|
|
23
|
+
*/
|
|
24
|
+
import { Migration20260425T055041CustomerAccountsPasswordResetTokens } from './20260425T055041_customer_accounts_password_reset_tokens.js';
|
|
25
|
+
import { Migration20260611T140351CustomerAccountsOrganizationOptional } from './20260611T140351_customer_accounts_organization_optional.js';
|
|
26
|
+
import { Migration20260611T140403CustomerAccountsLifecycle } from './20260611T140403_customer_accounts_lifecycle.js';
|
|
27
|
+
import { Migration20260718T200341CustomerAccountsCustomerAccountCustomFieldValues } from './20260718T200341_customer_accounts_customer_account_custom_field_values.js';
|
|
28
|
+
import { Migration20260720T044255CustomerAccountsCustomerSubtreeRollup } from './20260720T044255_customer_accounts_customer_subtree_rollup.js';
|
|
29
|
+
import { Migration20260819T074816CustomerAccountsPasswordSetAt } from './20260819T074816_customer_accounts_password_set_at.js';
|
|
30
|
+
import { Migration20260819T142837CustomerAccountsFoldEmailCase } from './20260819T142837_customer_accounts_fold_email_case.js';
|
|
31
|
+
import { Migration20260825T124759CustomerAccountsDropLegacyTwoFactorSecret } from './20260825T124759_customer_accounts_drop_legacy_two_factor_secret.js';
|
|
32
|
+
import { Migration20260825T141659CustomerAccountsOrganizationRequired } from './20260825T141659_customer_accounts_organization_required.js';
|
|
33
|
+
import { Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts } from './20260912T094701_customer_accounts_sales_channel_customer_accounts.js';
|
|
34
|
+
export const migrations = [
|
|
35
|
+
Migration20260425T055041CustomerAccountsPasswordResetTokens,
|
|
36
|
+
Migration20260611T140351CustomerAccountsOrganizationOptional,
|
|
37
|
+
Migration20260611T140403CustomerAccountsLifecycle,
|
|
38
|
+
Migration20260718T200341CustomerAccountsCustomerAccountCustomFieldValues,
|
|
39
|
+
Migration20260720T044255CustomerAccountsCustomerSubtreeRollup,
|
|
40
|
+
Migration20260819T074816CustomerAccountsPasswordSetAt,
|
|
41
|
+
Migration20260819T142837CustomerAccountsFoldEmailCase,
|
|
42
|
+
Migration20260825T124759CustomerAccountsDropLegacyTwoFactorSecret,
|
|
43
|
+
Migration20260825T141659CustomerAccountsOrganizationRequired,
|
|
44
|
+
Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts,
|
|
45
|
+
];
|
|
46
|
+
export { Migration20260425T055041CustomerAccountsPasswordResetTokens, Migration20260611T140351CustomerAccountsOrganizationOptional, Migration20260611T140403CustomerAccountsLifecycle, Migration20260718T200341CustomerAccountsCustomerAccountCustomFieldValues, Migration20260720T044255CustomerAccountsCustomerSubtreeRollup, Migration20260819T074816CustomerAccountsPasswordSetAt, Migration20260819T142837CustomerAccountsFoldEmailCase, Migration20260825T124759CustomerAccountsDropLegacyTwoFactorSecret, Migration20260825T141659CustomerAccountsOrganizationRequired, Migration20260912T094701CustomerAccountsSalesChannelCustomerAccounts, };
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,2DAA2D,EAAE,MAAM,8DAA8D,CAAC;AAC3I,OAAO,EAAE,4DAA4D,EAAE,MAAM,8DAA8D,CAAC;AAC5I,OAAO,EAAE,iDAAiD,EAAE,MAAM,kDAAkD,CAAC;AACrH,OAAO,EAAE,wEAAwE,EAAE,MAAM,6EAA6E,CAAC;AACvK,OAAO,EAAE,6DAA6D,EAAE,MAAM,gEAAgE,CAAC;AAC/I,OAAO,EAAE,qDAAqD,EAAE,MAAM,wDAAwD,CAAC;AAC/H,OAAO,EAAE,qDAAqD,EAAE,MAAM,wDAAwD,CAAC;AAC/H,OAAO,EAAE,iEAAiE,EAAE,MAAM,sEAAsE,CAAC;AACzJ,OAAO,EAAE,4DAA4D,EAAE,MAAM,8DAA8D,CAAC;AAC5I,OAAO,EAAE,oEAAoE,EAAE,MAAM,wEAAwE,CAAC;AAE9J,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,2DAA2D;IAC3D,4DAA4D;IAC5D,iDAAiD;IACjD,wEAAwE;IACxE,6DAA6D;IAC7D,qDAAqD;IACrD,qDAAqD;IACrD,iEAAiE;IACjE,4DAA4D;IAC5D,oEAAoE;CACrE,CAAC;AAEF,OAAO,EACL,2DAA2D,EAC3D,4DAA4D,EAC5D,iDAAiD,EACjD,wEAAwE,EACxE,6DAA6D,EAC7D,qDAAqD,EACrD,qDAAqD,EACrD,iEAAiE,EACjE,4DAA4D,EAC5D,oEAAoE,GACrE,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: customer_accounts
|
|
3
|
+
description: Customer login, password reset, 2FA, role assignment
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `customer_accounts`
|
|
7
|
+
|
|
8
|
+
Per-user state for Customers: login, password management, optional 2FA,
|
|
9
|
+
role within their Organization. Backed by the shared `auth` session
|
|
10
|
+
service; this module owns the customer-facing identity surface.
|
|
11
|
+
|
|
12
|
+
## Public surface
|
|
13
|
+
|
|
14
|
+
| Verb + Path | Purpose |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `POST /api/v1/auth/login` | Email + password (+ TOTP step if 2FA enabled) |
|
|
17
|
+
| `POST /api/v1/auth/logout` | Destroy session |
|
|
18
|
+
| `POST /api/v1/me/password` | Change password (rejects wrong `currentPassword`) |
|
|
19
|
+
| `POST /api/v1/auth/password-reset/request` | Begin reset flow |
|
|
20
|
+
| `POST /api/v1/auth/password-reset/confirm` | Redeem reset token |
|
|
21
|
+
|
|
22
|
+
## Entities
|
|
23
|
+
|
|
24
|
+
`CustomerAccount` (email, passwordHash, role), `PasswordResetToken`. Role is
|
|
25
|
+
enum `organization_admin | regular_user`.
|
|
26
|
+
|
|
27
|
+
## Extension points
|
|
28
|
+
|
|
29
|
+
- **Password policy** — `password-hasher.ts` wraps argon2id; tune cost
|
|
30
|
+
parameters there.
|
|
31
|
+
- **Backup codes and second factors** — not this module's. Customer and admin
|
|
32
|
+
2FA is the `mfa` module's, over `mfa_enrolments`, served at
|
|
33
|
+
`/api/v1/account/mfa/*`; recovery codes are single-use rows there. The
|
|
34
|
+
superseded scaffolding this bullet used to point at
|
|
35
|
+
(`totp-enrolment-service.ts`) was deleted on 2026-08-25 — it could never
|
|
36
|
+
complete a single enrolment.
|
|
37
|
+
- **Login throttling** — relies on Fastify `@fastify/rate-limit` at server
|
|
38
|
+
level; per-account lockout would be added here.
|
package/i18n/en.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"errors.CANNOT_DEMOTE_LAST_ADMIN": "This is the only administrator in the organization, and an organization always keeps at least one — demoting them would leave nobody able to manage members, addresses or approvals. Promote another member to administrator first, and then this role can be changed.",
|
|
3
|
+
"errors.CANNOT_REMOVE_LAST_ADMIN": "This is the only administrator in the organization, and an organization always keeps at least one — removing them would leave nobody able to manage members, addresses or approvals. Promote another member to administrator first, and then this one can be removed.",
|
|
4
|
+
"actions.openCustomerGroups.label": "Customer groups",
|
|
5
|
+
"actions.openCustomerGroups.description": "Manage the segmentation groups customers and organizations are assigned to",
|
|
6
|
+
"groups.page.title": "Customer groups",
|
|
7
|
+
"groups.page.description": "A customer group is a segment you assign to a customer or to an organization. Pricing rules, promotions and push audiences target these groups; a customer's own group wins over the one inherited from their organization.",
|
|
8
|
+
"groups.error.load": "Failed to load customer groups.",
|
|
9
|
+
"groups.error.save": "Failed to save the customer group.",
|
|
10
|
+
"groups.error.delete": "Failed to delete the customer group.",
|
|
11
|
+
"groups.loading": "Loading customer groups…",
|
|
12
|
+
"groups.empty": "No customer groups yet.",
|
|
13
|
+
"groups.column.code": "Code",
|
|
14
|
+
"groups.column.name": "Name",
|
|
15
|
+
"groups.column.description": "Description",
|
|
16
|
+
"groups.form.newTitle": "New customer group",
|
|
17
|
+
"groups.form.editTitle": "Edit “{code}”",
|
|
18
|
+
"groups.field.code": "Code",
|
|
19
|
+
"groups.field.code.help": "Lower-case identifier used by pricing rules and promotions. It cannot be changed after the group is created.",
|
|
20
|
+
"groups.field.name": "Name",
|
|
21
|
+
"groups.field.description": "Description",
|
|
22
|
+
"groups.action.edit": "Edit",
|
|
23
|
+
"groups.action.delete": "Delete",
|
|
24
|
+
"groups.action.save": "Save",
|
|
25
|
+
"groups.action.cancel": "Cancel",
|
|
26
|
+
"groups.action.delete.confirm": "Delete customer group “{code}”? Customers and organizations assigned to it keep their records and lose the assignment.",
|
|
27
|
+
"groups.message.saved": "Customer group “{code}” saved.",
|
|
28
|
+
"groups.message.deleted": "Customer group deleted.",
|
|
29
|
+
"nav.customerGroups.label": "Customer groups"
|
|
30
|
+
}
|
package/i18n/pl.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"errors.CANNOT_DEMOTE_LAST_ADMIN": "To jedyny administrator w tej organizacji, a organizacja zawsze musi mieć co najmniej jednego — po odebraniu mu tej roli nikt nie mógłby zarządzać użytkownikami, adresami ani akceptacjami. Najpierw nadaj rolę administratora innemu użytkownikowi, a potem tę rolę będzie można zmienić.",
|
|
3
|
+
"errors.CANNOT_REMOVE_LAST_ADMIN": "To jedyny administrator w tej organizacji, a organizacja zawsze musi mieć co najmniej jednego — po jego usunięciu nikt nie mógłby zarządzać użytkownikami, adresami ani akceptacjami. Najpierw nadaj rolę administratora innemu użytkownikowi, a potem tego będzie można usunąć.",
|
|
4
|
+
"actions.openCustomerGroups.label": "Grupy klientów",
|
|
5
|
+
"actions.openCustomerGroups.description": "Zarządzaj grupami segmentacji przypisywanymi klientom i organizacjom",
|
|
6
|
+
"groups.page.title": "Grupy klientów",
|
|
7
|
+
"groups.page.description": "Grupa klientów to segment przypisywany klientowi lub organizacji. Reguły cenowe, promocje i odbiorcy powiadomień push celują w te grupy; grupa przypisana bezpośrednio klientowi ma pierwszeństwo przed grupą odziedziczoną z organizacji.",
|
|
8
|
+
"groups.error.load": "Nie udało się wczytać grup klientów.",
|
|
9
|
+
"groups.error.save": "Nie udało się zapisać grupy klientów.",
|
|
10
|
+
"groups.error.delete": "Nie udało się usunąć grupy klientów.",
|
|
11
|
+
"groups.loading": "Wczytywanie grup klientów…",
|
|
12
|
+
"groups.empty": "Nie ma jeszcze żadnych grup klientów.",
|
|
13
|
+
"groups.column.code": "Kod",
|
|
14
|
+
"groups.column.name": "Nazwa",
|
|
15
|
+
"groups.column.description": "Opis",
|
|
16
|
+
"groups.form.newTitle": "Nowa grupa klientów",
|
|
17
|
+
"groups.form.editTitle": "Edycja „{code}”",
|
|
18
|
+
"groups.field.code": "Kod",
|
|
19
|
+
"groups.field.code.help": "Identyfikator pisany małymi literami, używany przez reguły cenowe i promocje. Po utworzeniu grupy nie można go zmienić.",
|
|
20
|
+
"groups.field.name": "Nazwa",
|
|
21
|
+
"groups.field.description": "Opis",
|
|
22
|
+
"groups.action.edit": "Edytuj",
|
|
23
|
+
"groups.action.delete": "Usuń",
|
|
24
|
+
"groups.action.save": "Zapisz",
|
|
25
|
+
"groups.action.cancel": "Anuluj",
|
|
26
|
+
"groups.action.delete.confirm": "Usunąć grupę klientów „{code}”? Klienci i organizacje do niej przypisani zachowają swoje dane i utracą to przypisanie.",
|
|
27
|
+
"groups.message.saved": "Grupa klientów „{code}” została zapisana.",
|
|
28
|
+
"groups.message.deleted": "Grupa klientów została usunięta.",
|
|
29
|
+
"nav.customerGroups.label": "Grupy klientów"
|
|
30
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@endora-commerce/mod-customer-accounts",
|
|
3
|
+
"version": "0.100.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"description": "Customer (B2B) account records, including organization membership and role.",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"endora": {
|
|
9
|
+
"type": "module",
|
|
10
|
+
"id": "customer_accounts"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/endora-commerce/endora-commerce.git",
|
|
15
|
+
"directory": "packages/modules/customer_accounts"
|
|
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
|
+
"./migrations": {
|
|
30
|
+
"types": "./dist/migrations/index.d.ts",
|
|
31
|
+
"default": "./dist/migrations/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./admin": {
|
|
34
|
+
"types": "./dist/admin/index.d.ts",
|
|
35
|
+
"default": "./dist/admin/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./tailwind.css": "./tailwind.css",
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"i18n",
|
|
43
|
+
"docs",
|
|
44
|
+
"tailwind.css"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22.18.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@mikro-orm/core": "^6",
|
|
51
|
+
"@mikro-orm/migrations": "^6",
|
|
52
|
+
"@mikro-orm/postgresql": "^6",
|
|
53
|
+
"fastify": "^5",
|
|
54
|
+
"lucide-react": "^1",
|
|
55
|
+
"react": "^19",
|
|
56
|
+
"zod": "^4",
|
|
57
|
+
"@endora-commerce/admin-kit": "0.100.0",
|
|
58
|
+
"@endora-commerce/contracts": "0.100.0",
|
|
59
|
+
"@endora-commerce/mod-organizations": "0.100.0",
|
|
60
|
+
"@endora-commerce/platform": "0.100.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"@endora-commerce/admin-kit": {
|
|
64
|
+
"optional": true
|
|
65
|
+
},
|
|
66
|
+
"lucide-react": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"react": {
|
|
70
|
+
"optional": true
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"@mikro-orm/core": "^6.6.13",
|
|
75
|
+
"@mikro-orm/migrations": "^6.6.13",
|
|
76
|
+
"@mikro-orm/postgresql": "^6.6.13",
|
|
77
|
+
"@types/node": "^22.9.0",
|
|
78
|
+
"@types/react": "^19.2.14",
|
|
79
|
+
"fastify": "^5.12.5",
|
|
80
|
+
"lucide-react": "^1.11.0",
|
|
81
|
+
"react": "^19.2.5",
|
|
82
|
+
"typescript": "^5.9.3",
|
|
83
|
+
"zod": "^4.2.0",
|
|
84
|
+
"@endora-commerce/admin-kit": "0.100.0",
|
|
85
|
+
"@endora-commerce/contracts": "0.100.0",
|
|
86
|
+
"@endora-commerce/mod-organizations": "0.100.0",
|
|
87
|
+
"@endora-commerce/platform": "0.100.0"
|
|
88
|
+
},
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsc -p tsconfig.build.json && tsc -p tsconfig.ui.json",
|
|
91
|
+
"typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.ui.json --noEmit",
|
|
92
|
+
"lint": "eslint src"
|
|
93
|
+
}
|
|
94
|
+
}
|
package/tailwind.css
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* @endora-commerce/mod-customer-accounts — 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";
|