libmodulor 0.3.0 → 0.5.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.
Files changed (247) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +7 -182
  3. package/dist/esm/app/workers/AppSrcFilePathBuilder.d.ts +16 -0
  4. package/dist/esm/app/workers/AppSrcFilePathBuilder.js +6 -4
  5. package/dist/esm/apps/Helper/index.js +1 -0
  6. package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.js +3 -2
  7. package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.js +3 -0
  8. package/dist/esm/convention.d.ts +1 -0
  9. package/dist/esm/convention.js +17 -4
  10. package/dist/esm/dt/Validation.d.ts +8 -0
  11. package/dist/esm/dt/Validation.js +8 -0
  12. package/dist/esm/dt/base/TBase.d.ts +2 -1
  13. package/dist/esm/dt/base/TBoolean.js +2 -0
  14. package/dist/esm/dt/base/TInt.js +3 -0
  15. package/dist/esm/dt/base/TNumber.js +2 -0
  16. package/dist/esm/dt/base/TObject.d.ts +15 -0
  17. package/dist/esm/dt/base/TObject.js +14 -0
  18. package/dist/esm/dt/base/TString.js +1 -1
  19. package/dist/esm/dt/final/TAmount.js +1 -0
  20. package/dist/esm/dt/final/TCountryISO3166Alpha2.js +1 -0
  21. package/dist/esm/dt/final/TCurrencyISO4217.js +1 -0
  22. package/dist/esm/dt/final/TDateTimeFormat.js +1 -0
  23. package/dist/esm/dt/final/TEmail.js +2 -0
  24. package/dist/esm/dt/final/TEmoji.js +4 -0
  25. package/dist/esm/dt/final/TFile.js +3 -0
  26. package/dist/esm/dt/final/THostAddress.js +2 -0
  27. package/dist/esm/dt/final/TIPv6.js +1 -0
  28. package/dist/esm/dt/final/TJWT.js +8 -0
  29. package/dist/esm/dt/final/TPercentage.js +5 -0
  30. package/dist/esm/dt/final/TSQLQuery.js +1 -0
  31. package/dist/esm/dt/final/TSSHPrivateKey.js +3 -1
  32. package/dist/esm/dt/final/TSemVerVersion.js +1 -0
  33. package/dist/esm/dt/final/TShellCommand.js +1 -0
  34. package/dist/esm/dt/final/TURL.js +2 -0
  35. package/dist/esm/dt/final/TUUID.js +1 -0
  36. package/dist/esm/dt/final/TYesNo.js +1 -1
  37. package/dist/esm/i18n/WordingManager.d.ts +16 -0
  38. package/dist/esm/i18n/types.d.ts +5 -0
  39. package/dist/esm/icon/Icon.d.ts +7 -0
  40. package/dist/esm/index.d.ts +3 -0
  41. package/dist/esm/index.js +4 -0
  42. package/dist/esm/index.react-native-pure.d.ts +10 -0
  43. package/dist/esm/index.react-native-pure.js +10 -0
  44. package/dist/esm/product/manifest.d.ts +15 -0
  45. package/dist/esm/products/Helper/index.js +3 -0
  46. package/dist/esm/products/Helper/manifest.d.ts +6 -1
  47. package/dist/esm/std/BufferManager.d.ts +18 -0
  48. package/dist/esm/std/ClockManager.d.ts +5 -0
  49. package/dist/esm/std/EnvironmentManager.d.ts +10 -0
  50. package/dist/esm/std/HTTPAPICaller.d.ts +6 -0
  51. package/dist/esm/std/I18nManager.d.ts +26 -0
  52. package/dist/esm/std/JWTManager.d.ts +26 -0
  53. package/dist/esm/std/JobManager.d.ts +6 -0
  54. package/dist/esm/std/LLMManager.d.ts +25 -0
  55. package/dist/esm/std/LLMManager.js +1 -0
  56. package/dist/esm/std/PromptManager.d.ts +8 -0
  57. package/dist/esm/std/SettingsManager.d.ts +19 -0
  58. package/dist/esm/std/SettingsManager.js +9 -0
  59. package/dist/esm/std/impl/ConsoleLogger.js +7 -1
  60. package/dist/esm/std/impl/FakeEmailManager.js +1 -0
  61. package/dist/esm/std/impl/FakeJobManager.js +1 -0
  62. package/dist/esm/std/impl/FetchHTTPAPICallExecutor.d.ts +9 -0
  63. package/dist/esm/std/impl/FetchHTTPAPICallExecutor.js +11 -0
  64. package/dist/esm/std/impl/MistralAILLMManager.d.ts +17 -0
  65. package/dist/esm/std/impl/MistralAILLMManager.js +56 -0
  66. package/dist/esm/std/impl/NodeCryptoManager.js +6 -1
  67. package/dist/esm/std/impl/NodeDeterministicCryptoManager.d.ts +14 -0
  68. package/dist/esm/std/impl/NodeDeterministicCryptoManager.js +17 -3
  69. package/dist/esm/std/impl/NodeFSManager.js +10 -0
  70. package/dist/esm/std/impl/NodeHTTPAPICallExecutorAgentBuilder.js +2 -0
  71. package/dist/esm/std/impl/NodePromptManager.js +3 -0
  72. package/dist/esm/std/impl/OllamaLLMManager.d.ts +20 -0
  73. package/dist/esm/std/impl/OllamaLLMManager.js +56 -0
  74. package/dist/esm/std/impl/OpenAILLMManager.d.ts +17 -0
  75. package/dist/esm/std/impl/OpenAILLMManager.js +51 -0
  76. package/dist/esm/std/impl/SimpleHTTPAPICaller.js +14 -0
  77. package/dist/esm/std/impl/SimpleMapI18nManager.js +4 -2
  78. package/dist/esm/std/impl/StdDateClockManager.js +3 -0
  79. package/dist/esm/std/impl/UCDataStoreExternalResourceManager.js +3 -0
  80. package/dist/esm/std/impl/WebCryptoManager.js +9 -0
  81. package/dist/esm/std/index.d.ts +1 -0
  82. package/dist/esm/std/index.js +1 -0
  83. package/dist/esm/target/lib/cli/renderer.js +3 -0
  84. package/dist/esm/target/lib/client/consts.d.ts +3 -0
  85. package/dist/esm/target/lib/client/consts.js +3 -0
  86. package/dist/esm/target/lib/mcp-server/MCPServerBooter.js +1 -0
  87. package/dist/esm/target/lib/react/UCContainer.js +1 -0
  88. package/dist/esm/target/lib/react/UCPanel.js +4 -0
  89. package/dist/esm/target/lib/react/entrypoint.d.ts +2 -0
  90. package/dist/esm/target/lib/react/useUC.d.ts +8 -0
  91. package/dist/esm/target/lib/react/useUC.js +22 -0
  92. package/dist/esm/target/lib/react/useUCOR.d.ts +15 -0
  93. package/dist/esm/target/lib/react/useUCOR.js +45 -0
  94. package/dist/esm/target/lib/rn/input.d.ts +15 -0
  95. package/dist/esm/target/lib/rn/input.js +28 -0
  96. package/dist/esm/target/lib/server/AuthenticationChecker.js +2 -1
  97. package/dist/esm/target/lib/server/BasicAuthenticationChecker.js +1 -0
  98. package/dist/esm/target/lib/server/CSPDirectivesBuilder.js +13 -0
  99. package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.js +3 -0
  100. package/dist/esm/target/lib/server/PrivateApiKeyAuthenticationChecker.js +1 -0
  101. package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
  102. package/dist/esm/target/lib/server/RequestChecker.js +5 -4
  103. package/dist/esm/target/lib/server/RequestHandler.d.ts +5 -0
  104. package/dist/esm/target/lib/server/RequestLogger.js +5 -0
  105. package/dist/esm/target/lib/server/ServerManager.d.ts +19 -0
  106. package/dist/esm/target/lib/server/consts.d.ts +3 -0
  107. package/dist/esm/target/lib/server/consts.js +3 -0
  108. package/dist/esm/target/lib/web/input.d.ts +21 -0
  109. package/dist/esm/target/lib/web/input.js +4 -0
  110. package/dist/esm/target/node-core-cli/NodeCoreCLIManager.js +2 -2
  111. package/dist/esm/target/node-express-server/NodeExpressServerManager.js +5 -0
  112. package/dist/esm/target/node-express-server/lib/AuthCookieCreator.js +1 -1
  113. package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.js +1 -0
  114. package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.js +1 -0
  115. package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.js +1 -0
  116. package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +8 -0
  117. package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.js +1 -0
  118. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.d.ts +10 -0
  119. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +14 -0
  120. package/dist/esm/target/react-native-pure/UCAutoExecLoader.d.ts +2 -0
  121. package/dist/esm/target/react-native-pure/UCAutoExecLoader.js +5 -0
  122. package/dist/esm/target/react-native-pure/UCEntrypointTouchable.d.ts +4 -0
  123. package/dist/esm/target/react-native-pure/UCEntrypointTouchable.js +6 -0
  124. package/dist/esm/target/react-native-pure/UCExecTouchable.d.ts +4 -0
  125. package/dist/esm/target/react-native-pure/UCExecTouchable.js +9 -0
  126. package/dist/esm/target/react-native-pure/UCForm.d.ts +4 -0
  127. package/dist/esm/target/react-native-pure/UCForm.js +13 -0
  128. package/dist/esm/target/react-native-pure/UCFormField.d.ts +11 -0
  129. package/dist/esm/target/react-native-pure/UCFormField.js +32 -0
  130. package/dist/esm/target/react-native-pure/UCFormFieldControl.d.ts +11 -0
  131. package/dist/esm/target/react-native-pure/UCFormFieldControl.js +37 -0
  132. package/dist/esm/target/react-native-pure/UCFormFieldDesc.d.ts +7 -0
  133. package/dist/esm/target/react-native-pure/UCFormFieldDesc.js +11 -0
  134. package/dist/esm/target/react-native-pure/UCFormFieldErr.d.ts +7 -0
  135. package/dist/esm/target/react-native-pure/UCFormFieldErr.js +5 -0
  136. package/dist/esm/target/react-native-pure/UCFormFieldLabel.d.ts +7 -0
  137. package/dist/esm/target/react-native-pure/UCFormFieldLabel.js +8 -0
  138. package/dist/esm/target/react-native-pure/UCFormSubmitControl.d.ts +9 -0
  139. package/dist/esm/target/react-native-pure/UCFormSubmitControl.js +8 -0
  140. package/dist/esm/target/react-web-pure/UCEntrypointTouchable.d.ts +1 -1
  141. package/dist/esm/target/react-web-pure/UCExecTouchable.d.ts +1 -1
  142. package/dist/esm/target/react-web-pure/UCExecTouchable.js +1 -1
  143. package/dist/esm/target/react-web-pure/UCFormFieldControl.d.ts +1 -1
  144. package/dist/esm/target/react-web-pure/UCFormFieldControl.js +3 -3
  145. package/dist/esm/testing/AppTester.d.ts +4 -0
  146. package/dist/esm/testing/AppTester.js +16 -0
  147. package/dist/esm/testing/AppTesterConfigurator.d.ts +68 -0
  148. package/dist/esm/testing/UCDataStoreTester.d.ts +9 -0
  149. package/dist/esm/testing/UCDataStoreTester.js +13 -0
  150. package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +22 -2
  151. package/dist/esm/testing/impl/SimpleAppTesterConfigurator.js +1 -0
  152. package/dist/esm/testing/impl/SimpleHTMLAppTestReportEmitter.js +9 -3
  153. package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +12 -4
  154. package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.js +6 -0
  155. package/dist/esm/testing/opts.d.ts +38 -0
  156. package/dist/esm/testing/opts.js +1 -1
  157. package/dist/esm/testing/uc-input.js +2 -0
  158. package/dist/esm/testing/workers/AppTesterCtxInitializer.js +7 -0
  159. package/dist/esm/testing/workers/UCExecutor.js +1 -0
  160. package/dist/esm/testing/workers/checkers/AppIndexChecker.js +1 -0
  161. package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +4 -0
  162. package/dist/esm/uc/UC.js +19 -1
  163. package/dist/esm/uc/UCInputField.d.ts +28 -0
  164. package/dist/esm/uc/UCInputField.js +42 -0
  165. package/dist/esm/uc/data.d.ts +3 -0
  166. package/dist/esm/uc/def.d.ts +7 -0
  167. package/dist/esm/uc/exec.d.ts +39 -0
  168. package/dist/esm/uc/exec.js +29 -0
  169. package/dist/esm/uc/ext.d.ts +30 -1
  170. package/dist/esm/uc/helpers/UCOutputBuilder.js +5 -0
  171. package/dist/esm/uc/helpers/UCOutputReader.js +3 -1
  172. package/dist/esm/uc/impl/HTTPUCTransporter.js +4 -0
  173. package/dist/esm/uc/impl/InMemoryUCDataStore.js +7 -0
  174. package/dist/esm/uc/impl/KnexUCDataStore.d.ts +4 -0
  175. package/dist/esm/uc/impl/KnexUCDataStore.js +14 -0
  176. package/dist/esm/uc/impl/SimpleUCManager.js +6 -0
  177. package/dist/esm/uc/input-field.d.ts +60 -0
  178. package/dist/esm/uc/input-field.js +33 -0
  179. package/dist/esm/uc/input.d.ts +24 -0
  180. package/dist/esm/uc/lifecycle/client/IdleClientMain.js +1 -0
  181. package/dist/esm/uc/lifecycle/server/IdleServerMain.js +2 -0
  182. package/dist/esm/uc/manager.d.ts +11 -0
  183. package/dist/esm/uc/metadata.d.ts +10 -0
  184. package/dist/esm/uc/opi-layout.d.ts +3 -0
  185. package/dist/esm/uc/opi.d.ts +8 -0
  186. package/dist/esm/uc/output-field.d.ts +9 -0
  187. package/dist/esm/uc/output-part.d.ts +22 -0
  188. package/dist/esm/uc/output.d.ts +3 -0
  189. package/dist/esm/uc/policies/RoleRegularUCPolicy.js +1 -0
  190. package/dist/esm/uc/policies/funcs.js +1 -0
  191. package/dist/esm/uc/policy.d.ts +22 -0
  192. package/dist/esm/uc/sec.d.ts +9 -0
  193. package/dist/esm/uc/server.d.ts +10 -0
  194. package/dist/esm/uc/settings.d.ts +25 -0
  195. package/dist/esm/uc/side-effect.d.ts +16 -0
  196. package/dist/esm/uc/side-effect.js +16 -0
  197. package/dist/esm/uc/utils/rInput.d.ts +12 -0
  198. package/dist/esm/uc/utils/rInput.js +2 -0
  199. package/dist/esm/uc/utils/rVal.d.ts +25 -0
  200. package/dist/esm/uc/utils/rVal.js +27 -0
  201. package/dist/esm/uc/utils/recIs.d.ts +9 -0
  202. package/dist/esm/uc/utils/recIs.js +12 -1
  203. package/dist/esm/uc/utils/stripUCDLifecycleServer.d.ts +13 -0
  204. package/dist/esm/uc/utils/stripUCDLifecycleServer.js +17 -0
  205. package/dist/esm/uc/utils/ucifcoIsForArray.d.ts +6 -0
  206. package/dist/esm/uc/utils/ucifcoIsForArray.js +6 -0
  207. package/dist/esm/uc/workers/SimpleAggregateFinder.d.ts +12 -0
  208. package/dist/esm/uc/workers/SimpleAggregateFinder.js +12 -0
  209. package/dist/esm/uc/workers/UCBuilder.d.ts +7 -0
  210. package/dist/esm/uc/workers/UCBuilder.js +7 -0
  211. package/dist/esm/uc/workers/UCExecChecker.js +2 -0
  212. package/dist/esm/uc/workers/UCInputFilesProcessor.js +10 -4
  213. package/dist/esm/uc/workers/UCOutputFilesProcessor.js +6 -2
  214. package/dist/esm/utils/async/sleep.d.ts +10 -0
  215. package/dist/esm/utils/async/sleep.js +10 -0
  216. package/dist/esm/utils/http/appendData.js +5 -1
  217. package/dist/esm/utils/ioc/ContainerPrinter.js +2 -0
  218. package/dist/esm/utils/ioc/bindCommon.js +4 -0
  219. package/dist/esm/utils/ioc/bindNodeCLI.js +2 -0
  220. package/dist/esm/utils/ioc/bindNodeCore.js +1 -0
  221. package/dist/esm/utils/ioc/bindProduct.js +2 -0
  222. package/dist/esm/utils/ioc/bindRN.js +1 -0
  223. package/dist/esm/utils/ioc/bindServer.js +1 -0
  224. package/dist/esm/utils/ioc/bindWeb.js +2 -0
  225. package/dist/esm/utils/ioc/container.js +6 -0
  226. package/dist/esm/utils/numbers/units.js +3 -0
  227. package/dist/esm/utils/types/funcs.d.ts +35 -0
  228. package/dist/esm/utils/types/funcs.js +35 -0
  229. package/dist/esm/utils/types/utility-types.d.ts +17 -0
  230. package/dist/esm/utils/types/utility-types.js +1 -0
  231. package/package.json +16 -9
  232. package/docs/assets/trading-buy-asset-sequence-diagram.png +0 -0
  233. package/docs/assets/trading-target-mcp-server.png +0 -0
  234. package/docs/assets/trading-target-web-human.png +0 -0
  235. package/docs/assets/trading-target-web.png +0 -0
  236. package/docs/getting-started/001_Create_the_project.md +0 -168
  237. package/docs/getting-started/002_Create_the_App.md +0 -49
  238. package/docs/getting-started/003_Create_the_UseCase.md +0 -205
  239. package/docs/getting-started/004_Test_the_App.md +0 -114
  240. package/docs/getting-started/005_Create_the_Product.md +0 -46
  241. package/docs/getting-started/006_Create_the_server_Target.md +0 -130
  242. package/docs/getting-started/007_Create_the_web_Target.md +0 -262
  243. package/docs/getting-started/008_Switch_to_a_persistent_data_storage.md +0 -55
  244. package/docs/getting-started/009_Define_wording_for_humans.md +0 -42
  245. package/docs/getting-started/010_Create_the_cli_Target.md +0 -102
  246. package/docs/getting-started/011_Create_the_mcp_server_Target.md +0 -157
  247. package/docs/getting-started/012_Summary.md +0 -29
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "libmodulor",
3
3
  "description": "An opinionated TypeScript library to create business oriented applications",
