@_tc/template-core 0.2.12 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/.skills/tc-component-usage-skills/SKILL.md +7 -9
  2. package/.skills/tc-component-usage-skills/reference/component-api.md +2 -2
  3. package/.skills/tc-component-usage-skills/reference/examples.md +9 -9
  4. package/.skills/tc-component-usage-skills/reference/patterns.md +5 -5
  5. package/.skills/tc-component-usage-skills/reference/template-core-frontend.md +1 -1
  6. package/.skills/tc-generator/SKILL.md +30 -14
  7. package/.skills/tc-generator/reference/example.md +4 -4
  8. package/.skills/tc-generator/reference/model-schema.md +9 -5
  9. package/.skills/tc-generator/reference/runtime-extensions.md +9 -7
  10. package/AGENT_README.md +52 -33
  11. package/CHANGE.md +48 -5
  12. package/README.md +147 -46
  13. package/cjs/app/controller/ssr.js +1 -0
  14. package/cjs/app/controller/view.js +1 -1
  15. package/cjs/app/html/shell.js +36 -0
  16. package/cjs/app/middleware.js +1 -1
  17. package/cjs/app/router/ssr.js +1 -0
  18. package/cjs/app/router/view.js +1 -1
  19. package/cjs/app/ssr/html.js +17 -0
  20. package/cjs/app/ssr/manifest.js +2 -0
  21. package/cjs/app/view/entry.tpl +2 -37
  22. package/cjs/bundler/buildBE.js +1 -1
  23. package/cjs/bundler/buildSSR.js +1 -0
  24. package/cjs/bundler/entryCollect.js +1 -0
  25. package/cjs/bundler/feSharedConfig.js +1 -0
  26. package/cjs/bundler/index.js +1 -1
  27. package/cjs/bundler/ssrClientManifest.js +1 -0
  28. package/cjs/bundler/ssrEntries.js +1 -0
  29. package/cjs/bundler/utils.js +3 -3
  30. package/cjs/packages/common/i18n/index.js +1 -1
  31. package/cjs/packages/common/index.js +1 -1
  32. package/cjs/packages/common/ssr/hydration.js +1 -0
  33. package/cjs/packages/common/ssr/index.js +1 -0
  34. package/cjs/packages/core/index.js +1 -1
  35. package/cjs/packages/core/loader/controller.js +1 -1
  36. package/cjs/packages/core/loader/extend.js +1 -1
  37. package/cjs/packages/core/loader/merge.js +1 -0
  38. package/cjs/packages/core/loader/middleware.js +1 -1
  39. package/cjs/packages/core/loader/model.js +1 -1
  40. package/cjs/packages/core/loader/router-schema.js +1 -1
  41. package/cjs/packages/core/loader/router.js +1 -1
  42. package/cjs/packages/core/loader/service.js +1 -1
  43. package/cjs/packages/core/paths.js +1 -1
  44. package/cjs/scripts/vite-build/build.js +3 -3
  45. package/cjs/scripts/vite-build/collect.js +1 -1
  46. package/cjs/scripts/vite-build/dts.js +1 -1
  47. package/cjs/scripts/vite-build/normalize.js +1 -1
  48. package/cjs/ssrSharedData/outputPaths.js +1 -0
  49. package/esm/app/controller/ssr.js +215 -0
  50. package/esm/app/controller/view.js +26 -25
  51. package/esm/app/html/shell.js +69 -0
  52. package/esm/app/middleware.js +18 -9
  53. package/esm/app/router/ssr.js +8 -0
  54. package/esm/app/router/view.js +5 -4
  55. package/esm/app/ssr/html.js +90 -0
  56. package/esm/app/ssr/manifest.js +47 -0
  57. package/esm/app/view/entry.tpl +2 -37
  58. package/esm/bundler/buildBE.js +1 -1
  59. package/esm/bundler/buildSSR.js +126 -0
  60. package/esm/bundler/entryCollect.js +45 -0
  61. package/esm/bundler/feSharedConfig.js +143 -0
  62. package/esm/bundler/index.js +4 -2
  63. package/esm/bundler/ssrClientManifest.js +14 -0
  64. package/esm/bundler/ssrEntries.js +13 -0
  65. package/esm/bundler/utils.js +248 -255
  66. package/esm/packages/common/i18n/index.js +5 -1
  67. package/esm/packages/common/index.js +4 -2
  68. package/esm/packages/common/ssr/hydration.js +55 -0
  69. package/esm/packages/common/ssr/index.js +20 -0
  70. package/esm/packages/core/index.js +42 -42
  71. package/esm/packages/core/loader/controller.js +11 -9
  72. package/esm/packages/core/loader/extend.js +20 -16
  73. package/esm/packages/core/loader/merge.js +7 -0
  74. package/esm/packages/core/loader/middleware.js +11 -12
  75. package/esm/packages/core/loader/model.js +2 -2
  76. package/esm/packages/core/loader/router-schema.js +22 -15
  77. package/esm/packages/core/loader/router.js +32 -26
  78. package/esm/packages/core/loader/service.js +11 -9
  79. package/esm/packages/core/paths.js +9 -1
  80. package/esm/scripts/vite-build/build.js +88 -83
  81. package/esm/scripts/vite-build/collect.js +31 -27
  82. package/esm/scripts/vite-build/dts.js +1 -1
  83. package/esm/scripts/vite-build/normalize.js +6 -3
  84. package/esm/ssrSharedData/outputPaths.js +33 -0
  85. package/fe/frontend/apps/dash/Dashboard.d.ts +5 -1
  86. package/fe/frontend/apps/dash/Dashboard.js +22 -13
  87. package/fe/frontend/apps/dash/types.d.ts +2 -0
  88. package/fe/frontend/src/api/baseInfo.d.ts +1 -1
  89. package/fe/frontend/src/common/CRUD/CRUD.js +1 -1
  90. package/fe/frontend/src/common/CRUD/index.js +1 -1
  91. package/fe/frontend/src/common/menu.d.ts +1 -1
  92. package/fe/frontend/src/common/menu.js +8 -7
  93. package/fe/frontend/src/common/request.js +1 -1
  94. package/fe/frontend/src/common/schemaForm.d.ts +1 -0
  95. package/fe/frontend/src/common/schemaForm.js +12 -0
  96. package/fe/frontend/src/components/AsyncSelect/AsyncSelect.d.ts +1 -1
  97. package/fe/frontend/src/components/Router/basename.d.ts +3 -0
  98. package/fe/frontend/src/components/Router/basename.js +11 -0
  99. package/fe/frontend/src/components/Router/index.d.ts +1 -1
  100. package/fe/frontend/src/components/Router/index.js +3 -1
  101. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/builtIn.d.ts +1 -1
  102. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.d.ts +1 -1
  103. package/fe/frontend/src/defaultPages/SchemaPage/schemaType.d.ts +2 -2
  104. package/fe/frontend/src/defaultPages/SchemaPage/utils/schemaConversion.d.ts +1 -1
  105. package/fe/frontend/src/defaultPages/SidebarSlotPage/SidebarSlotContainer.d.ts +2 -1
  106. package/fe/frontend/src/defaultPages/SidebarSlotPage/SidebarSlotContainer.js +8 -4
  107. package/fe/frontend/src/defaultPages/SidebarSlotPageTmp.js +2 -1
  108. package/fe/frontend/src/exportStore.js +2 -2
  109. package/fe/frontend/src/hooks/useCurrentMenuData.d.ts +1 -1
  110. package/fe/frontend/src/hooks/useCurrentMenuData.js +2 -2
  111. package/fe/frontend/src/hooks/useRouterParams.js +4 -3
  112. package/fe/frontend/src/index.d.ts +1 -0
  113. package/fe/frontend/src/index.js +4 -3
  114. package/fe/frontend/src/main.js +2 -0
  115. package/fe/frontend/src/stores/mode.d.ts +15 -2
  116. package/fe/frontend/src/stores/mode.js +19 -5
  117. package/fe/frontend/src/typing/window.d.ts +2 -0
  118. package/fe/packages/common/LRUCache.js +2 -0
  119. package/fe/packages/common/array/index.js +37 -0
  120. package/fe/packages/common/cache/index.js +2 -0
  121. package/fe/packages/common/guards/index.js +19 -1
  122. package/fe/packages/common/http/index.js +1 -1
  123. package/fe/packages/common/i18n/index.js +8 -4
  124. package/fe/packages/common/i18n/locales.js +1 -1
  125. package/fe/packages/common/i18n/types.d.ts +1 -0
  126. package/fe/packages/common/i18n/types.js +0 -0
  127. package/fe/packages/common/index.d.ts +1 -0
  128. package/fe/packages/common/index.js +17 -0
  129. package/fe/packages/common/log/index.js +146 -0
  130. package/fe/packages/common/number/index.js +11 -0
  131. package/fe/packages/common/object/filterEmpty.js +2 -1
  132. package/fe/packages/common/object/filtereEmpty.js +2 -0
  133. package/fe/packages/common/object/index.js +20 -0
  134. package/fe/packages/common/ssr/hydration.d.ts +23 -0
  135. package/fe/packages/common/ssr/hydration.js +88 -0
  136. package/fe/packages/common/ssr/index.d.ts +8 -0
  137. package/fe/packages/common/ssr/index.js +52 -0
  138. package/fe/packages/common/string/index.js +32 -0
  139. package/fe/packages/common/types/index.js +0 -0
  140. package/fe/packages/react/hooks/index.d.ts +2 -0
  141. package/fe/packages/react/hooks/index.js +3 -1
  142. package/fe/packages/react/hooks/useHydrationData.d.ts +2 -0
  143. package/fe/packages/react/hooks/useHydrationData.js +23 -0
  144. package/fe/packages/react/hooks/useSSR.d.ts +6 -0
  145. package/fe/packages/react/hooks/useSSR.js +46 -0
  146. package/fe/packages/react/ui/components/DataTable/index.js +16 -15
  147. package/fe/packages/react/ui/components/Form/SchemaForm/data.d.ts +3 -2
  148. package/fe/packages/react/ui/components/Form/SchemaForm/data.js +5 -6
  149. package/fe/packages/react/ui/components/Form/SchemaForm/index.d.ts +1 -0
  150. package/fe/packages/react/ui/components/Form/SchemaForm/index.js +2 -2
  151. package/fe/packages/react/ui/components/Form/index.js +2 -1
  152. package/fe/packages/react/ui/components/Input/Input.js +5 -1
  153. package/fe/packages/react/ui/components/Popup/Popup.js +6 -1
  154. package/fe/packages/react/ui/components/index.js +2 -1
  155. package/fe/packages/react/ui/components/testPage/demos/core/DataTableDemo.js +241 -211
  156. package/fe/packages/react/ui/components/testPage/demos/core/DataTableDemo2.js +1 -1
  157. package/fe/packages/react/ui/i18n/I18nProvider.js +4 -0
  158. package/fe/packages/react/ui/index.js +2 -1
  159. package/fe/ssr/apps/dash/dash.entry.d.ts +13 -0
  160. package/fe/ssr/apps/dash/dash.entry.js +162 -0
  161. package/fe/ssr/apps/demo/demo.entry.d.ts +13 -0
  162. package/fe/ssr/apps/demo/demo.entry.js +38 -0
  163. package/fe/ssr/apps/server-data/server-data.entry.d.ts +26 -0
  164. package/fe/ssr/apps/server-data/server-data.entry.js +275 -0
  165. package/fe/ssr/apps/ui-components/ui-components.entry.d.ts +5 -0
  166. package/fe/ssr/apps/ui-components/ui-components.entry.js +17 -0
  167. package/fe/ssr/components/StreamingRender/StreamingCache.d.ts +2 -0
  168. package/fe/ssr/components/StreamingRender/StreamingCache.js +31 -0
  169. package/fe/ssr/components/StreamingRender/StreamingRender.d.ts +3 -0
  170. package/fe/ssr/components/StreamingRender/StreamingRender.js +48 -0
  171. package/fe/ssr/components/StreamingRender/StreamingScript.d.ts +8 -0
  172. package/fe/ssr/components/StreamingRender/StreamingScript.js +58 -0
  173. package/fe/ssr/components/StreamingRender/index.d.ts +4 -0
  174. package/fe/ssr/components/StreamingRender/index.js +5 -0
  175. package/fe/ssr/components/StreamingRender/type.d.ts +9 -0
  176. package/fe/ssr/components/StreamingRender/type.js +0 -0
  177. package/fe/ssr/components/index.d.ts +2 -0
  178. package/fe/ssr/components/index.js +2 -0
  179. package/fe/ssr/createSSREntry.d.ts +6 -0
  180. package/fe/ssr/createSSREntry.js +42 -0
  181. package/fe/ssr/hooks/index.d.ts +1 -0
  182. package/fe/ssr/hooks/index.js +2 -0
  183. package/fe/ssr/hooks/useSuspensePromise.d.ts +1 -0
  184. package/fe/ssr/hooks/useSuspensePromise.js +31 -0
  185. package/fe/ssr/index.d.ts +4 -0
  186. package/fe/ssr/index.js +6 -0
  187. package/fe/ssr/types.d.ts +13 -0
  188. package/fe/ssr/types.js +0 -0
  189. package/{model → models}/frontend/src/typing/window.d.ts +2 -0
  190. package/{model → models}/packages/common/i18n/types.d.ts +1 -0
  191. package/{model → models}/packages/common/index.d.ts +1 -0
  192. package/models/packages/common/ssr/hydration.d.ts +23 -0
  193. package/models/packages/common/ssr/index.d.ts +8 -0
  194. package/{model → models}/packages/react/ui/components/Form/SchemaForm/data.d.ts +3 -2
  195. package/{model → models}/packages/react/ui/components/Form/SchemaForm/index.d.ts +1 -0
  196. package/package.json +43 -6
  197. package/types/app/controller/ssr.d.ts +14 -0
  198. package/types/app/html/shell.d.ts +101 -0
  199. package/types/app/router/ssr.d.ts +6 -0
  200. package/types/app/ssr/html.d.ts +53 -0
  201. package/types/app/ssr/manifest.d.ts +17 -0
  202. package/types/app/typings.d.ts +2 -0
  203. package/types/bundler/buildSSR.d.ts +56 -0
  204. package/types/bundler/entryCollect.d.ts +36 -0
  205. package/types/bundler/feSharedConfig.d.ts +35 -0
  206. package/types/bundler/index.d.ts +4 -0
  207. package/types/bundler/ssrClientManifest.d.ts +4 -0
  208. package/types/bundler/ssrEntries.d.ts +23 -0
  209. package/types/bundler/state.d.ts +2 -2
  210. package/types/bundler/utils.d.ts +35 -2
  211. package/types/config/config.default.d.ts +10 -0
  212. package/types/packages/common/i18n/types.d.ts +2 -0
  213. package/types/packages/common/index.d.ts +1 -0
  214. package/types/packages/common/ssr/hydration.d.ts +72 -0
  215. package/types/packages/common/ssr/index.d.ts +34 -0
  216. package/types/packages/core/loader/merge.d.ts +3 -0
  217. package/types/packages/core/loader/model.d.ts +2 -2
  218. package/types/packages/core/paths.d.ts +5 -0
  219. package/types/packages/core/types.d.ts +10 -1
  220. package/types/scripts/vite-build/build.d.ts +1 -0
  221. package/types/scripts/vite-build/types.d.ts +3 -0
  222. package/types/ssrSharedData/outputPaths.d.ts +59 -0
  223. package/fe/packages/react/hooks/useWatch.test.js +0 -24
  224. package/fe/packages/react/ui/assets/table/no-result.js +0 -4
  225. package/fe/packages/react/ui/components/DataTable/dataTableWidth.test.js +0 -39
  226. package/fe/packages/react/ui/components/InputNumber/inputNumberUtils.test.js +0 -59
  227. /package/.skills/tc-generator/reference/project-template/{model → models}/product/mode.js +0 -0
  228. /package/.skills/tc-generator/reference/project-template/{model → models}/product/project/default.js +0 -0
  229. /package/fe/{model → models}/types/data/button.d.ts +0 -0
  230. /package/fe/{model → models}/types/data/component.d.ts +0 -0
  231. /package/fe/{model → models}/types/data/fetchInfo.d.ts +0 -0
  232. /package/fe/{model → models}/types/data/schema.d.ts +0 -0
  233. /package/fe/{model → models}/types/data/search.d.ts +0 -0
  234. /package/fe/{model → models}/types/index.d.ts +0 -0
  235. /package/fe/{model → models}/types/menuType.d.ts +0 -0
  236. /package/fe/{model → models}/types/model.d.ts +0 -0
  237. /package/{model → models}/frontend/extended/SchemaForm/data.d.ts +0 -0
  238. /package/{model → models}/frontend/src/common/auth/index.d.ts +0 -0
  239. /package/{model → models}/frontend/src/common/fetchErrorShow.d.ts +0 -0
  240. /package/{model → models}/frontend/src/common/language.d.ts +0 -0
  241. /package/{model → models}/frontend/src/common/logFn/index.d.ts +0 -0
  242. /package/{model → models}/frontend/src/common/request.d.ts +0 -0
  243. /package/{model → models}/frontend/src/components/AsyncSelect/AsyncSelect.d.ts +0 -0
  244. /package/{model → models}/frontend/src/components/AsyncSelect/index.d.ts +0 -0
  245. /package/{model → models}/frontend/src/defaultPages/SchemaPage/components/CallCom/DetailPanel.d.ts +0 -0
  246. /package/{model → models}/frontend/src/defaultPages/SchemaPage/components/CallCom/PopFrom.d.ts +0 -0
  247. /package/{model → models}/frontend/src/defaultPages/SchemaPage/components/CallCom/builtIn.d.ts +0 -0
  248. /package/{model → models}/frontend/src/defaultPages/SchemaPage/data/eventInfo.d.ts +0 -0
  249. /package/{model → models}/frontend/src/defaultPages/SchemaPage/data/index.d.ts +0 -0
  250. /package/{model → models}/frontend/src/defaultPages/SchemaPage/hooks/useComConfig.d.ts +0 -0
  251. /package/{model → models}/frontend/src/defaultPages/SchemaPage/schemaType.d.ts +0 -0
  252. /package/{model → models}/frontend/src/defaultPages/SchemaPage/utils/permissions.d.ts +0 -0
  253. /package/{model → models}/frontend/src/defaultPages/SchemaPage/utils/validator.d.ts +0 -0
  254. /package/{model → models}/frontend/src/hooks/useText.d.ts +0 -0
  255. /package/{model → models}/frontend/src/language/en-US.d.ts +0 -0
  256. /package/{model → models}/frontend/src/language/index.d.ts +0 -0
  257. /package/{model → models}/frontend/src/language/resources.d.ts +0 -0
  258. /package/{model → models}/frontend/src/language/zh-CN.d.ts +0 -0
  259. /package/{model → models}/frontend/src/stores/apiFreezer.d.ts +0 -0
  260. /package/{model → models}/frontend/src/stores/schemaEventBus.d.ts +0 -0
  261. /package/{model → models}/frontend/src/stores/schemaStore.d.ts +0 -0
  262. /package/{model → models}/frontend/src/typing/scalability.d.ts +0 -0
  263. /package/{model/model → models/models}/index.d.ts +0 -0
  264. /package/{model/model → models/models}/test.d.ts +0 -0
  265. /package/{model/model → models/models}/types/data/button.d.ts +0 -0
  266. /package/{model/model → models/models}/types/data/component.d.ts +0 -0
  267. /package/{model/model → models/models}/types/data/fetchInfo.d.ts +0 -0
  268. /package/{model/model → models/models}/types/data/schema.d.ts +0 -0
  269. /package/{model/model → models/models}/types/data/search.d.ts +0 -0
  270. /package/{model/model → models/models}/types/index.d.ts +0 -0
  271. /package/{model/model → models/models}/types/menuType.d.ts +0 -0
  272. /package/{model/model → models/models}/types/model.d.ts +0 -0
  273. /package/{model → models}/packages/common/array/index.d.ts +0 -0
  274. /package/{model → models}/packages/common/cache/LRUCache.d.ts +0 -0
  275. /package/{model → models}/packages/common/cache/index.d.ts +0 -0
  276. /package/{model → models}/packages/common/guards/index.d.ts +0 -0
  277. /package/{model → models}/packages/common/http/index.d.ts +0 -0
  278. /package/{model → models}/packages/common/i18n/default.d.ts +0 -0
  279. /package/{model → models}/packages/common/i18n/en-US.d.ts +0 -0
  280. /package/{model → models}/packages/common/i18n/index.d.ts +0 -0
  281. /package/{model → models}/packages/common/i18n/locales.d.ts +0 -0
  282. /package/{model → models}/packages/common/log/index.d.ts +0 -0
  283. /package/{model → models}/packages/common/number/index.d.ts +0 -0
  284. /package/{model → models}/packages/common/object/filterEmpty.d.ts +0 -0
  285. /package/{model → models}/packages/common/object/index.d.ts +0 -0
  286. /package/{model → models}/packages/common/rafTimer.d.ts +0 -0
  287. /package/{model → models}/packages/common/string/index.d.ts +0 -0
  288. /package/{model → models}/packages/common/types/index.d.ts +0 -0
  289. /package/{model → models}/packages/react/hooks/useBreadcrumb.d.ts +0 -0
  290. /package/{model → models}/packages/react/hooks/useExecuteOnce.d.ts +0 -0
  291. /package/{model → models}/packages/react/hooks/useLanguage.d.ts +0 -0
  292. /package/{model → models}/packages/react/ui/components/Button/Button.d.ts +0 -0
  293. /package/{model → models}/packages/react/ui/components/Button/SubmitButton.d.ts +0 -0
  294. /package/{model → models}/packages/react/ui/components/Button/index.d.ts +0 -0
  295. /package/{model → models}/packages/react/ui/components/Card/Card.d.ts +0 -0
  296. /package/{model → models}/packages/react/ui/components/Card/index.d.ts +0 -0
  297. /package/{model → models}/packages/react/ui/components/Checkbox/Checkbox.d.ts +0 -0
  298. /package/{model → models}/packages/react/ui/components/Checkbox/index.d.ts +0 -0
  299. /package/{model → models}/packages/react/ui/components/ConfirmDialog/ConfirmDialog.d.ts +0 -0
  300. /package/{model → models}/packages/react/ui/components/ConfirmDialog/index.d.ts +0 -0
  301. /package/{model → models}/packages/react/ui/components/DataTable/ActionBtn.d.ts +0 -0
  302. /package/{model → models}/packages/react/ui/components/DataTable/dataTableWidth.d.ts +0 -0
  303. /package/{model → models}/packages/react/ui/components/DataTable/index.d.ts +0 -0
  304. /package/{model → models}/packages/react/ui/components/Date/Calendar.d.ts +0 -0
  305. /package/{model → models}/packages/react/ui/components/Date/Date.d.ts +0 -0
  306. /package/{model → models}/packages/react/ui/components/Date/LocaleContext.d.ts +0 -0
  307. /package/{model → models}/packages/react/ui/components/Date/LocaleProvider.d.ts +0 -0
  308. /package/{model → models}/packages/react/ui/components/Date/TimePicker.d.ts +0 -0
  309. /package/{model → models}/packages/react/ui/components/Date/data.d.ts +0 -0
  310. /package/{model → models}/packages/react/ui/components/Date/dateLocaleStore.d.ts +0 -0
  311. /package/{model → models}/packages/react/ui/components/Date/dropdownPositioning.d.ts +0 -0
  312. /package/{model → models}/packages/react/ui/components/Date/index.d.ts +0 -0
  313. /package/{model → models}/packages/react/ui/components/Date/locales.d.ts +0 -0
  314. /package/{model → models}/packages/react/ui/components/Drawer/Drawer.d.ts +0 -0
  315. /package/{model → models}/packages/react/ui/components/Drawer/index.d.ts +0 -0
  316. /package/{model → models}/packages/react/ui/components/Dropdown/Dropdown.d.ts +0 -0
  317. /package/{model → models}/packages/react/ui/components/Dropdown/index.d.ts +0 -0
  318. /package/{model → models}/packages/react/ui/components/Form/Form.d.ts +0 -0
  319. /package/{model → models}/packages/react/ui/components/Form/FormItem.d.ts +0 -0
  320. /package/{model → models}/packages/react/ui/components/Form/index.d.ts +0 -0
  321. /package/{model → models}/packages/react/ui/components/Form/useForm.d.ts +0 -0
  322. /package/{model → models}/packages/react/ui/components/ImagePreview/ImagePreview.d.ts +0 -0
  323. /package/{model → models}/packages/react/ui/components/ImagePreview/PreviewImage.d.ts +0 -0
  324. /package/{model → models}/packages/react/ui/components/ImagePreview/index.d.ts +0 -0
  325. /package/{model → models}/packages/react/ui/components/Input/Input.d.ts +0 -0
  326. /package/{model → models}/packages/react/ui/components/Input/index.d.ts +0 -0
  327. /package/{model → models}/packages/react/ui/components/InputNumber/InputNumber.d.ts +0 -0
  328. /package/{model → models}/packages/react/ui/components/InputNumber/index.d.ts +0 -0
  329. /package/{model → models}/packages/react/ui/components/InputNumber/inputNumberUtils.d.ts +0 -0
  330. /package/{model → models}/packages/react/ui/components/Label/Label.d.ts +0 -0
  331. /package/{model → models}/packages/react/ui/components/Label/index.d.ts +0 -0
  332. /package/{model → models}/packages/react/ui/components/Layout/Layout.d.ts +0 -0
  333. /package/{model → models}/packages/react/ui/components/Layout/index.d.ts +0 -0
  334. /package/{model → models}/packages/react/ui/components/Loading/Loading.d.ts +0 -0
  335. /package/{model → models}/packages/react/ui/components/Loading/index.d.ts +0 -0
  336. /package/{model → models}/packages/react/ui/components/Menu/Menu.d.ts +0 -0
  337. /package/{model → models}/packages/react/ui/components/Menu/MenuContext.d.ts +0 -0
  338. /package/{model → models}/packages/react/ui/components/Menu/MenuItem.d.ts +0 -0
  339. /package/{model → models}/packages/react/ui/components/Menu/SubMenu.d.ts +0 -0
  340. /package/{model → models}/packages/react/ui/components/Menu/index.d.ts +0 -0
  341. /package/{model → models}/packages/react/ui/components/Menu/menuTypes.d.ts +0 -0
  342. /package/{model → models}/packages/react/ui/components/Menu/utils.d.ts +0 -0
  343. /package/{model → models}/packages/react/ui/components/Message/Message.d.ts +0 -0
  344. /package/{model → models}/packages/react/ui/components/Message/MessageManager.d.ts +0 -0
  345. /package/{model → models}/packages/react/ui/components/Message/data.d.ts +0 -0
  346. /package/{model → models}/packages/react/ui/components/Message/index.d.ts +0 -0
  347. /package/{model → models}/packages/react/ui/components/Modal/Modal.d.ts +0 -0
  348. /package/{model → models}/packages/react/ui/components/Modal/ModalManager.d.ts +0 -0
  349. /package/{model → models}/packages/react/ui/components/Modal/index.d.ts +0 -0
  350. /package/{model → models}/packages/react/ui/components/Notification/Notification.d.ts +0 -0
  351. /package/{model → models}/packages/react/ui/components/Notification/index.d.ts +0 -0
  352. /package/{model → models}/packages/react/ui/components/Overlay/Overlay.d.ts +0 -0
  353. /package/{model → models}/packages/react/ui/components/Overlay/index.d.ts +0 -0
  354. /package/{model → models}/packages/react/ui/components/Pagination/Pagination.d.ts +0 -0
  355. /package/{model → models}/packages/react/ui/components/Pagination/index.d.ts +0 -0
  356. /package/{model → models}/packages/react/ui/components/Popup/Popup.d.ts +0 -0
  357. /package/{model → models}/packages/react/ui/components/Popup/index.d.ts +0 -0
  358. /package/{model → models}/packages/react/ui/components/Radio/Radio.d.ts +0 -0
  359. /package/{model → models}/packages/react/ui/components/Radio/RadioGroup.d.ts +0 -0
  360. /package/{model → models}/packages/react/ui/components/Radio/index.d.ts +0 -0
  361. /package/{model → models}/packages/react/ui/components/Search/Search.d.ts +0 -0
  362. /package/{model → models}/packages/react/ui/components/Search/index.d.ts +0 -0
  363. /package/{model → models}/packages/react/ui/components/Select/Select.d.ts +0 -0
  364. /package/{model → models}/packages/react/ui/components/Select/dropdownPositioning.d.ts +0 -0
  365. /package/{model → models}/packages/react/ui/components/Select/index.d.ts +0 -0
  366. /package/{model → models}/packages/react/ui/components/Skeleton/Skeleton.d.ts +0 -0
  367. /package/{model → models}/packages/react/ui/components/Skeleton/index.d.ts +0 -0
  368. /package/{model → models}/packages/react/ui/components/Switch/Switch.d.ts +0 -0
  369. /package/{model → models}/packages/react/ui/components/Switch/index.d.ts +0 -0
  370. /package/{model → models}/packages/react/ui/components/TableSearch/TableSearch.d.ts +0 -0
  371. /package/{model → models}/packages/react/ui/components/TableSearch/index.d.ts +0 -0
  372. /package/{model → models}/packages/react/ui/components/TableSearch/lang.d.ts +0 -0
  373. /package/{model → models}/packages/react/ui/components/TableSearch/tableSearchLocaleStore.d.ts +0 -0
  374. /package/{model → models}/packages/react/ui/components/Tabs/Tabs.d.ts +0 -0
  375. /package/{model → models}/packages/react/ui/components/Tabs/index.d.ts +0 -0
  376. /package/{model → models}/packages/react/ui/components/Textarea/Textarea.d.ts +0 -0
  377. /package/{model → models}/packages/react/ui/components/Textarea/index.d.ts +0 -0
  378. /package/{model → models}/packages/react/ui/components/Tooltip/Tooltip.d.ts +0 -0
  379. /package/{model → models}/packages/react/ui/components/Tooltip/index.d.ts +0 -0
  380. /package/{model → models}/packages/react/ui/components/TreeSelect/TreeSelect.d.ts +0 -0
  381. /package/{model → models}/packages/react/ui/components/TreeSelect/index.d.ts +0 -0
  382. /package/{model → models}/packages/react/ui/components/Upload/ImageUpload.d.ts +0 -0
  383. /package/{model → models}/packages/react/ui/components/Upload/Upload.d.ts +0 -0
  384. /package/{model → models}/packages/react/ui/components/Upload/index.d.ts +0 -0
  385. /package/{model → models}/packages/react/ui/components/breadcrumb/breadcrumb.d.ts +0 -0
  386. /package/{model → models}/packages/react/ui/components/breadcrumb/index.d.ts +0 -0
  387. /package/{model → models}/packages/react/ui/components/hooks/useDropdownPositioning.d.ts +0 -0
  388. /package/{model → models}/packages/react/ui/components/hooks/useInputController.d.ts +0 -0
  389. /package/{model → models}/packages/react/ui/components/index.d.ts +0 -0
  390. /package/{model → models}/packages/react/ui/components/table/index.d.ts +0 -0
  391. /package/{model → models}/packages/react/ui/components/table/table.d.ts +0 -0
  392. /package/{model → models}/packages/react/ui/components/types/baseType.d.ts +0 -0
  393. /package/{model → models}/packages/react/ui/i18n/I18nProvider.d.ts +0 -0
  394. /package/{model → models}/packages/react/ui/i18n/index.d.ts +0 -0
  395. /package/{model → models}/packages/react/ui/i18n/useI18n.d.ts +0 -0
  396. /package/{model → models}/packages/react/ui/index.d.ts +0 -0
  397. /package/{model → models}/packages/react/ui/lib/createStoreHook.d.ts +0 -0
  398. /package/{model → models}/packages/react/ui/lib/export.d.ts +0 -0
  399. /package/{model → models}/packages/react/ui/lib/utils.d.ts +0 -0
  400. /package/{model → models}/packages/react/ui/stores/breadcrumb.d.ts +0 -0
  401. /package/{model → models}/packages/react/ui/stores/language.d.ts +0 -0
  402. /package/{model → models}/packages/react/ui/types/index.d.ts +0 -0
  403. /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 页面、model 类型和类型扩展放到同一个 npm 包里,项目只需要按目录补充自己的 `app/`、`model/`、`frontend/`。
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
- ├── model/
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
- pageBasePage: '/',
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
- | `pageBasePage` | `string` | 否 | `'/'` | 页面访问前缀,所有前端页面路由的基础路径 |
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` 对应 `model/{modelKey}/project/{projectKey}.ts` 里的 `projectKey`。
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` | 构建入口,提供前端资源构建 `buildFE` 和消费方 Node/backend 构建 `buildBE` |
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/model` | model 配置类型 |
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
- model/{modelKey}/mode.ts
249
- model/{modelKey}/project/{projectKey}.ts
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/model'
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
- - `model/index.ts` 或 `model/index.js` 会被 loader 跳过。
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
- // model/product/mode.ts
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
- // model/product/project/demo.ts
514
+ // models/product/project/demo.ts
415
515
  export default {
416
516
  name: 'Demo 企业商品后台',
417
517
  menu: [
@@ -553,7 +653,7 @@ 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
- model/**/*.(js|ts) -> 内置 project service 按需读取的项目模型配置
656
+ models/**/*.(js|ts) -> 内置 project service 按需读取的项目模型配置
557
657
  ```
