@saolabs/client 1.0.0 → 1.0.2
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 +17 -15
- package/dist/src/core/app/Application.d.ts.map +1 -1
- package/dist/src/core/app/Application.js +41 -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 +74 -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 +125 -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 +13 -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/hellpers/utils.d.ts +2 -2
- package/dist/src/core/hellpers/utils.js +4 -4
- package/dist/src/core/helpers/ApiClient.d.ts +58 -0
- package/dist/src/core/helpers/ApiClient.d.ts.map +1 -0
- package/dist/src/core/helpers/ApiClient.js +131 -0
- 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/helpers/app.js +63 -0
- 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/helpers/utils.d.ts +26 -0
- package/dist/src/core/helpers/utils.d.ts.map +1 -0
- package/dist/src/core/helpers/utils.js +96 -0
- 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 +58 -31
- package/src/core/bootstrap/app.ts +80 -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 +136 -0
- package/src/core/cache/ViewCache.ts +1 -1
- package/src/core/cache/index.ts +1 -1
- package/src/core/contracts/ApplicationInterface.ts +13 -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/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
|
@@ -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>>();
|
|
@@ -97,7 +99,7 @@ export class Application implements ApplicationInterface {
|
|
|
97
99
|
'__store',
|
|
98
100
|
]; // Để track dynamic properties nếu cần
|
|
99
101
|
|
|
100
|
-
__store: Map<
|
|
102
|
+
__store: Map<any, { isOverridable: boolean, value: any }> = new Map(); // Store cho dynamic properties nếu cần
|
|
101
103
|
|
|
102
104
|
[key: string]: any; // Cho phép dynamic properties nếu cần
|
|
103
105
|
|
|
@@ -179,6 +181,18 @@ export class Application implements ApplicationInterface {
|
|
|
179
181
|
*/
|
|
180
182
|
instance<T>(key: ServiceKey<T>, value: T): this {
|
|
181
183
|
this.singletons.set(key, value);
|
|
184
|
+
if (typeof key === 'string' && !this.ownProperties.includes(key)) {
|
|
185
|
+
this.__store.set(key, { value, isOverridable: true });
|
|
186
|
+
Object.defineProperty(this, key, {
|
|
187
|
+
get: () => this.__store.get(key)?.value,
|
|
188
|
+
set: (newValue) => {
|
|
189
|
+
this.__store.set(key, { value: newValue, isOverridable: true });
|
|
190
|
+
this.singletons.set(key, newValue);
|
|
191
|
+
},
|
|
192
|
+
configurable: true,
|
|
193
|
+
enumerable: false,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
182
196
|
return this;
|
|
183
197
|
}
|
|
184
198
|
|
|
@@ -289,6 +303,15 @@ export class Application implements ApplicationInterface {
|
|
|
289
303
|
(provider as any).initApplication();
|
|
290
304
|
}
|
|
291
305
|
provider.register();
|
|
306
|
+
|
|
307
|
+
// Đăng ký SAU khi app đã boot — plugin nạp muộn qua App.push(), hoặc
|
|
308
|
+
// provider của theme cắm vào giữa phiên. boot() vòng lặp chính đã chạy
|
|
309
|
+
// xong và có cờ chặn, nên nếu không gọi ở đây thì provider chỉ chạy nửa
|
|
310
|
+
// vòng đời: register() có, boot() không, và KHÔNG có lỗi nào phát ra.
|
|
311
|
+
if (this.booted && typeof provider.boot === 'function') {
|
|
312
|
+
provider.boot();
|
|
313
|
+
}
|
|
314
|
+
|
|
292
315
|
return this;
|
|
293
316
|
}
|
|
294
317
|
|
|
@@ -342,31 +365,35 @@ export class Application implements ApplicationInterface {
|
|
|
342
365
|
}
|
|
343
366
|
|
|
344
367
|
|
|
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
|
-
}
|
|
368
|
+
set<T = any>(name: any, value: T, isOne: boolean = false): void {
|
|
349
369
|
if (this.__store.has(name) && this.__store.get(name)?.isOverridable === false) {
|
|
350
370
|
return; // Không cho ghi đè lên thuộc tính không thể override
|
|
351
371
|
}
|
|
372
|
+
const isString = typeof name === 'string';
|
|
373
|
+
if (isString && this.ownProperties.includes(name)) {
|
|
374
|
+
return; // Không cho ghi đè lên thuộc tính có sẵn
|
|
375
|
+
}
|
|
352
376
|
this.__store.set(name, { value, isOverridable: !isOne });
|
|
353
377
|
this.singletons.set(name, value); // Sync → DI container
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
378
|
+
if (isString) {
|
|
379
|
+
Object.defineProperty(this, name, {
|
|
380
|
+
get: () => this.__store.get(name)?.value,
|
|
381
|
+
set: (newValue) => {
|
|
382
|
+
if (this.__store.has(name) && this.__store.get(name)?.isOverridable === false) {
|
|
383
|
+
return; // Không cho ghi đè nếu isOverridable là false
|
|
384
|
+
}
|
|
385
|
+
this.__store.set(name, { value: newValue, isOverridable: !isOne });
|
|
386
|
+
this.singletons.set(name, newValue); // Sync → DI container
|
|
387
|
+
},
|
|
388
|
+
configurable: isOne ? false : true,
|
|
389
|
+
enumerable: false,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
366
392
|
}
|
|
367
393
|
|
|
368
|
-
get<T = any>(name:
|
|
369
|
-
|
|
394
|
+
get<T = any>(name: any): T {
|
|
395
|
+
const isString = typeof name === 'string';
|
|
396
|
+
if (isString && this.ownProperties.includes(name)) {
|
|
370
397
|
return (this as any)[name]; // Trả về thuộc tính có sẵn
|
|
371
398
|
}
|
|
372
399
|
// Check __store first (registered via set())
|
|
@@ -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
|
*
|
|
@@ -38,19 +76,55 @@ App.setMethod('init', function (config: Record<string, any> = {}) {
|
|
|
38
76
|
/**
|
|
39
77
|
* Start app — init nếu chưa, rồi start Router.
|
|
40
78
|
*
|
|
79
|
+
* Nếu phát hiện SSR boot (script saola-ssr), inject vào config.view.ssr để
|
|
80
|
+
* ViewManager + Router hydrate route đầu tiên thay vì mount mới.
|
|
81
|
+
*
|
|
41
82
|
* @example
|
|
42
83
|
* App.start(); // init với config mặc định
|
|
43
84
|
* App.start({ view: { container: '#app' } }); // init với config tùy chỉnh
|
|
44
85
|
*/
|
|
45
|
-
App.setMethod('start', function (config?: Record<string, any>) {
|
|
86
|
+
App.setMethod('start', async function (config?: Record<string, any>) {
|
|
46
87
|
if (App.isStarted) {
|
|
47
88
|
console.warn('[Bootstrap] App already started.');
|
|
48
89
|
return;
|
|
49
90
|
}
|
|
91
|
+
let bundles: MergedBundles | null = null;
|
|
50
92
|
if (!App.isInitialized) {
|
|
51
|
-
|
|
93
|
+
// Config app truyền có ưu tiên hơn boot config (window.APP_CONFIGS:
|
|
94
|
+
// routes + container từ server). Thiếu APP_CONFIGS → chỉ dùng config app.
|
|
95
|
+
const boot = readBootConfig() || {};
|
|
96
|
+
const cfg = mergeBootConfig(boot, config || {});
|
|
97
|
+
|
|
98
|
+
// SSR boot (script saola-ssr) → ssr + container cho hydrate route đầu.
|
|
99
|
+
const ssr = readSSRBoot();
|
|
100
|
+
if (ssr) {
|
|
101
|
+
cfg.view = {
|
|
102
|
+
...(cfg.view || {}),
|
|
103
|
+
ssr: { view: ssr.view, viewId: ssr.viewId },
|
|
104
|
+
container: (cfg.view && cfg.view.container) || ssr.container,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Bundle nạp rời (theme…): server phát danh sách URL trong
|
|
108
|
+
// APP_CONFIGS.bundles. Phải await TRƯỚC init để view/service/provider
|
|
109
|
+
// của chúng có mặt lúc provider boot và lúc render route đầu.
|
|
110
|
+
bundles = await loadBundles(cfg.bundles);
|
|
111
|
+
cfg.view = {
|
|
112
|
+
...(cfg.view || {}),
|
|
113
|
+
// Bundle nạp sau ĐÈ registry của app — đúng ngữ nghĩa overlay theme.
|
|
114
|
+
registry: { ...(cfg.view?.registry || {}), ...bundles.views },
|
|
115
|
+
};
|
|
116
|
+
cfg.services = { ...(cfg.services || {}), ...bundles.services };
|
|
117
|
+
cfg.helpers = { ...(cfg.helpers || {}), ...bundles.helpers };
|
|
118
|
+
cfg.providers = [...(cfg.providers || []), ...bundles.providers];
|
|
119
|
+
|
|
120
|
+
App.init(cfg);
|
|
121
|
+
bootBundles(bundles, App);
|
|
52
122
|
}
|
|
53
123
|
|
|
124
|
+
// Sau init (View/Router/Helper đã có), TRƯỚC khi render: chỗ duy nhất mà
|
|
125
|
+
// mã ngoài cắm vào được mà chắc chắn kịp.
|
|
126
|
+
drainPushQueue();
|
|
127
|
+
|
|
54
128
|
App.get<Router>('Router').start();
|
|
55
129
|
App.isStarted = true;
|
|
56
130
|
}, 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
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { NamedServiceProvider, resolveProviderOrder, PROVIDER_NAMES } from './provider-order';
|
|
2
|
-
export type { ProviderName } from './provider-order';
|
|
3
|
-
export { ServiceProvider } from './ServiceProvider';
|
|
4
|
-
export { buildDefaultProviders } from './default-providers';
|
|
5
|
-
export { CoreServiceProvider } from './CoreServiceProvider';
|
|
6
|
-
export { ViewServiceProvider } from './ViewServiceProvider';
|
|
7
|
-
export { RouteServiceProvider } from './RouteServiceProvider';
|
|
8
|
-
export { HelperServiceProvider } from './HelperServiceProvider';
|
|
9
|
-
export { ApiServiceProvider } from './ApiServiceProvider';
|
|
1
|
+
export { NamedServiceProvider, resolveProviderOrder, PROVIDER_NAMES } from './provider-order.js';
|
|
2
|
+
export type { ProviderName } from './provider-order.js';
|
|
3
|
+
export { ServiceProvider } from './ServiceProvider.js';
|
|
4
|
+
export { buildDefaultProviders } from './default-providers.js';
|
|
5
|
+
export { CoreServiceProvider } from './CoreServiceProvider.js';
|
|
6
|
+
export { ViewServiceProvider } from './ViewServiceProvider.js';
|
|
7
|
+
export { RouteServiceProvider } from './RouteServiceProvider.js';
|
|
8
|
+
export { HelperServiceProvider } from './HelperServiceProvider.js';
|
|
9
|
+
export { ApiServiceProvider } from './ApiServiceProvider.js';
|