4
- "version": "0.3.0",
4
+ "version": "0.5.0",
5
5
  "license": "LGPL-3.0",
6
6
  "author": "Chafik H'nini <chafik.hnini@gmail.com>",
7
7
  "homepage": "https://github.com/c100k/libmodulor#readme",
@@ -31,6 +31,9 @@
31
31
  "./node": {
32
32
  "import": "./dist/esm/index.node.js"
33
33
  },
34
+ "./react-native-pure": {
35
+ "import": "./dist/esm/index.react-native-pure.js"
36
+ },
34
37
  "./react-web-pure": {
35
38
  "import": "./dist/esm/index.react-web-pure.js"
36
39
  },
@@ -54,26 +57,27 @@
54
57
  }
55
58
  },
56
59
  "peerDependencies": {
57
- "@hono/node-server": "^1.13.7",
58
- "@modelcontextprotocol/sdk": "^1.1.1",
59
- "@stricli/core": "^1.1.0",
60
+ "@hono/node-server": "^1.13.8",
61
+ "@modelcontextprotocol/sdk": "^1.5.0",
62
+ "@stricli/core": "^1.1.1",
60
63
  "buffer": "^6.0.3",
61
64
  "cookie-parser": "^1.4.7",
62
65
  "express": "^4.21.2",
63
66
  "express-fileupload": "^1.5.1",
64
67
  "fast-check": "^3.23.2",
65
68
  "helmet": "^8.0.0",
66
- "hono": "^4.6.16",
67
- "inversify": "^6.2.1",
68
- "jose": "^5.9.6",
69
+ "hono": "^4.7.2",
70
+ "inversify": "^6.2.2",
71
+ "jose": "^6.0.6",
69
72
  "knex": "^3.1.0",
70
- "pg": "^8.13.1",
73
+ "pg": "^8.13.3",
71
74
  "react": "^18.3.1",
72
75
  "react-dom": "^18.3.1",
76
+ "react-native": "^0.78.0",
73
77
  "reflect-metadata": "^0.2.2",
74
78
  "sqlite3": "^5.1.7",
75
79
  "typescript": "^5.7.3",
76
- "vite": "^6.0.7"
80
+ "vite": "^6.1.1"
77
81
  },
