@_tc/template-core 0.2.0-bate.1 → 0.2.0-bate.10

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 (98) hide show
  1. package/.skills/tc-generator/reference/model-schema.md +18 -0
  2. package/.skills/tc-generator/reference/runtime-extensions.md +20 -0
  3. package/AGENT_README.md +29 -11
  4. package/README.md +215 -27
  5. package/cjs/app/controller/view.js +1 -1
  6. package/cjs/bundler/buildFE.js +1 -0
  7. package/cjs/bundler/index.js +1 -1
  8. package/cjs/bundler/utils.js +1 -1
  9. package/cjs/packages/common/index.js +1 -1
  10. package/cjs/packages/common/rafTimer.js +1 -0
  11. package/esm/app/controller/view.js +4 -1
  12. package/esm/bundler/buildFE.js +14 -0
  13. package/esm/bundler/index.js +3 -15
  14. package/esm/bundler/utils.js +1 -0
  15. package/esm/packages/common/index.js +3 -2
  16. package/esm/packages/common/rafTimer.js +47 -0
  17. package/fe/frontend/apps/dash/Dashboard.js +6 -4
  18. package/fe/frontend/apps/dash/dash.entry.js +4 -0
  19. package/fe/frontend/src/common/generateMenuData.d.ts +4 -1
  20. package/fe/frontend/src/common/generateMenuData.js +3 -3
  21. package/fe/frontend/src/common/language.d.ts +12 -1
  22. package/fe/frontend/src/common/language.js +25 -4
  23. package/fe/frontend/src/common/rafTimer.d.ts +1 -0
  24. package/fe/frontend/src/common/rafTimer.js +2 -0
  25. package/fe/frontend/src/common/request.js +1 -0
  26. package/fe/frontend/src/common/theme.d.ts +7 -0
  27. package/fe/frontend/src/common/theme.js +33 -0
  28. package/fe/frontend/src/components/BasePage/HeaderView.js +2 -2
  29. package/fe/frontend/src/components/LanguageSwitch/LanguageSwitch.js +22 -6
  30. package/fe/frontend/src/components/ThemeSwitch/ThemeSwitch.d.ts +3 -2
  31. package/fe/frontend/src/components/ThemeSwitch/ThemeSwitch.js +6 -29
  32. package/fe/frontend/src/components/ThemeSwitch/index.d.ts +1 -0
  33. package/fe/frontend/src/components/ThemeSwitch/index.js +3 -2
  34. package/fe/frontend/src/components/index.js +2 -2
  35. package/fe/frontend/src/defaultPages/NotFoundPage/index.js +4 -3
  36. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/DetailPanel.js +14 -9
  37. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/PopFrom.js +8 -7
  38. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaSearch/index.js +20 -24
  39. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.d.ts +10 -0
  40. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.js +17 -0
  41. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.d.ts +5 -0
  42. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.js +8 -0
  43. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/index.js +50 -32
  44. package/fe/frontend/src/defaultPages/SchemaPage/index.css +0 -4
  45. package/fe/frontend/src/defaultPages/SchemaPage/index.js +5 -3
  46. package/fe/frontend/src/defaultPages/SlotPage/index.js +6 -3
  47. package/fe/frontend/src/hooks/useText.d.ts +3 -0
  48. package/fe/frontend/src/hooks/useText.js +14 -0
  49. package/fe/frontend/src/index.d.ts +11 -3
  50. package/fe/frontend/src/index.js +8 -3
  51. package/fe/frontend/src/language/index.d.ts +0 -2
  52. package/fe/frontend/src/language/index.js +1 -7
  53. package/fe/frontend/src/language/resources.d.ts +2 -0
  54. package/fe/frontend/src/language/resources.js +9 -0
  55. package/fe/model/types/data/schema.d.ts +24 -2
  56. package/fe/model/types/index.d.ts +1 -0
  57. package/fe/packages/common/i18n/default.js +3 -0
  58. package/fe/packages/common/i18n/en-US.js +5 -2
  59. package/fe/packages/common/i18n/index.js +13 -0
  60. package/fe/packages/common/i18n/locales.js +7 -0
  61. package/fe/packages/common/index.d.ts +1 -0
  62. package/fe/packages/common/rafTimer.d.ts +7 -0
  63. package/fe/packages/common/rafTimer.js +168 -0
  64. package/fe/packages/react/hooks/index.d.ts +9 -0
  65. package/fe/packages/react/hooks/index.js +8 -0
  66. package/fe/packages/react/hooks/useRefState.d.ts +4 -12
  67. package/fe/packages/react/hooks/useRefState.js +18 -8
  68. package/fe/packages/react/ui/components/DataTable/dataTableWidth.d.ts +12 -0
  69. package/fe/packages/react/ui/components/DataTable/dataTableWidth.js +33 -0
  70. package/fe/packages/react/ui/components/DataTable/dataTableWidth.test.js +39 -0
  71. package/fe/packages/react/ui/components/DataTable/index.d.ts +1 -1
  72. package/fe/packages/react/ui/components/DataTable/index.js +12 -32
  73. package/fe/packages/react/ui/components/Textarea/Textarea.d.ts +1 -1
  74. package/fe/packages/react/ui/components/Textarea/Textarea.js +1 -1
  75. package/fe/packages/react/ui/components/types/baseType.d.ts +21 -0
  76. package/fe/packages/react/ui/components/types/baseType.js +0 -0
  77. package/model/frontend/src/common/language.d.ts +12 -1
  78. package/model/frontend/src/hooks/useText.d.ts +3 -0
  79. package/model/frontend/src/language/index.d.ts +0 -2
  80. package/model/frontend/src/language/resources.d.ts +2 -0
  81. package/model/model/types/data/schema.d.ts +24 -2
  82. package/model/model/types/index.d.ts +1 -0
  83. package/model/packages/common/index.d.ts +1 -0
  84. package/model/packages/common/rafTimer.d.ts +7 -0
  85. package/model/packages/react/ui/components/DataTable/dataTableWidth.d.ts +12 -0
  86. package/model/packages/react/ui/components/DataTable/index.d.ts +1 -1
  87. package/model/packages/react/ui/components/Textarea/Textarea.d.ts +1 -1
  88. package/model/packages/react/ui/components/types/baseType.d.ts +21 -0
  89. package/package.json +5 -5
  90. package/types/bundler/buildFE.d.ts +2 -0
  91. package/types/bundler/index.d.ts +1 -2
  92. package/types/packages/common/i18n/default.d.ts +4 -0
  93. package/types/packages/common/i18n/en-US.d.ts +6 -2
  94. package/types/packages/common/i18n/index.d.ts +21 -0
  95. package/types/packages/common/i18n/locales.d.ts +10 -0
  96. package/types/packages/common/i18n/types.d.ts +40 -0
  97. package/types/packages/common/index.d.ts +1 -0
  98. package/types/packages/common/rafTimer.d.ts +44 -0
