libmodulor 0.4.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 (204) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/README.md +3 -3
  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/product/manifest.d.ts +15 -0
  43. package/dist/esm/products/Helper/index.js +3 -0
  44. package/dist/esm/products/Helper/manifest.d.ts +6 -1
  45. package/dist/esm/std/BufferManager.d.ts +18 -0
  46. package/dist/esm/std/ClockManager.d.ts +5 -0
  47. package/dist/esm/std/EnvironmentManager.d.ts +10 -0
  48. package/dist/esm/std/HTTPAPICaller.d.ts +6 -0
  49. package/dist/esm/std/I18nManager.d.ts +26 -0
  50. package/dist/esm/std/JWTManager.d.ts +26 -0
  51. package/dist/esm/std/JobManager.d.ts +6 -0
  52. package/dist/esm/std/LLMManager.d.ts +25 -0
  53. package/dist/esm/std/LLMManager.js +1 -0
  54. package/dist/esm/std/PromptManager.d.ts +8 -0
  55. package/dist/esm/std/SettingsManager.d.ts +19 -0
  56. package/dist/esm/std/SettingsManager.js +9 -0
  57. package/dist/esm/std/impl/ConsoleLogger.js +7 -1
  58. package/dist/esm/std/impl/FakeEmailManager.js +1 -0
  59. package/dist/esm/std/impl/FakeJobManager.js +1 -0
  60. package/dist/esm/std/impl/FetchHTTPAPICallExecutor.d.ts +9 -0
  61. package/dist/esm/std/impl/FetchHTTPAPICallExecutor.js +11 -0
  62. package/dist/esm/std/impl/MistralAILLMManager.d.ts +17 -0
  63. package/dist/esm/std/impl/MistralAILLMManager.js +56 -0
  64. package/dist/esm/std/impl/NodeCryptoManager.js +6 -1
  65. package/dist/esm/std/impl/NodeDeterministicCryptoManager.d.ts +14 -0
  66. package/dist/esm/std/impl/NodeDeterministicCryptoManager.js +17 -3
  67. package/dist/esm/std/impl/NodeFSManager.js +10 -0
  68. package/dist/esm/std/impl/NodeHTTPAPICallExecutorAgentBuilder.js +2 -0
  69. package/dist/esm/std/impl/NodePromptManager.js +3 -0
  70. package/dist/esm/std/impl/OllamaLLMManager.d.ts +20 -0
  71. package/dist/esm/std/impl/OllamaLLMManager.js +56 -0
  72. package/dist/esm/std/impl/OpenAILLMManager.d.ts +17 -0
  73. package/dist/esm/std/impl/OpenAILLMManager.js +51 -0
  74. package/dist/esm/std/impl/SimpleHTTPAPICaller.js +14 -0
  75. package/dist/esm/std/impl/SimpleMapI18nManager.js +4 -2
  76. package/dist/esm/std/impl/StdDateClockManager.js +3 -0
  77. package/dist/esm/std/impl/UCDataStoreExternalResourceManager.js +3 -0
  78. package/dist/esm/std/impl/WebCryptoManager.js +9 -0
  79. package/dist/esm/std/index.d.ts +1 -0
  80. package/dist/esm/std/index.js +1 -0
  81. package/dist/esm/target/lib/cli/renderer.js +3 -0
  82. package/dist/esm/target/lib/client/consts.d.ts +3 -0
  83. package/dist/esm/target/lib/client/consts.js +3 -0
  84. package/dist/esm/target/lib/mcp-server/MCPServerBooter.js +1 -0
  85. package/dist/esm/target/lib/react/UCContainer.js +1 -0
  86. package/dist/esm/target/lib/react/UCPanel.js +4 -0
  87. package/dist/esm/target/lib/react/useUC.d.ts +8 -0
  88. package/dist/esm/target/lib/react/useUC.js +22 -0
  89. package/dist/esm/target/lib/react/useUCOR.d.ts +15 -0
  90. package/dist/esm/target/lib/react/useUCOR.js +45 -0
  91. package/dist/esm/target/lib/rn/input.d.ts +7 -0
  92. package/dist/esm/target/lib/rn/input.js +2 -0
  93. package/dist/esm/target/lib/server/AuthenticationChecker.js +2 -1
  94. package/dist/esm/target/lib/server/BasicAuthenticationChecker.js +1 -0
  95. package/dist/esm/target/lib/server/CSPDirectivesBuilder.js +13 -0
  96. package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.js +3 -0
  97. package/dist/esm/target/lib/server/PrivateApiKeyAuthenticationChecker.js +1 -0
  98. package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
  99. package/dist/esm/target/lib/server/RequestChecker.js +5 -4
  100. package/dist/esm/target/lib/server/RequestHandler.d.ts +5 -0
  101. package/dist/esm/target/lib/server/RequestLogger.js +5 -0
  102. package/dist/esm/target/lib/server/ServerManager.d.ts +19 -0
  103. package/dist/esm/target/lib/server/consts.d.ts +3 -0
  104. package/dist/esm/target/lib/server/consts.js +3 -0
  105. package/dist/esm/target/lib/web/input.d.ts +21 -0
  106. package/dist/esm/target/lib/web/input.js +4 -0
  107. package/dist/esm/target/node-core-cli/NodeCoreCLIManager.js +2 -2
  108. package/dist/esm/target/node-express-server/NodeExpressServerManager.js +5 -0
  109. package/dist/esm/target/node-express-server/lib/AuthCookieCreator.js +1 -1
  110. package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.js +1 -0
  111. package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.js +1 -0
  112. package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.js +1 -0
  113. package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +8 -0
  114. package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.js +1 -0
  115. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.d.ts +10 -0
  116. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +14 -0
  117. package/dist/esm/target/react-native-pure/UCFormFieldControl.js +1 -0
  118. package/dist/esm/testing/AppTester.d.ts +4 -0
  119. package/dist/esm/testing/AppTester.js +16 -0
  120. package/dist/esm/testing/AppTesterConfigurator.d.ts +68 -0
  121. package/dist/esm/testing/UCDataStoreTester.d.ts +9 -0
  122. package/dist/esm/testing/UCDataStoreTester.js +13 -0
  123. package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +22 -2
  124. package/dist/esm/testing/impl/SimpleAppTesterConfigurator.js +1 -0
  125. package/dist/esm/testing/impl/SimpleHTMLAppTestReportEmitter.js +9 -3
  126. package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +12 -4
  127. package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.js +6 -0
  128. package/dist/esm/testing/opts.d.ts +38 -0
  129. package/dist/esm/testing/opts.js +1 -1
  130. package/dist/esm/testing/uc-input.js +2 -0
  131. package/dist/esm/testing/workers/AppTesterCtxInitializer.js +7 -0
  132. package/dist/esm/testing/workers/UCExecutor.js +1 -0
  133. package/dist/esm/testing/workers/checkers/AppIndexChecker.js +1 -0
  134. package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +4 -0
  135. package/dist/esm/uc/UC.js +19 -1
  136. package/dist/esm/uc/UCInputField.d.ts +28 -0
  137. package/dist/esm/uc/UCInputField.js +42 -0
  138. package/dist/esm/uc/data.d.ts +3 -0
  139. package/dist/esm/uc/def.d.ts +7 -0
  140. package/dist/esm/uc/exec.d.ts +39 -0
  141. package/dist/esm/uc/exec.js +29 -0
  142. package/dist/esm/uc/ext.d.ts +30 -1
  143. package/dist/esm/uc/helpers/UCOutputBuilder.js +5 -0
  144. package/dist/esm/uc/helpers/UCOutputReader.js +3 -1
  145. package/dist/esm/uc/impl/HTTPUCTransporter.js +4 -0
  146. package/dist/esm/uc/impl/InMemoryUCDataStore.js +7 -0
  147. package/dist/esm/uc/impl/KnexUCDataStore.d.ts +4 -0
  148. package/dist/esm/uc/impl/KnexUCDataStore.js +14 -0
  149. package/dist/esm/uc/impl/SimpleUCManager.js +6 -0
  150. package/dist/esm/uc/input-field.d.ts +60 -0
  151. package/dist/esm/uc/input-field.js +33 -0
  152. package/dist/esm/uc/input.d.ts +24 -0
  153. package/dist/esm/uc/lifecycle/client/IdleClientMain.js +1 -0
  154. package/dist/esm/uc/lifecycle/server/IdleServerMain.js +2 -0
  155. package/dist/esm/uc/manager.d.ts +11 -0
  156. package/dist/esm/uc/metadata.d.ts +10 -0
  157. package/dist/esm/uc/opi-layout.d.ts +3 -0
  158. package/dist/esm/uc/opi.d.ts +8 -0
  159. package/dist/esm/uc/output-field.d.ts +9 -0
  160. package/dist/esm/uc/output-part.d.ts +22 -0
  161. package/dist/esm/uc/output.d.ts +3 -0
  162. package/dist/esm/uc/policies/RoleRegularUCPolicy.js +1 -0
  163. package/dist/esm/uc/policies/funcs.js +1 -0
  164. package/dist/esm/uc/policy.d.ts +22 -0
  165. package/dist/esm/uc/sec.d.ts +9 -0
  166. package/dist/esm/uc/server.d.ts +10 -0
  167. package/dist/esm/uc/settings.d.ts +25 -0
  168. package/dist/esm/uc/side-effect.d.ts +16 -0
  169. package/dist/esm/uc/side-effect.js +16 -0
  170. package/dist/esm/uc/utils/rInput.d.ts +12 -0
  171. package/dist/esm/uc/utils/rInput.js +2 -0
  172. package/dist/esm/uc/utils/rVal.d.ts +25 -0
  173. package/dist/esm/uc/utils/rVal.js +27 -0
  174. package/dist/esm/uc/utils/recIs.d.ts +9 -0
  175. package/dist/esm/uc/utils/recIs.js +12 -1
  176. package/dist/esm/uc/utils/stripUCDLifecycleServer.d.ts +13 -0
  177. package/dist/esm/uc/utils/stripUCDLifecycleServer.js +17 -0
  178. package/dist/esm/uc/utils/ucifcoIsForArray.d.ts +6 -0
  179. package/dist/esm/uc/utils/ucifcoIsForArray.js +6 -0
  180. package/dist/esm/uc/workers/SimpleAggregateFinder.d.ts +12 -0
  181. package/dist/esm/uc/workers/SimpleAggregateFinder.js +12 -0
  182. package/dist/esm/uc/workers/UCBuilder.d.ts +7 -0
  183. package/dist/esm/uc/workers/UCBuilder.js +7 -0
  184. package/dist/esm/uc/workers/UCExecChecker.js +2 -0
  185. package/dist/esm/uc/workers/UCInputFilesProcessor.js +10 -4
  186. package/dist/esm/uc/workers/UCOutputFilesProcessor.js +6 -2
  187. package/dist/esm/utils/async/sleep.d.ts +10 -0
  188. package/dist/esm/utils/async/sleep.js +10 -0
  189. package/dist/esm/utils/http/appendData.js +5 -1
  190. package/dist/esm/utils/ioc/ContainerPrinter.js +2 -0
  191. package/dist/esm/utils/ioc/bindCommon.js +4 -0
  192. package/dist/esm/utils/ioc/bindNodeCLI.js +2 -0
  193. package/dist/esm/utils/ioc/bindNodeCore.js +1 -0
  194. package/dist/esm/utils/ioc/bindProduct.js +2 -0
  195. package/dist/esm/utils/ioc/bindRN.js +1 -0
  196. package/dist/esm/utils/ioc/bindServer.js +1 -0
  197. package/dist/esm/utils/ioc/bindWeb.js +2 -0
  198. package/dist/esm/utils/ioc/container.js +6 -0
  199. package/dist/esm/utils/numbers/units.js +3 -0
  200. package/dist/esm/utils/types/funcs.d.ts +35 -0
  201. package/dist/esm/utils/types/funcs.js +35 -0
  202. package/dist/esm/utils/types/utility-types.d.ts +17 -0
  203. package/dist/esm/utils/types/utility-types.js +1 -0
  204. package/package.json +9 -9