558
658
 
559
659
  内置扩展:
@@ -1101,7 +1201,7 @@ Schema 表单校验会把 AJV keyword 映射到内置语言 key,覆盖 `requir
1101
1201
 
1102
1202
  非必填字段为空时会跳过 AJV 校验,空值包括 `undefined`、`null`、空字符串、空数组和空对象。
1103
1203
 
1104
- 如果需要扩展更多 AJV 文案,在源码项目中同步增加:
1204
+ 如果需要扩展更多 AJV 文案,需要在 TemplateCore 源码中补充后重新发布:
1105
1205
 
1106
1206
  1. `frontend/src/defaultPages/SchemaPage/utils/validator.ts` 的 `formatError()` 映射。
1107
1207
  2. `frontend/src/language/zh-CN.ts` 和 `frontend/src/language/en-US.ts` 文案。
@@ -1140,15 +1240,15 @@ initThemeMode()
1140
1240
  applyThemeMode('dark', true)
1141
1241
  ```
1142
1242
 
1143
- RAF 风格计时器由 `@tc/common/rafTimer` 提供,浏览器优先使用 `requestAnimationFrame`,缺少 RAF 时自动降级到 `setTimeout`。
1243
+ RAF 风格计时器通过 `@_tc/template-core/fe` 对外提供,浏览器优先使用 `requestAnimationFrame`,缺少 RAF 时自动降级到 `setTimeout`。
1144
1244
 
