@endora-commerce/mod-i18n 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 +52 -0
- package/dist/backend/cli/coverage.d.ts +29 -0
- package/dist/backend/cli/coverage.d.ts.map +1 -0
- package/dist/backend/cli/coverage.js +84 -0
- package/dist/backend/cli/coverage.js.map +1 -0
- package/dist/backend/cli/reload.d.ts +35 -0
- package/dist/backend/cli/reload.d.ts.map +1 -0
- package/dist/backend/cli/reload.js +18 -0
- package/dist/backend/cli/reload.js.map +1 -0
- package/dist/backend/entities/translation-bundle.entity.d.ts +23 -0
- package/dist/backend/entities/translation-bundle.entity.d.ts.map +1 -0
- package/dist/backend/entities/translation-bundle.entity.js +69 -0
- package/dist/backend/entities/translation-bundle.entity.js.map +1 -0
- package/dist/backend/index.d.ts +164 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +134 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +41 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +74 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/services/bundle-loader.d.ts +49 -0
- package/dist/backend/services/bundle-loader.d.ts.map +1 -0
- package/dist/backend/services/bundle-loader.js +84 -0
- package/dist/backend/services/bundle-loader.js.map +1 -0
- package/dist/backend/services/bundle-reconciler.d.ts +82 -0
- package/dist/backend/services/bundle-reconciler.d.ts.map +1 -0
- package/dist/backend/services/bundle-reconciler.js +38 -0
- package/dist/backend/services/bundle-reconciler.js.map +1 -0
- package/dist/backend/services/i18n-service.d.ts +67 -0
- package/dist/backend/services/i18n-service.d.ts.map +1 -0
- package/dist/backend/services/i18n-service.js +323 -0
- package/dist/backend/services/i18n-service.js.map +1 -0
- package/dist/backend/services/missing-key-logger.d.ts +52 -0
- package/dist/backend/services/missing-key-logger.d.ts.map +1 -0
- package/dist/backend/services/missing-key-logger.js +37 -0
- package/dist/backend/services/missing-key-logger.js.map +1 -0
- package/dist/manifest.d.ts +214 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +245 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260507T091405_i18n_admin_i18n_init.d.ts +30 -0
- package/dist/migrations/20260507T091405_i18n_admin_i18n_init.d.ts.map +1 -0
- package/dist/migrations/20260507T091405_i18n_admin_i18n_init.js +50 -0
- package/dist/migrations/20260507T091405_i18n_admin_i18n_init.js.map +1 -0
- package/dist/migrations/index.d.ts +23 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +23 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/i18n.md +166 -0
- package/i18n/en.json +1957 -0
- package/i18n/pl.json +1957 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
|
|
2
|
+
|
|
3
|
+
# @endora-commerce/mod-i18n
|
|
4
|
+
|
|
5
|
+
Per-user Admin UI language preference and module-scoped translation bundles. English is the platform-wide fallback (FR-013 / FR-016).
|
|
6
|
+
|
|
7
|
+
## What this is
|
|
8
|
+
|
|
9
|
+
An **Endora Commerce module package**. Its module id is `_i18n` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
|
|
10
|
+
|
|
11
|
+
A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
|
|
12
|
+
|
|
13
|
+
## Entry points
|
|
14
|
+
|
|
15
|
+
| Import | Contents |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `@endora-commerce/mod-i18n` | the module manifest — its id, version, dependencies, settings and activation |
|
|
18
|
+
| `@endora-commerce/mod-i18n/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
|
|
19
|
+
| `@endora-commerce/mod-i18n/migrations` | the module’s own schema migrations, in the order the platform runs them |
|
|
20
|
+
|
|
21
|
+
## Depends on
|
|
22
|
+
|
|
23
|
+
Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
|
|
24
|
+
|
|
25
|
+
**Endora packages**
|
|
26
|
+
|
|
27
|
+
- `@endora-commerce/contracts`
|
|
28
|
+
- `@endora-commerce/platform`
|
|
29
|
+
|
|
30
|
+
**Third-party**
|
|
31
|
+
|
|
32
|
+
- `@mikro-orm/core` ^6
|
|
33
|
+
- `@mikro-orm/migrations` ^6
|
|
34
|
+
- `@mikro-orm/postgresql` ^6
|
|
35
|
+
- `fastify` ^5
|
|
36
|
+
- `zod` ^4
|
|
37
|
+
|
|
38
|
+
## What the tarball carries
|
|
39
|
+
|
|
40
|
+
- `dist/` — the compiled JavaScript and its type declarations
|
|
41
|
+
- `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
|
|
42
|
+
- `docs/` — the package’s own pages in the Endora Commerce documentation site
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm add @endora-commerce/mod-i18n
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Licence
|
|
51
|
+
|
|
52
|
+
MIT — the text is in `LICENSE`, beside this file.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `_i18n coverage` — the translation-coverage snapshot (feature 021), as a
|
|
3
|
+
* host-run command (feature 080, T042b / D-160.9).
|
|
4
|
+
*
|
|
5
|
+
* Prints the same payload the admin route returns. Useful for developers and
|
|
6
|
+
* for CI; in `--strict` mode it exits non-zero when any module in the filtered
|
|
7
|
+
* set has `missingCount > 0`.
|
|
8
|
+
*
|
|
9
|
+
* Flags:
|
|
10
|
+
* --json Emit JSON (default: human-readable table)
|
|
11
|
+
* --strict Exit 1 when any missingCount > 0 for the filtered set
|
|
12
|
+
* --modules a,b,c Filter by module id (repeatable as CSV)
|
|
13
|
+
* --languages pl,en Filter by supported admin language code (repeatable as CSV)
|
|
14
|
+
* --include-keys all Match the route's includeKeys=all
|
|
15
|
+
*/
|
|
16
|
+
import { type SupportedAdminLanguage } from '@endora-commerce/contracts';
|
|
17
|
+
import type { ModuleCliCommandContext } from '@endora-commerce/contracts';
|
|
18
|
+
import { type ModuleContext } from '@endora-commerce/platform/kernel';
|
|
19
|
+
interface ParsedArgs {
|
|
20
|
+
json: boolean;
|
|
21
|
+
strict: boolean;
|
|
22
|
+
modules?: string[];
|
|
23
|
+
languages?: SupportedAdminLanguage[];
|
|
24
|
+
includeKeys?: 'all' | 'missing';
|
|
25
|
+
}
|
|
26
|
+
export declare function parseArgs(argv: readonly string[]): ParsedArgs;
|
|
27
|
+
export declare function coverage({ ctx, argv, out, err, }: ModuleCliCommandContext<ModuleContext>): Promise<number>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../../src/backend/cli/coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAGhF,UAAU,UAAU;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,WAAW,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;CACjC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAsB7D;AA+BD,wBAAsB,QAAQ,CAAC,EAC7B,GAAG,EACH,IAAI,EACJ,GAAG,EACH,GAAG,GACJ,EAAE,uBAAuB,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B1D"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `_i18n coverage` — the translation-coverage snapshot (feature 021), as a
|
|
3
|
+
* host-run command (feature 080, T042b / D-160.9).
|
|
4
|
+
*
|
|
5
|
+
* Prints the same payload the admin route returns. Useful for developers and
|
|
6
|
+
* for CI; in `--strict` mode it exits non-zero when any module in the filtered
|
|
7
|
+
* set has `missingCount > 0`.
|
|
8
|
+
*
|
|
9
|
+
* Flags:
|
|
10
|
+
* --json Emit JSON (default: human-readable table)
|
|
11
|
+
* --strict Exit 1 when any missingCount > 0 for the filtered set
|
|
12
|
+
* --modules a,b,c Filter by module id (repeatable as CSV)
|
|
13
|
+
* --languages pl,en Filter by supported admin language code (repeatable as CSV)
|
|
14
|
+
* --include-keys all Match the route's includeKeys=all
|
|
15
|
+
*/
|
|
16
|
+
import { SUPPORTED_LANGUAGES } from '@endora-commerce/contracts';
|
|
17
|
+
import { lazyPort } from '@endora-commerce/platform/kernel';
|
|
18
|
+
export function parseArgs(argv) {
|
|
19
|
+
const out = { json: false, strict: false };
|
|
20
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
21
|
+
const a = argv[i];
|
|
22
|
+
if (a === '--json')
|
|
23
|
+
out.json = true;
|
|
24
|
+
else if (a === '--strict')
|
|
25
|
+
out.strict = true;
|
|
26
|
+
else if (a === '--modules' || a === '--module') {
|
|
27
|
+
out.modules = (argv[i + 1] ?? '').split(',').filter(Boolean);
|
|
28
|
+
i += 1;
|
|
29
|
+
}
|
|
30
|
+
else if (a === '--languages' || a === '--language') {
|
|
31
|
+
const supported = new Set(SUPPORTED_LANGUAGES);
|
|
32
|
+
out.languages = (argv[i + 1] ?? '')
|
|
33
|
+
.split(',')
|
|
34
|
+
.filter((v) => supported.has(v));
|
|
35
|
+
i += 1;
|
|
36
|
+
}
|
|
37
|
+
else if (a === '--include-keys') {
|
|
38
|
+
const v = argv[i + 1];
|
|
39
|
+
if (v === 'all' || v === 'missing')
|
|
40
|
+
out.includeKeys = v;
|
|
41
|
+
i += 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function printTable(snapshot, out) {
|
|
47
|
+
out(`Coverage snapshot @ ${snapshot.capturedAt}`);
|
|
48
|
+
if (snapshot.modules.length === 0) {
|
|
49
|
+
out(' (no modules in the filtered set)');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
for (const m of snapshot.modules) {
|
|
53
|
+
out(` ${m.moduleId}`);
|
|
54
|
+
for (const l of m.languages) {
|
|
55
|
+
out(` ${l.languageCode} missing=${String(l.missingCount).padStart(3, ' ')} ` +
|
|
56
|
+
`fellBackToEn=${String(l.fellBackToEnCount).padStart(3, ' ')}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export async function coverage({ ctx, argv, out, err, }) {
|
|
61
|
+
const args = parseArgs(argv);
|
|
62
|
+
// This module's own port, resolved exactly as `backend.ts` resolves it — one
|
|
63
|
+
// `I18nService` for the composition rather than a second one built here.
|
|
64
|
+
const i18nService = lazyPort(ctx, 'adminI18nService');
|
|
65
|
+
const snapshot = await i18nService.getCoverageSnapshot({
|
|
66
|
+
...(args.modules ? { moduleIds: args.modules } : {}),
|
|
67
|
+
...(args.languages ? { languageCodes: args.languages } : {}),
|
|
68
|
+
...(args.includeKeys ? { includeKeys: args.includeKeys } : {}),
|
|
69
|
+
});
|
|
70
|
+
if (args.json)
|
|
71
|
+
out(JSON.stringify({ data: snapshot }, null, 2));
|
|
72
|
+
else
|
|
73
|
+
printTable(snapshot, out);
|
|
74
|
+
if (args.strict) {
|
|
75
|
+
const violators = snapshot.modules.flatMap((m) => m.languages.filter((l) => l.missingCount > 0).map((l) => ({ m, l })));
|
|
76
|
+
if (violators.length > 0) {
|
|
77
|
+
err(`[i18n coverage] strict mode: ${violators.length} (module, language) pair(s) are ` +
|
|
78
|
+
`missing entries.`);
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/backend/cli/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `_i18n reload` — hot-reload translations (feature 080, T042b / D-160.9).
|
|
3
|
+
*
|
|
4
|
+
* Re-reads every module's on-disk i18n JSON bundles into the
|
|
5
|
+
* `translation_bundles` table, bumping each row's version. A running backend
|
|
6
|
+
* serves the new strings on its next read (the per-language cache rebuilds when
|
|
7
|
+
* it sees a newer `MAX(version)`), so no restart is needed — admins just refresh
|
|
8
|
+
* the page, or the Admin UI "Reload translations" button does it for them.
|
|
9
|
+
*
|
|
10
|
+
* Note: the storefront ships its UI strings compiled in-tree
|
|
11
|
+
* (`storefront/lib/i18n/messages.ts`); those are not DB-backed and require a
|
|
12
|
+
* storefront rebuild/redeploy. This command covers the admin bundles.
|
|
13
|
+
*
|
|
14
|
+
* ## What composing bought here
|
|
15
|
+
*
|
|
16
|
+
* This was `scripts/reload.ts`, and it imported `resolvedManifestEntries` from
|
|
17
|
+
* `_lifecycle` to get the module list — the single entry in this module's
|
|
18
|
+
* `check:module-boundary` shard, escalated rather than cut because *"a
|
|
19
|
+
* module-owned CLI entry point has no container and no `ModuleContext` … and
|
|
20
|
+
* what it needs is the deployment's module registry, which is a
|
|
21
|
+
* composition-root input by nature"*. Both halves of that sentence are answered
|
|
22
|
+
* by the host running the command: `resolvedModuleRegistry` is a
|
|
23
|
+
* `PLATFORM_OWNED_NAMES` entry any module may read off its cradle, and the
|
|
24
|
+
* `I18nService` is this module's own registration rather than a second instance
|
|
25
|
+
* built here.
|
|
26
|
+
*
|
|
27
|
+
* It is deliberately the **composition's** registry rather than a fresh
|
|
28
|
+
* `resolvedManifestEntries()` call, which is what makes the command's answer
|
|
29
|
+
* the same as the running platform's: core, this deployment's overlay modules
|
|
30
|
+
* and every installed package (feature 080, T032).
|
|
31
|
+
*/
|
|
32
|
+
import type { ModuleCliCommandContext } from '@endora-commerce/contracts';
|
|
33
|
+
import { type ModuleContext } from '@endora-commerce/platform/kernel';
|
|
34
|
+
export declare function reload({ ctx, out, err, }: ModuleCliCommandContext<ModuleContext>): Promise<number>;
|
|
35
|
+
//# sourceMappingURL=reload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reload.d.ts","sourceRoot":"","sources":["../../../src/backend/cli/reload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAYhF,wBAAsB,MAAM,CAAC,EAC3B,GAAG,EACH,GAAG,EACH,GAAG,GACJ,EAAE,uBAAuB,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { lazyPort } from '@endora-commerce/platform/kernel';
|
|
2
|
+
import { reconcileBundles, } from '../services/bundle-reconciler.js';
|
|
3
|
+
export async function reload({ ctx, out, err, }) {
|
|
4
|
+
const entries = ctx.cradle().resolvedModuleRegistry;
|
|
5
|
+
// This module's own port, resolved exactly as `backend.ts` resolves it.
|
|
6
|
+
const i18nService = lazyPort(ctx, 'adminI18nService');
|
|
7
|
+
const result = await reconcileBundles(entries, i18nService, {
|
|
8
|
+
info: (msg) => out(msg),
|
|
9
|
+
warn: (msg) => err(msg),
|
|
10
|
+
});
|
|
11
|
+
out(`[i18n reload] done — installed=${result.installed} skipped=${result.skipped} ` +
|
|
12
|
+
`failed=${result.failed}`);
|
|
13
|
+
for (const failure of result.failures) {
|
|
14
|
+
err(`[i18n reload] "${failure.moduleId}" (${failure.reason}) at ${failure.modulePath}`);
|
|
15
|
+
}
|
|
16
|
+
return result.failed > 0 ? 1 : 0;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=reload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reload.js","sourceRoot":"","sources":["../../../src/backend/cli/reload.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,QAAQ,EAAsB,MAAM,kCAAkC,CAAC;AAChF,OAAO,EACL,gBAAgB,GAEjB,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAC3B,GAAG,EACH,GAAG,EACH,GAAG,GACoC;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAoB,CAAC,sBAAsB,CAAC;IACtE,wEAAwE;IACxE,MAAM,WAAW,GAAG,QAAQ,CAAc,GAAG,EAAE,kBAAkB,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE;QAC1D,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;QACvB,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;KACxB,CAAC,CAAC;IACH,GAAG,CACD,kCAAkC,MAAM,CAAC,SAAS,YAAY,MAAM,CAAC,OAAO,GAAG;QAC7E,UAAU,MAAM,CAAC,MAAM,EAAE,CAC5B,CAAC;IACF,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,GAAG,CAAC,kBAAkB,OAAO,CAAC,QAAQ,MAAM,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
import type { SupportedAdminLanguage, TranslationBundleEntries } from '@endora-commerce/contracts';
|
|
3
|
+
/**
|
|
4
|
+
* Translation Bundle — feature 019 / data-model.md §1.1.
|
|
5
|
+
*
|
|
6
|
+
* One row per `(module_id, language_code)`. JSONB `entries` carries the
|
|
7
|
+
* flat translation key → string map. `version` defaults to
|
|
8
|
+
* `nextval(translation_bundles_version_seq)` so every UPSERT bumps the
|
|
9
|
+
* vector and the in-process resolver cache invalidates on its next
|
|
10
|
+
* `MAX(version)` check (research §R9).
|
|
11
|
+
*
|
|
12
|
+
* No FK on `module_id` — see migration 040 for the rationale.
|
|
13
|
+
*/
|
|
14
|
+
export declare class TranslationBundle {
|
|
15
|
+
[OptionalProps]?: 'version' | 'installedAt' | 'updatedAt';
|
|
16
|
+
moduleId: string;
|
|
17
|
+
languageCode: SupportedAdminLanguage;
|
|
18
|
+
entries: TranslationBundleEntries;
|
|
19
|
+
version: number;
|
|
20
|
+
installedAt: Date;
|
|
21
|
+
updatedAt: Date;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=translation-bundle.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-bundle.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/translation-bundle.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAErF,OAAO,KAAK,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEnG;;;;;;;;;;GAUG;AACH,qBAMa,iBAAiB;IAC5B,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAG1D,QAAQ,EAAG,MAAM,CAAC;IAGlB,YAAY,EAAG,sBAAsB,CAAC;IAGtC,OAAO,EAAE,wBAAwB,CAAM;IAOvC,OAAO,EAAG,MAAM,CAAC;IAGjB,WAAW,EAAE,IAAI,CAAc;IAG/B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
* Translation Bundle — feature 019 / data-model.md §1.1.
|
|
14
|
+
*
|
|
15
|
+
* One row per `(module_id, language_code)`. JSONB `entries` carries the
|
|
16
|
+
* flat translation key → string map. `version` defaults to
|
|
17
|
+
* `nextval(translation_bundles_version_seq)` so every UPSERT bumps the
|
|
18
|
+
* vector and the in-process resolver cache invalidates on its next
|
|
19
|
+
* `MAX(version)` check (research §R9).
|
|
20
|
+
*
|
|
21
|
+
* No FK on `module_id` — see migration 040 for the rationale.
|
|
22
|
+
*/
|
|
23
|
+
let TranslationBundle = class TranslationBundle {
|
|
24
|
+
[OptionalProps];
|
|
25
|
+
moduleId;
|
|
26
|
+
languageCode;
|
|
27
|
+
entries = {};
|
|
28
|
+
version;
|
|
29
|
+
installedAt = new Date();
|
|
30
|
+
updatedAt = new Date();
|
|
31
|
+
};
|
|
32
|
+
__decorate([
|
|
33
|
+
PrimaryKey({ type: 'string', length: 64 }),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], TranslationBundle.prototype, "moduleId", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
PrimaryKey({ type: 'string', length: 12 }),
|
|
38
|
+
__metadata("design:type", String)
|
|
39
|
+
], TranslationBundle.prototype, "languageCode", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
Property({ type: 'json', columnType: 'jsonb' }),
|
|
42
|
+
__metadata("design:type", Object)
|
|
43
|
+
], TranslationBundle.prototype, "entries", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
Property({
|
|
46
|
+
type: 'bigint',
|
|
47
|
+
columnType: 'bigint',
|
|
48
|
+
defaultRaw: "nextval('translation_bundles_version_seq')",
|
|
49
|
+
}),
|
|
50
|
+
__metadata("design:type", Number)
|
|
51
|
+
], TranslationBundle.prototype, "version", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
Property({ type: 'Date' }),
|
|
54
|
+
__metadata("design:type", Date)
|
|
55
|
+
], TranslationBundle.prototype, "installedAt", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
Property({ type: 'Date', onUpdate: () => new Date() }),
|
|
58
|
+
__metadata("design:type", Date)
|
|
59
|
+
], TranslationBundle.prototype, "updatedAt", void 0);
|
|
60
|
+
TranslationBundle = __decorate([
|
|
61
|
+
GlobalEntity(),
|
|
62
|
+
Entity({ tableName: 'translation_bundles' }),
|
|
63
|
+
Index({
|
|
64
|
+
properties: ['languageCode'],
|
|
65
|
+
name: 'idx_translation_bundles_language_code',
|
|
66
|
+
})
|
|
67
|
+
], TranslationBundle);
|
|
68
|
+
export { TranslationBundle };
|
|
69
|
+
//# sourceMappingURL=translation-bundle.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-bundle.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/translation-bundle.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;AAGjE;;;;;;;;;;GAUG;AAOI,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAC5B,CAAC,aAAa,CAAC,CAA2C;IAG1D,QAAQ,CAAU;IAGlB,YAAY,CAA0B;IAGtC,OAAO,GAA6B,EAAE,CAAC;IAOvC,OAAO,CAAU;IAGjB,WAAW,GAAS,IAAI,IAAI,EAAE,CAAC;IAG/B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AApBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;mDACzB;AAGlB;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;uDACL;AAGtC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;;kDACT;AAOvC;IALC,QAAQ,CAAC;QACR,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,QAAQ;QACpB,UAAU,EAAE,4CAA4C;KACzD,CAAC;;kDACe;AAGjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8BACd,IAAI;sDAAc;AAG/B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAC5C,IAAI;oDAAc;AAvBlB,iBAAiB;IAN7B,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC;IAC5C,KAAK,CAAC;QACL,UAAU,EAAE,CAAC,cAAc,CAAC;QAC5B,IAAI,EAAE,uCAAuC;KAC9C,CAAC;GACW,iBAAiB,CAwB7B"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import type { FastifyRequest } from 'fastify';
|
|
3
|
+
import { type ModuleContext } from '@endora-commerce/platform/kernel';
|
|
4
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
5
|
+
import { I18nService } from './services/i18n-service.js';
|
|
6
|
+
import { type I18nReconcileEntry, type I18nReconcileResult } from './services/bundle-reconciler.js';
|
|
7
|
+
import { TranslationBundle } from './entities/translation-bundle.entity.js';
|
|
8
|
+
/**
|
|
9
|
+
* `_i18n` — the module whose boot-time work does not run in `ctx.onBoot`
|
|
10
|
+
* (feature 072, wave 1, T089).
|
|
11
|
+
*
|
|
12
|
+
* Seventeen conversions before this one put their boot-time work in
|
|
13
|
+
* `ctx.onBoot`. This one does not, and the reason is worth stating because the
|
|
14
|
+
* natural move is to make it uniform with the other seventeen.
|
|
15
|
+
*
|
|
16
|
+
* This module walks the lifecycle manifest registry to refresh every module's
|
|
17
|
+
* `translation_bundles` rows from disk. It reaches that registry through a lazy
|
|
18
|
+
* accessor, because `_lifecycle`'s orchestrator is constructed *after* it — the
|
|
19
|
+
* chicken-and-egg the original `registry?: T | (() => T | undefined)` option
|
|
20
|
+
* shape exists to break. The reconcile therefore runs from the `ctx.routes`
|
|
21
|
+
* callback, at **plugin attach**, which is the point at which every root has
|
|
22
|
+
* finished composing and the accessor is guaranteed to answer.
|
|
23
|
+
*
|
|
24
|
+
* D-45 made the boot phase the last thing a root does before it builds the
|
|
25
|
+
* server, so `ctx.onBoot` would find the registry today too. The reconcile stays
|
|
26
|
+
* where it is all the same: the two placements are not equivalent in general (a
|
|
27
|
+
* root that composes without building a server runs one and not the other), and
|
|
28
|
+
* the failure mode if the accessor ever answered `undefined` again is silent —
|
|
29
|
+
* the reconciler's documented behaviour for an absent registry is to return
|
|
30
|
+
* `{installed: 0, skipped: 0, failed: 0}`, i.e. success. Every module's
|
|
31
|
+
* translation bundles would quietly stop being refreshed, with no exception and
|
|
32
|
+
* no warning, and the first symptom would be screens rendering raw i18n keys
|
|
33
|
+
* some time after somebody edits a JSON bundle. Moving it therefore needs
|
|
34
|
+
* evidence, not tidiness. `test/unit/_i18n/reconcile-timing.test.ts` pins the
|
|
35
|
+
* placement, because the harness cannot: since issue #158 `setupBackendServer`
|
|
36
|
+
* does pass the resolved registry and this reconcile does run there, but a
|
|
37
|
+
* composed server can only observe that it happened — never that it happened at
|
|
38
|
+
* plugin attach rather than during registration or boot.
|
|
39
|
+
*
|
|
40
|
+
* **The third `AdminUserService` goes away.** `composition.ts` built one
|
|
41
|
+
* specially for this module — `new AdminUserService(em)`, with no audit writer
|
|
42
|
+
* — while `admin_users` built its own with one, and the harness a third.
|
|
43
|
+
* Nothing was being lost: the only method reached from here is
|
|
44
|
+
* `setPreferredLanguage`, which is explicitly marked `command-coverage-ignore`
|
|
45
|
+
* as a personal UI setting rather than an audited mutation. But it is the same
|
|
46
|
+
* shape this wave has now removed six times — an optional constructor argument,
|
|
47
|
+
* silently omitted, defaulting the unsafe way — and resolving the service from
|
|
48
|
+
* the container means there is one of it, and it is the audited one.
|
|
49
|
+
*
|
|
50
|
+
* `deps.orm` was in the option interface and read nowhere in the factory body.
|
|
51
|
+
* It does not reappear here.
|
|
52
|
+
*/
|
|
53
|
+
/**
|
|
54
|
+
* The slice of the lifecycle registry this module reads: every registered
|
|
55
|
+
* module's manifest and the path it was loaded from, which is all
|
|
56
|
+
* `reconcileBundles` needs to find `<module>/<bundlesDir>/<lang>.json`.
|
|
57
|
+
*
|
|
58
|
+
* Declared here rather than imported from `_lifecycle` (feature 075, Phase C).
|
|
59
|
+
* `lifecycleManifestRegistry` is a name a **composition root** supplies —
|
|
60
|
+
* which modules a deployment ships is a root's input, and `_lifecycle`'s own
|
|
61
|
+
* `LoadedManifestRegistry` additionally carries a dependency graph and each
|
|
62
|
+
* module's install hooks, none of which a bundle reconcile has any business
|
|
63
|
+
* seeing. Stating the demand is what keeps the two apart.
|
|
64
|
+
*/
|
|
65
|
+
export interface I18nManifestRegistryView {
|
|
66
|
+
readonly modules: {
|
|
67
|
+
values(): Iterable<I18nReconcileEntry>;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Reads the lifecycle registry lazily; `undefined` until `_lifecycle` exists. */
|
|
71
|
+
export type LifecycleManifestRegistryAccessor = () => I18nManifestRegistryView | undefined;
|
|
72
|
+
export interface AdminI18nCradle {
|
|
73
|
+
readonly emFactory: () => EntityManager;
|
|
74
|
+
readonly requireAdmin: RequireAdminFactory;
|
|
75
|
+
readonly adminContextResolver: (req: FastifyRequest) => {
|
|
76
|
+
adminUserId: string;
|
|
77
|
+
};
|
|
78
|
+
readonly lifecycleManifestRegistry: LifecycleManifestRegistryAccessor;
|
|
79
|
+
readonly adminI18nService: I18nService;
|
|
80
|
+
readonly adminI18nReconciler: AdminI18nReconciler;
|
|
81
|
+
}
|
|
82
|
+
/** The lifecycle-orchestrator-shaped hook surface (feature 019 FR-016). */
|
|
83
|
+
export interface AdminI18nReconciler {
|
|
84
|
+
install(args: {
|
|
85
|
+
moduleId: string;
|
|
86
|
+
modulePath: string;
|
|
87
|
+
bundlesDir: string;
|
|
88
|
+
}): Promise<{
|
|
89
|
+
installed: string[];
|
|
90
|
+
}>;
|
|
91
|
+
remove(moduleId: string): Promise<{
|
|
92
|
+
removed: number;
|
|
93
|
+
}>;
|
|
94
|
+
/** Re-read every module's on-disk bundles without a restart (`i18n:reload`). */
|
|
95
|
+
reloadAll(): Promise<I18nReconcileResult>;
|
|
96
|
+
}
|
|
97
|
+
export declare function registerModule(ctx: ModuleContext): void;
|
|
98
|
+
/**
|
|
99
|
+
* The module's own entity classes, as one array — D-168.
|
|
100
|
+
*
|
|
101
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
102
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
103
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
104
|
+
* which is the third source of `check:module-boundary`'s `table→owner` map and
|
|
105
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
106
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
107
|
+
*
|
|
108
|
+
* The class is **not** exported by name beside it (D-168): the ORM registers
|
|
109
|
+
* whichever copy this array carries, and a second, source-reached copy of a
|
|
110
|
+
* MikroORM entity is a lookup miss rather than a type error. A test that needs
|
|
111
|
+
* the runtime class takes it out of this array by name
|
|
112
|
+
* (`backend/test/helpers/package-entities.ts`).
|
|
113
|
+
*/
|
|
114
|
+
export declare const entities: (typeof TranslationBundle)[];
|
|
115
|
+
/**
|
|
116
|
+
* The rest of this module's published surface, and why each name is on it.
|
|
117
|
+
*
|
|
118
|
+
* Every one of these was reached relatively from `backend/` before the move,
|
|
119
|
+
* and a relative reach into a package's `src` is the defect
|
|
120
|
+
* `check:singleton-identity` refuses: the composed platform loads this
|
|
121
|
+
* package's `dist`, so a second evaluation of the same file is a second copy of
|
|
122
|
+
* everything module-scoped in it. Publishing the names is what gives those
|
|
123
|
+
* callers a spelling that lands on the copy the platform holds.
|
|
124
|
+
*
|
|
125
|
+
* * `buildErrorTranslationTargets` and its shapes **stood here and are gone**
|
|
126
|
+
* (`specs/117-instance-bring-up/` FR-030). The routing map is now
|
|
127
|
+
* `@endora-commerce/platform`'s, at `kernel/i18n/error-translation.ts`,
|
|
128
|
+
* beside `request-language.ts` — the producer of the other
|
|
129
|
+
* `ErrorEnvelopeOptions` member a composition root injects.
|
|
130
|
+
*
|
|
131
|
+
* The line it moved across is worth stating here as well as there, because
|
|
132
|
+
* this is where a reader looks for it: *the routing is derived from
|
|
133
|
+
* manifests, the translation is a service*. `I18nService.translate` — what
|
|
134
|
+
* the envelope's `translateErrorMessage` closure calls — resolves a key
|
|
135
|
+
* against a bundle and is `_i18n`'s. The derivation translated nothing; it
|
|
136
|
+
* read `manifest.errorCodes` off the **resolved manifest set**, which is a
|
|
137
|
+
* composition-root input, and it had no consumer inside this package at
|
|
138
|
+
* all: this barrel re-exported it and nothing here called it. That is
|
|
139
|
+
* T040b's criterion 8, the test `absolutizePublicUrl` moved out of `email`
|
|
140
|
+
* under, met exactly.
|
|
141
|
+
*
|
|
142
|
+
* `ERROR_TRANSLATION_KEYS` and `composeErrorTranslationTargets` stood here
|
|
143
|
+
* too and were **deleted** in feature 090 Phase 4: the first was the prefix
|
|
144
|
+
* chain's static table, the second the transitional composition that laid
|
|
145
|
+
* the declarations over it so the migration could be delivered one module
|
|
146
|
+
* per merge request. All eighteen owners have declared, so there is nothing
|
|
147
|
+
* left to lay over.
|
|
148
|
+
* * `I18nService` — the resolver the reconciler, the CLI commands and the
|
|
149
|
+
* acceptance probe construct over an `EntityManager` of their own.
|
|
150
|
+
* * `MissingKeyLogger` — the resolver's collaborator, constructed the same way.
|
|
151
|
+
* * `loadModuleBundles` / `BundleLoadError` and their shapes — the filesystem
|
|
152
|
+
* reader every module's bundles arrive through.
|
|
153
|
+
* * `reconcileBundles` and its shapes — the boot pass itself, which the
|
|
154
|
+
* acceptance probe runs against a live instance.
|
|
155
|
+
* * `registerI18nAdminRoutes` / `I18nAdminDeps` — the HTTP surface, registered
|
|
156
|
+
* against a bare Fastify instance by its own contract test.
|
|
157
|
+
*/
|
|
158
|
+
export { I18nService } from './services/i18n-service.js';
|
|
159
|
+
export { MissingKeyLogger } from './services/missing-key-logger.js';
|
|
160
|
+
export { BundleLoadError, loadModuleBundles, type BundleLoaderOptions, type LoadedBundles, } from './services/bundle-loader.js';
|
|
161
|
+
export { reconcileBundles, type I18nReconcileFailure, } from './services/bundle-reconciler.js';
|
|
162
|
+
export { registerI18nAdminRoutes, type I18nAdminDeps } from './routes.admin.js';
|
|
163
|
+
export type { I18nReconcileEntry, I18nReconcileResult };
|
|
164
|
+
//# 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,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE;QAAE,MAAM,IAAI,QAAQ,CAAC,kBAAkB,CAAC,CAAA;KAAE,CAAC;CAC9D;AAED,kFAAkF;AAClF,MAAM,MAAM,iCAAiC,GAAG,MAC5C,wBAAwB,GACxB,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAChF,QAAQ,CAAC,yBAAyB,EAAE,iCAAiC,CAAC;IACtE,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC;IACvC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;CACnD;AAED,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,IAAI,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,gFAAgF;IAChF,SAAS,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA6DvD;AAiBD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,8BAEpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChF,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC"}
|