@saolabs/client 1.0.0 → 1.1.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/README.md +52 -195
- package/dist/index.d.ts +20 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.js +2 -2
- package/dist/src/core/app/Application.d.ts +25 -15
- package/dist/src/core/app/Application.d.ts.map +1 -1
- package/dist/src/core/app/Application.js +55 -18
- package/dist/src/core/app/Application.js.map +1 -1
- package/dist/src/core/bootstrap/app.d.ts +1 -1
- package/dist/src/core/bootstrap/app.d.ts.map +1 -1
- package/dist/src/core/bootstrap/app.js +77 -4
- package/dist/src/core/bootstrap/app.js.map +1 -1
- package/dist/src/core/bootstrap/bundle.d.ts +41 -0
- package/dist/src/core/bootstrap/bundle.d.ts.map +1 -0
- package/dist/src/core/bootstrap/bundle.js +98 -0
- package/dist/src/core/bootstrap/bundle.js.map +1 -0
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +3 -3
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +11 -8
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +3 -1
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +8 -3
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +2 -1
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +14 -4
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +4 -4
- package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/ServiceProvider.js +5 -5
- package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +3 -3
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/default-providers.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/default-providers.js +44 -11
- package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -1
- package/dist/src/core/bootstrap/providers/index.d.ts +9 -9
- package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/index.js +8 -8
- package/dist/src/core/bootstrap/providers/index.js.map +1 -1
- package/dist/src/core/bootstrap/providers/provider-order.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -1
- package/dist/src/core/bootstrap/ssr.d.ts +47 -0
- package/dist/src/core/bootstrap/ssr.d.ts.map +1 -0
- package/dist/src/core/bootstrap/ssr.js +129 -0
- package/dist/src/core/bootstrap/ssr.js.map +1 -0
- package/dist/src/core/cache/ViewCache.d.ts +1 -1
- package/dist/src/core/cache/ViewCache.d.ts.map +1 -1
- package/dist/src/core/cache/index.d.ts +1 -1
- package/dist/src/core/cache/index.d.ts.map +1 -1
- package/dist/src/core/cache/index.js +1 -1
- package/dist/src/core/cache/index.js.map +1 -1
- package/dist/src/core/contracts/ApplicationInterface.d.ts +15 -11
- package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/BlockInterface.d.ts +10 -10
- package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/BundleInterface.d.ts +38 -0
- package/dist/src/core/contracts/BundleInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/BundleInterface.js +2 -0
- package/dist/src/core/contracts/BundleInterface.js.map +1 -0
- package/dist/src/core/contracts/ComponentInterface.d.ts +7 -6
- package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ElementInterface.d.ts +91 -27
- package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/HeadServiceInterface.d.ts +37 -0
- package/dist/src/core/contracts/HeadServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/HeadServiceInterface.js +3 -0
- package/dist/src/core/contracts/HeadServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/HelperInterface.d.ts +9 -1
- package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/HttpServiceInterface.d.ts +3 -0
- package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/MarkerInterface.d.ts +29 -44
- package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ReactiveInterface.d.ts +9 -9
- package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/RouterInterface.d.ts +5 -2
- package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/SectionInterface.d.ts +48 -0
- package/dist/src/core/contracts/SectionInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/SectionInterface.js +2 -0
- package/dist/src/core/contracts/SectionInterface.js.map +1 -0
- package/dist/src/core/contracts/ServiceProviderInterface.d.ts +3 -3
- package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewControllerInterface.d.ts +116 -15
- package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewInterface.d.ts +31 -5
- package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewManagerInterface.d.ts +47 -5
- package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewStateInterface.d.ts +39 -2
- package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/common.d.ts +3 -3
- package/dist/src/core/contracts/common.js +3 -3
- package/dist/src/core/contracts/utils.d.ts +19 -19
- package/dist/src/core/contracts/utils.d.ts.map +1 -1
- package/dist/src/core/contracts/views.d.ts +1 -22
- package/dist/src/core/contracts/views.d.ts.map +1 -1
- package/dist/src/core/devtools/hook.d.ts +66 -0
- package/dist/src/core/devtools/hook.d.ts.map +1 -0
- package/dist/src/core/devtools/hook.js +114 -0
- package/dist/src/core/devtools/hook.js.map +1 -0
- package/dist/src/core/devtools/index.d.ts +34 -0
- package/dist/src/core/devtools/index.d.ts.map +1 -0
- package/dist/src/core/devtools/index.js +33 -0
- package/dist/src/core/devtools/index.js.map +1 -0
- package/dist/src/core/devtools/inspector.d.ts +31 -0
- package/dist/src/core/devtools/inspector.d.ts.map +1 -0
- package/dist/src/core/devtools/inspector.js +249 -0
- package/dist/src/core/devtools/inspector.js.map +1 -0
- package/dist/src/core/elements/Block.d.ts +9 -7
- package/dist/src/core/elements/Block.d.ts.map +1 -1
- package/dist/src/core/elements/Block.js +33 -9
- package/dist/src/core/elements/Block.js.map +1 -1
- package/dist/src/core/elements/BlockOutlet.d.ts +19 -8
- package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -1
- package/dist/src/core/elements/BlockOutlet.js +57 -13
- package/dist/src/core/elements/BlockOutlet.js.map +1 -1
- package/dist/src/core/elements/Component.d.ts +83 -11
- package/dist/src/core/elements/Component.d.ts.map +1 -1
- package/dist/src/core/elements/Component.js +334 -13
- package/dist/src/core/elements/Component.js.map +1 -1
- package/dist/src/core/elements/ForeachSlotCache.d.ts +95 -0
- package/dist/src/core/elements/ForeachSlotCache.d.ts.map +1 -0
- package/dist/src/core/elements/ForeachSlotCache.js +149 -0
- package/dist/src/core/elements/ForeachSlotCache.js.map +1 -0
- package/dist/src/core/elements/Fragment.d.ts +19 -13
- package/dist/src/core/elements/Fragment.d.ts.map +1 -1
- package/dist/src/core/elements/Fragment.js +43 -20
- package/dist/src/core/elements/Fragment.js.map +1 -1
- package/dist/src/core/elements/Html.d.ts +89 -12
- package/dist/src/core/elements/Html.d.ts.map +1 -1
- package/dist/src/core/elements/Html.js +707 -106
- package/dist/src/core/elements/Html.js.map +1 -1
- package/dist/src/core/elements/Output.d.ts +34 -10
- package/dist/src/core/elements/Output.d.ts.map +1 -1
- package/dist/src/core/elements/Output.js +141 -26
- package/dist/src/core/elements/Output.js.map +1 -1
- package/dist/src/core/elements/Reactive.d.ts +85 -14
- package/dist/src/core/elements/Reactive.d.ts.map +1 -1
- package/dist/src/core/elements/Reactive.js +315 -41
- package/dist/src/core/elements/Reactive.js.map +1 -1
- package/dist/src/core/elements/TextElement.d.ts +11 -7
- package/dist/src/core/elements/TextElement.d.ts.map +1 -1
- package/dist/src/core/elements/TextElement.js +18 -11
- package/dist/src/core/elements/TextElement.js.map +1 -1
- package/dist/src/core/elements/Wrapper.d.ts +24 -13
- package/dist/src/core/elements/Wrapper.d.ts.map +1 -1
- package/dist/src/core/elements/Wrapper.js +65 -8
- package/dist/src/core/elements/Wrapper.js.map +1 -1
- package/dist/src/core/elements/Yield.d.ts +10 -9
- package/dist/src/core/elements/Yield.d.ts.map +1 -1
- package/dist/src/core/elements/Yield.js +31 -19
- package/dist/src/core/elements/Yield.js.map +1 -1
- package/dist/src/core/elements/helpers.d.ts +7 -7
- package/dist/src/core/elements/helpers.d.ts.map +1 -1
- package/dist/src/core/elements/helpers.js +4 -4
- package/dist/src/core/elements/index.d.ts +12 -11
- package/dist/src/core/elements/index.d.ts.map +1 -1
- package/dist/src/core/elements/index.js +12 -11
- package/dist/src/core/elements/index.js.map +1 -1
- package/dist/src/core/elements/reconcileChildren.d.ts +7 -0
- package/dist/src/core/elements/reconcileChildren.d.ts.map +1 -0
- package/dist/src/core/elements/reconcileChildren.js +74 -0
- package/dist/src/core/elements/reconcileChildren.js.map +1 -0
- package/dist/src/core/helpers/ApiClient.d.ts.map +1 -0
- package/dist/src/core/{hellpers → helpers}/ApiClient.js +10 -1
- package/dist/src/core/helpers/ApiClient.js.map +1 -0
- package/dist/src/core/helpers/app.d.ts +3 -0
- package/dist/src/core/helpers/app.d.ts.map +1 -0
- package/dist/src/core/{hellpers → helpers}/app.js +11 -1
- package/dist/src/core/helpers/app.js.map +1 -0
- package/dist/src/core/helpers/transition.d.ts +34 -0
- package/dist/src/core/helpers/transition.d.ts.map +1 -0
- package/dist/src/core/helpers/transition.js +118 -0
- package/dist/src/core/helpers/transition.js.map +1 -0
- package/dist/src/core/{hellpers → helpers}/utils.d.ts +2 -2
- package/dist/src/core/helpers/utils.d.ts.map +1 -0
- package/dist/src/core/{hellpers → helpers}/utils.js +4 -4
- package/dist/src/core/helpers/utils.js.map +1 -0
- package/dist/src/core/helpers/view.d.ts +39 -0
- package/dist/src/core/helpers/view.d.ts.map +1 -0
- package/dist/src/core/helpers/view.js +286 -0
- package/dist/src/core/helpers/view.js.map +1 -0
- package/dist/src/core/routers/Router.d.ts +108 -7
- package/dist/src/core/routers/Router.d.ts.map +1 -1
- package/dist/src/core/routers/Router.js +444 -68
- package/dist/src/core/routers/Router.js.map +1 -1
- package/dist/src/core/routers/index.d.ts +2 -2
- package/dist/src/core/routers/index.d.ts.map +1 -1
- package/dist/src/core/routers/index.js +1 -1
- package/dist/src/core/routers/index.js.map +1 -1
- package/dist/src/core/services/AssetManager.d.ts +112 -0
- package/dist/src/core/services/AssetManager.d.ts.map +1 -0
- package/dist/src/core/services/AssetManager.js +361 -0
- package/dist/src/core/services/AssetManager.js.map +1 -0
- package/dist/src/core/services/BlockManager.d.ts +73 -2
- package/dist/src/core/services/BlockManager.d.ts.map +1 -1
- package/dist/src/core/services/BlockManager.js +270 -48
- package/dist/src/core/services/BlockManager.js.map +1 -1
- package/dist/src/core/services/DomService.js +3 -3
- package/dist/src/core/services/DomService.js.map +1 -1
- package/dist/src/core/services/HeadService.d.ts +24 -0
- package/dist/src/core/services/HeadService.d.ts.map +1 -0
- package/dist/src/core/services/HeadService.js +120 -0
- package/dist/src/core/services/HeadService.js.map +1 -0
- package/dist/src/core/services/HelperService.d.ts +14 -3
- package/dist/src/core/services/HelperService.d.ts.map +1 -1
- package/dist/src/core/services/HelperService.js +32 -2
- package/dist/src/core/services/HelperService.js.map +1 -1
- package/dist/src/core/services/HttpService.d.ts +8 -0
- package/dist/src/core/services/HttpService.d.ts.map +1 -1
- package/dist/src/core/services/HttpService.js +121 -47
- package/dist/src/core/services/HttpService.js.map +1 -1
- package/dist/src/core/services/MarkerRegistry.d.ts +51 -8
- package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -1
- package/dist/src/core/services/MarkerRegistry.js +135 -14
- package/dist/src/core/services/MarkerRegistry.js.map +1 -1
- package/dist/src/core/services/PageCache.d.ts +101 -0
- package/dist/src/core/services/PageCache.d.ts.map +1 -0
- package/dist/src/core/services/PageCache.js +184 -0
- package/dist/src/core/services/PageCache.js.map +1 -0
- package/dist/src/core/services/SectionManager.d.ts +100 -0
- package/dist/src/core/services/SectionManager.d.ts.map +1 -0
- package/dist/src/core/services/SectionManager.js +408 -0
- package/dist/src/core/services/SectionManager.js.map +1 -0
- package/dist/src/core/services/StorageService.js +1 -1
- package/dist/src/core/services/TranslationService.d.ts +21 -0
- package/dist/src/core/services/TranslationService.d.ts.map +1 -0
- package/dist/src/core/services/TranslationService.js +95 -0
- package/dist/src/core/services/TranslationService.js.map +1 -0
- package/dist/src/core/services/index.d.ts +11 -8
- package/dist/src/core/services/index.d.ts.map +1 -1
- package/dist/src/core/services/index.js +11 -8
- package/dist/src/core/services/index.js.map +1 -1
- package/dist/src/core/types/utils.d.ts +8 -8
- package/dist/src/core/types/utils.d.ts.map +1 -1
- package/dist/src/core/view/LoopContext.d.ts +21 -1
- package/dist/src/core/view/LoopContext.d.ts.map +1 -1
- package/dist/src/core/view/LoopContext.js +36 -0
- package/dist/src/core/view/LoopContext.js.map +1 -1
- package/dist/src/core/view/ResourceScope.d.ts +38 -0
- package/dist/src/core/view/ResourceScope.d.ts.map +1 -0
- package/dist/src/core/view/ResourceScope.js +167 -0
- package/dist/src/core/view/ResourceScope.js.map +1 -0
- package/dist/src/core/view/Section.d.ts +17 -32
- package/dist/src/core/view/Section.d.ts.map +1 -1
- package/dist/src/core/view/Section.js +14 -55
- package/dist/src/core/view/Section.js.map +1 -1
- package/dist/src/core/view/View.d.ts +43 -7
- package/dist/src/core/view/View.d.ts.map +1 -1
- package/dist/src/core/view/View.js +22 -4
- package/dist/src/core/view/View.js.map +1 -1
- package/dist/src/core/view/ViewController.d.ts +313 -40
- package/dist/src/core/view/ViewController.d.ts.map +1 -1
- package/dist/src/core/view/ViewController.js +1002 -147
- package/dist/src/core/view/ViewController.js.map +1 -1
- package/dist/src/core/view/ViewManager.d.ts +318 -27
- package/dist/src/core/view/ViewManager.d.ts.map +1 -1
- package/dist/src/core/view/ViewManager.js +1199 -258
- package/dist/src/core/view/ViewManager.js.map +1 -1
- package/dist/src/core/view/ViewState.d.ts +185 -6
- package/dist/src/core/view/ViewState.d.ts.map +1 -1
- package/dist/src/core/view/ViewState.js +851 -123
- package/dist/src/core/view/ViewState.js.map +1 -1
- package/dist/src/core/view/index.d.ts +5 -5
- package/dist/src/core/view/index.d.ts.map +1 -1
- package/dist/src/core/view/index.js +5 -5
- package/dist/src/core/view/index.js.map +1 -1
- package/dist/src/testing/index.d.ts +69 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +140 -0
- package/dist/src/testing/index.js.map +1 -0
- package/index.ts +29 -5
- package/package.json +30 -21
- package/plugins.ts +2 -2
- package/src/core/app/Application.ts +72 -31
- package/src/core/bootstrap/app.ts +84 -6
- package/src/core/bootstrap/bundle.ts +101 -0
- package/src/core/bootstrap/providers/ApiServiceProvider.ts +4 -4
- package/src/core/bootstrap/providers/CoreServiceProvider.ts +14 -8
- package/src/core/bootstrap/providers/HelperServiceProvider.ts +8 -3
- package/src/core/bootstrap/providers/RouteServiceProvider.ts +15 -4
- package/src/core/bootstrap/providers/ServiceProvider.ts +8 -8
- package/src/core/bootstrap/providers/ViewServiceProvider.ts +3 -3
- package/src/core/bootstrap/providers/default-providers.ts +51 -16
- package/src/core/bootstrap/providers/index.ts +9 -9
- package/src/core/bootstrap/providers/provider-order.test.ts +16 -27
- package/src/core/bootstrap/providers/provider-order.ts +1 -1
- package/src/core/bootstrap/ssr.ts +141 -0
- package/src/core/cache/ViewCache.ts +1 -1
- package/src/core/cache/index.ts +1 -1
- package/src/core/contracts/ApplicationInterface.ts +15 -11
- package/src/core/contracts/BlockInterface.ts +18 -18
- package/src/core/contracts/BundleInterface.ts +40 -0
- package/src/core/contracts/ComponentInterface.ts +7 -6
- package/src/core/contracts/ElementInterface.ts +95 -27
- package/src/core/contracts/HeadServiceInterface.ts +41 -0
- package/src/core/contracts/HelperInterface.ts +9 -1
- package/src/core/contracts/HttpServiceInterface.ts +3 -0
- package/src/core/contracts/MarkerInterface.ts +22 -49
- package/src/core/contracts/ReactiveInterface.ts +9 -9
- package/src/core/contracts/RouterInterface.ts +5 -2
- package/src/core/contracts/SectionInterface.ts +49 -0
- package/src/core/contracts/ServiceProviderInterface.ts +3 -3
- package/src/core/contracts/ViewControllerInterface.ts +124 -16
- package/src/core/contracts/ViewInterface.ts +34 -5
- package/src/core/contracts/ViewManagerInterface.ts +40 -5
- package/src/core/contracts/ViewStateInterface.ts +39 -2
- package/src/core/contracts/common.ts +3 -3
- package/src/core/contracts/utils.ts +19 -19
- package/src/core/contracts/views.ts +2 -22
- package/src/core/devtools/hook.ts +142 -0
- package/src/core/devtools/index.ts +38 -0
- package/src/core/devtools/inspector.ts +270 -0
- package/src/core/elements/Block.ts +43 -21
- package/src/core/elements/BlockOutlet.ts +61 -21
- package/src/core/elements/Component.ts +352 -18
- package/src/core/elements/ElementManager.ts +9 -9
- package/src/core/elements/ForeachSlotCache.ts +170 -0
- package/src/core/elements/Fragment.ts +50 -32
- package/src/core/elements/Html.ts +696 -117
- package/src/core/elements/Output.ts +147 -30
- package/src/core/elements/Reactive.ts +329 -52
- package/src/core/elements/TextElement.ts +25 -16
- package/src/core/elements/Wrapper.ts +84 -18
- package/src/core/elements/Yield.ts +35 -24
- package/src/core/elements/helpers.ts +12 -12
- package/src/core/elements/index.ts +25 -24
- package/src/core/elements/reconcileChildren.ts +70 -0
- package/src/core/{hellpers → helpers}/ApiClient.ts +8 -1
- package/src/core/{hellpers → helpers}/app.ts +13 -2
- package/src/core/helpers/transition.ts +127 -0
- package/src/core/{hellpers → helpers}/utils.ts +4 -4
- package/src/core/helpers/view.ts +283 -0
- package/src/core/routers/Router.ts +458 -64
- package/src/core/routers/index.ts +2 -2
- package/src/core/services/AssetManager.ts +387 -0
- package/src/core/services/BlockManager.ts +272 -50
- package/src/core/services/DomService.ts +3 -3
- package/src/core/services/HeadService.ts +124 -0
- package/src/core/services/HelperService.ts +34 -4
- package/src/core/services/HttpService.ts +116 -55
- package/src/core/services/MarkerRegistry.ts +142 -16
- package/src/core/services/PageCache.ts +239 -0
- package/src/core/services/SectionManager.ts +387 -0
- package/src/core/services/StorageService.ts +1 -1
- package/src/core/services/TranslationService.ts +91 -0
- package/src/core/services/index.ts +11 -8
- package/src/core/types/utils.ts +8 -8
- package/src/core/view/LoopContext.ts +38 -1
- package/src/core/view/ResourceScope.ts +174 -0
- package/src/core/view/Section.ts +21 -68
- package/src/core/view/View.ts +57 -8
- package/src/core/view/ViewController.ts +1070 -186
- package/src/core/view/ViewManager.ts +1346 -272
- package/src/core/view/ViewState.ts +834 -116
- package/src/core/view/index.ts +5 -5
- package/src/testing/index.ts +184 -0
- package/dist/src/core/hellpers/ApiClient.d.ts.map +0 -1
- package/dist/src/core/hellpers/ApiClient.js.map +0 -1
- package/dist/src/core/hellpers/app.d.ts +0 -3
- package/dist/src/core/hellpers/app.d.ts.map +0 -1
- package/dist/src/core/hellpers/app.js.map +0 -1
- package/dist/src/core/hellpers/utils.d.ts.map +0 -1
- package/dist/src/core/hellpers/utils.js.map +0 -1
- package/dist/src/core/services/MarkerService.d.ts +0 -299
- package/dist/src/core/services/MarkerService.d.ts.map +0 -1
- package/dist/src/core/services/MarkerService.js +0 -723
- package/dist/src/core/services/MarkerService.js.map +0 -1
- package/src/core/services/MarkerService.ts +0 -923
- /package/dist/src/core/{hellpers → helpers}/ApiClient.d.ts +0 -0
|
@@ -27,22 +27,23 @@
|
|
|
27
27
|
* const router = app.make('router');
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import type { ApplicationInterface, ServiceKey, ServiceFactory, ServiceBinding } from '../contracts/ApplicationInterface';
|
|
31
|
-
import type { ServiceProviderInterface } from '../contracts/ServiceProviderInterface';
|
|
32
|
-
import type { ViewManagerInterface, RouterInterface } from '../contracts/utils';
|
|
33
|
-
import type { HelperInterface } from '../contracts/HelperInterface';
|
|
34
|
-
import type { EventServiceInterface } from '../contracts/EventServiceInterface';
|
|
35
|
-
import type { HttpServiceInterface } from '../contracts/HttpServiceInterface';
|
|
36
|
-
import type { StoreServiceInterface } from '../contracts/StoreServiceInterface';
|
|
37
|
-
import type { StorageServiceInterface } from '../contracts/StorageServiceInterface';
|
|
38
|
-
import type { LoggerServiceInterface } from '../contracts/LoggerServiceInterface';
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
30
|
+
import type { ApplicationInterface, ServiceKey, ServiceFactory, ServiceBinding } from '../contracts/ApplicationInterface.js';
|
|
31
|
+
import type { ServiceProviderInterface } from '../contracts/ServiceProviderInterface.js';
|
|
32
|
+
import type { ViewManagerInterface, RouterInterface } from '../contracts/utils.js';
|
|
33
|
+
import type { HelperInterface } from '../contracts/HelperInterface.js';
|
|
34
|
+
import type { EventServiceInterface } from '../contracts/EventServiceInterface.js';
|
|
35
|
+
import type { HttpServiceInterface } from '../contracts/HttpServiceInterface.js';
|
|
36
|
+
import type { StoreServiceInterface } from '../contracts/StoreServiceInterface.js';
|
|
37
|
+
import type { StorageServiceInterface } from '../contracts/StorageServiceInterface.js';
|
|
38
|
+
import type { LoggerServiceInterface } from '../contracts/LoggerServiceInterface.js';
|
|
39
|
+
import type { HeadServiceInterface } from '../contracts/HeadServiceInterface.js';
|
|
40
|
+
import { APIClientInterface } from '../contracts/ApiInterface.js';
|
|
41
|
+
import { SaoObjectType, OOTEnum } from '../types/utils.js';
|
|
41
42
|
|
|
42
43
|
// ─── Application ────────────────────────────────────────────────
|
|
43
44
|
|
|
44
45
|
export class Application implements ApplicationInterface {
|
|
45
|
-
readonly
|
|
46
|
+
readonly saoType: SaoObjectType = OOTEnum.APPLICATION;
|
|
46
47
|
// Service properties — set during bootstrap via App.set()
|
|
47
48
|
declare isInitialized: boolean;
|
|
48
49
|
declare isStarted: boolean;
|
|
@@ -55,6 +56,7 @@ export class Application implements ApplicationInterface {
|
|
|
55
56
|
declare Store: StoreServiceInterface;
|
|
56
57
|
declare Storage: StorageServiceInterface;
|
|
57
58
|
declare Logger: LoggerServiceInterface;
|
|
59
|
+
declare Head: HeadServiceInterface;
|
|
58
60
|
|
|
59
61
|
/** Factory bindings — mỗi lần make() gọi factory tạo instance mới */
|
|
60
62
|
private bindings = new Map<ServiceKey, ServiceFactory<any>>();
|
|
@@ -94,10 +96,11 @@ export class Application implements ApplicationInterface {
|
|
|
94
96
|
'destroy',
|
|
95
97
|
'getBindings',
|
|
96
98
|
'getSingletons',
|
|
99
|
+
'shared',
|
|
97
100
|
'__store',
|
|
98
101
|
]; // Để track dynamic properties nếu cần
|
|
99
102
|
|
|
100
|
-
__store: Map<
|
|
103
|
+
__store: Map<any, { isOverridable: boolean, value: any }> = new Map(); // Store cho dynamic properties nếu cần
|
|
101
104
|
|
|
102
105
|
[key: string]: any; // Cho phép dynamic properties nếu cần
|
|
103
106
|
|
|
@@ -179,6 +182,18 @@ export class Application implements ApplicationInterface {
|
|
|
179
182
|
*/
|
|
180
183
|
instance<T>(key: ServiceKey<T>, value: T): this {
|
|
181
184
|
this.singletons.set(key, value);
|
|
185
|
+
if (typeof key === 'string' && !this.ownProperties.includes(key)) {
|
|
186
|
+
this.__store.set(key, { value, isOverridable: true });
|
|
187
|
+
Object.defineProperty(this, key, {
|
|
188
|
+
get: () => this.__store.get(key)?.value,
|
|
189
|
+
set: (newValue) => {
|
|
190
|
+
this.__store.set(key, { value: newValue, isOverridable: true });
|
|
191
|
+
this.singletons.set(key, newValue);
|
|
192
|
+
},
|
|
193
|
+
configurable: true,
|
|
194
|
+
enumerable: false,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
182
197
|
return this;
|
|
183
198
|
}
|
|
184
199
|
|
|
@@ -289,6 +304,15 @@ export class Application implements ApplicationInterface {
|
|
|
289
304
|
(provider as any).initApplication();
|
|
290
305
|
}
|
|
291
306
|
provider.register();
|
|
307
|
+
|
|
308
|
+
// Đăng ký SAU khi app đã boot — plugin nạp muộn qua App.push(), hoặc
|
|
309
|
+
// provider của theme cắm vào giữa phiên. boot() vòng lặp chính đã chạy
|
|
310
|
+
// xong và có cờ chặn, nên nếu không gọi ở đây thì provider chỉ chạy nửa
|
|
311
|
+
// vòng đời: register() có, boot() không, và KHÔNG có lỗi nào phát ra.
|
|
312
|
+
if (this.booted && typeof provider.boot === 'function') {
|
|
313
|
+
provider.boot();
|
|
314
|
+
}
|
|
315
|
+
|
|
292
316
|
return this;
|
|
293
317
|
}
|
|
294
318
|
|
|
@@ -342,31 +366,35 @@ export class Application implements ApplicationInterface {
|
|
|
342
366
|
}
|
|
343
367
|
|
|
344
368
|
|
|
345
|
-
set<T = any>(name:
|
|
346
|
-
if (this.ownProperties.includes(name)) {
|
|
347
|
-
return; // Không cho ghi đè lên thuộc tính có sẵn
|
|
348
|
-
}
|
|
369
|
+
set<T = any>(name: any, value: T, isOne: boolean = false): void {
|
|
349
370
|
if (this.__store.has(name) && this.__store.get(name)?.isOverridable === false) {
|
|
350
371
|
return; // Không cho ghi đè lên thuộc tính không thể override
|
|
351
372
|
}
|
|
373
|
+
const isString = typeof name === 'string';
|
|
374
|
+
if (isString && this.ownProperties.includes(name)) {
|
|
375
|
+
return; // Không cho ghi đè lên thuộc tính có sẵn
|
|
376
|
+
}
|
|
352
377
|
this.__store.set(name, { value, isOverridable: !isOne });
|
|
353
378
|
this.singletons.set(name, value); // Sync → DI container
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
379
|
+
if (isString) {
|
|
380
|
+
Object.defineProperty(this, name, {
|
|
381
|
+
get: () => this.__store.get(name)?.value,
|
|
382
|
+
set: (newValue) => {
|
|
383
|
+
if (this.__store.has(name) && this.__store.get(name)?.isOverridable === false) {
|
|
384
|
+
return; // Không cho ghi đè nếu isOverridable là false
|
|
385
|
+
}
|
|
386
|
+
this.__store.set(name, { value: newValue, isOverridable: !isOne });
|
|
387
|
+
this.singletons.set(name, newValue); // Sync → DI container
|
|
388
|
+
},
|
|
389
|
+
configurable: isOne ? false : true,
|
|
390
|
+
enumerable: false,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
366
393
|
}
|
|
367
394
|
|
|
368
|
-
get<T = any>(name:
|
|
369
|
-
|
|
395
|
+
get<T = any>(name: any): T {
|
|
396
|
+
const isString = typeof name === 'string';
|
|
397
|
+
if (isString && this.ownProperties.includes(name)) {
|
|
370
398
|
return (this as any)[name]; // Trả về thuộc tính có sẵn
|
|
371
399
|
}
|
|
372
400
|
// Check __store first (registered via set())
|
|
@@ -380,6 +408,19 @@ export class Application implements ApplicationInterface {
|
|
|
380
408
|
return undefined as T;
|
|
381
409
|
}
|
|
382
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Dữ liệu package PHP chia sẻ cho client theo từng request (`Saola::share()`
|
|
413
|
+
* → `APP_CONFIGS.shared` → `App.init({ shared })`). Helper JS của package đọc
|
|
414
|
+
* ở đây thay vì tự đọc `window`, để test truyền được qua config.
|
|
415
|
+
*
|
|
416
|
+
* @example App.shared('permission', { routes: [] }).routes
|
|
417
|
+
*/
|
|
418
|
+
shared<T = any>(key?: string, fallback?: T): T {
|
|
419
|
+
const all = (this.__store.get('SharedData')?.value ?? {}) as Record<string, any>;
|
|
420
|
+
if (key === undefined) return all as T;
|
|
421
|
+
return (Object.prototype.hasOwnProperty.call(all, key) ? all[key] : fallback) as T;
|
|
422
|
+
}
|
|
423
|
+
|
|
383
424
|
setMethod(name: string, method: Function, isOne: boolean = false): void {
|
|
384
425
|
if (this.ownProperties.includes(name)) {
|
|
385
426
|
return; // Không cho ghi đè lên thuộc tính có sẵn
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { ApplicationInterface } from "../contracts/ApplicationInterface";
|
|
2
|
-
import { app } from "../
|
|
3
|
-
import { Router } from "../routers";
|
|
4
|
-
import { buildDefaultProviders, resolveProviderOrder } from "./providers";
|
|
1
|
+
import { ApplicationInterface } from "../contracts/ApplicationInterface.js";
|
|
2
|
+
import { app } from "../helpers/app.js";
|
|
3
|
+
import { Router } from "../routers/index.js";
|
|
4
|
+
import { buildDefaultProviders, resolveProviderOrder } from "./providers/index.js";
|
|
5
|
+
import { readSSRBoot, readBootConfig, mergeBootConfig } from "./ssr.js";
|
|
6
|
+
import { bootBundles, loadBundles } from "./bundle.js";
|
|
7
|
+
import type { MergedBundles } from "../contracts/BundleInterface.js";
|
|
5
8
|
|
|
6
9
|
const App: ApplicationInterface = app<ApplicationInterface>();
|
|
7
10
|
|
|
@@ -9,6 +12,41 @@ const App: ApplicationInterface = app<ApplicationInterface>();
|
|
|
9
12
|
App.set<boolean>('isInitialized', false);
|
|
10
13
|
App.set<boolean>('isStarted', false);
|
|
11
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Hàng đợi `App.push(fn)` — cửa cho mã KHÔNG đi qua bundler (snippet trong
|
|
17
|
+
* layout, plugin bên thứ ba, thư viện nạp bất đồng bộ).
|
|
18
|
+
*
|
|
19
|
+
* Mẫu `dataLayer.push`: trước khi file này chạy, `window.App` là một MẢNG và
|
|
20
|
+
* `.push(fn)` chỉ xếp hàng. Ở đây ta rút hàng đợi rồi thay bằng App thật, và
|
|
21
|
+
* gắn `App.push` = chạy NGAY. Nhờ vậy CÙNG MỘT dòng gọi
|
|
22
|
+
*
|
|
23
|
+
* (window.App = window.App || []).push(fn)
|
|
24
|
+
*
|
|
25
|
+
* hoạt động ở cả ba mốc: trước khi app.js tải, trong lúc parse, và sau khi app
|
|
26
|
+
* đã boot. Tác giả plugin không phải biết mình chạy lúc nào.
|
|
27
|
+
*
|
|
28
|
+
* ⚠️ Hệ quả: `window.App` là MẢNG cho tới lúc boot. Đọc App phải đọc TRONG
|
|
29
|
+
* callback, đừng đọc ở tầng module.
|
|
30
|
+
*/
|
|
31
|
+
function drainPushQueue(): void {
|
|
32
|
+
if (typeof window === 'undefined') return;
|
|
33
|
+
const w = window as any;
|
|
34
|
+
|
|
35
|
+
const pending: unknown[] = Array.isArray(w.App) ? w.App : [];
|
|
36
|
+
|
|
37
|
+
(App as any).push = (fn: (app: ApplicationInterface) => void): void => {
|
|
38
|
+
if (typeof fn !== 'function') return;
|
|
39
|
+
try {
|
|
40
|
+
fn(App);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error('[App.push] callback ném lỗi:', err);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
w.App = App;
|
|
46
|
+
|
|
47
|
+
for (const fn of pending) (App as any).push(fn);
|
|
48
|
+
}
|
|
49
|
+
|
|
12
50
|
/**
|
|
13
51
|
* Khởi tạo app — đăng ký + boot tất cả providers theo dependency order.
|
|
14
52
|
*
|
|
@@ -26,6 +64,10 @@ App.setMethod('init', function (config: Record<string, any> = {}) {
|
|
|
26
64
|
return;
|
|
27
65
|
}
|
|
28
66
|
|
|
67
|
+
if (config.shared && typeof config.shared === 'object') {
|
|
68
|
+
App.set<Record<string, any>>('SharedData', { ...config.shared });
|
|
69
|
+
}
|
|
70
|
+
|
|
29
71
|
const providers = resolveProviderOrder(buildDefaultProviders(config));
|
|
30
72
|
for (const provider of providers) {
|
|
31
73
|
App.register(provider);
|
|
@@ -38,19 +80,55 @@ App.setMethod('init', function (config: Record<string, any> = {}) {
|
|
|
38
80
|
/**
|
|
39
81
|
* Start app — init nếu chưa, rồi start Router.
|
|
40
82
|
*
|
|
83
|
+
* Nếu phát hiện SSR boot (script saola-ssr), inject vào config.view.ssr để
|
|
84
|
+
* ViewManager + Router hydrate route đầu tiên thay vì mount mới.
|
|
85
|
+
*
|
|
41
86
|
* @example
|
|
42
87
|
* App.start(); // init với config mặc định
|
|
43
88
|
* App.start({ view: { container: '#app' } }); // init với config tùy chỉnh
|
|
44
89
|
*/
|
|
45
|
-
App.setMethod('start', function (config?: Record<string, any>) {
|
|
90
|
+
App.setMethod('start', async function (config?: Record<string, any>) {
|
|
46
91
|
if (App.isStarted) {
|
|
47
92
|
console.warn('[Bootstrap] App already started.');
|
|
48
93
|
return;
|
|
49
94
|
}
|
|
95
|
+
let bundles: MergedBundles | null = null;
|
|
50
96
|
if (!App.isInitialized) {
|
|
51
|
-
|
|
97
|
+
// Config app truyền có ưu tiên hơn boot config (window.APP_CONFIGS:
|
|
98
|
+
// routes + container từ server). Thiếu APP_CONFIGS → chỉ dùng config app.
|
|
99
|
+
const boot = readBootConfig() || {};
|
|
100
|
+
const cfg = mergeBootConfig(boot, config || {});
|
|
101
|
+
|
|
102
|
+
// SSR boot (script saola-ssr) → ssr + container cho hydrate route đầu.
|
|
103
|
+
const ssr = readSSRBoot();
|
|
104
|
+
if (ssr) {
|
|
105
|
+
cfg.view = {
|
|
106
|
+
...(cfg.view || {}),
|
|
107
|
+
ssr: { view: ssr.view, viewId: ssr.viewId },
|
|
108
|
+
container: (cfg.view && cfg.view.container) || ssr.container,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// Bundle nạp rời (theme…): server phát danh sách URL trong
|
|
112
|
+
// APP_CONFIGS.bundles. Phải await TRƯỚC init để view/service/provider
|
|
113
|
+
// của chúng có mặt lúc provider boot và lúc render route đầu.
|
|
114
|
+
bundles = await loadBundles(cfg.bundles);
|
|
115
|
+
cfg.view = {
|
|
116
|
+
...(cfg.view || {}),
|
|
117
|
+
// Bundle nạp sau ĐÈ registry của app — đúng ngữ nghĩa overlay theme.
|
|
118
|
+
registry: { ...(cfg.view?.registry || {}), ...bundles.views },
|
|
119
|
+
};
|
|
120
|
+
cfg.services = { ...(cfg.services || {}), ...bundles.services };
|
|
121
|
+
cfg.helpers = { ...(cfg.helpers || {}), ...bundles.helpers };
|
|
122
|
+
cfg.providers = [...(cfg.providers || []), ...bundles.providers];
|
|
123
|
+
|
|
124
|
+
App.init(cfg);
|
|
125
|
+
bootBundles(bundles, App);
|
|
52
126
|
}
|
|
53
127
|
|
|
128
|
+
// Sau init (View/Router/Helper đã có), TRƯỚC khi render: chỗ duy nhất mà
|
|
129
|
+
// mã ngoài cắm vào được mà chắc chắn kịp.
|
|
130
|
+
drainPushQueue();
|
|
131
|
+
|
|
54
132
|
App.get<Router>('Router').start();
|
|
55
133
|
App.isStarted = true;
|
|
56
134
|
}, true);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle nạp rời — hợp đồng + loader.
|
|
3
|
+
*
|
|
4
|
+
* Bài toán: một gói build ĐỘC LẬP (theme) phải cắm được view / service /
|
|
5
|
+
* helper / provider vào app đang chạy, mà không chia sẻ module graph với app.
|
|
6
|
+
* Cầu nối là import map: `@saolabs/client` của gói đó resolve về đúng file
|
|
7
|
+
* entry của app, nên hai bên dùng CHUNG một instance runtime. Xem
|
|
8
|
+
* docs/EXTENSION_ARCHITECTURE.md §7.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ApplicationInterface } from "../contracts/ApplicationInterface.js";
|
|
12
|
+
import type { MergedBundles, SaolaBundle } from "../contracts/BundleInterface.js";
|
|
13
|
+
import logger from "../services/LoggerService.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Khai báo một bundle. Chỉ là identity + kiểu — nó tồn tại để tên khoá là HỢP
|
|
17
|
+
* ĐỒNG chứ không phải quy ước truyền miệng, và để IDE gợi ý được.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* export default defineBundle({
|
|
21
|
+
* name: 'theme:aurora',
|
|
22
|
+
* views: { 'themes.aurora.modules.ping.index': factory },
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
export function defineBundle(bundle: SaolaBundle): SaolaBundle {
|
|
26
|
+
return bundle;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function emptyMerged(): MergedBundles {
|
|
30
|
+
return { providers: [], services: {}, helpers: {}, views: {}, boots: [], loaded: [], failed: [] };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Gộp nhiều manifest theo ĐÚNG THỨ TỰ mảng — không theo thứ tự resolve của
|
|
35
|
+
* mạng. Bundle sau ĐÈ bundle trước ở `views`/`services`/`helpers`; `providers`
|
|
36
|
+
* thì CỘNG THÊM chứ không thay, để một bundle không gỡ được provider của app.
|
|
37
|
+
*/
|
|
38
|
+
export function mergeBundles(bundles: Array<SaolaBundle | null | undefined>): MergedBundles {
|
|
39
|
+
const out = emptyMerged();
|
|
40
|
+
|
|
41
|
+
for (const bundle of bundles) {
|
|
42
|
+
if (!bundle || typeof bundle !== 'object') continue;
|
|
43
|
+
out.loaded.push(bundle.name ?? '(không tên)');
|
|
44
|
+
if (Array.isArray(bundle.providers)) out.providers.push(...bundle.providers);
|
|
45
|
+
if (bundle.services) Object.assign(out.services, bundle.services);
|
|
46
|
+
if (bundle.helpers) Object.assign(out.helpers, bundle.helpers);
|
|
47
|
+
if (bundle.views) Object.assign(out.views, bundle.views);
|
|
48
|
+
if (typeof bundle.boot === 'function') out.boots.push(bundle.boot.bind(bundle));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Nạp danh sách URL bundle rồi gộp lại.
|
|
56
|
+
*
|
|
57
|
+
* Tải SONG SONG nhưng gộp theo thứ tự mảng — thứ tự URL là thứ tự ưu tiên do
|
|
58
|
+
* server quyết định (`APP_CONFIGS.bundles`), không phải do mạng.
|
|
59
|
+
*
|
|
60
|
+
* Một URL hỏng KHÔNG làm sập boot: ghi vào `failed` rồi đi tiếp. Theme lỗi thì
|
|
61
|
+
* site chạy bằng view gốc, còn hơn trắng trang.
|
|
62
|
+
*/
|
|
63
|
+
export async function loadBundles(urls: string[] | null | undefined): Promise<MergedBundles> {
|
|
64
|
+
if (!Array.isArray(urls) || urls.length === 0) return emptyMerged();
|
|
65
|
+
|
|
66
|
+
const results = await Promise.all(urls.map(async (url): Promise<[string, SaolaBundle | null, string | null]> => {
|
|
67
|
+
try {
|
|
68
|
+
// URL đến từ runtime nên bundler không phân tích tĩnh được — đúng ý
|
|
69
|
+
// đồ. Viết literal ở đây sẽ làm GÃY build của app (rollup cố resolve
|
|
70
|
+
// một đường dẫn không có trong module graph).
|
|
71
|
+
const mod: any = await import(/* @vite-ignore */ /* webpackIgnore: true */ url);
|
|
72
|
+
// Bundle có thể khai manifest (export default) HOẶC tự đăng ký ngay
|
|
73
|
+
// trong thân module qua App.View/App.set — import đã await xong nên
|
|
74
|
+
// cả hai đều kịp trước khi render.
|
|
75
|
+
return [url, (mod?.default ?? null) as SaolaBundle | null, null];
|
|
76
|
+
} catch (err) {
|
|
77
|
+
return [url, null, String(err)];
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
|
|
81
|
+
const merged = mergeBundles(results.map(([, bundle]) => bundle));
|
|
82
|
+
for (const [url, , error] of results) {
|
|
83
|
+
if (error) {
|
|
84
|
+
merged.failed.push([url, error]);
|
|
85
|
+
logger.error(`[Bundle] Không nạp được "${url}": ${error}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return merged;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Chạy `boot()` của các bundle, sau khi App đã init. Lỗi một cái không chặn cái sau. */
|
|
93
|
+
export function bootBundles(merged: MergedBundles, app: ApplicationInterface): void {
|
|
94
|
+
for (const boot of merged.boots) {
|
|
95
|
+
try {
|
|
96
|
+
boot(app);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
logger.error('[Bundle] boot() ném lỗi:', err);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { APIClientInterface } from "../../contracts/ApiInterface";
|
|
2
|
-
import { ApiClient } from "../../
|
|
3
|
-
import { PROVIDER_NAMES } from "./provider-order";
|
|
4
|
-
import { ServiceProvider } from "./ServiceProvider";
|
|
1
|
+
import { APIClientInterface } from "../../contracts/ApiInterface.js";
|
|
2
|
+
import { ApiClient } from "../../helpers/ApiClient.js";
|
|
3
|
+
import { PROVIDER_NAMES } from "./provider-order.js";
|
|
4
|
+
import { ServiceProvider } from "./ServiceProvider.js";
|
|
5
5
|
|
|
6
6
|
export class ApiServiceProvider extends ServiceProvider {
|
|
7
7
|
readonly name = PROVIDER_NAMES.API;
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
1
|
+
import { MarkerRegistryInterface } from "../../contracts/MarkerInterface.js";
|
|
2
|
+
import { app } from "../../helpers/app.js";
|
|
3
|
+
import { MarkerRegistry, MarkerRegistryService } from "../../services/index.js";
|
|
4
|
+
import { EventService } from "../../services/EventService.js";
|
|
5
|
+
import { HttpService } from "../../services/HttpService.js";
|
|
6
|
+
import { StoreService } from "../../services/StoreService.js";
|
|
7
|
+
import HeadService from "../../services/HeadService.js";
|
|
8
|
+
import { Devtools } from "../../devtools/index.js";
|
|
9
|
+
import type { HeadServiceInterface } from "../../contracts/HeadServiceInterface.js";
|
|
10
|
+
import { PROVIDER_NAMES } from "./provider-order.js";
|
|
11
|
+
import { ServiceProvider } from "./ServiceProvider.js";
|
|
8
12
|
|
|
9
13
|
export class CoreServiceProvider extends ServiceProvider {
|
|
10
14
|
readonly name = PROVIDER_NAMES.CORE;
|
|
11
15
|
|
|
12
16
|
register(): void {
|
|
13
|
-
this.app.set<MarkerService>("Marker", app<MarkerService>(MarkerService), true);
|
|
14
17
|
this.app.set<StoreService>("Store", StoreService.instance(), true);
|
|
15
18
|
this.app.set<StoreService>("Storage", StoreService.instance(), true);
|
|
16
19
|
this.app.set<EventService>("Event", EventService.instance(), true);
|
|
17
20
|
this.app.set<HttpService>("Http", HttpService.instance(), true);
|
|
21
|
+
this.app.set<MarkerRegistryInterface>("Registry", MarkerRegistry, true);
|
|
22
|
+
this.app.set<HeadServiceInterface>("Head", HeadService, true);
|
|
23
|
+
this.app.set("Devtools", Devtools, true);
|
|
18
24
|
}
|
|
19
25
|
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { HelperService } from "../../services/HelperService";
|
|
2
|
-
import { PROVIDER_NAMES } from "./provider-order";
|
|
3
|
-
import { ServiceProvider } from "./ServiceProvider";
|
|
1
|
+
import { HelperService } from "../../services/HelperService.js";
|
|
2
|
+
import { PROVIDER_NAMES } from "./provider-order.js";
|
|
3
|
+
import { ServiceProvider } from "./ServiceProvider.js";
|
|
4
4
|
|
|
5
5
|
export class HelperServiceProvider extends ServiceProvider {
|
|
6
6
|
readonly name = PROVIDER_NAMES.HELPER;
|
|
7
7
|
readonly dependsOn = [PROVIDER_NAMES.CORE, PROVIDER_NAMES.ROUTER, PROVIDER_NAMES.VIEW];
|
|
8
8
|
|
|
9
|
+
static config: Record<string, any> = {};
|
|
10
|
+
|
|
9
11
|
register(): void {
|
|
10
12
|
this.app.set<HelperService>("Helper", new HelperService(this.app), true);
|
|
11
13
|
}
|
|
14
|
+
boot(): void {
|
|
15
|
+
if (HelperServiceProvider.config.i18n) this.app.get<HelperService>("Helper").initTranslations(HelperServiceProvider.config.i18n);
|
|
16
|
+
}
|
|
12
17
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Router } from "../../routers";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { Router } from "../../routers/index.js";
|
|
2
|
+
import { ViewManager } from "../../view/index.js";
|
|
3
|
+
import { PROVIDER_NAMES } from "./provider-order.js";
|
|
4
|
+
import { ServiceProvider } from "./ServiceProvider.js";
|
|
4
5
|
|
|
5
6
|
export class RouteServiceProvider extends ServiceProvider {
|
|
6
7
|
readonly name = PROVIDER_NAMES.ROUTER;
|
|
8
|
+
/** ROUTER phải boot SAU VIEW để ViewManager đã sẵn sàng */
|
|
7
9
|
readonly dependsOn = [PROVIDER_NAMES.VIEW];
|
|
8
10
|
static config: Record<string, any> = {};
|
|
9
11
|
|
|
@@ -12,6 +14,15 @@ export class RouteServiceProvider extends ServiceProvider {
|
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
boot(): void {
|
|
15
|
-
this.app.get<Router>("Router")
|
|
17
|
+
const router = this.app.get<Router>("Router");
|
|
18
|
+
|
|
19
|
+
// Wire ViewManager → Router (Router cần để mountView khi navigate)
|
|
20
|
+
try {
|
|
21
|
+
const vm = this.app.get<ViewManager>("View");
|
|
22
|
+
if (vm) router.setViewManager(vm);
|
|
23
|
+
} catch (_) { /* View chưa register — Router sẽ fallback qua App.View */ }
|
|
24
|
+
|
|
25
|
+
// init: load routes config + auto-wire
|
|
26
|
+
router.init(RouteServiceProvider.config);
|
|
16
27
|
}
|
|
17
28
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ApplicationInterface } from "../../contracts/ApplicationInterface";
|
|
2
|
-
import { ServiceProviderInterface } from "../../contracts/utils";
|
|
3
|
-
import { app } from "../../
|
|
4
|
-
import {
|
|
5
|
-
import { NamedServiceProvider } from "./provider-order";
|
|
1
|
+
import { ApplicationInterface } from "../../contracts/ApplicationInterface.js";
|
|
2
|
+
import { ServiceProviderInterface } from "../../contracts/utils.js";
|
|
3
|
+
import { app } from "../../helpers/app.js";
|
|
4
|
+
import { SaoObjectType, OOTEnum } from "../../types/utils.js";
|
|
5
|
+
import { NamedServiceProvider } from "./provider-order.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Base class cho Service Provider — API giống Laravel.
|
|
@@ -27,7 +27,7 @@ import { NamedServiceProvider } from "./provider-order";
|
|
|
27
27
|
* }
|
|
28
28
|
*/
|
|
29
29
|
export abstract class ServiceProvider implements ServiceProviderInterface {
|
|
30
|
-
readonly
|
|
30
|
+
readonly saoType: SaoObjectType = OOTEnum.SERVICE_PROVIDER;
|
|
31
31
|
abstract readonly name: string;
|
|
32
32
|
readonly dependsOn?: string[];
|
|
33
33
|
protected app: ApplicationInterface;
|
|
@@ -38,8 +38,8 @@ export abstract class ServiceProvider implements ServiceProviderInterface {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
initApplication(App?: ApplicationInterface): void {
|
|
41
|
-
if (!this.app || typeof this.app !== 'object' || this.app.
|
|
42
|
-
this.app = (App && App.
|
|
41
|
+
if (!this.app || typeof this.app !== 'object' || this.app.saoType !== OOTEnum.APPLICATION) {
|
|
42
|
+
this.app = (App && App.saoType === OOTEnum.APPLICATION) ? App : app<ApplicationInterface>();
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ViewManager } from "../../view";
|
|
2
|
-
import { PROVIDER_NAMES } from "./provider-order";
|
|
3
|
-
import { ServiceProvider } from "./ServiceProvider";
|
|
1
|
+
import { ViewManager } from "../../view/index.js";
|
|
2
|
+
import { PROVIDER_NAMES } from "./provider-order.js";
|
|
3
|
+
import { ServiceProvider } from "./ServiceProvider.js";
|
|
4
4
|
|
|
5
5
|
export class ViewServiceProvider extends ServiceProvider {
|
|
6
6
|
readonly name = PROVIDER_NAMES.VIEW;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ApplicationInterface } from "../../contracts/ApplicationInterface";
|
|
2
|
-
import { app } from "../../
|
|
3
|
-
import { NamedServiceProvider, PROVIDER_NAMES } from "./provider-order";
|
|
4
|
-
import { ApiServiceProvider } from "./ApiServiceProvider";
|
|
5
|
-
import { CoreServiceProvider } from "./CoreServiceProvider";
|
|
6
|
-
import { HelperServiceProvider } from "./HelperServiceProvider";
|
|
7
|
-
import { RouteServiceProvider } from "./RouteServiceProvider";
|
|
8
|
-
import { ServiceProvider } from "./ServiceProvider";
|
|
9
|
-
import { ViewServiceProvider } from "./ViewServiceProvider";
|
|
10
|
-
import { ServiceProviderInterface } from "../../contracts/ServiceProviderInterface";
|
|
11
|
-
import { OOTEnum } from "../../types/utils";
|
|
1
|
+
import { ApplicationInterface } from "../../contracts/ApplicationInterface.js";
|
|
2
|
+
import { app } from "../../helpers/app.js";
|
|
3
|
+
import { NamedServiceProvider, PROVIDER_NAMES } from "./provider-order.js";
|
|
4
|
+
import { ApiServiceProvider } from "./ApiServiceProvider.js";
|
|
5
|
+
import { CoreServiceProvider } from "./CoreServiceProvider.js";
|
|
6
|
+
import { HelperServiceProvider } from "./HelperServiceProvider.js";
|
|
7
|
+
import { RouteServiceProvider } from "./RouteServiceProvider.js";
|
|
8
|
+
import { ServiceProvider } from "./ServiceProvider.js";
|
|
9
|
+
import { ViewServiceProvider } from "./ViewServiceProvider.js";
|
|
10
|
+
import { ServiceProviderInterface } from "../../contracts/ServiceProviderInterface.js";
|
|
11
|
+
import { OOTEnum } from "../../types/utils.js";
|
|
12
12
|
|
|
13
13
|
/** Provider class type — constructor nhận optional app */
|
|
14
14
|
type ProviderClass = new (app?: ApplicationInterface) => ServiceProvider;
|
|
@@ -17,7 +17,7 @@ type ProviderClass = new (app?: ApplicationInterface) => ServiceProvider;
|
|
|
17
17
|
const SYSTEM_PROVIDER_NAMES = new Set(Object.values(PROVIDER_NAMES));
|
|
18
18
|
|
|
19
19
|
/** Tên system services — không cho phép ghi đè qua config.services */
|
|
20
|
-
const SYSTEM_SERVICE_KEYS = new Set(['
|
|
20
|
+
const SYSTEM_SERVICE_KEYS = new Set(['Store', 'Storage', 'Event', 'Http', 'View', 'Router', 'Helper', 'API']);
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Chuyển `config.services` dạng { name: Class } thành NamedServiceProvider[].
|
|
@@ -26,7 +26,7 @@ const SYSTEM_SERVICE_KEYS = new Set(['Marker', 'Store', 'Storage', 'Event', 'Htt
|
|
|
26
26
|
* services: { Auth: AuthService, Toast: ToastService }
|
|
27
27
|
* → 2 providers, mỗi cái dependsOn ['core'], register = app.set(name, new Class(app))
|
|
28
28
|
*/
|
|
29
|
-
function servicesFromMap(map: Record<string,
|
|
29
|
+
function servicesFromMap(map: Record<string, any>): ServiceProviderInterface[] {
|
|
30
30
|
const appInstance = app<ApplicationInterface>();
|
|
31
31
|
return Object.entries(map)
|
|
32
32
|
.filter(([name]) => {
|
|
@@ -36,15 +36,44 @@ function servicesFromMap(map: Record<string, new (app: ApplicationInterface) =>
|
|
|
36
36
|
}
|
|
37
37
|
return true;
|
|
38
38
|
})
|
|
39
|
-
.map(([name,
|
|
39
|
+
.map(([name, value]) => ({
|
|
40
40
|
name,
|
|
41
41
|
dependsOn: [PROVIDER_NAMES.CORE],
|
|
42
42
|
register() {
|
|
43
|
-
|
|
43
|
+
// Bundle nạp rời (theme) hay gửi INSTANCE hoặc object thuần chứ
|
|
44
|
+
// không phải class — `new` vô điều kiện sẽ ném "is not a
|
|
45
|
+
// constructor". Chỉ dựng khi thật sự là class.
|
|
46
|
+
const isClass = typeof value === 'function' && value.prototype;
|
|
47
|
+
appInstance.set(name, isClass ? new value(appInstance) : value);
|
|
44
48
|
}
|
|
45
49
|
}));
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
/**
|
|
53
|
+
* `config.helpers` = { tên: fn } → MỘT provider gộp, phụ thuộc `helper`.
|
|
54
|
+
*
|
|
55
|
+
* Không gán tay sau `init()`: `App.Helper` chỉ tồn tại sau khi
|
|
56
|
+
* HelperServiceProvider register, nên phải để resolveProviderOrder xếp chỗ.
|
|
57
|
+
* Gán tay thì provider nào đọc helper trong boot() của mình sẽ nhận undefined.
|
|
58
|
+
*/
|
|
59
|
+
function helpersFromMap(map: Record<string, any>): ServiceProviderInterface[] {
|
|
60
|
+
const appInstance = app<ApplicationInterface>();
|
|
61
|
+
if (!map || Object.keys(map).length === 0) return [];
|
|
62
|
+
|
|
63
|
+
return [{
|
|
64
|
+
name: 'bundle.helpers',
|
|
65
|
+
dependsOn: [PROVIDER_NAMES.HELPER],
|
|
66
|
+
register() {
|
|
67
|
+
const helper = appInstance.get<Record<string, any>>('Helper');
|
|
68
|
+
if (!helper) {
|
|
69
|
+
console.warn('[Bootstrap] Helper chưa sẵn sàng, bỏ qua config.helpers.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
Object.assign(helper, map);
|
|
73
|
+
}
|
|
74
|
+
}];
|
|
75
|
+
}
|
|
76
|
+
|
|
48
77
|
/**
|
|
49
78
|
* Tạo danh sách providers mặc định.
|
|
50
79
|
*
|
|
@@ -60,6 +89,7 @@ export function buildDefaultProviders(config: Record<string, any> = {}): NamedSe
|
|
|
60
89
|
// Set static config cho default providers trước khi tạo instance
|
|
61
90
|
ViewServiceProvider.config = config.view || {};
|
|
62
91
|
RouteServiceProvider.config = config.router || {};
|
|
92
|
+
HelperServiceProvider.config = { i18n: config.i18n };
|
|
63
93
|
ApiServiceProvider.config = config.api || {};
|
|
64
94
|
const App = app<ApplicationInterface>();
|
|
65
95
|
const defaults: NamedServiceProvider[] = [
|
|
@@ -75,6 +105,11 @@ export function buildDefaultProviders(config: Record<string, any> = {}): NamedSe
|
|
|
75
105
|
? servicesFromMap(config.services)
|
|
76
106
|
: [];
|
|
77
107
|
|
|
108
|
+
// config.helpers: { tên: fn } → một provider phụ thuộc `helper`
|
|
109
|
+
const helperProviders = config.helpers
|
|
110
|
+
? helpersFromMap(config.helpers)
|
|
111
|
+
: [];
|
|
112
|
+
|
|
78
113
|
// config.providers: (ProviderClass | NamedServiceProvider)[] → instantiate classes
|
|
79
114
|
const customProviders: NamedServiceProvider[] = Array.isArray(config.providers)
|
|
80
115
|
? config.providers
|
|
@@ -90,5 +125,5 @@ export function buildDefaultProviders(config: Record<string, any> = {}): NamedSe
|
|
|
90
125
|
})
|
|
91
126
|
: [];
|
|
92
127
|
|
|
93
|
-
return [...defaults, ...serviceProviders, ...customProviders];
|
|
128
|
+
return [...defaults, ...serviceProviders, ...helperProviders, ...customProviders];
|
|
94
129
|
}
|