@@ -210,6 +210,24 @@ Option meaning:
210
210
  | `editFormOption` | Edit modal form field. Omit to hide from edit. |
211
211
  | `detailPanelOption` | Detail drawer field. Omit to hide from detail. |
212
212
 
213
+ Table cell render components:
214
+
215
+ ```js
216
+ cover: {
217
+ type: "string",
218
+ label: "Cover",
219
+ tableOption: {
220
+ renderComponent: "PreviewImage",
221
+ renderComponentProps: {
222
+ width: 48,
223
+ height: 48,
224
+ },
225
+ },
226
+ }
227
+ ```
228
+
229
+ Built-in `PreviewImage` accepts the current field value as a string or string array. Project-specific table render components are registered in `frontend/extended/SchemaPage/SchemaTable/data.ts` and referenced by `tableOption.renderComponent`.
230
+
213
231
  Common form `comType` values:
214
232
 
215
233
  ```text
@@ -295,6 +295,26 @@ this.success(ctx, [
295
295
 
296
296
  For project-specific field types, create `frontend/extended/SchemaForm/data.ts` and default-export a component map keyed by field type.
297
297
 
298
+ ## SchemaTable Render Components
299
+
300
+ Use `tableOption.renderComponent` when a Schema CRUD table column needs a reusable renderer. TemplateCore includes `PreviewImage` for image preview columns:
301
+
302
+ ```js
303
+ cover: {
304
+ type: "string",
305
+ label: "Cover",
306
+ tableOption: {
307
+ renderComponent: "PreviewImage",
308
+ renderComponentProps: {
309
+ width: 48,
310
+ height: 48,
311
+ },
312
+ },
313
+ }
314
+ ```
315
+
316
+ For project-specific renderers, create `frontend/extended/SchemaPage/SchemaTable/data.ts` and default-export a component map typed as `SchemaTableRenderComponentsMap` from `@_tc/template-core/fe`. Extend `SchemaTableNamespace.RenderComponentPropsMap` from `@_tc/template-core/model` when TypeScript model config should know the renderer props.
317
+
298
318
  ## SchemaPage CallCom Extensions
299
319
 
300
320
  Use `frontend/extended/SchemaPage/CallCom/data.ts` when model `componentConfig` should open a custom runtime component instead of built-in create/edit/detail components. Custom components can import `schemaEventBus`, `eventsInfo`, and `merge` from `@_tc/template-core/fe` to close panels or refresh Schema tables.
package/AGENT_README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TemplateCore AI 助手速读
2
2
 
3
- 这份文档给在消费方项目中协助开发的 AI 助手/代码代理阅读。项目本身才是 `@_tc/template-core` 的使用方;AI 通过这份速读文档快速理解包的用法和边界。它是 `README.md` 的精简版,按渐进式披露组织:先用下面的最小信息完成常见任务,只有需要深入时再读末尾的参考文档。
3
+ 这份文档由 TemplateCore 框架提供方维护,面向下游消费方项目中的 AI 助手/代码代理。消费方项目通过 `@_tc/template-core` 使用框架能力;AI 可以通过这份速读文档快速理解包的公开入口、约定用法和边界。它是 `README.md` 的面向 Agent 的精简版,按渐进式披露组织:先用下面的最小信息完成常见任务,只有需要深入时再读末尾的参考文档。
4
4
 
5
5
  ## 1. 先看结论
6
6
 
@@ -11,7 +11,7 @@ TemplateCore 是一个 TypeScript + Koa + React 的后台框架包。它提供
11
11
  - `model/` 配置驱动的菜单、项目和 CRUD 页面。
12
12
  - 前端构建 `buildFE()` 输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
13
13
  - 消费方 Node/backend 构建 `buildBE()`。
14
- - 类型扩展机制,用于扩展 SchemaForm 字段、CallCom 组件和 Koa app 类型。
14
+ - 类型扩展机制,用于扩展 SchemaForm 字段、SchemaTable 单元格渲染组件、CallCom 组件和 Koa app 类型。
15
15
 
16
16
  优先使用公开入口,不要从包内部源码路径导入。下面这些入口以 npm 发布产物为准;源码仓库根 `package.json` 的 `exports` 会在构建发布包时生成到 `dist/package.json`。
17
17
 
@@ -19,9 +19,11 @@ TemplateCore 是一个 TypeScript + Koa + React 的后台框架包。它提供
19
19
  | --- | --- |
20
20
  | `@_tc/template-core` | `serverStart`、`baseFn`、Koa/Controller/Service 类型。 |
21
21
  | `@_tc/template-core/bundler` | `buildFE()`、`buildBE()`。 |
22
- | `@_tc/template-core/fe` | 前端初始化、请求方法、Dashboard/Schema 类型、共享状态、业务前端组件。 |
22
+ | `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、请求方法、Dashboard/Schema 类型、token 工具、RAF 计时器、共享状态、业务前端组件。 |
23
+ | `@_tc/template-core/fe/main` | 前端初始化入口。 |
23
24
  | `@_tc/template-core/fe/common/request` | 请求实例、请求方法和请求类型的显式子路径。 |
