libmodulor 0.24.0 → 0.26.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 +32 -0
- package/README.md +32 -151
- package/dist/esm/app/workers/AppUCsLoader.d.ts +2 -3
- package/dist/esm/apps/Helper/src/i18n.d.ts +39 -2
- package/dist/esm/apps/Helper/src/i18n.js +15 -1
- package/dist/esm/apps/Helper/src/lib/SrcFilesGenerator.d.ts +13 -0
- package/dist/esm/apps/Helper/src/lib/SrcFilesGenerator.js +37 -0
- package/dist/esm/apps/Helper/src/lib/consts.d.ts +2 -0
- package/dist/esm/apps/Helper/src/lib/consts.js +2 -0
- package/dist/esm/apps/Helper/src/lib/funcs.d.ts +4 -0
- package/dist/esm/apps/Helper/src/lib/funcs.js +9 -0
- package/dist/esm/apps/Helper/src/lib/io.d.ts +10 -0
- package/dist/esm/apps/Helper/src/lib/io.js +22 -0
- package/dist/esm/apps/Helper/src/lib/layers/app.d.ts +3 -0
- package/dist/esm/apps/Helper/src/lib/layers/app.js +30 -0
- package/dist/esm/apps/Helper/src/lib/layers/product.d.ts +3 -0
- package/dist/esm/apps/Helper/src/lib/layers/product.js +27 -0
- package/dist/esm/apps/Helper/src/lib/layers/project.d.ts +4 -0
- package/dist/esm/apps/Helper/src/lib/layers/project.js +163 -0
- package/dist/esm/apps/Helper/src/lib/layers/target.d.ts +3 -0
- package/dist/esm/apps/Helper/src/lib/layers/target.js +202 -0
- package/dist/esm/apps/Helper/src/lib/layers/uc.d.ts +3 -0
- package/dist/esm/apps/Helper/src/lib/layers/uc.js +113 -0
- package/dist/esm/apps/Helper/src/lib/project.js +21 -23
- package/dist/esm/apps/Helper/src/lib/types.d.ts +3 -0
- package/dist/esm/apps/Helper/src/lib/types.js +1 -0
- package/dist/esm/apps/Helper/src/manifest.d.ts +20 -0
- package/dist/esm/apps/Helper/src/manifest.js +20 -0
- package/dist/esm/apps/Helper/src/ucds/CreateAppUCD.d.ts +7 -0
- package/dist/esm/apps/Helper/src/ucds/CreateAppUCD.js +101 -0
- package/dist/esm/apps/Helper/src/ucds/CreateProductUCD.d.ts +7 -0
- package/dist/esm/apps/Helper/src/ucds/CreateProductUCD.js +101 -0
- package/dist/esm/apps/Helper/src/ucds/CreateProjectUCD.d.ts +1 -17
- package/dist/esm/apps/Helper/src/ucds/CreateProjectUCD.js +40 -34
- package/dist/esm/apps/Helper/src/ucds/CreateTargetUCD.d.ts +9 -0
- package/dist/esm/apps/Helper/src/ucds/CreateTargetUCD.js +109 -0
- package/dist/esm/apps/Helper/src/ucds/CreateUCUCD.d.ts +8 -0
- package/dist/esm/apps/Helper/src/ucds/CreateUCUCD.js +87 -0
- package/dist/esm/apps/Helper/src/ucds/DeleteGeneratedAppsTestsUCD.d.ts +1 -1
- package/dist/esm/apps/Helper/src/ucds/DeleteGeneratedAppsTestsUCD.js +1 -1
- package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.d.ts +1 -1
- package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.js +1 -1
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.d.ts +1 -1
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.js +1 -1
- package/dist/esm/convention.d.ts +15 -4
- package/dist/esm/convention.js +33 -9
- 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 +4 -5
- 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/error/funcs.d.ts +2 -0
- package/dist/esm/error/funcs.js +20 -0
- package/dist/esm/error/index.d.ts +1 -1
- package/dist/esm/error/index.js +1 -1
- package/dist/esm/i18n/WordingManager.d.ts +2 -1
- package/dist/esm/i18n/WordingManager.js +23 -2
- package/dist/esm/i18n/locales/de.js +8 -0
- package/dist/esm/i18n/locales/en.js +8 -0
- package/dist/esm/i18n/locales/es.js +8 -0
- package/dist/esm/i18n/locales/fr.js +8 -0
- package/dist/esm/i18n/types.d.ts +2 -2
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.node-test.d.ts +1 -1
- package/dist/esm/index.node-test.js +1 -1
- package/dist/esm/product/index.d.ts +1 -1
- package/dist/esm/product/index.js +1 -1
- package/dist/esm/product/workers/ProductUCsLoader.d.ts +8 -6
- package/dist/esm/product/workers/ProductUCsLoader.js +19 -5
- package/dist/esm/products/Helper/cli-node-core/container.d.ts +3 -0
- package/dist/esm/products/Helper/cli-node-core/container.js +26 -0
- package/dist/esm/products/Helper/cli-node-core/index.d.ts +1 -0
- package/dist/esm/products/Helper/cli-node-core/index.js +9 -0
- package/dist/esm/products/Helper/i18n.d.ts +101 -2
- package/dist/esm/products/Helper/targets/node-core-cli/container.d.ts +3 -0
- package/dist/esm/products/Helper/targets/node-core-cli/container.js +26 -0
- package/dist/esm/products/Helper/targets/node-core-cli/index.d.ts +1 -0
- package/dist/esm/products/Helper/targets/node-core-cli/index.js +9 -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/SettingsManager.d.ts +3 -16
- package/dist/esm/std/SettingsManager.js +1 -16
- package/dist/esm/std/ShellCommandExecutor.d.ts +1 -1
- package/dist/esm/std/consts.js +4 -4
- package/dist/esm/std/impl/EnvSettingsManager.d.ts +5 -4
- package/dist/esm/std/impl/EnvSettingsManager.js +40 -62
- package/dist/esm/std/impl/FakeFSManager.d.ts +3 -1
- package/dist/esm/std/impl/FakeFSManager.js +3 -0
- package/dist/esm/std/impl/FakeShellCommandExecutor.d.ts +12 -0
- package/dist/esm/std/impl/FakeShellCommandExecutor.js +30 -0
- package/dist/esm/std/impl/NodeFSManager.js +3 -2
- package/dist/esm/std/impl/StaticSettingsManager.d.ts +1 -1
- package/dist/esm/std/impl/StaticSettingsManager.js +3 -0
- package/dist/esm/std/index.d.ts +1 -0
- package/dist/esm/std/index.js +1 -0
- package/dist/esm/std/lib/settings.d.ts +5 -0
- package/dist/esm/std/lib/settings.js +39 -0
- package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.d.ts +3 -1
- package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.js +12 -7
- package/dist/esm/target/index.d.ts +1 -0
- package/dist/esm/target/index.js +1 -0
- package/dist/esm/target/lib/cli/CLIManager.d.ts +2 -2
- package/dist/esm/target/lib/client/consts.js +2 -1
- package/dist/esm/target/lib/entrypoint.d.ts +2 -0
- package/dist/esm/target/lib/entrypoint.js +1 -0
- package/dist/esm/target/lib/manifest.d.ts +13 -0
- package/dist/esm/target/lib/manifest.js +11 -0
- package/dist/esm/target/lib/mcp-server/MCPServerBooter.d.ts +2 -2
- 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/CustomerFacingErrorBuilder.js +6 -1
- package/dist/esm/target/lib/server/ServerBooter.d.ts +2 -2
- package/dist/esm/target/lib/server/ServerRequestHandler.js +6 -2
- package/dist/esm/target/lib/server/consts.js +2 -1
- package/dist/esm/target/lib/server-express/funcs.d.ts +2 -0
- package/dist/esm/target/lib/server-express/funcs.js +8 -1
- package/dist/esm/target/lib/server-hono/funcs.d.ts +2 -1
- package/dist/esm/target/lib/server-hono/funcs.js +7 -3
- 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-express-server/NodeExpressServerManager.d.ts +3 -1
- package/dist/esm/target/node-express-server/NodeExpressServerManager.js +17 -12
- package/dist/esm/target/node-hono-server/NodeHonoServerManager.d.ts +3 -1
- package/dist/esm/target/node-hono-server/NodeHonoServerManager.js +15 -10
- package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.d.ts +3 -1
- package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.js +9 -5
- 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/impl/NodeAppTesterConfigurator.d.ts +15 -0
- package/dist/esm/testing/impl/NodeAppTesterConfigurator.js +68 -0
- 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/VitestAppTestSuiteEmitter.d.ts +2 -0
- package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.js +27 -10
- package/dist/esm/testing/impl/newNodeAppTester.js +4 -5
- package/dist/esm/testing/opts.d.ts +1 -1
- package/dist/esm/testing/uc-input.js +5 -2
- package/dist/esm/uc/exec.d.ts +42 -21
- package/dist/esm/uc/exec.js +48 -13
- 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/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/webpack/loader.js +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/ioc/bindCommon.d.ts +4 -4
- package/dist/esm/utils/ioc/bindCommon.js +17 -15
- package/dist/esm/utils/ioc/bindNodeCore.js +5 -0
- package/dist/esm/utils/ioc/bindServer.js +8 -2
- package/dist/esm/utils/types/utility-types.d.ts +4 -0
- package/package.json +19 -16
- package/pnpm-workspace.yaml +0 -8
- package/tsconfig.build.examples.json +0 -8
- package/tsconfig.json +0 -36
- package/vitest.config.ts +0 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.26.0 (2026-01-01)
|
|
4
|
+
|
|
5
|
+
**Highlights**
|
|
6
|
+
|
|
7
|
+
Added new CLI helper commands to create each element of the `libmodulor` 4-layer architecture faster : `CreateApp`, `CreateUC`, `CreateProduct`, `CreateTarget`.
|
|
8
|
+
Check them out with `npx libmodulor --help` (or `pnpm libmodulor --help` within a project with `libmodulor` installed).
|
|
9
|
+
|
|
10
|
+
Simplified settings management : moved to more and better defaults so you don't have to provide any settings when creating new product targets (see [Create a target](https://libmodulor.c100k.eu/docs/guides/create-target)).
|
|
11
|
+
|
|
12
|
+
Simplified testing : replaced `SimpleAppTesterConfigurator` by `NodeAppTesterConfigurator` including the necessary bindings to have tests working out of the box (see [Test an app](https://libmodulor.c100k.eu/docs/guides/test-app)). The `GenerateAppsTests` CLI command now generates a default `Configurator.ts` if it does not exist yet.
|
|
13
|
+
|
|
14
|
+
Moved all the targets of a product into a dedicated `targets` dir so they are not mixed with other types of directories you might have in a product (e.g. specific utilities, implementations, etc.).
|
|
15
|
+
|
|
16
|
+
See all the changes here : https://github.com/c100k/libmodulor/compare/v0.25.0...master
|
|
17
|
+
|
|
18
|
+
## v0.25.0 (2025-12-21)
|
|
19
|
+
|
|
20
|
+
**Highlights**
|
|
21
|
+
|
|
22
|
+
- 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
|
|
23
|
+
- Example : https://github.com/c100k/libmodulor/tree/42fd11307cdd9f8cdec19b4de75d4959bc9f9a9e/examples/apps/Spotify#createalbum
|
|
24
|
+
- Improved the `File` data type
|
|
25
|
+
- Changed the property `path` to `uri` to conform to the `FormData` spec (this is a breaking change)
|
|
26
|
+
- Simplified the declaration by inlining the accepted types via `accept` instead of `type.allowed` (this is also a breaking change)
|
|
27
|
+
- Added `maxSizeInBytes` and `minSizeInBytes` for size validation
|
|
28
|
+
- Added `getConstraintsForHuman` to format constraints for the end user in the targets. For instance :
|
|
29
|
+
- For `FreeTextShort`, it displays `Max length: 150` 🇬🇧 when present
|
|
30
|
+
- For `File`, it displays `Max size: 8MB - Accepted types: application/png, application/jpg` 🇬🇧 when present
|
|
31
|
+
- Applied to the `react-native-pure` and `react-native-web` targets (see `UCFormFieldHelp.tsx`)
|
|
32
|
+
|
|
33
|
+
See all the changes here : https://github.com/c100k/libmodulor/compare/v0.24.0...master
|
|
34
|
+
|
|
3
35
|
## v0.24.0 (2025-12-07)
|
|
4
36
|
|
|
5
37
|
**Highlights**
|
package/README.md
CHANGED
|
@@ -5,163 +5,44 @@
|
|
|
5
5
|
|
|
6
6
|
A TypeScript library to create platform-agnostic applications.
|
|
7
7
|
|
|
8
|
-
##
|
|
9
|
-
|
|
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.
|
|
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.
|
|
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
|
-
```
|
|
8
|
+
## Links
|
|
51
9
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
```
|
|
10
|
+
- [Website](https://libmodulor.c100k.eu)
|
|
11
|
+
- [Documentation](https://libmodulor.c100k.eu/docs)
|
|
12
|
+
- [Concepts > Philosophy](https://libmodulor.c100k.eu/docs/concepts/philosophy)
|
|
13
|
+
- [Examples > Playground](https://libmodulor.c100k.eu/docs/examples/Playground)
|
|
14
|
+
- [Guides > Playground](https://libmodulor.c100k.eu/docs/guides/create-project)
|
|
134
15
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
```
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
As described in the [Architecture](https://libmodulor.c100k.eu/docs/concepts/architecture) concept, `libmodulor` follows a 4-layer architecture with `UseCase`, `App`, `Product`, and `Target`.
|
|
154
19
|
|
|
155
|
-
|
|
20
|
+
Here is how to easily create all of them, in a brand new project :
|
|
156
21
|
|
|
157
|
-
```
|
|
158
|
-
|
|
22
|
+
```sh
|
|
23
|
+
# Create a project
|
|
24
|
+
npx libmodulor CreateProject --projectName my-super-project
|
|
25
|
+
cd my-super-project
|
|
159
26
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
27
|
+
# Create an app
|
|
28
|
+
pnpm libmodulor CreateApp --appName Banking
|
|
29
|
+
|
|
30
|
+
# Create a use case
|
|
31
|
+
pnpm libmodulor CreateUC --appName Banking --ucName CreateAccount
|
|
32
|
+
|
|
33
|
+
# Create a product
|
|
34
|
+
pnpm libmodulor CreateProduct --productName CustomerPortal
|
|
35
|
+
|
|
36
|
+
# Create a target
|
|
37
|
+
pnpm libmodulor CreateTarget --productName CustomerPortal --targetName node-express-server
|
|
38
|
+
pnpm libmodulor CreateTarget --productName CustomerPortal --targetName node-hono-server
|
|
39
|
+
pnpm libmodulor CreateTarget --productName CustomerPortal --targetName node-core-cli
|
|
40
|
+
pnpm libmodulor CreateTarget --productName CustomerPortal --targetName node-mcp-server
|
|
163
41
|
```
|
|
164
42
|
|
|
43
|
+
For more params, checkout the help section : `pnpm libmodulor --help`.
|
|
44
|
+
|
|
45
|
+
And for more details on the code, follow the ad-hoc guides in the documentation.
|
|
165
46
|
|
|
166
47
|
## 👨💻 Contribute
|
|
167
48
|
|
|
@@ -169,4 +50,4 @@ If you think you can help in any way, feel free to contact me (cf. `author` in `
|
|
|
169
50
|
|
|
170
51
|
## ⚖️ License
|
|
171
52
|
|
|
172
|
-
[LGPL-3.0](https://github.com/c100k/libmodulor/blob/v0.
|
|
53
|
+
[LGPL-3.0](https://github.com/c100k/libmodulor/blob/v0.26.0/LICENSE)
|
|
@@ -6,11 +6,10 @@ import type { AppManifestSourceSafe } from '../manifest.js';
|
|
|
6
6
|
import { AppManifestLoader } from './AppManifestLoader.js';
|
|
7
7
|
import type { Input as AppSrcFilePathBuilderInput } from './AppSrcFilePathBuilder.js';
|
|
8
8
|
import { UCDefLoader } from './UCDefLoader.js';
|
|
9
|
-
export
|
|
9
|
+
export type Input = Pick<AppSrcFilePathBuilderInput, 'appsRootPath'> & {
|
|
10
10
|
app: ProductAppReg;
|
|
11
|
-
appsRootPath?: AppSrcFilePathBuilderInput['appsRootPath'];
|
|
12
11
|
srcImporter: SrcImporter<AppManifestSourceSafe | UCDefSourceSafe>;
|
|
13
|
-
}
|
|
12
|
+
};
|
|
14
13
|
export type Output = UC<any, any, any>[];
|
|
15
14
|
export declare class AppUCsLoader implements Worker<Input, Promise<Output>> {
|
|
16
15
|
private appManifestLoader;
|
|
@@ -1,2 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export declare const I18n: {
|
|
2
|
+
en: {
|
|
3
|
+
err_existing_app: string;
|
|
4
|
+
err_existing_product: string;
|
|
5
|
+
err_existing_target: string;
|
|
6
|
+
err_target_generator_not_available: string;
|
|
7
|
+
err_unknown_app: string;
|
|
8
|
+
uc_CreateApp_desc: string;
|
|
9
|
+
uc_CreateApp_label: string;
|
|
10
|
+
uc_CreateProduct_desc: string;
|
|
11
|
+
uc_CreateProduct_label: string;
|
|
12
|
+
uc_CreateProject_desc: string;
|
|
13
|
+
uc_CreateProject_label: string;
|
|
14
|
+
uc_CreateTarget_desc: string;
|
|
15
|
+
uc_CreateTarget_label: string;
|
|
16
|
+
uc_CreateUC_desc: string;
|
|
17
|
+
uc_CreateUC_label: string;
|
|
18
|
+
uc_DeleteGeneratedAppsTests_desc: string;
|
|
19
|
+
uc_DeleteGeneratedAppsTests_label: string;
|
|
20
|
+
uc_GenerateAppsTests_desc: string;
|
|
21
|
+
uc_GenerateAppsTests_label: string;
|
|
22
|
+
uc_TestApp_desc: string;
|
|
23
|
+
uc_TestApp_label: string;
|
|
24
|
+
ucif_appName_desc: string;
|
|
25
|
+
ucif_appPath_desc: string;
|
|
26
|
+
ucif_appsPath_desc: string;
|
|
27
|
+
ucif_depsMapping_desc: string;
|
|
28
|
+
ucif_initialCommit_desc: string;
|
|
29
|
+
ucif_monkeyTestingTimeoutInMs_desc: string;
|
|
30
|
+
ucif_outPath_desc: string;
|
|
31
|
+
ucif_pkgManagerBin_desc: string;
|
|
32
|
+
ucif_productName_desc: string;
|
|
33
|
+
ucif_projectName_desc: string;
|
|
34
|
+
ucif_scmBin_desc: string;
|
|
35
|
+
ucif_serverPortRangeStart_desc: string;
|
|
36
|
+
ucif_skipCoverage_desc: string;
|
|
37
|
+
ucif_updateSnapshots_desc: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
export const I18n = {
|
|
2
2
|
en: {
|
|
3
|
-
|
|
3
|
+
err_existing_app: 'App "{{appPath}}" already exists',
|
|
4
|
+
err_existing_product: 'Product "{{productPath}}" already exists',
|
|
5
|
+
err_existing_target: 'Target "{{targetPath}}" already exists',
|
|
6
|
+
err_target_generator_not_available: 'This target has not been implemented yet via the generator. In the meantime, you can create it manually by following the examples.',
|
|
7
|
+
err_unknown_app: 'App "{{appPath}}" does not exist',
|
|
8
|
+
uc_CreateApp_desc: 'Create the basics of an app (index, i18n, manifest)',
|
|
9
|
+
uc_CreateApp_label: 'Create an app',
|
|
10
|
+
uc_CreateProduct_desc: 'Create the basics of a product (i18n, manifest)',
|
|
11
|
+
uc_CreateProduct_label: 'Create a product',
|
|
4
12
|
uc_CreateProject_desc: 'Create a project by initializing a git repo, creating basic config files and installing the required dependencies',
|
|
5
13
|
uc_CreateProject_label: 'Create a project',
|
|
14
|
+
uc_CreateTarget_desc: 'Create a target based on the ones provided by the lib (see https://libmodulor.c100k.eu/docs/references/targets)',
|
|
15
|
+
uc_CreateTarget_label: 'Create a target',
|
|
16
|
+
uc_CreateUC_desc: 'Create a basic use case',
|
|
17
|
+
uc_CreateUC_label: 'Create a use case',
|
|
6
18
|
uc_DeleteGeneratedAppsTests_desc: 'Delete the automated test suite generated for each app',
|
|
7
19
|
uc_DeleteGeneratedAppsTests_label: 'Delete generated apps tests',
|
|
8
20
|
uc_GenerateAppsTests_desc: 'Generate an automated test suite for each app',
|
|
9
21
|
uc_GenerateAppsTests_label: 'Generate apps tests',
|
|
10
22
|
uc_TestApp_desc: 'Test an app and generate coverage report',
|
|
11
23
|
uc_TestApp_label: 'Test app',
|
|
24
|
+
ucif_appName_desc: 'Name of the app conforming to the spec (i.e. PascalCase : A-Z, 0-9)',
|
|
12
25
|
ucif_appPath_desc: 'The path of the app',
|
|
13
26
|
ucif_appsPath_desc: 'The path to the directory containing all the apps',
|
|
14
27
|
ucif_depsMapping_desc: 'The mapping of dependencies in case some of them need a specific pattern (e.g. one directory above the default)',
|
|
@@ -16,6 +29,7 @@ export const I18n = {
|
|
|
16
29
|
ucif_monkeyTestingTimeoutInMs_desc: 'These tests can take longer than the usual default of 5000ms because they try lots of possibilities',
|
|
17
30
|
ucif_outPath_desc: 'Path to a directory where to create the project. Do not include the project name in it. It is created recursively if missing.',
|
|
18
31
|
ucif_pkgManagerBin_desc: "The package manager to use to install the deps and run the dev commands (must conform to npm's API)",
|
|
32
|
+
ucif_productName_desc: 'Name of the product conforming to the spec (i.e. PascalCase : A-Z, 0-9)',
|
|
19
33
|
ucif_projectName_desc: "Name of the project conforming to the package.json's spec (i.e. a-z, 0-9, -)",
|
|
20
34
|
ucif_scmBin_desc: "The source control manager to use to init and commit (must conform to git's API)",
|
|
21
35
|
ucif_serverPortRangeStart_desc: 'The port number to start with when generating the server to test (incremented by 1) for each app',
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DirPath, FilePath } from '../../../../dt/index.js';
|
|
2
|
+
import type { FSManager, Worker } from '../../../../std/index.js';
|
|
3
|
+
export type Files = Map<FilePath[], string>;
|
|
4
|
+
interface Input {
|
|
5
|
+
files: Files;
|
|
6
|
+
rootPath: DirPath;
|
|
7
|
+
}
|
|
8
|
+
export declare class SrcFilesGenerator implements Worker<Input, Promise<void>> {
|
|
9
|
+
private fsManager;
|
|
10
|
+
constructor(fsManager: FSManager);
|
|
11
|
+
exec({ files, rootPath }: Input): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { inject, injectable } from 'inversify';
|
|
14
|
+
let SrcFilesGenerator = class SrcFilesGenerator {
|
|
15
|
+
fsManager;
|
|
16
|
+
constructor(fsManager) {
|
|
17
|
+
this.fsManager = fsManager;
|
|
18
|
+
}
|
|
19
|
+
async exec({ files, rootPath }) {
|
|
20
|
+
for await (const [filePath, content] of files) {
|
|
21
|
+
const fileName = filePath[filePath.length - 1];
|
|
22
|
+
if (!fileName) {
|
|
23
|
+
throw new Error(`Incorrect file path : ${filePath}`);
|
|
24
|
+
}
|
|
25
|
+
const rest = filePath.slice(0, -1);
|
|
26
|
+
const path = this.fsManager.path(rootPath, ...rest);
|
|
27
|
+
await this.fsManager.mkdir(path, { recursive: true });
|
|
28
|
+
await this.fsManager.touch(this.fsManager.path(rootPath, ...filePath), content);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
SrcFilesGenerator = __decorate([
|
|
33
|
+
injectable(),
|
|
34
|
+
__param(0, inject('FSManager')),
|
|
35
|
+
__metadata("design:paramtypes", [Object])
|
|
36
|
+
], SrcFilesGenerator);
|
|
37
|
+
export { SrcFilesGenerator };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type DirPath } from '../../../../dt/index.js';
|
|
2
|
+
import type { UCInput, UCInputDef, UCInputFieldValue } from '../../../../uc/index.js';
|
|
3
|
+
export interface AppInput extends UCInput {
|
|
4
|
+
appsPath: UCInputFieldValue<DirPath>;
|
|
5
|
+
}
|
|
6
|
+
export declare const AppInputFieldsDef: UCInputDef<AppInput>['fields'];
|
|
7
|
+
export interface ProductInput extends UCInput {
|
|
8
|
+
productsPath: UCInputFieldValue<DirPath>;
|
|
9
|
+
}
|
|
10
|
+
export declare const ProductInputFieldsDef: UCInputDef<ProductInput>['fields'];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { APPS_ROOT_PATH, PRODUCTS_ROOT_PATH } from '../../../../convention.js';
|
|
2
|
+
import { TDirPath } from '../../../../dt/index.js';
|
|
3
|
+
export const AppInputFieldsDef = {
|
|
4
|
+
appsPath: {
|
|
5
|
+
cardinality: {
|
|
6
|
+
min: 0,
|
|
7
|
+
},
|
|
8
|
+
type: new TDirPath()
|
|
9
|
+
.setDefaultValue(APPS_ROOT_PATH.join('/'))
|
|
10
|
+
.setExamples([APPS_ROOT_PATH.join('/')]),
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export const ProductInputFieldsDef = {
|
|
14
|
+
productsPath: {
|
|
15
|
+
cardinality: {
|
|
16
|
+
min: 0,
|
|
17
|
+
},
|
|
18
|
+
type: new TDirPath()
|
|
19
|
+
.setDefaultValue(PRODUCTS_ROOT_PATH.join('/'))
|
|
20
|
+
.setExamples([PRODUCTS_ROOT_PATH.join('/')]),
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { APP_I18N_FILE_NAME, APP_I18N_NAME, APP_INDEX_FILE_NAME, APP_MANIFEST_FILE_NAME, APP_MANIFEST_NAME, APP_SRC_DIR_NAME, } from '../../../../../convention.js';
|
|
2
|
+
import { I18N_DEFAULT_LANG } from '../../../../../i18n/index.js';
|
|
3
|
+
import { LIB_NAME } from '../consts.js';
|
|
4
|
+
import { fileImportName } from '../funcs.js';
|
|
5
|
+
const INDEX_TS = `// Expose only what's necessary
|
|
6
|
+
|
|
7
|
+
export { ${APP_I18N_NAME} } from './${APP_SRC_DIR_NAME}/${fileImportName(APP_I18N_FILE_NAME)}';
|
|
8
|
+
export { ${APP_MANIFEST_NAME} } from './${APP_SRC_DIR_NAME}/${fileImportName(APP_MANIFEST_FILE_NAME)}';
|
|
9
|
+
`;
|
|
10
|
+
const I18N_TS = `import type { AppI18n } from '${LIB_NAME}';
|
|
11
|
+
|
|
12
|
+
export const ${APP_I18N_NAME} = {
|
|
13
|
+
${I18N_DEFAULT_LANG}: {},
|
|
14
|
+
} satisfies AppI18n;
|
|
15
|
+
`;
|
|
16
|
+
const MANIFEST_TS = (name) => `import type { AppManifest } from '${LIB_NAME}';
|
|
17
|
+
|
|
18
|
+
export const ${APP_MANIFEST_NAME} = {
|
|
19
|
+
languageCodes: ['${I18N_DEFAULT_LANG}'],
|
|
20
|
+
name: '${name}',
|
|
21
|
+
ucReg: {},
|
|
22
|
+
} satisfies AppManifest;
|
|
23
|
+
`;
|
|
24
|
+
export function files(name) {
|
|
25
|
+
return new Map([
|
|
26
|
+
[['.', APP_INDEX_FILE_NAME], INDEX_TS],
|
|
27
|
+
[[APP_SRC_DIR_NAME, APP_I18N_FILE_NAME], I18N_TS],
|
|
28
|
+
[[APP_SRC_DIR_NAME, APP_MANIFEST_FILE_NAME], MANIFEST_TS(name)],
|
|
29
|
+
]);
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PRODUCT_I18N_FILE_NAME, PRODUCT_I18N_NAME, PRODUCT_MANIFEST_FILE_NAME, PRODUCT_MANIFEST_NAME, } from '../../../../../convention.js';
|
|
2
|
+
import { I18N_DEFAULT_LANG } from '../../../../../i18n/index.js';
|
|
3
|
+
import { LIB_NAME } from '../consts.js';
|
|
4
|
+
const I18N_TS = `import type { ProductI18n } from '${LIB_NAME}';
|
|
5
|
+
import { I18n${I18N_DEFAULT_LANG.toLocaleUpperCase()} } from 'libmodulor/locales/${I18N_DEFAULT_LANG}';
|
|
6
|
+
|
|
7
|
+
export const ${PRODUCT_I18N_NAME} = {
|
|
8
|
+
${I18N_DEFAULT_LANG}: {
|
|
9
|
+
...I18n${I18N_DEFAULT_LANG.toLocaleUpperCase()},
|
|
10
|
+
p_desc: '',
|
|
11
|
+
p_slogan: '',
|
|
12
|
+
},
|
|
13
|
+
} satisfies ProductI18n;
|
|
14
|
+
`;
|
|
15
|
+
const MANIFEST_TS = (name) => `import type { ProductManifest } from '${LIB_NAME}';
|
|
16
|
+
|
|
17
|
+
export const ${PRODUCT_MANIFEST_NAME} = {
|
|
18
|
+
appReg: [],
|
|
19
|
+
name: '${name}',
|
|
20
|
+
} satisfies ProductManifest;
|
|
21
|
+
`;
|
|
22
|
+
export function files(name) {
|
|
23
|
+
return new Map([
|
|
24
|
+
[['.', PRODUCT_I18N_FILE_NAME], I18N_TS],
|
|
25
|
+
[['.', PRODUCT_MANIFEST_FILE_NAME], MANIFEST_TS(name)],
|
|
26
|
+
]);
|
|
27
|
+
}
|