@@ -0,0 +1,56 @@
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
+ import { IllegalArgumentError } from '../../error/index.js';
15
+ let OllamaLLMManager = class OllamaLLMManager {
16
+ httpAPICaller;
17
+ settingsManager;
18
+ constructor(httpAPICaller, settingsManager) {
19
+ this.httpAPICaller = httpAPICaller;
20
+ this.settingsManager = settingsManager;
21
+ }
22
+ s() {
23
+ return {
24
+ oll_base_url: this.settingsManager.get()('oll_base_url'),
25
+ };
26
+ }
27
+ async send(req) {
28
+ const firstMessage = req.messages[0];
29
+ if (!firstMessage) {
30
+ throw new IllegalArgumentError('Please provide at least one message');
31
+ }
32
+ return await this.httpAPICaller.exec({
33
+ errBuilder: async (error) => error.error,
34
+ method: 'POST',
35
+ outputBuilder: async (res) => ({
36
+ choices: [{ message: { content: res.response } }],
37
+ }),
38
+ req: {
39
+ envelope: 'json',
40
+ builder: async () => ({
41
+ model: req.model,
42
+ prompt: firstMessage.content,
43
+ stream: false,
44
+ }),
45
+ },
46
+ urlBuilder: async () => `${this.s().oll_base_url}/api/generate`,
47
+ });
48
+ }
49
+ };
50
+ OllamaLLMManager = __decorate([
51
+ injectable(),
52
+ __param(0, inject('HTTPAPICaller')),
53
+ __param(1, inject('SettingsManager')),
54
+ __metadata("design:paramtypes", [Object, Object])
55
+ ], OllamaLLMManager);
56
+ export { OllamaLLMManager };
@@ -0,0 +1,17 @@
1
+ import type { ApiKey } from '../../dt/index.js';
2
+ import type { HTTPAPICaller } from '../HTTPAPICaller.js';
3
+ import type { LLMManager, LLMManagerSendReq, LLMManagerSendRes } from '../LLMManager.js';
4
+ import type { Configurable, Settings, SettingsManager } from '../SettingsManager.js';
5
+ export interface OpenAILLMManagerSettings extends Settings {
6
+ oai_api_key: ApiKey;
7
+ }
8
+ type S = OpenAILLMManagerSettings;
9
+ export declare class OpenAILLMManager implements Configurable<S>, LLMManager {
10
+ private httpAPICaller;
11
+ private settingsManager;
12
+ private static BASE_URL;
13
+ constructor(httpAPICaller: HTTPAPICaller, settingsManager: SettingsManager<S>);
14
+ s(): OpenAILLMManagerSettings;
15
+ send(req: LLMManagerSendReq): Promise<LLMManagerSendRes>;
16
+ }
17
+ export {};
@@ -0,0 +1,51 @@
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
+ var OpenAILLMManager_1;
14
+ import { inject, injectable } from 'inversify';
15
+ let OpenAILLMManager = class OpenAILLMManager {
16
+ static { OpenAILLMManager_1 = this; }
17
+ httpAPICaller;
18
+ settingsManager;
19
+ static BASE_URL = 'https://api.openai.com/v1';
20
+ constructor(httpAPICaller, settingsManager) {
21
+ this.httpAPICaller = httpAPICaller;
22
+ this.settingsManager = settingsManager;
23
+ }
24
+ s() {
25
+ return {
26
+ oai_api_key: this.settingsManager.get()('oai_api_key'),
27
+ };
28
+ }
29
+ async send(req) {
30
+ return await this.httpAPICaller.exec({
31
+ authorizationHeader: {
32
+ value: this.s().oai_api_key,
33
+ prefix: 'Bearer',
34
+ },
35
+ errBuilder: async (error) => error.error.message,
36
+ method: 'POST',
37
+ req: {
38
+ envelope: 'json',
39
+ builder: async () => req,
40
+ },
41
+ urlBuilder: async () => `${OpenAILLMManager_1.BASE_URL}/chat/completions`,
42
+ });
43
+ }
44
+ };
45
+ OpenAILLMManager = OpenAILLMManager_1 = __decorate([
46
+ injectable(),
47
+ __param(0, inject('HTTPAPICaller')),
48
+ __param(1, inject('SettingsManager')),
49
+ __metadata("design:paramtypes", [Object, Object])
50
+ ], OpenAILLMManager);
51
+ export { OpenAILLMManager };
@@ -64,6 +64,7 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
64
64
  if (status === 202 || status === 204) {
65
65
  return {};
66
66
  }