24
25
  | `@_tc/template-core/fe/rc` | React UI 组件和 SchemaForm 组件。 |
26
+ | `@_tc/template-core/fe/rc/hooks` | React hooks 汇总入口。 |
25
27
  | `@_tc/template-core/fe/tailwind_ui.css` | 内置前端/UI 全局样式。 |
26
28
  | `@_tc/template-core/model` | `ModelDataType` 等 model 配置类型。 |
27
29
 
@@ -367,13 +369,24 @@ import '@_tc/template-core/fe/tailwind_ui.css'
367
369
 
368
370
  ```ts
369
371
  import {
372
+ addLanguageResources,
373
+ clearRafTimer,
370
374
  api,
375
+ clearAuthToken,
371
376
  get,
377
+ getAuthToken,
378
+ localKeyMap,
372
379
  post,
380
+ renderImportComponent,
373
381
  request,
382
+ rafSetInterval,
383
+ rafSetTimeout,
374
384
  schemaEventBus,
375
385
  schemaStore,
386
+ setAuthToken,
387
+ setLanguage,
376
388
  useSchemaStore,
389
+ useText,
377
390
  LanguageSwitch,
378
391
  ThemeSwitch,
379
392
  } from '@_tc/template-core/fe'
@@ -401,15 +414,19 @@ import { Button, DataTable, Form, Input, Modal, Select } from '@_tc/template-cor
401
414
  常用前端能力:
402
415
 
403
416
  - 请求方法:`api`、`request`、`get`、`post`、`put`、`patch`、`del`。
417
+ - RAF 风格计时器:`rafSetTimeout`、`rafSetInterval`、`rafClearTimeout`、`rafClearInterval`、`clearRafTimer`,缺少 RAF 时自动降级到 `setTimeout`。
404
418
  - 请求类型:`BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError`。
405
419
  - 请求 header:自动添加 `s_t`、`s_sign`、`projk`;存在短 token 时添加 `Authorization: Bearer ${token}`。
420
+ - 默认会先设置 `Content-Type: application/json`;如果是上传文件、`FormData` 或其他内容类型,请在请求配置里显式覆盖。
421
+ - Token 工具:`getAuthToken()`、`setAuthToken()`、`clearAuthToken()`、`localKeyMap`;`getAuthToken()` 是同步函数,读取前无需 `await`。
406
422
  - 本地 key:短 token 是 `localStorage.auth_token`,项目 key 是 `localStorage.p_J_k`;刷新 token header 默认名是 `RT`。
407
- - `getAuthToken()` 是同步函数,读取前无需 `await`。
423
+ - 组件加载辅助:`renderImportComponent(import('./Page'))` 会用 `React.lazy` + `Suspense` 渲染动态组件。
408
424
  - Schema 通信:`schemaEventBus`、`eventsInfo`、`merge`。
409
425
  - 共享状态:`modeStore`、`schemaStore`、`apiFreezerStore` 及对应 hooks。
410
- - 多语言:`i18nStore.getState().addResources()`,配置文案可写 `$i18n::...`。
426
+ - 多语言:`addLanguageResources()` 追加或新增某语种文案,`setLanguage()` 切换语言,React render 中用 `useText()`,非 React 工具代码用 `getText()`,配置文案可写 `$i18n::...`。
411
427
  - 主题:`ThemeSwitch` 会同步根节点 `dark` class 和 `localStorage`。
412
428
  - `Input type="password"` 会自动显示密码显隐按钮;`allowClear` 不作用于密码输入。
429
+ - RAF 风格计时器由 `@tc/common/rafTimer` 提供,浏览器优先使用 RAF,Node/SSR 自动降级到 `setTimeout`。
413
430
 
414
431
  不要直接依赖 `frontend/src/...`、`packages/react/ui/...` 这类包内部路径。
415
432
 
@@ -609,13 +626,14 @@ chokidar
609
626
 
610
627
  扩展前端类型或组件:
611
628
 
612
- 1. SchemaForm 字段类型、CallCom 组件、Koa app 类型都支持 TypeScript 声明合并。
629
+ 1. SchemaForm 字段类型、SchemaTable 单元格渲染组件、CallCom 组件、Koa app 类型都支持 TypeScript 声明合并。
613
630
  2. 运行时组件通常放在业务 `frontend/extended/`。
614
- 3. Dashboard 扩展点包括 `frontend/extended/dash/init.ts`、`frontend/extended/dash/customRoutes.tsx`、`frontend/extended/dash/components.tsx`、`frontend/extended/dash/routeGuard.ts`。
615
- 4. `dash/init` 在 React 渲染前执行,适合注册 axios 拦截器等全局初始化逻辑;类型是 `DashInit`。
616
- 5. `dash/routeGuard` 用来判断登录。返回登录页 URL 字符串时,Dashboard `window.location.href` 跳转;`DashRouteGuardResult` 是 `string | undefined`,`undefined`(包括已登录分支的隐式返回)会打断 Dashboard 内置重定向,业务方可自行跳转。
617
- 6. 自定义入口的 `initApp` 支持 `beforeRender` / `afterRender`,分别在 React 渲染前和首次渲染提交后触发。
618
- 7. 优先查看公开入口 `.d.ts` npm 包根目录 `README.md`;如果当前环境是源码仓库,再继续读 `docs/type-extension.md` `docs/schema-form.md`。
631
+ 3. 表格单元格渲染组件注册到 `frontend/extended/SchemaPage/SchemaTable/data.ts`,字段上用 `tableOption.renderComponent` 和 `renderComponentProps`。
632
+ 4. Dashboard 扩展点包括 `frontend/extended/dash/init.ts`、`frontend/extended/dash/customRoutes.tsx`、`frontend/extended/dash/components.tsx`、`frontend/extended/dash/routeGuard.ts`。
633
+ 5. `dash/init` React 渲染前执行,适合注册 axios 拦截器等全局初始化逻辑;类型是 `DashInit`。
634
+ 6. `dash/routeGuard` 用来判断登录。返回登录页 URL 字符串时,Dashboard 用 `window.location.href` 跳转;`DashRouteGuardResult` `string | undefined`,`undefined`(包括已登录分支的隐式返回)会打断 Dashboard 内置重定向,业务方可自行跳转。
635
+ 7. 自定义入口的 `initApp` 支持 `beforeRender` / `afterRender`,分别在 React 渲染前和首次渲染提交后触发。
636
+ 8. 优先查看公开入口 `.d.ts` 和 npm 包根目录 `README.md`;如果当前环境是源码仓库,再继续读 `docs/type-extension.md` 和 `docs/schema-form.md`。
619
637
 
620
638
  ## 8. 继续深入
621
639
 
package/README.md CHANGED
@@ -116,7 +116,7 @@ export default {
116
116
  }
117
117
  ```