1145
1245
  `@_tc/template-core/fe/rc` 和 `@_tc/template-core/fe/rc/hooks` 也会随发布包提供对应 UI 与 hooks 入口;hooks 汇总入口包含 `useBreadcrumb`、`useExecuteOnce`、`useInit`、`useLanguage`、`usePagination`、`useRefState`、`useWatch`。
1146
1246
 
1147
- `useRefState` 支持可选的 `delayTiming` 参数,传入大于 0 的值时会延迟 state 提交,并复用 `@tc/common/rafTimer` 的浏览器优先、Node/SSR 自动降级计时器实现。
1247
+ `useRefState` 支持可选的 `delayTiming` 参数,传入大于 0 的值时会延迟 state 提交,并复用包内浏览器优先、Node/SSR 自动降级的计时器实现。
1148
1248
 
1149
1249
  ### 前端请求封装详解
1150
1250
 
1151
- 框架内置的请求封装基于 `@tc/common/http`,底层使用原生 `fetch` API,实现了类似 Axios 的接口和拦截器机制,提供了签名、鉴权、错误处理等能力。
1251
+ 框架内置的请求封装通过 `@_tc/template-core/fe` 和 `@_tc/template-core/fe/common/request` 对外提供,底层使用原生 `fetch` API,实现了类似 Axios 的接口和拦截器机制,提供了签名、鉴权、错误处理等能力。
1152
1252
 