67
+ // Using .startsWith instead of === because the value can look like this 'application/json; charset=utf-8'
67
68
  const responseContentType = headers.get('Content-Type');
68
69
  const isJSON = responseContentType?.startsWith('application/json');
69
70
  const isFormURLEncoded = responseContentType?.startsWith('application/x-www-form-urlencoded');
@@ -87,6 +88,10 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
87
88
  async computeHeaders({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType = 'application/json', req, }) {
88
89
  const headers = {};
89
90
  if (req?.envelope !== 'form-data') {
91
+ // The boundary needs to be set when sending data this way, so the server can understand how to read it (Source : https://stackoverflow.com/a/20321259/1259118)
92
+ // In RN, the content-type we set is automatically overriden by the internal fetch client (i.e. 'content-type': 'multipart/form-data; boundary=7ZsqoHiTstShSc4-Yi4U7ier3GPc_4QL5iN2eT9rnSNd0g1UoFPgt3I6.fsWlV8YpJhFkG')
93
+ // In CLI, if it is set, it's not overriden. So it creates problems. With 'form-data', we send 'content-type': 'multipart/form-data'` but the server expects something like 'content-type': 'multipart/form-data;boundary=--------------------------743913816161509008636675'
94
+ // So we don't set it at all and we're good to go.
90
95
  headers['Content-Type'] = contentType;
91
96
  }
92
97
  if (authorizationHeader) {
@@ -110,6 +115,8 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
110
115
  return headers;
111
116
  }
112
117
  async processResBad({ errBuilder, opts, }, isJSON, isXML, response) {
118
+ // NOTE : This method must handle all possible cases and never throw
119
+ // Indeed, it's supposed to handle the errors so it shouldn't throw one
113
120
  let error;
114
121
  try {
115
122
  if (isJSON) {
@@ -134,6 +141,7 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
134
141
  return null;
135
142
  }
136
143
  if (typeof error === 'string') {
144
+ // For example, it can be from `asText`, containing funny formatting (developers and errors you know...)
137
145
  return error.trim();
138
146
  }
139
147
  if (!error) {
@@ -144,10 +152,14 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
144
152
  if (typeof message === 'string') {
145
153
  return message;
146
154
  }
155
+ // Case where `errBuilder` is of type (error: string) => string
156
+ // If an object is passed to it, it would return an object instead, interpreted incorrectly as [object Object] by error handlers
147
157
  return JSON.stringify(message);
148
158
  }
149
159
  catch (err) {
150
160
  this.logger.error(err);
161
+ // Case where `errBuilder` is of type (error: Object) => string
162
+ // If an object of another shape is passed to it, it would trigger some TypeError or cannot call .message of undefined
151
163
  return JSON.stringify(error);
152
164
  }
153
165
  }
@@ -163,7 +175,9 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
163
175
  });