118
118
 
119
- `auth.ATKey` / `auth.RTKey` 用于约定业务鉴权中间件读取短 token 和刷新 token 的 header 名;默认分别为 `Authorization` 和 `RT`。
119
+ `auth.ATKey` / `auth.RTKey` 用于约定项目鉴权中间件读取短 token 和刷新 token 的 header 名;默认分别为 `Authorization` 和 `RT`。
120
120
 
121
121
  静态资源挂载顺序为:项目 `app/public`、框架 `app/public`、`additionalPublicPaths`。Nunjucks 模板查找顺序为:项目 `app/public/dist`、框架 `app/public/dist`、`additionalPublicPaths/dist`。这些目录由 `app.publicsPath` 统一维护。当 `buildFE` 输出到自定义目录时,可以用 `additionalPublicPaths` 把该目录交给 Koa 提供静态资源访问和模板渲染;如果需要模板查找也命中追加目录,请传绝对路径数组。
122
122
 
@@ -127,7 +127,7 @@ buildFE(mode: 'dev' | 'prod', options?: BuildFEOptions)
127
127
  ```
128
128
 
129
129
  **mode**:构建模式
130
- - `'dev'`:开发模式,构建一次并监听业务 `frontend/` 变化后重建
130
+ - `'dev'`:开发模式,构建一次并监听项目 `frontend/` 变化后重建
131
131
  - `'prod'`:生产模式,构建优化后的静态资源
132
132
 
133
133
  **options.output**:构建输出位置
@@ -176,20 +176,23 @@ http://localhost:9000/dash?projk=demo
176
176
 
177
177
  ## 常用公开入口
178
178
 
179
- 完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks/*` 等子路径。
179
+ 完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/common/request`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks` 等子路径。
180
180
 
181
181
  | 入口 | 用途 |
182
182
  | --- | --- |
183
183
  | `@_tc/template-core` | 服务启动、基础 Controller/Service、Koa 类型 |
184
184
  | `@_tc/template-core/bundler` | 构建入口,提供前端资源构建 `buildFE` 和消费方 Node/backend 构建 `buildBE` |