1153
1253
  **基础配置**:
1154
1254
  - `BASE_URL`:固定为 `/api`
@@ -1259,7 +1359,7 @@ try {
1259
1359
 
1260
1360
  ## 样式与 Tailwind V4
1261
1361
 
1262
- 使用内置前端或 UI 组件时,需要引入包内样式。默认 `@_tc/template-core/fe` `initApp` 会经过源码入口 `frontend/src/main.tsx` 引入 `frontend/src/main.css`;如果项目侧自定义入口、只使用 `fe/rc` 组件,或希望样式入口更明确,建议显式引入:
1362
+ 使用内置前端或 UI 组件时,需要引入包内样式。默认 Dashboard 入口已经包含包内全局样式;如果项目侧自定义入口、只使用 `fe/rc` 组件,或希望样式入口更明确,建议显式引入:
1263
1363
 
1264
1364
  ```ts
1265
1365
  // frontend/xxx/xxx.entry.tsx
@@ -1274,7 +1374,7 @@ import '@_tc/template-core/fe/tailwind_ui.css'
1274
1374
 
1275
1375
  /* 扫描项目源码 */
1276
1376
  @source "./**/*.{js,ts,jsx,tsx}";
1277
- @source "../model/**/*.{js,ts,jsx,tsx}";
1377
+ @source "../models/**/*.{js,ts,jsx,tsx}";
1278
1378
  ```
1279
1379
 
1280
1380
  Tailwind V4 默认会忽略 `node_modules` 和 `.gitignore` 中的文件。如果没有使用上面的 `tailwind_ui.css`,或者项目侧构建链路绕过了 TemplateCore 的样式入口,需要手动把包加入 Tailwind 扫描:
@@ -1284,7 +1384,7 @@ Tailwind V4 默认会忽略 `node_modules` 和 `.gitignore` 中的文件。如
1284
1384
  @import "tailwindcss";
1285
1385
 
1286
1386
  @source "./**/*.{js,ts,jsx,tsx}";
1287
- @source "../model/**/*.{js,ts,jsx,tsx}";
1387
+ @source "../models/**/*.{js,ts,jsx,tsx}";
1288
1388
  @source "../node_modules/@_tc/template-core";
1289
1389
  ```
1290
1390
 
@@ -1478,7 +1578,7 @@ frontend/report/index.html yes
1478
1578
  frontend/report/report.html yes
1479
1579
  ```
1480
1580
 
1481
- 不要在插槽文件里写 `<!DOCTYPE html>`、`<html>`、`<body>` 或 `<div id="root"></div>`。页面外壳由 TemplateCore 的 `app/view/entry.tpl` 统一生成,`window._basePath`、`window._projKey`、`window._signKey`、`window.appOptions` 也由它注入。
1581
+ 不要在插槽文件里写 `<!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
1582
 
1483
1583
  扩展 Dashboard 路由:
1484
1584
 
@@ -1579,12 +1679,12 @@ import { buildBE } from '@_tc/template-core/bundler'
1579
1679
 
1580
1680
  await buildBE({
1581
1681
  rootDir: process.cwd(),
1582
- input: ['index.ts', 'index.js', 'app', 'config', 'model'],
1682
+ input: ['index.ts', 'index.js', 'app', 'config', 'models'],
1583
1683
  outDir: 'dist',
1584
1684
  format: 'cjs',
1585
1685
  alias: {
1586
1686
  '@app': './app',
1587
- '@model': './model',
1687
+ '@model': './models',
1588
1688
  },
1589
1689
  })
1590
1690
  ```
@@ -1604,7 +1704,7 @@ await buildBE({
1604
1704
  import chokidar from 'chokidar'
1605
1705
  import { buildBE } from '@_tc/template-core/bundler'
1606
1706
 
1607
- const input = ['index.ts', 'index.js', 'app', 'config', 'model']
1707
+ const input = ['index.ts', 'index.js', 'app', 'config', 'models']
1608
1708
 
1609
1709
  let building = false
1610
1710
  let pending = false
@@ -1626,7 +1726,7 @@ async function runBuild() {
1626
1726
  format: 'cjs',
1627
1727
  alias: {
1628
1728
  '@app': './app',
1629
- '@model': './model',
1729
+ '@model': './models',
1630
1730
  },
1631
1731
  })
1632
1732
  console.log('[buildBE] done')
@@ -1671,7 +1771,7 @@ chokidar
1671
1771
  默认会在当前工作目录构建这些入口:
1672
1772
 
1673
1773
  ```ts
1674
- ['index.ts', 'index.js', 'app', 'config', 'model']
1774
+ ['index.ts', 'index.js', 'app', 'config', 'models']
1675
1775
  ```
1676
1776
 
1677
1777
  不存在的默认入口会自动跳过;如果没有任何匹配源码,构建仍会失败。输出到 `dist`,格式为 `cjs`。默认 `outputStructure: "preserve"` 按源路径输出,`bundleDependencies: false` 会 external Node 内置模块和 npm 包,不会把依赖打进产物。`buildBE` 会按同一组 input 扫描并复制内置白名单资源扩展,主要覆盖 `app`、`config`、`model` 目录。
@@ -1680,12 +1780,12 @@ chokidar
1680
1780
 
1681
1781
  ```ts
1682
1782
  await buildBE({
1683
- input: ['app', 'config', 'model'],
1783
+ input: ['app', 'config', 'models'],
1684
1784
  outDir: 'dist',
1685
1785
  format: ['es', 'cjs'],
1686
1786
  alias: {
1687
1787
  '@app': './app',
1688
- '@model': './model',
1788
+ '@model': './models',
1689
1789
  },
1690
1790
  })
1691
1791
  ```
@@ -1707,7 +1807,7 @@ await buildBE({
1707
1807
 
1708
1808
  ```ts
1709
1809
  await buildBE({
1710
- input: ['app', 'config', 'model'],
1810
+ input: ['app', 'config', 'models'],
1711
1811
  allowMissingInput: true,
1712
1812
  })
1713
1813
  ```
@@ -1743,8 +1843,8 @@ export default components
1743
1843
  // frontend/extended/dash/routeGuard.ts
1744
1844
  import type { DashRouteGuard } from '@_tc/template-core/fe'
1745
1845
 
1746
- const dashRouteGuard: DashRouteGuard = ({ isLoggedIn }) => {
1747
- if (!isLoggedIn) return '/login'
1846
+ const dashRouteGuard: DashRouteGuard = ({ isLoggedIn, isSSR }) => {
1847
+ if (!isLoggedIn) return isSSR ? '/login?from=ssr' : '/login'
1748
1848
  }
1749
1849
 
1750
1850
  export default dashRouteGuard
@@ -1754,6 +1854,7 @@ export default dashRouteGuard
1754
1854
 
1755
1855
  - 返回 `string`:框架使用 `window.location.href` 跳转,登录页不需要在 Dash 路由下。
1756
1856
  - 返回非 `string`:中断 Dashboard 内置重定向,使用方可自行跳转或处理提示。
1857
+ - 入参包含 `renderMode: 'csr' | 'ssr'` 和 `isSSR`,可区分 SSR hydration 后的守卫跳转和普通 CSR 跳转。
1757
1858
  - `DashRouteGuardResult` 是 `string | undefined`;`undefined`(包括已登录分支的隐式返回)也会打断 Dashboard 内置重定向。
1758
1859
  - 没有自定义 `routeGuard` 文件时,框架使用兜底空对象,不影响默认 Dashboard 重定向。
1759
1860
 
@@ -1830,9 +1931,9 @@ CallCom 是 SchemaPage 中的弹窗、抽屉、面板类组件。内置组件有
1830
1931
 
1831
1932
  ```ts
1832
1933
  // typing/template-core.d.ts
1833
- import '@_tc/template-core/model'
1934
+ import '@_tc/template-core/models'
1834
1935
 
1835
- declare module '@_tc/template-core/model' {
1936
+ declare module '@_tc/template-core/models' {
1836
1937
  export namespace CallComNamespace {
1837
1938
  interface ConfigMap {
1838
1939
  auditPanel: {
@@ -1951,9 +2052,9 @@ cover: {
1951
2052
 
1952
2053
  ```ts
1953
2054
  // typing/template-core.d.ts
1954
- import '@_tc/template-core/model'
2055
+ import '@_tc/template-core/models'
1955
2056
 
1956
- declare module '@_tc/template-core/model' {
2057
+ declare module '@_tc/template-core/models' {
1957
2058
  export namespace SchemaTableNamespace {
1958
2059
  interface RenderComponentPropsMap {
1959
2060
  PriceCell: {
@@ -2017,7 +2118,7 @@ price: {
2017
2118
 
2018
2119
  ```json
2019
2120
  {
2020
- "include": ["app/**/*", "model/**/*", "frontend/**/*", "typing/**/*.d.ts"]
2121
+ "include": ["app/**/*", "models/**/*", "frontend/**/*", "typing/**/*.d.ts"]
2021
2122
  }
2022
2123
  ```
2023
2124
 
@@ -2044,9 +2145,9 @@ declare module '@_tc/template-core/fe/rc' {
2044
2145
 
2045
2146
  ```ts
2046
2147
  // typing/template-core.d.ts
2047
- import '@_tc/template-core/model'
2148
+ import '@_tc/template-core/models'
2048
2149
 
2049
- declare module '@_tc/template-core/model' {
2150
+ declare module '@_tc/template-core/models' {
2050
2151
  interface ModelModeMap {
2051
2152
  portal: {
2052
2153
  portalConfig: {
@@ -2061,7 +2162,7 @@ declare module '@_tc/template-core/model' {
2061
2162
  使用新 `mode`:
2062
2163
 
2063
2164
  ```ts
2064
- import type { ModelDataType } from '@_tc/template-core/model'
2165
+ import type { ModelDataType } from '@_tc/template-core/models'
2065
2166
 
2066
2167
  const model: ModelDataType<'portal'> = {
2067
2168
  mode: 'portal',
@@ -2080,7 +2181,7 @@ export default model
2080
2181
  继续使用内置管理后台时:
2081
2182
 
2082
2183
  ```ts
2083
- import type { ModelDataType } from '@_tc/template-core/model'
2184
+ import type { ModelDataType } from '@_tc/template-core/models'
2084
2185
 
2085
2186
  const model: ModelDataType<'MB'> = {
2086
2187
  mode: 'MB',
@@ -2096,7 +2197,7 @@ const model: ModelDataType<'MB'> = {
2096
2197
  扩展目标:
2097
2198
 
2098
2199
  ```ts
2099
- declare module '@_tc/template-core/model' {
2200
+ declare module '@_tc/template-core/models' {
2100
2201
  export namespace CallComNamespace {
2101
2202
  interface ConfigMap {}
2102
2203
  interface OptionMap {}
@@ -2113,7 +2214,7 @@ declare module '@_tc/template-core/model' {
2113
2214
  扩展目标:
2114
2215
 
2115
2216
  ```ts
2116
- declare module '@_tc/template-core/model' {
2217
+ declare module '@_tc/template-core/models' {
2117
2218
  export namespace SchemaTableNamespace {
2118
2219
  interface RenderComponentPropsMap {}
2119
2220
  }
@@ -2203,7 +2304,7 @@ cp -R node_modules/@_tc/template-core/.skills/tc-component-usage-skills "${CODEX
2203
2304
 
2204
2305
  ## 注意事项
2205
2306
 
2206
- - 不要在项目代码里引用 `dist/fe/*`、`dist/model/*` 这类构建产物路径。
2307
+ - 不要在项目代码里引用 `dist/fe/*`、`dist/models/*` 这类构建产物路径。
2207
2308
  - npm 使用方只使用公开入口:`@_tc/template-core/*`。
2208
2309
  - SchemaForm 和 CallCom 的类型扩展、运行时注册都要做,少一个就只会“类型通过但页面不显示”或“页面能配但类型报错”。
2209
2310
  - `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 t=e=>JSON.stringify(e).replace(/</g,`\\u003c`).replace(/>/g,`\\u003e`).replace(/&/g,`\\u0026`).replace(/\u2028/g,`\\u2028`).replace(/\u2029/g,`\\u2029`),n=(n=>class{async renderPage(r,i){let a=r.path;if(n.extends.localCacheHtmlEtag.keepFreshFEBuildKey(),a.includes(`${n.options.apiPrefix}/`))await i();else{n.extends.logger.log(` - render page: `+r.params.page);try{let i=r.query.projk;Array.isArray(i)&&(i=e.joinStr(...i));let a={projKey:i??``,name:n.options?.name??``,env:n.envs.get(),FEBasePage:t(`${n.options.pageBasePage}`),basePath:t(`${n.options.pageBasePage}${r.params.page}`),projKeyJson:t(String(r.query.projk??``)),signKey:t(n.config.signKey),options:t(n.options)},o=n.extends.renderView(`${r.params.page}.entry.tpl`,r,a),s=e.joinStr(a.basePath,a.name,a.env,a.projKey);if(!n.extends.localCacheHtmlEtag.hasEtag(s)){let e=n.extends.crypto.hmacSign(o);n.extends.localCacheHtmlEtag.setEtag(s,e)}let c=n.extends.localCacheHtmlEtag.getEtag(s);if(c||console.log(`---- etag 缓存异常 请检查服务 ----`),r.etag=c??Date.now()+``,r.set(`Cache-Control`,`public, max-age=${(n.config.resourceCacheTimeMs??300*1e3)/1e3}, immutable`),r.fresh){r.status=304;return}}catch(e){console.log(`-------------- render view error --------------`),console.log(e),n.extends.generateErrorMessage(`template not found`,{status:404,showError:!0,code:0})}}}});module.exports=n;
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,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}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;
@@ -1 +1 @@
1
- const e=require(`../_virtual/_rolldown/runtime.js`);let t=require(`koa-compress`);t=e.__toESM(t);let n=require(`koa-bodyparser`);n=e.__toESM(n);let r=require(`koa-static`);r=e.__toESM(r);var i=(0,n.default)({formLimit:`1000mb`,enableTypes:[`form`,`json`,`text`]}),a=e=>{let n=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,t.default)({threshold:2048})),e.publicsPath.forEach(t=>e.use((0,r.default)(t,n))),e.use(i),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=a;
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;
@@ -1 +1 @@
1
- var e=(e,t)=>{let{pageBasePage:n}=e.options;t.level=2,t.get([`${n}:page`,`${n}:page/:r(.*)`],e.controller.view.renderPage.bind(e.controller.view))};module.exports=e;
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,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}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;
@@ -1,46 +1,11 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en" class="dark" style="color-scheme: dark">
3
3
  <head>
4
- <meta charset="UTF-8" />
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
- <script id="input">
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 -->
@@ -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`,`model`];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;
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;
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../_virtual/_rolldown/runtime.js`),t=require(`../packages/common/log/index.js`),n=require(`../ssrSharedData/outputPaths.js`),r=require(`./feSharedConfig.js`),i=require(`./ssrEntries.js`),a=require(`./state.js`),o=require(`./utils.js`);let s=require(`path`);s=e.__toESM(s);let c=require(`vite`);var l=r.createBundlerPaths();function u(e){return i.collectBundlerSSREntries(l,e)}function d(e){return n.resolveSSRServerOutDir({...e,frameNodePath:l.frameNodePath})}function f(e){return n.resolveSSRClientOutDir({...e,frameNodePath:l.frameNodePath})}function p(e){return n.resolveSSRManifestOutDir({...e,frameNodePath:l.frameNodePath})}async function m(e,n){t.logGreen(`[SSR] Building server bundle...`),await(0,c.build)({configFile:!1,plugins:r.createFEBasePlugins(),build:{outDir:d(n),emptyOutDir:!0,ssr:!0,rolldownOptions:{input:e,external:r.ssrReactExternal,output:{codeSplitting:{groups:o.createFECodeSplittingGroups()}}}},ssr:{external:r.ssrReactExternal,noExternal:r.createSSRNoExternal(l,n?.ssrNoExternal)},resolve:{alias:r.createSSRResolveAlias(l,n)}}),t.logGreen(`[SSR] Server bundle done.`)}async function h(e,n){t.logGreen(`[SSR] Building shared browser client bundle...`);let r={...a.buildFESharedState.options};a.setBuildFEOptions({...r,baseDir:n?.baseDir??r.baseDir,output:n?.output??r.output,minifyHtml:n?.minifyHtml??r.minifyHtml});try{await o.VBuildFE(o.entries(a.buildFESharedState.options),void 0,{ssrInput:e,ssrManifestOutDir:p(n)})}finally{a.setBuildFEOptions(r)}t.logGreen(`[SSR] Shared browser client bundle done.`)}async function g(e){let n=u(e);if(Object.keys(n).length)try{await m(n,e),await h(n,e),t.logGreen(`[SSR] All builds completed.`)}catch(e){throw t.logRed(`[SSR] Build failed:`),t.logRed(e),e}}async function _(e){let r=await import(`chokidar`),i=e?.debounceMs??200,a=s.default.resolve(n.resolveRunPath(e),`./ssr/apps`),o=[...new Set([l.frameSSRAppsPath,a])],c=r.watch(o,{ignored:e=>{let t=e.split(s.default.sep).join(`/`);return/(^|\/)\./.test(t)||/(^|\/)node_modules(\/|$)/.test(t)||/(^|\/)(dist|build|coverage)(\/|$)/.test(t)||/(^|\/)ssr-(server|client)(\/|$)/.test(t)},depth:8,persistent:!0,ignoreInitial:!0,usePolling:!0,interval:300}),u,d=!1,f=!1,p=async()=>{if(d){f=!0;return}d=!0;try{do{f=!1;try{await g(e)}catch(e){t.logRed(e)}}while(f)}finally{d=!1}},m=e=>{t.logYellow(`[SSR] changed: ${e}`),u&&clearTimeout(u),u=setTimeout(()=>{u=void 0,p()},i)};return c.on(`all`,(e,t)=>{[`add`,`change`,`unlink`,`unlinkDir`].includes(e)&&m(t)}),c.on(`error`,e=>{t.logRed(`[SSR] watcher error:`),t.logRed(e)}),t.logYellow(`[SSR] watching ${o.join(`, `)}/...`),c}exports.buildSSR=g,exports.ssrClientOutDir=f,exports.ssrEntries=u,exports.ssrManifestOutDir=p,exports.ssrServerOutDir=d,exports.watchSSRFiles=_;