@endora-commerce/mod-dictionaries 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 +60 -0
- package/dist/admin/api/client.d.ts +76 -0
- package/dist/admin/api/client.d.ts.map +1 -0
- package/dist/admin/api/client.js +87 -0
- package/dist/admin/api/client.js.map +1 -0
- package/dist/admin/components/EntryStatusBadges.d.ts +9 -0
- package/dist/admin/components/EntryStatusBadges.d.ts.map +1 -0
- package/dist/admin/components/EntryStatusBadges.js +8 -0
- package/dist/admin/components/EntryStatusBadges.js.map +1 -0
- package/dist/admin/components/LanguagePicker.d.ts +8 -0
- package/dist/admin/components/LanguagePicker.d.ts.map +1 -0
- package/dist/admin/components/LanguagePicker.js +30 -0
- package/dist/admin/components/LanguagePicker.js.map +1 -0
- package/dist/admin/components/TranslationsDrawer.d.ts +10 -0
- package/dist/admin/components/TranslationsDrawer.d.ts.map +1 -0
- package/dist/admin/components/TranslationsDrawer.js +90 -0
- package/dist/admin/components/TranslationsDrawer.js.map +1 -0
- package/dist/admin/index.d.ts +48 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +82 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/AuditPage.d.ts +9 -0
- package/dist/admin/pages/AuditPage.d.ts.map +1 -0
- package/dist/admin/pages/AuditPage.js +80 -0
- package/dist/admin/pages/AuditPage.js.map +1 -0
- package/dist/admin/pages/DictionaryPage.d.ts +9 -0
- package/dist/admin/pages/DictionaryPage.d.ts.map +1 -0
- package/dist/admin/pages/DictionaryPage.js +38 -0
- package/dist/admin/pages/DictionaryPage.js.map +1 -0
- package/dist/admin/tabs/CountriesTab.d.ts +3 -0
- package/dist/admin/tabs/CountriesTab.d.ts.map +1 -0
- package/dist/admin/tabs/CountriesTab.js +233 -0
- package/dist/admin/tabs/CountriesTab.js.map +1 -0
- package/dist/admin/tabs/CurrenciesTab.d.ts +3 -0
- package/dist/admin/tabs/CurrenciesTab.d.ts.map +1 -0
- package/dist/admin/tabs/CurrenciesTab.js +209 -0
- package/dist/admin/tabs/CurrenciesTab.js.map +1 -0
- package/dist/admin/tabs/LanguagesTab.d.ts +3 -0
- package/dist/admin/tabs/LanguagesTab.d.ts.map +1 -0
- package/dist/admin/tabs/LanguagesTab.js +268 -0
- package/dist/admin/tabs/LanguagesTab.js.map +1 -0
- package/dist/backend/entities/country.entity.d.ts +35 -0
- package/dist/backend/entities/country.entity.d.ts.map +1 -0
- package/dist/backend/entities/country.entity.js +107 -0
- package/dist/backend/entities/country.entity.js.map +1 -0
- package/dist/backend/entities/dictionary-translation.entity.d.ts +25 -0
- package/dist/backend/entities/dictionary-translation.entity.d.ts.map +1 -0
- package/dist/backend/entities/dictionary-translation.entity.js +65 -0
- package/dist/backend/entities/dictionary-translation.entity.js.map +1 -0
- package/dist/backend/entities/language-country.entity.d.ts +17 -0
- package/dist/backend/entities/language-country.entity.d.ts.map +1 -0
- package/dist/backend/entities/language-country.entity.js +49 -0
- package/dist/backend/entities/language-country.entity.js.map +1 -0
- package/dist/backend/index.d.ts +85 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +155 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +39 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +317 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +7 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +34 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/seed/countries.d.ts +28 -0
- package/dist/backend/seed/countries.d.ts.map +1 -0
- package/dist/backend/seed/countries.js +121 -0
- package/dist/backend/seed/countries.js.map +1 -0
- package/dist/backend/seed/currencies.d.ts +9 -0
- package/dist/backend/seed/currencies.d.ts.map +1 -0
- package/dist/backend/seed/currencies.js +76 -0
- package/dist/backend/seed/currencies.js.map +1 -0
- package/dist/backend/seed/language-countries.d.ts +7 -0
- package/dist/backend/seed/language-countries.d.ts.map +1 -0
- package/dist/backend/seed/language-countries.js +19 -0
- package/dist/backend/seed/language-countries.js.map +1 -0
- package/dist/backend/seed/translations.pl-PL.d.ts +10 -0
- package/dist/backend/seed/translations.pl-PL.d.ts.map +1 -0
- package/dist/backend/seed/translations.pl-PL.js +74 -0
- package/dist/backend/seed/translations.pl-PL.js.map +1 -0
- package/dist/backend/services/country-currency-reference.d.ts +13 -0
- package/dist/backend/services/country-currency-reference.d.ts.map +1 -0
- package/dist/backend/services/country-currency-reference.js +25 -0
- package/dist/backend/services/country-currency-reference.js.map +1 -0
- package/dist/backend/services/country-reference-registry.d.ts +30 -0
- package/dist/backend/services/country-reference-registry.d.ts.map +1 -0
- package/dist/backend/services/country-reference-registry.js +54 -0
- package/dist/backend/services/country-reference-registry.js.map +1 -0
- package/dist/backend/services/country-service.d.ts +69 -0
- package/dist/backend/services/country-service.d.ts.map +1 -0
- package/dist/backend/services/country-service.js +193 -0
- package/dist/backend/services/country-service.js.map +1 -0
- package/dist/backend/services/dictionary-cache.d.ts +27 -0
- package/dist/backend/services/dictionary-cache.d.ts.map +1 -0
- package/dist/backend/services/dictionary-cache.js +57 -0
- package/dist/backend/services/dictionary-cache.js.map +1 -0
- package/dist/backend/services/dictionary-read-service.d.ts +36 -0
- package/dist/backend/services/dictionary-read-service.d.ts.map +1 -0
- package/dist/backend/services/dictionary-read-service.js +232 -0
- package/dist/backend/services/dictionary-read-service.js.map +1 -0
- package/dist/backend/services/dictionary-validator.d.ts +26 -0
- package/dist/backend/services/dictionary-validator.d.ts.map +1 -0
- package/dist/backend/services/dictionary-validator.js +72 -0
- package/dist/backend/services/dictionary-validator.js.map +1 -0
- package/dist/backend/services/dispatch-validator-mode.d.ts +19 -0
- package/dist/backend/services/dispatch-validator-mode.d.ts.map +1 -0
- package/dist/backend/services/dispatch-validator-mode.js +19 -0
- package/dist/backend/services/dispatch-validator-mode.js.map +1 -0
- package/dist/backend/services/label-resolver.d.ts +57 -0
- package/dist/backend/services/label-resolver.d.ts.map +1 -0
- package/dist/backend/services/label-resolver.js +116 -0
- package/dist/backend/services/label-resolver.js.map +1 -0
- package/dist/backend/services/language-country-service.d.ts +26 -0
- package/dist/backend/services/language-country-service.d.ts.map +1 -0
- package/dist/backend/services/language-country-service.js +108 -0
- package/dist/backend/services/language-country-service.js.map +1 -0
- package/dist/backend/services/seed-reconciler.d.ts +22 -0
- package/dist/backend/services/seed-reconciler.d.ts.map +1 -0
- package/dist/backend/services/seed-reconciler.js +149 -0
- package/dist/backend/services/seed-reconciler.js.map +1 -0
- package/dist/backend/services/translation-service.d.ts +29 -0
- package/dist/backend/services/translation-service.d.ts.map +1 -0
- package/dist/backend/services/translation-service.js +99 -0
- package/dist/backend/services/translation-service.js.map +1 -0
- package/dist/manifest.d.ts +174 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +178 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260506T112634_dictionaries_dictionary_init.d.ts +33 -0
- package/dist/migrations/20260506T112634_dictionaries_dictionary_init.d.ts.map +1 -0
- package/dist/migrations/20260506T112634_dictionaries_dictionary_init.js +157 -0
- package/dist/migrations/20260506T112634_dictionaries_dictionary_init.js.map +1 -0
- package/dist/migrations/index.d.ts +27 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +29 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/dictionaries/index.md +89 -0
- package/i18n/en.json +88 -0
- package/i18n/pl.json +88 -0
- package/package.json +99 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,107 @@
|
|
|
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
|
+
/**
|
|
13
|
+
* Country — ISO 3166-1 alpha-2 territories the platform recognises (feature 017).
|
|
14
|
+
* The natural code is the stable handle every consumer module references
|
|
15
|
+
* (Address, Tax, Warehouse, Organisation registered address). The "exactly
|
|
16
|
+
* one default" invariant is enforced by a partial unique index in the
|
|
17
|
+
* migration. Hard-delete is service-layer guarded: refused while any
|
|
18
|
+
* consumer references the row (FR-021).
|
|
19
|
+
*/
|
|
20
|
+
let Country = class Country {
|
|
21
|
+
[OptionalProps];
|
|
22
|
+
/** ISO 3166-1 alpha-2 code, immutable. Stable handle for every reference. */
|
|
23
|
+
code;
|
|
24
|
+
alpha3Code;
|
|
25
|
+
/** Zero-padded ISO 3166-1 numeric code (e.g. `616` for `PL`). */
|
|
26
|
+
numericCode;
|
|
27
|
+
/** Canonical English display name. Per-locale overrides live in `dictionary_translations`. */
|
|
28
|
+
label;
|
|
29
|
+
/** UN-style top-level region (`Africa`, `Americas`, `Asia`, `Europe`, `Oceania`, `Antarctic`). */
|
|
30
|
+
region;
|
|
31
|
+
subregion;
|
|
32
|
+
/** Phone-prefix string with leading `+` (e.g. `+48`). */
|
|
33
|
+
dialCode;
|
|
34
|
+
/** Drives VAT logic in the Tax module. */
|
|
35
|
+
isEuMember = false;
|
|
36
|
+
/** Hint for storefront pre-selection; soft FK to `currencies(code)`. */
|
|
37
|
+
defaultCurrencyCode;
|
|
38
|
+
isActive = true;
|
|
39
|
+
/** Exactly one row has `true` (partial unique index). */
|
|
40
|
+
isDefault = false;
|
|
41
|
+
sortOrder = 0;
|
|
42
|
+
createdAt = new Date();
|
|
43
|
+
updatedAt = new Date();
|
|
44
|
+
};
|
|
45
|
+
__decorate([
|
|
46
|
+
PrimaryKey({ type: 'string', length: 2 }),
|
|
47
|
+
__metadata("design:type", String)
|
|
48
|
+
], Country.prototype, "code", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
Property({ type: 'string', length: 3, fieldName: 'alpha3_code' }),
|
|
51
|
+
__metadata("design:type", String)
|
|
52
|
+
], Country.prototype, "alpha3Code", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
Property({ type: 'string', length: 3, fieldName: 'numeric_code' }),
|
|
55
|
+
__metadata("design:type", String)
|
|
56
|
+
], Country.prototype, "numericCode", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
Property({ type: 'string', length: 120 }),
|
|
59
|
+
__metadata("design:type", String)
|
|
60
|
+
], Country.prototype, "label", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
Property({ type: 'string', length: 32 }),
|
|
63
|
+
__metadata("design:type", String)
|
|
64
|
+
], Country.prototype, "region", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
Property({ type: 'string', length: 64, nullable: true }),
|
|
67
|
+
__metadata("design:type", Object)
|
|
68
|
+
], Country.prototype, "subregion", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
Property({ type: 'string', length: 8, nullable: true }),
|
|
71
|
+
__metadata("design:type", Object)
|
|
72
|
+
], Country.prototype, "dialCode", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
Property({ type: 'boolean' }),
|
|
75
|
+
__metadata("design:type", Boolean)
|
|
76
|
+
], Country.prototype, "isEuMember", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
Property({ type: 'string', length: 3, nullable: true }),
|
|
79
|
+
__metadata("design:type", Object)
|
|
80
|
+
], Country.prototype, "defaultCurrencyCode", void 0);
|
|
81
|
+
__decorate([
|
|
82
|
+
Property({ type: 'boolean' }),
|
|
83
|
+
Index(),
|
|
84
|
+
__metadata("design:type", Boolean)
|
|
85
|
+
], Country.prototype, "isActive", void 0);
|
|
86
|
+
__decorate([
|
|
87
|
+
Property({ type: 'boolean' }),
|
|
88
|
+
__metadata("design:type", Boolean)
|
|
89
|
+
], Country.prototype, "isDefault", void 0);
|
|
90
|
+
__decorate([
|
|
91
|
+
Property({ type: 'integer' }),
|
|
92
|
+
__metadata("design:type", Number)
|
|
93
|
+
], Country.prototype, "sortOrder", void 0);
|
|
94
|
+
__decorate([
|
|
95
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
96
|
+
__metadata("design:type", Date)
|
|
97
|
+
], Country.prototype, "createdAt", void 0);
|
|
98
|
+
__decorate([
|
|
99
|
+
Property({ type: 'datetime', onUpdate: () => new Date() }),
|
|
100
|
+
__metadata("design:type", Date)
|
|
101
|
+
], Country.prototype, "updatedAt", void 0);
|
|
102
|
+
Country = __decorate([
|
|
103
|
+
GlobalEntity(),
|
|
104
|
+
Entity({ tableName: 'countries' })
|
|
105
|
+
], Country);
|
|
106
|
+
export { Country };
|
|
107
|
+
//# sourceMappingURL=country.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"country.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/country.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;AAEjE;;;;;;;GAOG;AAGI,IAAM,OAAO,GAAb,MAAM,OAAO;IAClB,CAAC,aAAa,CAAC,CASW;IAE1B,6EAA6E;IAE7E,IAAI,CAAU;IAGd,UAAU,CAAU;IAEpB,iEAAiE;IAEjE,WAAW,CAAU;IAErB,8FAA8F;IAE9F,KAAK,CAAU;IAEf,kGAAkG;IAElG,MAAM,CAAU;IAGhB,SAAS,CAAiB;IAE1B,yDAAyD;IAEzD,QAAQ,CAAiB;IAEzB,0CAA0C;IAE1C,UAAU,GAAY,KAAK,CAAC;IAE5B,wEAAwE;IAExE,mBAAmB,CAAiB;IAIpC,QAAQ,GAAY,IAAI,CAAC;IAEzB,yDAAyD;IAEzD,SAAS,GAAY,KAAK,CAAC;IAG3B,SAAS,GAAW,CAAC,CAAC;IAGtB,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAhDC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;;qCAC5B;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;;2CAC9C;AAIpB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;;4CAC9C;AAIrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;sCAC3B;AAIf;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;uCACzB;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CAC/B;AAI1B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;yCAC/B;AAIzB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;2CACF;AAI5B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;oDACpB;AAIpC;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,KAAK,EAAE;;yCACiB;AAIzB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;0CACH;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;0CACR;AAGtB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;0CAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;0CAAc;AA7DlB,OAAO;IAFnB,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;GACtB,OAAO,CA8DnB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* DictionaryTranslation — per-Language display-label override for a Country,
|
|
4
|
+
* Currency, or Language entry (feature 017 / R3).
|
|
5
|
+
*
|
|
6
|
+
* Polymorphic by `entryType`. Postgres cannot enforce a polymorphic FK to
|
|
7
|
+
* three different parent tables, so the parent-existence invariant is
|
|
8
|
+
* enforced at the service layer (`TranslationService.upsert`) inside the
|
|
9
|
+
* same transaction that performs the write. The `language_code` FK to
|
|
10
|
+
* `languages(code)` IS database-enforced — that's the only side the schema
|
|
11
|
+
* knows is uniform. ON DELETE CASCADE there: hard-deleting a Language
|
|
12
|
+
* wipes its translations everywhere.
|
|
13
|
+
*/
|
|
14
|
+
export declare class DictionaryTranslation {
|
|
15
|
+
[OptionalProps]?: 'createdAt' | 'updatedAt';
|
|
16
|
+
entryType: 'country' | 'currency' | 'language';
|
|
17
|
+
/** The natural code of the parent entry. 2 chars for country, 3 for currency, 2..12 for language. */
|
|
18
|
+
entryCode: string;
|
|
19
|
+
/** The locale this translation is FOR. FK to `languages(code)` ON DELETE CASCADE. */
|
|
20
|
+
languageCode: string;
|
|
21
|
+
label: string;
|
|
22
|
+
createdAt: Date;
|
|
23
|
+
updatedAt: Date;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=dictionary-translation.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionary-translation.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/dictionary-translation.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAGrF;;;;;;;;;;;GAWG;AACH,qBAEa,qBAAqB;IAChC,CAAC,aAAa,CAAC,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IAG5C,SAAS,EAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAEhD,qGAAqG;IAErG,SAAS,EAAG,MAAM,CAAC;IAEnB,qFAAqF;IAGrF,YAAY,EAAG,MAAM,CAAC;IAGtB,KAAK,EAAG,MAAM,CAAC;IAGf,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
/**
|
|
13
|
+
* DictionaryTranslation — per-Language display-label override for a Country,
|
|
14
|
+
* Currency, or Language entry (feature 017 / R3).
|
|
15
|
+
*
|
|
16
|
+
* Polymorphic by `entryType`. Postgres cannot enforce a polymorphic FK to
|
|
17
|
+
* three different parent tables, so the parent-existence invariant is
|
|
18
|
+
* enforced at the service layer (`TranslationService.upsert`) inside the
|
|
19
|
+
* same transaction that performs the write. The `language_code` FK to
|
|
20
|
+
* `languages(code)` IS database-enforced — that's the only side the schema
|
|
21
|
+
* knows is uniform. ON DELETE CASCADE there: hard-deleting a Language
|
|
22
|
+
* wipes its translations everywhere.
|
|
23
|
+
*/
|
|
24
|
+
let DictionaryTranslation = class DictionaryTranslation {
|
|
25
|
+
[OptionalProps];
|
|
26
|
+
entryType;
|
|
27
|
+
/** The natural code of the parent entry. 2 chars for country, 3 for currency, 2..12 for language. */
|
|
28
|
+
entryCode;
|
|
29
|
+
/** The locale this translation is FOR. FK to `languages(code)` ON DELETE CASCADE. */
|
|
30
|
+
languageCode;
|
|
31
|
+
label;
|
|
32
|
+
createdAt = new Date();
|
|
33
|
+
updatedAt = new Date();
|
|
34
|
+
};
|
|
35
|
+
__decorate([
|
|
36
|
+
PrimaryKey({ type: 'string', length: 16 }),
|
|
37
|
+
__metadata("design:type", String)
|
|
38
|
+
], DictionaryTranslation.prototype, "entryType", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
PrimaryKey({ type: 'string', length: 12 }),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], DictionaryTranslation.prototype, "entryCode", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
PrimaryKey({ type: 'string', length: 12 }),
|
|
45
|
+
Index(),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], DictionaryTranslation.prototype, "languageCode", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
Property({ type: 'string', length: 160 }),
|
|
50
|
+
__metadata("design:type", String)
|
|
51
|
+
], DictionaryTranslation.prototype, "label", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
54
|
+
__metadata("design:type", Date)
|
|
55
|
+
], DictionaryTranslation.prototype, "createdAt", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
Property({ type: 'datetime', onUpdate: () => new Date() }),
|
|
58
|
+
__metadata("design:type", Date)
|
|
59
|
+
], DictionaryTranslation.prototype, "updatedAt", void 0);
|
|
60
|
+
DictionaryTranslation = __decorate([
|
|
61
|
+
GlobalEntity(),
|
|
62
|
+
Entity({ tableName: 'dictionary_translations' })
|
|
63
|
+
], DictionaryTranslation);
|
|
64
|
+
export { DictionaryTranslation };
|
|
65
|
+
//# sourceMappingURL=dictionary-translation.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionary-translation.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/dictionary-translation.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;AAEjE;;;;;;;;;;;GAWG;AAGI,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAChC,CAAC,aAAa,CAAC,CAA6B;IAG5C,SAAS,CAAuC;IAEhD,qGAAqG;IAErG,SAAS,CAAU;IAEnB,qFAAqF;IAGrF,YAAY,CAAU;IAGtB,KAAK,CAAU;IAGf,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAnBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;wDACK;AAIhD;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;wDACxB;AAKnB;IAFC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC1C,KAAK,EAAE;;2DACc;AAGtB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;oDAC3B;AAGf;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;wDAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;wDAAc;AAtBlB,qBAAqB;IAFjC,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,yBAAyB,EAAE,CAAC;GACpC,qBAAqB,CAuBjC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* LanguageCountry — many-to-many association between Languages and the
|
|
4
|
+
* Countries they are primarily associated with (feature 017).
|
|
5
|
+
*
|
|
6
|
+
* Used by storefront locale auto-detection ("user is in DE, prefer de-DE
|
|
7
|
+
* if the channel offers it"). The `is_primary` flag pins at most one
|
|
8
|
+
* primary Language per Country (partial unique index in the migration).
|
|
9
|
+
*/
|
|
10
|
+
export declare class LanguageCountry {
|
|
11
|
+
[OptionalProps]?: 'createdAt' | 'isPrimary';
|
|
12
|
+
languageCode: string;
|
|
13
|
+
countryCode: string;
|
|
14
|
+
isPrimary: boolean;
|
|
15
|
+
createdAt: Date;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=language-country.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-country.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/language-country.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAGrF;;;;;;;GAOG;AACH,qBAEa,eAAe;IAC1B,CAAC,aAAa,CAAC,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IAG5C,YAAY,EAAG,MAAM,CAAC;IAItB,WAAW,EAAG,MAAM,CAAC;IAGrB,SAAS,EAAE,OAAO,CAAS;IAG3B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
/**
|
|
13
|
+
* LanguageCountry — many-to-many association between Languages and the
|
|
14
|
+
* Countries they are primarily associated with (feature 017).
|
|
15
|
+
*
|
|
16
|
+
* Used by storefront locale auto-detection ("user is in DE, prefer de-DE
|
|
17
|
+
* if the channel offers it"). The `is_primary` flag pins at most one
|
|
18
|
+
* primary Language per Country (partial unique index in the migration).
|
|
19
|
+
*/
|
|
20
|
+
let LanguageCountry = class LanguageCountry {
|
|
21
|
+
[OptionalProps];
|
|
22
|
+
languageCode;
|
|
23
|
+
countryCode;
|
|
24
|
+
isPrimary = false;
|
|
25
|
+
createdAt = new Date();
|
|
26
|
+
};
|
|
27
|
+
__decorate([
|
|
28
|
+
PrimaryKey({ type: 'string', length: 12 }),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], LanguageCountry.prototype, "languageCode", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
PrimaryKey({ type: 'string', length: 2 }),
|
|
33
|
+
Index(),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], LanguageCountry.prototype, "countryCode", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
Property({ type: 'boolean' }),
|
|
38
|
+
__metadata("design:type", Boolean)
|
|
39
|
+
], LanguageCountry.prototype, "isPrimary", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
42
|
+
__metadata("design:type", Date)
|
|
43
|
+
], LanguageCountry.prototype, "createdAt", void 0);
|
|
44
|
+
LanguageCountry = __decorate([
|
|
45
|
+
GlobalEntity(),
|
|
46
|
+
Entity({ tableName: 'language_countries' })
|
|
47
|
+
], LanguageCountry);
|
|
48
|
+
export { LanguageCountry };
|
|
49
|
+
//# sourceMappingURL=language-country.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-country.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/language-country.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;AAEjE;;;;;;;GAOG;AAGI,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,CAAC,aAAa,CAAC,CAA6B;IAG5C,YAAY,CAAU;IAItB,WAAW,CAAU;IAGrB,SAAS,GAAY,KAAK,CAAC;IAG3B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAXC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;qDACrB;AAItB;IAFC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACzC,KAAK,EAAE;;oDACa;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;kDACH;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;kDAAc;AAdlB,eAAe;IAF3B,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;GAC/B,eAAe,CAe3B"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import type { Redis } from 'ioredis';
|
|
3
|
+
import { type CurrencyAdminPort, type CurrencyReadPort, type DictionaryReferenceRegistryPort, type DictionaryValidator as DictionaryValidatorPort, type LanguageAdminPort, type LanguageReadPort } from '@endora-commerce/contracts';
|
|
4
|
+
import type { AuditPort } from '@endora-commerce/platform/kernel';
|
|
5
|
+
import type { ModuleContext } from '@endora-commerce/platform/kernel';
|
|
6
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
7
|
+
import { DictionaryCache } from './services/dictionary-cache.js';
|
|
8
|
+
import { Country } from './entities/country.entity.js';
|
|
9
|
+
import { DictionaryTranslation } from './entities/dictionary-translation.entity.js';
|
|
10
|
+
import { LanguageCountry } from './entities/language-country.entity.js';
|
|
11
|
+
/**
|
|
12
|
+
* `dictionaries` — the module that owns the cache everybody else announces to
|
|
13
|
+
* (feature 072, wave 2, T112).
|
|
14
|
+
*
|
|
15
|
+
* Two things move *into* this module, and both were in a composition root only
|
|
16
|
+
* because the module could not reach them.
|
|
17
|
+
*
|
|
18
|
+
* **The invalidation listeners.** Each root subscribed to `currencies.changed`
|
|
19
|
+
* and `languages.changed` and reached back in to call
|
|
20
|
+
* `dictionaries.handle.validator.invalidate()` and
|
|
21
|
+
* `cache?.invalidateAll()`. That is this module's own cache being dropped by
|
|
22
|
+
* somebody else, spelled twice. `ctx.subscribe` puts it where it belongs — and
|
|
23
|
+
* gates it, so the drops stop when the module does. The direction stays the one
|
|
24
|
+
* wave 1 established: `currencies` and `languages` *announce*, and whoever
|
|
25
|
+
* caches their data subscribes. Declaring the reverse call as a dependency
|
|
26
|
+
* produces a real cycle, because this module reads both their entities.
|
|
27
|
+
*
|
|
28
|
+
* **The second `LanguageService`.** `plugin.ts` built one here —
|
|
29
|
+
* `new LanguageService(emFactory, invalidateDictionaryState, auditLog)` — while
|
|
30
|
+
* `languages` built another that announces on the EventBus. Two services
|
|
31
|
+
* writing the same table through different invalidation mechanisms, which is
|
|
32
|
+
* the divergence this transition keeps finding. `languages` provides the port
|
|
33
|
+
* now, so this module resolves it and there is one.
|
|
34
|
+
*
|
|
35
|
+
* `requireAdmin` stops being optional. Its absence removed the admin surface
|
|
36
|
+
* rather than opening it — the `comparisons` shape, safe but still a surface
|
|
37
|
+
* that exists or not depending on whether an argument was passed.
|
|
38
|
+
*
|
|
39
|
+
* `dictionaryValidator` is a **port**, and its `HOST_REGISTERED_PORTS` entry
|
|
40
|
+
* goes: `blog`, `taxes`, `organizations`, `orders` and `catalog` resolve it to
|
|
41
|
+
* validate country, region, currency and language codes on write, and a
|
|
42
|
+
* composition with dictionaries off should refuse those writes rather than
|
|
43
|
+
* accept unvalidated ones.
|
|
44
|
+
*
|
|
45
|
+
* **Feature 075, Phase C.** Seventeen imports of `currencies`' and `languages`'
|
|
46
|
+
* files are gone. Ten of them read those modules' *entities* — this module owns
|
|
47
|
+
* the admin screen and the storefront registry for two tables it does not own,
|
|
48
|
+
* so it queried them directly, and deactivation drops no tables: the registry
|
|
49
|
+
* kept listing currencies and the validator kept accepting codes out of modules
|
|
50
|
+
* an operator had switched off. Both are now the four published ports, each
|
|
51
|
+
* resolved with `lazyPort` and handed to the service that needs it, never
|
|
52
|
+
* captured. The two event names are constants in `@endora-commerce/contracts` now, which is
|
|
53
|
+
* where a string belongs; the direction is untouched — `currencies` and
|
|
54
|
+
* `languages` announce, this module subscribes, and neither learns who listens.
|
|
55
|
+
*/
|
|
56
|
+
export interface DictionariesCradle {
|
|
57
|
+
readonly emFactory: () => EntityManager;
|
|
58
|
+
readonly auditLogService: AuditPort;
|
|
59
|
+
readonly redis: Redis | undefined;
|
|
60
|
+
readonly requireAdmin: RequireAdminFactory;
|
|
61
|
+
/** Owned by `currencies`; this module's admin surface serves both. */
|
|
62
|
+
readonly currencyReadPort: CurrencyReadPort;
|
|
63
|
+
readonly currencyAdminPort: CurrencyAdminPort;
|
|
64
|
+
/** Owned by `languages`; there used to be a second service built here. */
|
|
65
|
+
readonly languageReadPort: LanguageReadPort;
|
|
66
|
+
readonly languageAdminPort: LanguageAdminPort;
|
|
67
|
+
readonly dictionaryCache: DictionaryCache | undefined;
|
|
68
|
+
readonly dictionaryValidator: DictionaryValidatorPort;
|
|
69
|
+
readonly dictionaryInvalidator: () => Promise<void>;
|
|
70
|
+
readonly countryReferenceRegistry: DictionaryReferenceRegistryPort;
|
|
71
|
+
}
|
|
72
|
+
export declare function registerModule(ctx: ModuleContext): void;
|
|
73
|
+
/**
|
|
74
|
+
* The module's persisted entity classes, on the `./backend` subpath, as one
|
|
75
|
+
* array and **no named class export** (D-168).
|
|
76
|
+
*
|
|
77
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
78
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
79
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
80
|
+
* which is the third source of `check:module-boundary`'s `table→owner` map and
|
|
81
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
82
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
83
|
+
*/
|
|
84
|
+
export declare const entities: (typeof Country | typeof LanguageCountry | typeof DictionaryTranslation)[];
|
|
85
|
+
//# 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;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAErB,KAAK,+BAA+B,EACpC,KAAK,mBAAmB,IAAI,uBAAuB,EACnD,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAEtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAYjE,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,sEAAsE;IACtE,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,QAAQ,CAAC,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,mBAAmB,EAAE,uBAAuB,CAAC;IACtD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,QAAQ,CAAC,wBAAwB,EAAE,+BAA+B,CAAC;CACpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAiLvD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,4EAIpB,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { CURRENCY_CHANGED_EVENT, LANGUAGE_CHANGED_EVENT, } from '@endora-commerce/contracts';
|
|
2
|
+
import { lazyPort } from '@endora-commerce/platform/kernel';
|
|
3
|
+
import { DictionaryCache } from './services/dictionary-cache.js';
|
|
4
|
+
import { DictionaryValidator as DictionaryValidatorService } from './services/dictionary-validator.js';
|
|
5
|
+
import { DictionaryReadService } from './services/dictionary-read-service.js';
|
|
6
|
+
import { LabelResolver } from './services/label-resolver.js';
|
|
7
|
+
import { TranslationService } from './services/translation-service.js';
|
|
8
|
+
import { CountryService } from './services/country-service.js';
|
|
9
|
+
import { CountryReferenceRegistry } from './services/country-reference-registry.js';
|
|
10
|
+
import { registerCountryCurrencyReference } from './services/country-currency-reference.js';
|
|
11
|
+
import { LanguageCountryService } from './services/language-country-service.js';
|
|
12
|
+
import { runDictionarySeedReconciler } from './services/seed-reconciler.js';
|
|
13
|
+
import { registerDictionaryAdminRoutes } from './routes.admin.js';
|
|
14
|
+
import { registerDictionaryStorefrontRoutes } from './routes.storefront.js';
|
|
15
|
+
import { Country } from './entities/country.entity.js';
|
|
16
|
+
import { DictionaryTranslation } from './entities/dictionary-translation.entity.js';
|
|
17
|
+
import { LanguageCountry } from './entities/language-country.entity.js';
|
|
18
|
+
export function registerModule(ctx) {
|
|
19
|
+
ctx.di.register({
|
|
20
|
+
dictionaryCache: ctx
|
|
21
|
+
.asFunction(({ redis }) => redis ? new DictionaryCache(redis) : undefined)
|
|
22
|
+
.singleton(),
|
|
23
|
+
/** Drops both layers: the validator's in-process map and the Redis cache. */
|
|
24
|
+
dictionaryInvalidator: ctx
|
|
25
|
+
.asFunction(() => async () => {
|
|
26
|
+
const { dictionaryValidator, dictionaryCache } = ctx.cradle();
|
|
27
|
+
dictionaryValidator.invalidate();
|
|
28
|
+
// Swallowed rather than left floating: a drop that lands after the
|
|
29
|
+
// server closed surfaces as an unhandled rejection from ioredis's
|
|
30
|
+
// socket-close path. A cache that could not be dropped because the
|
|
31
|
+
// process is going away has nothing to be stale for.
|
|
32
|
+
await dictionaryCache?.invalidateAll().catch(() => undefined);
|
|
33
|
+
})
|
|
34
|
+
.singleton(),
|
|
35
|
+
});
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Feature 077 (D-87 drain) — who still points at a country?
|
|
38
|
+
//
|
|
39
|
+
// `CountryService.remove` used to answer that with raw counts over
|
|
40
|
+
// `addresses`, `taxes` and `organizations`, and the orphan report with twelve
|
|
41
|
+
// `left join`s over eleven tables in nine modules. Every one of them named a
|
|
42
|
+
// table this module does not own, in a string no import-level boundary check
|
|
43
|
+
// can see. Contributors push a descriptor from their own boot hook now.
|
|
44
|
+
//
|
|
45
|
+
// A plain `ctx.di.register`, not a port: a contributor resolves it from a boot
|
|
46
|
+
// hook, and a boot hook that resolved a transient gate would stop the backend
|
|
47
|
+
// from starting the moment this module was switched off. Enumeration policy is
|
|
48
|
+
// stated at the class.
|
|
49
|
+
ctx.di.register({
|
|
50
|
+
countryReferenceRegistry: ctx
|
|
51
|
+
.asFunction(() => new CountryReferenceRegistry())
|
|
52
|
+
.singleton(),
|
|
53
|
+
});
|
|
54
|
+
ctx.di.providePort('dictionaryValidator', ctx
|
|
55
|
+
.asFunction(({ emFactory }) => new DictionaryValidatorService(emFactory, lazyPort(ctx, 'currencyReadPort'), lazyPort(ctx, 'languageReadPort')))
|
|
56
|
+
.singleton());
|
|
57
|
+
// Whoever caches currency or language data drops its own when told. This
|
|
58
|
+
// module is one of them, and now says so itself rather than being reached
|
|
59
|
+
// into by a root.
|
|
60
|
+
//
|
|
61
|
+
// The two sales-channel events are issue #101's other half. The registry a
|
|
62
|
+
// storefront reads is *scoped to a channel* — `languages` and `currencies`
|
|
63
|
+
// are filtered by the channel's own lists, and `defaults` come off its
|
|
64
|
+
// `defaultLanguage` / `defaultCurrency` — so a channel write invalidates this
|
|
65
|
+
// cache exactly as a currency or language write does. Nothing subscribed
|
|
66
|
+
// before, so a PATCH of the default channel's languages served the old
|
|
67
|
+
// registry until the entry's hour expired, and a flag move (D-51) changed
|
|
68
|
+
// which channel the platform-wide read resolves without dropping anything.
|
|
69
|
+
// `identity_changed` covers the PATCH, `lifecycle_changed` the move and the
|
|
70
|
+
// deactivations. Both are EventBus announcements — no manifest dependency,
|
|
71
|
+
// and none is wanted: `sales_channels` must not know who caches its rows.
|
|
72
|
+
const invalidationEvents = [
|
|
73
|
+
CURRENCY_CHANGED_EVENT,
|
|
74
|
+
LANGUAGE_CHANGED_EVENT,
|
|
75
|
+
'sales_channels.identity_changed',
|
|
76
|
+
'sales_channels.lifecycle_changed',
|
|
77
|
+
];
|
|
78
|
+
for (const event of invalidationEvents) {
|
|
79
|
+
ctx.subscribe(event, async () => {
|
|
80
|
+
await ctx.cradle().dictionaryInvalidator();
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* `countries.default_currency_code` points at `currencies`, so this module is
|
|
85
|
+
* one of that dictionary's consumers and contributes a descriptor like any
|
|
86
|
+
* other. `blocking: false` — the column's own foreign key is
|
|
87
|
+
* `on delete set null`, so the reference is worth reporting to an operator
|
|
88
|
+
* about to blank it but must not refuse the delete, which is exactly what the
|
|
89
|
+
* hand-written version said in a comment and expressed by leaving the count
|
|
90
|
+
* out of a sum.
|
|
91
|
+
*
|
|
92
|
+
* A contribution hook, kept separate from the seeding hook below: it must run
|
|
93
|
+
* whatever this module's state, and pushes an inert descriptor into an ungated
|
|
94
|
+
* registry (D-62). `product_feeds/backend.ts` is the shipped example of the
|
|
95
|
+
* pair.
|
|
96
|
+
*/
|
|
97
|
+
ctx.onBoot(() => {
|
|
98
|
+
registerCountryCurrencyReference(lazyPort(ctx, 'currencyReferenceRegistry'), ctx.cradle().emFactory);
|
|
99
|
+
});
|
|
100
|
+
ctx.onBoot(async () => {
|
|
101
|
+
// Seeds the ISO reference data. The two tables it seeds that this module
|
|
102
|
+
// does not own — `currencies` and `languages` — go through their owners'
|
|
103
|
+
// published ports since feature 077's D-87 drain; before that they were raw
|
|
104
|
+
// statements naming those tables here.
|
|
105
|
+
await runDictionarySeedReconciler(ctx.cradle().emFactory, {
|
|
106
|
+
currencySeed: lazyPort(ctx, 'currencySeedPort'),
|
|
107
|
+
currencyRead: lazyPort(ctx, 'currencyReadPort'),
|
|
108
|
+
languageSeed: lazyPort(ctx, 'languageSeedPort'),
|
|
109
|
+
languageRead: lazyPort(ctx, 'languageReadPort'),
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
ctx.routes(async (app) => {
|
|
113
|
+
const { emFactory, auditLogService, requireAdmin, dictionaryCache, dictionaryInvalidator, countryReferenceRegistry, } = ctx.cradle();
|
|
114
|
+
// Resolved once per route registration and handed down, never captured into
|
|
115
|
+
// a singleton: `lazyPort` returns a proxy that resolves the gate per call,
|
|
116
|
+
// so a switched-off owner is answered at the call and not at composition.
|
|
117
|
+
const currencyRead = lazyPort(ctx, 'currencyReadPort');
|
|
118
|
+
const languageRead = lazyPort(ctx, 'languageReadPort');
|
|
119
|
+
await registerDictionaryAdminRoutes(app, {
|
|
120
|
+
emFactory,
|
|
121
|
+
countryService: new CountryService(emFactory, dictionaryInvalidator, auditLogService, () => countryReferenceRegistry),
|
|
122
|
+
currencyRead,
|
|
123
|
+
currencyAdmin: lazyPort(ctx, 'currencyAdminPort'),
|
|
124
|
+
languageRead,
|
|
125
|
+
languageAdmin: lazyPort(ctx, 'languageAdminPort'),
|
|
126
|
+
languageCountryService: new LanguageCountryService(emFactory, languageRead, dictionaryInvalidator, auditLogService),
|
|
127
|
+
translationService: new TranslationService(emFactory, currencyRead, languageRead, dictionaryInvalidator, auditLogService),
|
|
128
|
+
invalidateDictionaryState: dictionaryInvalidator,
|
|
129
|
+
requireAdmin,
|
|
130
|
+
countryReferences: countryReferenceRegistry,
|
|
131
|
+
currencyReferences: lazyPort(ctx, 'currencyReferenceRegistry'),
|
|
132
|
+
languageReferences: lazyPort(ctx, 'languageReferenceRegistry'),
|
|
133
|
+
});
|
|
134
|
+
await registerDictionaryStorefrontRoutes(app, {
|
|
135
|
+
readService: new DictionaryReadService(emFactory, currencyRead, languageRead, dictionaryCache, new LabelResolver(emFactory, currencyRead, languageRead)),
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The module's persisted entity classes, on the `./backend` subpath, as one
|
|
141
|
+
* array and **no named class export** (D-168).
|
|
142
|
+
*
|
|
143
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
144
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
145
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
146
|
+
* which is the third source of `check:module-boundary`'s `table→owner` map and
|
|
147
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
148
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
149
|
+
*/
|
|
150
|
+
export const entities = [
|
|
151
|
+
Country,
|
|
152
|
+
DictionaryTranslation,
|
|
153
|
+
LanguageCountry,
|
|
154
|
+
];
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
3
|
+
import { type CurrencyAdminPort, type CurrencyReadPort, type DictionaryReferenceRegistryPort, type LanguageAdminPort, type LanguageReadPort } from '@endora-commerce/contracts';
|
|
4
|
+
import type { CountryService } from './services/country-service.js';
|
|
5
|
+
import type { LanguageCountryService } from './services/language-country-service.js';
|
|
6
|
+
import type { TranslationService } from './services/translation-service.js';
|
|
7
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
8
|
+
/**
|
|
9
|
+
* Feature 075, Phase C — this module hosts the admin screen for two tables it
|
|
10
|
+
* does not own, which is why the write side crosses a boundary by design
|
|
11
|
+
* (`languages.ts` and `currencies.ts` both say so). It used to cross by holding
|
|
12
|
+
* the owners' service classes and serialising their entities; it now holds the
|
|
13
|
+
* four published ports and serialises the records they return, so the screen
|
|
14
|
+
* refuses while an owner is switched off instead of editing rows nobody is
|
|
15
|
+
* serving.
|
|
16
|
+
*/
|
|
17
|
+
export interface DictionaryAdminRoutesDeps {
|
|
18
|
+
emFactory: () => EntityManager;
|
|
19
|
+
countryService: CountryService;
|
|
20
|
+
currencyRead: CurrencyReadPort;
|
|
21
|
+
currencyAdmin: CurrencyAdminPort;
|
|
22
|
+
languageRead: LanguageReadPort;
|
|
23
|
+
languageAdmin: LanguageAdminPort;
|
|
24
|
+
languageCountryService: LanguageCountryService;
|
|
25
|
+
translationService: TranslationService;
|
|
26
|
+
invalidateDictionaryState: () => Promise<void>;
|
|
27
|
+
requireAdmin: RequireAdminFactory;
|
|
28
|
+
/**
|
|
29
|
+
* One reference registry per dictionary, each owned by the module that owns
|
|
30
|
+
* the table being pointed at (feature 077, D-87). The orphan report is the
|
|
31
|
+
* one caller that needs all three: it asks each consumer which codes it
|
|
32
|
+
* stores and subtracts the codes the dictionary really has.
|
|
33
|
+
*/
|
|
34
|
+
countryReferences: DictionaryReferenceRegistryPort;
|
|
35
|
+
currencyReferences: DictionaryReferenceRegistryPort;
|
|
36
|
+
languageReferences: DictionaryReferenceRegistryPort;
|
|
37
|
+
}
|
|
38
|
+
export declare function registerDictionaryAdminRoutes(app: FastifyInstance, deps: DictionaryAdminRoutesDeps): Promise<void>;
|
|
39
|
+
//# sourceMappingURL=routes.admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.admin.d.ts","sourceRoot":"","sources":["../../src/backend/routes.admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAYL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAErB,KAAK,+BAA+B,EACpC,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAItB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EACV,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAKvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAIrF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG5E;;;;;;;;GAQG;AACH,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,iBAAiB,CAAC;IACjC,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,yBAAyB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,iBAAiB,EAAE,+BAA+B,CAAC;IACnD,kBAAkB,EAAE,+BAA+B,CAAC;IACpD,kBAAkB,EAAE,+BAA+B,CAAC;CACrD;AASD,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAqPf"}
|