libmodulor 0.23.0 → 0.24.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/CHANGELOG.md +17 -0
- package/README.md +154 -2
- package/dist/esm/apps/Helper/src/lib/project.js +3 -3
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.d.ts +2 -1
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.js +8 -0
- package/dist/esm/convention.d.ts +3 -0
- package/dist/esm/convention.js +3 -0
- package/dist/esm/dt/DataTypes.d.ts +1 -2
- package/dist/esm/dt/base/TObject.js +1 -1
- package/dist/esm/i18n/index.d.ts +1 -1
- package/dist/esm/i18n/locales/de.d.ts +2 -0
- package/dist/esm/i18n/locales/de.js +54 -0
- package/dist/esm/i18n/locales/es.d.ts +2 -0
- package/dist/esm/i18n/locales/es.js +54 -0
- package/dist/esm/i18n/types.d.ts +3 -2
- package/dist/esm/index.babel.d.ts +1 -0
- package/dist/esm/index.babel.js +1 -0
- package/dist/esm/index.node-stricli-cli.d.ts +2 -0
- package/dist/esm/index.node-stricli-cli.js +2 -0
- package/dist/esm/index.vite.d.ts +1 -1
- package/dist/esm/index.vite.js +1 -1
- package/dist/esm/index.webpack.d.ts +1 -0
- package/dist/esm/index.webpack.js +1 -0
- package/dist/esm/std/I18nManager.d.ts +12 -0
- package/dist/esm/std/impl/NodeFSManager.js +1 -1
- package/dist/esm/std/impl/SimpleMapI18nManager.d.ts +6 -1
- package/dist/esm/std/impl/SimpleMapI18nManager.js +41 -12
- package/dist/esm/target/lib/server/AuthenticationChecker.js +1 -1
- package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
- package/dist/esm/target/lib/server/ServerRequestHandler.js +2 -2
- package/dist/esm/target/lib/server-express/funcs.js +2 -2
- package/dist/esm/target/lib/server-hono/funcs.js +2 -2
- package/dist/esm/target/lib/server-node/funcs.js +1 -1
- package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.d.ts +12 -0
- package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.js +118 -0
- package/dist/esm/testing/AppTester.js +4 -5
- package/dist/esm/testing/UCDefASTParser.d.ts +24 -6
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +4 -5
- package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +38 -11
- package/dist/esm/testing/impl/VitestAppTestSuiteRunner.d.ts +1 -1
- package/dist/esm/testing/impl/VitestAppTestSuiteRunner.js +17 -2
- package/dist/esm/testing/opts.js +1 -1
- package/dist/esm/testing/workers/AppTestSuiteRunner.d.ts +2 -0
- package/dist/esm/testing/workers/UCExecutor.js +1 -1
- package/dist/esm/testing/workers/checkers/AppI18nChecker.d.ts +8 -2
- package/dist/esm/testing/workers/checkers/AppI18nChecker.js +44 -2
- package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +12 -12
- package/dist/esm/uc/impl/HTTPUCTransporter.js +2 -2
- package/dist/esm/uc/impl/KnexUCDataStore.js +2 -2
- package/dist/esm/uc/index.d.ts +0 -1
- package/dist/esm/uc/index.js +0 -1
- package/dist/esm/uc/workers/UCExecChecker.js +1 -1
- package/dist/esm/utils/bundling/babel/plugin.d.ts +2 -0
- package/dist/esm/utils/bundling/babel/plugin.js +38 -0
- package/dist/esm/utils/bundling/funcs.d.ts +6 -0
- package/dist/esm/utils/bundling/funcs.js +20 -0
- package/dist/esm/utils/bundling/typescript.d.ts +3 -0
- package/dist/esm/utils/bundling/typescript.js +61 -0
- package/dist/esm/utils/bundling/vite/plugin.d.ts +6 -0
- package/dist/esm/utils/bundling/vite/plugin.js +17 -0
- package/dist/esm/utils/bundling/webpack/loader.d.ts +2 -0
- package/dist/esm/utils/bundling/webpack/loader.js +12 -0
- package/dist/esm/utils/http/HTTPRequestBuilder.js +1 -1
- package/dist/esm/utils/ioc/bindCommon.js +1 -1
- package/dist/esm/utils/terminal/fmt.js +1 -1
- package/package.json +30 -8
- package/pnpm-workspace.yaml +1 -4
- package/tsconfig.build.examples.json +8 -0
- package/tsconfig.json +1 -0
- package/vitest.config.ts +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.24.0 (2025-12-07)
|
|
4
|
+
|
|
5
|
+
**Highlights**
|
|
6
|
+
|
|
7
|
+
- Introduced `babel`, `vite` plugins and `webpack` loader => https://libmodulor.c100k.eu/docs/guides/bundle-target
|
|
8
|
+
- Introduced the `node-stricli-cli` target using @bloomberg's `stricli` library
|
|
9
|
+
- Introduced the `Playground` example, runnable locally, to play with all the features of `libmodulor` => https://libmodulor.c100k.eu/docs/examples/Playground
|
|
10
|
+
- Improved apps testing by making sure non-english languages are fully translated
|
|
11
|
+
- Improved apps testing performance by optimizing use cases testing using the `stream` transport
|
|
12
|
+
- Introduced `de` 🇩🇪 and `es` 🇪🇸 locales (see them in action in the `Playground`)
|
|
13
|
+
|
|
14
|
+
Some breaking changes but at the very low level. If your apps break, just follow the TypeScript errors and you should be good to go.
|
|
15
|
+
|
|
16
|
+
Also bumped React versions for the infamous [React2Shell vulnerability](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components).
|
|
17
|
+
|
|
18
|
+
See all the changes here : https://github.com/c100k/libmodulor/compare/v0.23.0...master
|
|
19
|
+
|
|
3
20
|
## v0.23.0 (2025-11-11)
|
|
4
21
|
|
|
5
22
|
See all the changes here : https://github.com/c100k/libmodulor/compare/v0.22.0...master
|
package/README.md
CHANGED
|
@@ -7,14 +7,166 @@ A TypeScript library to create platform-agnostic applications.
|
|
|
7
7
|
|
|
8
8
|
## 🚀 Getting Started
|
|
9
9
|
|
|
10
|
-
If you're discovering `libmodulor`, we recommend reading the [📖 Documentation](https://libmodulor.c100k.eu/docs) first.
|
|
10
|
+
If you're discovering `libmodulor`, we recommend reading the [📖 Documentation](https://libmodulor.c100k.eu/docs) first.
|
|
11
|
+
You'll find everything you need to get started : Concepts, Examples and Guides.
|
|
11
12
|
|
|
12
13
|
When you're ready, [🚀 Create a project](https://libmodulor.c100k.eu/docs/guides/create-project) and build the awesome idea you have in mind.
|
|
13
14
|
|
|
15
|
+
In the meantime, here is how to declare the four layers of `libmodulor`.
|
|
16
|
+
|
|
17
|
+
_These snippets are extracted from the [`Basic`](https://libmodulor.c100k.eu/docs/examples/Basic) example (check out the full example to get the full picture)._
|
|
18
|
+
|
|
19
|
+
### App
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
const appManifest = {
|
|
23
|
+
languageCodes: ['en', 'fr'],
|
|
24
|
+
name: 'Event',
|
|
25
|
+
ucReg: {
|
|
26
|
+
Register: {
|
|
27
|
+
action: 'Create',
|
|
28
|
+
icon: 'user',
|
|
29
|
+
name: 'Register',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
} satisfies AppManifest;
|
|
33
|
+
|
|
34
|
+
const appI18n: AppI18n = {
|
|
35
|
+
en: {
|
|
36
|
+
ucif_email_label: 'Your email address',
|
|
37
|
+
ucif_firstname_label: 'Your firstname',
|
|
38
|
+
ucif_lastname_label: 'Your lastname',
|
|
39
|
+
ucof_id_label: 'Your registration #',
|
|
40
|
+
ucof_ticketNumber_label: 'Your ticket #',
|
|
41
|
+
},
|
|
42
|
+
fr: {
|
|
43
|
+
ucif_email_label: 'Votre adresse email',
|
|
44
|
+
ucif_firstname_label: 'Votre prénom',
|
|
45
|
+
ucif_lastname_label: 'Votre nom',
|
|
46
|
+
ucof_id_label: "Votre # d'inscription",
|
|
47
|
+
ucof_ticketNumber_label: 'Votre # de ticket',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Use Case
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
interface RegisterInput extends UCInput {
|
|
56
|
+
email: UCInputFieldValue<Email>;
|
|
57
|
+
firstname: UCInputFieldValue<PersonFirstname>;
|
|
58
|
+
lastname: UCInputFieldValue<PersonLastname>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface RegisterOPI0 extends AggregateOPI0 {
|
|
62
|
+
amount: Amount;
|
|
63
|
+
ticketNumber: TicketNumber;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@injectable()
|
|
67
|
+
class RegisterClientMain implements UCMain<RegisterInput, RegisterOPI0> {
|
|
68
|
+
constructor(@inject('UCManager') private ucManager: UCManager) {}
|
|
69
|
+
|
|
70
|
+
public async exec({
|
|
71
|
+
uc,
|
|
72
|
+
}: UCMainInput<RegisterInput, RegisterOPI0>): Promise<
|
|
73
|
+
UCOutput<RegisterOPI0>
|
|
74
|
+
> {
|
|
75
|
+
const { aggregateId } = await this.ucManager.persist(uc);
|
|
76
|
+
|
|
77
|
+
const amount: Amount = 99.99; // Should come from some catalog in a real application
|
|
78
|
+
const ticketNumber: TicketNumber = 1; // Should come from a safely auto-generated sequence in a real application
|
|
79
|
+
|
|
80
|
+
return new UCOutputBuilder<RegisterOPI0>()
|
|
81
|
+
.add({
|
|
82
|
+
amount,
|
|
83
|
+
id: aggregateId,
|
|
84
|
+
ticketNumber,
|
|
85
|
+
})
|
|
86
|
+
.get();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const RegisterUCD: UCDef<RegisterInput, RegisterOPI0> = {
|
|
91
|
+
io: {
|
|
92
|
+
i: {
|
|
93
|
+
fields: {
|
|
94
|
+
email: {
|
|
95
|
+
type: new TEmail(),
|
|
96
|
+
},
|
|
97
|
+
firstname: {
|
|
98
|
+
type: new TPersonFirstname(),
|
|
99
|
+
},
|
|
100
|
+
lastname: {
|
|
101
|
+
type: new TPersonLastname(),
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
o: {
|
|
106
|
+
parts: {
|
|
107
|
+
_0: {
|
|
108
|
+
fields: {
|
|
109
|
+
amount: {
|
|
110
|
+
type: new TAmount('EUR'),
|
|
111
|
+
},
|
|
112
|
+
ticketNumber: {
|
|
113
|
+
type: new TTicketNumber(),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
order: ['ticketNumber', 'amount', 'id'],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
lifecycle: {
|
|
122
|
+
client: {
|
|
123
|
+
main: RegisterClientMain,
|
|
124
|
+
policy: EverybodyUCPolicy,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
metadata: {
|
|
128
|
+
action: 'Create',
|
|
129
|
+
icon: 'user',
|
|
130
|
+
name: 'Register',
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Product
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const productManifest: ProductManifest = {
|
|
139
|
+
appReg: [{ name: 'Event' }],
|
|
140
|
+
name: 'Eventer',
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const productI18n: ProductI18n = {
|
|
144
|
+
en: {
|
|
145
|
+
...I18nEN,
|
|
146
|
+
...appI18n.en,
|
|
147
|
+
},
|
|
148
|
+
fr: {
|
|
149
|
+
...I18nFR,
|
|
150
|
+
...appI18n.fr,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Target
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const container = new Container(CONTAINER_OPTS);
|
|
159
|
+
|
|
160
|
+
bindCommon(container);
|
|
161
|
+
bindNodeCore(container);
|
|
162
|
+
bindProduct(container, productManifest, productI18n);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
|
|
14
166
|
## 👨💻 Contribute
|
|
15
167
|
|
|
16
168
|
If you think you can help in any way, feel free to contact me (cf. `author` in `package.json`). I'd love to chat.
|
|
17
169
|
|
|
18
170
|
## ⚖️ License
|
|
19
171
|
|
|
20
|
-
[LGPL-3.0](https://github.com/c100k/libmodulor/blob/v0.
|
|
172
|
+
[LGPL-3.0](https://github.com/c100k/libmodulor/blob/v0.24.0/LICENSE)
|
|
@@ -86,8 +86,8 @@ export const PACKAGE_JSON = (name) => `{
|
|
|
86
86
|
"reflect-metadata": "^0.2.2"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@biomejs/biome": "^2.3.
|
|
90
|
-
"@types/node": "^24.10.
|
|
89
|
+
"@biomejs/biome": "^2.3.8",
|
|
90
|
+
"@types/node": "^24.10.1",
|
|
91
91
|
"@vitest/coverage-v8": "^3.2.4",
|
|
92
92
|
"buffer": "^6.0.3",
|
|
93
93
|
"cookie-parser": "^1.4.7",
|
|
@@ -95,7 +95,7 @@ export const PACKAGE_JSON = (name) => `{
|
|
|
95
95
|
"express-fileupload": "^1.5.2",
|
|
96
96
|
"fast-check": "^4.3.0",
|
|
97
97
|
"helmet": "^8.1.0",
|
|
98
|
-
"jose": "^6.1.
|
|
98
|
+
"jose": "^6.1.2",
|
|
99
99
|
"typescript": "^5.9.3",
|
|
100
100
|
"vite": "^6.4.1",
|
|
101
101
|
"vitest": "^3.2.4"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { AppName } from '../../../../app/index.js';
|
|
2
|
-
import { type UCDef, type UCInputFieldValue } from '../../../../uc/index.js';
|
|
2
|
+
import { type UCDef, type UCInputFieldValue, type UCName } from '../../../../uc/index.js';
|
|
3
3
|
import { type AppInput } from '../lib/app.js';
|
|
4
4
|
export interface TestAppInput extends AppInput {
|
|
5
5
|
appName: UCInputFieldValue<AppName>;
|
|
6
|
+
only: UCInputFieldValue<UCName>;
|
|
6
7
|
skipCoverage: UCInputFieldValue<boolean>;
|
|
7
8
|
updateSnapshots: UCInputFieldValue<boolean>;
|
|
8
9
|
}
|
|
@@ -34,6 +34,7 @@ let TestAppClientMain = class TestAppClientMain {
|
|
|
34
34
|
async exec({ uc }) {
|
|
35
35
|
const appsPath = uc.reqVal0('appsPath');
|
|
36
36
|
const appName = uc.reqVal0('appName');
|
|
37
|
+
const only = uc.rVal0('only');
|
|
37
38
|
const skipCoverage = uc.reqVal0('skipCoverage');
|
|
38
39
|
const updateSnapshots = uc.reqVal0('updateSnapshots');
|
|
39
40
|
const appPath = this.fsManager.path(appsPath, appName);
|
|
@@ -42,6 +43,7 @@ let TestAppClientMain = class TestAppClientMain {
|
|
|
42
43
|
}
|
|
43
44
|
await this.appTestSuiteRunner.exec({
|
|
44
45
|
appPath,
|
|
46
|
+
only,
|
|
45
47
|
skipCoverage,
|
|
46
48
|
updateSnapshots,
|
|
47
49
|
});
|
|
@@ -84,6 +86,12 @@ export const TestAppUCD = {
|
|
|
84
86
|
appName: {
|
|
85
87
|
type: new TString().setExamples([APP_NAME_PLACEHOLDER]),
|
|
86
88
|
},
|
|
89
|
+
only: {
|
|
90
|
+
cardinality: {
|
|
91
|
+
min: 0,
|
|
92
|
+
},
|
|
93
|
+
type: new TString().setExamples(['CreatePost']),
|
|
94
|
+
},
|
|
87
95
|
skipCoverage: {
|
|
88
96
|
type: new TBoolean().setDefaultValue(false),
|
|
89
97
|
},
|
package/dist/esm/convention.d.ts
CHANGED
|
@@ -36,6 +36,9 @@ export declare const UC_DEF_TYPE: string;
|
|
|
36
36
|
export declare const UC_INPUT_BASE: string;
|
|
37
37
|
export declare const UC_INPUT_FIELD_PATTERN: string;
|
|
38
38
|
export declare const UC_INPUT_SUFFIX: string;
|
|
39
|
+
export declare const UC_LIFECYCLE_PROP_NAME: string;
|
|
40
|
+
export declare const UC_LIFECYCLE_CLIENT_PROP_NAME: string;
|
|
41
|
+
export declare const UC_LIFECYCLE_SERVER_PROP_NAME: string;
|
|
39
42
|
export declare const UC_MAIN_SUFFIX: string;
|
|
40
43
|
export declare const UC_MAIN_CLIENT_SUFFIX: string;
|
|
41
44
|
export declare const UC_MAIN_SERVER_SUFFIX: string;
|
package/dist/esm/convention.js
CHANGED
|
@@ -46,6 +46,9 @@ export const UC_DEF_TYPE = 'UCDef';
|
|
|
46
46
|
export const UC_INPUT_BASE = 'UCInput';
|
|
47
47
|
export const UC_INPUT_FIELD_PATTERN = '^UCInputFieldValue<(.*)>$';
|
|
48
48
|
export const UC_INPUT_SUFFIX = 'Input';
|
|
49
|
+
export const UC_LIFECYCLE_PROP_NAME = 'lifecycle';
|
|
50
|
+
export const UC_LIFECYCLE_CLIENT_PROP_NAME = 'client';
|
|
51
|
+
export const UC_LIFECYCLE_SERVER_PROP_NAME = 'server';
|
|
49
52
|
export const UC_MAIN_SUFFIX = 'Main';
|
|
50
53
|
export const UC_MAIN_CLIENT_SUFFIX = `Client${UC_MAIN_SUFFIX}`;
|
|
51
54
|
export const UC_MAIN_SERVER_SUFFIX = `Server${UC_MAIN_SUFFIX}`;
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const DataTypes: DataType[];
|
|
1
|
+
export declare const DataTypes: readonly ["Address", "Amount", "ApiKey", "BarCode", "CSS", "Color", "ColorRGBA", "CompanyName", "CountryISO3166Alpha2", "CurrencyISO4217", "DateISO8601", "DateTimeFormat", "DirPath", "DomainName", "Email", "EmbeddedObject", "Emoji", "EncryptionKey", "ErrorMessage", "ExternalServiceId", "File", "FileExtension", "FileMimeType", "FileName", "FilePath", "FreeTextLong", "FreeTextShort", "Geolocation", "GitSSHURL", "HTML", "HTTPContentType", "HTTPMethod", "HTTPStatusNumber", "HostAddress", "HostPort", "IPv4", "IPv6", "JSONString", "JWT", "JavaScript", "JobTitle", "Markdown", "NumIndex", "Password", "Percentage", "PersonFirstname", "PersonFullname", "PersonInitials", "PersonLastname", "QRCode", "SQLQuery", "SSHPrivateKey", "SSHPublicKey", "SearchQuery", "SemVerVersion", "ShellCommand", "Slug", "Time", "Timestamp", "TransportType", "UIntDuration", "UIntQuantity", "URL", "URLPath", "UUID", "Username", "Year", "YesNo"];
|
package/dist/esm/i18n/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { I18N_DEFAULT_LANG } from './consts.js';
|
|
2
|
-
export type { I18n, I18nCoreKey, I18nCoreTranslations, I18nLanguageCode, I18nSource, I18nSourceSafe, I18nTranslation, I18nTranslationKey, } from './types.js';
|
|
2
|
+
export type { I18n, I18nCoreKey, I18nCoreTranslations, I18nEntry, I18nLanguageCode, I18nSource, I18nSourceSafe, I18nTranslation, I18nTranslationKey, } from './types.js';
|
|
3
3
|
export { WordingManager, type WordingManagerKey } from './WordingManager.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const I18nDE = {
|
|
2
|
+
dt_YesNo_N_desc: '',
|
|
3
|
+
dt_YesNo_N_label: 'Nein',
|
|
4
|
+
dt_YesNo_Y_desc: '',
|
|
5
|
+
dt_YesNo_Y_label: 'Ja',
|
|
6
|
+
uc_client_confirm_cancel: 'Abbrechen',
|
|
7
|
+
uc_client_confirm_confirm: 'Ja',
|
|
8
|
+
uc_client_confirm_message: '',
|
|
9
|
+
uc_client_confirm_title: 'Sind Sie sicher?',
|
|
10
|
+
uc_i_submit_changing: 'Laden',
|
|
11
|
+
uc_i_submit_idle: 'Speichern',
|
|
12
|
+
uc_i_submit_initializing: 'Laden',
|
|
13
|
+
uc_i_submit_submitting: 'Speichern',
|
|
14
|
+
validation_fieldsOr: 'Mindestens eines dieser Felder muss ausgefüllt werden: {{expected}}',
|
|
15
|
+
validation_format_ColorRGBA: 'Muss eine gültige RGBA-Farbe sein',
|
|
16
|
+
validation_format_DateISO8601: 'Muss ein gültiges Datum im ISO8601-Format sein',
|
|
17
|
+
validation_format_DirPath: 'Muss ein gültiger Verzeichnispfad sein',
|
|
18
|
+
validation_format_DomainName: 'Muss ein gültiger Domainname sein',
|
|
19
|
+
validation_format_Email: 'Muss eine gültige E-Mail-Adresse sein',
|
|
20
|
+
validation_format_FilePath: 'Muss ein gültiger Dateipfad sein',
|
|
21
|
+
validation_format_GitSSHURL: 'Muss eine gültige Git-SSH-URL sein',
|
|
22
|
+
validation_format_IPv4: 'Muss eine gültige IPv4-Adresse sein',
|
|
23
|
+
validation_format_IPv6: 'Muss eine gültige IPv6-Adresse sein',
|
|
24
|
+
validation_format_JSON: 'Muss ein gültiger JSON-String sein',
|
|
25
|
+
validation_format_JWT: 'Muss ein gültiges JWT sein',
|
|
26
|
+
validation_format_PersonFirstname: 'Muss ein gültiger Vorname sein, beginnend mit einem Großbuchstaben',
|
|
27
|
+
validation_format_PersonFullname: 'Muss ein gültiger vollständiger Name sein, beginnend mit einem Großbuchstaben',
|
|
28
|
+
validation_format_PersonInitials: 'Muss gültige Initialen aus Großbuchstaben enthalten',
|
|
29
|
+
validation_format_PersonLastname: 'Muss ein gültiger Nachname sein, beginnend mit einem Großbuchstaben',
|
|
30
|
+
validation_format_QRCode: 'Muss ein gültiger QR-Code im Base64-Format sein',
|
|
31
|
+
validation_format_SemVerVersion: 'Muss eine gültige SemVer-Version sein (X.X.X)',
|
|
32
|
+
validation_format_Slug: 'Darf nur Kleinbuchstaben, Ziffern und Bindestriche (-) enthalten',
|
|
33
|
+
validation_format_SSHPrivateKey: 'Muss ein gültiger privater SSH-Schlüssel sein',
|
|
34
|
+
validation_format_SSHPublicKey: 'Muss ein gültiger öffentlicher SSH-Schlüssel sein',
|
|
35
|
+
validation_format_Time: 'Muss eine gültige Uhrzeit sein',
|
|
36
|
+
validation_format_URL: 'Muss eine gültige URL sein',
|
|
37
|
+
validation_format_UUID: 'Muss eine gültige UUID sein',
|
|
38
|
+
validation_mandatory: 'Muss ausgefüllt werden',
|
|
39
|
+
validation_max: 'Muss kleiner oder gleich {{expected}} sein',
|
|
40
|
+
validation_maxCount: 'Darf höchstens {{expected}} Element(e) enthalten',
|
|
41
|
+
validation_maxLength: 'Darf höchstens {{expected}} Zeichen enthalten',
|
|
42
|
+
validation_min: 'Muss größer oder gleich {{expected}} sein',
|
|
43
|
+
validation_minCount: 'Muss mindestens {{expected}} Element(e) enthalten',
|
|
44
|
+
validation_minLength: 'Muss mindestens {{expected}} Zeichen enthalten',
|
|
45
|
+
validation_oneOf: 'Muss eines der Elemente der Liste sein',
|
|
46
|
+
validation_shape: 'Muss der erwarteten Objektstruktur entsprechen',
|
|
47
|
+
validation_type_array: 'Muss ein Array sein',
|
|
48
|
+
validation_type_boolean: 'Muss ein Boolescher Wert sein',
|
|
49
|
+
validation_type_int: 'Muss eine ganze Zahl sein',
|
|
50
|
+
validation_type_number: 'Muss eine Zahl sein',
|
|
51
|
+
validation_type_object: 'Muss ein Objekt sein',
|
|
52
|
+
validation_type_scalar: 'Muss ein Skalar sein',
|
|
53
|
+
validation_type_string: 'Muss ein String sein',
|
|
54
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const I18nES = {
|
|
2
|
+
dt_YesNo_N_desc: '',
|
|
3
|
+
dt_YesNo_N_label: 'No',
|
|
4
|
+
dt_YesNo_Y_desc: '',
|
|
5
|
+
dt_YesNo_Y_label: 'Sí',
|
|
6
|
+
uc_client_confirm_cancel: 'Cancelar',
|
|
7
|
+
uc_client_confirm_confirm: 'Sí',
|
|
8
|
+
uc_client_confirm_message: '',
|
|
9
|
+
uc_client_confirm_title: '¿Estás seguro?',
|
|
10
|
+
uc_i_submit_changing: 'Cargando',
|
|
11
|
+
uc_i_submit_idle: 'Guardar',
|
|
12
|
+
uc_i_submit_initializing: 'Cargando',
|
|
13
|
+
uc_i_submit_submitting: 'Guardando',
|
|
14
|
+
validation_fieldsOr: 'Al menos uno de estos campos debe estar completado: {{expected}}',
|
|
15
|
+
validation_format_ColorRGBA: 'Debe ser un color RGBA válido',
|
|
16
|
+
validation_format_DateISO8601: 'Debe ser una fecha válida con formato ISO8601',
|
|
17
|
+
validation_format_DirPath: 'Debe ser una ruta de directorio válida',
|
|
18
|
+
validation_format_DomainName: 'Debe ser un nombre de dominio válido',
|
|
19
|
+
validation_format_Email: 'Debe ser una dirección de correo válida',
|
|
20
|
+
validation_format_FilePath: 'Debe ser una ruta de archivo válida',
|
|
21
|
+
validation_format_GitSSHURL: 'Debe ser una URL SSH de Git válida',
|
|
22
|
+
validation_format_IPv4: 'Debe ser una dirección IPv4 válida',
|
|
23
|
+
validation_format_IPv6: 'Debe ser una dirección IPv6 válida',
|
|
24
|
+
validation_format_JSON: 'Debe ser una cadena JSON válida',
|
|
25
|
+
validation_format_JWT: 'Debe ser un JWT válido',
|
|
26
|
+
validation_format_PersonFirstname: 'Debe ser un nombre válido comenzando con mayúscula',
|
|
27
|
+
validation_format_PersonFullname: 'Debe ser un nombre completo válido comenzando con mayúscula',
|
|
28
|
+
validation_format_PersonInitials: 'Debe contener iniciales válidas compuestas por letras mayúsculas',
|
|
29
|
+
validation_format_PersonLastname: 'Debe ser un apellido válido comenzando con mayúscula',
|
|
30
|
+
validation_format_QRCode: 'Debe ser un código QR válido en formato base64',
|
|
31
|
+
validation_format_SemVerVersion: 'Debe ser una versión SemVer válida (X.X.X)',
|
|
32
|
+
validation_format_Slug: 'Debe contener solo letras minúsculas, dígitos y guiones (-)',
|
|
33
|
+
validation_format_SSHPrivateKey: 'Debe ser una clave privada SSH válida',
|
|
34
|
+
validation_format_SSHPublicKey: 'Debe ser una clave pública SSH válida',
|
|
35
|
+
validation_format_Time: 'Debe ser una hora válida',
|
|
36
|
+
validation_format_URL: 'Debe ser una URL válida',
|
|
37
|
+
validation_format_UUID: 'Debe ser un UUID válido',
|
|
38
|
+
validation_mandatory: 'Debe completarse',
|
|
39
|
+
validation_max: 'Debe ser menor o igual que {{expected}}',
|
|
40
|
+
validation_maxCount: 'Debe contener como máximo {{expected}} elemento(s)',
|
|
41
|
+
validation_maxLength: 'Debe contener como máximo {{expected}} carácter(es)',
|
|
42
|
+
validation_min: 'Debe ser mayor o igual que {{expected}}',
|
|
43
|
+
validation_minCount: 'Debe contener al menos {{expected}} elemento(s)',
|
|
44
|
+
validation_minLength: 'Debe contener al menos {{expected}} carácter(es)',
|
|
45
|
+
validation_oneOf: 'Debe ser uno de los elementos de la lista',
|
|
46
|
+
validation_shape: 'Debe respetar la estructura esperada del objeto',
|
|
47
|
+
validation_type_array: 'Debe ser un array',
|
|
48
|
+
validation_type_boolean: 'Debe ser un valor booleano',
|
|
49
|
+
validation_type_int: 'Debe ser un número entero',
|
|
50
|
+
validation_type_number: 'Debe ser un número',
|
|
51
|
+
validation_type_object: 'Debe ser un objeto',
|
|
52
|
+
validation_type_scalar: 'Debe ser un escalar',
|
|
53
|
+
validation_type_string: 'Debe ser una cadena',
|
|
54
|
+
};
|
package/dist/esm/i18n/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ViolationI18nable, YesNo } from '../dt/index.js';
|
|
2
2
|
import type { UCClientConfirmConfig, UCExecState, UCWording } from '../uc/index.js';
|
|
3
|
-
export type I18nLanguageCode = 'en' | 'fr';
|
|
3
|
+
export type I18nLanguageCode = 'de' | 'en' | 'es' | 'fr';
|
|
4
4
|
/**
|
|
5
5
|
* A translation value
|
|
6
6
|
*
|
|
@@ -14,6 +14,7 @@ export type I18nSource = any;
|
|
|
14
14
|
export type I18nSourceSafe = {
|
|
15
15
|
I18n: I18n;
|
|
16
16
|
};
|
|
17
|
+
export type I18nEntry = Record<I18nTranslationKey, I18nTranslation>;
|
|
17
18
|
export type I18n = {
|
|
18
|
-
[key in I18nLanguageCode]?:
|
|
19
|
+
[key in I18nLanguageCode]?: I18nEntry;
|
|
19
20
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Plugin } from './utils/bundling/babel/plugin.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Plugin } from './utils/bundling/babel/plugin.js';
|
package/dist/esm/index.vite.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Plugin } from './utils/bundling/vite/plugin.js';
|
package/dist/esm/index.vite.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Plugin } from './utils/bundling/vite/plugin.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './utils/bundling/webpack/loader.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './utils/bundling/webpack/loader.js';
|
|
@@ -16,6 +16,18 @@ export interface I18nManager extends Initializable {
|
|
|
16
16
|
* @param value
|
|
17
17
|
*/
|
|
18
18
|
add<K extends I18nTranslationKey>(key: K, value: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the list of available languages
|
|
21
|
+
*/
|
|
22
|
+
availableLangs(): I18nLanguageCode[];
|
|
23
|
+
/**
|
|
24
|
+
* Change the current language
|
|
25
|
+
*
|
|
26
|
+
* It might not work for all the implementations, depending on how langs are managed.
|
|
27
|
+
*
|
|
28
|
+
* @param lang
|
|
29
|
+
*/
|
|
30
|
+
changeLang(lang: I18nLanguageCode): Promise<void>;
|
|
19
31
|
/**
|
|
20
32
|
* Get the current lang code
|
|
21
33
|
*/
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { I18n, I18nLanguageCode, I18nTranslationKey } from '../../i18n/index.js';
|
|
2
2
|
import type { I18nManager, I18nManagerTOpts } from '../I18nManager.js';
|
|
3
3
|
import type { Logger } from '../Logger.js';
|
|
4
4
|
export declare class SimpleMapI18nManager implements I18nManager {
|
|
5
5
|
private i18n;
|
|
6
6
|
private logger;
|
|
7
7
|
private static PLACEHOLDERS_REGEX;
|
|
8
|
+
private langs;
|
|
8
9
|
private entries;
|
|
10
|
+
private currentLang;
|
|
9
11
|
constructor(i18n: I18n, logger: Logger);
|
|
10
12
|
add<K extends I18nTranslationKey>(key: K, value: string): Promise<void>;
|
|
13
|
+
availableLangs(): I18nLanguageCode[];
|
|
14
|
+
changeLang(lang: I18nLanguageCode): Promise<void>;
|
|
11
15
|
init(): Promise<void>;
|
|
12
16
|
initSync(): void;
|
|
13
17
|
l(): I18nLanguageCode;
|
|
14
18
|
t<K extends I18nTranslationKey>(key: K, opts?: I18nManagerTOpts): string;
|
|
15
19
|
private initCommon;
|
|
16
20
|
tOrNull<K extends I18nTranslationKey>(key: K, _opts?: I18nManagerTOpts): string | null;
|
|
21
|
+
private current;
|
|
17
22
|
private replacePlaceholders;
|
|
18
23
|
}
|
|
@@ -12,20 +12,34 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
12
12
|
};
|
|
13
13
|
var SimpleMapI18nManager_1;
|
|
14
14
|
import { inject, injectable } from 'inversify';
|
|
15
|
-
import { I18N_DEFAULT_LANG, } from '../../i18n/index.js';
|
|
16
15
|
let SimpleMapI18nManager = class SimpleMapI18nManager {
|
|
17
16
|
static { SimpleMapI18nManager_1 = this; }
|
|
18
17
|
i18n;
|
|
19
18
|
logger;
|
|
20
19
|
static PLACEHOLDERS_REGEX = /{{([A-Z-a-z0-9]+)}}/g; // Note the 'g' so it can be used with `matchAll`
|
|
20
|
+
langs;
|
|
21
21
|
entries;
|
|
22
|
+
currentLang;
|
|
22
23
|
constructor(i18n, logger) {
|
|
23
24
|
this.i18n = i18n;
|
|
24
25
|
this.logger = logger;
|
|
26
|
+
this.langs = Object.keys(i18n);
|
|
27
|
+
if (this.langs.length === 0) {
|
|
28
|
+
throw new Error('I18n must define at least one lang');
|
|
29
|
+
}
|
|
25
30
|
this.entries = new Map();
|
|
31
|
+
// biome-ignore lint/style/noNonNullAssertion: we want it
|
|
32
|
+
this.currentLang = this.langs[0];
|
|
26
33
|
}
|
|
27
34
|
async add(key, value) {
|
|
28
|
-
this.
|
|
35
|
+
this.current().set(key, value);
|
|
36
|
+
}
|
|
37
|
+
availableLangs() {
|
|
38
|
+
return this.langs;
|
|
39
|
+
}
|
|
40
|
+
async changeLang(lang) {
|
|
41
|
+
this.currentLang = lang;
|
|
42
|
+
this.initCommon();
|
|
29
43
|
}
|
|
30
44
|
async init() {
|
|
31
45
|
this.initCommon();
|
|
@@ -34,10 +48,10 @@ let SimpleMapI18nManager = class SimpleMapI18nManager {
|
|
|
34
48
|
this.initCommon();
|
|
35
49
|
}
|
|
36
50
|
l() {
|
|
37
|
-
return
|
|
51
|
+
return this.currentLang;
|
|
38
52
|
}
|
|
39
53
|
t(key, opts) {
|
|
40
|
-
const v = this.
|
|
54
|
+
const v = this.current().get(key);
|
|
41
55
|
if (v) {
|
|
42
56
|
return this.replacePlaceholders(v, opts);
|
|
43
57
|
}
|
|
@@ -47,17 +61,32 @@ let SimpleMapI18nManager = class SimpleMapI18nManager {
|
|
|
47
61
|
return key; // Mimic the behavior of some common libraries like i18next
|
|
48
62
|
}
|
|
49
63
|
initCommon() {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
for (const lang of this.langs) {
|
|
65
|
+
const translations = this.i18n[lang];
|
|
66
|
+
this.logger.trace('Initializing I18nManager', {
|
|
67
|
+
lang,
|
|
68
|
+
translations,
|
|
69
|
+
});
|
|
70
|
+
if (!translations) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!this.entries.has(lang)) {
|
|
74
|
+
this.entries.set(lang, new Map());
|
|
75
|
+
}
|
|
76
|
+
for (const [k, v] of Object.entries(translations)) {
|
|
77
|
+
this.entries.get(lang)?.set(k, v);
|
|
78
|
+
}
|
|
57
79
|
}
|
|
58
80
|
}
|
|
59
81
|
tOrNull(key, _opts) {
|
|
60
|
-
return this.
|
|
82
|
+
return this.current().get(key) || null;
|
|
83
|
+
}
|
|
84
|
+
current() {
|
|
85
|
+
const entry = this.entries.get(this.currentLang);
|
|
86
|
+
if (!entry) {
|
|
87
|
+
throw new Error(`I18nManager must contain an entry for lang : ${this.currentLang}`);
|
|
88
|
+
}
|
|
89
|
+
return entry;
|
|
61
90
|
}
|
|
62
91
|
replacePlaceholders(v, opts) {
|
|
63
92
|
// DO NOT USE THIS IN PRODUCTION
|
|
@@ -127,7 +127,7 @@ let ServerRequestHandler = class ServerRequestHandler {
|
|
|
127
127
|
uc.fill((await req.bodyFromQueryParams()));
|
|
128
128
|
break;
|
|
129
129
|
default:
|
|
130
|
-
|
|
130
|
+
envelope;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
async applySideEffects(res, ucd, output) {
|
|
@@ -154,7 +154,7 @@ let ServerRequestHandler = class ServerRequestHandler {
|
|
|
154
154
|
await this.applySetAuthSideEffect(res, item);
|
|
155
155
|
break;
|
|
156
156
|
default:
|
|
157
|
-
(
|
|
157
|
+
(type);
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
return { status: undefined };
|