@_tc/template-core 0.2.0-bate.0 → 0.2.0-bate.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.skills/tc-component-usage-skills/reference/template-core-frontend.md +8 -1
- package/.skills/tc-generator/SKILL.md +3 -2
- package/.skills/tc-generator/reference/example.md +1 -1
- package/.skills/tc-generator/reference/project-template/index.js +1 -1
- package/.skills/tc-generator/reference/runtime-extensions.md +2 -2
- package/AGENT_README.md +6 -3
- package/README.md +24 -7
- package/cjs/app/controller/view.js +1 -1
- package/cjs/app/{extend → extends}/db.js +1 -1
- package/cjs/app/extends/localCacheHtmlEtag.js +1 -0
- package/cjs/app/extends/render-view.js +1 -0
- package/cjs/app/middleware.js +1 -1
- package/cjs/app/view/entry.tpl +0 -16
- package/cjs/bundler/index.js +1 -1
- package/cjs/bundler/state.js +1 -1
- package/cjs/bundler/utils.js +3 -3
- package/cjs/packages/common/index.js +1 -1
- package/cjs/packages/common/string/index.js +1 -1
- package/cjs/packages/core/index.js +1 -1
- package/cjs/packages/core/loader/controller.js +1 -1
- package/cjs/packages/core/loader/extend.js +1 -1
- package/cjs/packages/core/loader/middleware.js +1 -1
- package/cjs/packages/core/loader/router-schema.js +1 -1
- package/cjs/packages/core/loader/router.js +1 -1
- package/cjs/packages/core/loader/service.js +1 -1
- package/cjs/packages/utils/runFileFn.js +1 -1
- package/esm/app/controller/view.js +25 -15
- package/esm/app/{extend → extends}/$fetch.js +1 -1
- package/esm/app/{extend → extends}/crypto.js +1 -1
- package/esm/app/{extend → extends}/db.js +2 -2
- package/esm/app/{extend → extends}/generateErrorMessage.js +1 -1
- package/esm/app/extends/localCacheHtmlEtag.js +41 -0
- package/esm/app/{extend → extends}/logger.js +1 -1
- package/esm/app/{extend → extends}/parsingParamsOnUrl.js +1 -1
- package/esm/app/extends/render-view.js +18 -0
- package/esm/app/middleware.js +8 -12
- package/esm/app/view/entry.tpl +0 -16
- package/esm/bundler/index.js +6 -6
- package/esm/bundler/state.js +5 -1
- package/esm/bundler/utils.js +129 -104
- package/esm/packages/common/index.js +6 -6
- package/esm/packages/common/string/index.js +11 -2
- package/esm/packages/core/index.js +34 -28
- package/esm/packages/core/loader/controller.js +6 -6
- package/esm/packages/core/loader/extend.js +6 -6
- package/esm/packages/core/loader/middleware.js +6 -6
- package/esm/packages/core/loader/router-schema.js +7 -7
- package/esm/packages/core/loader/router.js +13 -13
- package/esm/packages/core/loader/service.js +6 -6
- package/esm/packages/utils/runFileFn.js +10 -10
- package/fe/packages/common/string/index.d.ts +9 -0
- package/model/packages/common/string/index.d.ts +9 -0
- package/package.json +1 -1
- package/types/app/extends/localCacheHtmlEtag.d.ts +10 -0
- package/types/app/{extend → extends}/render-view.d.ts +1 -1
- package/types/app/service/base.d.ts +1 -1
- package/types/app/service/project.d.ts +1 -1
- package/types/app/type.d.ts +2 -1
- package/types/app/typings.d.ts +10 -8
- package/types/bundler/state.d.ts +4 -0
- package/types/bundler/utils.d.ts +5 -0
- package/types/index.d.ts +3 -3
- package/types/packages/common/string/index.d.ts +16 -0
- package/types/packages/core/loader/extend.d.ts +1 -1
- package/types/packages/core/types.d.ts +4 -0
- package/cjs/app/extend/render-view.js +0 -1
- package/esm/app/extend/render-view.js +0 -25
- /package/cjs/app/{extend → extends}/$fetch.js +0 -0
- /package/cjs/app/{extend → extends}/crypto.js +0 -0
- /package/cjs/app/{extend → extends}/generateErrorMessage.js +0 -0
- /package/cjs/app/{extend → extends}/logger.js +0 -0
- /package/cjs/app/{extend → extends}/parsingParamsOnUrl.js +0 -0
- /package/types/app/{extend → extends}/$fetch.d.ts +0 -0
- /package/types/app/{extend → extends}/crypto.d.ts +0 -0
- /package/types/app/{extend → extends}/db.d.ts +0 -0
- /package/types/app/{extend → extends}/generateErrorMessage.d.ts +0 -0
- /package/types/app/{extend → extends}/logger.d.ts +0 -0
- /package/types/app/{extend → extends}/parsingParamsOnUrl.d.ts +0 -0
|
@@ -19,7 +19,7 @@ Inside this repository, use `@tc/ui-react` for the raw UI workspace package. In
|
|
|
19
19
|
<LanguageSwitch />
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Default languages are `zh-CN` and `en-US`. Pass `options` to replace the list. `onChange(language)` receives the selected language string. The component calls `i18nStore.getState().setLanguage()`, so it uses the same `tc_language` persistence as the UI i18n runtime.
|
|
22
|
+
Default languages are `zh-CN` and `en-US`. Pass `options` to replace the list. The current UI is a button-triggered dropdown; `option.label` can be a ReactNode and `buttonClassName` customizes the trigger. `onChange(language)` receives the selected language string. The component calls `i18nStore.getState().setLanguage()`, so it uses the same `tc_language` persistence as the UI i18n runtime.
|
|
23
23
|
|
|
24
24
|
Useful props:
|
|
25
25
|
|
|
@@ -31,6 +31,13 @@ interface LanguageSwitchProps {
|
|
|
31
31
|
defaultValue?: LanguageSwitchValue
|
|
32
32
|
options?: Array<{ label: ReactNode; value: LanguageSwitchValue; searchText?: string }>
|
|
33
33
|
onChange?: (language: LanguageSwitchValue) => void
|
|
34
|
+
disabled?: boolean
|
|
35
|
+
loading?: boolean
|
|
36
|
+
placeholder?: string
|
|
37
|
+
clearable?: boolean
|
|
38
|
+
searchable?: boolean
|
|
39
|
+
buttonClassName?: string
|
|
40
|
+
getPopupContainer?: (() => HTMLElement) | 'parent'
|
|
34
41
|
}
|
|
35
42
|
```
|
|
36
43
|
|
|
@@ -28,10 +28,11 @@ Use this skill to generate or update TemplateCore business code.
|
|
|
28
28
|
## TemplateCore Conventions
|
|
29
29
|
|
|
30
30
|
- Start the app with `serverStart({ name, baseDir })` from `@_tc/template-core`.
|
|
31
|
-
- Start the built-in frontend with `await buildFE("dev")` from `@_tc/template-core/bundler` when the user needs the admin UI. The current API returns `Promise<void>`; in dev mode it performs the initial build, then watches the business `frontend/` directory.
|
|
31
|
+
- Start the built-in frontend with `await buildFE("dev")` from `@_tc/template-core/bundler` when the user needs the admin UI. The current API returns `Promise<void>`; in dev mode it performs the initial build, then watches the business `frontend/` directory. Use `buildFE("prod", { output: "run", minifyHtml: true })` when the generated project should emit its own `app/public/dist` templates and compact final `.tpl` output.
|
|
32
|
+
- `buildFE()` writes `FEBuildKey` into the output directory; the server uses it to invalidate local HTML ETag cache after frontend rebuilds.
|
|
32
33
|
- If `buildFE("dev")` is used in a standalone project, include the TemplateCore peer dependencies or use the package manager's peer dependency auto-install behavior.
|
|
33
34
|
- Business code lives under the user's `baseDir`, not inside TemplateCore framework folders.
|
|
34
|
-
- The framework provides `app.extends.db` as a default SQLite-backed KV/SQL helper. Use it for small framework/business settings; override `app/
|
|
35
|
+
- The framework provides `app.extends.db` as a default SQLite-backed KV/SQL helper. Use it for small framework/business settings; override `app/extends/db.js` only when the project needs a custom storage implementation.
|
|
35
36
|
- Backend loaders map filenames to camelCase fields:
|
|
36
37
|
- `app/controller/product.js` -> `app.controller.product`
|
|
37
38
|
- `app/service/user-profile.js` -> `app.service.userProfile`
|
|
@@ -74,7 +74,7 @@ module.exports = (app) => {
|
|
|
74
74
|
};
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
If the runtime does not support the built-in SQLite module or the project needs another store, generate `app/
|
|
77
|
+
If the runtime does not support the built-in SQLite module or the project needs another store, generate `app/extends/db.js` or `app/extends/db.ts` and preserve the same method names so existing controllers keep working.
|
|
78
78
|
|
|
79
79
|
## Default Crypto
|
|
80
80
|
|
|
@@ -257,7 +257,7 @@ import { Button, DataTable, TableSearch } from '@_tc/template-core/fe/rc'
|
|
|
257
257
|
|
|
258
258
|
Inside this source repository, use `@tc/ui-react` for the raw UI workspace package. The `@_tc/template-core/fe/rc` path is for published TemplateCore consumers.
|
|
259
259
|
|
|
260
|
-
`LanguageSwitch` updates the shared i18n language and persists through `tc_language
|
|
260
|
+
`LanguageSwitch` is a button-triggered dropdown that updates the shared i18n language and persists through `tc_language`; use `buttonClassName` when the trigger needs custom sizing or styling. `ThemeSwitch` toggles the root `dark` class and persists through `tc_theme`. `AsyncSelect` loads options from a `fetchConfig` endpoint returning `{ label, value, searchText? }[]`.
|
|
261
261
|
|
|
262
262
|
## SchemaForm Extensions
|
|
263
263
|
|
package/AGENT_README.md
CHANGED
|
@@ -9,7 +9,8 @@ TemplateCore 是一个 TypeScript + Koa + React 的后台框架包。它提供
|
|
|
9
9
|
- Koa 服务启动和约定式后端加载。
|
|
10
10
|
- 内置 Dashboard、Schema CRUD 页面和 React UI 组件库。
|
|
11
11
|
- `model/` 配置驱动的菜单、项目和 CRUD 页面。
|
|
12
|
-
- 前端构建 `buildFE()`
|
|
12
|
+
- 前端构建 `buildFE()` 输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
|
|
13
|
+
- 消费方 Node/backend 构建 `buildBE()`。
|
|
13
14
|
- 类型扩展机制,用于扩展 SchemaForm 字段、CallCom 组件和 Koa app 类型。
|
|
14
15
|
|
|
15
16
|
优先使用公开入口,不要从包内部源码路径导入。下面这些入口以 npm 发布产物为准;源码仓库根 `package.json` 的 `exports` 会在构建发布包时生成到 `dist/package.json`。
|
|
@@ -104,7 +105,7 @@ app/middleware.(js|ts) -> 全局中间件编排,按 frame -> busines
|
|
|
104
105
|
app/router/**/*.(js|ts) -> Koa router
|
|
105
106
|
app/router-guard.(js|ts) -> 兜底路由守卫
|
|
106
107
|
app/router-schema/**/*.(js|ts) -> app.routerSchema
|
|
107
|
-
app/
|
|
108
|
+
app/extends/*.(js|ts) -> app.extends
|
|
108
109
|
config/config.default.(js|ts) -> app.config
|
|
109
110
|
config/config.{env}.(js|ts) -> app.config
|
|
110
111
|
model/**/*.(js|ts) -> 内置 project service 读取的项目模型配置
|
|
@@ -211,7 +212,7 @@ export default (_app: KoaApp) => {
|
|
|
211
212
|
|
|
212
213
|
- `app.extends.$fetch`:Node 侧 axios 风格 fetch 实例。
|
|
213
214
|
- `app.extends.crypto`:Node 侧加密辅助方法,支持 base64url 编解码、HMAC 签名、签名 payload 和常量时间比较。
|
|
214
|
-
- `app.extends.db`:默认 SQLite 数据存储,可用业务 `app/
|
|
215
|
+
- `app.extends.db`:默认 SQLite 数据存储,可用业务 `app/extends/db.ts` 覆盖。
|
|
215
216
|
|
|
216
217
|
## 4. model 配置
|
|
217
218
|
|
|
@@ -480,9 +481,11 @@ import { buildFE } from '@_tc/template-core/bundler'
|
|
|
480
481
|
|
|
481
482
|
await buildFE('dev')
|
|
482
483
|
await buildFE('prod', { output: 'run' })
|
|
484
|
+
await buildFE('prod', { output: 'run', minifyHtml: true })
|
|
483
485
|
```
|
|
484
486
|
|
|
485
487
|
`buildFE('dev')` 是构建一次并监听业务 `frontend/` 变化后重建,不是 Vite dev server/HMR。
|
|
488
|
+
`minifyHtml: true` 会压缩最终 `.tpl` 模板输出;构建完成后会写入 `FEBuildKey`,服务端渲染 HTML 时用它判断本地 HTML ETag 缓存是否需要清空。
|
|
486
489
|
|
|
487
490
|
Node/backend 构建:
|
|
488
491
|
|
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ export default {
|
|
|
118
118
|
|
|
119
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
|
|
|
123
123
|
### buildFE 参数说明
|
|
124
124
|
|
|
@@ -135,6 +135,10 @@ buildFE(mode: 'dev' | 'prod', options?: BuildFEOptions)
|
|
|
135
135
|
- `'run'`:输出到项目根目录的 `app/public/dist`,适合 TypeScript 编译后的项目
|
|
136
136
|
- `() => string`:自定义函数,返回输出目录;建议返回绝对路径
|
|
137
137
|
|
|
138
|
+
**options.minifyHtml**:是否压缩 Vite 输出的 HTML 内容后再写出最终 `.tpl` / `.html` 文件,默认 `false`
|
|
139
|
+
|
|
140
|
+
构建完成后会在输出目录写入 `FEBuildKey`。服务端渲染 HTML 时会读取 `public/dist/FEBuildKey`,构建 key 变化后自动清空本地 HTML ETag 缓存。
|
|
141
|
+
|
|
138
142
|
示例:
|
|
139
143
|
|
|
140
144
|
```ts
|
|
@@ -148,6 +152,9 @@ await buildFE('prod', { output: 'run' })
|
|
|
148
152
|
await buildFE('prod', {
|
|
149
153
|
output: () => join(__dirname, 'dist/public')
|
|
150
154
|
})
|
|
155
|
+
|
|
156
|
+
// 压缩最终模板输出
|
|
157
|
+
await buildFE('prod', { minifyHtml: true })
|
|
151
158
|
```
|
|
152
159
|
|
|
153
160
|
配置文件:
|
|
@@ -280,7 +287,7 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
|
|
|
280
287
|
## 内置功能
|
|
281
288
|
|
|
282
289
|
- Koa 服务启动:`serverStart(options)`。
|
|
283
|
-
- 约定式加载:自动加载 `config`、`
|
|
290
|
+
- 约定式加载:自动加载 `config`、`extends`、`router-schema`、`service`、`controller`、`middlewares`、根级 `middleware`、`router`。
|
|
284
291
|
- 双层 app:框架内置 `app/` 和项目 `app/` 一起加载。
|
|
285
292
|
- 默认项目接口:
|
|
286
293
|
- `GET /api/project/model_list`
|
|
@@ -292,7 +299,7 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
|
|
|
292
299
|
- Schema CRUD:根据 `model` 中的 `schemaConfig` 生成搜索、表格、新增、编辑、详情。
|
|
293
300
|
- 内置 UI 组件:提供丰富的 React 组件库,详见下方"内置 UI 组件"章节。
|
|
294
301
|
- API 中间件:错误处理、静态资源、body parser、项目上下文、接口签名、参数校验。
|
|
295
|
-
- 前端构建:扫描框架和项目的 `frontend/**/*.entry.{ts,tsx,js,jsx}`,输出服务端可渲染的 `.entry.tpl`
|
|
302
|
+
- 前端构建:扫描框架和项目的 `frontend/**/*.entry.{ts,tsx,js,jsx}`,输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
|
|
296
303
|
- 类型扩展:支持扩展 SchemaForm、CallCom、KoaApp。
|
|
297
304
|
|
|
298
305
|
## 前端公共能力
|
|
@@ -469,7 +476,7 @@ export function Toolbar() {
|
|
|
469
476
|
}
|
|
470
477
|
```
|
|
471
478
|
|
|
472
|
-
`LanguageSwitch` 默认提供 `zh-CN` 和 `en-US`,也支持传入 `options`
|
|
479
|
+
`LanguageSwitch` 默认提供 `zh-CN` 和 `en-US`,也支持传入 `options` 覆盖语言列表。组件当前是按钮 + 下拉菜单形态,`option.label` 支持 ReactNode,`buttonClassName` 可自定义触发按钮样式。组件内部会调用 `i18nStore.getState().setLanguage()`,因此会沿用 `tc_language` 的持久化行为。
|
|
473
480
|
|
|
474
481
|
**AJV 校验文案**:
|
|
475
482
|
|
|
@@ -738,7 +745,7 @@ app/middlewares/**/*.(js|ts) -> app.middlewares
|
|
|
738
745
|
app/middleware.(js|ts) -> 全局中间件编排,按框架 -> 项目顺序执行
|
|
739
746
|
app/router/**/*.(js|ts) -> Koa router
|
|
740
747
|
app/router-schema/**/*.(js|ts) -> app.routerSchema
|
|
741
|
-
app/
|
|
748
|
+
app/extends/*.(js|ts) -> app.extends
|
|
742
749
|
config/config.default.(js|ts) -> app.config
|
|
743
750
|
config/config.{env}.(js|ts) -> app.config
|
|
744
751
|
model/**/*.(js|ts) -> 内置 project service 按需读取的项目模型配置
|
|
@@ -872,10 +879,10 @@ const unsafeUsers = app.extends.db.queryDB(
|
|
|
872
879
|
)
|
|
873
880
|
```
|
|
874
881
|
|
|
875
|
-
业务项目可以用自己的 `app/
|
|
882
|
+
业务项目可以用自己的 `app/extends/db.ts` 覆盖默认实现。建议保留同一组方法名,这样 controller/service 调用方不用调整。
|
|
876
883
|
|
|
877
884
|
```ts
|
|
878
|
-
// app/
|
|
885
|
+
// app/extends/db.ts
|
|
879
886
|
import type { DB, DBFactory } from '@_tc/template-core'
|
|
880
887
|
|
|
881
888
|
interface DataOptions {
|
|
@@ -1792,6 +1799,16 @@ await buildFE('prod', {
|
|
|
1792
1799
|
})
|
|
1793
1800
|
```
|
|
1794
1801
|
|
|
1802
|
+
也可以压缩最终模板输出:
|
|
1803
|
+
|
|
1804
|
+
```ts
|
|
1805
|
+
await buildFE('prod', {
|
|
1806
|
+
minifyHtml: true,
|
|
1807
|
+
})
|
|
1808
|
+
```
|
|
1809
|
+
|
|
1810
|
+
构建完成后会在输出目录写入 `FEBuildKey`,服务端渲染 HTML 时会用它判断本地 HTML ETag 缓存是否需要清空。
|
|
1811
|
+
|
|
1795
1812
|
## Node/backend 构建 buildBE
|
|
1796
1813
|
|
|
1797
1814
|
消费方 Node/backend 侧构建使用 `buildBE()`。它复用发布包内的 `scripts/vite-build/buildEntries`,只是提供消费方默认配置。
|
|
@@ -1 +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;
|
|
@@ -6,7 +6,7 @@ require(`../../_virtual/_rolldown/runtime.js`);let e=require(`node:fs`),t=requir
|
|
|
6
6
|
FROM tc_framework_data
|
|
7
7
|
WHERE namespace = ?
|
|
8
8
|
ORDER BY updated_at DESC, data_key ASC
|
|
9
|
-
LIMIT ? OFFSET ?`,[d(e?.namespace),t,n]).map(e=>_(e))},countDBData:e=>{let t=y.getDBFirst(`SELECT COUNT(1) AS count_value FROM tc_framework_data WHERE namespace = ?`,[d(e?.namespace)]);return Number(t?.count_value??0)},clearDBData:e=>y.runDB(`DELETE FROM tc_framework_data WHERE namespace = ?`,[d(e?.namespace)]).changes,closeDB:()=>{c||=(i?.close(),!0)}};return y}function a(e){let t=`node:sqlite`,n;try{n=require(t)}catch(e){throw Error(`[db] 默认数据库依赖 Node.js 内置 ${t},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/
|
|
9
|
+
LIMIT ? OFFSET ?`,[d(e?.namespace),t,n]).map(e=>_(e))},countDBData:e=>{let t=y.getDBFirst(`SELECT COUNT(1) AS count_value FROM tc_framework_data WHERE namespace = ?`,[d(e?.namespace)]);return Number(t?.count_value??0)},clearDBData:e=>y.runDB(`DELETE FROM tc_framework_data WHERE namespace = ?`,[d(e?.namespace)]).changes,closeDB:()=>{c||=(i?.close(),!0)}};return y}function a(e){let t=`node:sqlite`,n;try{n=require(t)}catch(e){throw Error(`[db] 默认数据库依赖 Node.js 内置 ${t},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。${y(e)}`)}if(!n.DatabaseSync)throw Error(`[db] ${t} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。`);return new n.DatabaseSync(e)}function o(e){e.exec(`
|
|
10
10
|
CREATE TABLE IF NOT EXISTS tc_framework_data (
|
|
11
11
|
namespace TEXT NOT NULL,
|
|
12
12
|
data_key TEXT NOT NULL,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require(`../../_virtual/_rolldown/runtime.js`);let t=require(`fs`),n=require(`path`);n=e.__toESM(n);var r=`./dist/FEBuildKey`,i={etags:{},FEBuildKey:null},a=(e=>{let a=(e,t)=>{i.etags[e]=t},o=e=>!!s(e),s=e=>i.etags[e]||null,c=e=>{i.FEBuildKey=e},l=()=>i.FEBuildKey||null,u=()=>{for(let i of e.publicsPath){let e=n.default.resolve(i,r);if((0,t.existsSync)(e))return e}},d=()=>{let e,n=u();return n&&(e=(0,t.readFileSync)(n,`utf-8`)),e===l()};return{keepFreshFEBuildKey:()=>{if(!d()){let e=u();if(e){let n=(0,t.readFileSync)(e,`utf-8`);if(n){c(n),i.etags={};return}}console.log(`--- 没找到前端构建key文件 ---`),console.log(`--- filePath --- -> `,e)}},hasEtag:o,getEtag:s,setEtag:a}});module.exports=a;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require(`../../_virtual/_rolldown/runtime.js`);let t=require(`node:path`);t=e.__toESM(t);let n=require(`nunjucks`);n=e.__toESM(n);var r=e=>{let r=e.publicsPath.map(e=>t.default.resolve(e,`./dist`));console.log(r);let i=n.default.configure(r,{autoescape:!0,throwOnUndefined:!1,trimBlocks:!1,lstripBlocks:!1,noCache:e.envs.get()===`local`,...typeof e.config.nunjucks==`object`?e.config.nunjucks:{}});return e.extends.nunjucksEnv=i,(e,t,n)=>t.body=i.render(e,Object.assign({},t.state,n))};module.exports=r;
|
package/cjs/app/middleware.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../_virtual/_rolldown/runtime.js`)
|
|
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:365*24*60*60*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;
|
package/cjs/app/view/entry.tpl
CHANGED
|
@@ -3,22 +3,6 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<script>
|
|
7
|
-
;(() => {
|
|
8
|
-
const root = document.documentElement
|
|
9
|
-
let theme = root.classList.contains('dark') ? 'dark' : 'light'
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
const storedTheme = window.localStorage.getItem('tc_theme')
|
|
13
|
-
if (storedTheme === 'light' || storedTheme === 'dark') {
|
|
14
|
-
theme = storedTheme
|
|
15
|
-
}
|
|
16
|
-
} catch (_error) {}
|
|
17
|
-
|
|
18
|
-
root.classList.toggle('dark', theme === 'dark')
|
|
19
|
-
root.style.colorScheme = theme
|
|
20
|
-
})()
|
|
21
|
-
</script>
|
|
22
6
|
<link rel="icon" type="image/x-icon" href="/static/logo.png" />
|
|
23
7
|
<title>{{ name }}</title>
|
|
24
8
|
<!-- TC_HEAD_SLOT -->
|
package/cjs/bundler/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(
|
|
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;
|
package/cjs/bundler/state.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={options:{output:`frame
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={options:{output:`frame`,minifyHtml:!1}};function t(t){e.options={output:`frame`,minifyHtml:!1,...t}}exports.buildFESharedState=e,exports.setBuildFEOptions=t;
|
package/cjs/bundler/utils.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../_virtual/_rolldown/runtime.js`),t=require(`../packages/
|
|
2
|
-
`))}return
|
|
3
|
-
`))},
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../_virtual/_rolldown/runtime.js`),t=require(`../packages/common/log/index.js`),n=require(`../packages/utils/path.js`);require(`../packages/utils/index.js`);const r=require(`./state.js`);let i=require(`fs`),a=require(`path`);a=e.__toESM(a);let o=require(`glob`);o=e.__toESM(o);let s=require(`vite`),c=require(`@tailwindcss/vite`);c=e.__toESM(c);let l=require(`module`),u=require(`url`);var d=typeof __filename==`string`?__filename:(0,u.fileURLToPath)({}.url),f=a.default.dirname(d),p=process.cwd(),m=(0,l.createRequire)(d),h=a.default.resolve(f,`../../`),g=a.default.resolve(f,`../`),_=a.default.resolve(h,`./fe/frontend`),v=a.default.resolve(p,`.`),y=a.default.resolve(v,`./frontend`),b=e=>a.default.dirname(m.resolve(`${e}/package.json`)),x=a.default.join(v,`.tc-entry-html`),S=`<!-- {{InsertScript}} -->`,C={head:`<!-- TC_HEAD_SLOT -->`,bodyBeforeRoot:`<!-- TC_BODY_BEFORE_ROOT_SLOT -->`,bodyAfterRoot:`<!-- TC_BODY_AFTER_ROOT_SLOT -->`},w=[`head`,`body-before-root`,`body-after-root`],T=()=>({head:``,"body-before-root":``,"body-after-root":``}),E=e=>e.trim().replace(/<!--(?!\s*(?:tc-slot:|\/tc-slot:))[\s\S]*?-->/g,``).replace(/>\s+</g,`><`),D=e=>{let t=[],n=e.replace(/<(script|style|textarea|pre)\b[\s\S]*?<\/\1>/gi,e=>{let n=`__TC_HTML_PRESERVED_${t.length}__`;return t.push(e),n}).replace(/<!--(?!\s*(?:tc-slot:|\/tc-slot:|\{\{InsertScript\}\}|TC_))[\s\S]*?-->/g,``).replace(/>\s+</g,`><`).trim();return t.reduce((e,t,n)=>e.replace(`__TC_HTML_PRESERVED_${n}__`,t),n)},O=e=>e.split(a.default.sep).join(`/`),k=e=>{let t=O(e);return t.startsWith(`.`)||t.startsWith(`/`)?t:`./${t}`},A=e=>/<html[\s>]/i.test(e)&&e.includes(`window['_basePath']`)&&/<div\s+id=["']root["']\s*><\/div>/i.test(e),j=e=>{let n=T(),r=(0,i.readFileSync)(e,`utf-8`),a=/<!--\s*tc-slot:([\w-]+)\s*-->([\s\S]*?)<!--\s*\/tc-slot:\1\s*-->/g,o=!1,s=r;if(r.replace(a,(t,r,i)=>{if(o=!0,!w.includes(r))throw Error(`Invalid html slot "${r}" in ${e}. Allowed slots: ${w.join(`, `)}.`);return n[r]+=i.trim()?`${i}\n`:``,s=s.replace(t,``),t}),s.trim()){if(A(r))return t.logYellow(`ignored legacy generated entry html: ${e}`),T();throw Error([`Invalid custom entry html: ${e}.`,`Custom entry html can only contain tc-slot blocks, for example:`,`<!-- tc-slot:head -->`,`<meta name="description" content="..." />`,`<!-- /tc-slot:head -->`].join(`
|
|
2
|
+
`))}return o&&t.logYellow(`using custom entry html slots: ${e}`),n},M=(e,t)=>{let r=a.default.basename(e),s=[a.default.join(e,`${t}.html`),a.default.join(e,`${r}.html`)].find(e=>(0,i.existsSync)(e));if(s)return s;if(o.sync(n.resolve(e,`*.html`)).length)throw Error([`Entry html filename is not supported in ${e}.`,`Use ${t}.html or ${r}.html as a tc-slot file.`].join(`
|
|
3
|
+
`))},N=(e,t)=>e.replace(C.head,E(t.head)).replace(C.bodyBeforeRoot,E(t[`body-before-root`])).replace(C.bodyAfterRoot,E(t[`body-after-root`])),P=(e=new Date)=>{let t=(e,t=2)=>e.toString().padStart(t,`0`);return[e.getFullYear(),t(e.getMonth()+1),t(e.getDate()),t(e.getHours())].join(`/`)+`:${t(e.getMinutes())}:${t(e.getSeconds())}:${t(e.getMilliseconds(),3)}`},F=(e,t,n,r)=>{let o=a.default.join(x,`${n}.html`),s=k(a.default.relative(a.default.dirname(o),t));return(0,i.writeFileSync)(o,N(e,r).replace(S,`<script type="module" src="${s}"><\/script>`)),o};function I(){t.logWhite(`frameFEPath: `+_),t.logWhite(`runFEPath: `+y);let e=[_,y].reduce((e,t)=>{let r=[`js`,`jsx`,`ts`,`tsx`].map(e=>n.resolve(t,`/**`,`/*.`+e)),i=o.sync(r).filter(e=>e.includes(`.entry.`)).filter(e=>!e.includes(`.d.ts`));return[...e,...i]},[]),r={};if(!e.length)return r;(0,i.rmSync)(x,{recursive:!0,force:!0}),(0,i.mkdirSync)(x,{recursive:!0});let s=(0,i.readFileSync)(a.default.resolve(g,`./app/view/entry.tpl`),`utf-8`);for(let t=0;t<e.length;t++){let n=e[t],i=a.default.resolve(n,`../`),o=M(i,a.default.basename(n).replace(/\.entry\.[^.]+$/,``)),c=o?a.default.basename(o,`.html`):i.split(a.default.sep).at(-1);r[c]=F(s,n,c,o?j(o):T())}return r}function L(){let e=r.buildFESharedState.options.output??`frame`;return e!==`frame`&&t.logRed(`Please pay attention to the build output.`),e===`run`?a.default.join(v,`./app/public/dist`):typeof e==`function`?e():a.default.join(g,`./app/public/dist`)}var R=async e=>{let n=(await import(`chokidar`)).watch(y,{ignored:/(^|[\/\\])\../,persistent:!0,ignoreInitial:!0}),r=!1;n.on(`change`,async n=>{if(!r){r=!0,t.logYellow(`changed: ${n}`);try{await e?.()}catch(e){t.logRed(e)}finally{r=!1}}}),t.logYellow(`watching ${y}/...`)};function z(){return{name:`flatten-html`,apply:`build`,closeBundle(){let e=L(),t=P();(0,i.writeFileSync)(n.resolve(e,`./FEBuildKey`),t)}}}function B(e=`.html`){let n=[...new Set(Array.isArray(e)?e:[e])];return{name:`flatten-html`,apply:`build`,closeBundle(){let e=L();if(!(0,i.existsSync)(e))return;let s=r.buildFESharedState.options.minifyHtml??!1,c=o.sync(`**/*.html`,{cwd:e,dot:!0});for(let t of c){let r=a.default.join(e,t),o=(0,i.readFileSync)(r,`utf-8`),c=s?D(o):o,l=a.default.basename(t,`.html`),u=`.entry`;l.indexOf(u)===-1&&(l+=u);for(let t of n){let n=l+t,o=a.default.join(e,n);r===o?s&&(0,i.writeFileSync)(o,c):(0,i.writeFileSync)(o,c)}n.some(t=>r===a.default.join(e,l+t))||(0,i.unlinkSync)(r)}let l=[...new Set(c.map(e=>a.default.dirname(e)))].sort().reverse(),u=e=>{if(!((0,i.existsSync)(e)?(0,i.readdirSync)(e):[1]).length){(0,i.rmdirSync)(e);let t=e.split(a.default.sep).slice(0,-1);t.length&&u(t.join(a.default.sep))}};for(let t of l)t&&t!==`.`&&u(a.default.join(e,t));let d=n.flatMap(t=>o.sync(`**/*`+t,{cwd:e,dot:!0}));for(let e of d)t.logYellow(`final file path -----> `+e)}}}function V(e){let t=[``,`.ts`,`.tsx`,`.js`,`.jsx`];return e.reduce((e,[n,r,o=y,s=`./defaultAlias`])=>{let c=t.map(e=>a.default.resolve(o,r+e)).find(e=>(0,i.existsSync)(e)),l=a.default.resolve(f,s);return c&&(l=c),e[n]=l,e},{})}var H=(...e)=>new RegExp(e.join(`[\\/]`)),U=e=>`_${e}_tcC`,W=async(e,n)=>{try{await(0,s.build)({configFile:!1,base:`/dist`,plugins:[(await import(`@vitejs/plugin-react`)).default(),B([`.tpl`]),z(),(0,c.default)()],build:{outDir:L(),emptyOutDir:!0,sourcemap:n===`dev`?`inline`:`hidden`,rolldownOptions:{input:e,output:{codeSplitting:{groups:[{name:U(`__nm`),test:H(`node_modules`),maxSize:5e5,minShareCount:2,priority:1},{name:U(`r`),test:H(`node_modules`,`react`),minShareCount:2,maxSize:5e5,priority:5},{name:U(`r-d`),test:H(`node_modules`,`react-dom`),minShareCount:2,maxSize:2e5,priority:10},{name:U(`r-r-d`),test:H(`node_modules`,`react-router-dom`),minShareCount:2,maxSize:5e5,priority:10},{name:U(`ajv`),test:H(`node_modules`,`ajv`),minShareCount:2,maxSize:2e5,priority:10},{name:U(`ui-lib`),test:H(`components`),minShareCount:2,maxSize:2e5,priority:5},{name:U(`ui-f-lib`),test:H(`components`,`.*?[Ff]orm.*?`),minShareCount:2,maxSize:5e4,priority:10}]}}}},resolve:{alias:{react:b(`react`),"react-dom":b(`react-dom`),"@tc/ui-react/hooks":a.default.resolve(f,`../../fe/packages/react/hooks/`),"@tc/ui-react":a.default.resolve(f,`../../fe/packages/react/ui/`),...V([[`@tc/scalability/SchemaForm/frameData`,`./extended/SchemaForm/data`,_],[`@tc/scalability/SchemaForm/data`,`./extended/SchemaForm/data`],[`@tc/scalability/SchemaPage/CallCom/data`,`./extended/SchemaPage/CallCom/data`],[`@tc/scalability/dash/customRoutes`,`./extended/dash/customRoutes`],[`@tc/scalability/dash/init`,`./extended/dash/init`],[`@tc/scalability/dash/components`,`./extended/dash/components`],[`@tc/scalability/dash/routeGuard`,`./extended/dash/routeGuard`,void 0,`./defaultRouteGuard`]])}}}),t.logJoinColorized(t.colorize(`builded`,`green`),t.colorize(` -> `,`white`),t.colorize(`time: `,`cyan`),t.colorize(new Date,`pink`))}catch(e){if(t.logRed(e),n!==`dev`)throw e}};exports.VBuildFE=W,exports.entries=I,exports.generateBuildKeyPlugin=z,exports.outDir=L,exports.watchFiles=R;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./guards/index.js`),t=require(`./array/index.js`),n=require(`./cache/LRUCache.js`),r=require(`./http/index.js`),i=require(`./i18n/default.js`),a=require(`./i18n/en-US.js`),o=require(`./i18n/locales.js`),s=require(`./i18n/index.js`),c=require(`./log/index.js`),l=require(`./number/index.js`),u=require(`./object/filterEmpty.js`),d=require(`./object/index.js`),f=require(`./string/index.js`);exports.ANSI_RESET=c.ANSI_RESET,exports.FetchAxios=r.FetchAxios,exports.LRUCache=n.LRUCache,exports.ansiColors=c.ansiColors,exports.axios=r.axios,exports.capitalize=f.capitalize,exports.chunk=t.chunk,exports.clamp=l.clamp,exports.colorLog=c.colorLog,exports.colorize=c.colorize,exports.compact=t.compact,exports.createInstance=r.createInstance,exports.defaultEnglishResources=a.defaultEnglishResources,exports.defaultLanguage=o.defaultLanguage,exports.defaultLanguageResources=i.defaultLanguageResources,exports.filterEmpty=u.filterEmpty,exports.filtereEmpty=u.filtereEmpty,exports.getI18nPathValue=s.getI18nPathValue,exports.getLanguage=s.getLanguage,exports.groupBy=t.groupBy,exports.i18n=s.i18n,exports.i18nStore=s.i18nStore,exports.interpolateI18nMessage=s.interpolateI18nMessage,exports.isBlank=f.isBlank,exports.isBoolean=e.isBoolean,exports.isFunction=e.isFunction,exports.isNil=e.isNil,exports.isNonNullable=e.isNonNullable,exports.isNumber=e.isNumber,exports.isPlainI18nDictionary=s.isPlainI18nDictionary,exports.isPlainObject=e.isPlainObject,exports.isString=e.isString,exports.joinColorized=c.joinColorized,exports.joinStr=f.joinStr,exports.kebabCase=f.kebabCase,exports.languageLocalKey=o.languageLocalKey,exports.logColor=c.logColor,exports.logColorized=c.logColorized,exports.logGreen=c.logGreen,exports.logJoinColorized=c.logJoinColorized,exports.logPink=c.logPink,exports.logRed=c.logRed,exports.logWhite=c.logWhite,exports.logYellow=c.logYellow,exports.mapValues=d.mapValues,exports.mergeI18nDictionary=s.mergeI18nDictionary,exports.mergeI18nResources=s.mergeI18nResources,exports.omit=d.omit,exports.pick=d.pick,exports.t=s.t,exports.toArray=t.toArray,exports.toFiniteNumber=l.toFiniteNumber,exports.translate=s.translate,exports.translations=o.translations,exports.uniqueBy=t.uniqueBy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=e=>e==null||e.trim().length===0,t=e=>e.length===0?e:`${e.charAt(0).toUpperCase()}${e.slice(1)}`,n=e=>e.trim().replace(/([a-z0-9])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).replace(/-+/g,`-`).toLowerCase();exports.capitalize=t,exports.isBlank=e,exports.kebabCase=n;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=e=>e==null||e.trim().length===0,t=e=>e.length===0?e:`${e.charAt(0).toUpperCase()}${e.slice(1)}`,n=e=>e.trim().replace(/([a-z0-9])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).replace(/-+/g,`-`).toLowerCase(),r=(...e)=>{let t=e[e.length-1],n=typeof t==`object`&&t&&!Array.isArray(t)&&`separator`in t?t:void 0,r=n?.separator??` `;return(n?e.slice(0,-1):e).flatMap(e=>{if(Array.isArray(e)){let[t,n]=e;return t?n:void 0}return e}).filter(e=>e!=null&&e!==!1&&e!==``).join(r)};exports.capitalize=t,exports.isBlank=e,exports.joinStr=r,exports.kebabCase=n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../_virtual/_rolldown/runtime.js`),t=require(`./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../_virtual/_rolldown/runtime.js`),t=require(`./env.js`),n=require(`../utils/path.js`),r=require(`../utils/runFileFn.js`);require(`../utils/index.js`);const i=require(`./loader/config.js`),a=require(`./paths.js`),o=require(`./loader/controller.js`),s=require(`./loader/extend.js`),c=require(`./loader/middleware.js`),l=require(`./loader/model.js`),u=require(`./loader/router.js`),d=require(`./loader/router-schema.js`),f=require(`./loader/service.js`);let p=require(`koa`);p=e.__toESM(p,1);var m=l,h=async(e={})=>{let r=new p.default;r.hooks={},r.hooks.initing?.();let{frameBaseDir:l,baseDir:m,...h}=e;r.options=h,r.options.pageBasePage=r.options.pageBasePage??`/`,r.options.apiPrefix=r.options.apiPrefix||`/api`;let _=r.baseDir=m??process.cwd(),v=r.frameBaseDir=l??n.resolve(__dirname,`..`);r.businessAppPath=n.resolve(_,`app`),r.frameAppPath=n.resolve(v,`app`),r.paths=[{type:`frame`,path:r.frameAppPath},{type:`business`,path:r.businessAppPath}];let y=r.options.additionalPublicPaths??[];y=Array.isArray(y)?y:[y],r.publicsPath=[n.resolve(a.getAppPath(r,`business`),`./public`),n.resolve(a.getAppPath(r,`frame`),`./public`),...y],r.envs=t(),console.log(`-- [init] env: ${r.envs.get()} --`),i(r),console.log(`-- [init] loader config done --`),await s(r),console.log(`-- [init] loader extends done --`),d(r),console.log(`-- [init] loader routerSchema done --`),f(r),console.log(`-- [init] loader service done --`),o(r),console.log(`-- [init] loader controller done --`),c(r),console.log(`-- [init] loader middleware done --`),g(r),u(r),console.log(`-- [init] loader router done --`);try{let e=r.config.port||process.env.PORT||`8080`,n=parseInt(e+``,10),i=process.env.IP||`0.0.0.0`;r.listen(n,i),console.log(`Server port: http://localhost:${n}`),console.log(`run env is ${t().get()}`)}catch(e){console.error(e)}return r.hooks.inited?.(),r},g=e=>{[`frame`,`business`].map(t=>({type:t,path:a.getAppPath(e,t)})).forEach(t=>{for(let i of[`ts`,`js`]){let a=`middleware.${i}`,o=n.resolve(t.path,a);try{r.runFileFn(o)?.(e),console.log(`-- [init] loader ${t.type} appMiddleware ${a} done -- (${t.path})`);break}catch(e){let n=e;if(!(n?.code===`MODULE_NOT_FOUND`&&typeof n?.message==`string`&&(n.message.includes(`Cannot find module '${o}'`)||n.message.includes(`Cannot find module "${o}"`))))throw console.log(`-- [error] loader ${t.type} appMiddleware ${a} error -- (${o})`),e}}})};exports.loaderModel=m,exports.start=h;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require(`../../utils/loadFile.js`),t=require(`../../utils/runFileFn.js`);require(`../../utils/index.js`);const n=require(`../paths.js`);var r=r=>{r.controller=n.getAppPaths(r).reduce((n,i)=>({...n,...e.loadFileFn(i,`controller`,{loadFileCallback:e=>new(t.runFileFn(e)(r))})}),{})};module.exports=r;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require(`../../utils/loadFile.js`),t=require(`../../utils/runFileFn.js`);require(`../../utils/index.js`);const n=require(`../paths.js`);var r=async r=>{r.extends={...r.extends};let i=[];n.getAppPaths(r).forEach(n=>{e.loadFileFn(n,`extends`,{processingFileCallback:((e,n,a)=>{if(!a){for(let t in r)if(t===e){console.log(`\x1B[31m%s\x1B[0m`,`[extend loader error] name:${e} is already in app`);return}let a=t.runFileFn(n)(r);i.push(Promise.resolve(a).then(t=>({fileName:e,value:t})))}})})}),(await Promise.all(i)).forEach(({fileName:e,value:t})=>{r.extends[e]=t})};module.exports=r;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require(`../../utils/loadFile.js`),t=require(`../../utils/runFileFn.js`);require(`../../utils/index.js`);const n=require(`../paths.js`);var r=r=>{r.middlewares=n.getAppPaths(r).reduce((n,i)=>{let a=e.loadFileFn(i,`middlewares`,{loadFileCallback:e=>t.runFileFn(e)(r)});return{...n,...a}},{})};module.exports=r;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require(`../../utils/path.js`),t=require(`../../utils/loadFile.js`),n=require(`../../utils/runFileFn.js`);require(`../../utils/index.js`);const r=require(`../paths.js`);var i=i=>{let a={};r.getAppPaths(i).forEach(r=>{t.loadFileFn(r,`router-schema`,{preProcessingFileCallback(t){a={...a,...n.runFileFn(e.resolve(t))}}})}),i.routerSchema=a};module.exports=i;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../../../_virtual/_rolldown/runtime.js`),t=require(
|
|
1
|
+
const e=require(`../../../_virtual/_rolldown/runtime.js`),t=require(`../../utils/path.js`),n=require(`../../utils/loadFile.js`),r=require(`../../utils/runFileFn.js`);require(`../../utils/index.js`);const i=require(`../paths.js`);let a=require(`fs`),o=require(`koa-router`);o=e.__toESM(o,1);var s=e=>{let s,c=i.getAppPath(e,`business`);if(c)for(let n of[`router-guard.ts`,`router-guard.js`]){let i=t.resolve(c,n);if((0,a.existsSync)(i)){s=r.runFileFn(i)(e);break}}s||console.info(`-- [router-guard] -- not router-guard.(ts|js) file`);let l=[];i.getAppPaths(e).forEach(i=>{n.loadFileFn(i,`router`,{preProcessingFileCallback:n=>{let i=new o.default;i.level=0,l.push(i),r.runFileFn(t.resolve(n))(e,i)}})});let u=new o.default;u.level=99,u.get(`(.*)`,async(t,n)=>{console.info(`\x1B[31m%s\x1B[0m`,`-- notFound path: ${t.path} --`);let r=s?.(t);t.status=302,r?typeof r==`string`?t.redirect(r??`/`):(t.status=r.status,t.body=r.body):t.path.includes(`${e.options.apiPrefix}/`)?(t.status=200,t.body={code:404,message:`${t.path} not found`}):(t.status=404,t.body=`notFound`)}),l.push(u),l.sort((e,t)=>(e.level??0)<(t.level??0)?-1:1),l.forEach(t=>{e.use(t.routes()),e.use(t.allowedMethods())}),e.currentUseRouter=l};module.exports=s;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require(`../../utils/loadFile.js`),t=require(`../../utils/runFileFn.js`);require(`../../utils/index.js`);const n=require(`../paths.js`);var r=r=>{r.service=n.getAppPaths(r).reduce((n,i)=>({...n,...e.loadFileFn(i,`service`,{loadFileCallback:e=>new(t.runFileFn(e)(r))})}),{})};module.exports=r;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../../_virtual/_rolldown/runtime.js`);let e=require(`
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../../_virtual/_rolldown/runtime.js`);let e=require(`fs`),t=require(`path`);var n=!1;function r(e){return i(typeof e==`string`?a(e):e)}function i(e){return e&&typeof e==`object`&&`default`in e&&e.default!==void 0?e.default:e}function a(e){try{return require(e)}catch(n){if((0,t.extname)(e)!==`.ts`||!o(n))throw n;return s(),delete require.cache[require.resolve(e)],require(e)}}function o(e){let t=e,n=t?.message??``;return t?.code===`ERR_UNKNOWN_FILE_EXTENSION`||t?.code===`ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX`||t?.name===`SyntaxError`||n.indexOf(`Cannot use import statement outside a module`)!==-1||n.indexOf(`Unexpected token 'export'`)!==-1}function s(){if(n)return;let t=c();require.extensions[`.ts`]=(n,r)=>{let{outputText:i}=t.transpileModule((0,e.readFileSync)(r,`utf8`),{compilerOptions:{module:t.ModuleKind.CommonJS,target:t.ScriptTarget.ES2020,esModuleInterop:!0,allowSyntheticDefaultImports:!0}});n._compile(i,r)},n=!0}function c(){try{return require(`typescript`)}catch(e){throw Error(`Unable to load TypeScript file. Please install "typescript" or run with a TypeScript runtime. ${String(e)}`)}}exports.runFileFn=r;
|
|
@@ -1,21 +1,31 @@
|
|
|
1
|
+
import { joinStr as e } from "../../packages/common/string/index.js";
|
|
1
2
|
//#region app/controller/view.ts
|
|
2
|
-
var
|
|
3
|
-
async renderPage(
|
|
4
|
-
|
|
3
|
+
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 {
|
|
4
|
+
async renderPage(r, i) {
|
|
5
|
+
let a = r.path;
|
|
6
|
+
if (n.extends.localCacheHtmlEtag.keepFreshFEBuildKey(), a.includes(`${n.options.apiPrefix}/`)) await i();
|
|
5
7
|
else {
|
|
6
|
-
|
|
8
|
+
n.extends.logger.log(" - render page: " + r.params.page);
|
|
7
9
|
try {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
let i = r.query.projk;
|
|
11
|
+
Array.isArray(i) && (i = e(...i));
|
|
12
|
+
let a = {
|
|
13
|
+
projKey: i ?? "",
|
|
14
|
+
name: n.options?.name ?? "",
|
|
15
|
+
env: n.envs.get(),
|
|
16
|
+
basePath: t(`${n.options.pageBasePage}${r.params.page}`),
|
|
17
|
+
projKeyJson: t(String(r.query.projk ?? "")),
|
|
18
|
+
signKey: t(n.config.signKey),
|
|
19
|
+
options: t(n.options)
|
|
20
|
+
}, o = n.extends.renderView(`${r.params.page}.entry.tpl`, r, a), s = e(a.basePath, a.name, a.env, a.projKey);
|
|
21
|
+
if (!n.extends.localCacheHtmlEtag.hasEtag(s)) {
|
|
22
|
+
let e = n.extends.crypto.hmacSign(o);
|
|
23
|
+
n.extends.localCacheHtmlEtag.setEtag(s, e);
|
|
24
|
+
}
|
|
25
|
+
let c = n.extends.localCacheHtmlEtag.getEtag(s);
|
|
26
|
+
c || console.log("---- etag 缓存异常 请检查服务 ----"), r.etag = c ?? Date.now() + "";
|
|
17
27
|
} catch (e) {
|
|
18
|
-
console.log("-------------- render view error --------------"), console.log(e),
|
|
28
|
+
console.log("-------------- render view error --------------"), console.log(e), n.extends.generateErrorMessage("template not found", {
|
|
19
29
|
status: 404,
|
|
20
30
|
showError: !0,
|
|
21
31
|
code: 0
|
|
@@ -25,4 +35,4 @@ var e = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u003e
|
|
|
25
35
|
}
|
|
26
36
|
});
|
|
27
37
|
//#endregion
|
|
28
|
-
export {
|
|
38
|
+
export { n as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHmac as e, timingSafeEqual as t } from "node:crypto";
|
|
2
|
-
//#region app/
|
|
2
|
+
//#region app/extends/crypto.ts
|
|
3
3
|
var n = "sha256", r = ".", i = "template-core-crypto", a = (e, t) => String(t ?? e.config.signKey ?? i), o = (e) => e ?? n, s = (e) => e || r, c = (e) => Buffer.isBuffer(e) ? e : Buffer.from(e), l = (n) => {
|
|
4
4
|
let r = (e) => c(e).toString("base64url"), i = (e) => Buffer.from(e, "base64url"), l = (e) => i(e).toString("utf8"), u = (t, r) => e(o(r?.algorithm), a(n, r?.secret)).update(t).digest("base64url"), d = (e, n) => {
|
|
5
5
|
let r = Buffer.from(e), i = Buffer.from(n);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __require as e } from "../../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { mkdirSync as t } from "node:fs";
|
|
3
3
|
import { dirname as n, isAbsolute as r, resolve as i } from "node:path";
|
|
4
|
-
//#region app/
|
|
4
|
+
//#region app/extends/db.ts
|
|
5
5
|
var a = "framework", o = ".template-core/template-core.sqlite";
|
|
6
6
|
function s(e) {
|
|
7
7
|
let r = u(e), i, a = !1, o = 0, s = () => (x(a), i || (t(n(r), { recursive: !0 }), i = c(r), l(i)), i), d = {
|
|
@@ -70,7 +70,7 @@ function c(t) {
|
|
|
70
70
|
try {
|
|
71
71
|
r = e(n);
|
|
72
72
|
} catch (e) {
|
|
73
|
-
throw Error(`[db] 默认数据库依赖 Node.js 内置 ${n},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/
|
|
73
|
+
throw Error(`[db] 默认数据库依赖 Node.js 内置 ${n},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。${S(e)}`);
|
|
74
74
|
}
|
|
75
75
|
if (!r.DatabaseSync) throw Error(`[db] ${n} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。`);
|
|
76
76
|
return new r.DatabaseSync(t);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync as e, readFileSync as t } from "fs";
|
|
2
|
+
import n from "path";
|
|
3
|
+
//#region app/extends/localCacheHtmlEtag.ts
|
|
4
|
+
var r = "./dist/FEBuildKey", i = {
|
|
5
|
+
etags: {},
|
|
6
|
+
FEBuildKey: null
|
|
7
|
+
}, a = ((a) => {
|
|
8
|
+
let o = (e, t) => {
|
|
9
|
+
i.etags[e] = t;
|
|
10
|
+
}, s = (e) => !!c(e), c = (e) => i.etags[e] || null, l = (e) => {
|
|
11
|
+
i.FEBuildKey = e;
|
|
12
|
+
}, u = () => i.FEBuildKey || null, d = () => {
|
|
13
|
+
for (let t of a.publicsPath) {
|
|
14
|
+
let i = n.resolve(t, r);
|
|
15
|
+
if (e(i)) return i;
|
|
16
|
+
}
|
|
17
|
+
}, f = () => {
|
|
18
|
+
let e, n = d();
|
|
19
|
+
return n && (e = t(n, "utf-8")), e === u();
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
keepFreshFEBuildKey: () => {
|
|
23
|
+
if (!f()) {
|
|
24
|
+
let e = d();
|
|
25
|
+
if (e) {
|
|
26
|
+
let n = t(e, "utf-8");
|
|
27
|
+
if (n) {
|
|
28
|
+
l(n), i.etags = {};
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
console.log("--- 没找到前端构建key文件 ---"), console.log("--- filePath --- -> ", e);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
hasEtag: s,
|
|
36
|
+
getEtag: c,
|
|
37
|
+
setEtag: o
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { a as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import e from "node:path";
|
|
2
|
+
import t from "nunjucks";
|
|
3
|
+
//#region app/extends/render-view.ts
|
|
4
|
+
var n = (n) => {
|
|
5
|
+
let r = n.publicsPath.map((t) => e.resolve(t, "./dist"));
|
|
6
|
+
console.log(r);
|
|
7
|
+
let i = t.configure(r, {
|
|
8
|
+
autoescape: !0,
|
|
9
|
+
throwOnUndefined: !1,
|
|
10
|
+
trimBlocks: !1,
|
|
11
|
+
lstripBlocks: !1,
|
|
12
|
+
noCache: n.envs.get() === "local",
|
|
13
|
+
...typeof n.config.nunjucks == "object" ? n.config.nunjucks : {}
|
|
14
|
+
});
|
|
15
|
+
return n.extends.nunjucksEnv = i, (e, t, n) => t.body = i.render(e, Object.assign({}, t.state, n));
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { n as default };
|