185
- | `@_tc/template-core/fe` | 前端初始化、Dash 路由扩展、请求方法、SchemaPage 事件、共享状态和内置前端组件 |
185
+ | `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、Dash 路由扩展、请求方法、SchemaPage 事件、token 工具、共享状态和内置前端组件 |
186
+ | `@_tc/template-core/fe/main` | 前端初始化入口 |
187
+ | `@_tc/template-core/fe/common/request` | 请求实例、请求方法和请求类型的显式子路径 |
186
188
  | `@_tc/template-core/fe/rc` | UI/SchemaForm 组件和类型 |
189
+ | `@_tc/template-core/fe/rc/hooks` | React hooks 汇总入口 |
187
190
  | `@_tc/template-core/fe/tailwind_ui.css` | 前端全局样式入口,源码对应 `frontend/src/main.css` |
188
191
  | `@_tc/template-core/model` | model 配置类型 |
189
192
 
190
193
  ### 后端类型
191
194
 
192
- `@_tc/template-core` 会导出常用 Node 侧类型,业务项目写 `app/*` 文件时建议优先复用这些类型。
195
+ `@_tc/template-core` 会导出常用 Node 侧类型,项目编写 `app/*` 文件时建议优先复用这些类型。
193
196
 
194
197
  | 类型 | 使用场景 |
195
198
  | --- | --- |
@@ -300,7 +303,7 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
300
303
  - 内置 UI 组件:提供丰富的 React 组件库,详见下方"内置 UI 组件"章节。
301
304
  - API 中间件:错误处理、静态资源、body parser、项目上下文、接口签名、参数校验。
302
305
  - 前端构建:扫描框架和项目的 `frontend/**/*.entry.{ts,tsx,js,jsx}`,输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
303
- - 类型扩展:支持扩展 SchemaForm、CallCom、KoaApp。
306
+ - 类型扩展:支持扩展 SchemaForm、SchemaTable 单元格渲染组件、CallCom、KoaApp。
304
307
 
305
308
  ## 前端公共能力
306
309
 
@@ -310,21 +313,36 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
310
313
  import {
311
314
  api,
312
315
  apiFreezerStore,
316
+ addLanguageResources,
313
317
  AsyncSelect,
318
+ clearAuthToken,
314
319
  eventsInfo,
320
+ getCurrentLanguage,
321
+ getFallbackLanguage,
315
322
  FreezeState,
316
323
  get,
324
+ getSupportedLanguages,
325
+ getAuthToken,
317
326
  LanguageSwitch,
327
+ localKeyMap,
318
328
  merge,
319
329
  modeStore,
320
330
  post,
331
+ renderImportComponent,
332
+ registerFrontendI18nResources,
321
333
  request,
322
334
  schemaEventBus,
323
335
  schemaStore,
336
+ setFallbackLanguage,
337
+ setLanguage,
338
+ setResources,
339
+ setAuthToken,
324
340
  ThemeSwitch,
341
+ t,
325
342
  useApiFreezer,
326
343
  useModeStore,
327
344
  useSchemaStore,
345
+ useText,
328
346
  } from '@_tc/template-core/fe'
329
347
 
330
348
  import type {
@@ -340,6 +358,8 @@ import type {
340
358
  PageResponse,
341
359
  RequestConfig,
342
360
  ResponseConfig,
361
+ SchemaTableRenderComponent,
362
+ SchemaTableRenderComponentsMap,
343
363
  SchemaFormComponentsMap,
344
364
  SchemaFormNamespace,
345
365
  SelectProps,
@@ -352,30 +372,50 @@ import type {
352
372
  | --- | --- |
353
373
  | 应用启动 | `initApp` |
354
374
  | 内置前端组件 | `AsyncSelect`、`LanguageSwitch`、`ThemeSwitch` |
375
+ | 组件加载辅助 | `renderImportComponent` |
355
376
  | Dash 扩展类型 | `DashRoutesExtender`、`DashRoutesContext`、`DashComponentsMap`、`DashHeaderUserAreaProps`、`DashRouteGuard` |
356
- | SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer` |
377
+ | SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer`、`SchemaTableRenderComponent`、`SchemaTableRenderComponentsMap` |
357
378
  | SchemaForm 类型 | `FormFieldSchema`、`SchemaFormComponentsMap`、`SchemaFormNamespace`、`SelectProps` |
358
379
  | 请求方法 | `api`、`request`、`get`、`post`、`put`、`patch`、`del` |
359
380
  | 请求类型 | `BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError` |
381
+ | RAF 风格计时器 | `rafSetTimeout`、`rafSetInterval`、`rafClearTimeout`、`rafClearInterval`、`clearRafTimer`、`RafTimerId`、`RafTimerCallback` |
382
+ | Token 工具 | `getAuthToken`、`setAuthToken`、`clearAuthToken`、`localKeyMap` |
383
+ | 多语言工具 | `useText`、`getText`、`t`、`registerFrontendI18nResources`、`addLanguageResources`、`setLanguage`、`setFallbackLanguage`、`setResources`、`getCurrentLanguage`、`getFallbackLanguage`、`getSupportedLanguages` |
360
384
  | 请求冻结 | `apiFreezerStore`、`useApiFreezer`、`FreezeState`、`ApiFreezerRequestMatcher` |
361
385
  | 事件工具 | `eventsInfo`、`merge` |
362
386
  | 共享状态 | `modeStore`、`useModeStore`、`schemaStore`、`useSchemaStore`、`schemaEventBus` |
363
387
 
364
388
  `modeStore` 管项目模型和当前项目数据,`schemaStore` 管当前 Schema 页面的 schema/cache,`schemaEventBus` 用来在 Search、Table、CallCom 之间通信。
365
389
 
390
+ `renderImportComponent` 封装了 `React.lazy` + `Suspense`,默认会用页面骨架屏作为 fallback。`getAuthToken()`、`setAuthToken()` 和 `clearAuthToken()` 用于读写或清理本地短 token,`localKeyMap` 暴露对应的本地存储 key 常量。
391
+
366
392
  只使用请求层时,也可以从 `@_tc/template-core/fe/common/request` 导入 `api`、请求方法和请求类型;这是发布包显式子路径,不要下钻到 `frontend/src/common/request`。
367
393
 
368
394
  ### 前端多语言
369
395
 
370
- TemplateCore 前端通过 `@_tc/template-core/fe` 暴露 i18n 能力。框架内置中文、英文资源,项目可以继续追加自己的资源。
396
+ TemplateCore 前端通过 `@_tc/template-core/fe` 暴露 i18n 能力。框架内置中文、英文资源,但不会在普通自定义页面 import 前端入口时自动注册,避免非 Dashboard 页面把框架文案整包带入运行时资源。
397
+
398
+ 默认 Dashboard 入口会自动调用 `registerFrontendI18nResources()`,所以 Dashboard、Schema CRUD、内置页头、语言切换等框架页面可以直接使用框架内置文案。自定义入口如果也要复用这些框架文案,需要在渲染前手动注册:
399
+
400
+ ```ts
401
+ import { initApp, registerFrontendI18nResources } from '@_tc/template-core/fe'
402
+
403
+ initApp(App, {
404
+ beforeRender: async () => {
405
+ await registerFrontendI18nResources()
406
+ },
407
+ })
408
+ ```
409
+
410
+ 项目可以继续追加自己的资源或新增语种。
371
411
 
372
412
  **追加自定义语言资源**:
373
413
 
374
414
  ```ts
375
- import { i18nStore } from '@_tc/template-core/fe'
415
+ import { addLanguageResources } from '@_tc/template-core/fe'
376
416
 
