libmodulor 0.1.0 → 0.3.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/.github/ISSUE_TEMPLATE/generic-issue.md +16 -0
- package/CHANGELOG.md +30 -2
- package/LICENSE +165 -0
- package/MAINTAINERS.md +1 -0
- package/README.md +71 -1339
- package/dist/esm/app/i18n.d.ts +2 -0
- package/dist/esm/app/i18n.js +1 -0
- package/dist/esm/app/index.d.ts +8 -0
- package/dist/esm/app/index.js +5 -0
- package/dist/esm/app/installer.d.ts +4 -0
- package/dist/esm/app/installer.js +1 -0
- package/dist/esm/app/manifest.d.ts +14 -0
- package/dist/esm/app/manifest.js +1 -0
- package/dist/esm/app/workers/AppManifestLoader.d.ts +15 -0
- package/dist/esm/app/workers/AppManifestLoader.js +56 -0
- package/dist/esm/app/workers/AppSrcBrowser.d.ts +19 -0
- package/dist/esm/app/workers/AppSrcBrowser.js +59 -0
- package/dist/esm/app/workers/AppSrcFilePathBuilder.d.ts +19 -0
- package/dist/esm/app/workers/AppSrcFilePathBuilder.js +48 -0
- package/dist/esm/app/workers/AppUCsLoader.d.ts +22 -0
- package/dist/esm/app/workers/AppUCsLoader.js +65 -0
- package/dist/esm/app/workers/UCDefLoader.d.ts +15 -0
- package/dist/esm/app/workers/UCDefLoader.js +57 -0
- package/dist/esm/apps/Helper/index.d.ts +2 -0
- package/dist/esm/apps/Helper/index.js +2 -0
- package/dist/esm/apps/Helper/src/i18n.d.ts +2 -0
- package/dist/esm/apps/Helper/src/i18n.js +18 -0
- package/dist/esm/apps/Helper/src/lib/app.d.ts +6 -0
- package/dist/esm/apps/Helper/src/lib/app.js +12 -0
- package/dist/esm/apps/Helper/src/manifest.d.ts +22 -0
- package/dist/esm/apps/Helper/src/manifest.js +22 -0
- package/dist/esm/apps/Helper/src/ucds/DeleteGeneratedAppsTestsUCD.d.ts +5 -0
- package/dist/esm/apps/Helper/src/ucds/DeleteGeneratedAppsTestsUCD.js +70 -0
- package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.d.ts +12 -0
- package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.js +106 -0
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.d.ts +9 -0
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.js +103 -0
- package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.d.ts +2 -0
- package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.js +15 -0
- package/dist/esm/convention.d.ts +42 -0
- package/dist/esm/convention.js +40 -0
- package/dist/esm/dt/DataType.d.ts +68 -0
- package/dist/esm/dt/DataType.js +1 -0
- package/dist/esm/dt/DataTypes.d.ts +2 -0
- package/dist/esm/dt/DataTypes.js +68 -0
- package/dist/esm/dt/Validation.d.ts +25 -0
- package/dist/esm/dt/Validation.js +42 -0
- package/dist/esm/dt/base/TBase.d.ts +66 -0
- package/dist/esm/dt/base/TBase.js +120 -0
- package/dist/esm/dt/base/TBoolean.d.ts +10 -0
- package/dist/esm/dt/base/TBoolean.js +38 -0
- package/dist/esm/dt/base/TInt.d.ts +20 -0
- package/dist/esm/dt/base/TInt.js +53 -0
- package/dist/esm/dt/base/TNumber.d.ts +31 -0
- package/dist/esm/dt/base/TNumber.js +83 -0
- package/dist/esm/dt/base/TObject.d.ts +18 -0
- package/dist/esm/dt/base/TObject.js +66 -0
- package/dist/esm/dt/base/TString.d.ts +22 -0
- package/dist/esm/dt/base/TString.js +62 -0
- package/dist/esm/dt/base/TUInt.d.ts +12 -0
- package/dist/esm/dt/base/TUInt.js +18 -0
- package/dist/esm/dt/final/TAddress.d.ts +7 -0
- package/dist/esm/dt/final/TAddress.js +9 -0
- package/dist/esm/dt/final/TAmount.d.ts +13 -0
- package/dist/esm/dt/final/TAmount.js +27 -0
- package/dist/esm/dt/final/TApiKey.d.ts +10 -0
- package/dist/esm/dt/final/TApiKey.js +15 -0
- package/dist/esm/dt/final/TBarCode.d.ts +7 -0
- package/dist/esm/dt/final/TBarCode.js +9 -0
- package/dist/esm/dt/final/TCSS.d.ts +8 -0
- package/dist/esm/dt/final/TCSS.js +12 -0
- package/dist/esm/dt/final/TColor.d.ts +9 -0
- package/dist/esm/dt/final/TColor.js +12 -0
- package/dist/esm/dt/final/TColorRGBA.d.ts +11 -0
- package/dist/esm/dt/final/TColorRGBA.js +19 -0
- package/dist/esm/dt/final/TCompanyName.d.ts +7 -0
- package/dist/esm/dt/final/TCompanyName.js +9 -0
- package/dist/esm/dt/final/TCountryISO3166Alpha2.d.ts +10 -0
- package/dist/esm/dt/final/TCountryISO3166Alpha2.js +270 -0
- package/dist/esm/dt/final/TCurrencyISO4217.d.ts +15 -0
- package/dist/esm/dt/final/TCurrencyISO4217.js +24 -0
- package/dist/esm/dt/final/TDateISO8601.d.ts +12 -0
- package/dist/esm/dt/final/TDateISO8601.js +29 -0
- package/dist/esm/dt/final/TDateTimeFormat.d.ts +7 -0
- package/dist/esm/dt/final/TDateTimeFormat.js +9 -0
- package/dist/esm/dt/final/TDirPath.d.ts +9 -0
- package/dist/esm/dt/final/TDirPath.js +16 -0
- package/dist/esm/dt/final/TDomainName.d.ts +13 -0
- package/dist/esm/dt/final/TDomainName.js +22 -0
- package/dist/esm/dt/final/TEmail.d.ts +13 -0
- package/dist/esm/dt/final/TEmail.js +22 -0
- package/dist/esm/dt/final/TEmbeddedObject.d.ts +6 -0
- package/dist/esm/dt/final/TEmbeddedObject.js +10 -0
- package/dist/esm/dt/final/TEmoji.d.ts +7 -0
- package/dist/esm/dt/final/TEmoji.js +9 -0
- package/dist/esm/dt/final/TEncryptionKey.d.ts +10 -0
- package/dist/esm/dt/final/TEncryptionKey.js +15 -0
- package/dist/esm/dt/final/TErrorMessage.d.ts +7 -0
- package/dist/esm/dt/final/TErrorMessage.js +9 -0
- package/dist/esm/dt/final/TExternalServiceId.d.ts +7 -0
- package/dist/esm/dt/final/TExternalServiceId.js +9 -0
- package/dist/esm/dt/final/TFile.d.ts +23 -0
- package/dist/esm/dt/final/TFile.js +41 -0
- package/dist/esm/dt/final/TFileExtension.d.ts +15 -0
- package/dist/esm/dt/final/TFileExtension.js +15 -0
- package/dist/esm/dt/final/TFileMimeType.d.ts +11 -0
- package/dist/esm/dt/final/TFileMimeType.js +15 -0
- package/dist/esm/dt/final/TFileName.d.ts +7 -0
- package/dist/esm/dt/final/TFileName.js +9 -0
- package/dist/esm/dt/final/TFilePath.d.ts +9 -0
- package/dist/esm/dt/final/TFilePath.js +16 -0
- package/dist/esm/dt/final/TFreeTextLong.d.ts +8 -0
- package/dist/esm/dt/final/TFreeTextLong.js +12 -0
- package/dist/esm/dt/final/TFreeTextShort.d.ts +7 -0
- package/dist/esm/dt/final/TFreeTextShort.js +9 -0
- package/dist/esm/dt/final/TGeolocation.d.ts +12 -0
- package/dist/esm/dt/final/TGeolocation.js +20 -0
- package/dist/esm/dt/final/TGitSSHURL.d.ts +11 -0
- package/dist/esm/dt/final/TGitSSHURL.js +17 -0
- package/dist/esm/dt/final/THTML.d.ts +8 -0
- package/dist/esm/dt/final/THTML.js +12 -0
- package/dist/esm/dt/final/THTTPContentType.d.ts +9 -0
- package/dist/esm/dt/final/THTTPContentType.js +20 -0
- package/dist/esm/dt/final/THTTPMethod.d.ts +9 -0
- package/dist/esm/dt/final/THTTPMethod.js +24 -0
- package/dist/esm/dt/final/THTTPStatusNumber.d.ts +10 -0
- package/dist/esm/dt/final/THTTPStatusNumber.js +27 -0
- package/dist/esm/dt/final/THostAddress.d.ts +7 -0
- package/dist/esm/dt/final/THostAddress.js +9 -0
- package/dist/esm/dt/final/THostPort.d.ts +8 -0
- package/dist/esm/dt/final/THostPort.js +15 -0
- package/dist/esm/dt/final/TIPv4.d.ts +9 -0
- package/dist/esm/dt/final/TIPv4.js +16 -0
- package/dist/esm/dt/final/TIPv6.d.ts +9 -0
- package/dist/esm/dt/final/TIPv6.js +16 -0
- package/dist/esm/dt/final/TJSONString.d.ts +10 -0
- package/dist/esm/dt/final/TJSONString.js +25 -0
- package/dist/esm/dt/final/TJWT.d.ts +12 -0
- package/dist/esm/dt/final/TJWT.js +41 -0
- package/dist/esm/dt/final/TJavaScript.d.ts +8 -0
- package/dist/esm/dt/final/TJavaScript.js +12 -0
- package/dist/esm/dt/final/TJobTitle.d.ts +7 -0
- package/dist/esm/dt/final/TJobTitle.js +9 -0
- package/dist/esm/dt/final/TMarkdown.d.ts +8 -0
- package/dist/esm/dt/final/TMarkdown.js +12 -0
- package/dist/esm/dt/final/TNumIndex.d.ts +7 -0
- package/dist/esm/dt/final/TNumIndex.js +9 -0
- package/dist/esm/dt/final/TPassword.d.ts +10 -0
- package/dist/esm/dt/final/TPassword.js +15 -0
- package/dist/esm/dt/final/TPercentage.d.ts +10 -0
- package/dist/esm/dt/final/TPercentage.js +21 -0
- package/dist/esm/dt/final/TPersonFirstname.d.ts +9 -0
- package/dist/esm/dt/final/TPersonFirstname.js +19 -0
- package/dist/esm/dt/final/TPersonFullname.d.ts +11 -0
- package/dist/esm/dt/final/TPersonFullname.js +19 -0
- package/dist/esm/dt/final/TPersonInitials.d.ts +9 -0
- package/dist/esm/dt/final/TPersonInitials.js +19 -0
- package/dist/esm/dt/final/TPersonLastname.d.ts +9 -0
- package/dist/esm/dt/final/TPersonLastname.js +19 -0
- package/dist/esm/dt/final/TQRCode.d.ts +9 -0
- package/dist/esm/dt/final/TQRCode.js +19 -0
- package/dist/esm/dt/final/TSQLQuery.d.ts +8 -0
- package/dist/esm/dt/final/TSQLQuery.js +12 -0
- package/dist/esm/dt/final/TSSHPrivateKey.d.ts +16 -0
- package/dist/esm/dt/final/TSSHPrivateKey.js +26 -0
- package/dist/esm/dt/final/TSSHPublicKey.d.ts +13 -0
- package/dist/esm/dt/final/TSSHPublicKey.js +27 -0
- package/dist/esm/dt/final/TSearchQuery.d.ts +19 -0
- package/dist/esm/dt/final/TSearchQuery.js +23 -0
- package/dist/esm/dt/final/TSemVerVersion.d.ts +9 -0
- package/dist/esm/dt/final/TSemVerVersion.js +19 -0
- package/dist/esm/dt/final/TShellCommand.d.ts +8 -0
- package/dist/esm/dt/final/TShellCommand.js +12 -0
- package/dist/esm/dt/final/TSlug.d.ts +9 -0
- package/dist/esm/dt/final/TSlug.js +16 -0
- package/dist/esm/dt/final/TTime.d.ts +13 -0
- package/dist/esm/dt/final/TTime.js +22 -0
- package/dist/esm/dt/final/TTimestamp.d.ts +7 -0
- package/dist/esm/dt/final/TTimestamp.js +9 -0
- package/dist/esm/dt/final/TUIntDuration.d.ts +7 -0
- package/dist/esm/dt/final/TUIntDuration.js +9 -0
- package/dist/esm/dt/final/TUIntQuantity.d.ts +7 -0
- package/dist/esm/dt/final/TUIntQuantity.js +9 -0
- package/dist/esm/dt/final/TURL.d.ts +16 -0
- package/dist/esm/dt/final/TURL.js +32 -0
- package/dist/esm/dt/final/TURLPath.d.ts +7 -0
- package/dist/esm/dt/final/TURLPath.js +9 -0
- package/dist/esm/dt/final/TUUID.d.ts +9 -0
- package/dist/esm/dt/final/TUUID.js +16 -0
- package/dist/esm/dt/final/TUsername.d.ts +7 -0
- package/dist/esm/dt/final/TUsername.js +9 -0
- package/dist/esm/dt/final/TYesNo.d.ts +9 -0
- package/dist/esm/dt/final/TYesNo.js +20 -0
- package/dist/esm/dt/index.d.ts +78 -0
- package/dist/esm/dt/index.js +75 -0
- package/dist/esm/dt/targets/rn.d.ts +1 -0
- package/dist/esm/dt/targets/rn.js +1 -0
- package/dist/esm/dt/targets/web.d.ts +1 -0
- package/dist/esm/dt/targets/web.js +1 -0
- package/dist/esm/error/CustomError.d.ts +10 -0
- package/dist/esm/error/CustomError.js +13 -0
- package/dist/esm/error/ForbiddenAsNotFoundError.d.ts +6 -0
- package/dist/esm/error/ForbiddenAsNotFoundError.js +9 -0
- package/dist/esm/error/ForbiddenError.d.ts +6 -0
- package/dist/esm/error/ForbiddenError.js +9 -0
- package/dist/esm/error/IllegalArgumentError.d.ts +6 -0
- package/dist/esm/error/IllegalArgumentError.js +9 -0
- package/dist/esm/error/InternalServerError.d.ts +6 -0
- package/dist/esm/error/InternalServerError.js +9 -0
- package/dist/esm/error/NotFoundError.d.ts +6 -0
- package/dist/esm/error/NotFoundError.js +9 -0
- package/dist/esm/error/UnauthorizedError.d.ts +6 -0
- package/dist/esm/error/UnauthorizedError.js +9 -0
- package/dist/esm/error/index.d.ts +7 -0
- package/dist/esm/error/index.js +7 -0
- package/dist/esm/i18n/WordingManager.d.ts +20 -0
- package/dist/esm/i18n/WordingManager.js +109 -0
- package/dist/esm/i18n/consts.d.ts +2 -0
- package/dist/esm/i18n/consts.js +1 -0
- package/dist/esm/i18n/index.d.ts +3 -0
- package/dist/esm/i18n/index.js +2 -0
- package/dist/esm/i18n/locales/en.d.ts +2 -0
- package/dist/esm/i18n/locales/en.js +54 -0
- package/dist/esm/i18n/locales/fr.d.ts +2 -0
- package/dist/esm/i18n/locales/fr.js +54 -0
- package/dist/esm/i18n/types.d.ts +14 -0
- package/dist/esm/i18n/types.js +1 -0
- package/dist/esm/icon/Icon.d.ts +1 -0
- package/dist/esm/icon/Icon.js +1 -0
- package/dist/esm/icon/index.d.ts +1 -0
- package/dist/esm/icon/index.js +1 -0
- package/dist/esm/index.d.ts +42 -0
- package/dist/esm/index.js +42 -1
- package/dist/esm/index.node-mcp.d.ts +2 -0
- package/dist/esm/index.node-mcp.js +2 -0
- package/dist/esm/index.node-test.d.ts +3 -0
- package/dist/esm/index.node-test.js +2 -0
- package/dist/esm/index.node.d.ts +13 -0
- package/dist/esm/index.node.js +13 -0
- package/dist/esm/index.react-web-pure.d.ts +10 -0
- package/dist/esm/index.react-web-pure.js +10 -0
- package/dist/esm/index.react.d.ts +9 -0
- package/dist/esm/index.react.js +6 -0
- package/dist/esm/index.rn.d.ts +2 -0
- package/dist/esm/index.rn.js +2 -0
- package/dist/esm/index.std-jwt-manager-jose.d.ts +1 -0
- package/dist/esm/index.std-jwt-manager-jose.js +1 -0
- package/dist/esm/index.uc-data-store-knex.d.ts +1 -0
- package/dist/esm/index.uc-data-store-knex.js +1 -0
- package/dist/esm/index.vite.d.ts +1 -0
- package/dist/esm/index.vite.js +1 -0
- package/dist/esm/index.web.d.ts +5 -0
- package/dist/esm/index.web.js +5 -0
- package/dist/esm/product/i18n.d.ts +2 -0
- package/dist/esm/product/i18n.js +1 -0
- package/dist/esm/product/index.d.ts +3 -0
- package/dist/esm/product/index.js +1 -0
- package/dist/esm/product/manifest.d.ts +17 -0
- package/dist/esm/product/manifest.js +1 -0
- package/dist/esm/product/workers/ProductUCsLoader.d.ts +12 -0
- package/dist/esm/product/workers/ProductUCsLoader.js +41 -0
- package/dist/esm/products/Helper/container.d.ts +3 -0
- package/dist/esm/products/Helper/container.js +22 -0
- package/dist/esm/products/Helper/i18n.d.ts +2 -0
- package/dist/esm/products/Helper/i18n.js +10 -0
- package/dist/esm/products/Helper/index.d.ts +1 -0
- package/dist/esm/products/Helper/index.js +11 -0
- package/dist/esm/products/Helper/manifest.d.ts +1 -0
- package/dist/esm/products/Helper/manifest.js +4 -0
- package/dist/esm/std/BufferManager.d.ts +9 -0
- package/dist/esm/std/BufferManager.js +1 -0
- package/dist/esm/std/ClockManager.d.ts +7 -0
- package/dist/esm/std/ClockManager.js +1 -0
- package/dist/esm/std/CryptoManager.d.ts +20 -0
- package/dist/esm/std/CryptoManager.js +1 -0
- package/dist/esm/std/EmailManager.d.ts +25 -0
- package/dist/esm/std/EmailManager.js +1 -0
- package/dist/esm/std/EnvironmentManager.d.ts +14 -0
- package/dist/esm/std/EnvironmentManager.js +1 -0
- package/dist/esm/std/ExternalResourceInstaller.d.ts +17 -0
- package/dist/esm/std/ExternalResourceInstaller.js +37 -0
- package/dist/esm/std/ExternalResourceManager.d.ts +6 -0
- package/dist/esm/std/ExternalResourceManager.js +1 -0
- package/dist/esm/std/FSManager.d.ts +55 -0
- package/dist/esm/std/FSManager.js +6 -0
- package/dist/esm/std/FormDataBuilder.d.ts +9 -0
- package/dist/esm/std/FormDataBuilder.js +1 -0
- package/dist/esm/std/HTTPAPICallExecutor.d.ts +40 -0
- package/dist/esm/std/HTTPAPICallExecutor.js +1 -0
- package/dist/esm/std/HTTPAPICaller.d.ts +39 -0
- package/dist/esm/std/HTTPAPICaller.js +1 -0
- package/dist/esm/std/I18nManager.d.ts +14 -0
- package/dist/esm/std/I18nManager.js +1 -0
- package/dist/esm/std/JWTManager.d.ts +34 -0
- package/dist/esm/std/JWTManager.js +1 -0
- package/dist/esm/std/JobManager.d.ts +17 -0
- package/dist/esm/std/JobManager.js +1 -0
- package/dist/esm/std/Logger.d.ts +13 -0
- package/dist/esm/std/Logger.js +1 -0
- package/dist/esm/std/PromptManager.d.ts +6 -0
- package/dist/esm/std/PromptManager.js +1 -0
- package/dist/esm/std/SettingsManager.d.ts +14 -0
- package/dist/esm/std/SettingsManager.js +7 -0
- package/dist/esm/std/Worker.d.ts +3 -0
- package/dist/esm/std/Worker.js +1 -0
- package/dist/esm/std/XMLManager.d.ts +9 -0
- package/dist/esm/std/XMLManager.js +1 -0
- package/dist/esm/std/consts.d.ts +8 -0
- package/dist/esm/std/consts.js +22 -0
- package/dist/esm/std/impl/BufferLibBufferManager.d.ts +10 -0
- package/dist/esm/std/impl/BufferLibBufferManager.js +32 -0
- package/dist/esm/std/impl/ConsoleLogger.d.ts +17 -0
- package/dist/esm/std/impl/ConsoleLogger.js +77 -0
- package/dist/esm/std/impl/EnvSettingsManager.d.ts +10 -0
- package/dist/esm/std/impl/EnvSettingsManager.js +108 -0
- package/dist/esm/std/impl/FakeEmailManager.d.ts +13 -0
- package/dist/esm/std/impl/FakeEmailManager.js +29 -0
- package/dist/esm/std/impl/FakeFSManager.d.ts +23 -0
- package/dist/esm/std/impl/FakeFSManager.js +104 -0
- package/dist/esm/std/impl/FakeHTTPAPICallExecutor.d.ts +9 -0
- package/dist/esm/std/impl/FakeHTTPAPICallExecutor.js +74 -0
- package/dist/esm/std/impl/FakeJobManager.d.ts +12 -0
- package/dist/esm/std/impl/FakeJobManager.js +29 -0
- package/dist/esm/std/impl/FetchHTTPAPICallExecutor.d.ts +4 -0
- package/dist/esm/std/impl/FetchHTTPAPICallExecutor.js +16 -0
- package/dist/esm/std/impl/JoseJWTManager.d.ts +14 -0
- package/dist/esm/std/impl/JoseJWTManager.js +110 -0
- package/dist/esm/std/impl/NodeBufferManager.d.ts +9 -0
- package/dist/esm/std/impl/NodeBufferManager.js +31 -0
- package/dist/esm/std/impl/NodeCryptoManager.d.ts +13 -0
- package/dist/esm/std/impl/NodeCryptoManager.js +60 -0
- package/dist/esm/std/impl/NodeDeterministicCryptoManager.d.ts +10 -0
- package/dist/esm/std/impl/NodeDeterministicCryptoManager.js +59 -0
- package/dist/esm/std/impl/NodeEnvironmentManager.d.ts +9 -0
- package/dist/esm/std/impl/NodeEnvironmentManager.js +29 -0
- package/dist/esm/std/impl/NodeFSManager.d.ts +19 -0
- package/dist/esm/std/impl/NodeFSManager.js +126 -0
- package/dist/esm/std/impl/NodeFormDataBuilder.d.ts +4 -0
- package/dist/esm/std/impl/NodeFormDataBuilder.js +37 -0
- package/dist/esm/std/impl/NodeHTTPAPICallExecutorAgentBuilder.d.ts +7 -0
- package/dist/esm/std/impl/NodeHTTPAPICallExecutorAgentBuilder.js +35 -0
- package/dist/esm/std/impl/NodePromptManager.d.ts +4 -0
- package/dist/esm/std/impl/NodePromptManager.js +34 -0
- package/dist/esm/std/impl/NoopHTTPAPICallExecutorAgentBuilder.d.ts +4 -0
- package/dist/esm/std/impl/NoopHTTPAPICallExecutorAgentBuilder.js +16 -0
- package/dist/esm/std/impl/NoopXMLManager.d.ts +4 -0
- package/dist/esm/std/impl/NoopXMLManager.js +16 -0
- package/dist/esm/std/impl/SettingsServerClientManager.d.ts +16 -0
- package/dist/esm/std/impl/SettingsServerClientManager.js +59 -0
- package/dist/esm/std/impl/SimpleFormDataBuilder.d.ts +4 -0
- package/dist/esm/std/impl/SimpleFormDataBuilder.js +16 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.d.ts +19 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.js +196 -0
- package/dist/esm/std/impl/SimpleMapI18nManager.d.ts +16 -0
- package/dist/esm/std/impl/SimpleMapI18nManager.js +74 -0
- package/dist/esm/std/impl/StaticSettingsManager.d.ts +6 -0
- package/dist/esm/std/impl/StaticSettingsManager.js +28 -0
- package/dist/esm/std/impl/StdDateClockManager.d.ts +7 -0
- package/dist/esm/std/impl/StdDateClockManager.js +25 -0
- package/dist/esm/std/impl/UCDataStoreExternalResourceManager.d.ts +10 -0
- package/dist/esm/std/impl/UCDataStoreExternalResourceManager.js +37 -0
- package/dist/esm/std/impl/WebCryptoManager.d.ts +13 -0
- package/dist/esm/std/impl/WebCryptoManager.js +60 -0
- package/dist/esm/std/impl/WebFSManager.d.ts +18 -0
- package/dist/esm/std/impl/WebFSManager.js +55 -0
- package/dist/esm/std/index.d.ts +20 -0
- package/dist/esm/std/index.js +20 -0
- package/dist/esm/target/lib/cli/CLIManager.d.ts +6 -0
- package/dist/esm/target/lib/cli/CLIManager.js +1 -0
- package/dist/esm/target/lib/cli/CommandExecutor.d.ts +24 -0
- package/dist/esm/target/lib/cli/CommandExecutor.js +118 -0
- package/dist/esm/target/lib/cli/renderer.d.ts +2 -0
- package/dist/esm/target/lib/cli/renderer.js +17 -0
- package/dist/esm/target/lib/client/ServerClientManager.d.ts +27 -0
- package/dist/esm/target/lib/client/ServerClientManager.js +1 -0
- package/dist/esm/target/lib/client/consts.d.ts +2 -0
- package/dist/esm/target/lib/client/consts.js +5 -0
- package/dist/esm/target/lib/mcp-server/MCPServerBooter.d.ts +15 -0
- package/dist/esm/target/lib/mcp-server/MCPServerBooter.js +55 -0
- package/dist/esm/target/lib/react/DIContextProvider.d.ts +16 -0
- package/dist/esm/target/lib/react/DIContextProvider.js +19 -0
- package/dist/esm/target/lib/react/UCContainer.d.ts +6 -0
- package/dist/esm/target/lib/react/UCContainer.js +24 -0
- package/dist/esm/target/lib/react/UCEntrypoint.d.ts +9 -0
- package/dist/esm/target/lib/react/UCEntrypoint.js +8 -0
- package/dist/esm/target/lib/react/UCPanel.d.ts +20 -0
- package/dist/esm/target/lib/react/UCPanel.js +86 -0
- package/dist/esm/target/lib/react/entrypoint.d.ts +6 -0
- package/dist/esm/target/lib/react/entrypoint.js +1 -0
- package/dist/esm/target/lib/react/form.d.ts +10 -0
- package/dist/esm/target/lib/react/form.js +1 -0
- package/dist/esm/target/lib/react/loader.d.ts +2 -0
- package/dist/esm/target/lib/react/loader.js +1 -0
- package/dist/esm/target/lib/react/panel.d.ts +14 -0
- package/dist/esm/target/lib/react/panel.js +1 -0
- package/dist/esm/target/lib/react/touchable.d.ts +12 -0
- package/dist/esm/target/lib/react/touchable.js +1 -0
- package/dist/esm/target/lib/react/useUC.d.ts +15 -0
- package/dist/esm/target/lib/react/useUC.js +22 -0
- package/dist/esm/target/lib/react/useUCOR.d.ts +17 -0
- package/dist/esm/target/lib/react/useUCOR.js +80 -0
- package/dist/esm/target/lib/server/AuthenticationChecker.d.ts +30 -0
- package/dist/esm/target/lib/server/AuthenticationChecker.js +108 -0
- package/dist/esm/target/lib/server/BasicAuthenticationChecker.d.ts +17 -0
- package/dist/esm/target/lib/server/BasicAuthenticationChecker.js +69 -0
- package/dist/esm/target/lib/server/CSPDirectivesBuilder.d.ts +22 -0
- package/dist/esm/target/lib/server/CSPDirectivesBuilder.js +63 -0
- package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.d.ts +15 -0
- package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.js +42 -0
- package/dist/esm/target/lib/server/EntrypointsBuilder.d.ts +15 -0
- package/dist/esm/target/lib/server/EntrypointsBuilder.js +46 -0
- package/dist/esm/target/lib/server/JWTAuthenticationChecker.d.ts +17 -0
- package/dist/esm/target/lib/server/JWTAuthenticationChecker.js +78 -0
- package/dist/esm/target/lib/server/PrivateApiKeyAuthenticationChecker.d.ts +15 -0
- package/dist/esm/target/lib/server/PrivateApiKeyAuthenticationChecker.js +52 -0
- package/dist/esm/target/lib/server/PublicApiKeyChecker.d.ts +16 -0
- package/dist/esm/target/lib/server/PublicApiKeyChecker.js +55 -0
- package/dist/esm/target/lib/server/RequestChecker.d.ts +18 -0
- package/dist/esm/target/lib/server/RequestChecker.js +53 -0
- package/dist/esm/target/lib/server/RequestHandler.d.ts +9 -0
- package/dist/esm/target/lib/server/RequestHandler.js +1 -0
- package/dist/esm/target/lib/server/RequestLogger.d.ts +14 -0
- package/dist/esm/target/lib/server/RequestLogger.js +36 -0
- package/dist/esm/target/lib/server/ServerBooter.d.ts +24 -0
- package/dist/esm/target/lib/server/ServerBooter.js +111 -0
- package/dist/esm/target/lib/server/ServerInstaller.d.ts +10 -0
- package/dist/esm/target/lib/server/ServerInstaller.js +44 -0
- package/dist/esm/target/lib/server/ServerManager.d.ts +39 -0
- package/dist/esm/target/lib/server/ServerManager.js +1 -0
- package/dist/esm/target/lib/server/consts.d.ts +2 -0
- package/dist/esm/target/lib/server/consts.js +20 -0
- package/dist/esm/target/lib/shared.d.ts +2 -0
- package/dist/esm/target/lib/shared.js +1 -0
- package/dist/esm/target/lib/web/input.d.ts +24 -0
- package/dist/esm/target/lib/web/input.js +41 -0
- package/dist/esm/target/node-core-cli/NodeCoreCLIManager.d.ts +12 -0
- package/dist/esm/target/node-core-cli/NodeCoreCLIManager.js +93 -0
- package/dist/esm/target/node-core-cli/commands.d.ts +3 -0
- package/dist/esm/target/node-core-cli/commands.js +55 -0
- package/dist/esm/target/node-express-server/NodeExpressServerManager.d.ts +44 -0
- package/dist/esm/target/node-express-server/NodeExpressServerManager.js +184 -0
- package/dist/esm/target/node-express-server/lib/AuthCookieCreator.d.ts +21 -0
- package/dist/esm/target/node-express-server/lib/AuthCookieCreator.js +50 -0
- package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.d.ts +21 -0
- package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.js +66 -0
- package/dist/esm/target/node-express-server/middlewares/ErrorMiddlewareBuilder.d.ts +12 -0
- package/dist/esm/target/node-express-server/middlewares/ErrorMiddlewareBuilder.js +35 -0
- package/dist/esm/target/node-express-server/middlewares/HelmetMiddlewareBuilder.d.ts +12 -0
- package/dist/esm/target/node-express-server/middlewares/HelmetMiddlewareBuilder.js +39 -0
- package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.d.ts +18 -0
- package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.js +49 -0
- package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.d.ts +12 -0
- package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.js +41 -0
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.d.ts +23 -0
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +151 -0
- package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.d.ts +13 -0
- package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.js +45 -0
- package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.d.ts +32 -0
- package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +155 -0
- package/dist/esm/target/node-mcp-server/funcs.d.ts +7 -0
- package/dist/esm/target/node-mcp-server/funcs.js +45 -0
- package/dist/esm/target/node-mcp-server/types.d.ts +19 -0
- package/dist/esm/target/node-mcp-server/types.js +1 -0
- package/dist/esm/target/react-web-pure/UCAutoExecLoader.d.ts +2 -0
- package/dist/esm/target/react-web-pure/UCAutoExecLoader.js +4 -0
- package/dist/esm/target/react-web-pure/UCEntrypointTouchable.d.ts +4 -0
- package/dist/esm/target/react-web-pure/UCEntrypointTouchable.js +4 -0
- package/dist/esm/target/react-web-pure/UCExecTouchable.d.ts +4 -0
- package/dist/esm/target/react-web-pure/UCExecTouchable.js +7 -0
- package/dist/esm/target/react-web-pure/UCForm.d.ts +4 -0
- package/dist/esm/target/react-web-pure/UCForm.js +17 -0
- package/dist/esm/target/react-web-pure/UCFormField.d.ts +11 -0
- package/dist/esm/target/react-web-pure/UCFormField.js +32 -0
- package/dist/esm/target/react-web-pure/UCFormFieldControl.d.ts +11 -0
- package/dist/esm/target/react-web-pure/UCFormFieldControl.js +34 -0
- package/dist/esm/target/react-web-pure/UCFormFieldDesc.d.ts +7 -0
- package/dist/esm/target/react-web-pure/UCFormFieldDesc.js +10 -0
- package/dist/esm/target/react-web-pure/UCFormFieldErr.d.ts +7 -0
- package/dist/esm/target/react-web-pure/UCFormFieldErr.js +4 -0
- package/dist/esm/target/react-web-pure/UCFormFieldLabel.d.ts +7 -0
- package/dist/esm/target/react-web-pure/UCFormFieldLabel.js +8 -0
- package/dist/esm/target/react-web-pure/UCFormSubmitControl.d.ts +6 -0
- package/dist/esm/target/react-web-pure/UCFormSubmitControl.js +6 -0
- package/dist/esm/testing/AppTester.d.ts +67 -0
- package/dist/esm/testing/AppTester.js +343 -0
- package/dist/esm/testing/AppTesterConfigurator.d.ts +26 -0
- package/dist/esm/testing/AppTesterConfigurator.js +1 -0
- package/dist/esm/testing/UCDataStoreTester.d.ts +25 -0
- package/dist/esm/testing/UCDataStoreTester.js +192 -0
- package/dist/esm/testing/UCDefASTParser.d.ts +43 -0
- package/dist/esm/testing/UCDefASTParser.js +44 -0
- package/dist/esm/testing/ctx.d.ts +18 -0
- package/dist/esm/testing/ctx.js +1 -0
- package/dist/esm/testing/flow.d.ts +13 -0
- package/dist/esm/testing/flow.js +1 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.d.ts +7 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +161 -0
- package/dist/esm/testing/impl/SimpleAppTesterConfigurator.d.ts +14 -0
- package/dist/esm/testing/impl/SimpleAppTesterConfigurator.js +34 -0
- package/dist/esm/testing/impl/SimpleHTMLAppTestReportEmitter.d.ts +10 -0
- package/dist/esm/testing/impl/SimpleHTMLAppTestReportEmitter.js +186 -0
- package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.d.ts +24 -0
- package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +246 -0
- package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.d.ts +7 -0
- package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.js +231 -0
- package/dist/esm/testing/impl/VitestAppTestSuiteRunner.d.ts +10 -0
- package/dist/esm/testing/impl/VitestAppTestSuiteRunner.js +51 -0
- package/dist/esm/testing/impl/newNodeAppTester.d.ts +3 -0
- package/dist/esm/testing/impl/newNodeAppTester.js +67 -0
- package/dist/esm/testing/index.d.ts +13 -0
- package/dist/esm/testing/index.js +5 -0
- package/dist/esm/testing/opts.d.ts +34 -0
- package/dist/esm/testing/opts.js +50 -0
- package/dist/esm/testing/uc-auth.d.ts +7 -0
- package/dist/esm/testing/uc-auth.js +13 -0
- package/dist/esm/testing/uc-input.d.ts +11 -0
- package/dist/esm/testing/uc-input.js +52 -0
- package/dist/esm/testing/utils.d.ts +6 -0
- package/dist/esm/testing/utils.js +8 -0
- package/dist/esm/testing/workers/AppDocsEmitter.d.ts +12 -0
- package/dist/esm/testing/workers/AppDocsEmitter.js +1 -0
- package/dist/esm/testing/workers/AppTestReportEmitter.d.ts +14 -0
- package/dist/esm/testing/workers/AppTestReportEmitter.js +1 -0
- package/dist/esm/testing/workers/AppTestSuiteEmitter.d.ts +32 -0
- package/dist/esm/testing/workers/AppTestSuiteEmitter.js +1 -0
- package/dist/esm/testing/workers/AppTestSuiteRunner.d.ts +10 -0
- package/dist/esm/testing/workers/AppTestSuiteRunner.js +1 -0
- package/dist/esm/testing/workers/AppTesterCtxInitializer.d.ts +17 -0
- package/dist/esm/testing/workers/AppTesterCtxInitializer.js +57 -0
- package/dist/esm/testing/workers/UCExecutor.d.ts +45 -0
- package/dist/esm/testing/workers/UCExecutor.js +94 -0
- package/dist/esm/testing/workers/checkers/AppI18nChecker.d.ts +19 -0
- package/dist/esm/testing/workers/checkers/AppI18nChecker.js +52 -0
- package/dist/esm/testing/workers/checkers/AppIndexChecker.d.ts +16 -0
- package/dist/esm/testing/workers/checkers/AppIndexChecker.js +41 -0
- package/dist/esm/testing/workers/checkers/AppManifestChecker.d.ts +17 -0
- package/dist/esm/testing/workers/checkers/AppManifestChecker.js +34 -0
- package/dist/esm/testing/workers/checkers/UCDefChecker.d.ts +14 -0
- package/dist/esm/testing/workers/checkers/UCDefChecker.js +45 -0
- package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.d.ts +27 -0
- package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +249 -0
- package/dist/esm/uc/UC.d.ts +39 -0
- package/dist/esm/uc/UC.js +157 -0
- package/dist/esm/uc/UCInputField.d.ts +23 -0
- package/dist/esm/uc/UCInputField.js +162 -0
- package/dist/esm/uc/UCOutputField.d.ts +9 -0
- package/dist/esm/uc/UCOutputField.js +8 -0
- package/dist/esm/uc/auth/consts.d.ts +3 -0
- package/dist/esm/uc/auth/consts.js +16 -0
- package/dist/esm/uc/auth.d.ts +13 -0
- package/dist/esm/uc/auth.js +1 -0
- package/dist/esm/uc/client.d.ts +19 -0
- package/dist/esm/uc/client.js +1 -0
- package/dist/esm/uc/data-store.d.ts +71 -0
- package/dist/esm/uc/data-store.js +1 -0
- package/dist/esm/uc/data.d.ts +2 -0
- package/dist/esm/uc/data.js +1 -0
- package/dist/esm/uc/def.d.ts +33 -0
- package/dist/esm/uc/def.js +1 -0
- package/dist/esm/uc/exec.d.ts +7 -0
- package/dist/esm/uc/exec.js +11 -0
- package/dist/esm/uc/ext.d.ts +16 -0
- package/dist/esm/uc/ext.js +1 -0
- package/dist/esm/uc/file.d.ts +3 -0
- package/dist/esm/uc/file.js +1 -0
- package/dist/esm/uc/helpers/UCOutputBuilder.d.ts +18 -0
- package/dist/esm/uc/helpers/UCOutputBuilder.js +71 -0
- package/dist/esm/uc/helpers/UCOutputReader.d.ts +43 -0
- package/dist/esm/uc/helpers/UCOutputReader.js +119 -0
- package/dist/esm/uc/impl/HTTPUCTransporter.d.ts +17 -0
- package/dist/esm/uc/impl/HTTPUCTransporter.js +118 -0
- package/dist/esm/uc/impl/InMemoryUCDataStore.d.ts +22 -0
- package/dist/esm/uc/impl/InMemoryUCDataStore.js +97 -0
- package/dist/esm/uc/impl/KnexUCDataStore.d.ts +43 -0
- package/dist/esm/uc/impl/KnexUCDataStore.js +237 -0
- package/dist/esm/uc/impl/PromptUCClientConfirmManager.d.ts +16 -0
- package/dist/esm/uc/impl/PromptUCClientConfirmManager.js +51 -0
- package/dist/esm/uc/impl/SimpleUCManager.d.ts +39 -0
- package/dist/esm/uc/impl/SimpleUCManager.js +163 -0
- package/dist/esm/uc/impl/StaticUCClientConfirmManager.d.ts +12 -0
- package/dist/esm/uc/impl/StaticUCClientConfirmManager.js +34 -0
- package/dist/esm/uc/impl/WebUCClientConfirmManager.d.ts +10 -0
- package/dist/esm/uc/impl/WebUCClientConfirmManager.js +34 -0
- package/dist/esm/uc/index.d.ts +62 -0
- package/dist/esm/uc/index.js +62 -0
- package/dist/esm/uc/init.d.ts +3 -0
- package/dist/esm/uc/init.js +1 -0
- package/dist/esm/uc/input-field.d.ts +35 -0
- package/dist/esm/uc/input-field.js +73 -0
- package/dist/esm/uc/input.d.ts +12 -0
- package/dist/esm/uc/input.js +1 -0
- package/dist/esm/uc/io/input/AggregateInput.d.ts +7 -0
- package/dist/esm/uc/io/input/AggregateInput.js +11 -0
- package/dist/esm/uc/io/input/ListInput.d.ts +10 -0
- package/dist/esm/uc/io/input/ListInput.js +29 -0
- package/dist/esm/uc/io/output/AggregateOutput.d.ts +5 -0
- package/dist/esm/uc/io/output/AggregateOutput.js +13 -0
- package/dist/esm/uc/lifecycle/client/IdleClientMain.d.ts +6 -0
- package/dist/esm/uc/lifecycle/client/IdleClientMain.js +15 -0
- package/dist/esm/uc/lifecycle/client/SendClientMain.d.ts +10 -0
- package/dist/esm/uc/lifecycle/client/SendClientMain.js +28 -0
- package/dist/esm/uc/lifecycle/server/IdleServerMain.d.ts +6 -0
- package/dist/esm/uc/lifecycle/server/IdleServerMain.js +15 -0
- package/dist/esm/uc/main.d.ts +10 -0
- package/dist/esm/uc/main.js +1 -0
- package/dist/esm/uc/manager.d.ts +25 -0
- package/dist/esm/uc/manager.js +1 -0
- package/dist/esm/uc/metadata.d.ts +17 -0
- package/dist/esm/uc/metadata.js +20 -0
- package/dist/esm/uc/opi-layout.d.ts +13 -0
- package/dist/esm/uc/opi-layout.js +1 -0
- package/dist/esm/uc/opi.d.ts +6 -0
- package/dist/esm/uc/opi.js +1 -0
- package/dist/esm/uc/output-field.d.ts +8 -0
- package/dist/esm/uc/output-field.js +1 -0
- package/dist/esm/uc/output-part.d.ts +26 -0
- package/dist/esm/uc/output-part.js +1 -0
- package/dist/esm/uc/output.d.ts +19 -0
- package/dist/esm/uc/output.js +1 -0
- package/dist/esm/uc/policies/AnonymousUCPolicy.d.ts +7 -0
- package/dist/esm/uc/policies/AnonymousUCPolicy.js +22 -0
- package/dist/esm/uc/policies/AuthenticatedUCPolicy.d.ts +7 -0
- package/dist/esm/uc/policies/AuthenticatedUCPolicy.js +22 -0
- package/dist/esm/uc/policies/EverybodyUCPolicy.d.ts +7 -0
- package/dist/esm/uc/policies/EverybodyUCPolicy.js +22 -0
- package/dist/esm/uc/policies/NobodyUCPolicy.d.ts +7 -0
- package/dist/esm/uc/policies/NobodyUCPolicy.js +22 -0
- package/dist/esm/uc/policies/RoleAdminUCPolicy.d.ts +7 -0
- package/dist/esm/uc/policies/RoleAdminUCPolicy.js +22 -0
- package/dist/esm/uc/policies/RoleRegularUCPolicy.d.ts +7 -0
- package/dist/esm/uc/policies/RoleRegularUCPolicy.js +22 -0
- package/dist/esm/uc/policies/funcs.d.ts +2 -0
- package/dist/esm/uc/policies/funcs.js +6 -0
- package/dist/esm/uc/policy.d.ts +13 -0
- package/dist/esm/uc/policy.js +1 -0
- package/dist/esm/uc/sec/consts.d.ts +3 -0
- package/dist/esm/uc/sec/consts.js +2 -0
- package/dist/esm/uc/sec.d.ts +6 -0
- package/dist/esm/uc/sec.js +1 -0
- package/dist/esm/uc/server.d.ts +13 -0
- package/dist/esm/uc/server.js +1 -0
- package/dist/esm/uc/settings/consts.d.ts +2 -0
- package/dist/esm/uc/settings/consts.js +6 -0
- package/dist/esm/uc/settings.d.ts +11 -0
- package/dist/esm/uc/settings.js +1 -0
- package/dist/esm/uc/side-effect.d.ts +12 -0
- package/dist/esm/uc/side-effect.js +6 -0
- package/dist/esm/uc/transporter.d.ts +7 -0
- package/dist/esm/uc/transporter.js +1 -0
- package/dist/esm/uc/utils/appendUCInputToURL.d.ts +4 -0
- package/dist/esm/uc/utils/appendUCInputToURL.js +12 -0
- package/dist/esm/uc/utils/fmtVal.d.ts +7 -0
- package/dist/esm/uc/utils/fmtVal.js +20 -0
- package/dist/esm/uc/utils/rInput.d.ts +11 -0
- package/dist/esm/uc/utils/rInput.js +39 -0
- package/dist/esm/uc/utils/rVal.d.ts +5 -0
- package/dist/esm/uc/utils/rVal.js +20 -0
- package/dist/esm/uc/utils/recIs.d.ts +5 -0
- package/dist/esm/uc/utils/recIs.js +1 -0
- package/dist/esm/uc/utils/stripUCDLifecycleServer.d.ts +2 -0
- package/dist/esm/uc/utils/stripUCDLifecycleServer.js +60 -0
- package/dist/esm/uc/utils/ucHTTPContract.d.ts +15 -0
- package/dist/esm/uc/utils/ucHTTPContract.js +39 -0
- package/dist/esm/uc/utils/ucMountingPoint.d.ts +7 -0
- package/dist/esm/uc/utils/ucMountingPoint.js +7 -0
- package/dist/esm/uc/utils/ucifcoIsForArray.d.ts +2 -0
- package/dist/esm/uc/utils/ucifcoIsForArray.js +7 -0
- package/dist/esm/uc/value.d.ts +2 -0
- package/dist/esm/uc/value.js +1 -0
- package/dist/esm/uc/workers/SimpleAggregateFinder.d.ts +20 -0
- package/dist/esm/uc/workers/SimpleAggregateFinder.js +45 -0
- package/dist/esm/uc/workers/SimpleAggregateOwnershipChecker.d.ts +17 -0
- package/dist/esm/uc/workers/SimpleAggregateOwnershipChecker.js +35 -0
- package/dist/esm/uc/workers/UCBuilder.d.ts +10 -0
- package/dist/esm/uc/workers/UCBuilder.js +17 -0
- package/dist/esm/uc/workers/UCExecChecker.d.ts +24 -0
- package/dist/esm/uc/workers/UCExecChecker.js +72 -0
- package/dist/esm/uc/workers/UCInputFilesProcessor.d.ts +20 -0
- package/dist/esm/uc/workers/UCInputFilesProcessor.js +75 -0
- package/dist/esm/uc/workers/UCInputValidator.d.ts +15 -0
- package/dist/esm/uc/workers/UCInputValidator.js +48 -0
- package/dist/esm/uc/workers/UCOutputFilesProcessor.d.ts +20 -0
- package/dist/esm/uc/workers/UCOutputFilesProcessor.js +60 -0
- package/dist/esm/utils/async/sleep.d.ts +2 -0
- package/dist/esm/utils/async/sleep.js +7 -0
- package/dist/esm/utils/concerns/Clearable.d.ts +3 -0
- package/dist/esm/utils/concerns/Clearable.js +1 -0
- package/dist/esm/utils/concerns/Initializable.d.ts +3 -0
- package/dist/esm/utils/concerns/Initializable.js +1 -0
- package/dist/esm/utils/esm/srcImporter.d.ts +2 -0
- package/dist/esm/utils/esm/srcImporter.js +1 -0
- package/dist/esm/utils/http/HTTPRequestBuilder.d.ts +17 -0
- package/dist/esm/utils/http/HTTPRequestBuilder.js +55 -0
- package/dist/esm/utils/http/appendData.d.ts +2 -0
- package/dist/esm/utils/http/appendData.js +14 -0
- package/dist/esm/utils/http/toFormData.d.ts +3 -0
- package/dist/esm/utils/http/toFormData.js +4 -0
- package/dist/esm/utils/http/toJSON.d.ts +3 -0
- package/dist/esm/utils/http/toJSON.js +3 -0
- package/dist/esm/utils/http/toQueryParams.d.ts +2 -0
- package/dist/esm/utils/http/toQueryParams.js +4 -0
- package/dist/esm/utils/http/types.d.ts +2 -0
- package/dist/esm/utils/http/types.js +1 -0
- package/dist/esm/utils/index.d.ts +18 -0
- package/dist/esm/utils/index.js +12 -0
- package/dist/esm/utils/ioc/ContainerPrinter.d.ts +12 -0
- package/dist/esm/utils/ioc/ContainerPrinter.js +53 -0
- package/dist/esm/utils/ioc/bindCommon.d.ts +6 -0
- package/dist/esm/utils/ioc/bindCommon.js +71 -0
- package/dist/esm/utils/ioc/bindNodeCLI.d.ts +2 -0
- package/dist/esm/utils/ioc/bindNodeCLI.js +8 -0
- package/dist/esm/utils/ioc/bindNodeCore.d.ts +2 -0
- package/dist/esm/utils/ioc/bindNodeCore.js +16 -0
- package/dist/esm/utils/ioc/bindProduct.d.ts +4 -0
- package/dist/esm/utils/ioc/bindProduct.js +6 -0
- package/dist/esm/utils/ioc/bindProvider.d.ts +2 -0
- package/dist/esm/utils/ioc/bindProvider.js +9 -0
- package/dist/esm/utils/ioc/bindRN.d.ts +2 -0
- package/dist/esm/utils/ioc/bindRN.js +4 -0
- package/dist/esm/utils/ioc/bindServer.d.ts +2 -0
- package/dist/esm/utils/ioc/bindServer.js +8 -0
- package/dist/esm/utils/ioc/bindWeb.d.ts +2 -0
- package/dist/esm/utils/ioc/bindWeb.js +12 -0
- package/dist/esm/utils/ioc/container.d.ts +2 -0
- package/dist/esm/utils/ioc/container.js +3 -0
- package/dist/esm/utils/ioc/types.d.ts +2 -0
- package/dist/esm/utils/ioc/types.js +1 -0
- package/dist/esm/utils/numbers/fmt.d.ts +3 -0
- package/dist/esm/utils/numbers/fmt.js +24 -0
- package/dist/esm/utils/numbers/units.d.ts +9 -0
- package/dist/esm/utils/numbers/units.js +53 -0
- package/dist/esm/utils/strings/capitalize.d.ts +2 -0
- package/dist/esm/utils/strings/capitalize.js +14 -0
- package/dist/esm/utils/strings/humanize.d.ts +1 -0
- package/dist/esm/utils/strings/humanize.js +5 -0
- package/dist/esm/utils/strings/truncate.d.ts +2 -0
- package/dist/esm/utils/strings/truncate.js +3 -0
- package/dist/esm/utils/terminal/fmt.d.ts +4 -0
- package/dist/esm/utils/terminal/fmt.js +13 -0
- package/dist/esm/utils/types/funcs.d.ts +6 -0
- package/dist/esm/utils/types/funcs.js +32 -0
- package/dist/esm/utils/types/utility-types.d.ts +5 -0
- package/dist/esm/utils/types/utility-types.js +1 -0
- package/docs/getting-started/001_Create_the_project.md +168 -0
- package/docs/getting-started/002_Create_the_App.md +49 -0
- package/docs/getting-started/003_Create_the_UseCase.md +205 -0
- package/docs/getting-started/004_Test_the_App.md +114 -0
- package/docs/getting-started/005_Create_the_Product.md +46 -0
- package/docs/getting-started/006_Create_the_server_Target.md +130 -0
- package/docs/getting-started/007_Create_the_web_Target.md +262 -0
- package/docs/getting-started/008_Switch_to_a_persistent_data_storage.md +55 -0
- package/docs/getting-started/009_Define_wording_for_humans.md +42 -0
- package/docs/getting-started/010_Create_the_cli_Target.md +102 -0
- package/docs/getting-started/011_Create_the_mcp_server_Target.md +157 -0
- package/docs/getting-started/012_Summary.md +29 -0
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# libmodulor
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/libmodulor)
|
|
4
|
+
[](https://github.com/c100k/libmodulor/blob/master/LICENSE)
|
|
5
|
+
|
|
3
6
|
An opinionated TypeScript library to create business oriented applications.
|
|
4
7
|
|
|
5
8
|
Applications created with `libmodulor` have **6 main properties** :
|
|
@@ -14,14 +17,15 @@ Applications created with `libmodulor` have **6 main properties** :
|
|
|
14
17
|
> [!WARNING]
|
|
15
18
|
> The project is still in active development. Although already used in pilot projects, it's not suitable for all production scenarios yet.
|
|
16
19
|
> Being developed by only one person, it may keep going for years or stop at any time.
|
|
17
|
-
> In the meantime, it's still a "research project" that needs improvement. Thus, it will be subject to BREAKING CHANGES as long as the version is not 1.0.0
|
|
20
|
+
> In the meantime, it's still a "research project" that needs improvement. Thus, it will be subject to BREAKING CHANGES as long as the version is not `1.0.0`.
|
|
21
|
+
> All that said, the end goal is really to have a **production-grade library** to help everyone build **quality projects faster**. If you want to help in any way or have questions, feel free to contact me (cf. `author` in `package.json`).
|
|
18
22
|
|
|
19
23
|
> [!NOTE]
|
|
20
|
-
> At the beginning, the whole documentation will be
|
|
24
|
+
> At the beginning, the whole documentation will be on GitHub, starting from this file, to make it easier to have the big picture, maintain and <kbd>cmd</kbd> + <kbd>F</kbd>. At some point, I'll consider having a beautiful documentation website like all the cool kids.
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
---
|
|
23
27
|
|
|
24
|
-
## Philosophy
|
|
28
|
+
## 📚 Philosophy
|
|
25
29
|
|
|
26
30
|
One might argue that, with so many "JS frameworks" on the market, there are already too many ways to build new applications today. And they would be right.
|
|
27
31
|
|
|
@@ -41,7 +45,7 @@ Thus, you are free to use :
|
|
|
41
45
|
|
|
42
46
|
The main goal is to offer higher level primitives that make building business applications faster, without having to use a boilerplate or worse, no/low code, and thus, avoid vendor lock-in.
|
|
43
47
|
|
|
44
|
-
## How it works
|
|
48
|
+
## 💡 How it works
|
|
45
49
|
|
|
46
50
|
The library defines a **4-layer architecture** composed of : `UseCase`, `App`, `Product`, `Target`.
|
|
47
51
|
|
|
@@ -61,6 +65,8 @@ block-beta
|
|
|
61
65
|
UseCase6
|
|
62
66
|
```
|
|
63
67
|
|
|
68
|
+
_If you're not seeing the mermaid chart (e.g. on npm), head to GitHub._
|
|
69
|
+
|
|
64
70
|
### UseCase
|
|
65
71
|
|
|
66
72
|
A use case is the smallest unit. It defines the contract, mainly as an `Input` that goes into lifecycle methods (`client` and/or `server`) to finally give an `Output`. In the end, it constitutes a piece of business functionality.
|
|
@@ -101,389 +107,42 @@ _Examples : `web-react`, `web-angular`, `server-node`, `cli-node`, `cli-stricli`
|
|
|
101
107
|
|
|
102
108
|
Note that it's the only place where the "infrastructure" choices are applied.
|
|
103
109
|
|
|
104
|
-
##
|
|
105
|
-
|
|
106
|
-
Enough theory, let's dive in and learn by doing.
|
|
107
|
-
|
|
108
|
-
> [!NOTE]
|
|
109
|
-
> This Guide is voluntarily very verbose and not scripted so you can get a full overview of how things work. `npx` magic is good. But understanding what happens behind the scenes is good as well.
|
|
110
|
-
|
|
111
|
-
In this Guide, we'll init a repository (a repository can contain multiple apps and products) and create a real life application using the `libmodulor` primitives.
|
|
112
|
-
|
|
113
|
-
We'll build a small trading application. It will contain one `App` named `Trading`, which will contain one `UseCase` named `BuyAsset`. The `App` will be mounted in a `Product` called `SuperTrader` which will be exposed via a `server` `Target`, a `web` `Target`, a `cli` `Target` and finally, a `mcp-server` `Target`.
|
|
114
|
-
|
|
115
|
-
> [!NOTE]
|
|
116
|
-
> MCP stands for [Model Context Protocol](https://modelcontextprotocol.io) introduced recently by [@anthropics](https://github.com/anthropics).
|
|
117
|
-
|
|
118
|
-
If we adapt the abstract mermaid chart displayed above, concretely, it looks like this :
|
|
119
|
-
|
|
120
|
-
```mermaid
|
|
121
|
-
block-beta
|
|
122
|
-
server
|
|
123
|
-
web
|
|
124
|
-
cli
|
|
125
|
-
mcp_server
|
|
126
|
-
columns 4
|
|
127
|
-
SuperTrader:4
|
|
128
|
-
Trading:2
|
|
129
|
-
Auth:2
|
|
130
|
-
BuyAsset
|
|
131
|
-
ListOrders
|
|
132
|
-
SignUp
|
|
133
|
-
SignIn
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
Note that we'll only develop one use case in this Guide but you get the idea.
|
|
137
|
-
|
|
138
|
-
### Create the project
|
|
139
|
-
|
|
140
|
-
> [!IMPORTANT]
|
|
141
|
-
> At this stage, I'm following a documentation and spec first process. Thus, the source code is not yet published, just like the package on `npm`. Therefore, the commands below are not fully executable since `yarn install` will fail fetching the dependency. Currently, the main goal is to expose the docs, optimize the process, and most of all, get feedback on the mechanism. Thank you.
|
|
142
|
-
|
|
143
|
-
Assuming you have the following installed (otherwise, install them or adapt the commands) :
|
|
144
|
-
|
|
145
|
-
- `node` >= 22
|
|
146
|
-
- `yarn` >= 1.x
|
|
147
|
-
- `wget` and `curl`
|
|
148
|
-
|
|
149
|
-
If you're on macOS, for the `sed` commands, add a `''` after `-i` ([Explanation](https://stackoverflow.com/a/4247319/1259118)).
|
|
150
|
-
|
|
151
|
-
```sh
|
|
152
|
-
# Create the directory
|
|
153
|
-
mkdir libmodulor-tuto && cd libmodulor-tuto # Note how the repository is generic to contain multiple apps and products
|
|
154
|
-
|
|
155
|
-
# Initialize git
|
|
156
|
-
git init
|
|
157
|
-
|
|
158
|
-
# Initialize config files
|
|
159
|
-
touch .gitignore biome.json package.json README.md tsconfig.json vitest.config.ts
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
#### .gitignore
|
|
163
|
-
|
|
164
|
-
```.gitignore
|
|
165
|
-
coverage
|
|
166
|
-
dist
|
|
167
|
-
node_modules
|
|
168
|
-
src/apps/**/test/reports
|
|
169
|
-
.env
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
#### biome.json
|
|
173
|
-
|
|
174
|
-
```json
|
|
175
|
-
{
|
|
176
|
-
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
|
177
|
-
"files": {
|
|
178
|
-
"ignore": ["coverage", "dist", "node_modules"],
|
|
179
|
-
"ignoreUnknown": true
|
|
180
|
-
},
|
|
181
|
-
"formatter": {
|
|
182
|
-
"indentStyle": "space",
|
|
183
|
-
"indentWidth": 4
|
|
184
|
-
},
|
|
185
|
-
"javascript": {
|
|
186
|
-
"formatter": {
|
|
187
|
-
"quoteStyle": "single"
|
|
188
|
-
},
|
|
189
|
-
"parser": {
|
|
190
|
-
"unsafeParameterDecoratorsEnabled": true
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
#### package.json
|
|
197
|
-
|
|
198
|
-
```json
|
|
199
|
-
{
|
|
200
|
-
"name": "libmodulor-tuto",
|
|
201
|
-
"version": "0.1.0",
|
|
202
|
-
"author": "Chafik H'nini <chafik.hnini@gmail.com>",
|
|
203
|
-
"type": "module",
|
|
204
|
-
"private": true,
|
|
205
|
-
"scripts": {
|
|
206
|
-
"cli": "node ./node_modules/libmodulor/dist/esm/products/Wizard/index.js",
|
|
207
|
-
"lint": "biome check --write .",
|
|
208
|
-
"test": "tsc && vitest run"
|
|
209
|
-
},
|
|
210
|
-
"dependencies": {
|
|
211
|
-
"inversify": "^6.2.1",
|
|
212
|
-
"libmodulor": "c100k/libmodulor#master",
|
|
213
|
-
"reflect-metadata": "^0.2.2"
|
|
214
|
-
},
|
|
215
|
-
"devDependencies": {
|
|
216
|
-
"@biomejs/biome": "^1.9.4",
|
|
217
|
-
"@types/node": "^22.10.2",
|
|
218
|
-
"@vitest/coverage-v8": "^2.1.1",
|
|
219
|
-
"buffer": "^6.0.3",
|
|
220
|
-
"cookie-parser": "^1.4.7",
|
|
221
|
-
"express": "^4.21.2",
|
|
222
|
-
"express-fileupload": "^1.5.1",
|
|
223
|
-
"fast-check": "^3.23.2",
|
|
224
|
-
"helmet": "^8.0.0",
|
|
225
|
-
"jose": "^5.9.6",
|
|
226
|
-
"typescript": "^5.7.2",
|
|
227
|
-
"vite": "^6.0.5",
|
|
228
|
-
"vitest": "^2.1.8"
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
#### README.md
|
|
234
|
-
|
|
235
|
-
```md
|
|
236
|
-
# libmodulor-tuto
|
|
237
|
-
|
|
238
|
-
🚀🚀🚀
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
#### tsconfig.json
|
|
242
|
-
|
|
243
|
-
```json
|
|
244
|
-
{
|
|
245
|
-
"compilerOptions": {
|
|
246
|
-
"allowSyntheticDefaultImports": true,
|
|
247
|
-
"declaration": true,
|
|
248
|
-
"lib": ["dom", "esnext"],
|
|
249
|
-
"module": "NodeNext",
|
|
250
|
-
"moduleResolution": "NodeNext",
|
|
251
|
-
"noEmit": true,
|
|
252
|
-
"removeComments": true,
|
|
253
|
-
"skipLibCheck": true,
|
|
254
|
-
"sourceMap": true,
|
|
255
|
-
"target": "ESNext",
|
|
256
|
-
|
|
257
|
-
"strict": true,
|
|
258
|
-
"allowUnreachableCode": false,
|
|
259
|
-
"allowUnusedLabels": false,
|
|
260
|
-
"exactOptionalPropertyTypes": true,
|
|
261
|
-
"noFallthroughCasesInSwitch": true,
|
|
262
|
-
"noPropertyAccessFromIndexSignature": true,
|
|
263
|
-
"noImplicitOverride": true,
|
|
264
|
-
"noImplicitReturns": true,
|
|
265
|
-
"noUncheckedIndexedAccess": true,
|
|
266
|
-
"noUnusedLocals": true,
|
|
267
|
-
"noUnusedParameters": true,
|
|
268
|
-
"verbatimModuleSyntax": true,
|
|
269
|
-
|
|
270
|
-
"emitDecoratorMetadata": true,
|
|
271
|
-
"experimentalDecorators": true,
|
|
272
|
-
|
|
273
|
-
"jsx": "react"
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
#### vitest.config.ts
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
import { defineConfig } from 'vitest/config';
|
|
282
|
-
|
|
283
|
-
export default defineConfig({
|
|
284
|
-
test: {
|
|
285
|
-
coverage: {
|
|
286
|
-
enabled: true,
|
|
287
|
-
exclude: ['src/apps/**/test', 'src/**/*.test.ts'],
|
|
288
|
-
include: ['src'],
|
|
289
|
-
reporter: ['html', 'lcov', 'text'],
|
|
290
|
-
},
|
|
291
|
-
reporters: ['verbose'],
|
|
292
|
-
},
|
|
293
|
-
});
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
#### Install
|
|
297
|
-
|
|
298
|
-
```sh
|
|
299
|
-
yarn install
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
```sh
|
|
303
|
-
yarn lint && git add . && git commit -m "chore: init source code"
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
Optionally, you can create a remote repository (e.g. on GitHub) and push it.
|
|
307
|
-
|
|
308
|
-
### Create the App
|
|
309
|
-
|
|
310
|
-
An app is composed of three main files : `i18n.ts`, `manifest.ts` and `index.ts`.
|
|
311
|
-
|
|
312
|
-
```sh
|
|
313
|
-
mkdir -p src/apps/Trading/src/ucds
|
|
314
|
-
touch src/apps/Trading/src/{i18n.ts,manifest.ts}
|
|
315
|
-
touch src/apps/Trading/index.ts
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
> [!NOTE]
|
|
319
|
-
> 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.
|
|
320
|
-
|
|
321
|
-
#### i18n.ts
|
|
322
|
-
|
|
323
|
-
```typescript
|
|
324
|
-
import type { AppI18n } from 'libmodulor';
|
|
325
|
-
|
|
326
|
-
export const I18n: AppI18n = {
|
|
327
|
-
en: {},
|
|
328
|
-
};
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
#### manifest.ts
|
|
332
|
-
|
|
333
|
-
```typescript
|
|
334
|
-
import type { AppManifest } from 'libmodulor';
|
|
335
|
-
|
|
336
|
-
export const Manifest = {
|
|
337
|
-
languageCodes: ['en'],
|
|
338
|
-
name: 'Trading',
|
|
339
|
-
ucReg: {},
|
|
340
|
-
} satisfies AppManifest;
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
#### index.ts
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
// Expose only what's necessary
|
|
347
|
-
|
|
348
|
-
export { I18n } from './src/i18n.js';
|
|
349
|
-
export { Manifest } from './src/manifest.js';
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
```sh
|
|
353
|
-
yarn lint && git add . && git commit -m "feat: add the app"
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
### Create the UseCase
|
|
357
|
-
|
|
358
|
-
> [!NOTE]
|
|
359
|
-
> 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.
|
|
360
|
-
|
|
361
|
-
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.
|
|
362
|
-
|
|
363
|
-
Update `manifest.ts` to register the new use case.
|
|
364
|
-
|
|
365
|
-
```typescript
|
|
366
|
-
// ...
|
|
367
|
-
ucReg: {
|
|
368
|
-
BuyAsset: {
|
|
369
|
-
action: 'Create',
|
|
370
|
-
icon: 'plus',
|
|
371
|
-
name: 'BuyAsset',
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
// ...
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
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.
|
|
378
|
-
|
|
379
|
-
```sh
|
|
380
|
-
mkdir src/apps/Trading/src/dt
|
|
381
|
-
touch src/apps/Trading/src/dt/TISIN.ts
|
|
382
|
-
touch src/apps/Trading/src/ucds/{BuyAssetServerMain.ts,BuyAssetUCD.ts}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
#### TISIN.ts
|
|
110
|
+
## 👀 At a glance
|
|
386
111
|
|
|
387
|
-
|
|
112
|
+
Here is what a typical use case looks like. For more details, please follow the Guide below.
|
|
388
113
|
|
|
389
114
|
```typescript
|
|
390
|
-
import {
|
|
391
|
-
|
|
392
|
-
export type ISIN = Capitalize<string>;
|
|
393
|
-
|
|
394
|
-
export class TISIN extends TString<ISIN, 'ISIN'> {
|
|
395
|
-
public static readonly FORMAT: RegExp = /^[A-Z]{2}[A-Z0-9]{9}[0-9]$/;
|
|
396
|
-
|
|
397
|
-
constructor(constraints?: TStringConstraints) {
|
|
398
|
-
super({
|
|
399
|
-
...constraints,
|
|
400
|
-
format: { f: 'ISIN', regexp: TISIN.FORMAT },
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
public override tName(): TName {
|
|
405
|
-
return 'ISIN';
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
public override example(): ISIN {
|
|
409
|
-
return 'US02079K3059';
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
#### BuyAssetUCD.ts
|
|
415
|
-
|
|
416
|
-
```typescript
|
|
417
|
-
import {
|
|
418
|
-
type AggregateOPI0,
|
|
419
|
-
type Amount,
|
|
420
|
-
EverybodyUCPolicy,
|
|
421
|
-
TAmount,
|
|
422
|
-
TBoolean,
|
|
423
|
-
TUIntQuantity,
|
|
424
|
-
type UCDef,
|
|
425
|
-
type UCInput,
|
|
426
|
-
type UCInputFieldValue,
|
|
427
|
-
type UCMain,
|
|
428
|
-
type UCMainInput,
|
|
429
|
-
type UCOutputOrNothing,
|
|
430
|
-
type UCTransporter,
|
|
431
|
-
type UIntQuantity,
|
|
432
|
-
} from 'libmodulor';
|
|
433
|
-
import { inject, injectable } from 'inversify';
|
|
434
|
-
|
|
115
|
+
import { UCInput, /* omitted for brevity */ } from 'libmodulor';
|
|
435
116
|
import { Manifest } from '../manifest.js';
|
|
117
|
+
import { SignInServerMain } from './SignInServerMain.js';
|
|
436
118
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
export interface BuyAssetInput extends UCInput {
|
|
441
|
-
isin: UCInputFieldValue<ISIN>;
|
|
442
|
-
limit: UCInputFieldValue<Amount>;
|
|
443
|
-
qty: UCInputFieldValue<UIntQuantity>;
|
|
119
|
+
export interface SignInInput extends UCInput {
|
|
120
|
+
email: UCInputFieldValue<Email>;
|
|
121
|
+
password: UCInputFieldValue<Password>;
|
|
444
122
|
}
|
|
445
123
|
|
|
446
|
-
export interface
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
@injectable()
|
|
451
|
-
class BuyAssetClientMain implements UCMain<BuyAssetInput, BuyAssetOPI0> {
|
|
452
|
-
constructor(
|
|
453
|
-
@inject('UCTransporter')
|
|
454
|
-
private ucTransporter: UCTransporter,
|
|
455
|
-
) {}
|
|
456
|
-
|
|
457
|
-
public async exec({
|
|
458
|
-
uc,
|
|
459
|
-
}: UCMainInput<BuyAssetInput, BuyAssetOPI0>): Promise<
|
|
460
|
-
UCOutputOrNothing<BuyAssetOPI0>
|
|
461
|
-
> {
|
|
462
|
-
return this.ucTransporter.send(uc);
|
|
463
|
-
}
|
|
124
|
+
export interface SignInOPI0 extends UCOPIBase {
|
|
125
|
+
jwt: JWT;
|
|
464
126
|
}
|
|
465
127
|
|
|
466
|
-
export const
|
|
128
|
+
export const SignInUCD: UCDef<SignInInput, SignInOPI0> = {
|
|
467
129
|
io: {
|
|
468
|
-
|
|
130
|
+
i: {
|
|
469
131
|
fields: {
|
|
470
|
-
|
|
471
|
-
type: new
|
|
132
|
+
email: {
|
|
133
|
+
type: new TEmail(),
|
|
472
134
|
},
|
|
473
|
-
|
|
474
|
-
type: new
|
|
475
|
-
},
|
|
476
|
-
qty: {
|
|
477
|
-
type: new TUIntQuantity(),
|
|
135
|
+
password: {
|
|
136
|
+
type: new TPassword({ minLength: 10 }),
|
|
478
137
|
},
|
|
479
138
|
},
|
|
480
139
|
},
|
|
481
|
-
|
|
140
|
+
o: {
|
|
482
141
|
parts: {
|
|
483
142
|
_0: {
|
|
484
143
|
fields: {
|
|
485
|
-
|
|
486
|
-
type: new
|
|
144
|
+
jwt: {
|
|
145
|
+
type: new TJWT(),
|
|
487
146
|
},
|
|
488
147
|
},
|
|
489
148
|
},
|
|
@@ -492,994 +151,67 @@ export const BuyAssetUCD: UCDef<BuyAssetInput, BuyAssetOPI0> = {
|
|
|
492
151
|
},
|
|
493
152
|
lifecycle: {
|
|
494
153
|
client: {
|
|
495
|
-
main:
|
|
496
|
-
policy:
|
|
154
|
+
main: SendClientMain,
|
|
155
|
+
policy: AnonymousUCPolicy,
|
|
497
156
|
},
|
|
498
157
|
server: {
|
|
499
|
-
main:
|
|
500
|
-
policy:
|
|
158
|
+
main: SignInServerMain,
|
|
159
|
+
policy: AnonymousUCPolicy,
|
|
501
160
|
},
|
|
502
161
|
},
|
|
503
|
-
metadata: Manifest.ucReg.
|
|
504
|
-
};
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
#### BuyAssetServerMain.ts
|
|
508
|
-
|
|
509
|
-
```typescript
|
|
510
|
-
import {
|
|
511
|
-
type UCMain,
|
|
512
|
-
type UCMainInput,
|
|
513
|
-
type UCManager,
|
|
514
|
-
type UCOutput,
|
|
515
|
-
UCOutputBuilder,
|
|
516
|
-
} from 'libmodulor';
|
|
517
|
-
import { inject, injectable } from 'inversify';
|
|
518
|
-
|
|
519
|
-
import type { BuyAssetInput, BuyAssetOPI0 } from './BuyAssetUCD.js';
|
|
520
|
-
|
|
521
|
-
@injectable()
|
|
522
|
-
export class BuyAssetServerMain implements UCMain<BuyAssetInput, BuyAssetOPI0> {
|
|
523
|
-
constructor(@inject('UCManager') private ucManager: UCManager) {}
|
|
524
|
-
|
|
525
|
-
public async exec({
|
|
526
|
-
uc,
|
|
527
|
-
}: UCMainInput<BuyAssetInput, BuyAssetOPI0>): Promise<
|
|
528
|
-
UCOutput<BuyAssetOPI0>
|
|
529
|
-
> {
|
|
530
|
-
// >=> Persist the order
|
|
531
|
-
const { aggregateId } = await this.ucManager.persist(uc);
|
|
532
|
-
|
|
533
|
-
// >=> TODO : Check the user has enough funds to place the order
|
|
534
|
-
|
|
535
|
-
// >=> TODO : Send the order to a queue for processing
|
|
536
|
-
const executedDirectly: BuyAssetOPI0['executedDirectly'] = false;
|
|
537
|
-
|
|
538
|
-
return new UCOutputBuilder<BuyAssetOPI0>()
|
|
539
|
-
.add({
|
|
540
|
-
executedDirectly,
|
|
541
|
-
id: aggregateId,
|
|
542
|
-
})
|
|
543
|
-
.get();
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
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.
|
|
549
|
-
|
|
550
|
-
> [!TIP]
|
|
551
|
-
> Using a comment following the pattern `// >=> ` in `ClientMain` and `ServerMain` has a specific meaning as we'll see a little bit later.
|
|
552
|
-
|
|
553
|
-
> [!NOTE]
|
|
554
|
-
> Unlike `ClientMain`, `ServerMain` is put in another file for "historical" reasons, mainly for stripping and tree shaking reasons. More on this later.
|
|
555
|
-
|
|
556
|
-
```sh
|
|
557
|
-
yarn lint && git add . && git commit -m "feat: add the use case"
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
### Test the App
|
|
561
|
-
|
|
562
|
-
#### Preliminary test
|
|
563
|
-
|
|
564
|
-
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.
|
|
565
|
-
|
|
566
|
-
```sh
|
|
567
|
-
yarn test
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
```sh
|
|
571
|
-
% Coverage report from v8
|
|
572
|
-
------------------------|---------|----------|---------|---------|-------------------
|
|
573
|
-
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
574
|
-
------------------------|---------|----------|---------|---------|-------------------
|
|
575
|
-
All files | 0 | 40 | 40 | 0 |
|
|
576
|
-
Trading | 0 | 0 | 0 | 0 |
|
|
577
|
-
index.ts | 0 | 0 | 0 | 0 | 1
|
|
578
|
-
Trading/src | 0 | 100 | 100 | 0 |
|
|
579
|
-
i18n.ts | 0 | 100 | 100 | 0 | 3-5
|
|
580
|
-
manifest.ts | 0 | 100 | 100 | 0 | 3-14
|
|
581
|
-
Trading/src/ucds | 0 | 0 | 0 | 0 |
|
|
582
|
-
BuyAssetServerMain.ts | 0 | 0 | 0 | 0 | 1-28
|
|
583
|
-
BuyAssetUCD.ts | 0 | 0 | 0 | 0 | 1-92
|
|
584
|
-
------------------------|---------|----------|---------|---------|-------------------
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
As expected, the coverage report is pretty lame. Which is understandable, since we haven't written any tests yet.
|
|
588
|
-
|
|
589
|
-
```sh
|
|
590
|
-
mkdir src/apps/Trading/test
|
|
591
|
-
touch src/apps/Trading/test/Configurator.ts
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
#### Configurator.ts
|
|
595
|
-
|
|
596
|
-
```typescript
|
|
597
|
-
import { type AppTesterCtx, type CryptoManager, bindCommon } from 'libmodulor';
|
|
598
|
-
import {
|
|
599
|
-
NodeDeterministicCryptoManager,
|
|
600
|
-
bindNodeCore,
|
|
601
|
-
bindServer,
|
|
602
|
-
} from 'libmodulor/node';
|
|
603
|
-
import { SimpleAppTesterConfigurator } from 'libmodulor/node-test';
|
|
604
|
-
import { injectable } from 'inversify';
|
|
605
|
-
|
|
606
|
-
@injectable()
|
|
607
|
-
export class Configurator extends SimpleAppTesterConfigurator {
|
|
608
|
-
public override async bindImplementations(
|
|
609
|
-
ctx: AppTesterCtx,
|
|
610
|
-
): Promise<void> {
|
|
611
|
-
await super.bindImplementations(ctx);
|
|
612
|
-
|
|
613
|
-
const { container } = ctx;
|
|
614
|
-
|
|
615
|
-
bindCommon(container);
|
|
616
|
-
bindNodeCore(container);
|
|
617
|
-
bindServer(container);
|
|
618
|
-
|
|
619
|
-
container
|
|
620
|
-
.rebind<CryptoManager>('CryptoManager')
|
|
621
|
-
.to(NodeDeterministicCryptoManager);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
#### Automated test
|
|
627
|
-
|
|
628
|
-
Generate the automated tests and execute them with the CLI (it does more than a simple `yarn test`).
|
|
629
|
-
|
|
630
|
-
```sh
|
|
631
|
-
yarn cli GenerateAppsTests
|
|
632
|
-
yarn cli TestApp --appName Trading
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
```sh
|
|
636
|
-
% Coverage report from v8
|
|
637
|
-
------------------------|---------|----------|---------|---------|-------------------
|
|
638
|
-
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
639
|
-
------------------------|---------|----------|---------|---------|-------------------
|
|
640
|
-
All files | 98.83 | 80 | 80 | 98.83 |
|
|
641
|
-
Trading | 0 | 0 | 0 | 0 |
|
|
642
|
-
index.ts | 0 | 0 | 0 | 0 | 1
|
|
643
|
-
Trading/src | 100 | 100 | 100 | 100 |
|
|
644
|
-
i18n.ts | 100 | 100 | 100 | 100 |
|
|
645
|
-
manifest.ts | 100 | 100 | 100 | 100 |
|
|
646
|
-
Trading/src/ucds | 100 | 100 | 100 | 100 |
|
|
647
|
-
BuyAssetServerMain.ts | 100 | 100 | 100 | 100 |
|
|
648
|
-
BuyAssetUCD.ts | 100 | 100 | 100 | 100 |
|
|
649
|
-
------------------------|---------|----------|---------|---------|-------------------
|
|
650
|
-
2024-12-29T11:00:53.178Z [info] Coverage Report => open src/apps/Trading/test/reports/coverage/index.html
|
|
651
|
-
2024-12-29T11:00:53.178Z [info] Simple HTML Report => open src/apps/Trading/test/reports/simple-html/index.html
|
|
652
|
-
```
|
|
653
|
-
|
|
654
|
-
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.
|
|
655
|
-
|
|
656
|
-
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.
|
|
657
|
-
|
|
658
|
-
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.
|
|
659
|
-
|
|
660
|
-
<img src="/docs/assets/trading-buy-asset-sequence-diagram.png" width="600px">
|
|
661
|
-
|
|
662
|
-
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.
|
|
663
|
-
|
|
664
|
-
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.
|
|
665
|
-
|
|
666
|
-
> [!NOTE]
|
|
667
|
-
> 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.
|
|
668
|
-
|
|
669
|
-
```sh
|
|
670
|
-
yarn lint && git add . && git commit -m "test: init app tests"
|
|
671
|
-
```
|
|
672
|
-
|
|
673
|
-
### Create the Product
|
|
674
|
-
|
|
675
|
-
Like the app, the product has a `i18n.ts` and `manifest.ts`.
|
|
676
|
-
|
|
677
|
-
```sh
|
|
678
|
-
mkdir -p src/products/SuperTrader
|
|
679
|
-
touch src/products/SuperTrader/{i18n.ts,manifest.ts}
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
#### i18n.ts
|
|
683
|
-
|
|
684
|
-
```typescript
|
|
685
|
-
import type { ProductI18n } from 'libmodulor';
|
|
686
|
-
import { I18nEN } from 'libmodulor/locales/en';
|
|
687
|
-
|
|
688
|
-
import { I18n as TradingI18n } from '../../apps/Trading/index.js';
|
|
689
|
-
|
|
690
|
-
export const I18n: ProductI18n = {
|
|
691
|
-
en: {
|
|
692
|
-
...I18nEN,
|
|
693
|
-
...TradingI18n.en,
|
|
694
|
-
p_desc: 'A simple app to trade crypto, shares and other assets',
|
|
695
|
-
p_slogan: 'Trading made simple',
|
|
696
|
-
},
|
|
162
|
+
metadata: Manifest.ucReg.SignIn,
|
|
697
163
|
};
|
|
698
164
|
```
|
|
699
165
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
```typescript
|
|
703
|
-
import type { ProductManifest } from 'libmodulor';
|
|
704
|
-
|
|
705
|
-
export const Manifest: ProductManifest = {
|
|
706
|
-
appReg: [{ name: 'Trading' }],
|
|
707
|
-
name: 'SuperTrader',
|
|
708
|
-
};
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
> [!NOTE]
|
|
712
|
-
> 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.
|
|
713
|
-
|
|
714
|
-
```sh
|
|
715
|
-
yarn lint && git add . && git commit -m "feat: add the product"
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
### Create the server Target
|
|
719
|
-
|
|
720
|
-
We'll use the pre-built [express](https://expressjs.com) `ServerManager`.
|
|
721
|
-
|
|
722
|
-
```sh
|
|
723
|
-
mkdir src/products/SuperTrader/server
|
|
724
|
-
touch src/products/SuperTrader/server/{container.ts,index.ts}
|
|
725
|
-
touch tsconfig.build.json
|
|
726
|
-
touch .env
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
#### container.ts
|
|
730
|
-
|
|
731
|
-
```typescript
|
|
732
|
-
import {
|
|
733
|
-
CONTAINER_OPTS,
|
|
734
|
-
EnvSettingsManager,
|
|
735
|
-
type ServerManager,
|
|
736
|
-
type ServerManagerSettings,
|
|
737
|
-
type SettingsManager,
|
|
738
|
-
TARGET_DEFAULT_SERVER_MANAGER_SETTINGS,
|
|
739
|
-
bindCommon,
|
|
740
|
-
bindProduct,
|
|
741
|
-
} from 'libmodulor';
|
|
742
|
-
import {
|
|
743
|
-
NodeExpressServerManager,
|
|
744
|
-
bindNodeCore,
|
|
745
|
-
bindServer,
|
|
746
|
-
} from 'libmodulor/node';
|
|
747
|
-
import { Container } from 'inversify';
|
|
748
|
-
|
|
749
|
-
import { I18n } from '../i18n.js';
|
|
750
|
-
import { Manifest } from '../manifest.js';
|
|
751
|
-
|
|
752
|
-
type S = ServerManagerSettings;
|
|
753
|
-
|
|
754
|
-
const container = new Container(CONTAINER_OPTS);
|
|
755
|
-
|
|
756
|
-
bindCommon<S>(container, () => ({
|
|
757
|
-
...TARGET_DEFAULT_SERVER_MANAGER_SETTINGS,
|
|
758
|
-
}));
|
|
759
|
-
bindNodeCore(container);
|
|
760
|
-
bindServer(container);
|
|
761
|
-
bindProduct(container, Manifest, I18n);
|
|
762
|
-
|
|
763
|
-
container.rebind<SettingsManager>('SettingsManager').to(EnvSettingsManager);
|
|
764
|
-
|
|
765
|
-
container.bind<ServerManager>('ServerManager').to(NodeExpressServerManager);
|
|
766
|
-
|
|
767
|
-
export default container;
|
|
768
|
-
```
|
|
769
|
-
|
|
770
|
-
#### index.ts
|
|
771
|
-
|
|
772
|
-
```typescript
|
|
773
|
-
import {
|
|
774
|
-
APPS_ROOT_DIR_NAME,
|
|
775
|
-
type FSManager,
|
|
776
|
-
type I18nManager,
|
|
777
|
-
ServerBooter,
|
|
778
|
-
} from 'libmodulor';
|
|
779
|
-
|
|
780
|
-
import container from './container.js';
|
|
781
|
-
|
|
782
|
-
await container.get<I18nManager>('I18nManager').init();
|
|
783
|
-
|
|
784
|
-
await container.resolve(ServerBooter).exec({
|
|
785
|
-
appsRootPath: container
|
|
786
|
-
.get<FSManager>('FSManager')
|
|
787
|
-
.path('..', '..', '..', APPS_ROOT_DIR_NAME),
|
|
788
|
-
srcImporter: (path) => import(path),
|
|
789
|
-
});
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
#### tsconfig.build.json
|
|
793
|
-
|
|
794
|
-
```json
|
|
795
|
-
{
|
|
796
|
-
"extends": "./tsconfig.json",
|
|
797
|
-
"compilerOptions": {
|
|
798
|
-
"noEmit": false,
|
|
799
|
-
"outDir": "dist"
|
|
800
|
-
},
|
|
801
|
-
"include": ["src"]
|
|
802
|
-
}
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
#### .env
|
|
806
|
-
|
|
807
|
-
```properties
|
|
808
|
-
app_logger_level=trace # the default is 'debug'
|
|
809
|
-
```
|
|
166
|
+
## 🚀 Getting Started
|
|
810
167
|
|
|
811
|
-
|
|
812
|
-
> A setting named `my_setting` in the code can be overriden with an environment variable called `app_my_setting`.
|
|
813
|
-
|
|
814
|
-
#### Build & Run
|
|
815
|
-
|
|
816
|
-
Update `package.json` to add new entries to the `scripts`.
|
|
817
|
-
|
|
818
|
-
```json
|
|
819
|
-
"build": "tsc --project tsconfig.build.json && cp .env dist/products/SuperTrader/server/.env",
|
|
820
|
-
"run:server": "cd dist/products/SuperTrader/server && node --env-file .env index.js",
|
|
821
|
-
```
|
|
822
|
-
|
|
823
|
-
```sh
|
|
824
|
-
yarn build && yarn run:server
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
Et voilà ! The server is running !
|
|
828
|
-
|
|
829
|
-
```sh
|
|
830
|
-
curl -X POST -H "Content-Type: application/json" http://localhost:7443/api/v1/BuyAsset
|
|
831
|
-
# ❌ {"message":"Invalid credentials"}
|
|
832
|
-
curl -X POST -H "Content-Type: application/json" -H "X-API-Key: PublicApiKeyToBeChangedWhenDeploying" http://localhost:7443/api/v1/BuyAsset
|
|
833
|
-
# ❌ {"message":"isin must be filled"}
|
|
834
|
-
curl -X POST -H "Content-Type: application/json" -H "X-API-Key: PublicApiKeyToBeChangedWhenDeploying" -d '{"isin":"US02079K3059","limit":123.5,"qty":150}' http://localhost:7443/api/v1/BuyAsset
|
|
835
|
-
# ✅ {"parts":{"_0":{"items":[{"executedDirectly":false,"id":"95dddca5-5e9d-48ac-a90c-71a58d4e8554"}],"total":1}}}
|
|
836
|
-
```
|
|
837
|
-
|
|
838
|
-
As you can see, validation comes out of the box. Later we'll see how to add even more precise rules to the data types.
|
|
839
|
-
|
|
840
|
-
> [!NOTE]
|
|
841
|
-
> The `public_api_key` is just a first layer of security to "authenticate" the client apps calling the server. Hopefully this is not the only security mechanism because of course, this key must be present in clear client side (web, cli, curl...). We'll dive deeper in security when we study the policies.
|
|
842
|
-
|
|
843
|
-
```sh
|
|
844
|
-
yarn lint && git add . && git commit -m "feat: add the server target"
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
### Create the web Target
|
|
848
|
-
|
|
849
|
-
We'll use the pre-built [React](https://react.dev) components to build a SPA (Single Page Application), bundled with [vite](https://vite.dev) and served with the server defined above.
|
|
850
|
-
|
|
851
|
-
> [!WARNING]
|
|
852
|
-
> For readers used to "beautiful" websites à la Linear, Vercel and related, your eyes will burn. You're going to discover the simple and pure CSS-less Web. The most beautiful one.
|
|
853
|
-
> Of course, feel free to add CSS if you want to. The main goal here is to focus on the essence of the UI and not the UI design.
|
|
854
|
-
|
|
855
|
-
```sh
|
|
856
|
-
yarn add --dev "@types/react@^18.3.17" "@types/react-dom@^18.3.5"
|
|
857
|
-
yarn add "react@^18.3.1" "react-dom@^18.3.1"
|
|
858
|
-
|
|
859
|
-
mkdir -p src/products/SuperTrader/web/components
|
|
860
|
-
touch src/products/SuperTrader/vite.config.web.ts
|
|
861
|
-
touch src/products/SuperTrader/web/{container.ts,index.html,index.tsx}
|
|
862
|
-
touch src/products/SuperTrader/web/components/App.tsx
|
|
863
|
-
```
|
|
864
|
-
|
|
865
|
-
#### vite.config.web.ts
|
|
866
|
-
|
|
867
|
-
```typescript
|
|
868
|
-
import { join } from 'node:path';
|
|
869
|
-
|
|
870
|
-
import { StripUCDLifecycleServerPlugin } from 'libmodulor/vite';
|
|
871
|
-
import { defineConfig } from 'vite';
|
|
872
|
-
|
|
873
|
-
const base = process.cwd();
|
|
874
|
-
const root = join('src', 'products', 'SuperTrader', 'web');
|
|
875
|
-
const outDir = join(
|
|
876
|
-
base,
|
|
877
|
-
'dist',
|
|
878
|
-
'products',
|
|
879
|
-
'SuperTrader',
|
|
880
|
-
'server',
|
|
881
|
-
'public',
|
|
882
|
-
);
|
|
883
|
-
|
|
884
|
-
export default defineConfig({
|
|
885
|
-
build: {
|
|
886
|
-
emptyOutDir: true,
|
|
887
|
-
outDir,
|
|
888
|
-
},
|
|
889
|
-
plugins: [StripUCDLifecycleServerPlugin],
|
|
890
|
-
root,
|
|
891
|
-
});
|
|
892
|
-
```
|
|
893
|
-
|
|
894
|
-
#### container.ts
|
|
895
|
-
|
|
896
|
-
```typescript
|
|
897
|
-
import {
|
|
898
|
-
CONTAINER_OPTS,
|
|
899
|
-
type ServerClientManagerSettings,
|
|
900
|
-
TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS,
|
|
901
|
-
bindCommon,
|
|
902
|
-
bindProduct,
|
|
903
|
-
} from 'libmodulor';
|
|
904
|
-
import { bindWeb } from 'libmodulor/web';
|
|
905
|
-
import { Container } from 'inversify';
|
|
906
|
-
|
|
907
|
-
import { I18n } from '../i18n.js';
|
|
908
|
-
import { Manifest } from '../manifest.js';
|
|
909
|
-
|
|
910
|
-
type S = ServerClientManagerSettings;
|
|
911
|
-
|
|
912
|
-
const container = new Container(CONTAINER_OPTS);
|
|
913
|
-
|
|
914
|
-
bindCommon<S>(container, () => ({
|
|
915
|
-
...TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS,
|
|
916
|
-
}));
|
|
917
|
-
bindWeb(container);
|
|
918
|
-
bindProduct(container, Manifest, I18n);
|
|
919
|
-
|
|
920
|
-
export default container;
|
|
921
|
-
```
|
|
922
|
-
|
|
923
|
-
#### index.html
|
|
924
|
-
|
|
925
|
-
```html
|
|
926
|
-
<!DOCTYPE html>
|
|
927
|
-
<html lang="en">
|
|
928
|
-
<head>
|
|
929
|
-
<meta charset="utf-8" />
|
|
930
|
-
<meta content="width=device-width, initial-scale=1" name="viewport"
|
|
931
|
-
/>
|
|
932
|
-
</head>
|
|
933
|
-
<body>
|
|
934
|
-
<div id="root"></div>
|
|
935
|
-
<script type="module" src="/index.tsx"></script>
|
|
936
|
-
</body>
|
|
937
|
-
</html>
|
|
938
|
-
```
|
|
939
|
-
|
|
940
|
-
#### App.tsx
|
|
941
|
-
|
|
942
|
-
Update `src/apps/Trading/index.ts` to expose the use case.
|
|
943
|
-
|
|
944
|
-
```typescript
|
|
945
|
-
export { BuyAssetUCD } from './src/ucds/BuyAssetUCD.js';
|
|
946
|
-
```
|
|
947
|
-
|
|
948
|
-
Naturally, in real life scenarios, we would never have such a bloated `App.tsx` and we could create fine-grained components. Everybody does that, right ?
|
|
949
|
-
|
|
950
|
-
```tsx
|
|
951
|
-
import { type Logger, type ProductManifest, UCOutputReader } from 'libmodulor';
|
|
952
|
-
import {
|
|
953
|
-
UCPanel,
|
|
954
|
-
type UCPanelOnError,
|
|
955
|
-
useDIContext,
|
|
956
|
-
useUC,
|
|
957
|
-
useUCOR,
|
|
958
|
-
} from 'libmodulor/react';
|
|
959
|
-
import {
|
|
960
|
-
UCAutoExecLoader,
|
|
961
|
-
UCExecTouchable,
|
|
962
|
-
UCForm,
|
|
963
|
-
} from 'libmodulor/react-web-pure';
|
|
964
|
-
import React, { useEffect, useState, type ReactElement } from 'react';
|
|
965
|
-
|
|
966
|
-
import { BuyAssetUCD, Manifest } from '../../../../apps/Trading/index.js';
|
|
967
|
-
|
|
968
|
-
export default function App(): ReactElement {
|
|
969
|
-
const { container, i18nManager, wordingManager } = useDIContext();
|
|
970
|
-
const [logger] = useState(container.get<Logger>('Logger'));
|
|
971
|
-
const [productManifest] = useState(
|
|
972
|
-
container.get<ProductManifest>('ProductManifest'),
|
|
973
|
-
);
|
|
974
|
-
|
|
975
|
-
const [buyAssetUC] = useUC(Manifest, BuyAssetUCD, null);
|
|
976
|
-
const [buyAssetPart0, _buyAssetPart1, { append0 }] = useUCOR(
|
|
977
|
-
new UCOutputReader(BuyAssetUCD, undefined),
|
|
978
|
-
);
|
|
979
|
-
|
|
980
|
-
const [loading, setLoading] = useState(true);
|
|
981
|
-
|
|
982
|
-
useEffect(() => {
|
|
983
|
-
(async () => {
|
|
984
|
-
logger.debug('Initializing i18n');
|
|
985
|
-
await i18nManager.init();
|
|
986
|
-
logger.debug('Done initializing i18n');
|
|
987
|
-
setLoading(false);
|
|
988
|
-
})();
|
|
989
|
-
|
|
990
|
-
const { slogan } = wordingManager.p();
|
|
991
|
-
document.title = `${productManifest.name} : ${slogan}`;
|
|
992
|
-
}, [i18nManager, logger, productManifest, wordingManager]);
|
|
993
|
-
|
|
994
|
-
const onError: UCPanelOnError = async (err) => alert(err.message);
|
|
995
|
-
|
|
996
|
-
const { slogan } = wordingManager.p();
|
|
997
|
-
const { label } = wordingManager.uc(buyAssetUC.def);
|
|
998
|
-
const { label: idLabel } = wordingManager.ucof('id');
|
|
999
|
-
const { label: executedDirectlyLabel } =
|
|
1000
|
-
wordingManager.ucof('executedDirectly');
|
|
1001
|
-
|
|
1002
|
-
return (
|
|
1003
|
-
<div>
|
|
1004
|
-
{loading && 'Loading...'}
|
|
1005
|
-
|
|
1006
|
-
{!loading && (
|
|
1007
|
-
<>
|
|
1008
|
-
<h1>
|
|
1009
|
-
{productManifest.name} : {slogan}
|
|
1010
|
-
</h1>
|
|
1011
|
-
|
|
1012
|
-
<h2>{label}</h2>
|
|
1013
|
-
|
|
1014
|
-
<UCPanel
|
|
1015
|
-
clearAfterExec={false}
|
|
1016
|
-
onDone={async (ucor) => append0(ucor)}
|
|
1017
|
-
onError={onError}
|
|
1018
|
-
renderAutoExecLoader={UCAutoExecLoader}
|
|
1019
|
-
renderExecTouchable={UCExecTouchable}
|
|
1020
|
-
renderForm={UCForm}
|
|
1021
|
-
sleepInMs={200} // Fake delay to see submit wording changing
|
|
1022
|
-
uc={buyAssetUC}
|
|
1023
|
-
/>
|
|
1024
|
-
|
|
1025
|
-
<table>
|
|
1026
|
-
<thead>
|
|
1027
|
-
<tr>
|
|
1028
|
-
<th>{idLabel}</th>
|
|
1029
|
-
<th>{executedDirectlyLabel}</th>
|
|
1030
|
-
</tr>
|
|
1031
|
-
</thead>
|
|
1032
|
-
<tbody>
|
|
1033
|
-
{buyAssetPart0?.items.map((i) => (
|
|
1034
|
-
<tr key={i.id}>
|
|
1035
|
-
<td>{i.id}</td>
|
|
1036
|
-
<td>{i.executedDirectly ? '✅' : '❌'}</td>
|
|
1037
|
-
</tr>
|
|
1038
|
-
))}
|
|
1039
|
-
</tbody>
|
|
1040
|
-
<tfoot>
|
|
1041
|
-
<tr>
|
|
1042
|
-
<th>{i18nManager.t('total')}</th>
|
|
1043
|
-
<th>{buyAssetPart0?.pagination.total}</th>
|
|
1044
|
-
</tr>
|
|
1045
|
-
</tfoot>
|
|
1046
|
-
</table>
|
|
1047
|
-
</>
|
|
1048
|
-
)}
|
|
1049
|
-
</div>
|
|
1050
|
-
);
|
|
1051
|
-
}
|
|
1052
|
-
```
|
|
1053
|
-
|
|
1054
|
-
#### index.tsx
|
|
1055
|
-
|
|
1056
|
-
```typescript
|
|
1057
|
-
import { DIContextProvider } from 'libmodulor/react';
|
|
1058
|
-
import React, { StrictMode } from 'react';
|
|
1059
|
-
import ReactDOM from 'react-dom/client';
|
|
1060
|
-
|
|
1061
|
-
import App from './components/App.js';
|
|
1062
|
-
import container from './container.js';
|
|
1063
|
-
|
|
1064
|
-
const rootElt = document.getElementById('root');
|
|
1065
|
-
if (!rootElt) {
|
|
1066
|
-
throw new Error('Add a div#root in index.html');
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
ReactDOM.createRoot(rootElt).render(
|
|
1070
|
-
<StrictMode>
|
|
1071
|
-
<DIContextProvider container={container}>
|
|
1072
|
-
<App />
|
|
1073
|
-
</DIContextProvider>
|
|
1074
|
-
</StrictMode>,
|
|
1075
|
-
);
|
|
1076
|
-
```
|
|
1077
|
-
|
|
1078
|
-
#### Build & Run
|
|
1079
|
-
|
|
1080
|
-
Update `package.json` to add the `web` build to the `build` command.
|
|
1081
|
-
|
|
1082
|
-
```json
|
|
1083
|
-
"build": "tsc --project tsconfig.build.json && cp .env dist/products/SuperTrader/server/.env && vite -c src/products/SuperTrader/vite.config.web.ts build",
|
|
1084
|
-
```
|
|
1085
|
-
|
|
1086
|
-
Update `src/products/SuperTrader/server/container.ts` to mount the `public` directory.
|
|
1087
|
-
|
|
1088
|
-
```diff
|
|
1089
|
-
...TARGET_DEFAULT_SERVER_MANAGER_SETTINGS,
|
|
1090
|
-
+server_static_dir_path: 'public',
|
|
1091
|
-
```
|
|
1092
|
-
|
|
1093
|
-
Press <kbd>ctrl</kbd> + <kbd>C</kbd> to stop the server (we'll setup hot reload later).
|
|
1094
|
-
|
|
1095
|
-
```sh
|
|
1096
|
-
yarn build && yarn run:server
|
|
1097
|
-
open http://localhost:7443
|
|
1098
|
-
```
|
|
1099
|
-
|
|
1100
|
-
Et voilà ! The server is running ! Fill the form and see how it automatically submits to the server with client side and server side validation out of the box.
|
|
1101
|
-
|
|
1102
|
-
<img src="/docs/assets/trading-target-web.png" width="600px">
|
|
1103
|
-
|
|
1104
|
-
```sh
|
|
1105
|
-
yarn lint && git add . && git commit -m "feat: add the web target"
|
|
1106
|
-
```
|
|
1107
|
-
|
|
1108
|
-
### Switch to a persistent data storage
|
|
1109
|
-
|
|
1110
|
-
By default, the data is stored in memory on the server. Therefore, whenever we restart it, we lose everything. That is not very practical in real life scenarios. Let's use SQLite instead.
|
|
1111
|
-
|
|
1112
|
-
```sh
|
|
1113
|
-
yarn add "knex@^3.1.0" "sqlite3@^5.1.7"
|
|
1114
|
-
```
|
|
1115
|
-
|
|
1116
|
-
Update `src/products/SuperTrader/server/container.ts` to change the implementation.
|
|
1117
|
-
|
|
1118
|
-
```diff
|
|
1119
|
-
[...]
|
|
1120
|
-
TARGET_DEFAULT_SERVER_MANAGER_SETTINGS,
|
|
1121
|
-
+ type UCDataStore,
|
|
1122
|
-
[...]
|
|
1123
|
-
+import { KnexUCDataStore } from 'libmodulor/uc-data-store/knex';
|
|
1124
|
-
[...]
|
|
1125
|
-
+type S = KnexUCDataStoreSettings & ServerManagerSettings;
|
|
1126
|
-
[...]
|
|
1127
|
-
...TARGET_DEFAULT_SERVER_MANAGER_SETTINGS,
|
|
1128
|
-
+ knex_uc_data_store_conn_string: 'postgresql://toto',
|
|
1129
|
-
+ knex_uc_data_store_file_path: 'uc-data-store.sqlite',
|
|
1130
|
-
+ knex_uc_data_store_pool_max: 5,
|
|
1131
|
-
+ knex_uc_data_store_pool_min: 0,
|
|
1132
|
-
+ knex_uc_data_store_type: 'sqlite3',
|
|
1133
|
-
server_static_dir_path: 'public',
|
|
1134
|
-
[...]
|
|
1135
|
-
container.rebind<SettingsManager>('SettingsManager').to(EnvSettingsManager);
|
|
1136
|
-
+container.rebind<UCDataStore>('UCDataStore').to(KnexUCDataStore);
|
|
1137
|
-
```
|
|
1138
|
-
|
|
1139
|
-
Press <kbd>ctrl</kbd> + <kbd>C</kbd> to stop the server.
|
|
1140
|
-
|
|
1141
|
-
```sh
|
|
1142
|
-
yarn build && yarn run:server
|
|
1143
|
-
```
|
|
1144
|
-
|
|
1145
|
-
Fill and submit the use case multiple times.
|
|
1146
|
-
|
|
1147
|
-
Open the SQLite database with you with your favorite DB editor (e.g. TablePlus, DBeaver...).
|
|
1148
|
-
|
|
1149
|
-
```sh
|
|
1150
|
-
open dist/products/SuperTrader/server/uc-data-store.sqlite
|
|
1151
|
-
```
|
|
1152
|
-
|
|
1153
|
-
You should see all your submissions stored in the database.
|
|
1154
|
-
|
|
1155
|
-
```sh
|
|
1156
|
-
yarn lint && git add . && git commit -m "feat: persist data in SQLite"
|
|
1157
|
-
```
|
|
1158
|
-
|
|
1159
|
-
### Define wording for humans
|
|
1160
|
-
|
|
1161
|
-
By default, the UI simply "humanizes" the use case field keys. It's fine for technical people, but not for humans.
|
|
1162
|
-
|
|
1163
|
-
Update `src/apps/Trading/src/i18n.ts` and add the following keys to `en`.
|
|
1164
|
-
|
|
1165
|
-
```typescript
|
|
1166
|
-
uc_BuyAsset_label: 'Buy an asset',
|
|
1167
|
-
uc_BuyAsset_i_submit_idle: 'Send buy order',
|
|
1168
|
-
uc_BuyAsset_i_submit_submitting: 'Sending',
|
|
1169
|
-
ucif_isin_label: 'ISIN',
|
|
1170
|
-
ucif_qty_label: 'Quantity',
|
|
1171
|
-
ucof_executedDirectly_label: '🚀 Executed directly',
|
|
1172
|
-
ucof_id_label: 'Identifier',
|
|
1173
|
-
validation_format_ISIN:
|
|
1174
|
-
'Must be 2 uppercase letters, followed by 9 alphanumeric characters and 1 digit',
|
|
1175
|
-
```
|
|
1176
|
-
|
|
1177
|
-
Update `src/products/SuperTrader/i18n.ts` and add the following keys to `en`.
|
|
1178
|
-
|
|
1179
|
-
```typescript
|
|
1180
|
-
total: 'Total',
|
|
1181
|
-
```
|
|
168
|
+
Enough theory, let's dive in and learn by doing.
|
|
1182
169
|
|
|
1183
170
|
> [!NOTE]
|
|
1184
|
-
>
|
|
1185
|
-
|
|
1186
|
-
Press <kbd>ctrl</kbd> + <kbd>C</kbd> to stop the server.
|
|
1187
|
-
|
|
1188
|
-
```sh
|
|
1189
|
-
yarn build && yarn run:server
|
|
1190
|
-
```
|
|
1191
|
-
|
|
1192
|
-
Refresh the page. You should see a better wording. Try to type an invalid `ISIN` and see how the full validation message is displayed as well.
|
|
1193
|
-
|
|
1194
|
-
<img src="/docs/assets/trading-target-web-human.png" width="600px">
|
|
1195
|
-
|
|
1196
|
-
```sh
|
|
1197
|
-
yarn lint && git add . && git commit -m "feat: define wording for humans"
|
|
1198
|
-
```
|
|
1199
|
-
|
|
1200
|
-
### Create the cli Target
|
|
1201
|
-
|
|
1202
|
-
We'll use the pre-built [Node.js parseArgs](https://nodejs.org/api/util.html#utilparseargsconfig) CLI program.
|
|
1203
|
-
|
|
1204
|
-
```sh
|
|
1205
|
-
mkdir src/products/SuperTrader/cli
|
|
1206
|
-
touch src/products/SuperTrader/cli/{container.ts,index.ts}
|
|
1207
|
-
```
|
|
1208
|
-
|
|
1209
|
-
#### container.ts
|
|
1210
|
-
|
|
1211
|
-
```typescript
|
|
1212
|
-
import {
|
|
1213
|
-
CONTAINER_OPTS,
|
|
1214
|
-
type ServerClientManagerSettings,
|
|
1215
|
-
TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS,
|
|
1216
|
-
bindCommon,
|
|
1217
|
-
bindProduct,
|
|
1218
|
-
} from 'libmodulor';
|
|
1219
|
-
import { bindNodeCLI, bindNodeCore } from 'libmodulor/node';
|
|
1220
|
-
import { Container } from 'inversify';
|
|
1221
|
-
|
|
1222
|
-
import { I18n } from '../i18n.js';
|
|
1223
|
-
import { Manifest } from '../manifest.js';
|
|
1224
|
-
|
|
1225
|
-
const container = new Container(CONTAINER_OPTS);
|
|
1226
|
-
|
|
1227
|
-
bindCommon<ServerClientManagerSettings>(container, () => ({
|
|
1228
|
-
...TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS,
|
|
1229
|
-
}));
|
|
1230
|
-
bindNodeCore(container);
|
|
1231
|
-
bindNodeCLI(container);
|
|
1232
|
-
bindProduct(container, Manifest, I18n);
|
|
1233
|
-
|
|
1234
|
-
export default container;
|
|
1235
|
-
```
|
|
1236
|
-
|
|
1237
|
-
#### index.ts
|
|
1238
|
-
|
|
1239
|
-
```typescript
|
|
1240
|
-
import {
|
|
1241
|
-
APPS_ROOT_DIR_NAME,
|
|
1242
|
-
type FSManager,
|
|
1243
|
-
type I18nManager,
|
|
1244
|
-
} from 'libmodulor';
|
|
1245
|
-
import { NodeCoreCLIManager } from 'libmodulor/node';
|
|
1246
|
-
|
|
1247
|
-
import container from './container.js';
|
|
1248
|
-
|
|
1249
|
-
await container.get<I18nManager>('I18nManager').init();
|
|
1250
|
-
|
|
1251
|
-
await container.resolve(NodeCoreCLIManager).handleCommand({
|
|
1252
|
-
appsRootPath: container
|
|
1253
|
-
.get<FSManager>('FSManager')
|
|
1254
|
-
.path('..', '..', '..', APPS_ROOT_DIR_NAME),
|
|
1255
|
-
srcImporter: (path) => import(path),
|
|
1256
|
-
});
|
|
1257
|
-
```
|
|
1258
|
-
|
|
1259
|
-
#### Build & Run
|
|
1260
|
-
|
|
1261
|
-
Update `package.json` to add a new entry to the `scripts`.
|
|
1262
|
-
|
|
1263
|
-
```json
|
|
1264
|
-
"run:cli": "cd dist/products/SuperTrader/cli && node index.js",
|
|
1265
|
-
```
|
|
1266
|
-
|
|
1267
|
-
```sh
|
|
1268
|
-
yarn build && yarn run:cli
|
|
1269
|
-
```
|
|
1270
|
-
|
|
1271
|
-
You can see the CLI help appearing with the available commands.
|
|
1272
|
-
|
|
1273
|
-
> [!TIP]
|
|
1274
|
-
> Update the app's `i18n.ts` to add `uc_BuyAsset_desc` and `ucif_isin_desc` to have a more detailed help section.
|
|
1275
|
-
|
|
1276
|
-
Start the server if it's not running.
|
|
1277
|
-
|
|
1278
|
-
```sh
|
|
1279
|
-
yarn run:server
|
|
1280
|
-
```
|
|
1281
|
-
|
|
1282
|
-
Execute the CLI in another terminal or tab.
|
|
1283
|
-
|
|
1284
|
-
```sh
|
|
1285
|
-
yarn run:cli BuyAsset
|
|
1286
|
-
# ❌ ISIN must be filled
|
|
1287
|
-
yarn run:cli BuyAsset --isin US02079K3059 --limit 123.5 --qty 150
|
|
1288
|
-
# ✅ {"parts":{"_0":{"items":[{"executedDirectly":false,"id":"da3dc295-6d7c-41b1-a00a-62683f3e6ab9"}],"total":1}}}
|
|
1289
|
-
```
|
|
1290
|
-
|
|
1291
|
-
Open the SQLite database with you with your favorite DB editor (e.g. TablePlus, DBeaver...).
|
|
1292
|
-
|
|
1293
|
-
```sh
|
|
1294
|
-
open dist/products/SuperTrader/server/uc-data-store.sqlite
|
|
1295
|
-
```
|
|
1296
|
-
|
|
1297
|
-
```sh
|
|
1298
|
-
yarn lint && git add . && git commit -m "feat: add the cli target"
|
|
1299
|
-
```
|
|
1300
|
-
|
|
1301
|
-
### Create the mcp-server Target
|
|
1302
|
-
|
|
1303
|
-
We'll use the pre-built local [stdio transport](https://modelcontextprotocol.io/docs/concepts/transports#standard-input-output-stdio) server.
|
|
1304
|
-
|
|
1305
|
-
```sh
|
|
1306
|
-
yarn add "@modelcontextprotocol/sdk@^1.0.4"
|
|
1307
|
-
```
|
|
1308
|
-
|
|
1309
|
-
```sh
|
|
1310
|
-
mkdir src/products/SuperTrader/mcp-server
|
|
1311
|
-
touch src/products/SuperTrader/mcp-server/{container.ts,index.ts}
|
|
1312
|
-
```
|
|
1313
|
-
|
|
1314
|
-
#### container.ts
|
|
1315
|
-
|
|
1316
|
-
```typescript
|
|
1317
|
-
import {
|
|
1318
|
-
CONTAINER_OPTS,
|
|
1319
|
-
type ServerClientManagerSettings,
|
|
1320
|
-
type ServerManager,
|
|
1321
|
-
TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS,
|
|
1322
|
-
bindCommon,
|
|
1323
|
-
bindProduct,
|
|
1324
|
-
} from 'libmodulor';
|
|
1325
|
-
import { bindNodeCore, bindServer } from 'libmodulor/node';
|
|
1326
|
-
import { NodeLocalStdioMCPServerManager } from 'libmodulor/node-mcp';
|
|
1327
|
-
import { Container } from 'inversify';
|
|
1328
|
-
|
|
1329
|
-
import { I18n } from '../i18n.js';
|
|
1330
|
-
import { Manifest } from '../manifest.js';
|
|
1331
|
-
|
|
1332
|
-
type S = ServerClientManagerSettings;
|
|
1333
|
-
|
|
1334
|
-
const container = new Container(CONTAINER_OPTS);
|
|
1335
|
-
|
|
1336
|
-
bindCommon<S>(container, () => ({
|
|
1337
|
-
...TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS,
|
|
1338
|
-
logger_level: 'error',
|
|
1339
|
-
}));
|
|
1340
|
-
bindNodeCore(container);
|
|
1341
|
-
bindServer(container);
|
|
1342
|
-
bindProduct(container, Manifest, I18n);
|
|
1343
|
-
|
|
1344
|
-
container
|
|
1345
|
-
.bind<ServerManager>('ServerManager')
|
|
1346
|
-
.to(NodeLocalStdioMCPServerManager);
|
|
1347
|
-
|
|
1348
|
-
export default container;
|
|
1349
|
-
```
|
|
1350
|
-
|
|
1351
|
-
#### index.ts
|
|
1352
|
-
|
|
1353
|
-
```typescript
|
|
1354
|
-
import {
|
|
1355
|
-
APPS_ROOT_DIR_NAME,
|
|
1356
|
-
type FSManager,
|
|
1357
|
-
type I18nManager,
|
|
1358
|
-
} from 'libmodulor';
|
|
1359
|
-
import { MCPServerBooter } from 'libmodulor/node-mcp';
|
|
1360
|
-
|
|
1361
|
-
import container from './container.js';
|
|
171
|
+
> This Guide is voluntarily very verbose and not scripted so you can get a full overview of how things work. `npx` magic is good. But understanding what happens behind the scenes is good as well.
|
|
1362
172
|
|
|
1363
|
-
|
|
173
|
+
In this Guide, we'll init a repository (a repository can contain multiple apps and products) and create a real life application using the `libmodulor` primitives.
|
|
1364
174
|
|
|
1365
|
-
|
|
1366
|
-
appsRootPath: container
|
|
1367
|
-
.get<FSManager>('FSManager')
|
|
1368
|
-
.path('..', '..', '..', APPS_ROOT_DIR_NAME),
|
|
1369
|
-
srcImporter: (path) => import(path),
|
|
1370
|
-
});
|
|
1371
|
-
```
|
|
175
|
+
We'll build a small trading application. It will contain one `App` named `Trading`, which will contain one `UseCase` named `BuyAsset`. The `App` will be mounted in a `Product` called `SuperTrader` which will be exposed via a `server` `Target`, a `web` `Target`, a `cli` `Target` and finally, a `mcp-server` `Target`.
|
|
1372
176
|
|
|
1373
177
|
> [!NOTE]
|
|
1374
|
-
>
|
|
1375
|
-
|
|
1376
|
-
#### Claude Desktop
|
|
1377
|
-
|
|
1378
|
-
If you don't have [Claude Desktop](https://claude.ai/download) on your machine, install it.
|
|
1379
|
-
|
|
1380
|
-
The following instructions are for macOS. You might need to adapt the paths if you are using another OS.
|
|
1381
|
-
|
|
1382
|
-
Register the mcp server in Claude (make sure you adapt the absolute path to your `libmodulor-tuto` directory).
|
|
1383
|
-
|
|
1384
|
-
```sh
|
|
1385
|
-
nano ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
|
1386
|
-
```
|
|
1387
|
-
|
|
1388
|
-
```json
|
|
1389
|
-
{
|
|
1390
|
-
"mcpServers": {
|
|
1391
|
-
"libmodulor-tuto": {
|
|
1392
|
-
"command": "node",
|
|
1393
|
-
"args": [
|
|
1394
|
-
"/Users/toto/libmodulor-tuto/dist/products/SuperTrader/mcp-server/index.js"
|
|
1395
|
-
]
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
```
|
|
1400
|
-
|
|
1401
|
-
If you want to enable debugging within Claude Desktop :
|
|
1402
|
-
|
|
1403
|
-
```sh
|
|
1404
|
-
nano ~/Library/Application\ Support/Claude/developer_settings.json
|
|
1405
|
-
```
|
|
1406
|
-
|
|
1407
|
-
```json
|
|
1408
|
-
{
|
|
1409
|
-
"allowDevTools": true
|
|
1410
|
-
}
|
|
1411
|
-
```
|
|
1412
|
-
|
|
1413
|
-
To vizualize the logs :
|
|
1414
|
-
|
|
1415
|
-
```sh
|
|
1416
|
-
ls -la ~/Library/Logs/Claude
|
|
1417
|
-
tail -f ~/Library/Logs/Claude/mcp.log
|
|
1418
|
-
tail -f ~/Library/Logs/Claude/mcp-server-libmodulor-tuto.log
|
|
1419
|
-
```
|
|
1420
|
-
|
|
1421
|
-
To open the Chrome Developer Tools wihtin Claude, press <kbd>cmd</kbd> + <kbd>option</kbd> + <kbd>shift</kbd> + <kbd>I</kbd> (should be easy if you're an emacs user).
|
|
1422
|
-
|
|
1423
|
-
#### Build & Run
|
|
1424
|
-
|
|
1425
|
-
Press <kbd>ctrl</kbd> + <kbd>C</kbd> to stop the server.
|
|
1426
|
-
|
|
1427
|
-
```sh
|
|
1428
|
-
yarn build && yarn run:server
|
|
1429
|
-
```
|
|
1430
|
-
|
|
1431
|
-
Launch Claude Desktop.
|
|
1432
|
-
|
|
1433
|
-
At the bottom right of the prompt you should see a little hammer 🔨 indicating `1 MCP Tool available`.
|
|
1434
|
-
|
|
1435
|
-
Click on it. You should see the `BuyAsset` use case registered.
|
|
1436
|
-
|
|
1437
|
-
Now just write a prompt like below :
|
|
1438
|
-
|
|
1439
|
-
```txt
|
|
1440
|
-
Dear Claude. Please buy 150 shares of Google.
|
|
1441
|
-
```
|
|
1442
|
-
|
|
1443
|
-
And let the magic happens.
|
|
1444
|
-
|
|
1445
|
-
<img src="/docs/assets/trading-target-mcp-server.png" width="600px">
|
|
1446
|
-
|
|
1447
|
-
Open the SQLite database with you with your favorite DB editor (e.g. TablePlus, DBeaver...).
|
|
1448
|
-
|
|
1449
|
-
```sh
|
|
1450
|
-
open dist/products/SuperTrader/server/uc-data-store.sqlite
|
|
1451
|
-
```
|
|
1452
|
-
|
|
1453
|
-
```sh
|
|
1454
|
-
yarn lint && git add . && git commit -m "feat: add the mcp-server target"
|
|
1455
|
-
```
|
|
1456
|
-
|
|
1457
|
-
### Summary
|
|
178
|
+
> MCP stands for [Model Context Protocol](https://modelcontextprotocol.io) introduced recently by [@anthropics](https://github.com/anthropics).
|
|
1458
179
|
|
|
1459
|
-
|
|
1460
|
-
git log --oneline
|
|
1461
|
-
```
|
|
180
|
+
If we adapt the abstract mermaid chart displayed above, concretely, it looks like this :
|
|
1462
181
|
|
|
1463
|
-
```
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
182
|
+
```mermaid
|
|
183
|
+
block-beta
|
|
184
|
+
server
|
|
185
|
+
web
|
|
186
|
+
cli
|
|
187
|
+
mcp_server
|
|
188
|
+
columns 4
|
|
189
|
+
SuperTrader:4
|
|
190
|
+
Trading:2
|
|
191
|
+
Auth:2
|
|
192
|
+
BuyAsset
|
|
193
|
+
ListOrders
|
|
194
|
+
SignUp
|
|
195
|
+
SignIn
|
|
1475
196
|
```
|
|
1476
197
|
|
|
1477
|
-
|
|
198
|
+
_If you're not seeing the mermaid chart (e.g. on npm), head to GitHub._
|
|
1478
199
|
|
|
1479
|
-
|
|
200
|
+
Please note that we'll only develop one use case to keep the Guide straightforward but you'll quickly get the idea to develop all the others by yourself.
|
|
1480
201
|
|
|
1481
|
-
|
|
202
|
+
Here are the steps we're going to follow. Don't worry. Even though it seems a lot, it will be super quick, efficient and straight to the point.
|
|
1482
203
|
|
|
1483
|
-
|
|
204
|
+
1. [Create the project](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/001_Create_the_project.md)
|
|
205
|
+
1. [Create the App](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/002_Create_the_App.md)
|
|
206
|
+
1. [Create the UseCase](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/003_Create_the_UseCase.md)
|
|
207
|
+
1. [Test the App](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/004_Test_the_App.md)
|
|
208
|
+
1. [Create the Product](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/005_Create_the_Product.md)
|
|
209
|
+
1. [Create the server Target](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/006_Create_the_server_Target.md)
|
|
210
|
+
1. [Create the web Target](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/007_Create_the_web_Target.md)
|
|
211
|
+
1. [Switch to a persistent data storage](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/008_Switch_to_a_persistent_data_storage.md)
|
|
212
|
+
1. [Define wording for humans](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/009_Define_wording_for_humans.md)
|
|
213
|
+
1. [Create the cli Target](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/010_Create_the_cli_Target.md)
|
|
214
|
+
1. [Create the mcp-server Target](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/011_Create_the_mcp_server_Target.md)
|
|
215
|
+
1. [Summary](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/012_Summary.md)
|
|
1484
216
|
|
|
1485
|
-
|
|
217
|
+
Let's go with the first step : [Create the project](https://github.com/c100k/libmodulor/blob/v0.3.0/docs/getting-started/001_Create_the_project.md).
|