@_tc/template-core 0.2.12 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.skills/tc-component-usage-skills/SKILL.md +7 -9
- package/.skills/tc-component-usage-skills/reference/component-api.md +2 -2
- package/.skills/tc-component-usage-skills/reference/examples.md +9 -9
- package/.skills/tc-component-usage-skills/reference/patterns.md +5 -5
- package/.skills/tc-component-usage-skills/reference/template-core-frontend.md +1 -1
- package/.skills/tc-generator/SKILL.md +31 -14
- package/.skills/tc-generator/reference/example.md +4 -4
- package/.skills/tc-generator/reference/model-schema.md +9 -5
- package/.skills/tc-generator/reference/runtime-extensions.md +9 -7
- package/AGENT_README.md +66 -33
- package/CHANGE.md +48 -5
- package/README.md +161 -46
- package/cjs/app/controller/ssr.js +1 -0
- package/cjs/app/controller/view.js +1 -1
- package/cjs/app/html/shell.js +36 -0
- package/cjs/app/middleware.js +1 -1
- package/cjs/app/router/ssr.js +1 -0
- package/cjs/app/router/view.js +1 -1
- package/cjs/app/ssr/html.js +17 -0
- package/cjs/app/ssr/manifest.js +2 -0
- package/cjs/app/view/entry.tpl +2 -37
- package/cjs/bundler/buildBE.js +1 -1
- package/cjs/bundler/buildSSR.js +1 -0
- package/cjs/bundler/entryCollect.js +1 -0
- package/cjs/bundler/feSharedConfig.js +1 -0
- package/cjs/bundler/index.js +1 -1
- package/cjs/bundler/ssrClientManifest.js +1 -0
- package/cjs/bundler/ssrEntries.js +1 -0
- package/cjs/bundler/utils.js +3 -3
- package/cjs/packages/common/i18n/index.js +1 -1
- package/cjs/packages/common/index.js +1 -1
- package/cjs/packages/common/ssr/hydration.js +1 -0
- package/cjs/packages/common/ssr/index.js +1 -0
- package/cjs/packages/core/index.js +1 -1
- package/cjs/packages/core/loader/controller.js +1 -1
- package/cjs/packages/core/loader/extend.js +1 -1
- package/cjs/packages/core/loader/merge.js +1 -0
- package/cjs/packages/core/loader/middleware.js +1 -1
- package/cjs/packages/core/loader/model.js +1 -1
- package/cjs/packages/core/loader/router-schema.js +1 -1
- package/cjs/packages/core/loader/router.js +1 -1
- package/cjs/packages/core/loader/service.js +1 -1
- package/cjs/packages/core/paths.js +1 -1
- package/cjs/scripts/vite-build/build.js +3 -3
- package/cjs/scripts/vite-build/collect.js +1 -1
- package/cjs/scripts/vite-build/dts.js +1 -1
- package/cjs/scripts/vite-build/normalize.js +1 -1
- package/cjs/ssrSharedData/outputPaths.js +1 -0
- package/esm/app/controller/ssr.js +215 -0
- package/esm/app/controller/view.js +26 -25
- package/esm/app/html/shell.js +69 -0
- package/esm/app/middleware.js +18 -9
- package/esm/app/router/ssr.js +8 -0
- package/esm/app/router/view.js +5 -4
- package/esm/app/ssr/html.js +90 -0
- package/esm/app/ssr/manifest.js +47 -0
- package/esm/app/view/entry.tpl +2 -37
- package/esm/bundler/buildBE.js +1 -1
- package/esm/bundler/buildSSR.js +126 -0
- package/esm/bundler/entryCollect.js +45 -0
- package/esm/bundler/feSharedConfig.js +143 -0
- package/esm/bundler/index.js +4 -2
- package/esm/bundler/ssrClientManifest.js +14 -0
- package/esm/bundler/ssrEntries.js +13 -0
- package/esm/bundler/utils.js +248 -255
- package/esm/packages/common/i18n/index.js +5 -1
- package/esm/packages/common/index.js +4 -2
- package/esm/packages/common/ssr/hydration.js +55 -0
- package/esm/packages/common/ssr/index.js +20 -0
- package/esm/packages/core/index.js +42 -42
- package/esm/packages/core/loader/controller.js +11 -9
- package/esm/packages/core/loader/extend.js +20 -16
- package/esm/packages/core/loader/merge.js +7 -0
- package/esm/packages/core/loader/middleware.js +11 -12
- package/esm/packages/core/loader/model.js +2 -2
- package/esm/packages/core/loader/router-schema.js +22 -15
- package/esm/packages/core/loader/router.js +32 -26
- package/esm/packages/core/loader/service.js +11 -9
- package/esm/packages/core/paths.js +9 -1
- package/esm/scripts/vite-build/build.js +88 -83
- package/esm/scripts/vite-build/collect.js +31 -27
- package/esm/scripts/vite-build/dts.js +1 -1
- package/esm/scripts/vite-build/normalize.js +6 -3
- package/esm/ssrSharedData/outputPaths.js +33 -0
- package/fe/frontend/apps/dash/Dashboard.d.ts +5 -1
- package/fe/frontend/apps/dash/Dashboard.js +22 -13
- package/fe/frontend/apps/dash/types.d.ts +2 -0
- package/fe/frontend/src/api/baseInfo.d.ts +1 -1
- package/fe/frontend/src/common/CRUD/CRUD.js +1 -1
- package/fe/frontend/src/common/CRUD/index.js +1 -1
- package/fe/frontend/src/common/menu.d.ts +1 -1
- package/fe/frontend/src/common/menu.js +8 -7
- package/fe/frontend/src/common/request.js +1 -1
- package/fe/frontend/src/common/schemaForm.d.ts +1 -0
- package/fe/frontend/src/common/schemaForm.js +12 -0
- package/fe/frontend/src/components/AsyncSelect/AsyncSelect.d.ts +1 -1
- package/fe/frontend/src/components/Router/basename.d.ts +3 -0
- package/fe/frontend/src/components/Router/basename.js +11 -0
- package/fe/frontend/src/components/Router/index.d.ts +1 -1
- package/fe/frontend/src/components/Router/index.js +3 -1
- package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/builtIn.d.ts +1 -1
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.d.ts +1 -1
- package/fe/frontend/src/defaultPages/SchemaPage/schemaType.d.ts +2 -2
- package/fe/frontend/src/defaultPages/SchemaPage/utils/schemaConversion.d.ts +1 -1
- package/fe/frontend/src/defaultPages/SidebarSlotPage/SidebarSlotContainer.d.ts +2 -1
- package/fe/frontend/src/defaultPages/SidebarSlotPage/SidebarSlotContainer.js +8 -4
- package/fe/frontend/src/defaultPages/SidebarSlotPageTmp.js +2 -1
- package/fe/frontend/src/exportStore.js +2 -2
- package/fe/frontend/src/hooks/useCurrentMenuData.d.ts +1 -1
- package/fe/frontend/src/hooks/useCurrentMenuData.js +2 -2
- package/fe/frontend/src/hooks/useRouterParams.js +4 -3
- package/fe/frontend/src/index.d.ts +1 -0
- package/fe/frontend/src/index.js +4 -3
- package/fe/frontend/src/main.js +2 -0
- package/fe/frontend/src/stores/mode.d.ts +15 -2
- package/fe/frontend/src/stores/mode.js +19 -5
- package/fe/frontend/src/typing/window.d.ts +2 -0
- package/fe/packages/common/LRUCache.js +2 -0
- package/fe/packages/common/array/index.js +37 -0
- package/fe/packages/common/cache/index.js +2 -0
- package/fe/packages/common/guards/index.js +19 -1
- package/fe/packages/common/http/index.js +1 -1
- package/fe/packages/common/i18n/index.js +8 -4
- package/fe/packages/common/i18n/locales.js +1 -1
- package/fe/packages/common/i18n/types.d.ts +1 -0
- package/fe/packages/common/i18n/types.js +0 -0
- package/fe/packages/common/index.d.ts +1 -0
- package/fe/packages/common/index.js +17 -0
- package/fe/packages/common/log/index.js +146 -0
- package/fe/packages/common/number/index.js +11 -0
- package/fe/packages/common/object/filterEmpty.js +2 -1
- package/fe/packages/common/object/filtereEmpty.js +2 -0
- package/fe/packages/common/object/index.js +20 -0
- package/fe/packages/common/ssr/hydration.d.ts +23 -0
- package/fe/packages/common/ssr/hydration.js +88 -0
- package/fe/packages/common/ssr/index.d.ts +8 -0
- package/fe/packages/common/ssr/index.js +52 -0
- package/fe/packages/common/string/index.js +32 -0
- package/fe/packages/common/types/index.js +0 -0
- package/fe/packages/react/hooks/index.d.ts +2 -0
- package/fe/packages/react/hooks/index.js +3 -1
- package/fe/packages/react/hooks/useHydrationData.d.ts +2 -0
- package/fe/packages/react/hooks/useHydrationData.js +23 -0
- package/fe/packages/react/hooks/useSSR.d.ts +6 -0
- package/fe/packages/react/hooks/useSSR.js +46 -0
- package/fe/packages/react/ui/components/DataTable/index.js +16 -15
- package/fe/packages/react/ui/components/Form/SchemaForm/data.d.ts +3 -2
- package/fe/packages/react/ui/components/Form/SchemaForm/data.js +5 -6
- package/fe/packages/react/ui/components/Form/SchemaForm/index.d.ts +1 -0
- package/fe/packages/react/ui/components/Form/SchemaForm/index.js +2 -2
- package/fe/packages/react/ui/components/Form/index.js +2 -1
- package/fe/packages/react/ui/components/Input/Input.js +5 -1
- package/fe/packages/react/ui/components/Popup/Popup.js +6 -1
- package/fe/packages/react/ui/components/index.js +2 -1
- package/fe/packages/react/ui/components/testPage/demos/core/DataTableDemo.js +241 -211
- package/fe/packages/react/ui/components/testPage/demos/core/DataTableDemo2.js +1 -1
- package/fe/packages/react/ui/i18n/I18nProvider.js +4 -0
- package/fe/packages/react/ui/index.js +2 -1
- package/fe/ssr/apps/dash/dash.entry.d.ts +13 -0
- package/fe/ssr/apps/dash/dash.entry.js +162 -0
- package/fe/ssr/apps/demo/demo.entry.d.ts +13 -0
- package/fe/ssr/apps/demo/demo.entry.js +38 -0
- package/fe/ssr/apps/server-data/server-data.entry.d.ts +26 -0
- package/fe/ssr/apps/server-data/server-data.entry.js +275 -0
- package/fe/ssr/apps/ui-components/ui-components.entry.d.ts +5 -0
- package/fe/ssr/apps/ui-components/ui-components.entry.js +17 -0
- package/fe/ssr/components/StreamingRender/StreamingCache.d.ts +2 -0
- package/fe/ssr/components/StreamingRender/StreamingCache.js +31 -0
- package/fe/ssr/components/StreamingRender/StreamingRender.d.ts +3 -0
- package/fe/ssr/components/StreamingRender/StreamingRender.js +48 -0
- package/fe/ssr/components/StreamingRender/StreamingScript.d.ts +8 -0
- package/fe/ssr/components/StreamingRender/StreamingScript.js +58 -0
- package/fe/ssr/components/StreamingRender/index.d.ts +4 -0
- package/fe/ssr/components/StreamingRender/index.js +5 -0
- package/fe/ssr/components/StreamingRender/type.d.ts +9 -0
- package/fe/ssr/components/StreamingRender/type.js +0 -0
- package/fe/ssr/components/index.d.ts +2 -0
- package/fe/ssr/components/index.js +2 -0
- package/fe/ssr/createSSREntry.d.ts +6 -0
- package/fe/ssr/createSSREntry.js +42 -0
- package/fe/ssr/hooks/index.d.ts +1 -0
- package/fe/ssr/hooks/index.js +2 -0
- package/fe/ssr/hooks/useSuspensePromise.d.ts +1 -0
- package/fe/ssr/hooks/useSuspensePromise.js +31 -0
- package/fe/ssr/index.d.ts +4 -0
- package/fe/ssr/index.js +6 -0
- package/fe/ssr/types.d.ts +13 -0
- package/fe/ssr/types.js +0 -0
- package/{model → models}/frontend/src/typing/window.d.ts +2 -0
- package/{model → models}/packages/common/i18n/types.d.ts +1 -0
- package/{model → models}/packages/common/index.d.ts +1 -0
- package/models/packages/common/ssr/hydration.d.ts +23 -0
- package/models/packages/common/ssr/index.d.ts +8 -0
- package/{model → models}/packages/react/ui/components/Form/SchemaForm/data.d.ts +3 -2
- package/{model → models}/packages/react/ui/components/Form/SchemaForm/index.d.ts +1 -0
- package/package.json +43 -6
- package/types/app/controller/ssr.d.ts +14 -0
- package/types/app/html/shell.d.ts +101 -0
- package/types/app/router/ssr.d.ts +6 -0
- package/types/app/ssr/html.d.ts +53 -0
- package/types/app/ssr/manifest.d.ts +17 -0
- package/types/app/typings.d.ts +2 -0
- package/types/bundler/buildSSR.d.ts +56 -0
- package/types/bundler/entryCollect.d.ts +36 -0
- package/types/bundler/feSharedConfig.d.ts +35 -0
- package/types/bundler/index.d.ts +4 -0
- package/types/bundler/ssrClientManifest.d.ts +4 -0
- package/types/bundler/ssrEntries.d.ts +23 -0
- package/types/bundler/state.d.ts +2 -2
- package/types/bundler/utils.d.ts +35 -2
- package/types/config/config.default.d.ts +10 -0
- package/types/packages/common/i18n/types.d.ts +2 -0
- package/types/packages/common/index.d.ts +1 -0
- package/types/packages/common/ssr/hydration.d.ts +72 -0
- package/types/packages/common/ssr/index.d.ts +34 -0
- package/types/packages/core/loader/merge.d.ts +3 -0
- package/types/packages/core/loader/model.d.ts +2 -2
- package/types/packages/core/paths.d.ts +5 -0
- package/types/packages/core/types.d.ts +10 -1
- package/types/scripts/vite-build/build.d.ts +1 -0
- package/types/scripts/vite-build/types.d.ts +3 -0
- package/types/ssrSharedData/outputPaths.d.ts +59 -0
- package/fe/packages/react/hooks/useWatch.test.js +0 -24
- package/fe/packages/react/ui/assets/table/no-result.js +0 -4
- package/fe/packages/react/ui/components/DataTable/dataTableWidth.test.js +0 -39
- package/fe/packages/react/ui/components/InputNumber/inputNumberUtils.test.js +0 -59
- /package/.skills/tc-generator/reference/project-template/{model → models}/product/mode.js +0 -0
- /package/.skills/tc-generator/reference/project-template/{model → models}/product/project/default.js +0 -0
- /package/fe/{model → models}/types/data/button.d.ts +0 -0
- /package/fe/{model → models}/types/data/component.d.ts +0 -0
- /package/fe/{model → models}/types/data/fetchInfo.d.ts +0 -0
- /package/fe/{model → models}/types/data/schema.d.ts +0 -0
- /package/fe/{model → models}/types/data/search.d.ts +0 -0
- /package/fe/{model → models}/types/index.d.ts +0 -0
- /package/fe/{model → models}/types/menuType.d.ts +0 -0
- /package/fe/{model → models}/types/model.d.ts +0 -0
- /package/{model → models}/frontend/extended/SchemaForm/data.d.ts +0 -0
- /package/{model → models}/frontend/src/common/auth/index.d.ts +0 -0
- /package/{model → models}/frontend/src/common/fetchErrorShow.d.ts +0 -0
- /package/{model → models}/frontend/src/common/language.d.ts +0 -0
- /package/{model → models}/frontend/src/common/logFn/index.d.ts +0 -0
- /package/{model → models}/frontend/src/common/request.d.ts +0 -0
- /package/{model → models}/frontend/src/components/AsyncSelect/AsyncSelect.d.ts +0 -0
- /package/{model → models}/frontend/src/components/AsyncSelect/index.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/components/CallCom/DetailPanel.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/components/CallCom/PopFrom.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/components/CallCom/builtIn.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/data/eventInfo.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/data/index.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/hooks/useComConfig.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/schemaType.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/utils/permissions.d.ts +0 -0
- /package/{model → models}/frontend/src/defaultPages/SchemaPage/utils/validator.d.ts +0 -0
- /package/{model → models}/frontend/src/hooks/useText.d.ts +0 -0
- /package/{model → models}/frontend/src/language/en-US.d.ts +0 -0
- /package/{model → models}/frontend/src/language/index.d.ts +0 -0
- /package/{model → models}/frontend/src/language/resources.d.ts +0 -0
- /package/{model → models}/frontend/src/language/zh-CN.d.ts +0 -0
- /package/{model → models}/frontend/src/stores/apiFreezer.d.ts +0 -0
- /package/{model → models}/frontend/src/stores/schemaEventBus.d.ts +0 -0
- /package/{model → models}/frontend/src/stores/schemaStore.d.ts +0 -0
- /package/{model → models}/frontend/src/typing/scalability.d.ts +0 -0
- /package/{model/model → models/models}/index.d.ts +0 -0
- /package/{model/model → models/models}/test.d.ts +0 -0
- /package/{model/model → models/models}/types/data/button.d.ts +0 -0
- /package/{model/model → models/models}/types/data/component.d.ts +0 -0
- /package/{model/model → models/models}/types/data/fetchInfo.d.ts +0 -0
- /package/{model/model → models/models}/types/data/schema.d.ts +0 -0
- /package/{model/model → models/models}/types/data/search.d.ts +0 -0
- /package/{model/model → models/models}/types/index.d.ts +0 -0
- /package/{model/model → models/models}/types/menuType.d.ts +0 -0
- /package/{model/model → models/models}/types/model.d.ts +0 -0
- /package/{model → models}/packages/common/array/index.d.ts +0 -0
- /package/{model → models}/packages/common/cache/LRUCache.d.ts +0 -0
- /package/{model → models}/packages/common/cache/index.d.ts +0 -0
- /package/{model → models}/packages/common/guards/index.d.ts +0 -0
- /package/{model → models}/packages/common/http/index.d.ts +0 -0
- /package/{model → models}/packages/common/i18n/default.d.ts +0 -0
- /package/{model → models}/packages/common/i18n/en-US.d.ts +0 -0
- /package/{model → models}/packages/common/i18n/index.d.ts +0 -0
- /package/{model → models}/packages/common/i18n/locales.d.ts +0 -0
- /package/{model → models}/packages/common/log/index.d.ts +0 -0
- /package/{model → models}/packages/common/number/index.d.ts +0 -0
- /package/{model → models}/packages/common/object/filterEmpty.d.ts +0 -0
- /package/{model → models}/packages/common/object/index.d.ts +0 -0
- /package/{model → models}/packages/common/rafTimer.d.ts +0 -0
- /package/{model → models}/packages/common/string/index.d.ts +0 -0
- /package/{model → models}/packages/common/types/index.d.ts +0 -0
- /package/{model → models}/packages/react/hooks/useBreadcrumb.d.ts +0 -0
- /package/{model → models}/packages/react/hooks/useExecuteOnce.d.ts +0 -0
- /package/{model → models}/packages/react/hooks/useLanguage.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Button/Button.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Button/SubmitButton.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Button/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Card/Card.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Card/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Checkbox/Checkbox.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Checkbox/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/ConfirmDialog/ConfirmDialog.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/ConfirmDialog/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/DataTable/ActionBtn.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/DataTable/dataTableWidth.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/DataTable/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/Calendar.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/Date.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/LocaleContext.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/LocaleProvider.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/TimePicker.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/data.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/dateLocaleStore.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/dropdownPositioning.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Date/locales.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Drawer/Drawer.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Drawer/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Dropdown/Dropdown.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Dropdown/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Form/Form.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Form/FormItem.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Form/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Form/useForm.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/ImagePreview/ImagePreview.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/ImagePreview/PreviewImage.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/ImagePreview/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Input/Input.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Input/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/InputNumber/InputNumber.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/InputNumber/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/InputNumber/inputNumberUtils.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Label/Label.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Label/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Layout/Layout.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Layout/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Loading/Loading.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Loading/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/Menu.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/MenuContext.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/MenuItem.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/SubMenu.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/menuTypes.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Menu/utils.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Message/Message.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Message/MessageManager.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Message/data.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Message/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Modal/Modal.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Modal/ModalManager.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Modal/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Notification/Notification.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Notification/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Overlay/Overlay.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Overlay/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Pagination/Pagination.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Pagination/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Popup/Popup.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Popup/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Radio/Radio.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Radio/RadioGroup.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Radio/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Search/Search.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Search/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Select/Select.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Select/dropdownPositioning.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Select/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Skeleton/Skeleton.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Skeleton/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Switch/Switch.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Switch/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/TableSearch/TableSearch.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/TableSearch/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/TableSearch/lang.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/TableSearch/tableSearchLocaleStore.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Tabs/Tabs.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Tabs/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Textarea/Textarea.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Textarea/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Tooltip/Tooltip.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Tooltip/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/TreeSelect/TreeSelect.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/TreeSelect/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Upload/ImageUpload.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Upload/Upload.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/Upload/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/breadcrumb/breadcrumb.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/breadcrumb/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/hooks/useDropdownPositioning.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/hooks/useInputController.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/table/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/table/table.d.ts +0 -0
- /package/{model → models}/packages/react/ui/components/types/baseType.d.ts +0 -0
- /package/{model → models}/packages/react/ui/i18n/I18nProvider.d.ts +0 -0
- /package/{model → models}/packages/react/ui/i18n/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/i18n/useI18n.d.ts +0 -0
- /package/{model → models}/packages/react/ui/index.d.ts +0 -0
- /package/{model → models}/packages/react/ui/lib/createStoreHook.d.ts +0 -0
- /package/{model → models}/packages/react/ui/lib/export.d.ts +0 -0
- /package/{model → models}/packages/react/ui/lib/utils.d.ts +0 -0
- /package/{model → models}/packages/react/ui/stores/breadcrumb.d.ts +0 -0
- /package/{model → models}/packages/react/ui/stores/language.d.ts +0 -0
- /package/{model → models}/packages/react/ui/types/index.d.ts +0 -0
- /package/{model → models}/typings/type.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @_tc/template-core
|
|
2
2
|
|
|
3
|
-
TemplateCore 是一个基于 TypeScript、Koa、React 的后台框架包。它把后端约定式加载、前端 Dashboard、Schema CRUD 页面、
|
|
3
|
+
TemplateCore 是一个基于 TypeScript、Koa、React 的后台框架包。它把后端约定式加载、前端 Dashboard、Schema CRUD 页面、models 类型和类型扩展放到同一个 npm 包里,项目只需要按目录补充自己的 `app/`、`models/`、`frontend/`。
|
|
4
4
|
|
|
5
5
|
预览 & 文档地址:https://t-c-s-p.allomg.qzz.io/preview
|
|
6
6
|
|
|
@@ -34,7 +34,9 @@ my-admin/
|
|
|
34
34
|
│ ├── src/ # 库代码
|
|
35
35
|
│ ├── apps/ # 应用入口
|
|
36
36
|
│ └── extended/ # 扩展点
|
|
37
|
-
├──
|
|
37
|
+
├── ssr/
|
|
38
|
+
│ └── apps/ # SSR 页面入口,可选
|
|
39
|
+
├── models/
|
|
38
40
|
│ └── product/
|
|
39
41
|
│ ├── mode.ts
|
|
40
42
|
│ └── project/
|
|
@@ -55,7 +57,7 @@ async function main() {
|
|
|
55
57
|
await serverStart({
|
|
56
58
|
name: 'my-admin',
|
|
57
59
|
baseDir: join(__dirname, '.'),
|
|
58
|
-
|
|
60
|
+
pageBasePath: '/',
|
|
59
61
|
additionalPublicPaths: [join(__dirname, 'dist/public')],
|
|
60
62
|
})
|
|
61
63
|
|
|
@@ -76,7 +78,8 @@ main().catch((error) => {
|
|
|
76
78
|
| --- | --- | --- | --- | --- |
|
|
77
79
|
| `name` | `string` | 否 | - | 应用名称 |
|
|
78
80
|
| `baseDir` | `string` | 否 | - | 项目根目录,通常为 `join(__dirname, '.')` |
|
|
79
|
-
| `
|
|
81
|
+
| `pageBasePath` | `string` | 否 | `'/'` | 页面访问前缀,所有前端页面路由的基础路径 |
|
|
82
|
+
| `ssrPageBasePath` | `string` | 否 | `'/fessr'` | SSR 页面访问前缀,如 `/tssr` 会让 SSR 页面路由变成 `/tssr/:page` |
|
|
80
83
|
| `homePage` | `string` | 否 | - | 应用首页路径 |
|
|
81
84
|
| `additionalPublicPaths` | `string | string[]` | 否 | - | 追加静态资源目录;如需同时作为 Nunjucks 模板查找目录,建议传绝对路径数组 |
|
|
82
85
|
|
|
@@ -141,6 +144,96 @@ await buildFE('prod', {
|
|
|
141
144
|
await buildFE('prod', { minifyHtml: true })
|
|
142
145
|
```
|
|
143
146
|
|
|
147
|
+
### SSR 页面(可选)
|
|
148
|
+
|
|
149
|
+
SSR 入口放在根级 `ssr/apps/{page}/{page}.entry.tsx`。SSR 和 CSR 并存,SSR 页面默认通过 `/fessr/:page` 访问,不影响现有 `frontend/apps/` 页面。
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
my-admin/
|
|
153
|
+
└── ssr/
|
|
154
|
+
└── apps/
|
|
155
|
+
└── hello/
|
|
156
|
+
└── hello.entry.tsx
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
import { createSSREntry } from '@_tc/template-core/ssr/createSSREntry'
|
|
161
|
+
import type { SSRPageMetaResolver, SSRPropsContext } from '@_tc/template-core/ssr'
|
|
162
|
+
|
|
163
|
+
interface HelloProps {
|
|
164
|
+
name: string
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function HelloPage({ name }: HelloProps) {
|
|
168
|
+
return <h1>Hello, {name}</h1>
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export async function getServerProps(context: SSRPropsContext) {
|
|
172
|
+
return { name: (context.query.name as string) || 'SSR' }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const pageTitle: SSRPageMetaResolver<HelloProps> = ({ props }) => `Hello, ${props.name}`
|
|
176
|
+
export const pageDescription: SSRPageMetaResolver<HelloProps> = ({ path }) => `SSR hello page at ${path}`
|
|
177
|
+
|
|
178
|
+
export default HelloPage
|
|
179
|
+
|
|
180
|
+
createSSREntry(HelloPage)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
SSR 运行时会通过 React streaming bootstrap 动态 import 客户端入口。页面包含 `Suspense` 边界时,服务端可以先输出 shell / fallback,浏览器侧先启动 hydration,pending 内容后续继续 stream;如果页面没有 `Suspense` 边界,hydration 时机通常会接近完整 root HTML 到达之后。完整机制见 [Streaming Bootstrap 说明](./ssr/STREAMING_BOOTSTRAP.md)。
|
|
184
|
+
|
|
185
|
+
`pageTitle` / `pageDescription` 可以导出字符串,也可以导出同步或异步函数。函数会在 `getServerProps()` 之后执行,入参包含 `params`、`query`、`path`、`app`、`ctx` 和 `props`。
|
|
186
|
+
|
|
187
|
+
组件级流式异步数据可以使用 `StreamingRender`。它会在服务端 Suspense 中等待 `getData()`,把结果随 HTML 片段用 JSON script 注入,客户端 hydration 时优先复用这份数据。
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { StreamingRender } from '@_tc/template-core/ssr/components'
|
|
191
|
+
|
|
192
|
+
function OverviewPanel() {
|
|
193
|
+
return (
|
|
194
|
+
<StreamingRender
|
|
195
|
+
keyName="overview"
|
|
196
|
+
fallback={<div>Loading...</div>}
|
|
197
|
+
getData={loadOverview}
|
|
198
|
+
>
|
|
199
|
+
{(data) => <OverviewView data={data} />}
|
|
200
|
+
</StreamingRender>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`keyName` 需要在页面内稳定且唯一;`getData()` 的返回值必须可 JSON 序列化,并且会进入 HTML,不能包含 token、密钥等敏感信息。客户端找不到对应注入数据时也可能执行 `getData()`,因此数据函数需要兼容浏览器 fallback,或在函数内部显式区分服务端和客户端逻辑。底层 Suspense Promise hook 可从 `@_tc/template-core/ssr/hooks` 或 `@_tc/template-core/ssr/hooks/useSuspensePromise` 引入。
|
|
206
|
+
|
|
207
|
+
启动时构建 SSR 双产物:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
import { join } from 'path'
|
|
211
|
+
import { serverStart } from '@_tc/template-core'
|
|
212
|
+
import { buildSSR, watchSSRFiles } from '@_tc/template-core/bundler'
|
|
213
|
+
|
|
214
|
+
const baseDir = join(__dirname, '.')
|
|
215
|
+
|
|
216
|
+
await serverStart({
|
|
217
|
+
name: 'my-admin',
|
|
218
|
+
baseDir,
|
|
219
|
+
ssrPageBasePath: '/fessr',
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
await buildSSR({ baseDir, output: 'run' })
|
|
223
|
+
await watchSSRFiles({ baseDir, output: 'run' })
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
访问:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
http://localhost:9000/fessr/hello
|
|
230
|
+
http://localhost:9000/fessr/hello?name=TemplateCore
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
`buildSSR()` 会构建私有 `{ssrPrivateRoot}/ssr-server/{page}.mjs`、私有 `{ssrPrivateRoot}/ssr-manifest/manifest.json`,并把 SSR hydration 入口并入 FE browser build。浏览器侧静态资源走普通 `/dist/assets/*`,可与 CSR 入口共享 chunk;SSR HTML 会根据 manifest 生成 preload,并通过 React bootstrap dynamic import 启动对应客户端入口。服务端会从 `{publicPath}/../.tc/ssr` 查找 server bundle 和 manifest。`/dist/ssr-server/*` 和 `/dist/.vite/*` 会被拦截为 404,避免私有产物或误放文件直连暴露。如果 `output` 使用自定义目录,需要把对应 public 根目录加入 `additionalPublicPaths`。
|
|
234
|
+
|
|
235
|
+
`*.entry.tsx` 会被 server/client 两次构建处理,顶层代码需要同时兼容 Node 和浏览器。Node-only 逻辑建议放到 `*.server.ts`,并在 `getServerProps()` 内动态导入;浏览器 API 需要放到 `useEffect` 或 `typeof window !== 'undefined'` 守卫之后。`getServerProps()` 运行在 Node 侧,不要直接复用依赖 `window` / `localStorage` 签名上下文的前端 API 层。
|
|
236
|
+
|
|
144
237
|
配置文件:
|
|
145
238
|
|
|
146
239
|
```ts
|
|
@@ -161,7 +254,7 @@ export default {
|
|
|
161
254
|
http://localhost:9000/dash?projk=demo
|
|
162
255
|
```
|
|
163
256
|
|
|
164
|
-
`projk` 对应 `
|
|
257
|
+
`projk` 对应 `models/{modelKey}/project/{projectKey}.ts` 里的 `projectKey`。
|
|
165
258
|
|
|
166
259
|
## 内置功能
|
|
167
260
|
|
|
@@ -179,23 +272,30 @@ http://localhost:9000/dash?projk=demo
|
|
|
179
272
|
- 内置 UI 组件:提供丰富的 React 组件库,详见下方"内置 UI 组件"章节。
|
|
180
273
|
- API 中间件:错误处理、静态资源、body parser、项目上下文、接口签名、参数校验。
|
|
181
274
|
- 前端构建:扫描框架和项目的 `frontend/**/*.entry.{ts,tsx,js,jsx}`,输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
|
|
275
|
+
- SSR 页面:扫描框架和项目的 `ssr/apps/**/*.entry.{ts,tsx,js,jsx}`,输出 server/client 双产物并通过 `/fessr/:page` 服务端渲染。
|
|
182
276
|
- 类型扩展:支持扩展 SchemaForm、SchemaTable 单元格渲染组件、CallCom、KoaApp。
|
|
183
277
|
|
|
184
278
|
## 常用公开入口
|
|
185
279
|
|
|
186
|
-
完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/common/request`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks` 等子路径。
|
|
280
|
+
完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/common/request`、`./ssr`、`./ssr/createSSREntry`、`./ssr/components`、`./ssr/components/StreamingRender`、`./ssr/hooks`、`./ssr/hooks/useSuspensePromise`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks` 等子路径。
|
|
187
281
|
|
|
188
282
|
| 入口 | 用途 |
|
|
189
283
|
| --- | --- |
|
|
190
284
|
| `@_tc/template-core` | 服务启动、基础 Controller/Service、Koa 类型 |
|
|
191
|
-
| `@_tc/template-core/bundler` |
|
|
285
|
+
| `@_tc/template-core/bundler` | 构建入口,提供 `buildFE`、`buildBE`、`buildSSR`、`watchSSRFiles` |
|
|
286
|
+
| `@_tc/template-core/ssr` | SSR 类型与运行时辅助,导出 `SSRPropsContext`、`SSRPageMetaResolver`、`StreamingRender`、`useSuspensePromise` |
|
|
287
|
+
| `@_tc/template-core/ssr/createSSREntry` | SSR 页面客户端 hydration 工厂 |
|
|
288
|
+
| `@_tc/template-core/ssr/components` | SSR 组件汇总入口,导出 `StreamingRender` |
|
|
289
|
+
| `@_tc/template-core/ssr/components/StreamingRender` | `StreamingRender` 显式子路径 |
|
|
290
|
+
| `@_tc/template-core/ssr/hooks` | SSR hooks 汇总入口,导出 `useSuspensePromise` |
|
|
291
|
+
| `@_tc/template-core/ssr/hooks/useSuspensePromise` | `useSuspensePromise` 显式子路径 |
|
|
192
292
|
| `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、Dash 路由扩展、请求方法、SchemaPage 事件、token 工具、共享状态和内置前端组件 |
|
|
193
293
|
| `@_tc/template-core/fe/main` | 前端初始化入口 |
|
|
194
294
|
| `@_tc/template-core/fe/common/request` | 请求实例、请求方法和请求类型的显式子路径 |
|
|
195
295
|
| `@_tc/template-core/fe/rc` | UI/SchemaForm 组件和类型 |
|
|
196
296
|
| `@_tc/template-core/fe/rc/hooks` | React hooks 汇总入口 |
|
|
197
297
|
| `@_tc/template-core/fe/tailwind_ui.css` | 前端全局样式入口,源码对应 `frontend/src/main.css` |
|
|
198
|
-
| `@_tc/template-core/
|
|
298
|
+
| `@_tc/template-core/models` | model 配置类型 |
|
|
199
299
|
|
|
200
300
|
### 后端类型
|
|
201
301
|
|
|
@@ -245,14 +345,14 @@ export const demoRouter = ((app, router) => {
|
|
|
245
345
|
`model` 是后台菜单、项目和 Schema 页面的数据源。框架会读取:
|
|
246
346
|
|
|
247
347
|
```text
|
|
248
|
-
|
|
249
|
-
|
|
348
|
+
models/{modelKey}/mode.ts
|
|
349
|
+
models/{modelKey}/project/{projectKey}.ts
|
|
250
350
|
```
|
|
251
351
|
|
|
252
|
-
`mode.ts`
|
|
352
|
+
`mode.ts` 定义模型基础配置:
|
|
253
353
|
|
|
254
354
|
```ts
|
|
255
|
-
import type { ModelDataType } from '@_tc/template-core/
|
|
355
|
+
import type { ModelDataType } from '@_tc/template-core/models'
|
|
256
356
|
|
|
257
357
|
const model: ModelDataType = {
|
|
258
358
|
mode: 'MB',
|
|
@@ -373,14 +473,14 @@ export default {
|
|
|
373
473
|
- `project` 会继承同目录上层 `mode`。
|
|
374
474
|
- 对象递归合并,`project` 覆盖 `mode`。
|
|
375
475
|
- 数组按 `key` 合并:同 key 覆盖,不同 key 新增。
|
|
376
|
-
- `
|
|
476
|
+
- `models/index.ts` 或 `models/index.js` 会被 loader 跳过。
|
|
377
477
|
|
|
378
478
|
### model 数组合并示例
|
|
379
479
|
|
|
380
480
|
假设 `mode.ts` 定义了两个菜单项:
|
|
381
481
|
|
|
382
482
|
```ts
|
|
383
|
-
//
|
|
483
|
+
// models/product/mode.ts
|
|
384
484
|
export default {
|
|
385
485
|
name: '商品后台',
|
|
386
486
|
menu: [
|
|
@@ -411,7 +511,7 @@ export default {
|
|
|
411
511
|
`project/demo.ts` 可以:
|
|
412
512
|
|
|
413
513
|
```ts
|
|
414
|
-
//
|
|
514
|
+
// models/product/project/demo.ts
|
|
415
515
|
export default {
|
|
416
516
|
name: 'Demo 企业商品后台',
|
|
417
517
|
menu: [
|
|
@@ -553,9 +653,23 @@ app/router-schema/**/*.(js|ts) -> app.routerSchema
|
|
|
553
653
|
app/extends/*.(js|ts) -> app.extends
|
|
554
654
|
config/config.default.(js|ts) -> app.config
|
|
555
655
|
config/config.{env}.(js|ts) -> app.config
|
|
556
|
-
|
|
656
|
+
models/**/*.(js|ts) -> 内置 project service 按需读取的项目模型配置
|
|
557
657
|
```
|
|
558
658
|
|
|
659
|
+
### 后端约定文件的模块格式
|
|
660
|
+
|
|
661
|
+
TemplateCore 包本身提供 ESM/CJS 入口,业务项目可以用 `import` 引入包。但上面这些后端约定文件是由 loader 扫描真实文件路径后同步加载的,当前按 `require()` 语义处理,并只扫描 `.js` / `.ts`。
|
|
662
|
+
|
|
663
|
+
因此后端约定文件需要满足 CommonJS 加载语义:
|
|
664
|
+
|
|
665
|
+
- 普通 CommonJS 项目可以使用 `.js` + `module.exports`。
|
|
666
|
+
- TypeScript 项目可以使用 `.ts` + `export default`,loader 会把 `.ts` 按 CommonJS 方式转译后加载。
|
|
667
|
+
- 如果业务项目声明了 `"type": "module"`,不要把 `.js` 后端约定文件写成原生 ESM 作为稳定用法,也不要在该作用域下使用 `.js` + `module.exports`。
|
|
668
|
+
- `"type": "module"` 项目如需保留 `.js` 后端约定文件,请在 `app/`、`config/` 或 `models/` 下增加局部 `package.json`:`{ "type": "commonjs" }`。
|
|
669
|
+
- `.mjs`、顶层 `await`、依赖原生 ESM 语义的后端约定文件当前不作为支持约定。
|
|
670
|
+
|
|
671
|
+
推荐分层:启动脚本、构建脚本和前端代码可以使用 ESM;`config/`、`app/`、`models/` 里的后端约定文件保持 CommonJS 加载语义。
|
|
672
|
+
|
|
559
673
|
内置扩展:
|
|
560
674
|
|
|
561
675
|
- `app.extends.$fetch`:Node 侧基于 `fetch` 的 axios 风格请求实例,支持 `get/post/put/patch/delete` 和 `create(config)`。
|
|
@@ -1101,7 +1215,7 @@ Schema 表单校验会把 AJV keyword 映射到内置语言 key,覆盖 `requir
|
|
|
1101
1215
|
|
|
1102
1216
|
非必填字段为空时会跳过 AJV 校验,空值包括 `undefined`、`null`、空字符串、空数组和空对象。
|
|
1103
1217
|
|
|
1104
|
-
如果需要扩展更多 AJV
|
|
1218
|
+
如果需要扩展更多 AJV 文案,需要在 TemplateCore 源码中补充后重新发布:
|
|
1105
1219
|
|
|
1106
1220
|
1. `frontend/src/defaultPages/SchemaPage/utils/validator.ts` 的 `formatError()` 映射。
|
|
1107
1221
|
2. `frontend/src/language/zh-CN.ts` 和 `frontend/src/language/en-US.ts` 文案。
|
|
@@ -1140,15 +1254,15 @@ initThemeMode()
|
|
|
1140
1254
|
applyThemeMode('dark', true)
|
|
1141
1255
|
```
|
|
1142
1256
|
|
|
1143
|
-
RAF
|
|
1257
|
+
RAF 风格计时器通过 `@_tc/template-core/fe` 对外提供,浏览器优先使用 `requestAnimationFrame`,缺少 RAF 时自动降级到 `setTimeout`。
|
|
1144
1258
|
|
|
1145
1259
|
`@_tc/template-core/fe/rc` 和 `@_tc/template-core/fe/rc/hooks` 也会随发布包提供对应 UI 与 hooks 入口;hooks 汇总入口包含 `useBreadcrumb`、`useExecuteOnce`、`useInit`、`useLanguage`、`usePagination`、`useRefState`、`useWatch`。
|
|
1146
1260
|
|
|
1147
|
-
`useRefState` 支持可选的 `delayTiming` 参数,传入大于 0 的值时会延迟 state
|
|
1261
|
+
`useRefState` 支持可选的 `delayTiming` 参数,传入大于 0 的值时会延迟 state 提交,并复用包内浏览器优先、Node/SSR 自动降级的计时器实现。
|
|
1148
1262
|
|
|
1149
1263
|
### 前端请求封装详解
|
|
1150
1264
|
|
|
1151
|
-
|
|
1265
|
+
框架内置的请求封装通过 `@_tc/template-core/fe` 和 `@_tc/template-core/fe/common/request` 对外提供,底层使用原生 `fetch` API,实现了类似 Axios 的接口和拦截器机制,提供了签名、鉴权、错误处理等能力。
|
|
1152
1266
|
|
|
1153
1267
|
**基础配置**:
|
|
1154
1268
|
- `BASE_URL`:固定为 `/api`
|
|
@@ -1259,7 +1373,7 @@ try {
|
|
|
1259
1373
|
|
|
1260
1374
|
## 样式与 Tailwind V4
|
|
1261
1375
|
|
|
1262
|
-
使用内置前端或 UI 组件时,需要引入包内样式。默认
|
|
1376
|
+
使用内置前端或 UI 组件时,需要引入包内样式。默认 Dashboard 入口已经包含包内全局样式;如果项目侧自定义入口、只使用 `fe/rc` 组件,或希望样式入口更明确,建议显式引入:
|
|
1263
1377
|
|
|
1264
1378
|
```ts
|
|
1265
1379
|
// frontend/xxx/xxx.entry.tsx
|
|
@@ -1274,7 +1388,7 @@ import '@_tc/template-core/fe/tailwind_ui.css'
|
|
|
1274
1388
|
|
|
1275
1389
|
/* 扫描项目源码 */
|
|
1276
1390
|
@source "./**/*.{js,ts,jsx,tsx}";
|
|
1277
|
-
@source "../
|
|
1391
|
+
@source "../models/**/*.{js,ts,jsx,tsx}";
|
|
1278
1392
|
```
|
|
1279
1393
|
|
|
1280
1394
|
Tailwind V4 默认会忽略 `node_modules` 和 `.gitignore` 中的文件。如果没有使用上面的 `tailwind_ui.css`,或者项目侧构建链路绕过了 TemplateCore 的样式入口,需要手动把包加入 Tailwind 扫描:
|
|
@@ -1284,7 +1398,7 @@ Tailwind V4 默认会忽略 `node_modules` 和 `.gitignore` 中的文件。如
|
|
|
1284
1398
|
@import "tailwindcss";
|
|
1285
1399
|
|
|
1286
1400
|
@source "./**/*.{js,ts,jsx,tsx}";
|
|
1287
|
-
@source "../
|
|
1401
|
+
@source "../models/**/*.{js,ts,jsx,tsx}";
|
|
1288
1402
|
@source "../node_modules/@_tc/template-core";
|
|
1289
1403
|
```
|
|
1290
1404
|
|
|
@@ -1478,7 +1592,7 @@ frontend/report/index.html yes
|
|
|
1478
1592
|
frontend/report/report.html yes
|
|
1479
1593
|
```
|
|
1480
1594
|
|
|
1481
|
-
不要在插槽文件里写 `<!DOCTYPE html>`、`<html>`、`<body>` 或 `<div id="root"></div>`。页面外壳由 TemplateCore 的 `app/view/entry.tpl` 统一生成,`window._basePath`、`window._projKey`、`window._signKey`、`window.appOptions` 也由它注入。
|
|
1595
|
+
不要在插槽文件里写 `<!DOCTYPE html>`、`<html>`、`<body>` 或 `<div id="root"></div>`。页面外壳由 TemplateCore 的 `app/view/entry.tpl` 统一生成,`window._basePath`、`window._projKey`、`window._signKey`、`window._renderMode`、`window._isSSR`、`window.appOptions` 也由它注入。
|
|
1482
1596
|
|
|
1483
1597
|
扩展 Dashboard 路由:
|
|
1484
1598
|
|
|
@@ -1579,12 +1693,12 @@ import { buildBE } from '@_tc/template-core/bundler'
|
|
|
1579
1693
|
|
|
1580
1694
|
await buildBE({
|
|
1581
1695
|
rootDir: process.cwd(),
|
|
1582
|
-
input: ['index.ts', 'index.js', 'app', 'config', '
|
|
1696
|
+
input: ['index.ts', 'index.js', 'app', 'config', 'models'],
|
|
1583
1697
|
outDir: 'dist',
|
|
1584
1698
|
format: 'cjs',
|
|
1585
1699
|
alias: {
|
|
1586
1700
|
'@app': './app',
|
|
1587
|
-
'@model': './
|
|
1701
|
+
'@model': './models',
|
|
1588
1702
|
},
|
|
1589
1703
|
})
|
|
1590
1704
|
```
|
|
@@ -1604,7 +1718,7 @@ await buildBE({
|
|
|
1604
1718
|
import chokidar from 'chokidar'
|
|
1605
1719
|
import { buildBE } from '@_tc/template-core/bundler'
|
|
1606
1720
|
|
|
1607
|
-
const input = ['index.ts', 'index.js', 'app', 'config', '
|
|
1721
|
+
const input = ['index.ts', 'index.js', 'app', 'config', 'models']
|
|
1608
1722
|
|
|
1609
1723
|
let building = false
|
|
1610
1724
|
let pending = false
|
|
@@ -1626,7 +1740,7 @@ async function runBuild() {
|
|
|
1626
1740
|
format: 'cjs',
|
|
1627
1741
|
alias: {
|
|
1628
1742
|
'@app': './app',
|
|
1629
|
-
'@model': './
|
|
1743
|
+
'@model': './models',
|
|
1630
1744
|
},
|
|
1631
1745
|
})
|
|
1632
1746
|
console.log('[buildBE] done')
|
|
@@ -1671,7 +1785,7 @@ chokidar
|
|
|
1671
1785
|
默认会在当前工作目录构建这些入口:
|
|
1672
1786
|
|
|
1673
1787
|
```ts
|
|
1674
|
-
['index.ts', 'index.js', 'app', 'config', '
|
|
1788
|
+
['index.ts', 'index.js', 'app', 'config', 'models']
|
|
1675
1789
|
```
|
|
1676
1790
|
|
|
1677
1791
|
不存在的默认入口会自动跳过;如果没有任何匹配源码,构建仍会失败。输出到 `dist`,格式为 `cjs`。默认 `outputStructure: "preserve"` 按源路径输出,`bundleDependencies: false` 会 external Node 内置模块和 npm 包,不会把依赖打进产物。`buildBE` 会按同一组 input 扫描并复制内置白名单资源扩展,主要覆盖 `app`、`config`、`model` 目录。
|
|
@@ -1680,12 +1794,12 @@ chokidar
|
|
|
1680
1794
|
|
|
1681
1795
|
```ts
|
|
1682
1796
|
await buildBE({
|
|
1683
|
-
input: ['app', 'config', '
|
|
1797
|
+
input: ['app', 'config', 'models'],
|
|
1684
1798
|
outDir: 'dist',
|
|
1685
1799
|
format: ['es', 'cjs'],
|
|
1686
1800
|
alias: {
|
|
1687
1801
|
'@app': './app',
|
|
1688
|
-
'@model': './
|
|
1802
|
+
'@model': './models',
|
|
1689
1803
|
},
|
|
1690
1804
|
})
|
|
1691
1805
|
```
|
|
@@ -1707,7 +1821,7 @@ await buildBE({
|
|
|
1707
1821
|
|
|
1708
1822
|
```ts
|
|
1709
1823
|
await buildBE({
|
|
1710
|
-
input: ['app', 'config', '
|
|
1824
|
+
input: ['app', 'config', 'models'],
|
|
1711
1825
|
allowMissingInput: true,
|
|
1712
1826
|
})
|
|
1713
1827
|
```
|
|
@@ -1743,8 +1857,8 @@ export default components
|
|
|
1743
1857
|
// frontend/extended/dash/routeGuard.ts
|
|
1744
1858
|
import type { DashRouteGuard } from '@_tc/template-core/fe'
|
|
1745
1859
|
|
|
1746
|
-
const dashRouteGuard: DashRouteGuard = ({ isLoggedIn }) => {
|
|
1747
|
-
if (!isLoggedIn) return '/login'
|
|
1860
|
+
const dashRouteGuard: DashRouteGuard = ({ isLoggedIn, isSSR }) => {
|
|
1861
|
+
if (!isLoggedIn) return isSSR ? '/login?from=ssr' : '/login'
|
|
1748
1862
|
}
|
|
1749
1863
|
|
|
1750
1864
|
export default dashRouteGuard
|
|
@@ -1754,6 +1868,7 @@ export default dashRouteGuard
|
|
|
1754
1868
|
|
|
1755
1869
|
- 返回 `string`:框架使用 `window.location.href` 跳转,登录页不需要在 Dash 路由下。
|
|
1756
1870
|
- 返回非 `string`:中断 Dashboard 内置重定向,使用方可自行跳转或处理提示。
|
|
1871
|
+
- 入参包含 `renderMode: 'csr' | 'ssr'` 和 `isSSR`,可区分 SSR hydration 后的守卫跳转和普通 CSR 跳转。
|
|
1757
1872
|
- `DashRouteGuardResult` 是 `string | undefined`;`undefined`(包括已登录分支的隐式返回)也会打断 Dashboard 内置重定向。
|
|
1758
1873
|
- 没有自定义 `routeGuard` 文件时,框架使用兜底空对象,不影响默认 Dashboard 重定向。
|
|
1759
1874
|
|
|
@@ -1830,9 +1945,9 @@ CallCom 是 SchemaPage 中的弹窗、抽屉、面板类组件。内置组件有
|
|
|
1830
1945
|
|
|
1831
1946
|
```ts
|
|
1832
1947
|
// typing/template-core.d.ts
|
|
1833
|
-
import '@_tc/template-core/
|
|
1948
|
+
import '@_tc/template-core/models'
|
|
1834
1949
|
|
|
1835
|
-
declare module '@_tc/template-core/
|
|
1950
|
+
declare module '@_tc/template-core/models' {
|
|
1836
1951
|
export namespace CallComNamespace {
|
|
1837
1952
|
interface ConfigMap {
|
|
1838
1953
|
auditPanel: {
|
|
@@ -1951,9 +2066,9 @@ cover: {
|
|
|
1951
2066
|
|
|
1952
2067
|
```ts
|
|
1953
2068
|
// typing/template-core.d.ts
|
|
1954
|
-
import '@_tc/template-core/
|
|
2069
|
+
import '@_tc/template-core/models'
|
|
1955
2070
|
|
|
1956
|
-
declare module '@_tc/template-core/
|
|
2071
|
+
declare module '@_tc/template-core/models' {
|
|
1957
2072
|
export namespace SchemaTableNamespace {
|
|
1958
2073
|
interface RenderComponentPropsMap {
|
|
1959
2074
|
PriceCell: {
|
|
@@ -2017,7 +2132,7 @@ price: {
|
|
|
2017
2132
|
|
|
2018
2133
|
```json
|
|
2019
2134
|
{
|
|
2020
|
-
"include": ["app/**/*", "
|
|
2135
|
+
"include": ["app/**/*", "models/**/*", "frontend/**/*", "typing/**/*.d.ts"]
|
|
2021
2136
|
}
|
|
2022
2137
|
```
|
|
2023
2138
|
|
|
@@ -2044,9 +2159,9 @@ declare module '@_tc/template-core/fe/rc' {
|
|
|
2044
2159
|
|
|
2045
2160
|
```ts
|
|
2046
2161
|
// typing/template-core.d.ts
|
|
2047
|
-
import '@_tc/template-core/
|
|
2162
|
+
import '@_tc/template-core/models'
|
|
2048
2163
|
|
|
2049
|
-
declare module '@_tc/template-core/
|
|
2164
|
+
declare module '@_tc/template-core/models' {
|
|
2050
2165
|
interface ModelModeMap {
|
|
2051
2166
|
portal: {
|
|
2052
2167
|
portalConfig: {
|
|
@@ -2061,7 +2176,7 @@ declare module '@_tc/template-core/model' {
|
|
|
2061
2176
|
使用新 `mode`:
|
|
2062
2177
|
|
|
2063
2178
|
```ts
|
|
2064
|
-
import type { ModelDataType } from '@_tc/template-core/
|
|
2179
|
+
import type { ModelDataType } from '@_tc/template-core/models'
|
|
2065
2180
|
|
|
2066
2181
|
const model: ModelDataType<'portal'> = {
|
|
2067
2182
|
mode: 'portal',
|
|
@@ -2080,7 +2195,7 @@ export default model
|
|
|
2080
2195
|
继续使用内置管理后台时:
|
|
2081
2196
|
|
|
2082
2197
|
```ts
|
|
2083
|
-
import type { ModelDataType } from '@_tc/template-core/
|
|
2198
|
+
import type { ModelDataType } from '@_tc/template-core/models'
|
|
2084
2199
|
|
|
2085
2200
|
const model: ModelDataType<'MB'> = {
|
|
2086
2201
|
mode: 'MB',
|
|
@@ -2096,7 +2211,7 @@ const model: ModelDataType<'MB'> = {
|
|
|
2096
2211
|
扩展目标:
|
|
2097
2212
|
|
|
2098
2213
|
```ts
|
|
2099
|
-
declare module '@_tc/template-core/
|
|
2214
|
+
declare module '@_tc/template-core/models' {
|
|
2100
2215
|
export namespace CallComNamespace {
|
|
2101
2216
|
interface ConfigMap {}
|
|
2102
2217
|
interface OptionMap {}
|
|
@@ -2113,7 +2228,7 @@ declare module '@_tc/template-core/model' {
|
|
|
2113
2228
|
扩展目标:
|
|
2114
2229
|
|
|
2115
2230
|
```ts
|
|
2116
|
-
declare module '@_tc/template-core/
|
|
2231
|
+
declare module '@_tc/template-core/models' {
|
|
2117
2232
|
export namespace SchemaTableNamespace {
|
|
2118
2233
|
interface RenderComponentPropsMap {}
|
|
2119
2234
|
}
|
|
@@ -2203,7 +2318,7 @@ cp -R node_modules/@_tc/template-core/.skills/tc-component-usage-skills "${CODEX
|
|
|
2203
2318
|
|
|
2204
2319
|
## 注意事项
|
|
2205
2320
|
|
|
2206
|
-
- 不要在项目代码里引用 `dist/fe/*`、`dist/
|
|
2321
|
+
- 不要在项目代码里引用 `dist/fe/*`、`dist/models/*` 这类构建产物路径。
|
|
2207
2322
|
- npm 使用方只使用公开入口:`@_tc/template-core/*`。
|
|
2208
2323
|
- SchemaForm 和 CallCom 的类型扩展、运行时注册都要做,少一个就只会“类型通过但页面不显示”或“页面能配但类型报错”。
|
|
2209
2324
|
- `model` 数组合并依赖稳定 `key`。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require(`../../_virtual/_rolldown/runtime.js`),t=require(`../../packages/common/ssr/hydration.js`),n=require(`../../ssrSharedData/outputPaths.js`),r=require(`../html/shell.js`),i=require(`../ssr/html.js`),a=require(`../ssr/manifest.js`);let o=require(`node:fs`);o=e.__toESM(o);let s=require(`node:path`);s=e.__toESM(s);let c=require(`node:stream`),l=require(`node:url`);var u=/^[A-Za-z0-9_-]+$/,d=1e4,f=3e4;function p(e){return e instanceof Error?e:Error(String(e))}async function m(e,t,n){let r=typeof e==`function`?await e(t):e;return r==null?n:String(r)}function h(e){e.compress=!1}function g(e,t,n={}){let r=new c.Writable({write(e,n,r){if(t.destroyed){r(Error(`SSR response stream is already closed.`));return}if(t.write(e,n)){r();return}t.once(`drain`,r)},final(e){if(t.destroyed){e();return}t.end(()=>{n.onComplete?.(),e()})},destroy(e,n){e&&!t.destroyed&&t.destroy(e),n()}});t.once(`close`,()=>{!t.readableEnded&&!r.destroyed&&(n.onAbort?.(),e.abort(Error(`SSR response stream closed before rendering completed.`)),r.destroy(Error(`SSR response stream closed before rendering completed.`)))}),t.once(`error`,t=>{n.onAbort?.(),e.abort(t),r.destroyed||r.destroy(t)}),r.once(`error`,()=>void 0),e.pipe(r)}var _=(e=>{function _(t){for(let r of e.publicsPath){let e=n.resolveSSRPrivateDir(r,t);if(o.default.existsSync(e))return e}return null}let v=new Map,y=new Map;function b(e){return typeof e==`string`&&u.test(e)}function x(e,t){let n=s.default.relative(t,e);return!!n&&!n.startsWith(`..`)&&!s.default.isAbsolute(n)}function S(e,t){if(!b(t))return null;let n=o.default.realpathSync(e);return[`${t}.mjs`,`${t}.js`].map(t=>s.default.resolve(e,t)).find(t=>!x(t,e)||!o.default.existsSync(t)?!1:x(o.default.realpathSync(t),n))??null}function C(e,t){let n=(0,l.pathToFileURL)(e);return n.searchParams.set(`t`,String(t)),n.href}async function w(e){let t=_(n.SSR_SERVER_OUT_DIR);if(!t)return null;let r=S(t,e);if(!r)return null;let i=o.default.statSync(r),a=v.get(e);if(a&&a.path===r&&a.mtime===i.mtimeMs)return a.module;let s=await import(C(r,i.mtimeMs));return v.set(e,{module:s,mtime:i.mtimeMs,path:r}),s}async function T(e){let t=_(n.SSR_MANIFEST_OUT_DIR);if(!t)return null;let r=s.default.resolve(t,n.SSR_CLIENT_MANIFEST_FILE);if(!o.default.existsSync(r))return null;let i=o.default.statSync(r),a=y.get(r);if(a&&a.mtime===i.mtimeMs)return a.manifest;let c=o.default.readFileSync(r,`utf-8`),l=JSON.parse(c);return y.set(r,{manifest:l,mtime:i.mtimeMs}),l}function E(t,n,r,a,o,s){h(t),t.status=r,t.type=`text/html`,t.body=i.renderSSRErrorHtml({app:e,ctx:t,page:n,status:r,title:a,message:o,error:s})}return class{async renderSSRPage(o,s){let l=o.params.page;if(h(o),!b(l)){E(o,String(l??`unknown`),404,`SSR page not found`,`The requested SSR page is not registered.`);return}e.extends.logger.log(` - SSR render: ${l}`);try{let s=await w(l);if(!s){e.extends.logger.log(` - SSR bundle not found: ${l}, falling back`),E(o,l,404,`SSR bundle not found`,`No server bundle was found for "${l}".`);return}let u=s.default,h=s.getServerProps,_={params:o.params,query:o.query,path:o.path,app:e,ctx:o},v={};typeof h==`function`&&(v=await h(_)??{});let y={..._,props:v},b=await m(s.pageTitle,y,l),x=await m(s.pageDescription,y,``),S=t.createHydrationData(v,{title:b,description:x,pathname:o.path}),C=t.serializeHydrationDataScriptContent(S),D=await T(l),O=a.findSSRClientEntry(D,l),k=a.generateSSRPreloadLinks(D,O),A=O?.file?`import(${r.serializeForHtmlScript(n.ssrClientAssetUrl(O.file))})`:void 0,j=await import(`react`),M=i.createSSRDocumentElement(j,{app:e,ctx:o,page:l,title:S.meta.title??l,description:S.meta.description??``,preloadLinks:k,hydrationScriptContent:C,appNode:j.createElement(u,v)}),{renderToPipeableStream:N}=await import(`react-dom/server`);await new Promise((t,n)=>{let r=null,i=null,a=!1,s=null,u=!1,m=null,h=null,_=()=>{m&&=(clearTimeout(m),null)},v=()=>{h&&=(clearTimeout(h),null)},y=e=>{let t=p(e);v(),r?.abort(t),i?.destroy(t)},b=()=>{u||(_(),u=!0,t())},x=e=>{u||(_(),v(),u=!0,n(e))};try{r=N(M,{bootstrapScriptContent:A,onShellReady(){if(s){r?.abort(s),x(s);return}let e=new c.PassThrough;i=e,o.body=e,o.type=`text/html`,a=!0,_(),h=setTimeout(()=>{y(Error(`SSR stream render timed out after ${f}ms.`))},f);try{g(r,e,{onAbort:v,onComplete:v}),b()}catch(t){e.destroy(p(t)),v(),x(t)}},onShellError(e){r?.abort(e),x(e)},onError(t){if(!a){s=t;return}e.extends.logger.log(` - SSR stream error after shell: ${l}`),console.error(`[SSR Stream Error]`,t),v(),y(t)}}),u||(m=setTimeout(()=>{let e=Error(`SSR shell render timed out after ${d}ms.`);r?.abort(e),x(e)},d))}catch(e){x(e)}})}catch(t){e.extends.logger.log(` - SSR render error: ${l}`),console.error(`[SSR Error]`,t),E(o,l,500,`SSR render error`,`The SSR page failed while loading data or rendering.`,t)}}}});module.exports=_;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../../packages/common/string/index.js`);var
|
|
1
|
+
const e=require(`../../packages/common/string/index.js`),t=require(`../../packages/core/paths.js`);var n=e=>JSON.stringify(e).replace(/</g,`\\u003c`).replace(/>/g,`\\u003e`).replace(/&/g,`\\u0026`).replace(/\u2028/g,`\\u2028`).replace(/\u2029/g,`\\u2029`),r=(r=>class{async renderPage(i,a){let o=i.path;if(r.extends.localCacheHtmlEtag.keepFreshFEBuildKey(),o.includes(`${r.options.apiPrefix}/`))await a();else{r.extends.logger.log(` - render page: `+i.params.page);try{let a=i.query.projk;Array.isArray(a)&&(a=e.joinStr(...a));let o=t.normalizeRouteBasePath(r.options.pageBasePath)||`/`,s=o===`/`?`/${i.params.page}`:`${o}/${i.params.page}`,c={projKey:a??``,name:r.options?.name??``,env:r.envs.get(),FEBasePage:n(o),basePath:n(s),projKeyJson:n(String(i.query.projk??``)),signKey:n(r.config.signKey),options:n(r.options)},l=r.extends.renderView(`${i.params.page}.entry.tpl`,i,c),u=e.joinStr(c.basePath,c.name,c.env,c.projKey);if(!r.extends.localCacheHtmlEtag.hasEtag(u)){let e=r.extends.crypto.hmacSign(l);r.extends.localCacheHtmlEtag.setEtag(u,e)}let d=r.extends.localCacheHtmlEtag.getEtag(u);if(d||console.log(`---- etag 缓存异常 请检查服务 ----`),i.etag=d??Date.now()+``,i.set(`Cache-Control`,`public, max-age=${(r.config.resourceCacheTimeMs??300*1e3)/1e3}, immutable`),i.fresh){i.status=304;return}}catch(e){console.log(`-------------- render view error --------------`),console.log(e),r.extends.generateErrorMessage(`template not found`,{status:404,showError:!0,code:0})}}}});module.exports=r;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={head:`<!-- TC_SHARED_HEAD -->`,runtimeContext:`<!-- TC_RUNTIME_CONTEXT -->`},t=e=>JSON.stringify(e).replace(/</g,`\\u003c`).replace(/>/g,`\\u003e`).replace(/&/g,`\\u0026`).replace(/\u2028/g,`\\u2028`).replace(/\u2029/g,`\\u2029`);function n(e){return String(e).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`)}function r(e){return n(e)}function i(){return`;(() => {
|
|
2
|
+
const storageKey = 'tc_theme'
|
|
3
|
+
let mode = 'dark'
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
const storedMode = localStorage.getItem(storageKey)
|
|
7
|
+
if (storedMode === 'light' || storedMode === 'dark') {
|
|
8
|
+
mode = storedMode
|
|
9
|
+
}
|
|
10
|
+
} catch (error) {
|
|
11
|
+
// Keep the template default when localStorage is unavailable.
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const root = document.documentElement
|
|
15
|
+
root.classList.toggle('dark', mode === 'dark')
|
|
16
|
+
root.style.colorScheme = mode
|
|
17
|
+
})()`}function a(){return`<script>${i()}<\/script>`}function o({titleHtml:e,descriptionAttr:t,preloadLinks:n=``}){let r=typeof t==`string`?`\n <meta name="description" content="${t}" />`:``,i=n?`\n ${n}`:``;return` <meta charset="UTF-8" />
|
|
18
|
+
${a()}
|
|
19
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
20
|
+
<link rel="icon" type="image/x-icon" href="/static/logo.png" />
|
|
21
|
+
<title>${e}</title>${r}${i}`}function s(){return o({titleHtml:`{{ name }}`})}function c({basePathExpression:e,feBasePageExpression:t,projKeyExpression:n,signKeyExpression:r,renderModeExpression:i}){return`window['_basePath'] = ${e}
|
|
22
|
+
window['_FEBasePage'] = ${t}
|
|
23
|
+
window['_projKey'] = ${n}
|
|
24
|
+
window['_signKey'] = ${r}
|
|
25
|
+
window['_renderMode'] = ${i}
|
|
26
|
+
window['_isSSR'] = window['_renderMode'] === 'ssr'
|
|
27
|
+
const s = document.getElementById('input')
|
|
28
|
+
s.parentElement.removeChild(s)`}function l(){return`const appOptionsScript = document.getElementById('app-options-data')
|
|
29
|
+
window['appOptions'] = JSON.parse(appOptionsScript.textContent || '{}')
|
|
30
|
+
appOptionsScript.parentElement.removeChild(appOptionsScript)`}function u(e){return`<script id="input">
|
|
31
|
+
${c(e)}
|
|
32
|
+
<\/script>
|
|
33
|
+
<script type="application/json" id="app-options-data">${e.optionsJsonHtml}<\/script>
|
|
34
|
+
<script>
|
|
35
|
+
${l()}
|
|
36
|
+
<\/script>`}function d(){return u({basePathExpression:`{{basePath | safe}}`,feBasePageExpression:`{{FEBasePage | safe}}`,projKeyExpression:`{{projKeyJson | safe}}`,signKeyExpression:`{{signKey | safe}}`,renderModeExpression:t(`csr`),optionsJsonHtml:`{{ options | safe }}`})}function f(e,t,n){if(!e.includes(t))throw Error(`CSR entry template is missing shared shell marker: ${t}`);return e.replace(t,n)}function p(t){return f(f(t,e.head,s()),e.runtimeContext,d())}exports.applySharedCSRShellTemplate=p,exports.escapeHtml=n,exports.escapeHtmlAttr=r,exports.renderAppOptionsScriptContent=l,exports.renderCSRDocumentHeadTemplate=s,exports.renderCSRRuntimeContextScriptsTemplate=d,exports.renderDocumentHeadHtml=o,exports.renderRuntimeContextScriptsFromExpressions=u,exports.renderRuntimeInputScriptContentFromExpressions=c,exports.renderThemeScript=a,exports.renderThemeScriptContent=i,exports.serializeForHtmlScript=t,exports.sharedCSRShellMarkers=e;
|
package/cjs/app/middleware.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../_virtual/_rolldown/runtime.js`);let
|
|
1
|
+
const e=require(`../_virtual/_rolldown/runtime.js`),t=require(`../ssrSharedData/outputPaths.js`);let n=require(`koa-compress`);n=e.__toESM(n);let r=require(`koa-bodyparser`);r=e.__toESM(r);let i=require(`koa-static`);i=e.__toESM(i);var a=(0,r.default)({formLimit:`1000mb`,enableTypes:[`form`,`json`,`text`]}),o=e=>{let r=e.envs.isLocal()?{maxage:0,setHeaders(e){e.setHeader(`Cache-Control`,`no-store, no-cache, must-revalidate, proxy-revalidate`),e.setHeader(`Pragma`,`no-cache`),e.setHeader(`Expires`,`0`)}}:{maxage:e.config.resourceCacheTimeMs??300*1e3};e.use(e.middlewares.errorHandle),e.use((0,n.default)({threshold:2048}));let o=[`/dist/${t.SSR_SERVER_OUT_DIR}`,`/dist/.vite`];e.use(async(e,t)=>{if(o.some(t=>e.path===t||e.path.startsWith(`${t}/`))){e.status=404;return}await t()}),e.publicsPath.forEach(t=>e.use((0,i.default)(t,r))),e.use(a),e.use(e.middlewares.requestParameterParsing),e.use(e.middlewares.projectHandler),!e.envs.isLocal()&&e.use(e.middlewares.apiSignVerify),e.use(e.middlewares.apiParamsVerify)};module.exports=o;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require(`../../packages/core/paths.js`);var t=(t,n)=>{let r=e.normalizeRouteBasePath(t.options.ssrPageBasePath,`/fessr`);n.level=1,n.get([`${r}/:page`,`${r}/:page/:rest(.*)`],t.controller.ssr.renderSSRPage.bind(t.controller.ssr))};module.exports=t;
|
package/cjs/app/router/view.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=require(`../../packages/core/paths.js`);var t=(t,n)=>{let r=e.normalizeRouteBasePath(t.options.pageBasePath);n.level=2,n.get([`${r}/:page`,`${r}/:page/:r(.*)`],t.controller.view.renderPage.bind(t.controller.view))};module.exports=t;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../packages/core/paths.js`),t=require(`../html/shell.js`);function n(...e){return`/${e.filter(Boolean).map(e=>e.replace(/^\/+|\/+$/g,``)).filter(Boolean).join(`/`)}`}function r(e){let t=e.query.projk;return Array.isArray(t)?t.join(``):String(t??``)}function i(i,a,o){let s=e.normalizeRouteBasePath(i.options.pageBasePath)||`/`,c=n(e.normalizeRouteBasePath(i.options.ssrPageBasePath,`/fessr`)||`/fessr`,o),l=r(a);return{basePathExpression:t.serializeForHtmlScript(c),feBasePageExpression:t.serializeForHtmlScript(s),projKeyExpression:t.serializeForHtmlScript(l),signKeyExpression:t.serializeForHtmlScript(i.config.signKey),renderModeExpression:t.serializeForHtmlScript(`ssr`),optionsJsonHtml:t.serializeForHtmlScript(i.options)}}function a(e,n,r){return t.renderRuntimeInputScriptContentFromExpressions(i(e,n,r))}function o(e,n,r){return t.renderRuntimeContextScriptsFromExpressions(i(e,n,r))}function s(e){let{app:t,ctx:n,page:r,hydrationScript:i=``,clientScript:a=``}=e;return{beforeAppHtml:`<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="dark" style="color-scheme: dark">
|
|
3
|
+
<head>
|
|
4
|
+
${c(e)}
|
|
5
|
+
</head>
|
|
6
|
+
${o(t,n,r)}
|
|
7
|
+
<body>
|
|
8
|
+
<div id="root">`,afterAppHtml:`</div>
|
|
9
|
+
${i}
|
|
10
|
+
${a}
|
|
11
|
+
</body>
|
|
12
|
+
</html>`}}function c(e){let{title:n,description:r=``,preloadLinks:i=``}=e;return t.renderDocumentHeadHtml({titleHtml:t.escapeHtml(n),descriptionAttr:t.escapeHtmlAttr(r),preloadLinks:i})}function l(e,n){let{app:r,ctx:i,page:o,appNode:s,hydrationScriptContent:l=``}=n;return e.createElement(`html`,{lang:`en`,className:`dark`,style:{colorScheme:`dark`}},e.createElement(`head`,{dangerouslySetInnerHTML:{__html:c(n)}}),e.createElement(`body`,null,e.createElement(`script`,{id:`input`,dangerouslySetInnerHTML:{__html:a(r,i,o)}}),e.createElement(`script`,{type:`application/json`,id:`app-options-data`,dangerouslySetInnerHTML:{__html:t.serializeForHtmlScript(r.options)}}),e.createElement(`script`,{dangerouslySetInnerHTML:{__html:t.renderAppOptionsScriptContent()}}),l?e.createElement(`script`,{dangerouslySetInnerHTML:{__html:l}}):null,e.createElement(`div`,{id:`root`},s)))}function u(e){let{appHtml:t,...n}=e,{beforeAppHtml:r,afterAppHtml:i}=s(n);return`${r}${t}${i}`}function d(e){let{app:n,ctx:r,page:i,status:a,title:o,message:s,error:c}=e,l=n.config.ssr?.exposeErrorDetails??n.envs.isLocal(),d=c instanceof Error?c.stack||c.message:String(c??``),f=l&&d?`<pre style="white-space:pre-wrap;margin-top:16px;padding:12px;border:1px solid #d8dee4;background:#f6f8fa;color:#24292f;overflow:auto">${t.escapeHtml(d)}</pre>`:``;return u({app:n,ctx:r,page:i,title:o,description:s,appHtml:`<main style="font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;max-width:720px;margin:72px auto;padding:0 24px;line-height:1.5;color:#24292f">
|
|
13
|
+
<p style="margin:0 0 8px;color:#57606a;font-size:14px">SSR ${a}</p>
|
|
14
|
+
<h1 style="margin:0 0 12px;font-size:28px;line-height:1.2">${t.escapeHtml(o)}</h1>
|
|
15
|
+
<p style="margin:0;color:#57606a">${t.escapeHtml(s)}</p>
|
|
16
|
+
${f}
|
|
17
|
+
</main>`})}exports.createSSRDocumentElement=l,exports.escapeHtml=t.escapeHtml,exports.escapeHtmlAttr=t.escapeHtmlAttr,exports.renderSSRErrorHtml=d,exports.renderSSRHtmlShell=u,exports.renderSSRHtmlShellParts=s,exports.serializeForHtmlScript=t.serializeForHtmlScript;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../_virtual/_rolldown/runtime.js`),t=require(`../../ssrSharedData/outputPaths.js`);let n=require(`node:path`);n=e.__toESM(n);function r(e){return String(e).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`)}function i(e,t,r){let i=t.split(n.default.sep).join(`/`),a=r.src?.split(n.default.sep).join(`/`);return[r.name,i,a].filter(e=>!!e).some(t=>{let r=t.split(n.default.sep).join(`/`),i=n.default.basename(r).replace(/\.entry\.[^.]+$/,``);return r===e||i===e||n.default.basename(n.default.dirname(r))===e})}function a(e,t){if(!e)return null;let n=Object.entries(e),r=n.find(([,e])=>e.isEntry&&e.name===t);if(r)return r[1];let a=n.find(([e,n])=>n.isEntry&&i(t,e,n));return a?a[1]:n.find(([e,n])=>i(t,e,n))?.[1]??null}function o(e,n){if(!e||!n)return``;let i=e,a=[],o=new Set,s=new Set;function c(e){o.has(e)||(o.add(e),a.push(`<link rel="modulepreload" href="${r(t.ssrClientAssetUrl(e))}" />`))}function l(e){o.has(e)||(o.add(e),a.push(`<link rel="stylesheet" href="${r(t.ssrClientAssetUrl(e))}" />`))}function u(e){if(!s.has(e)){s.add(e),e.file&&c(e.file);for(let t of e.css??[])l(t);for(let t of e.imports??[]){let e=i[t];e&&u(e)}}}return u(n),a.join(`
|
|
2
|
+
`)}exports.findSSRClientEntry=a,exports.generateSSRPreloadLinks=o;
|
package/cjs/app/view/entry.tpl
CHANGED
|
@@ -1,46 +1,11 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en" class="dark" style="color-scheme: dark">
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
<script>
|
|
6
|
-
;(() => {
|
|
7
|
-
const storageKey = 'tc_theme'
|
|
8
|
-
let mode = 'dark'
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
const storedMode = localStorage.getItem(storageKey)
|
|
12
|
-
if (storedMode === 'light' || storedMode === 'dark') {
|
|
13
|
-
mode = storedMode
|
|
14
|
-
}
|
|
15
|
-
} catch (error) {
|
|
16
|
-
// Keep the template default when localStorage is unavailable.
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const root = document.documentElement
|
|
20
|
-
root.classList.toggle('dark', mode === 'dark')
|
|
21
|
-
root.style.colorScheme = mode
|
|
22
|
-
})()
|
|
23
|
-
</script>
|
|
24
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
25
|
-
<link rel="icon" type="image/x-icon" href="/static/logo.png" />
|
|
26
|
-
<title>{{ name }}</title>
|
|
4
|
+
<!-- TC_SHARED_HEAD -->
|
|
27
5
|
<!-- TC_HEAD_SLOT -->
|
|
28
6
|
</head>
|
|
29
7
|
|
|
30
|
-
|
|
31
|
-
window['_basePath'] = {{basePath | safe}}
|
|
32
|
-
window['_FEBasePage'] = {{FEBasePage | safe}}
|
|
33
|
-
window['_projKey'] = {{projKeyJson | safe}}
|
|
34
|
-
window['_signKey'] = {{signKey | safe}}
|
|
35
|
-
const s = document.getElementById('input')
|
|
36
|
-
s.parentElement.removeChild(s)
|
|
37
|
-
</script>
|
|
38
|
-
<script type="application/json" id="app-options-data">{{ options | safe }}</script>
|
|
39
|
-
<script>
|
|
40
|
-
const appOptionsScript = document.getElementById('app-options-data')
|
|
41
|
-
window['appOptions'] = JSON.parse(appOptionsScript.textContent || '{}')
|
|
42
|
-
appOptionsScript.parentElement.removeChild(appOptionsScript)
|
|
43
|
-
</script>
|
|
8
|
+
<!-- TC_RUNTIME_CONTEXT -->
|
|
44
9
|
|
|
45
10
|
<body>
|
|
46
11
|
<!-- TC_BODY_BEFORE_ROOT_SLOT -->
|
package/cjs/bundler/buildBE.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../scripts/vite-build/build.js`);require(`../scripts/vite-build/index.js`);var t=[`index.ts`,`index.js`,`app`,`config`,`
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../scripts/vite-build/build.js`);require(`../scripts/vite-build/index.js`);var t=[`index.ts`,`index.js`,`app`,`config`,`models`];async function n(n={}){return e.buildEntries({...n,rootDir:n.rootDir,input:n.input??t,outDir:n.outDir??`dist`,format:n.format??`cjs`,alias:n.alias,allowMissingInput:n.allowMissingInput??!n.input,outputStructure:n.outputStructure??`preserve`,bundleDependencies:n.bundleDependencies??!1,externalNodeBuiltins:n.externalNodeBuiltins??!0,dts:n.dts??!1,copy:n.copy??{input:n.input??t,extensions:{input:[`.tpl`,`.html`,`.css`,`.scss`,`.sass`,`.less`,`.svg`,`.png`,`.jpg`,`.jpeg`,`.gif`,`.webp`,`.ico`,`.json`,`.md`,`.txt`,`.xml`,`.yml`,`.yaml`],mergeDefault:!1}}})}exports.buildBE=n;
|