377
- i18nStore.getState().addResources('zh-CN', {
378
- business: {
417
+ addLanguageResources('zh-CN', {
418
+ app: {
379
419
  product: {
380
420
  menu: '商品管理',
381
421
  name: '商品名称',
@@ -385,8 +425,8 @@ i18nStore.getState().addResources('zh-CN', {
385
425
  },
386
426
  })
387
427
 
388
- i18nStore.getState().addResources('en-US', {
389
- business: {
428
+ addLanguageResources('en-US', {
429
+ app: {
390
430
  product: {
391
431
  menu: 'Products',
392
432
  name: 'Product name',
@@ -397,17 +437,49 @@ i18nStore.getState().addResources('en-US', {
397
437
  })
398
438
  ```
399
439
 
440
+ **新增语种并切换**:
441
+
442
+ ```ts
443
+ import { addLanguageResources, setLanguage } from '@_tc/template-core/fe'
444
+
445
+ addLanguageResources('ja-JP', {
446
+ app: {
447
+ product: {
448
+ menu: '商品管理',
449
+ },
450
+ },
451
+ })
452
+
453
+ setLanguage('ja-JP')
454
+ ```
455
+
456
+ `addLanguageResources()` 用于追加或新增某个语种的文案,默认会深合并同语种资源;传 `{ merge: false }` 可以替换该语种资源。`setResources(resources, { merge: true })` 可批量合并多语种资源。`LanguageSwitch` 默认会把已注册语种加入选项;需要自定义展示文案时仍可传入 `options`。
457
+
458
+ React 组件 render 中使用 `useText()` 读取文案。它会订阅语言和资源变化,调用 `setLanguage()` 后组件会自动重渲染:
459
+
460
+ ```tsx
461
+ import { useText } from '@_tc/template-core/fe'
462
+
463
+ function ProductTitle() {
464
+ const text = useText()
465
+
466
+ return <h1>{text('$i18n::app.product.menu')}</h1>
467
+ }
468
+ ```
469
+
470
+ `getText()` 是普通函数,适合请求错误、日志、校验工具或事件回调等非 React 场景;它不会主动触发 React 组件重渲染。
471
+
400
472
  资源注册时不写 `$i18n::` 前缀,配置中使用时才写:
401
473
 
402
474
  ```ts
403
- const title = '$i18n::business.product.createTitle'
475
+ const title = '$i18n::app.product.createTitle'
404
476
  ```
405
477
 
406
478
  **在 model / Schema 配置中使用**:
407
479
 
408
480
  ```ts
409
481
  {
410
- name: '$i18n::business.product.menu',
482
+ name: '$i18n::app.product.menu',
411
483
  moduleType: 'schema',
412
484
  schemaConfig: {
413
485
  schema: {
@@ -415,7 +487,7 @@ const title = '$i18n::business.product.createTitle'
415
487
  properties: {
416
488
  name: {
417
489
  type: 'string',
418
- label: '$i18n::business.product.name',
490
+ label: '$i18n::app.product.name',
419
491
  minLength: 2,
420
492
  createFormOption: {
421
493
  comType: 'input',
@@ -429,7 +501,7 @@ const title = '$i18n::business.product.createTitle'
429
501
  tableConfig: {
430
502
  headerButtons: [
431
503
  {
432
- label: '$i18n::business.product.create',
504
+ label: '$i18n::app.product.create',
433
505
  eventKey: 'callComponent',
434
506
  eventOption: { comName: 'createForm' },
435
507
  },
@@ -437,7 +509,7 @@ const title = '$i18n::business.product.createTitle'
437
509
  },
438
510
  componentConfig: {
439
511
  createForm: {
440
- title: '$i18n::business.product.createTitle',
512
+ title: '$i18n::app.product.createTitle',
441
513
  saveBtnText: '$i18n::common.submit',
442
514
  },
443
515
  },
@@ -502,7 +574,7 @@ export function Toolbar() {
502
574
  }
503
575
  ```
504
576
 
505
- `ThemeSwitch` 会切换 `document.documentElement` 上的 `dark` class,并同步 `color-scheme`。默认写入 localStorage,key 是 `tc_theme`。刷新页面后会优先读取本地主题;没有本地主题时,读取当前根节点是否已有 `dark` class
577
+ `ThemeSwitch` 会切换 `document.documentElement` 上的 `dark` class,并同步 `color-scheme`。默认写入 localStorage,key 是 `tc_theme`。刷新页面后会优先读取本地主题;没有本地主题时,读取当前根节点是否已有 `dark` class。默认 Dashboard 会在渲染前调用 `initThemeMode()`,让已保存主题尽早生效。
506
578
 
507
579
  常用参数:
508
580
 
@@ -514,6 +586,21 @@ export function Toolbar() {
514
586
  | `persist` | 是否写入 localStorage,默认 `true`。 |
515
587
  | `storageKey` | 自定义本地存储 key,默认 `tc_theme`。 |
516
588
 
589
+ 如需在自定义入口或组件外手动初始化/切换主题,可以从 `@_tc/template-core/fe` 导入主题工具:
590
+
591
+ ```ts
592
+ import { applyThemeMode, getCurrentThemeMode, initThemeMode, themeSwitchStorageKey } from '@_tc/template-core/fe'
593
+
594
+ initThemeMode()
595
+ applyThemeMode('dark', true)
596
+ ```
597
+
598
+ RAF 风格计时器由 `@tc/common/rafTimer` 提供,浏览器优先使用 `requestAnimationFrame`,缺少 RAF 时自动降级到 `setTimeout`。
599
+
600
+ `@_tc/template-core/fe/rc` 和 `@_tc/template-core/fe/rc/hooks` 也会随发布包提供对应 UI 与 hooks 入口;hooks 汇总入口包含 `useBreadcrumb`、`useExecuteOnce`、`useInit`、`useLanguage`、`usePagination`、`useRefState`、`useWatch`。
601
+
602
+ `useRefState` 支持可选的 `delayTiming` 参数,传入大于 0 的值时会延迟 state 提交,并复用 `@tc/common/rafTimer` 的浏览器优先、Node/SSR 自动降级计时器实现。
603
+
517
604
  ### 前端请求封装详解
518
605
 
519
606
  框架内置的请求封装基于 `@tc/common/http`,底层使用原生 `fetch` API,实现了类似 Axios 的接口和拦截器机制,提供了签名、鉴权、错误处理等能力。
@@ -523,6 +610,7 @@ export function Toolbar() {
523
610
  - `timeout`:15000ms(15秒)
524
611
  - `credentials`:`'include'`,支持跨域携带 cookie
525
612
  - `window._signKey`:由服务端页面模板从 `app.config.signKey` 注入
613
+ - 默认会先设置 `Content-Type: application/json`;如果是上传文件、`FormData` 或其他内容类型,请在请求配置里显式覆盖
526
614
 
527
615
  **请求拦截器**:
528
616
 
@@ -879,7 +967,7 @@ const unsafeUsers = app.extends.db.queryDB(
879
967
  )
880
968
  ```
881
969
 
882
- 业务项目可以用自己的 `app/extends/db.ts` 覆盖默认实现。建议保留同一组方法名,这样 controller/service 调用方不用调整。
970
+ 项目可以用自己的 `app/extends/db.ts` 覆盖默认实现。建议保留同一组方法名,这样 controller/service 调用方不用调整。
883
971
 
884
972
  ```ts
885
973
  // app/extends/db.ts
@@ -995,7 +1083,7 @@ export default (app: KoaApp, router: Router) => {
995
1083
  - 每个 `app/router/*.ts` 文件都会获得独立的 `koa-router` 实例。
996
1084
  - 可以通过 `router.level = number` 控制挂载顺序,数值越小越早挂载。
997
1085
  - 默认 `level` 是 `0`,框架兜底 router 是 `99`。
998
- - 通配、兜底、重定向类路由建议设置较大的 `level`,避免抢先匹配业务 API。
1086
+ - 通配、兜底、重定向类路由建议设置较大的 `level`,避免抢先匹配项目 API。
999
1087
 
1000
1088
  ```ts
1001
1089
  import type { KoaApp, Router } from '@_tc/template-core'
@@ -1284,7 +1372,7 @@ DELETE {api} -> 删除
1284
1372
 
1285
1373
  ### 服务端兜底路由守卫
1286
1374
 
1287
- 业务项目可以创建 `app/router-guard.ts` 或 `app/router-guard.js`。它只在所有正常 `app/router/*` 路由都没有命中时执行。
1375
+ 项目可以创建 `app/router-guard.ts` 或 `app/router-guard.js`。它只在所有正常 `app/router/*` 路由都没有命中时执行。
1288
1376
 
1289
1377
  ```ts
1290
1378
  import type { Ctx, KoaApp } from '@_tc/template-core'
@@ -1309,7 +1397,7 @@ export default (_app: KoaApp) => {
1309
1397
 
1310
1398
  ### 扩展 Dashboard 顶部用户区域
1311
1399
 
1312
- 业务项目可以创建 `frontend/extended/dash/components.tsx`,通过组件映射填充内置 Dashboard 页头右侧区域。
1400
+ 项目可以创建 `frontend/extended/dash/components.tsx`,通过组件映射填充内置 Dashboard 页头右侧区域。
1313
1401
 
1314
1402
  ```tsx
1315
1403
  // frontend/extended/dash/components.tsx
@@ -1330,7 +1418,7 @@ export default components
1330
1418
 
1331
1419
  ### 扩展 Dashboard 登录守卫
1332
1420
 
1333
- 业务项目可以创建 `frontend/extended/dash/routeGuard.ts`,用于在 Dashboard 内置 `homePage` / 首菜单重定向前做登录判断。
1421
+ 项目可以创建 `frontend/extended/dash/routeGuard.ts`,用于在 Dashboard 内置 `homePage` / 首菜单重定向前做登录判断。
1334
1422
 
1335
1423
  ```ts
1336
1424
  // frontend/extended/dash/routeGuard.ts
@@ -1346,9 +1434,9 @@ export default dashRouteGuard
1346
1434
  返回值规则:
1347
1435
 
1348
1436
  - 返回 `string`:框架使用 `window.location.href` 跳转,登录页不需要在 Dash 路由下。
1349
- - 返回非 `string`:中断 Dashboard 内置重定向,业务方可自行跳转或处理提示。
1437
+ - 返回非 `string`:中断 Dashboard 内置重定向,使用方可自行跳转或处理提示。
1350
1438
  - `DashRouteGuardResult` 是 `string | undefined`;`undefined`(包括已登录分支的隐式返回)也会打断 Dashboard 内置重定向。
1351
- - 没有业务 `routeGuard` 文件时,框架使用兜底空对象,不影响默认 Dashboard 重定向。
1439
+ - 没有自定义 `routeGuard` 文件时,框架使用兜底空对象,不影响默认 Dashboard 重定向。
1352
1440
 
1353
1441
  ### 扩展 SchemaForm 字段组件
1354
1442
 
@@ -1518,6 +1606,90 @@ remark: {
1518
1606
  }
1519
1607
  ```
1520
1608
 
1609
+ ### 扩展 SchemaTable 单元格渲染组件
1610
+
1611
+ SchemaPage 表格列支持通过 `tableOption.renderComponent` 使用内置或自定义注册的渲染组件。内置组件:
1612
+
1613
+ - `PreviewImage`:把当前单元格值渲染成图片预览;值是数组时直接作为图片列表,值是单个字符串时自动转成单图数组。
1614
+
1615
+ 直接使用内置组件:
1616
+
1617
+ ```ts
1618
+ cover: {
1619
+ type: 'string',
1620
+ label: '封面',
1621
+ tableOption: {
1622
+ renderComponent: 'PreviewImage',
1623
+ renderComponentProps: {
1624
+ width: 48,
1625
+ height: 48,
1626
+ },
1627
+ },
1628
+ }
1629
+ ```
1630
+
1631
+ 自定义渲染组件时,先声明 props 类型:
1632
+
1633
+ ```ts
1634
+ // typing/template-core.d.ts
1635
+ import '@_tc/template-core/model'
1636
+
1637
+ declare module '@_tc/template-core/model' {
1638
+ export namespace SchemaTableNamespace {
1639
+ interface RenderComponentPropsMap {
1640
+ PriceCell: {
1641
+ value?: unknown
1642
+ record?: Record<string, unknown>
1643
+ rowIndex?: number
1644
+ fieldKey?: string
1645
+ currency?: string
1646
+ }
1647
+ }
1648
+ }
1649
+ }
1650
+ ```
1651
+
1652
+ 注册运行时组件:
1653
+
1654
+ ```ts
1655
+ // frontend/extended/SchemaPage/SchemaTable/data.ts
1656
+ import { lazy } from 'react'
1657
+ import type { SchemaTableRenderComponentsMap } from '@_tc/template-core/fe'
1658
+
1659
+ const componentsMap = {
1660
+ PriceCell: lazy(() => import('../../components/PriceCell')),
1661
+ } satisfies SchemaTableRenderComponentsMap
1662
+
1663
+ export default componentsMap
1664
+ ```
1665
+
1666
+ 组件会收到 `value`、`record`、`rowIndex`、`fieldKey`,以及 `renderComponentProps` 中的自定义参数:
1667
+
1668
+ ```tsx
1669
+ // frontend/components/PriceCell.tsx
1670
+ export default function PriceCell(props: {
1671
+ value?: unknown
1672
+ currency?: string
1673
+ }) {
1674
+ return <span>{props.currency ?? '¥'}{Number(props.value ?? 0).toFixed(2)}</span>
1675
+ }
1676
+ ```
1677
+
1678
+ model 中使用:
1679
+
1680
+ ```ts
1681
+ price: {
1682
+ type: 'number',
1683
+ label: '价格',
1684
+ tableOption: {
1685
+ renderComponent: 'PriceCell',
1686
+ renderComponentProps: {
1687
+ currency: '¥',
1688
+ },
1689
+ },
1690
+ }
1691
+ ```
1692
+
1521
1693
  ## 如何配置类型扩展
1522
1694
 
1523
1695
  ### tsconfig
@@ -1617,6 +1789,22 @@ declare module '@_tc/template-core/model' {
1617
1789
  - `OptionMap` 对应字段上的 `xxxOption`。
1618
1790
  - 运行时组件注册在 `frontend/extended/SchemaPage/CallCom/data.ts`。
1619
1791
 
1792
+ ### SchemaTable 渲染组件类型扩展
1793
+
1794
+ 扩展目标:
1795
+
1796
+ ```ts
1797
+ declare module '@_tc/template-core/model' {
1798
+ export namespace SchemaTableNamespace {
1799
+ interface RenderComponentPropsMap {}
1800
+ }
1801
+ }
1802
+ ```
1803
+
1804
+ - `RenderComponentPropsMap` 的 key 对应 `tableOption.renderComponent`。
1805
+ - 运行时组件注册在 `frontend/extended/SchemaPage/SchemaTable/data.ts`。
1806
+ - 组件运行时会自动收到 `value`、`record`、`rowIndex`、`fieldKey`;`renderComponentProps` 只配置自定义参数。
1807
+
1620
1808
  ### KoaApp 类型扩展
1621
1809
 
1622
1810
  使用方推荐增强根包 `@_tc/template-core`:
@@ -1970,6 +2158,6 @@ await buildBE({
1970
2158
  - `model` 数组合并依赖稳定 `key`。
1971
2159
  - Dashboard 默认需要 URL 带 `?projk=项目key`。
1972
2160
  - Dashboard 登录守卫放在 `frontend/extended/dash/routeGuard.ts`;登录页通常不在 Dash 路由下,返回登录页 URL 即可。
1973
- - 服务端兜底守卫放在业务 `app/router-guard.ts|js`,不是 `app/business` 子目录。
2161
+ - 服务端兜底守卫放在项目根目录的 `app/router-guard.ts|js`。
1974
2162
  - 前端入口必须命名为 `.entry.tsx`、`.entry.ts`、`.entry.jsx` 或 `.entry.js`。
1975
2163
  - 入口同目录的 `.html` 只能作为插槽文件使用,不能写完整 HTML 文档;页面外壳始终由 `app/view/entry.tpl` 生成。
@@ -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(),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);c||console.log(`---- etag 缓存异常 请检查服务 ----`),r.etag=c??Date.now()+``}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`);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(),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.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;
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../packages/common/log/index.js`),t=require(`./state.js`),n=require(`./dev.js`),r=require(`./prod.js`);var i=(i,a)=>{switch(t.setBuildFEOptions(a),i){case`dev`:return n.dev();case`prod`:return r.prod();default:return e.logRed(`Usage: npx tsx scripts/index.ts [dev|prod]`),Promise.resolve()}};exports.buildFE=i;
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../packages/common/log/index.js`),t=require(`./buildBE.js`),n=require(`./state.js`),r=require(`./dev.js`),i=require(`./prod.js`);var a=(t,a)=>{switch(n.setBuildFEOptions(a),t){case`dev`:return r.dev();case`prod`:return i.prod();default:return e.logRed(`Usage: npx tsx scripts/index.ts [dev|prod]`),Promise.resolve()}};exports.buildBE=t.buildBE,exports.buildFE=a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./buildBE.js`),t=require(`./buildFE.js`);exports.buildBE=e.buildBE,exports.buildFE=t.buildFE;