jopijs 0.0.1
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/README.md +134 -0
- package/bin/jopib.js +4 -0
- package/bin/jopin.js +4 -0
- package/dist/@bundler/_logs.d.ts +2 -0
- package/dist/@bundler/_logs.js +4 -0
- package/dist/@bundler/_logs.js.map +1 -0
- package/dist/@bundler/core.d.ts +1 -0
- package/dist/@bundler/core.js +34 -0
- package/dist/@bundler/core.js.map +1 -0
- package/dist/@bundler/esbuild.d.ts +6 -0
- package/dist/@bundler/esbuild.js +111 -0
- package/dist/@bundler/esbuild.js.map +1 -0
- package/dist/@bundler/index.d.ts +2 -0
- package/dist/@bundler/index.js +3 -0
- package/dist/@bundler/index.js.map +1 -0
- package/dist/@bundler/plugins.d.ts +13 -0
- package/dist/@bundler/plugins.js +145 -0
- package/dist/@bundler/plugins.js.map +1 -0
- package/dist/@bundler/tailwind.d.ts +3 -0
- package/dist/@bundler/tailwind.js +119 -0
- package/dist/@bundler/tailwind.js.map +1 -0
- package/dist/@core/PageComponent.d.ts +6 -0
- package/dist/@core/PageComponent.js +10 -0
- package/dist/@core/PageComponent.js.map +1 -0
- package/dist/@core/_logs.d.ts +7 -0
- package/dist/@core/_logs.js +9 -0
- package/dist/@core/_logs.js.map +1 -0
- package/dist/@core/automaticStartStop.d.ts +25 -0
- package/dist/@core/automaticStartStop.js +106 -0
- package/dist/@core/automaticStartStop.js.map +1 -0
- package/dist/@core/browserCacheControl.d.ts +21 -0
- package/dist/@core/browserCacheControl.js +17 -0
- package/dist/@core/browserCacheControl.js.map +1 -0
- package/dist/@core/bundler/bundler.d.ts +22 -0
- package/dist/@core/bundler/bundler.js +90 -0
- package/dist/@core/bundler/bundler.js.map +1 -0
- package/dist/@core/bundler/common.d.ts +2 -0
- package/dist/@core/bundler/common.js +17 -0
- package/dist/@core/bundler/common.js.map +1 -0
- package/dist/@core/bundler/config.d.ts +20 -0
- package/dist/@core/bundler/config.js +11 -0
- package/dist/@core/bundler/config.js.map +1 -0
- package/dist/@core/bundler/extraContent.d.ts +6 -0
- package/dist/@core/bundler/extraContent.js +27 -0
- package/dist/@core/bundler/extraContent.js.map +1 -0
- package/dist/@core/bundler/pagesGenerator.d.ts +1 -0
- package/dist/@core/bundler/pagesGenerator.js +173 -0
- package/dist/@core/bundler/pagesGenerator.js.map +1 -0
- package/dist/@core/bundler/server.d.ts +8 -0
- package/dist/@core/bundler/server.js +35 -0
- package/dist/@core/bundler/server.js.map +1 -0
- package/dist/@core/caches/InMemoryCache.d.ts +35 -0
- package/dist/@core/caches/InMemoryCache.js +353 -0
- package/dist/@core/caches/InMemoryCache.js.map +1 -0
- package/dist/@core/caches/SimpleFileCache.d.ts +18 -0
- package/dist/@core/caches/SimpleFileCache.js +171 -0
- package/dist/@core/caches/SimpleFileCache.js.map +1 -0
- package/dist/@core/caches/cache.d.ts +36 -0
- package/dist/@core/caches/cache.js +33 -0
- package/dist/@core/caches/cache.js.map +1 -0
- package/dist/@core/caches/webSiteMirrorCache.d.ts +16 -0
- package/dist/@core/caches/webSiteMirrorCache.js +81 -0
- package/dist/@core/caches/webSiteMirrorCache.js.map +1 -0
- package/dist/@core/gzip.d.ts +4 -0
- package/dist/@core/gzip.js +31 -0
- package/dist/@core/gzip.js.map +1 -0
- package/dist/@core/index.d.ts +18 -0
- package/dist/@core/index.js +19 -0
- package/dist/@core/index.js.map +1 -0
- package/dist/@core/internalTools.d.ts +14 -0
- package/dist/@core/internalTools.js +79 -0
- package/dist/@core/internalTools.js.map +1 -0
- package/dist/@core/jQuery.d.ts +5 -0
- package/dist/@core/jQuery.js +18 -0
- package/dist/@core/jQuery.js.map +1 -0
- package/dist/@core/jopiEasy.d.ts +287 -0
- package/dist/@core/jopiEasy.js +983 -0
- package/dist/@core/jopiEasy.js.map +1 -0
- package/dist/@core/jopiRequest.d.ts +269 -0
- package/dist/@core/jopiRequest.js +1060 -0
- package/dist/@core/jopiRequest.js.map +1 -0
- package/dist/@core/jopiServer.d.ts +77 -0
- package/dist/@core/jopiServer.js +100 -0
- package/dist/@core/jopiServer.js.map +1 -0
- package/dist/@core/jopiWebSite.d.ts +319 -0
- package/dist/@core/jopiWebSite.js +653 -0
- package/dist/@core/jopiWebSite.js.map +1 -0
- package/dist/@core/letsEncrypt.d.ts +25 -0
- package/dist/@core/letsEncrypt.js +189 -0
- package/dist/@core/letsEncrypt.js.map +1 -0
- package/dist/@core/linker.d.ts +4 -0
- package/dist/@core/linker.js +37 -0
- package/dist/@core/linker.js.map +1 -0
- package/dist/@core/loadBalancing.d.ts +18 -0
- package/dist/@core/loadBalancing.js +126 -0
- package/dist/@core/loadBalancing.js.map +1 -0
- package/dist/@core/middlewares/CorsMiddleware.d.ts +5 -0
- package/dist/@core/middlewares/CorsMiddleware.js +15 -0
- package/dist/@core/middlewares/CorsMiddleware.js.map +1 -0
- package/dist/@core/middlewares/DdosProtection.d.ts +42 -0
- package/dist/@core/middlewares/DdosProtection.js +62 -0
- package/dist/@core/middlewares/DdosProtection.js.map +1 -0
- package/dist/@core/middlewares/index.d.ts +10 -0
- package/dist/@core/middlewares/index.js +14 -0
- package/dist/@core/middlewares/index.js.map +1 -0
- package/dist/@core/publicTools.d.ts +8 -0
- package/dist/@core/publicTools.js +11 -0
- package/dist/@core/publicTools.js.map +1 -0
- package/dist/@core/routeConfig.d.ts +48 -0
- package/dist/@core/routeConfig.js +102 -0
- package/dist/@core/routeConfig.js.map +1 -0
- package/dist/@core/searchParamFilter.d.ts +70 -0
- package/dist/@core/searchParamFilter.js +212 -0
- package/dist/@core/searchParamFilter.js.map +1 -0
- package/dist/@core/serverFetch.d.ts +122 -0
- package/dist/@core/serverFetch.js +312 -0
- package/dist/@core/serverFetch.js.map +1 -0
- package/dist/@core/serverImpl/server_bunjs.d.ts +29 -0
- package/dist/@core/serverImpl/server_bunjs.js +180 -0
- package/dist/@core/serverImpl/server_bunjs.js.map +1 -0
- package/dist/@core/serverImpl/server_nodejs.d.ts +22 -0
- package/dist/@core/serverImpl/server_nodejs.js +235 -0
- package/dist/@core/serverImpl/server_nodejs.js.map +1 -0
- package/dist/@core/serverInstanceBuilder.d.ts +17 -0
- package/dist/@core/serverInstanceBuilder.js +14 -0
- package/dist/@core/serverInstanceBuilder.js.map +1 -0
- package/dist/@core/userStores.d.ts +13 -0
- package/dist/@core/userStores.js +20 -0
- package/dist/@core/userStores.js.map +1 -0
- package/dist/@crawler/common.d.ts +203 -0
- package/dist/@crawler/common.js +68 -0
- package/dist/@crawler/common.js.map +1 -0
- package/dist/@crawler/core.d.ts +87 -0
- package/dist/@crawler/core.js +586 -0
- package/dist/@crawler/core.js.map +1 -0
- package/dist/@crawler/directFileCache.d.ts +10 -0
- package/dist/@crawler/directFileCache.js +60 -0
- package/dist/@crawler/directFileCache.js.map +1 -0
- package/dist/@crawler/index.d.ts +4 -0
- package/dist/@crawler/index.js +5 -0
- package/dist/@crawler/index.js.map +1 -0
- package/dist/@crawler/urlMapping.d.ts +21 -0
- package/dist/@crawler/urlMapping.js +52 -0
- package/dist/@crawler/urlMapping.js.map +1 -0
- package/dist/@crawler/utils.d.ts +6 -0
- package/dist/@crawler/utils.js +13 -0
- package/dist/@crawler/utils.js.map +1 -0
- package/dist/@generated/index.d.ts +29 -0
- package/dist/@generated/index.js +93 -0
- package/dist/@generated/index.js.map +1 -0
- package/dist/@linker/arobaseTypes.d.ts +50 -0
- package/dist/@linker/arobaseTypes.js +235 -0
- package/dist/@linker/arobaseTypes.js.map +1 -0
- package/dist/@linker/changeProof.d.ts +5 -0
- package/dist/@linker/changeProof.js +50 -0
- package/dist/@linker/changeProof.js.map +1 -0
- package/dist/@linker/config.d.ts +2 -0
- package/dist/@linker/config.js +40 -0
- package/dist/@linker/config.js.map +1 -0
- package/dist/@linker/engine.d.ts +156 -0
- package/dist/@linker/engine.js +665 -0
- package/dist/@linker/engine.js.map +1 -0
- package/dist/@linker/index.d.ts +3 -0
- package/dist/@linker/index.js +4 -0
- package/dist/@linker/index.js.map +1 -0
- package/dist/@linker/install.d.ts +4 -0
- package/dist/@linker/install.js +42 -0
- package/dist/@linker/install.js.map +1 -0
- package/dist/@linker/modInstaller.d.ts +10 -0
- package/dist/@linker/modInstaller.js +38 -0
- package/dist/@linker/modInstaller.js.map +1 -0
- package/dist/@linker/typeEvents.d.ts +9 -0
- package/dist/@linker/typeEvents.js +48 -0
- package/dist/@linker/typeEvents.js.map +1 -0
- package/dist/@linker/typeRoutes.d.ts +23 -0
- package/dist/@linker/typeRoutes.js +197 -0
- package/dist/@linker/typeRoutes.js.map +1 -0
- package/dist/@linker/typeUiComposite.d.ts +6 -0
- package/dist/@linker/typeUiComposite.js +16 -0
- package/dist/@linker/typeUiComposite.js.map +1 -0
- package/dist/@loader/index.d.ts +1 -0
- package/dist/@loader/index.js +17 -0
- package/dist/@loader/index.js.map +1 -0
- package/dist/@loader/nodeJsLoader.d.ts +2 -0
- package/dist/@loader/nodeJsLoader.js +19 -0
- package/dist/@loader/nodeJsLoader.js.map +1 -0
- package/dist/@loader-client/index.d.ts +33 -0
- package/dist/@loader-client/index.js +98 -0
- package/dist/@loader-client/index.js.map +1 -0
- package/dist/@loader-tools/bunJsLoader.d.ts +1 -0
- package/dist/@loader-tools/bunJsLoader.js +28 -0
- package/dist/@loader-tools/bunJsLoader.js.map +1 -0
- package/dist/@loader-tools/config.d.ts +49 -0
- package/dist/@loader-tools/config.js +79 -0
- package/dist/@loader-tools/config.js.map +1 -0
- package/dist/@loader-tools/cssModuleCompiler.d.ts +5 -0
- package/dist/@loader-tools/cssModuleCompiler.js +65 -0
- package/dist/@loader-tools/cssModuleCompiler.js.map +1 -0
- package/dist/@loader-tools/esBuildPlugin.d.ts +5 -0
- package/dist/@loader-tools/esBuildPlugin.js +113 -0
- package/dist/@loader-tools/esBuildPlugin.js.map +1 -0
- package/dist/@loader-tools/index.d.ts +9 -0
- package/dist/@loader-tools/index.js +10 -0
- package/dist/@loader-tools/index.js.map +1 -0
- package/dist/@loader-tools/jopin.d.ts +10 -0
- package/dist/@loader-tools/jopin.js +331 -0
- package/dist/@loader-tools/jopin.js.map +1 -0
- package/dist/@loader-tools/nodeJsLoader.d.ts +13 -0
- package/dist/@loader-tools/nodeJsLoader.js +101 -0
- package/dist/@loader-tools/nodeJsLoader.js.map +1 -0
- package/dist/@loader-tools/nodeJsResolver.d.ts +2 -0
- package/dist/@loader-tools/nodeJsResolver.js +117 -0
- package/dist/@loader-tools/nodeJsResolver.js.map +1 -0
- package/dist/@loader-tools/rules.d.ts +3 -0
- package/dist/@loader-tools/rules.js +33 -0
- package/dist/@loader-tools/rules.js.map +1 -0
- package/dist/@loader-tools/sourceChangesWatcher.d.ts +39 -0
- package/dist/@loader-tools/sourceChangesWatcher.js +182 -0
- package/dist/@loader-tools/sourceChangesWatcher.js.map +1 -0
- package/dist/@loader-tools/tools.d.ts +21 -0
- package/dist/@loader-tools/tools.js +113 -0
- package/dist/@loader-tools/tools.js.map +1 -0
- package/dist/@loader-tools/transform.d.ts +5 -0
- package/dist/@loader-tools/transform.js +114 -0
- package/dist/@loader-tools/transform.js.map +1 -0
- package/dist/@loader-tools/virtualUrl.d.ts +9 -0
- package/dist/@loader-tools/virtualUrl.js +40 -0
- package/dist/@loader-tools/virtualUrl.js.map +1 -0
- package/dist/@tool-jopinb/index.d.ts +1 -0
- package/dist/@tool-jopinb/index.js +9 -0
- package/dist/@tool-jopinb/index.js.map +1 -0
- package/dist/@ui/components.d.ts +27 -0
- package/dist/@ui/components.js +42 -0
- package/dist/@ui/components.js.map +1 -0
- package/dist/@ui/cssModules.d.ts +11 -0
- package/dist/@ui/cssModules.js +17 -0
- package/dist/@ui/cssModules.js.map +1 -0
- package/dist/@ui/hooks.d.ts +31 -0
- package/dist/@ui/hooks.js +71 -0
- package/dist/@ui/hooks.js.map +1 -0
- package/dist/@ui/index.d.ts +9 -0
- package/dist/@ui/index.js +11 -0
- package/dist/@ui/index.js.map +1 -0
- package/dist/@ui/internal.d.ts +4 -0
- package/dist/@ui/internal.js +10 -0
- package/dist/@ui/internal.js.map +1 -0
- package/dist/@ui/modules.d.ts +41 -0
- package/dist/@ui/modules.js +74 -0
- package/dist/@ui/modules.js.map +1 -0
- package/dist/@ui/objectRegistry.d.ts +12 -0
- package/dist/@ui/objectRegistry.js +35 -0
- package/dist/@ui/objectRegistry.js.map +1 -0
- package/dist/@ui/pageController.d.ts +61 -0
- package/dist/@ui/pageController.js +166 -0
- package/dist/@ui/pageController.js.map +1 -0
- package/dist/@ui/tools.d.ts +24 -0
- package/dist/@ui/tools.js +78 -0
- package/dist/@ui/tools.js.map +1 -0
- package/dist/@uikit/core/UiKitModule.d.ts +6 -0
- package/dist/@uikit/core/UiKitModule.js +18 -0
- package/dist/@uikit/core/UiKitModule.js.map +1 -0
- package/dist/@uikit/core/index.d.ts +1 -0
- package/dist/@uikit/core/index.js +4 -0
- package/dist/@uikit/core/index.js.map +1 -0
- package/dist/@uikit/core/jBundler_ifBrowser.d.ts +1 -0
- package/dist/@uikit/core/jBundler_ifBrowser.js +5 -0
- package/dist/@uikit/core/jBundler_ifBrowser.js.map +1 -0
- package/dist/@uikit/core/jBundler_ifServer.d.ts +6 -0
- package/dist/@uikit/core/jBundler_ifServer.js +17 -0
- package/dist/@uikit/core/jBundler_ifServer.js.map +1 -0
- package/dist/@uikit/forms/components.d.ts +18 -0
- package/dist/@uikit/forms/components.js +69 -0
- package/dist/@uikit/forms/components.js.map +1 -0
- package/dist/@uikit/forms/hooks.d.ts +4 -0
- package/dist/@uikit/forms/hooks.js +31 -0
- package/dist/@uikit/forms/hooks.js.map +1 -0
- package/dist/@uikit/forms/index.d.ts +3 -0
- package/dist/@uikit/forms/index.js +4 -0
- package/dist/@uikit/forms/index.js.map +1 -0
- package/dist/@uikit/forms/interfaces.d.ts +101 -0
- package/dist/@uikit/forms/interfaces.js +4 -0
- package/dist/@uikit/forms/interfaces.js.map +1 -0
- package/dist/@uikit/forms/private.d.ts +40 -0
- package/dist/@uikit/forms/private.js +307 -0
- package/dist/@uikit/forms/private.js.map +1 -0
- package/dist/@uikit/helpers/hooks.d.ts +33 -0
- package/dist/@uikit/helpers/hooks.js +107 -0
- package/dist/@uikit/helpers/hooks.js.map +1 -0
- package/dist/@uikit/helpers/index.d.ts +2 -0
- package/dist/@uikit/helpers/index.js +3 -0
- package/dist/@uikit/helpers/index.js.map +1 -0
- package/dist/@uikit/helpers/tools.d.ts +8 -0
- package/dist/@uikit/helpers/tools.js +35 -0
- package/dist/@uikit/helpers/tools.js.map +1 -0
- package/dist/@uikit/index.d.ts +10 -0
- package/dist/@uikit/index.js +13 -0
- package/dist/@uikit/index.js.map +1 -0
- package/dist/@uikit/menu/core.d.ts +21 -0
- package/dist/@uikit/menu/core.js +191 -0
- package/dist/@uikit/menu/core.js.map +1 -0
- package/dist/@uikit/menu/hooks.d.ts +5 -0
- package/dist/@uikit/menu/hooks.js +24 -0
- package/dist/@uikit/menu/hooks.js.map +1 -0
- package/dist/@uikit/menu/index.d.ts +3 -0
- package/dist/@uikit/menu/index.js +4 -0
- package/dist/@uikit/menu/index.js.map +1 -0
- package/dist/@uikit/menu/interfaces.d.ts +20 -0
- package/dist/@uikit/menu/interfaces.js +8 -0
- package/dist/@uikit/menu/interfaces.js.map +1 -0
- package/dist/@uikit/menu/internal.d.ts +40 -0
- package/dist/@uikit/menu/internal.js +191 -0
- package/dist/@uikit/menu/internal.js.map +1 -0
- package/dist/@uikit/reactRouter/hooks/jBundler_ifBrowser.d.ts +18 -0
- package/dist/@uikit/reactRouter/hooks/jBundler_ifBrowser.js +40 -0
- package/dist/@uikit/reactRouter/hooks/jBundler_ifBrowser.js.map +1 -0
- package/dist/@uikit/reactRouter/hooks/jBundler_ifServer.d.ts +28 -0
- package/dist/@uikit/reactRouter/hooks/jBundler_ifServer.js +35 -0
- package/dist/@uikit/reactRouter/hooks/jBundler_ifServer.js.map +1 -0
- package/dist/@uikit/reactRouter/index.d.ts +1 -0
- package/dist/@uikit/reactRouter/index.js +2 -0
- package/dist/@uikit/reactRouter/index.js.map +1 -0
- package/dist/@uikit/users/hooks.d.ts +10 -0
- package/dist/@uikit/users/hooks.js +39 -0
- package/dist/@uikit/users/hooks.js.map +1 -0
- package/dist/@uikit/users/index.d.ts +1 -0
- package/dist/@uikit/users/index.js +2 -0
- package/dist/@uikit/users/index.js.map +1 -0
- package/dist/@uikit/variants/index.d.ts +7 -0
- package/dist/@uikit/variants/index.js +16 -0
- package/dist/@uikit/variants/index.js.map +1 -0
- package/package.json +115 -0
- package/src/@bundler/README.md +1 -0
- package/src/@bundler/_logs.ts +4 -0
- package/src/@bundler/core.ts +41 -0
- package/src/@bundler/esbuild.ts +141 -0
- package/src/@bundler/index.ts +3 -0
- package/src/@bundler/plugins.ts +163 -0
- package/src/@bundler/tailwind.ts +139 -0
- package/src/@core/PageComponent.tsx +25 -0
- package/src/@core/README.md +1 -0
- package/src/@core/_logs.ts +11 -0
- package/src/@core/automaticStartStop.ts +132 -0
- package/src/@core/browserCacheControl.ts +40 -0
- package/src/@core/bundler/bundler.ts +128 -0
- package/src/@core/bundler/common.ts +18 -0
- package/src/@core/bundler/config.ts +37 -0
- package/src/@core/bundler/extraContent.ts +30 -0
- package/src/@core/bundler/pagesGenerator.ts +194 -0
- package/src/@core/bundler/server.ts +41 -0
- package/src/@core/caches/InMemoryCache.ts +483 -0
- package/src/@core/caches/SimpleFileCache.ts +205 -0
- package/src/@core/caches/cache.ts +77 -0
- package/src/@core/caches/webSiteMirrorCache.ts +90 -0
- package/src/@core/cheerio.d.ts +332 -0
- package/src/@core/gzip.ts +33 -0
- package/src/@core/index.ts +23 -0
- package/src/@core/internalTools.ts +95 -0
- package/src/@core/jQuery.ts +22 -0
- package/src/@core/jopiEasy.ts +1285 -0
- package/src/@core/jopiRequest.tsx +1279 -0
- package/src/@core/jopiServer.ts +188 -0
- package/src/@core/jopiWebSite.tsx +1027 -0
- package/src/@core/letsEncrypt.ts +243 -0
- package/src/@core/linker.ts +42 -0
- package/src/@core/loadBalancing.ts +152 -0
- package/src/@core/middlewares/CorsMiddleware.ts +23 -0
- package/src/@core/middlewares/DdosProtection.ts +120 -0
- package/src/@core/middlewares/index.ts +16 -0
- package/src/@core/publicTools.ts +14 -0
- package/src/@core/routeConfig.ts +104 -0
- package/src/@core/searchParamFilter.ts +315 -0
- package/src/@core/serverFetch.ts +454 -0
- package/src/@core/serverImpl/server_bunjs.tsx +230 -0
- package/src/@core/serverImpl/server_nodejs.ts +312 -0
- package/src/@core/serverInstanceBuilder.ts +36 -0
- package/src/@core/userStores.ts +34 -0
- package/src/@crawler/README.md +1 -0
- package/src/@crawler/common.ts +275 -0
- package/src/@crawler/core.ts +678 -0
- package/src/@crawler/directFileCache.ts +69 -0
- package/src/@crawler/index.ts +4 -0
- package/src/@crawler/urlMapping.ts +67 -0
- package/src/@crawler/utils.ts +13 -0
- package/src/@generated/index.ts +134 -0
- package/src/@linker/arobaseTypes.ts +325 -0
- package/src/@linker/changeProof.ts +53 -0
- package/src/@linker/config.ts +46 -0
- package/src/@linker/engine.ts +865 -0
- package/src/@linker/index.ts +3 -0
- package/src/@linker/install.ts +39 -0
- package/src/@linker/modInstaller.ts +50 -0
- package/src/@linker/typeEvents.ts +58 -0
- package/src/@linker/typeRoutes.ts +255 -0
- package/src/@linker/typeUiComposite.ts +19 -0
- package/src/@loader/README.md +4 -0
- package/src/@loader/bunHtmlCompiler.mjs +27 -0
- package/src/@loader/index.ts +19 -0
- package/src/@loader/loader.mjs +7 -0
- package/src/@loader/nodeJsLoader.ts +21 -0
- package/src/@loader-client/README.md +2 -0
- package/src/@loader-client/index.ts +108 -0
- package/src/@loader-tools/README.md +6 -0
- package/src/@loader-tools/bunJsLoader.ts +33 -0
- package/src/@loader-tools/config.ts +142 -0
- package/src/@loader-tools/cssModuleCompiler.ts +76 -0
- package/src/@loader-tools/esBuildPlugin.ts +142 -0
- package/src/@loader-tools/index.ts +11 -0
- package/src/@loader-tools/jopin.ts +403 -0
- package/src/@loader-tools/nodeJsLoader.ts +119 -0
- package/src/@loader-tools/nodeJsResolver.ts +140 -0
- package/src/@loader-tools/rules.ts +45 -0
- package/src/@loader-tools/sourceChangesWatcher.ts +225 -0
- package/src/@loader-tools/tools.ts +139 -0
- package/src/@loader-tools/transform.ts +138 -0
- package/src/@loader-tools/virtualUrl.ts +57 -0
- package/src/@loader-types/README.md +15 -0
- package/src/@loader-types/extensions.d.ts +65 -0
- package/src/@tool-jopinb/README.md +1 -0
- package/src/@tool-jopinb/index.ts +11 -0
- package/src/@ui/README.md +3 -0
- package/src/@ui/components.tsx +49 -0
- package/src/@ui/cssModules.tsx +27 -0
- package/src/@ui/hooks.tsx +95 -0
- package/src/@ui/index.ts +13 -0
- package/src/@ui/internal.ts +12 -0
- package/src/@ui/modules.ts +100 -0
- package/src/@ui/objectRegistry.ts +50 -0
- package/src/@ui/pageController.ts +203 -0
- package/src/@ui/tools.ts +116 -0
- package/src/@uikit/README.md +1 -0
- package/src/@uikit/core/UiKitModule.ts +20 -0
- package/src/@uikit/core/index.ts +4 -0
- package/src/@uikit/core/jBundler_ifBrowser.ts +4 -0
- package/src/@uikit/core/jBundler_ifServer.ts +18 -0
- package/src/@uikit/forms/components.tsx +97 -0
- package/src/@uikit/forms/hooks.ts +38 -0
- package/src/@uikit/forms/index.ts +3 -0
- package/src/@uikit/forms/interfaces.ts +159 -0
- package/src/@uikit/forms/private.ts +365 -0
- package/src/@uikit/helpers/hooks.ts +133 -0
- package/src/@uikit/helpers/index.ts +2 -0
- package/src/@uikit/helpers/tools.ts +39 -0
- package/src/@uikit/index.ts +15 -0
- package/src/@uikit/menu/core.ts +227 -0
- package/src/@uikit/menu/hooks.ts +28 -0
- package/src/@uikit/menu/index.ts +3 -0
- package/src/@uikit/menu/interfaces.ts +26 -0
- package/src/@uikit/menu/internal.ts +218 -0
- package/src/@uikit/package.json +15 -0
- package/src/@uikit/reactRouter/hooks/jBundler_ifBrowser.tsx +59 -0
- package/src/@uikit/reactRouter/hooks/jBundler_ifServer.tsx +51 -0
- package/src/@uikit/reactRouter/index.ts +1 -0
- package/src/@uikit/users/hooks.ts +50 -0
- package/src/@uikit/users/index.ts +1 -0
- package/src/@uikit/variants/index.tsx +20 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import * as acme from 'acme-client';
|
|
2
|
+
import {type SslCertificatePath, type WebSite, WebSiteImpl} from "./jopiWebSite.tsx";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import * as jk_timer from "jopi-toolkit/jk_timer";
|
|
5
|
+
import * as jk_fs from "jopi-toolkit/jk_fs";
|
|
6
|
+
|
|
7
|
+
export type OnTimeoutError = (webSite: WebSite, isRenew: boolean) => void;
|
|
8
|
+
|
|
9
|
+
export interface LetsEncryptParams {
|
|
10
|
+
email: string;
|
|
11
|
+
|
|
12
|
+
certificateDir?: string;
|
|
13
|
+
|
|
14
|
+
log?: boolean;
|
|
15
|
+
isProduction?: boolean;
|
|
16
|
+
forceRenew?: boolean;
|
|
17
|
+
|
|
18
|
+
expireAfter_days?: number;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Allow stopping if the certificate isn't renewed after this delay.
|
|
22
|
+
* Will to an error with error.code="TIME_OUT".
|
|
23
|
+
*/
|
|
24
|
+
timout_sec?: number;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Is called if there is an error.
|
|
28
|
+
*/
|
|
29
|
+
onTimeoutError?: OnTimeoutError;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
enum CertificateState {
|
|
33
|
+
DontExist, IsExpired, IsOk
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function getCertificateState(certPaths: SslCertificatePath, params: LetsEncryptParams): Promise<CertificateState> {
|
|
37
|
+
if (!await jk_fs.isFile(certPaths.cert)) return CertificateState.DontExist;
|
|
38
|
+
if (!await jk_fs.isFile(certPaths.key)) return CertificateState.DontExist;
|
|
39
|
+
|
|
40
|
+
let proofFile = path.join(path.dirname(certPaths.cert), "_updateDate.txt");
|
|
41
|
+
if (!await jk_fs.isFile(proofFile)) return CertificateState.DontExist;
|
|
42
|
+
|
|
43
|
+
// Using a file allows copying/paste the file or store it in GitHub.
|
|
44
|
+
// It's better than checking his update date.
|
|
45
|
+
//
|
|
46
|
+
const sDate = await jk_fs.readTextFromFile(proofFile);
|
|
47
|
+
if (!sDate) return CertificateState.DontExist;
|
|
48
|
+
|
|
49
|
+
const now = new Date();
|
|
50
|
+
let updateDate = parseInt(sDate);
|
|
51
|
+
const diffDays = (now.getTime() - updateDate) / (1000 * 60 * 60 * 24);
|
|
52
|
+
|
|
53
|
+
if (diffDays > params.expireAfter_days!) {
|
|
54
|
+
return CertificateState.IsExpired;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return CertificateState.IsOk;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getCertificateDir(certDirPath: string, hostName: string): SslCertificatePath {
|
|
61
|
+
const sslDirPath = path.resolve(certDirPath, hostName);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
key: path.join(sslDirPath, "certificate.key"),
|
|
65
|
+
cert:path.join(sslDirPath, "certificate.crt.key")
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function saveCertificate(certPaths: SslCertificatePath, key: string, cert: string): Promise<void> {
|
|
70
|
+
await jk_fs.mkDir(path.dirname(certPaths.cert));
|
|
71
|
+
await jk_fs.writeTextToFile(certPaths.key, key);
|
|
72
|
+
await jk_fs.writeTextToFile(certPaths.cert, cert);
|
|
73
|
+
|
|
74
|
+
let proofFile = path.join(path.dirname(certPaths.cert), "_updateDate.txt");
|
|
75
|
+
await jk_fs.writeTextToFile(proofFile, Date.now().toString());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Download a LetsEncrypt certificate.
|
|
80
|
+
* Will be renewed if no current certificat or if the current one is perempted.
|
|
81
|
+
*/
|
|
82
|
+
export async function getLetsEncryptCertificate(httpsWebSite: WebSite, params: LetsEncryptParams): Promise<void> {
|
|
83
|
+
return checkWebSite(httpsWebSite, params, false);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function checkWebSite(httpsWebSite: WebSite, params: LetsEncryptParams, isFromCron: boolean): Promise<void> {
|
|
87
|
+
/**
|
|
88
|
+
* Write a proof.
|
|
89
|
+
*/
|
|
90
|
+
async function challengeCreateFn(_auth: acme.Authorization, challenge: any, keyAuthorization: string): Promise<void> {
|
|
91
|
+
vChallengeToken = challenge.token;
|
|
92
|
+
vKeyAuthorization = keyAuthorization;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Remove the proof.
|
|
97
|
+
*/
|
|
98
|
+
async function challengeRemoveFn(_auth: acme.Authorization, _challenge: any, _keyAuthorization: string) {
|
|
99
|
+
if (canLog) console.log("LetsEncrypt - removing challenge");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!params.certificateDir) params.certificateDir = "certs";
|
|
103
|
+
if (params.log===undefined) params.log = true;
|
|
104
|
+
|
|
105
|
+
// Use 80 and not 90, to have a grace period.
|
|
106
|
+
if (!params.expireAfter_days) params.expireAfter_days = 80;
|
|
107
|
+
|
|
108
|
+
if (!params.timout_sec) params.timout_sec = 30;
|
|
109
|
+
|
|
110
|
+
if (!params.isProduction===undefined) {
|
|
111
|
+
// Need: NODE_ENV=production node app.js
|
|
112
|
+
params.isProduction = process.env.NODE_ENV === 'production';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!params.isProduction) {
|
|
116
|
+
console.warn("LetsEncrypt - Requesting as development");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Will allow checking and replacing the certificate.
|
|
120
|
+
//
|
|
121
|
+
if (!isFromCron) {
|
|
122
|
+
registerToCron(httpsWebSite, params);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ACME challenge requires port 80 of the server.
|
|
126
|
+
const webSite80 = httpsWebSite.getOrCreateHttpRedirectWebsite();
|
|
127
|
+
|
|
128
|
+
const certPaths = getCertificateDir(params.certificateDir, (webSite80 as WebSiteImpl).host);
|
|
129
|
+
let canLog = params.log;
|
|
130
|
+
|
|
131
|
+
let certState = await getCertificateState(certPaths, params);
|
|
132
|
+
|
|
133
|
+
if (certState===CertificateState.IsOk) {
|
|
134
|
+
if (!params.forceRenew) {
|
|
135
|
+
if (canLog) console.log("LetsEncrypt - certificat is already valid");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let vChallengeToken = "";
|
|
141
|
+
let vKeyAuthorization = "";
|
|
142
|
+
|
|
143
|
+
const host = new URL((webSite80 as WebSiteImpl).welcomeUrl).host;
|
|
144
|
+
|
|
145
|
+
if (canLog) {
|
|
146
|
+
if (certState==CertificateState.IsExpired) console.log("LetsEncrypt - Will renew certificate for", host);
|
|
147
|
+
else console.log("LetsEncrypt - Requesting initial certificate for", host);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Must be on port 80.
|
|
151
|
+
webSite80.onGET("/.well-known/acme-challenge/**", async req => {
|
|
152
|
+
console.log("LetsEncrypt - requested ", req.url);
|
|
153
|
+
|
|
154
|
+
if (req.url.endsWith(vChallengeToken)) {
|
|
155
|
+
console.log("LetsEncrypt - returning the auth", vKeyAuthorization);
|
|
156
|
+
return req.res_textResponse(vKeyAuthorization);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return req.res_returnError404_NotFound();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const client = new acme.Client({
|
|
163
|
+
directoryUrl: params.isProduction ? acme.directory.letsencrypt.production : acme.directory.letsencrypt.staging,
|
|
164
|
+
accountKey: await acme.crypto.createPrivateKey()
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// CSR: Certificate Signing Request
|
|
168
|
+
const [key, csr] = await acme.crypto.createCsr({commonName: host});
|
|
169
|
+
|
|
170
|
+
const options: acme.ClientAutoOptions = {
|
|
171
|
+
csr,
|
|
172
|
+
email: params.email,
|
|
173
|
+
termsOfServiceAgreed: true,
|
|
174
|
+
challengePriority: ['http-01'],
|
|
175
|
+
|
|
176
|
+
challengeCreateFn,
|
|
177
|
+
challengeRemoveFn,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
let isResolved = false;
|
|
181
|
+
|
|
182
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
if (isResolved) return;
|
|
185
|
+
|
|
186
|
+
const error = new Error(`Let's Encrypt certificate request timed out after ${params.timout_sec} seconds`);
|
|
187
|
+
(error as any).code = "TIME_OUT";
|
|
188
|
+
reject(error);
|
|
189
|
+
}, params.timout_sec! * 1000);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
const cert = await Promise.race([
|
|
194
|
+
client.auto(options),
|
|
195
|
+
timeoutPromise
|
|
196
|
+
]);
|
|
197
|
+
|
|
198
|
+
isResolved = true;
|
|
199
|
+
if (canLog) console.log("LetsEncrypt - Certificate received for", host);
|
|
200
|
+
|
|
201
|
+
await saveCertificate(certPaths, key.toString(), cert);
|
|
202
|
+
} catch (error: any) {
|
|
203
|
+
if (error.code === "TIME_OUT") {
|
|
204
|
+
if (params.onTimeoutError) {
|
|
205
|
+
params.onTimeoutError(httpsWebSite, isFromCron);
|
|
206
|
+
} else {
|
|
207
|
+
if (canLog) console.error("LetsEncrypt - Request is time-out");
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Re-lancer l'erreur originale si ce n'est pas un timeout
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (isFromCron) {
|
|
216
|
+
webSite80.updateSslCertificate(certPaths);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
interface CronEntry {
|
|
221
|
+
webSite: WebSite;
|
|
222
|
+
params: LetsEncryptParams
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
let gIsCronStarted = false;
|
|
226
|
+
const gWebsiteToCheck: CronEntry[] = [];
|
|
227
|
+
|
|
228
|
+
function startCron() {
|
|
229
|
+
if (gIsCronStarted) return;
|
|
230
|
+
gIsCronStarted = true;
|
|
231
|
+
|
|
232
|
+
jk_timer.newInterval(jk_timer.ONE_DAY, () => {
|
|
233
|
+
gWebsiteToCheck.forEach(ce => checkWebSite(ce.webSite, ce.params, true));
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function registerToCron(webSite: WebSite, params: LetsEncryptParams) {
|
|
238
|
+
if (!gIsCronStarted) {
|
|
239
|
+
startCron();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
gWebsiteToCheck.push({webSite, params});
|
|
243
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {type InstallFunction, loadServerInstall, getBrowserInstallFunction, getDefaultLinkerConfig, compile} from "jopijs/linker";
|
|
2
|
+
import {ModuleInitContext} from "jopijs/ui";
|
|
3
|
+
import * as jk_events from "jopi-toolkit/jk_events";
|
|
4
|
+
import {JopiEasyWebSite, type WebSite} from "jopijs";
|
|
5
|
+
import {logServer_linker} from "./_logs.ts";
|
|
6
|
+
import {DontCallBeforeElapsed} from "jopi-toolkit/jk_tools";
|
|
7
|
+
|
|
8
|
+
let gBrowserInstallFunction: InstallFunction<ModuleInitContext>;
|
|
9
|
+
let gIsInit = false;
|
|
10
|
+
|
|
11
|
+
export async function initLinker(webSite: JopiEasyWebSite, onWebSiteCreate: (h: (webSite: WebSite) => void|Promise<void>) => void) {
|
|
12
|
+
if (gIsInit) return;
|
|
13
|
+
gIsInit = true;
|
|
14
|
+
|
|
15
|
+
const endLog = logServer_linker.beginInfo("Rebuild linker on start");
|
|
16
|
+
await compile(import.meta, getDefaultLinkerConfig());
|
|
17
|
+
endLog();
|
|
18
|
+
|
|
19
|
+
gBrowserInstallFunction = await getBrowserInstallFunction();
|
|
20
|
+
|
|
21
|
+
await loadServerInstall(webSite, onWebSiteCreate);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function executeBrowserInstall(ctx: ModuleInitContext) {
|
|
25
|
+
if (!gIsInit) return;
|
|
26
|
+
gBrowserInstallFunction(ctx);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const gLimitCompileCalls = new DontCallBeforeElapsed(2000);
|
|
30
|
+
|
|
31
|
+
// Will allows updating shared components and composites.
|
|
32
|
+
jk_events.addListener("@jopi.bundler.watch.beforeRebuild", async () => {
|
|
33
|
+
/**
|
|
34
|
+
* This event can occur multiple times with the single-page mode.
|
|
35
|
+
* It's why we limit the number of calls.
|
|
36
|
+
*/
|
|
37
|
+
if (!gLimitCompileCalls.check()) return;
|
|
38
|
+
|
|
39
|
+
const endLog = logServer_linker.beginInfo("Rebuild linker on change");
|
|
40
|
+
await compile(import.meta, getDefaultLinkerConfig(), true /* is refreshing */);
|
|
41
|
+
endLog();
|
|
42
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type {ServerFetch} from "./serverFetch.ts";
|
|
2
|
+
import {type SendingBody} from "./jopiWebSite.tsx";
|
|
3
|
+
import {JopiRequest} from "./jopiRequest.js";
|
|
4
|
+
import * as jk_timer from "jopi-toolkit/jk_timer";
|
|
5
|
+
|
|
6
|
+
const newInterval = jk_timer.newInterval;
|
|
7
|
+
|
|
8
|
+
export class LoadBalancer {
|
|
9
|
+
private readonly servers: Server[] = [];
|
|
10
|
+
private totalWeight = 0;
|
|
11
|
+
private head?: Server;
|
|
12
|
+
private tail?: Server;
|
|
13
|
+
private lastUsedServer?: Server;
|
|
14
|
+
private isTimerStarted = false;
|
|
15
|
+
|
|
16
|
+
addServer<T>(server: ServerFetch<T>, weight?: number) {
|
|
17
|
+
if (server.loadBalancer) throw Error("Server already added to a load balancer");
|
|
18
|
+
server.loadBalancer = this;
|
|
19
|
+
|
|
20
|
+
if (!weight) weight = 1;
|
|
21
|
+
else if (weight>1) weight = 1;
|
|
22
|
+
else if (weight<0) weight = 0;
|
|
23
|
+
|
|
24
|
+
const lbServer = {fetcher: server, weight} as Server;
|
|
25
|
+
|
|
26
|
+
if (!this.head) this.head = lbServer;
|
|
27
|
+
lbServer.next = this.head;
|
|
28
|
+
|
|
29
|
+
if (this.tail) this.tail.next = lbServer;
|
|
30
|
+
this.tail = lbServer;
|
|
31
|
+
|
|
32
|
+
this.servers.push(lbServer);
|
|
33
|
+
this.totalWeight += lbServer.weight;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
replaceServer<T>(oldServer: ServerFetch<T>, newServer: ServerFetch<T>, weight?: number) {
|
|
37
|
+
const lbServer = this.servers.find(s => s.fetcher===oldServer);
|
|
38
|
+
if (!lbServer) return;
|
|
39
|
+
|
|
40
|
+
newServer.loadBalancer = this;
|
|
41
|
+
|
|
42
|
+
lbServer.isServerDown = false;
|
|
43
|
+
lbServer.fetcher = newServer as ServerFetch<unknown>;
|
|
44
|
+
if (weight!==undefined) lbServer.weight = weight;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private selectServer(): Server|undefined {
|
|
48
|
+
if (this.servers.length === 0) return undefined;
|
|
49
|
+
|
|
50
|
+
const lastUsedServer = this.lastUsedServer! || this.tail!;
|
|
51
|
+
let cursor = lastUsedServer.next;
|
|
52
|
+
let round = 0;
|
|
53
|
+
|
|
54
|
+
let random = Math.random();
|
|
55
|
+
|
|
56
|
+
while (true) {
|
|
57
|
+
if (cursor===lastUsedServer) {
|
|
58
|
+
round++;
|
|
59
|
+
|
|
60
|
+
if (round===1) {
|
|
61
|
+
// If we are here, it's mean we have tested all the server but no one is ok.
|
|
62
|
+
// Then reduce the random value to 0 to include a server with weight 0.
|
|
63
|
+
//
|
|
64
|
+
random = 0;
|
|
65
|
+
} else if (round===2) {
|
|
66
|
+
// No server despite that?
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (cursor.isServerDown) continue;
|
|
72
|
+
if (random < cursor.weight) break;
|
|
73
|
+
|
|
74
|
+
cursor = cursor.next;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.lastUsedServer = cursor;
|
|
78
|
+
return cursor;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async fetch(method: string, url: URL, body?: SendingBody, headers?: any): Promise<Response> {
|
|
82
|
+
const server = this.selectServer();
|
|
83
|
+
if (!server) return new Response("", {status: 521});
|
|
84
|
+
|
|
85
|
+
const res = await server.fetcher.fetch(method, url, body, headers);
|
|
86
|
+
|
|
87
|
+
if (res.status===521) {
|
|
88
|
+
this.declareServerDown(server);
|
|
89
|
+
|
|
90
|
+
// We retry with the next server.
|
|
91
|
+
// It's ok since the body isn't consumed yey.
|
|
92
|
+
return this.fetch(method, url, body, headers);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return res;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async directProxy(serverRequest: JopiRequest): Promise<Response> {
|
|
99
|
+
const server = this.selectServer();
|
|
100
|
+
if (!server) return new Response("", {status: 521});
|
|
101
|
+
|
|
102
|
+
const res = await server.fetcher.directProxy(serverRequest);
|
|
103
|
+
|
|
104
|
+
if (res.status===521) {
|
|
105
|
+
this.declareServerDown(server);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return res;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private declareServerDown(server: Server) {
|
|
112
|
+
if (server.isServerDown) return;
|
|
113
|
+
server.isServerDown = true;
|
|
114
|
+
|
|
115
|
+
// Will try to restart the server automatically.
|
|
116
|
+
//
|
|
117
|
+
if (!this.isTimerStarted) {
|
|
118
|
+
newInterval(2000, () => this.onTimer())
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
onTimer() {
|
|
123
|
+
let hasServerDown = false;
|
|
124
|
+
|
|
125
|
+
this.servers.forEach(async server => {
|
|
126
|
+
if (!server.isServerDown) return;
|
|
127
|
+
|
|
128
|
+
if (await server.fetcher.checkIfServerOk()) {
|
|
129
|
+
server.isServerDown = false;
|
|
130
|
+
} else {
|
|
131
|
+
hasServerDown = true;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (!hasServerDown) {
|
|
136
|
+
this.isTimerStarted = false;
|
|
137
|
+
|
|
138
|
+
// Returning false will stop the timer.
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// The timer will continue.
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
interface Server {
|
|
148
|
+
fetcher: ServerFetch<unknown>;
|
|
149
|
+
weight: number;
|
|
150
|
+
next: Server;
|
|
151
|
+
isServerDown?: boolean;
|
|
152
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type {JopiPostMiddleware} from "../jopiWebSite.tsx";
|
|
2
|
+
|
|
3
|
+
export interface CorsMiddlewareOptions {
|
|
4
|
+
accessControlAllowOrigin?: string[];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default function(options: CorsMiddlewareOptions): JopiPostMiddleware {
|
|
8
|
+
let accessControlAllowOrigin: string|undefined;
|
|
9
|
+
if (options.accessControlAllowOrigin) {
|
|
10
|
+
// Make it easier when setting urls.
|
|
11
|
+
const values = options.accessControlAllowOrigin.map(v => new URL(v).origin);
|
|
12
|
+
|
|
13
|
+
accessControlAllowOrigin = values.join(",");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (req, res) => {
|
|
17
|
+
if (accessControlAllowOrigin) {
|
|
18
|
+
res.headers.set("Access-Control-Allow-Origin", accessControlAllowOrigin);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return res;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {JopiRequest} from "../jopiRequest.tsx";
|
|
2
|
+
import type {JopiMiddleware} from "../jopiWebSite.tsx";
|
|
3
|
+
import {getServerStartOptions} from "../jopiServer.ts";
|
|
4
|
+
import * as jk_tools from "jopi-toolkit/jk_tools";
|
|
5
|
+
import * as jk_timer from "jopi-toolkit/jk_timer";
|
|
6
|
+
|
|
7
|
+
const newInterval = jk_timer.newInterval;
|
|
8
|
+
const applyDefaults = jk_tools.applyDefaults;
|
|
9
|
+
|
|
10
|
+
// slowhttptest -c 1000 -H -i 10 -r 200 -t GET -u http://my-server -x 24 -p 3
|
|
11
|
+
|
|
12
|
+
export interface DdosProtectionOptions {
|
|
13
|
+
/**
|
|
14
|
+
* If the request takes more than n-milliseconds to send his headers, then we reject this request.
|
|
15
|
+
* Warning: this value is global to all websites. Setting it will affect all of them.
|
|
16
|
+
* Default: 500 ms.
|
|
17
|
+
*/
|
|
18
|
+
sendHeadersTimeout_ms?: number;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Delay in millisecondes after which the request timeout.
|
|
22
|
+
* Default: 60 seconds.
|
|
23
|
+
*/
|
|
24
|
+
requestTimeout_sec?: number;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* We will limit the number of calls allowed during an interval.
|
|
28
|
+
* Here it's the size of this interval in milliseconds.
|
|
29
|
+
* Default is 1000 ms (one second).
|
|
30
|
+
*
|
|
31
|
+
* The default behaviors are that you can do more than 10 calls to the same second with the same IP.
|
|
32
|
+
* If you need an exception for an IP, use onBlackRequest
|
|
33
|
+
*/
|
|
34
|
+
timeInterval_ms?: number;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* We will limit the number of calls allowed during an interval.
|
|
38
|
+
* Here's the number of connections allowed during this interval of time.
|
|
39
|
+
* Default is 10.
|
|
40
|
+
*
|
|
41
|
+
* The default behaviors are that you can do more than 10 calls to the same second with the same IP.
|
|
42
|
+
* If you need an exception for an IP, use onBlackRequest
|
|
43
|
+
*/
|
|
44
|
+
connectionLimit?: number;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Is call if a request is detected as an anomaly.
|
|
48
|
+
*/
|
|
49
|
+
onBlackRequest?: JopiMiddleware;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let gGlobalBlackRequestListener: JopiMiddleware|undefined;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Allow setting a listener which is called when a black request is detected.
|
|
56
|
+
* It'd mainly used to add his IP to a banned IP list.
|
|
57
|
+
*/
|
|
58
|
+
export function setGlobalBlackRequestListener(listener: JopiMiddleware) {
|
|
59
|
+
gGlobalBlackRequestListener = listener;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default function(options?: DdosProtectionOptions): JopiMiddleware {
|
|
63
|
+
options = applyDefaults<DdosProtectionOptions>(options, {
|
|
64
|
+
sendHeadersTimeout_ms: 500,
|
|
65
|
+
requestTimeout_sec: 60,
|
|
66
|
+
|
|
67
|
+
timeInterval_ms: 1000,
|
|
68
|
+
connectionLimit: 10,
|
|
69
|
+
|
|
70
|
+
onBlackRequest: () => {
|
|
71
|
+
return new Response("Too many request", { status: 429 });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Here it's a common value for all servers.
|
|
76
|
+
getServerStartOptions().timeout = options.sendHeadersTimeout_ms!;
|
|
77
|
+
|
|
78
|
+
const mapConnectionsPerIP = new Map<String, number>;
|
|
79
|
+
const connectionLimit = options.connectionLimit!;
|
|
80
|
+
|
|
81
|
+
let mustReset = false;
|
|
82
|
+
|
|
83
|
+
// The values here are reset after a delay.
|
|
84
|
+
//
|
|
85
|
+
newInterval(options.timeInterval_ms!, () => {
|
|
86
|
+
if (mustReset) {
|
|
87
|
+
mapConnectionsPerIP.clear();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return (req: JopiRequest) => {
|
|
92
|
+
// If we are here, it's mean the request take less than 1 second to send his headers.
|
|
93
|
+
// It's why we can extend the time-out delay (60 secondes).
|
|
94
|
+
//
|
|
95
|
+
req.req_extendTimeout_sec(options.requestTimeout_sec!);
|
|
96
|
+
|
|
97
|
+
// > Check how many-time this request has reached the server recently.
|
|
98
|
+
|
|
99
|
+
const clientIP = req.requestIP?.address;
|
|
100
|
+
|
|
101
|
+
if (clientIP) {
|
|
102
|
+
const currentConnections = (mapConnectionsPerIP.get(clientIP) || 0) + 1;
|
|
103
|
+
|
|
104
|
+
if (currentConnections > connectionLimit) {
|
|
105
|
+
if (gGlobalBlackRequestListener) {
|
|
106
|
+
const res = gGlobalBlackRequestListener(req);
|
|
107
|
+
if (res!==null) return res;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return options.onBlackRequest!(req);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
mapConnectionsPerIP.set(clientIP, currentConnections);
|
|
114
|
+
mustReset = true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Allow continuing to the next middleware.
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import DdosProtection from "./DdosProtection.ts";
|
|
2
|
+
import CorsMiddleware from "./CorsMiddleware.ts";
|
|
3
|
+
import {JopiRequest} from "../jopiRequest.js";
|
|
4
|
+
|
|
5
|
+
export const Middlewares = {
|
|
6
|
+
ddosProtection: DdosProtection,
|
|
7
|
+
|
|
8
|
+
requestTimeout_sec: (timeInSec:number) => (req: JopiRequest) => {
|
|
9
|
+
req.req_extendTimeout_sec(timeInSec);
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const PostMiddlewares = {
|
|
15
|
+
cors: CorsMiddleware
|
|
16
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type {HttpMethod} from "./jopiWebSite.tsx";
|
|
2
|
+
|
|
3
|
+
export function octetToMo(size: number) {
|
|
4
|
+
const res = size / ONE_MEGA_OCTET;
|
|
5
|
+
return Math.trunc(res * 100) / 100;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const ONE_MINUTE = 1000 * 60;
|
|
9
|
+
export const ONE_HOUR = ONE_MINUTE * 60;
|
|
10
|
+
export const ONE_DAY = ONE_HOUR * 24;
|
|
11
|
+
export const ONE_KILO_OCTET = 1024;
|
|
12
|
+
export const ONE_MEGA_OCTET = 1024 * ONE_KILO_OCTET;
|
|
13
|
+
|
|
14
|
+
export const HTTP_VERBS: HttpMethod[] = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
|