libmodulor 0.23.0 → 0.25.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 +34 -0
- package/README.md +154 -2
- package/dist/esm/apps/Helper/src/lib/project.js +6 -6
- 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/Validation.d.ts +2 -2
- package/dist/esm/dt/base/TBase.d.ts +2 -0
- package/dist/esm/dt/base/TBase.js +3 -0
- package/dist/esm/dt/base/TObject.d.ts +6 -4
- package/dist/esm/dt/base/TObject.js +5 -6
- package/dist/esm/dt/base/TString.d.ts +2 -1
- package/dist/esm/dt/base/TString.js +22 -0
- package/dist/esm/dt/final/TFile.d.ts +13 -4
- package/dist/esm/dt/final/TFile.js +70 -8
- package/dist/esm/dt/final/TFileExtension.d.ts +1 -1
- package/dist/esm/dt/final/TFileMimeType.d.ts +2 -6
- package/dist/esm/dt/final/TFileMimeType.js +0 -6
- package/dist/esm/dt/final/TFilePath.d.ts +7 -0
- package/dist/esm/dt/final/TFilePath.js +5 -1
- package/dist/esm/dt/index.d.ts +1 -1
- package/dist/esm/i18n/WordingManager.d.ts +2 -1
- package/dist/esm/i18n/WordingManager.js +23 -2
- 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 +62 -0
- package/dist/esm/i18n/locales/en.js +8 -0
- package/dist/esm/i18n/locales/es.d.ts +2 -0
- package/dist/esm/i18n/locales/es.js +62 -0
- package/dist/esm/i18n/locales/fr.js +8 -0
- package/dist/esm/i18n/types.d.ts +5 -4
- 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/FSManager.d.ts +7 -5
- package/dist/esm/std/FSManager.js +5 -6
- package/dist/esm/std/FormDataBuilder.d.ts +2 -1
- package/dist/esm/std/I18nManager.d.ts +12 -0
- package/dist/esm/std/impl/NodeFSManager.js +4 -3
- package/dist/esm/std/impl/SimpleMapI18nManager.d.ts +6 -1
- package/dist/esm/std/impl/SimpleMapI18nManager.js +41 -12
- package/dist/esm/target/lib/react/StyleContextProvider.d.ts +1 -0
- package/dist/esm/target/lib/react/form.d.ts +1 -1
- package/dist/esm/target/lib/react/form.js +1 -0
- package/dist/esm/target/lib/react/useAction.d.ts +1 -1
- package/dist/esm/target/lib/react/useAction.js +13 -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 +4 -3
- 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/lib/web/input.d.ts +1 -0
- package/dist/esm/target/lib/web/input.js +5 -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/target/react-native-pure/UCFormField.js +2 -1
- package/dist/esm/target/react-native-pure/UCFormFieldControl.js +6 -4
- package/dist/esm/target/react-native-pure/UCFormFieldErr.d.ts +1 -1
- package/dist/esm/target/react-native-pure/UCFormFieldErr.js +4 -1
- package/dist/esm/target/react-native-pure/UCFormFieldHelp.d.ts +4 -0
- package/dist/esm/target/react-native-pure/UCFormFieldHelp.js +15 -0
- package/dist/esm/target/react-web-pure/UCFormField.js +2 -1
- package/dist/esm/target/react-web-pure/UCFormFieldErr.d.ts +1 -1
- package/dist/esm/target/react-web-pure/UCFormFieldErr.js +4 -1
- package/dist/esm/target/react-web-pure/UCFormFieldHelp.d.ts +4 -0
- package/dist/esm/target/react-web-pure/UCFormFieldHelp.js +14 -0
- package/dist/esm/testing/AppTester.js +4 -5
- package/dist/esm/testing/UCDefASTParser.d.ts +24 -6
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/SimpleAppDocsEmitter.d.ts +7 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/SimpleAppDocsEmitter.js +59 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/markdown.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/markdown.js +10 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/sequence-diagram.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/sequence-diagram.js +92 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/tech-summary.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/tech-summary.js +27 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/uc-summary.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/uc-summary.js +63 -0
- 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/impl/newNodeAppTester.js +1 -1
- package/dist/esm/testing/opts.js +1 -1
- package/dist/esm/testing/uc-input.js +5 -2
- 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/exec.d.ts +42 -21
- package/dist/esm/uc/exec.js +48 -13
- 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/input-field.d.ts +6 -4
- package/dist/esm/uc/input-field.js +4 -5
- package/dist/esm/uc/side-effect.d.ts +10 -8
- package/dist/esm/uc/side-effect.js +5 -6
- package/dist/esm/uc/workers/UCExecChecker.js +1 -1
- package/dist/esm/uc/workers/UCInputFilesProcessor.js +3 -3
- package/dist/esm/uc/workers/UCInputValidator.js +2 -1
- package/dist/esm/uc/workers/UCOutputFilesProcessor.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/index.d.ts +1 -1
- package/dist/esm/utils/ioc/bindCommon.js +1 -1
- package/dist/esm/utils/terminal/fmt.js +1 -1
- package/dist/esm/utils/types/utility-types.d.ts +4 -0
- package/package.json +36 -12
- 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,39 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.25.0 (2025-12-21)
|
|
4
|
+
|
|
5
|
+
**Highlights**
|
|
6
|
+
|
|
7
|
+
- Added use case summary in the auto-generated app docs : In addition to the existing mermaid diagram, there is now a summary of the lifecyle, input and output in a dedicated table
|
|
8
|
+
- Example : https://github.com/c100k/libmodulor/tree/42fd11307cdd9f8cdec19b4de75d4959bc9f9a9e/examples/apps/Spotify#createalbum
|
|
9
|
+
- Improved the `File` data type
|
|
10
|
+
- Changed the property `path` to `uri` to conform to the `FormData` spec (this is a breaking change)
|
|
11
|
+
- Simplified the declaration by inlining the accepted types via `accept` instead of `type.allowed` (this is also a breaking change)
|
|
12
|
+
- Added `maxSizeInBytes` and `minSizeInBytes` for size validation
|
|
13
|
+
- Added `getConstraintsForHuman` to format constraints for the end user in the targets. For instance :
|
|
14
|
+
- For `FreeTextShort`, it displays `Max length: 150` 🇬🇧 when present
|
|
15
|
+
- For `File`, it displays `Max size: 8MB - Accepted types: application/png, application/jpg` 🇬🇧 when present
|
|
16
|
+
- Applied to the `react-native-pure` and `react-native-web` targets (see `UCFormFieldHelp.tsx`)
|
|
17
|
+
|
|
18
|
+
See all the changes here : https://github.com/c100k/libmodulor/compare/v0.24.0...master
|
|
19
|
+
|
|
20
|
+
## v0.24.0 (2025-12-07)
|
|
21
|
+
|
|
22
|
+
**Highlights**
|
|
23
|
+
|
|
24
|
+
- Introduced `babel`, `vite` plugins and `webpack` loader => https://libmodulor.c100k.eu/docs/guides/bundle-target
|
|
25
|
+
- Introduced the `node-stricli-cli` target using @bloomberg's `stricli` library
|
|
26
|
+
- Introduced the `Playground` example, runnable locally, to play with all the features of `libmodulor` => https://libmodulor.c100k.eu/docs/examples/Playground
|
|
27
|
+
- Improved apps testing by making sure non-english languages are fully translated
|
|
28
|
+
- Improved apps testing performance by optimizing use cases testing using the `stream` transport
|
|
29
|
+
- Introduced `de` 🇩🇪 and `es` 🇪🇸 locales (see them in action in the `Playground`)
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
Also bumped React versions for the infamous [React2Shell vulnerability](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components).
|
|
34
|
+
|
|
35
|
+
See all the changes here : https://github.com/c100k/libmodulor/compare/v0.23.0...master
|
|
36
|
+
|
|
3
37
|
## v0.23.0 (2025-11-11)
|
|
4
38
|
|
|
5
39
|
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.25.0/LICENSE)
|
|
@@ -81,21 +81,21 @@ export const PACKAGE_JSON = (name) => `{
|
|
|
81
81
|
"test": "tsc && vitest run --passWithNoTests"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"inversify": "^7.10.
|
|
84
|
+
"inversify": "^7.10.7",
|
|
85
85
|
"libmodulor": "latest",
|
|
86
86
|
"reflect-metadata": "^0.2.2"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@biomejs/biome": "^2.3.
|
|
90
|
-
"@types/node": "^
|
|
89
|
+
"@biomejs/biome": "^2.3.10",
|
|
90
|
+
"@types/node": "^25.0.3",
|
|
91
91
|
"@vitest/coverage-v8": "^3.2.4",
|
|
92
92
|
"buffer": "^6.0.3",
|
|
93
93
|
"cookie-parser": "^1.4.7",
|
|
94
|
-
"express": "^5.1
|
|
94
|
+
"express": "^5.2.1",
|
|
95
95
|
"express-fileupload": "^1.5.2",
|
|
96
|
-
"fast-check": "^4.
|
|
96
|
+
"fast-check": "^4.4.0",
|
|
97
97
|
"helmet": "^8.1.0",
|
|
98
|
-
"jose": "^6.1.
|
|
98
|
+
"jose": "^6.1.3",
|
|
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"];
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { I18nTranslation } from '../i18n/index.js';
|
|
2
2
|
import type { NumIndex } from './final/TNumIndex.js';
|
|
3
|
-
type ViolationConstraint = 'fieldsOr' | 'format' | 'mandatory' | 'max' | 'maxCount' | 'maxLength' | 'min' | 'minCount' | 'minLength' | 'oneOf' | 'shape' | 'type';
|
|
3
|
+
type ViolationConstraint = 'fieldsOr' | 'format' | 'mandatory' | 'max' | 'maxCount' | 'maxLength' | 'maxSize' | 'min' | 'minCount' | 'minLength' | 'minSize' | 'oneOf' | 'shape' | 'type';
|
|
4
4
|
type ViolationBase<C extends ViolationConstraint, EV> = {
|
|
5
5
|
constraint: C;
|
|
6
6
|
expected: EV;
|
|
7
7
|
};
|
|
8
8
|
export type ViolationFormat = 'ColorRGBA' | 'DateISO8601' | 'DirPath' | 'DomainName' | 'Email' | 'FilePath' | 'GitSSHURL' | 'IPv4' | 'IPv6' | 'JSON' | 'JWT' | 'PersonFirstname' | 'PersonFullname' | 'PersonInitials' | 'PersonLastname' | 'QRCode' | 'SemVerVersion' | 'Slug' | 'SSHPrivateKey' | 'SSHPublicKey' | 'Time' | 'URL' | 'UUID';
|
|
9
9
|
export type ViolationType = 'array' | 'boolean' | 'int' | 'number' | 'object' | 'scalar' | 'string';
|
|
10
|
-
export type Violation<T = unknown> = ViolationBase<'fieldsOr', string> | ViolationBase<'format', ViolationFormat> | ViolationBase<'format', string> | ViolationBase<'mandatory', undefined> | ViolationBase<'max', number> | ViolationBase<'maxCount', number> | ViolationBase<'maxLength', number> | ViolationBase<'min', number> | ViolationBase<'minCount', number> | ViolationBase<'minLength', number> | ViolationBase<'oneOf', T[]> | ViolationBase<'shape', object> | ViolationBase<'type', ViolationType>;
|
|
10
|
+
export type Violation<T = unknown> = ViolationBase<'fieldsOr', string> | ViolationBase<'format', ViolationFormat> | ViolationBase<'format', string> | ViolationBase<'mandatory', undefined> | ViolationBase<'max', number> | ViolationBase<'maxCount', number> | ViolationBase<'maxLength', number> | ViolationBase<'maxSize', string> | ViolationBase<'min', number> | ViolationBase<'minCount', number> | ViolationBase<'minLength', number> | ViolationBase<'minSize', string> | ViolationBase<'oneOf', T[]> | ViolationBase<'shape', object> | ViolationBase<'type', ViolationType>;
|
|
11
11
|
type ViolationI18nableSimple = Exclude<ViolationConstraint, 'format' | 'type'>;
|
|
12
12
|
export type ViolationI18nable = `validation_${ViolationI18nableSimple}` | `validation_format_${ViolationFormat}` | `validation_type_${ViolationType}`;
|
|
13
13
|
export type ViolationI18n = Record<ViolationI18nable, I18nTranslation>;
|
|
@@ -26,6 +26,7 @@ export interface OptionsOpts {
|
|
|
26
26
|
shouldTranslateLabels?: boolean;
|
|
27
27
|
strict?: boolean;
|
|
28
28
|
}
|
|
29
|
+
export type ConstraintsForHuman = Record<string, string>;
|
|
29
30
|
export declare abstract class TBase<T extends DataType> {
|
|
30
31
|
static DEFAULT_OPTIONS: Required<OptionsOpts>;
|
|
31
32
|
protected defaultValue: T | undefined;
|
|
@@ -44,6 +45,7 @@ export declare abstract class TBase<T extends DataType> {
|
|
|
44
45
|
fmt(ifNullOrUndefined?: string): string;
|
|
45
46
|
getDefaultValue(): T | undefined;
|
|
46
47
|
getExamples(): T[] | undefined;
|
|
48
|
+
getConstraintsForHuman(): ConstraintsForHuman | null;
|
|
47
49
|
getInitialValue(): T | undefined;
|
|
48
50
|
getOptions(): Option<T>[] | undefined;
|
|
49
51
|
getSemanticsMapping(): SemanticsMapping | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { EnumOf } from '../../utils/index.js';
|
|
1
2
|
import type { Validation } from '../Validation.js';
|
|
2
3
|
import { TBase, type TName } from './TBase.js';
|
|
3
|
-
export declare
|
|
4
|
+
export declare const TObjectShapeValidationStrategy: {
|
|
4
5
|
/**
|
|
5
6
|
* No shape validation is performed
|
|
6
7
|
*
|
|
@@ -8,14 +9,15 @@ export declare enum TObjectShapeValidationStrategy {
|
|
|
8
9
|
*
|
|
9
10
|
* Otherwise, you can still override {@link validate} in the `T*` class and do your own validation.
|
|
10
11
|
*/
|
|
11
|
-
NONE
|
|
12
|
+
readonly NONE: "NONE";
|
|
12
13
|
/**
|
|
13
14
|
* Validate against the {@link TObject.example()}
|
|
14
15
|
*
|
|
15
16
|
* It checks that the keys of the value, sorted alphabetically, are the same as the example's keys.
|
|
16
17
|
*/
|
|
17
|
-
SAME_AS_EXAMPLE
|
|
18
|
-
}
|
|
18
|
+
readonly SAME_AS_EXAMPLE: "SAME_AS_EXAMPLE";
|
|
19
|
+
};
|
|
20
|
+
export type TObjectShapeValidationStrategy = EnumOf<typeof TObjectShapeValidationStrategy>;
|
|
19
21
|
export interface TObjectConstraints {
|
|
20
22
|
/**
|
|
21
23
|
* @defaultValue {@link TObjectShapeValidationStrategy.SAME_AS_EXAMPLE}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { TBase } from './TBase.js';
|
|
2
|
-
export
|
|
3
|
-
(function (TObjectShapeValidationStrategy) {
|
|
2
|
+
export const TObjectShapeValidationStrategy = {
|
|
4
3
|
/**
|
|
5
4
|
* No shape validation is performed
|
|
6
5
|
*
|
|
@@ -8,14 +7,14 @@ export var TObjectShapeValidationStrategy;
|
|
|
8
7
|
*
|
|
9
8
|
* Otherwise, you can still override {@link validate} in the `T*` class and do your own validation.
|
|
10
9
|
*/
|
|
11
|
-
|
|
10
|
+
NONE: 'NONE',
|
|
12
11
|
/**
|
|
13
12
|
* Validate against the {@link TObject.example()}
|
|
14
13
|
*
|
|
15
14
|
* It checks that the keys of the value, sorted alphabetically, are the same as the example's keys.
|
|
16
15
|
*/
|
|
17
|
-
|
|
18
|
-
}
|
|
16
|
+
SAME_AS_EXAMPLE: 'SAME_AS_EXAMPLE',
|
|
17
|
+
};
|
|
19
18
|
export class TObject extends TBase {
|
|
20
19
|
constraints;
|
|
21
20
|
constructor(constraints = {
|
|
@@ -65,7 +64,7 @@ export class TObject extends TBase {
|
|
|
65
64
|
break;
|
|
66
65
|
}
|
|
67
66
|
default:
|
|
68
|
-
|
|
67
|
+
strategy;
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
70
|
return validation;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Validation, ViolationFormat } from '../Validation.js';
|
|
2
|
-
import { TBase, type TName } from './TBase.js';
|
|
2
|
+
import { type ConstraintsForHuman, TBase, type TName } from './TBase.js';
|
|
3
3
|
export interface TStringConstraints<VF extends ViolationFormat | (string & {}) = ViolationFormat> {
|
|
4
4
|
format?: {
|
|
5
5
|
f: VF;
|
|
@@ -15,6 +15,7 @@ export declare class TString<T extends string = string, VF extends ViolationForm
|
|
|
15
15
|
constructor(constraints?: TStringConstraints<VF> | undefined);
|
|
16
16
|
tName(): TName;
|
|
17
17
|
example(): T;
|
|
18
|
+
getConstraintsForHuman(): ConstraintsForHuman | null;
|
|
18
19
|
getConstraints(): TStringConstraints<VF> | undefined;
|
|
19
20
|
isPotentiallyLong(): boolean;
|
|
20
21
|
protected removeFormatConstraint(): void;
|
|
@@ -13,6 +13,28 @@ export class TString extends TBase {
|
|
|
13
13
|
example() {
|
|
14
14
|
return 'Miami';
|
|
15
15
|
}
|
|
16
|
+
getConstraintsForHuman() {
|
|
17
|
+
if (!this.constraints) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const c = {};
|
|
21
|
+
const { format, maxLength, minLength } = this.constraints;
|
|
22
|
+
if (minLength) {
|
|
23
|
+
// biome-ignore lint/complexity/useLiteralKeys: typescript disagrees
|
|
24
|
+
c['minLength'] = minLength.toString();
|
|
25
|
+
}
|
|
26
|
+
if (maxLength) {
|
|
27
|
+
// biome-ignore lint/complexity/useLiteralKeys: typescript disagrees
|
|
28
|
+
c['maxLength'] = maxLength.toString();
|
|
29
|
+
}
|
|
30
|
+
if (format) {
|
|
31
|
+
// Are regexes really "human" ?
|
|
32
|
+
// TODO : Find a more human way of displaying regexes
|
|
33
|
+
// biome-ignore lint/complexity/useLiteralKeys: typescript disagrees
|
|
34
|
+
c['format'] = format.regexp.toString();
|
|
35
|
+
}
|
|
36
|
+
return c;
|
|
37
|
+
}
|
|
16
38
|
getConstraints() {
|
|
17
39
|
return this.constraints;
|
|
18
40
|
}
|
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
import type { TName } from '../base/TBase.js';
|
|
1
|
+
import type { ConstraintsForHuman, TName } from '../base/TBase.js';
|
|
2
2
|
import { TObject } from '../base/TObject.js';
|
|
3
3
|
import type { HTMLInputType } from '../targets/web.js';
|
|
4
4
|
import type { Validation } from '../Validation.js';
|
|
5
|
-
import { type FileMimeType
|
|
5
|
+
import { type FileMimeType } from './TFileMimeType.js';
|
|
6
6
|
import { type FileName } from './TFileName.js';
|
|
7
7
|
import { type FilePath } from './TFilePath.js';
|
|
8
|
+
import type { UIntQuantity } from './TUIntQuantity.js';
|
|
8
9
|
export type File = {
|
|
9
10
|
name: FileName;
|
|
10
|
-
|
|
11
|
+
size: UIntQuantity;
|
|
11
12
|
type: FileMimeType;
|
|
13
|
+
uri: FilePath;
|
|
12
14
|
};
|
|
13
15
|
export interface TFileConstraints {
|
|
14
|
-
|
|
16
|
+
accept: FileMimeType[];
|
|
17
|
+
maxSizeInBytes?: UIntQuantity;
|
|
18
|
+
minSizeInBytes?: UIntQuantity;
|
|
15
19
|
}
|
|
16
20
|
export declare class TFile extends TObject<File> {
|
|
17
21
|
protected fileConstraints: TFileConstraints;
|
|
22
|
+
static readonly UNITS: string[];
|
|
18
23
|
constructor(fileConstraints: TFileConstraints);
|
|
19
24
|
tName(): TName;
|
|
20
25
|
example(): File;
|
|
26
|
+
getConstraintsForHuman(): ConstraintsForHuman | null;
|
|
21
27
|
htmlInputType(): HTMLInputType;
|
|
22
28
|
validate(): Validation;
|
|
29
|
+
getFileConstraints(): TFileConstraints;
|
|
30
|
+
fmtBytes(bytes: number, decimals?: number): string;
|
|
31
|
+
withOneExample(name: File['name']): this;
|
|
23
32
|
}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { TObject, TObjectShapeValidationStrategy } from '../base/TObject.js';
|
|
2
|
-
import { TFileMimeType
|
|
2
|
+
import { TFileMimeType } from './TFileMimeType.js';
|
|
3
3
|
import { TFileName } from './TFileName.js';
|
|
4
4
|
import { TFilePath } from './TFilePath.js';
|
|
5
5
|
export class TFile extends TObject {
|
|
6
6
|
fileConstraints;
|
|
7
|
+
// We consider them generic enough to not having to be translated
|
|
8
|
+
static UNITS = [
|
|
9
|
+
'B',
|
|
10
|
+
'KB',
|
|
11
|
+
'MB',
|
|
12
|
+
'GB',
|
|
13
|
+
'TB',
|
|
14
|
+
'PB',
|
|
15
|
+
'EB',
|
|
16
|
+
'ZB',
|
|
17
|
+
'YB',
|
|
18
|
+
];
|
|
7
19
|
constructor(fileConstraints) {
|
|
8
20
|
super({
|
|
9
21
|
// We usually process instances of https://developer.mozilla.org/fr/docs/Web/API/File
|
|
@@ -17,11 +29,27 @@ export class TFile extends TObject {
|
|
|
17
29
|
}
|
|
18
30
|
example() {
|
|
19
31
|
return {
|
|
20
|
-
name:
|
|
21
|
-
|
|
22
|
-
type:
|
|
32
|
+
name: TFilePath.FILE_NAME,
|
|
33
|
+
size: TFilePath.FILE_SIZE,
|
|
34
|
+
type: TFilePath.MIME_TYPE,
|
|
35
|
+
uri: `${TFilePath.ABS_PATH}/${TFilePath.FILE_NAME}`,
|
|
23
36
|
};
|
|
24
37
|
}
|
|
38
|
+
getConstraintsForHuman() {
|
|
39
|
+
const c = {};
|
|
40
|
+
const { accept, maxSizeInBytes, minSizeInBytes } = this.fileConstraints;
|
|
41
|
+
if (minSizeInBytes) {
|
|
42
|
+
// biome-ignore lint/complexity/useLiteralKeys: typescript disagrees
|
|
43
|
+
c['minSizeInBytes'] = this.fmtBytes(minSizeInBytes);
|
|
44
|
+
}
|
|
45
|
+
if (maxSizeInBytes) {
|
|
46
|
+
// biome-ignore lint/complexity/useLiteralKeys: typescript disagrees
|
|
47
|
+
c['maxSizeInBytes'] = this.fmtBytes(maxSizeInBytes);
|
|
48
|
+
}
|
|
49
|
+
// biome-ignore lint/complexity/useLiteralKeys: typescript disagrees
|
|
50
|
+
c['accept'] = accept.join(', ');
|
|
51
|
+
return c;
|
|
52
|
+
}
|
|
25
53
|
htmlInputType() {
|
|
26
54
|
return 'file';
|
|
27
55
|
}
|
|
@@ -32,13 +60,47 @@ export class TFile extends TObject {
|
|
|
32
60
|
}
|
|
33
61
|
const val = this.raw;
|
|
34
62
|
validation.concat(new TFileName().assign(val.name).validate());
|
|
63
|
+
const { accept, maxSizeInBytes, minSizeInBytes } = this.fileConstraints;
|
|
64
|
+
const { size, type, uri } = val;
|
|
35
65
|
if (!(val instanceof File)) {
|
|
36
|
-
validation.concat(new TFilePath().assign(
|
|
66
|
+
validation.concat(new TFilePath().assign(uri).validate());
|
|
37
67
|
}
|
|
38
|
-
validation.concat(new TFileMimeType(
|
|
39
|
-
.
|
|
68
|
+
validation.concat(new TFileMimeType()
|
|
69
|
+
.setOptions(accept.map((a) => ({ label: a, value: a })))
|
|
70
|
+
.assign(type)
|
|
40
71
|
.validate());
|
|
41
|
-
|
|
72
|
+
if (minSizeInBytes && size < minSizeInBytes) {
|
|
73
|
+
validation.add({
|
|
74
|
+
constraint: 'minSize',
|
|
75
|
+
expected: this.fmtBytes(minSizeInBytes),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (maxSizeInBytes && size > maxSizeInBytes) {
|
|
79
|
+
validation.add({
|
|
80
|
+
constraint: 'maxSize',
|
|
81
|
+
expected: this.fmtBytes(maxSizeInBytes),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
42
84
|
return validation;
|
|
43
85
|
}
|
|
86
|
+
getFileConstraints() {
|
|
87
|
+
return this.fileConstraints;
|
|
88
|
+
}
|
|
89
|
+
fmtBytes(bytes, decimals = 2) {
|
|
90
|
+
const k = 1024;
|
|
91
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
92
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
93
|
+
return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${TFile.UNITS[i]}`;
|
|
94
|
+
}
|
|
95
|
+
withOneExample(name) {
|
|
96
|
+
this.setExamples([
|
|
97
|
+
{
|
|
98
|
+
name,
|
|
99
|
+
size: TFilePath.FILE_SIZE,
|
|
100
|
+
type: this.fileConstraints.accept[0] ?? TFilePath.MIME_TYPE,
|
|
101
|
+
uri: `${TFilePath.ABS_PATH}/${name}`,
|
|
102
|
+
},
|
|
103
|
+
]);
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
44
106
|
}
|
|
@@ -3,7 +3,7 @@ import { TString, type TStringConstraints } from '../base/TString.js';
|
|
|
3
3
|
type ImageExtension = 'gif' | 'heic' | 'jpg' | 'png';
|
|
4
4
|
type VideoExtension = 'mov' | 'mp4';
|
|
5
5
|
type XMLExtension = 'gpx' | 'xml';
|
|
6
|
-
export type FileExtension = ImageExtension | VideoExtension | XMLExtension;
|
|
6
|
+
export type FileExtension = ImageExtension | VideoExtension | XMLExtension | (string & {});
|
|
7
7
|
export interface TFileExtensionConstraints extends TStringConstraints {
|
|
8
8
|
allowed: FileExtension[];
|
|
9
9
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { TName } from '../base/TBase.js';
|
|
2
|
-
import { TString
|
|
3
|
-
export type FileMimeType = 'text/plain' | 'audio/aac' | 'application/x-abiword' | 'application/octet-stream' | 'video/x-msvideo' | 'application/vnd.amazon.ebook' | 'image/bmp' | 'application/x-bzip' | 'application/x-bzip2' | 'application/x-csh' | 'text/css' | 'text/csv' | 'application/msword' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/vnd.ms-fontobject' | 'application/epub+zip' | 'image/gif' | 'text/html' | 'image/x-icon' | 'text/calendar' | 'application/java-archive' | 'image/jpeg' | 'image/jpg' | 'application/javascript' | 'application/json' | 'audio/midi' | 'video/mpeg' | 'application/vnd.apple.installer+xml' | 'application/vnd.oasis.opendocument.presentation' | 'application/vnd.oasis.opendocument.spreadsheet' | 'application/vnd.oasis.opendocument.text' | 'audio/ogg' | 'video/ogg' | 'application/ogg' | 'font/otf' | 'image/png' | 'application/pdf' | 'application/vnd.ms-powerpoint' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' | 'application/x-rar-compressed' | 'application/rtf' | 'application/x-sh' | 'image/svg+xml' | 'application/x-shockwave-flash' | 'application/x-tar' | 'image/tiff' | 'application/typescript' | 'font/ttf' | 'application/vnd.visio' | 'audio/x-wav' | 'audio/webm' | 'video/webm' | 'image/webp' | 'font/woff' | 'font/woff2' | 'application/xhtml+xml' | 'application/vnd.ms-excel' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | 'application/xml' | 'application/vnd.mozilla.xul+xml' | 'application/zip' | 'video/3gpp audio/3gpp' | 'video/3gpp2 audio/3gpp2' | 'application/x-7z-compressed';
|
|
4
|
-
export interface TFileMimeTypeConstraints extends TStringConstraints {
|
|
5
|
-
allowed: FileMimeType[];
|
|
6
|
-
}
|
|
2
|
+
import { TString } from '../base/TString.js';
|
|
3
|
+
export type FileMimeType = 'text/plain' | 'audio/aac' | 'application/x-abiword' | 'application/octet-stream' | 'video/x-msvideo' | 'application/vnd.amazon.ebook' | 'image/bmp' | 'application/x-bzip' | 'application/x-bzip2' | 'application/x-csh' | 'text/css' | 'text/csv' | 'application/msword' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/vnd.ms-fontobject' | 'application/epub+zip' | 'image/gif' | 'text/html' | 'image/x-icon' | 'text/calendar' | 'application/java-archive' | 'image/jpeg' | 'image/jpg' | 'application/javascript' | 'application/json' | 'audio/midi' | 'video/mpeg' | 'application/vnd.apple.installer+xml' | 'application/vnd.oasis.opendocument.presentation' | 'application/vnd.oasis.opendocument.spreadsheet' | 'application/vnd.oasis.opendocument.text' | 'audio/ogg' | 'video/ogg' | 'application/ogg' | 'font/otf' | 'image/png' | 'application/pdf' | 'application/vnd.ms-powerpoint' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' | 'application/x-rar-compressed' | 'application/rtf' | 'application/x-sh' | 'image/svg+xml' | 'application/x-shockwave-flash' | 'application/x-tar' | 'image/tiff' | 'application/typescript' | 'font/ttf' | 'application/vnd.visio' | 'audio/x-wav' | 'audio/webm' | 'video/webm' | 'image/webp' | 'font/woff' | 'font/woff2' | 'application/xhtml+xml' | 'application/vnd.ms-excel' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | 'application/xml' | 'application/vnd.mozilla.xul+xml' | 'application/zip' | 'video/3gpp audio/3gpp' | 'video/3gpp2 audio/3gpp2' | 'application/x-7z-compressed' | (string & {});
|
|
7
4
|
export declare class TFileMimeType extends TString<FileMimeType> {
|
|
8
|
-
constructor(constraints?: TFileMimeTypeConstraints);
|
|
9
5
|
tName(): TName;
|
|
10
6
|
example(): FileMimeType;
|
|
11
7
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { TString } from '../base/TString.js';
|
|
2
2
|
export class TFileMimeType extends TString {
|
|
3
|
-
constructor(constraints) {
|
|
4
|
-
super(constraints);
|
|
5
|
-
if (constraints?.allowed) {
|
|
6
|
-
this.setOptions(constraints?.allowed.map((v) => ({ label: v, value: v })));
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
3
|
tName() {
|
|
10
4
|
return 'FileMimeType';
|
|
11
5
|
}
|