78
82
  "peerDependenciesMeta": {
79
83
  "@hono/node-server": {
@@ -103,6 +107,9 @@
103
107
  "react-dom": {
104
108
  "optional": true
105
109
  },
110
+ "react-native": {
111
+ "optional": true
112
+ },
106
113
  "sqlite3": {
107
114
  "optional": true
108
115
  },
Binary file
@@ -1,168 +0,0 @@
1
- # Create the project
2
-
3
- Assuming you have the following installed (otherwise, install them or adapt the commands) :
4
-
5
- - `node` >= 22
6
- - `yarn` >= 1.x
7
- - `wget` and `curl`
8
-
9
- If you're on macOS, for the `sed` commands, add a `''` after `-i` ([Explanation](https://stackoverflow.com/a/4247319/1259118)).
10
-
11
- ```sh
12
- # Create the directory
13
- mkdir libmodulor-tuto && cd libmodulor-tuto # Note how the repository is generic to contain multiple apps and products
14
-
15
- # Initialize git
16
- git init
17
-
18
- # Initialize config files
19
- touch .gitignore biome.json package.json README.md tsconfig.json vitest.config.ts
20
- ```
21
-
22
- ## .gitignore
23
-
24
- ```.gitignore
25
- coverage
26
- dist
27
- node_modules
28
- src/apps/**/test/reports
29
- .env
30
- ```
31
-
32
- ## biome.json
33
-
34
- ```json
35
- {
36
- "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
37
- "files": {
38
- "ignore": ["coverage", "dist", "node_modules"],
39
- "ignoreUnknown": true
40
- },
41
- "formatter": {
42
- "indentStyle": "space",
43
- "indentWidth": 4
44
- },
45
- "javascript": {
46
- "formatter": {
47
- "quoteStyle": "single"
48
- },
49
- "parser": {
50
- "unsafeParameterDecoratorsEnabled": true
51
- }
52
- }
53
- }
54
- ```
55
-
56
- ## package.json
57
-
58
- ```json
59
- {
60
- "name": "libmodulor-tuto",
61
- "version": "0.1.0",
62
- "author": "Chafik H'nini <chafik.hnini@gmail.com>",
63
- "type": "module",
64
- "private": true,
65
- "scripts": {
66
- "helper": "node ./node_modules/libmodulor/dist/esm/products/Helper/index.js",
67
- "lint": "biome check --write .",
68
- "test": "tsc && vitest run"
69
- },
70
- "dependencies": {
71
- "inversify": "^6.2.1",
72
- "libmodulor": "^0.3.0",
73
- "reflect-metadata": "^0.2.2"
74
- },
75
- "devDependencies": {
76
- "@biomejs/biome": "^1.9.4",
77
- "@types/node": "^22.10.7",
78
- "@vitest/coverage-v8": "^3.0.2",
79
- "buffer": "^6.0.3",
80
- "cookie-parser": "^1.4.7",
81
- "express": "^4.21.2",
82
- "express-fileupload": "^1.5.1",
83
- "fast-check": "^3.23.2",
84
- "helmet": "^8.0.0",
85
- "jose": "^5.9.6",
86
- "typescript": "^5.7.3",
87
- "vite": "^6.0.11",
88
- "vitest": "^3.0.3"
89
- }
90
- }
91
- ```
92
-
93
- ## README.md
94
-
95
- ```md
96
- # libmodulor-tuto
97
-
98
- 🚀🚀🚀
99
- ```
100
-
101
- ## tsconfig.json
102
-
103
- ```json
104
- {
105
- "compilerOptions": {
106
- "allowSyntheticDefaultImports": true,
107
- "declaration": true,
108
- "lib": ["dom", "esnext"],
109
- "module": "NodeNext",
110
- "moduleResolution": "NodeNext",
111
- "noEmit": true,
112
- "removeComments": true,
113
- "skipLibCheck": true,
114
- "sourceMap": true,
115
- "target": "ESNext",
116
-
117
- "strict": true,
118
- "allowUnreachableCode": false,
119
- "allowUnusedLabels": false,
120
- "exactOptionalPropertyTypes": true,
121
- "noFallthroughCasesInSwitch": true,
122
- "noPropertyAccessFromIndexSignature": true,
123
- "noImplicitOverride": true,
124
- "noImplicitReturns": true,
125
- "noUncheckedIndexedAccess": true,
126
- "noUnusedLocals": true,
127
- "noUnusedParameters": true,
128
- "verbatimModuleSyntax": true,
129
-
130
- "emitDecoratorMetadata": true,
131
- "experimentalDecorators": true,
132
-
133
- "jsx": "react"
134
- }
135
- }
136
- ```
137
-
138
- ## vitest.config.ts
139
-
140
- ```typescript
141
- import { defineConfig } from 'vitest/config';
142
-
143
- export default defineConfig({
144
- test: {
145
- coverage: {
146
- enabled: true,
147
- exclude: ['src/apps/**/test', 'src/**/*.test.ts'],
148
- include: ['src'],
149
- reporter: ['html', 'lcov', 'text'],
150
- },
151
- reporters: ['verbose'],
152
- },
153
- });
154
- ```
155
-
156
- ## Install
157
-
158
- ```sh
159
- yarn install
160
- ```
161
-
162
- ```sh
163
- yarn lint && git add . && git commit -m "chore: init source code"
164
- ```
165
-
166
- Optionally, you can create a remote repository (e.g. on GitHub) and push it.
167
-
168
- Now that's done, let's [Create the App](./002_Create_the_App.md).
@@ -1,49 +0,0 @@
1
- # Create the App
2
-
3
- An app is composed of three main files : `i18n.ts`, `manifest.ts` and `index.ts`.
4
-
5
- ```sh
6
- mkdir -p src/apps/Trading/src/ucds
7
- touch src/apps/Trading/src/{i18n.ts,manifest.ts}
8
- touch src/apps/Trading/index.ts
9
- ```
10
-
11
- > [!NOTE]
12
- > There is a lot of controversy about barrel files. In this specific context, they are useful to only expose the necessary things to the upper layers and keep the app isolated.
13
-
14
- ## i18n.ts
15
-
16
- ```typescript
17
- import type { AppI18n } from 'libmodulor';
18
-
19
- export const I18n: AppI18n = {
20
- en: {},
21
- };
22
- ```
23
-
24
- ## manifest.ts
25
-
26
- ```typescript
27
- import type { AppManifest } from 'libmodulor';
28
-
29
- export const Manifest = {
30
- languageCodes: ['en'],
31
- name: 'Trading',
32
- ucReg: {},
33
- } satisfies AppManifest;
34
- ```
35
-
36
- ## index.ts
37
-
38
- ```typescript
39
- // Expose only what's necessary
40
-
41
- export { I18n } from './src/i18n.js';
42
- export { Manifest } from './src/manifest.js';
43
- ```
44
-
45
- ```sh
46
- yarn lint && git add . && git commit -m "feat: add the app"
47
- ```
48
-
49
- Now that's done, let's [Create the UseCase](./003_Create_the_UseCase.md).
@@ -1,205 +0,0 @@
1
- # Create the UseCase
2
-
3
- > [!NOTE]
4
- > Starting now, you'll see `UC` or `uc` a lot. It's the abbreviation of `UseCase`. Acronyms are not good in codebases, except those that are commonly used ([debate](https://stackoverflow.com/questions/2236807/java-naming-convention-with-acronyms)). In any case, when you write `UseCase` hundreds of times, you're happy to be able to write `UC` instead. Thus, `UCD` stands for `Use Case Definition`, `UCIF` stands for `Use Case Input Field` and so on.
5
-
6
- The app manifest registers all the use cases metadata. Use cases can depend on each other as we'll see later, and this dependency must go through the manifest. Never directly.
7
-
8
- Update `manifest.ts` to register the new use case.
9
-
10
- ```typescript
11
- // ...
12
- ucReg: {
13
- BuyAsset: {
14
- action: 'Create',
15
- icon: 'plus',
16
- name: 'BuyAsset',
17
- },
18
- },
19
- // ...
20
- ```
21
-
22
- If you're using an IDE with auto-complete, you might have noticed the other properties like `beta`, `new`, `sensitive`. We'll come back to them later.
23
-
24
- ```sh
25
- mkdir src/apps/Trading/src/dt
26
- touch src/apps/Trading/src/dt/TISIN.ts
27
- touch src/apps/Trading/src/ucds/{BuyAssetServerMain.ts,BuyAssetUCD.ts}
28
- ```
29
-
30
- ## TISIN.ts
31
-
32
- An asset is usually identified by a unique code called [ISIN](https://www.isin.org). This is a typical business data type that has specific rules and that is not simply a `string`.
33
-
34
- ```typescript
35
- import { type TName, TString, type TStringConstraints } from 'libmodulor';
36
-
37
- export type ISIN = Capitalize<string>;
38
-
39
- export class TISIN extends TString<ISIN, 'ISIN'> {
40
- public static readonly FORMAT: RegExp = /^[A-Z]{2}[A-Z0-9]{9}[0-9]$/;
41
-
42
- constructor(constraints?: TStringConstraints) {
43
- super({
44
- ...constraints,
45
- format: { f: 'ISIN', regexp: TISIN.FORMAT },
46
- });
47
- }
48
-
49
- public override tName(): TName {
50
- return 'ISIN';
51
- }
52
-
53
- public override example(): ISIN {
54
- return 'US02079K3059';
55
- }
56
- }
57
- ```
58
-
59
- ## BuyAssetUCD.ts
60
-
61
- ```typescript
62
- import {
63
- type AggregateOPI0,
64
- type Amount,
65
- EverybodyUCPolicy,
66
- TAmount,
67
- TBoolean,
68
- TUIntQuantity,
69
- type UCDef,
70
- type UCInput,
71
- type UCInputFieldValue,
72
- type UCMain,
73
- type UCMainInput,
74
- type UCOutputOrNothing,
75
- type UCTransporter,
76
- type UIntQuantity,
77
- } from 'libmodulor';
78
- import { inject, injectable } from 'inversify';
79
-
80
- import { Manifest } from '../manifest.js';
81
-
82
- import { type ISIN, TISIN } from '../dt/TISIN.js';
83
- import { BuyAssetServerMain } from './BuyAssetServerMain.js';
84
-
85
- export interface BuyAssetInput extends UCInput {
86
- isin: UCInputFieldValue<ISIN>;
87
- limit: UCInputFieldValue<Amount>;
88
- qty: UCInputFieldValue<UIntQuantity>;
89
- }
90
-
91
- export interface BuyAssetOPI0 extends AggregateOPI0 {
92
- executedDirectly: boolean;
93
- }
94
-
95
- @injectable()
96
- class BuyAssetClientMain implements UCMain<BuyAssetInput, BuyAssetOPI0> {
97
- constructor(
98
- @inject('UCTransporter')
99
- private ucTransporter: UCTransporter,
100
- ) {}
101
-
102
- public async exec({
103
- uc,
104
- }: UCMainInput<BuyAssetInput, BuyAssetOPI0>): Promise<
105
- UCOutputOrNothing<BuyAssetOPI0>
106
- > {
107
- return this.ucTransporter.send(uc);
108
- }
109
- }
110
-
111
- export const BuyAssetUCD: UCDef<BuyAssetInput, BuyAssetOPI0> = {
112
- io: {
113
- i: {
114
- fields: {
115
- isin: {
116
- type: new TISIN(),
117
- },
118
- limit: {
119
- type: new TAmount('USD'),
120
- },
121
- qty: {
122
- type: new TUIntQuantity(),
123
- },
124
- },
125
- },
126
- o: {
127
- parts: {
128
- _0: {
129
- fields: {
130
- executedDirectly: {
131
- type: new TBoolean(),
132
- },
133
- },
134
- },
135
- },
136
- },
137
- },
138
- lifecycle: {
139
- client: {
140
- main: BuyAssetClientMain,
141
- policy: EverybodyUCPolicy,
142
- },
143
- server: {
144
- main: BuyAssetServerMain,
145
- policy: EverybodyUCPolicy,
146
- },
147
- },
148
- metadata: Manifest.ucReg.BuyAsset,
149
- };
150
- ```
151
-
152
- ## BuyAssetServerMain.ts
153
-
154
- ```typescript
155
- import {
156
- type UCMain,
157
- type UCMainInput,
158
- type UCManager,
159
- type UCOutput,
160
- UCOutputBuilder,
161
- } from 'libmodulor';
162
- import { inject, injectable } from 'inversify';
163
-
164
- import type { BuyAssetInput, BuyAssetOPI0 } from './BuyAssetUCD.js';
165
-
166
- @injectable()
167
- export class BuyAssetServerMain implements UCMain<BuyAssetInput, BuyAssetOPI0> {
168
- constructor(@inject('UCManager') private ucManager: UCManager) {}
169
-
170
- public async exec({
171
- uc,
172
- }: UCMainInput<BuyAssetInput, BuyAssetOPI0>): Promise<
173
- UCOutput<BuyAssetOPI0>
174
- > {
175
- // >=> Persist the order
176
- const { aggregateId } = await this.ucManager.persist(uc);
177
-
178
- // >=> TODO : Check the user has enough funds to place the order
179
-
180
- // >=> TODO : Send the order to a queue for processing
181
- const executedDirectly: BuyAssetOPI0['executedDirectly'] = false;
182
-
183
- return new UCOutputBuilder<BuyAssetOPI0>()
184
- .add({
185
- executedDirectly,
186
- id: aggregateId,
187
- })
188
- .get();
189
- }
190
- }
191
- ```
192
-
193
- For now, we won't detail all this code but take the time to read it and understand how it works. Hopefully it's clear enough and self-explanatory.
194
-
195
- > [!TIP]
196
- > Using a comment following the pattern `// >=> ` in `ClientMain` and `ServerMain` has a specific meaning as we'll see a little bit later.
197
-
198
- > [!NOTE]
199
- > Unlike `ClientMain`, `ServerMain` is put in another file for "historical" reasons, mainly for stripping and tree shaking reasons. More on this later.
200
-
201
- ```sh
202
- yarn lint && git add . && git commit -m "feat: add the use case"
203
- ```
204
-
205
- Now that's done, let's [Test the App](./004_Test_the_App.md).
@@ -1,114 +0,0 @@
1
- # Test the App
2
-
3
- ## Preliminary test
4
-
5
- By default, we rely on [vitest](https://vitest.dev) to run the tests and [@vitest/coverage-v8](https://vitest.dev/guide/coverage) for the coverage.
6
-
7
- ```sh
8
- yarn test
9
- ```
10
-
11
- ```sh
12
- % Coverage report from v8
13
- ------------------------|---------|----------|---------|---------|-------------------
14
- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
15
- ------------------------|---------|----------|---------|---------|-------------------
16
- All files | 0 | 40 | 40 | 0 |
17
- Trading | 0 | 0 | 0 | 0 |
18
- index.ts | 0 | 0 | 0 | 0 | 1
19
- Trading/src | 0 | 100 | 100 | 0 |
20
- i18n.ts | 0 | 100 | 100 | 0 | 3-5
21
- manifest.ts | 0 | 100 | 100 | 0 | 3-14
22
- Trading/src/ucds | 0 | 0 | 0 | 0 |
23
- BuyAssetServerMain.ts | 0 | 0 | 0 | 0 | 1-28
24
- BuyAssetUCD.ts | 0 | 0 | 0 | 0 | 1-92
25
- ------------------------|---------|----------|---------|---------|-------------------
26
- ```
27
-
28
- As expected, the coverage report is pretty lame. Which is understandable, since we haven't written any tests yet.
29
-
30
- ```sh
31
- mkdir src/apps/Trading/test
32
- touch src/apps/Trading/test/Configurator.ts
33
- ```
34
-
35
- ## Configurator.ts
36
-
37
- ```typescript
38
- import { type AppTesterCtx, type CryptoManager, bindCommon } from 'libmodulor';
39
- import {
40
- NodeDeterministicCryptoManager,
41
- bindNodeCore,
42
- bindServer,
43
- } from 'libmodulor/node';
44
- import { SimpleAppTesterConfigurator } from 'libmodulor/node-test';
45
- import { injectable } from 'inversify';
46
-
47
- @injectable()
48
- export class Configurator extends SimpleAppTesterConfigurator {
49
- public override async bindImplementations(
50
- ctx: AppTesterCtx,
51
- ): Promise<void> {
52
- await super.bindImplementations(ctx);
53
-
54
- const { container } = ctx;
55
-
56
- bindCommon(container);
57
- bindNodeCore(container);
58
- bindServer(container);
59
-
60
- container
61
- .rebind<CryptoManager>('CryptoManager')
62
- .to(NodeDeterministicCryptoManager);
63
- }
64
- }
65
- ```
66
-
67
- ## Automated test
68
-
69
- Generate the automated tests and execute them with the CLI (it does more than a simple `yarn test`).
70
-
71
- ```sh
72
- yarn helper GenerateAppsTests
73
- yarn helper TestApp --appName Trading
74
- ```
75
-
76
- ```sh
77
- % Coverage report from v8
78
- ------------------------|---------|----------|---------|---------|-------------------
79
- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
80
- ------------------------|---------|----------|---------|---------|-------------------
81
- All files | 98.83 | 80 | 80 | 98.83 |
82
- Trading | 0 | 0 | 0 | 0 |
83
- index.ts | 0 | 0 | 0 | 0 | 1
84
- Trading/src | 100 | 100 | 100 | 100 |
85
- i18n.ts | 100 | 100 | 100 | 100 |
86
- manifest.ts | 100 | 100 | 100 | 100 |
87
- Trading/src/ucds | 100 | 100 | 100 | 100 |
88
- BuyAssetServerMain.ts | 100 | 100 | 100 | 100 |
89
- BuyAssetUCD.ts | 100 | 100 | 100 | 100 |
90
- ------------------------|---------|----------|---------|---------|-------------------
91
- 2024-12-29T11:00:53.178Z [info] Coverage Report => open src/apps/Trading/test/reports/coverage/index.html
92
- 2024-12-29T11:00:53.178Z [info] Simple HTML Report => open src/apps/Trading/test/reports/simple-html/index.html
93
- ```
94
-
95
- That's much better. Without writing any line of test code, we've reached almost 100% coverage. Although coverage is a vanity metric in some way, it still is a valuable one.
96
-
97
- Note another important thing : auto documentation. Check out the generated `src/apps/Trading/README.md` that shows a mermaid chart for each use case and a technical summary. This is very valuable to whoever wants to understand what the app does.
98
-
99
- To vizualize the mermaid chart, you can copy/paste it [here](https://mermaid.live) or if you've published your repository to GitHub, they are displayed out of the box.
100
-
101
- <img src="/docs/assets/trading-buy-asset-sequence-diagram.png" width="600px">
102
-
103
- You can see how the special comments we've mentioned earlier show up in this chart. It's nice in order to describe with more details what happens at each step.
104
-
105
- Note also the generated "Coverage Report" and the "Simple HTML Report". The former is provided by `c8` while the other is built by `libmodulor`. It gives a great overview of the test scenarios.
106
-
107
- > [!NOTE]
108
- > You might have seen that `Configurator` is extensible. It allows you to define specific flows to test a suite of use cases, define specific assertions, etc.
109
-
110
- ```sh
111
- yarn lint && git add . && git commit -m "test: init app tests"
112
- ```
113
-
114
- Now that's done, let's [Create the Product](./005_Create_the_Product.md).
@@ -1,46 +0,0 @@
1
- # Create the Product
2
-
3
- Like the app, the product has a `i18n.ts` and `manifest.ts`.
4
-
5
- ```sh
6
- mkdir -p src/products/SuperTrader
7
- touch src/products/SuperTrader/{i18n.ts,manifest.ts}
8
- ```
9
-
10
- ## i18n.ts
11
-
12
- ```typescript
13
- import type { ProductI18n } from 'libmodulor';
14
- import { I18nEN } from 'libmodulor/locales/en';
15
-
16
- import { I18n as TradingI18n } from '../../apps/Trading/index.js';
17
-
18
- export const I18n: ProductI18n = {
19
- en: {
20
- ...I18nEN,
21
- ...TradingI18n.en,
22
- p_desc: 'A simple app to trade crypto, shares and other assets',
23
- p_slogan: 'Trading made simple',
24
- },
25
- };
26
- ```
27
-
28
- ## manifest.ts
29
-
30
- ```typescript
31
- import type { ProductManifest } from 'libmodulor';
32
-
33
- export const Manifest: ProductManifest = {
34
- appReg: [{ name: 'Trading' }],
35
- name: 'SuperTrader',
36
- };
37
- ```
38
-
39
- > [!NOTE]
40
- > The same way we register use cases in an app, we register apps in a product. Since apps are reusable across products, you can even exclude some use cases for a given product.
41
-
42
- ```sh
43
- yarn lint && git add . && git commit -m "feat: add the product"
44
- ```
45
-
46
- Now that's done, let's [Create the server Target](./006_Create_the_server_Target.md).