164
176
  if (isFormURLEncoded) {
165
177
  payload = {};
178
+ // TODO : Find a better way to do this (without adding any external dependency because the code must be portable)
166
179
  new URL(`http://localhost?${asText}`).searchParams.forEach((v, k) => {
180
+ // @ts-ignore
167
181
  payload[k] = v;
168
182
  });
169
183
  }
@@ -17,7 +17,7 @@ let SimpleMapI18nManager = class SimpleMapI18nManager {
17
17
  static { SimpleMapI18nManager_1 = this; }
18
18
  i18n;
19
19
  logger;
20
- static PLACEHOLDERS_REGEX = /{{([A-Z-a-z0-9]+)}}/g;
20
+ static PLACEHOLDERS_REGEX = /{{([A-Z-a-z0-9]+)}}/g; // Note the 'g' so it can be used with `matchAll`
21
21
  entries;
22
22
  constructor(i18n, logger) {
23
23
  this.i18n = i18n;
@@ -48,12 +48,14 @@ let SimpleMapI18nManager = class SimpleMapI18nManager {
48
48
  if (opts?.fallback) {
49
49
  return opts.fallback;
50
50
  }
51
- return key;
51
+ return key; // Mimic the behavior of some common libraries like i18next
52
52
  }
53
53
  tOrNull(key, _opts) {
54
54
  return this.entries.get(key) || null;
55
55
  }
56
56
  replacePlaceholders(v, opts) {
57
+ // DO NOT USE THIS IN PRODUCTION
58
+ // The purpose of it is to have a simple and dependency-less implementation, to play with
57
59
  let res = v;
58
60
  const placeholders = res.matchAll(SimpleMapI18nManager_1.PLACEHOLDERS_REGEX);
59
61
  for (const [placeholder, key] of placeholders) {
@@ -10,6 +10,9 @@ let StdDateClockManager = class StdDateClockManager {
10
10
  return new Date();
11
11
  }
12
12
  nowToKey() {
13
+ // The rationale behind this being hardcoded is to avoid adding a library (luxon, date-fns) just for that.
14
+ // For instance, luxon adds a huge amount of code to a basic web target when bundled, for nothing.
15
+ // See https://github.com/moment/luxon/issues/854#issuecomment-1729384672
13
16
  return this.now()
14
17
  .toISOString()
15
18
  .replaceAll(/-|T|:/g, '')
@@ -11,6 +11,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  import { inject, injectable } from 'inversify';
14
+ // TODO : Wait for the DB to be ready or add a retry mechanism
15
+ // Because when we start from a fresh install, this is executed before the docker container is ready
16
+ // A temporary workaround is to stop and restart everything. At the 2nd startup, the db is ready, and it works
14
17
  let UCDataStoreExternalResourceManager = class UCDataStoreExternalResourceManager {
15
18
  ucDataStore;
16
19
  constructor(ucDataStore) {
@@ -10,6 +10,7 @@ const DIGEST_MAPPING = new Map([
10
10
  ]);
11
11
  let WebCryptoManager = class WebCryptoManager {
12
12
  async clear() {
13
+ // Nothing to do
13
14
  }
14
15
  hash(_algorithm, _base) {
15
16
  throw new Error('Method not implemented.');
@@ -25,9 +26,13 @@ let WebCryptoManager = class WebCryptoManager {
25
26
  if (!hash) {
26
27
  throw new Error(`Digest ${digest} is not valid for WebCryptoManager`);
27
28
  }
29
+ // "Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers."
30
+ // Warning: This API provides a number of low-level cryptographic primitives. It's very easy to misuse them, and the pitfalls involved can be very subtle.
31
+ // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
28
32
  const textEncoder = new TextEncoder();
29
33
  const passwordKey = await crypto.subtle.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits']);
30
34
  const result = await crypto.subtle.deriveBits({
35
+ // https://developer.mozilla.org/en-US/docs/Web/API/Pbkdf2Params
31
36
  hash,
32
37
  iterations: iterationsCount,
33
38
  name: 'PBKDF2',
@@ -36,9 +41,11 @@ let WebCryptoManager = class WebCryptoManager {
36
41
  return new Uint8Array(result);
37
42
  }
38
43
  async randomString(length) {
44
+ // Not perfect in terms of randomness (because of Math.random() but pretty fine for now)
39
45
  let res = '';
40
46
  while (res.length < length) {
41
47
  const next = Math.random().toString(36).slice(2, 3);
48
+ // For now, we want only chars at the beginning, so it can be used as an identifier (i.e. in a database)
42
49
  if (res.length === 0 &&
43
50
  Number.isInteger(Number.parseInt(next, 10))) {
44
51
  continue;
@@ -48,6 +55,8 @@ let WebCryptoManager = class WebCryptoManager {
48
55
  return res;
49
56
  }
50
57
  randomUUID() {
58
+ // "Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers."
59
+ // https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID
51
60
  return crypto.randomUUID();
52
61
  }
53
62
  async scrypt() {
@@ -13,6 +13,7 @@ export * from './HTTPAPICallExecutor.js';
13
13
  export * from './I18nManager.js';
14
14
  export * from './JobManager.js';
15
15
  export * from './JWTManager.js';
16
+ export * from './LLMManager.js';
16
17
  export * from './Logger.js';
17
18
  export * from './PromptManager.js';
18
19
  export * from './SettingsManager.js';
@@ -13,6 +13,7 @@ export * from './HTTPAPICallExecutor.js';
13
13
  export * from './I18nManager.js';
14
14
  export * from './JobManager.js';
15
15
  export * from './JWTManager.js';
16
+ export * from './LLMManager.js';
16
17
  export * from './Logger.js';
17
18
  export * from './PromptManager.js';
18
19
  export * from './SettingsManager.js';
@@ -1,5 +1,6 @@
1
1
  import { CustomError } from '../../../error/index.js';
2
2
  export function print(line) {
3
+ // biome-ignore lint/suspicious/noConsole: we want it
3
4
  console.info(line);
4
5
  }
5
6
  export function printError(err) {
@@ -7,11 +8,13 @@ export function printError(err) {
7
8
  if (err instanceof Error) {
8
9
  message = err.message;
9
10
  if (!(err instanceof CustomError)) {
11
+ // biome-ignore lint/suspicious/noConsole: we want it
10
12
  console.error(err);
11
13
  }
12
14
  }
13
15
  else if (typeof err === 'string') {
14
16
  message = err;
15
17
  }
18
+ // biome-ignore lint/suspicious/noConsole: we want it
16
19
  console.error(message);
17
20
  }
@@ -1,2 +1,5 @@
1
1
  import type { ServerClientManagerSettings } from './ServerClientManager.js';
2
+ /**
3
+ * @see TARGET_DEFAULT_SERVER_MANAGER_SETTINGS
4
+ */
2
5
  export declare const TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS: ServerClientManagerSettings;
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @see TARGET_DEFAULT_SERVER_MANAGER_SETTINGS
3
+ */
1
4
  export const TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS = {
2
5
  server_public_api_key: 'PublicApiKeyToBeChangedWhenDeploying',
3
6
  server_public_api_key_header_name: 'X-API-Key',
@@ -32,6 +32,7 @@ let MCPServerBooter = class MCPServerBooter {
32
32
  srcImporter,
33
33
  });
34
34
  for await (const uc of ucs) {
35
+ // Declared only for compatibility with ServerManager's contract but not used
35
36
  const contract = ucHTTPContract(uc);
36
37
  await this.ucManager.initServer(uc);
37
38
  await this.serverManager.mount(uc.appManifest, uc.def, contract);
@@ -15,6 +15,7 @@ export function UCContainer({ children, uc, }) {
15
15
  })();
16
16
  }, [uc, ucExecChecker]);
17
17
  if (isAllowed === undefined) {
18
+ // TODO : Add some loader while we check if can do
18
19
  return React.createElement(React.Fragment, null);
19
20
  }
20
21
  if (isAllowed === false) {
@@ -33,6 +33,9 @@ export function UCPanel({ autoExec = false, clearAfterExec = true, onDone, onErr
33
33
  };
34
34
  const onSubmit = async () => {
35
35
  setExecState('submitting');
36
+ // Is some targets, the confirmClient blocks the main thread (e.g. window.confirm()).
37
+ // This leads to the state set above not being updated.
38
+ // This is a "hacky" workaroud to let React re-render the control with 'submitting' state before
36
39
  await sleep(100);
37
40
  await onStartSubmitting?.();
38
41
  const confirmed = await ucManager.confirmClient(uc);
@@ -62,6 +65,7 @@ export function UCPanel({ autoExec = false, clearAfterExec = true, onDone, onErr
62
65
  };
63
66
  const disabled = ucIsDisabled(execState);
64
67
  const loading = ucIsLoading(execState);
68
+ // TODO : Keep these as a state to avoid recomputation
65
69
  const ctx = {
66
70
  clearAfterExec,
67
71
  disabled,
@@ -2,6 +2,14 @@ import { type ArgsRecord, UC, type UCDef, type UCInput, type UCOPIBase } from '.
2
2
  type CloneFunc<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = (i: Partial<I>) => UC<I, OPI0, OPI1>;
3
3
  type DivertFunc<II extends UCInput | undefined = undefined, OOPI0 extends UCOPIBase | undefined = undefined, OOPI1 extends UCOPIBase | undefined = undefined> = (siblingUCD: UCDef) => UC<II, OOPI0, OOPI1>;
4
4
  type RefillFunc<I extends UCInput | undefined = undefined> = (i: Partial<I>) => void;
5
+ /**
6
+ * This hook provides utilities to init a use case and perform actions on it in a React way
7
+ * @param appManifest
8
+ * @param def
9
+ * @param auth
10
+ * @param opts
11
+ * @returns
12
+ */
5
13
  export declare function useUC<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: ArgsRecord<I, OPI0, OPI1>['appManifest'], def: ArgsRecord<I, OPI0, OPI1>['def'], auth: ArgsRecord<I, OPI0, OPI1>['auth'], opts?: {
6
14
  fillWith: Partial<I>;
7
15
  }): [
@@ -1,5 +1,13 @@
1
1
  import { useState } from 'react';
2
2
  import { UC, } from '../../../uc/index.js';
3
+ /**
4
+ * This hook provides utilities to init a use case and perform actions on it in a React way
5
+ * @param appManifest
6
+ * @param def
7
+ * @param auth
8
+ * @param opts
9
+ * @returns
10
+ */
3
11
  export function useUC(appManifest, def, auth, opts) {
4
12
  const [uc, setUC] = useState(() => {
5
13
  const { name: appName, ucReg } = appManifest;
@@ -13,8 +21,22 @@ export function useUC(appManifest, def, auth, opts) {
13
21
  }
14
22
  return v;
15
23
  });
24
+ /**
25
+ * Get a new `UC` based on the initial one
26
+ * @param i
27
+ * @returns
28
+ */
16
29
  const clone = (i) => new UC(uc.appManifest, uc.def, uc.auth).fill(i);
30
+ /**
31
+ * Get a new `UC` based on the "common" settings of the initial one (i.e. `auth`)
32
+ * @param ucd
33
+ * @returns
34
+ */
17
35
  const divert = (siblingUCD) => new UC(uc.appManifest, siblingUCD, uc.auth);
36
+ /**
37
+ * Update the existing `uc` in an immutable way to trigger components re-rendering
38
+ * @param i
39
+ */
18
40
  const refill = (i) => {
19
41
  setUC(new UC(uc.appManifest, uc.def, uc.auth).fill(i));
20
42
  };
@@ -2,6 +2,21 @@ import type { UCInput, UCOPIBase, UCOutputReader, UCOutputReaderPart } from '../
2
2
  type AppendFunc<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = (ucor: UCOutputReader<any, OPI0, OPI1>) => void;
3
3
  type RemoveFunc<OPI extends UCOPIBase> = (item: OPI) => void;
4
4
  type UpdateFunc<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = (ucor: UCOutputReader<any, OPI0, OPI1>) => void;
5
+ /**
6
+ * This hook provides utilities to act on a {@link UCOutputReader} in a React way
7
+ *
8
+ * A usual scenario of this is a "CRUD-like" UI displaying multiple use cases :
9
+ *
10
+ * - A `List` use case to display a collection of items
11
+ * - A `Create` use case to add an item
12
+ * - A `Delete` use case to remove an item
13
+ * - An `Update` use case to update an item
14
+ *
15
+ * Whenever one of this use case is performed, you can use the `ucor` to act on the main UCOR in an immutable way.
16
+ *
17
+ * @param ucor
18
+ * @returns
19
+ */
5
20
  export declare function useUCOR<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(ucor: UCOutputReader<I, OPI0, OPI1>): [
6
21
  UCOutputReaderPart<NonNullable<OPI0>> | undefined,
7
22
  UCOutputReaderPart<NonNullable<OPI1>> | undefined,
@@ -39,10 +39,35 @@ function update(a, b) {
39
39
  items: newItems,
40
40
  };
41
41
  }
42
+ /**
43
+ * This hook provides utilities to act on a {@link UCOutputReader} in a React way
44
+ *
45
+ * A usual scenario of this is a "CRUD-like" UI displaying multiple use cases :
46
+ *
47
+ * - A `List` use case to display a collection of items
48
+ * - A `Create` use case to add an item
49
+ * - A `Delete` use case to remove an item
50
+ * - An `Update` use case to update an item
51
+ *
52
+ * Whenever one of this use case is performed, you can use the `ucor` to act on the main UCOR in an immutable way.
53
+ *
54
+ * @param ucor
55
+ * @returns
56
+ */
42
57
  export function useUCOR(ucor) {
43
58
  const [part0, setPart0] = useState(ucor.part0());
44
59
  const [part1, setPart1] = useState(ucor.part1());
60
+ /**
61
+ * Append items to part0
62
+ * @param ucor2
63
+ * @returns
64
+ */
45
65
  const append0 = (ucor2) => setPart0((prev) => append(prev, ucor2.part0()));
66
+ /**
67
+ * Append items to part1 (if applicable)
68
+ * @param ucor2
69
+ * @returns
70
+ */
46
71
  const append1 = (ucor2) => setPart1((prev) => {
47
72
  const b = ucor2.part1();
48
73
  if (!prev || !b) {
@@ -50,14 +75,34 @@ export function useUCOR(ucor) {
50
75
  }
51
76
  return append(prev, b);
52
77
  });
78
+ /**
79
+ * Remove the item from part0
80
+ * @param item
81
+ * @returns
82
+ */
53
83
  const remove0 = (item) => setPart0((prev) => remove(prev, item));
84
+ /**
85
+ * Remove the item from part1 (if applicable)
86
+ * @param item
87
+ * @returns
88
+ */
54
89
  const remove1 = (item) => setPart1((prev) => {
55
90
  if (!prev) {
56
91
  return;
57
92
  }
58
93
  return remove(prev, item);
59
94
  });
95
+ /**
96
+ * Update items in part0
97
+ * @param ucor2
98
+ * @returns
99
+ */
60
100
  const update0 = (ucor2) => setPart0((prev) => update(prev, ucor2.part0()));
101
+ /**
102
+ * Update items in part1 (if applicable)
103
+ * @param ucor2
104
+ * @returns
105
+ */
61
106
  const update1 = (ucor2) => setPart1((prev) => {
62
107
  const b = ucor2.part1();
63
108
  if (!prev || !b) {
@@ -3,6 +3,13 @@ import { type DataType, type ErrorMessage } from '../../../dt/index.js';
3
3
  import { type UCExecState, type UCInputField } from '../../../uc/index.js';
4
4
  export interface RNInputDef {
5
5
  internal?: undefined;
6
+ /**
7
+ * Fields that are part of {@link TextInputProps}
8
+ *
9
+ * These are safe to destructure directly in a `<TextInput />` component.
10
+ *
11
+ * @example `<TextInput {...attrs.spec} />`
12
+ */
6
13
  spec?: TextInputProps;
7
14
  }
8
15
  export declare function rnInputDef<T extends DataType>(field: UCInputField<T>, execState: UCExecState, _errMsg: ErrorMessage | null): RNInputDef;
@@ -6,12 +6,14 @@ export function rnInputDef(field, execState, _errMsg) {
6
6
  spec: {},
7
7
  };
8
8
  if (!def.spec) {
9
+ // Just a guard to safely type the rest of the function without using !
9
10
  return def;
10
11
  }
11
12
  const { key, def: fDef } = field;
12
13
  const { type: fType } = fDef;
13
14
  def.spec.editable = !ucIsDisabled(execState);
14
15
  def.spec.id = ucifId(key);
16
+ // Testing the types by usage probability to make the if/else evaluation stop ideally earlier
15
17
  if (fType instanceof TString) {
16
18
  const constraints = fType.getConstraints();
17
19
  if (constraints) {
@@ -35,7 +35,7 @@ let AuthenticationChecker = class AuthenticationChecker {
35
35
  authorizationHeader,
36
36
  });
37
37
  const output = {
38
- allowed: false,
38
+ allowed: false, // By default it's not allowed
39
39
  auth: null,
40
40
  };
41
41
  const { lifecycle: { server }, sec, } = uc.def;
@@ -52,6 +52,7 @@ let AuthenticationChecker = class AuthenticationChecker {
52
52
  output.allowed = allowed;
53
53
  }
54
54
  else {
55
+ // Follows the OpenAPI spec : https://swagger.io/docs/specification/authentication
55
56
  switch (authType) {
56
57
  case 'apiKey':
57
58
  if (authorizationHeader &&
@@ -46,6 +46,7 @@ let BasicAuthenticationChecker = class BasicAuthenticationChecker {
46
46
  if (!passwordsMatch) {
47
47
  return null;
48
48
  }
49
+ // TODO : Improve this by fetching data from a data store for example
49
50
  return {
50
51
  organization: {
51
52
  id: '',
@@ -36,10 +36,23 @@ let CSPDirectivesBuilder = class CSPDirectivesBuilder {
36
36
  this.logger.info('Default CSP directives', defaultDirectives);
37
37
  const directives = { ...defaultDirectives };
38
38
  if (!this.environmentManager.isProd()) {
39
+ // In dev mode, we allow ourselves to remove this directive.
40
+ // It is necessary when testing from an external device and accessing the server via 192.168.x.x for example
41
+ // Otherwise the requests are upgraded and it doesn't work since there is no HTTPS in localhost
42
+ // Source : https://stackoverflow.com/questions/66599655/how-to-enable-and-disable-upgradeinsecurerequests-csp-directive-using-helmet-4-4
39
43
  this.logger.warn('Disabling upgrade-insecure-requests');
40
44
  directives['upgrade-insecure-requests'] = null;
45
+ // In dev mode, NextJS uses eval
46
+ // Enabling it prevents the following error from occurring in the console
47
+ // Uncaught EvalError: call to eval() blocked by CSP NextJS
48
+ // Source : https://github.com/vercel/next.js/discussions/17396
41
49
  this.logger.warn('Enabling unsafe-eval');
42
50
  directives[CSPDirectivesBuilder_1.SCRIPT_SRC]?.push("'unsafe-eval'");
51
+ // In dev mode, React Dev Tools use inline injection
52
+ // Enabling it prevents the following error from occurring in the console
53
+ // Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).
54
+ // Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
55
+ // Uncaught TypeError: hook.sub is not a function
43
56
  this.logger.warn('Enabling unsafe-inline');
44
57
  directives[CSPDirectivesBuilder_1.SCRIPT_SRC]?.push("'unsafe-inline'");
45
58
  }
@@ -21,11 +21,14 @@ let CustomerFacingErrorBuilder = class CustomerFacingErrorBuilder {
21
21
  }
22
22
  exec({ error }) {
23
23
  if (error instanceof CustomError) {
24
+ // It's already ready to be sent as is
24
25
  return {
25
26
  error,
26
27
  };
27
28
  }
28
29
  this.logger.error(error);
30
+ // Create a specific generic error to avoid leaking potentially sensitive error
31
+ // We all know the infamous "Cannot connect to MySQL database"...
29
32
  return {
30
33
  error: new InternalServerError(this.environmentManager.isProd()
31
34
  ? undefined
@@ -31,6 +31,7 @@ let PrivateApiKeyAuthenticationChecker = class PrivateApiKeyAuthenticationChecke
31
31
  if (!exists) {
32
32
  return null;
33
33
  }
34
+ // TODO : Improve this by fetching data from a data store for example
34
35
  return {
35
36
  organization: {
36
37
  id: '',
@@ -27,7 +27,7 @@ let PublicApiKeyChecker = class PublicApiKeyChecker {
27
27
  }
28
28
  async exec({ checkType = DEFAULT_UC_SEC_PAKCT, value, }) {
29
29
  this.logger.trace('Checking apiKey', { checkType, value });
30
- let allowed = false;
30
+ let allowed = false; // By default it's not allowed
31
31
  switch (checkType) {
32
32
  case 'off':
33
33
  allowed = true;