@_tc/template-core 0.2.0-bate.10 → 0.2.0-bate.12
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/AGENT_README.md +1 -1
- package/README.md +11 -2
- package/cjs/app/controller/project.js +1 -1
- package/cjs/app/extends/db.js +4 -4
- package/cjs/app/middlewares/error-handle.js +1 -1
- package/cjs/app/middlewares/project-handler.js +1 -1
- package/cjs/app/utils/i18n.js +1 -0
- package/cjs/packages/common/i18n/default.js +1 -1
- package/cjs/packages/common/i18n/en-US.js +1 -1
- package/cjs/packages/common/index.js +1 -1
- package/esm/app/controller/project.js +12 -11
- package/esm/app/extends/db.js +64 -60
- package/esm/app/middlewares/error-handle.js +16 -15
- package/esm/app/middlewares/project-handler.js +8 -7
- package/esm/app/utils/i18n.js +36 -0
- package/esm/packages/common/i18n/default.js +13 -0
- package/esm/packages/common/i18n/en-US.js +13 -0
- package/esm/packages/common/index.js +9 -9
- package/fe/frontend/src/common/language.js +2 -2
- package/fe/frontend/src/common/request.js +3 -1
- package/fe/frontend/src/hooks/useText.js +2 -2
- package/fe/packages/common/i18n/default.d.ts +15 -0
- package/fe/packages/common/i18n/default.js +13 -0
- package/fe/packages/common/i18n/en-US.d.ts +15 -0
- package/fe/packages/common/i18n/en-US.js +13 -0
- package/model/packages/common/i18n/default.d.ts +15 -0
- package/model/packages/common/i18n/en-US.d.ts +15 -0
- package/package.json +1 -1
- package/types/app/utils/i18n.d.ts +12 -0
- package/types/packages/common/i18n/default.d.ts +15 -0
- package/types/packages/common/i18n/en-US.d.ts +15 -0
package/AGENT_README.md
CHANGED
|
@@ -423,7 +423,7 @@ import { Button, DataTable, Form, Input, Modal, Select } from '@_tc/template-cor
|
|
|
423
423
|
- 组件加载辅助:`renderImportComponent(import('./Page'))` 会用 `React.lazy` + `Suspense` 渲染动态组件。
|
|
424
424
|
- Schema 通信:`schemaEventBus`、`eventsInfo`、`merge`。
|
|
425
425
|
- 共享状态:`modeStore`、`schemaStore`、`apiFreezerStore` 及对应 hooks。
|
|
426
|
-
- 多语言:`addLanguageResources()` 追加或新增某语种文案,`setLanguage()`
|
|
426
|
+
- 多语言:`addLanguageResources()` 追加或新增某语种文案,`setLanguage()` 切换语言。React render 中用 `useText()`,非 React 工具代码用 `getText()`;`$i18n::` 前缀会被去掉后查询资源,无前缀字符串会按原 key 查询,未命中时原样返回。配置文案推荐写 `$i18n::...`,也可写普通字符串。
|
|
427
427
|
- 主题:`ThemeSwitch` 会同步根节点 `dark` class 和 `localStorage`。
|
|
428
428
|
- `Input type="password"` 会自动显示密码显隐按钮;`allowClear` 不作用于密码输入。
|
|
429
429
|
- RAF 风格计时器由 `@tc/common/rafTimer` 提供,浏览器优先使用 RAF,Node/SSR 自动降级到 `setTimeout`。
|
package/README.md
CHANGED
|
@@ -118,6 +118,8 @@ export default {
|
|
|
118
118
|
|
|
119
119
|
`auth.ATKey` / `auth.RTKey` 用于约定项目鉴权中间件读取短 token 和刷新 token 的 header 名;默认分别为 `Authorization` 和 `RT`。
|
|
120
120
|
|
|
121
|
+
服务端返回给前端的错误消息会按请求头里的语种翻译。当前优先读取 `x-tc-language`,也兼容 `tc_language`、`tc-language`、`language`、`lang`、`locale` 和 `accept-language`;如果没取到,默认按英文 `en-US` 处理。
|
|
122
|
+
|
|
121
123
|
静态资源挂载顺序为:项目 `app/public`、框架 `app/public`、`additionalPublicPaths`。Nunjucks 模板查找顺序为:项目 `app/public/dist`、框架 `app/public/dist`、`additionalPublicPaths/dist`。这些目录由 `app.publicsPath` 统一维护。当 `buildFE` 输出到自定义目录时,可以用 `additionalPublicPaths` 把该目录交给 Koa 提供静态资源访问和模板渲染;如果需要模板查找也命中追加目录,请传绝对路径数组。
|
|
122
124
|
|
|
123
125
|
### buildFE 参数说明
|
|
@@ -455,7 +457,9 @@ setLanguage('ja-JP')
|
|
|
455
457
|
|
|
456
458
|
`addLanguageResources()` 用于追加或新增某个语种的文案,默认会深合并同语种资源;传 `{ merge: false }` 可以替换该语种资源。`setResources(resources, { merge: true })` 可批量合并多语种资源。`LanguageSwitch` 默认会把已注册语种加入选项;需要自定义展示文案时仍可传入 `options`。
|
|
457
459
|
|
|
458
|
-
React 组件 render 中使用 `useText()` 读取文案。它会订阅语言和资源变化,调用 `setLanguage()`
|
|
460
|
+
React 组件 render 中使用 `useText()` 读取文案。它会订阅语言和资源变化,调用 `setLanguage()` 后组件会自动重渲染。
|
|
461
|
+
|
|
462
|
+
`useText()` / `getText()` 遇到 `$i18n::` 前缀会先去掉前缀再查语言资源;没有前缀时会直接把传入字符串作为 key 查询,查不到才原样返回:
|
|
459
463
|
|
|
460
464
|
```tsx
|
|
461
465
|
import { useText } from '@_tc/template-core/fe'
|
|
@@ -463,7 +467,12 @@ import { useText } from '@_tc/template-core/fe'
|
|
|
463
467
|
function ProductTitle() {
|
|
464
468
|
const text = useText()
|
|
465
469
|
|
|
466
|
-
return
|
|
470
|
+
return (
|
|
471
|
+
<>
|
|
472
|
+
<h1>{text('$i18n::app.product.menu')}</h1>
|
|
473
|
+
<span>{text('Plain title')}</span>
|
|
474
|
+
</>
|
|
475
|
+
)
|
|
467
476
|
}
|
|
468
477
|
```
|
|
469
478
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./base.js`);var
|
|
1
|
+
const e=require(`./base.js`),t=require(`../utils/i18n.js`);var n=(n=>{let r=e(n);return class extends r{getModelList=async e=>{let t=(await this.service.project.getModelList()).reduce((e,t)=>{let{model:n,project:r}=t,{key:i,name:a,desc:o}=n,s={key:i,name:a,desc:o},c=Object.keys(r).reduce((e,t)=>{let{key:n,name:i,desc:a,homePage:o}=r[t];return e[t]={key:n,name:i,desc:a,homePage:o},e},{});return e.push({model:s,project:c}),e},[]);this.success(e,t)};getProjectList=async e=>{let t=e.reqData?.data.projk,n=(await this.service.project.getList(t))?.map(e=>{let{modelKey:t,key:n,name:r,desc:i,homePage:a}=e;return{modelKey:t,key:n,name:r,desc:i,homePage:a}});this.success(e,n)};getProject=async e=>{let{key:n}=e.params;if(!n){this.fail(e,10001,t.requestT(e,`server.errors.getProjectFailed`));return}let r=this.service.project.getProject(n);if(!r){this.fail(e,10001,t.requestT(e,`server.errors.getProjectFailed`));return}this.success(e,r)}}});module.exports=n;
|
package/cjs/app/extends/db.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
require(`../../_virtual/_rolldown/runtime.js`);
|
|
1
|
+
require(`../../_virtual/_rolldown/runtime.js`);const e=require(`../utils/i18n.js`);let t=require(`node:fs`),n=require(`node:path`);var r=`framework`,i=`.template-core/template-core.sqlite`;function a(e){let r=c(e),i,a=!1,l=0,u=()=>(y(a),i||((0,t.mkdirSync)((0,n.dirname)(r),{recursive:!0}),i=o(r),s(i)),i),_={dbPath:r,getDBConnection:u,execDB:e=>{u().exec(e)},runDB:(e,t)=>{let n=u().prepare(e).run(...d(t));return{changes:Number(n.changes??0),lastInsertRowid:n.lastInsertRowid??0}},queryDB:(e,t)=>u().prepare(e).all(...d(t)),getDBFirst:(e,t)=>u().prepare(e).get(...d(t)),transactionDB:e=>{let t=u(),n=`tc_savepoint_${l}`,r=l===0;t.exec(r?`BEGIN IMMEDIATE`:`SAVEPOINT ${n}`),l+=1;try{let i=e(_);return--l,t.exec(r?`COMMIT`:`RELEASE SAVEPOINT ${n}`),i}catch(e){throw--l,t.exec(r?`ROLLBACK`:`ROLLBACK TO SAVEPOINT ${n}`),r||t.exec(`RELEASE SAVEPOINT ${n}`),e}},getDBData:(e,t)=>_.getDBDataRecord(e,t)?.value,getDBDataRecord:(e,t)=>{let n=_.getDBFirst(`SELECT namespace, data_key, data_value, created_at, updated_at FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1`,[f(t?.namespace),p(e)]);return n?v(n):void 0},setDBData:(e,t,n)=>{let r=new Date().toISOString();return _.runDB(`INSERT INTO tc_framework_data (namespace, data_key, data_value, created_at, updated_at)
|
|
2
2
|
VALUES (?, ?, ?, ?, ?)
|
|
3
3
|
ON CONFLICT(namespace, data_key) DO UPDATE SET
|
|
4
4
|
data_value = excluded.data_value,
|
|
5
|
-
updated_at = excluded.updated_at`,[
|
|
5
|
+
updated_at = excluded.updated_at`,[f(n?.namespace),p(e),g(t),r,r])},hasDBData:(e,t)=>!!_.getDBFirst(`SELECT 1 AS exists_value FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1`,[f(t?.namespace),p(e)]),deleteDBData:(e,t)=>_.runDB(`DELETE FROM tc_framework_data WHERE namespace = ? AND data_key = ?`,[f(t?.namespace),p(e)]).changes>0,listDBData:e=>{let t=m(e?.limit),n=h(e?.offset);return _.queryDB(`SELECT namespace, data_key, data_value, created_at, updated_at
|
|
6
6
|
FROM tc_framework_data
|
|
7
7
|
WHERE namespace = ?
|
|
8
8
|
ORDER BY updated_at DESC, data_key ASC
|
|
9
|
-
LIMIT ? OFFSET ?`,[
|
|
9
|
+
LIMIT ? OFFSET ?`,[f(e?.namespace),t,n]).map(e=>v(e))},countDBData:e=>{let t=_.getDBFirst(`SELECT COUNT(1) AS count_value FROM tc_framework_data WHERE namespace = ?`,[f(e?.namespace)]);return Number(t?.count_value??0)},clearDBData:e=>_.runDB(`DELETE FROM tc_framework_data WHERE namespace = ?`,[f(e?.namespace)]).changes,closeDB:()=>{a||=(i?.close(),!0)}};return _}function o(t){let n=`node:sqlite`,r;try{r=require(n)}catch(t){throw e.createI18nError(`server.errors.dbNodeSqliteUnavailable`,{sqliteSpecifier:n,cause:b(t)})}if(!r.DatabaseSync)throw e.createI18nError(`server.errors.dbDatabaseSyncUnavailable`,{sqliteSpecifier:n});return new r.DatabaseSync(t)}function s(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,
|
|
@@ -17,4 +17,4 @@ require(`../../_virtual/_rolldown/runtime.js`);let e=require(`node:fs`),t=requir
|
|
|
17
17
|
);
|
|
18
18
|
CREATE INDEX IF NOT EXISTS idx_tc_framework_data_namespace_updated_at
|
|
19
19
|
ON tc_framework_data (namespace, updated_at);
|
|
20
|
-
`)}function
|
|
20
|
+
`)}function c(e){let t=l(e),r=typeof t==`string`?t:t?.path??t?.filename??t?.sqlitePath??u(t?.sqlite);return r?(0,n.isAbsolute)(r)?r:(0,n.resolve)(e.baseDir,r):(0,n.resolve)(e.baseDir,i)}function l(e){let t=e.config;return t.db??(t.sqlite?{sqlite:t.sqlite}:void 0)}function u(e){if(e)return typeof e==`string`?e:e.path??e.filename}function d(e){return e?Array.isArray(e)?e:[e]:[]}function f(t=r){let n=t.trim();if(!n)throw e.createI18nError(`server.errors.dbNamespaceRequired`);return n}function p(t){let n=t.trim();if(!n)throw e.createI18nError(`server.errors.dbKeyRequired`);return n}function m(t=100){if(!Number.isSafeInteger(t)||t<=0)throw e.createI18nError(`server.errors.dbLimitInvalid`);return t}function h(t=0){if(!Number.isSafeInteger(t)||t<0)throw e.createI18nError(`server.errors.dbOffsetInvalid`);return t}function g(t){try{let e=JSON.stringify(t);if(e===void 0)throw Error(`value is not JSON serializable`);return e}catch(t){throw e.createI18nError(`server.errors.dbValueNotSerializable`,{cause:b(t)})}}function _(e){return JSON.parse(e)}function v(e){return{key:e.data_key,value:_(e.data_value),namespace:e.namespace,createdAt:e.created_at,updatedAt:e.updated_at}}function y(t){if(t)throw e.createI18nError(`server.errors.dbClosed`)}function b(e){return e instanceof Error&&e.message?` Cause: ${e.message}`:``}module.exports=a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=require(`../utils/i18n.js`);var t={},n=n=>async(r,i)=>{try{await i()}catch(i){let a=i,{status:o=200,message:s,detail:c,code:l=5e4,returnError:u}=a,d=e.getRequestErrorMessage(r,a,s);if(n.extends.logger?.info(`error info -> ${JSON.stringify(i)}`),n.extends.logger?.error(`-- [excption] --`,i),n.extends.logger?.error(`-- [excption] info --`,o,s,c),s?.includes(`template not found`)){let e=r.path??r.req.url??r.url;if(t[e]===void 0?t[e]=0:t[e]+=1,t[e]<n.config.notFoundRedirectCount){r.status=302,r.redirect(n.options?.homePage??`/`);return}else t[e]=0}u?(r.status=o,r.body={code:l,message:d}):(r.status=200,r.body={code:5e4,message:e.requestT(r,`server.errors.network`)})}};module.exports=n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=require(`../utils/i18n.js`);var t=t=>async(n,r)=>{let i=n.headers.projk,{path:a}=n;if(a.indexOf(`${t.options.apiPrefix}/proj/`)!==-1&&(!i||[`undefined`,`null`].includes(i))){n.status=200,n.body={code:110,data:null,message:e.requestT(n,`server.errors.invalidRequest`)};return}n.extInfo={key:i},await r()};module.exports=t;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../packages/common/i18n/index.js`);var t=`x-tc-language`,n=`en-US`,r=[t,`tc_language`,`tc-language`,`language`,`lang`,`locale`],i=e=>Array.isArray(e)?e[0]:e,a=(e,t)=>i(e[t.toLowerCase()]),o=e=>e?e.split(`,`).map(e=>e.trim().split(`;`)[0]?.trim()).filter(e=>!!e):[],s=t=>{if(!t)return n;let r=Object.keys(e.i18nStore.getState().resources),i=t.trim().toLowerCase(),a=r.find(e=>e.toLowerCase()===i);if(a)return a;let o=i.split(`-`)[0];return r.find(e=>e.toLowerCase().split(`-`)[0]===o)??n},c=e=>{for(let t of r){let n=a(e.headers,t);if(n)return s(n)}let t=o(a(e.headers,`accept-language`));for(let e of t){let t=s(e);if(t)return t}return n},l=(t,r,i,a)=>e.i18n(r,i,{...a,language:a?.language??c(t),fallbackLanguage:a?.fallbackLanguage??n}),u=(e,t,n)=>{let r=Error(n??e);return r.i18nKey=e,r.i18nData=t,r},d=(e,t,n)=>t.i18nKey?l(e,t.i18nKey,t.i18nData,{fallback:n??t.message}):n??t.message;exports.LANGUAGE_HEADER_KEY=t,exports.createI18nError=u,exports.getRequestErrorMessage=d,exports.getRequestLanguage=c,exports.normalizeI18nLanguage=s,exports.requestT=l;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={common:{tip:`提示`,confirm:`确认`,cancel:`取消`,close:`关闭`,submit:`提交`,reset:`重置`},components:{breadcrumb:{close:`关闭`},confirmDialog:{title:`提示`,okText:`确认`,cancelText:`取消`},dataTable:{noData:`暂无数据`},date:{placeholder:`请选择日期`,placeholderDateTime:`请选择日期时间`,placeholderRange:`选择日期范围`,placeholderDateTimeRange:`选择日期时间范围`,weekDays:[`日`,`一`,`二`,`三`,`四`,`五`,`六`],selectTime:`选择时间`,startTime:`开始时间`,endTime:`结束时间`,confirm:`确认`,monthFormat:`yyyy年 M月`,quickRanges:`快速选择`,quickRangeToday:`今天`,quickRangeYesterday:`昨天`,quickRangeLast7Days:`近7天`,quickRangeLast30Days:`近30天`,quickRangeThisMonth:`本月`,quickRangeLastYear:`最近一年`,clear:`清除`},form:{submit:`提交`,cancel:`取消`},imagePreview:{closePreview:`关闭预览`,previousImage:`上一张`,nextImage:`下一张`,zoomOut:`缩小`,zoomIn:`放大`,reset:`重置`,rotateLeft:`左旋转`,rotateRight:`右旋转`,flipHorizontal:`左右镜像`,flipVertical:`上下镜像`,previewImage:`预览第{index}张`},modal:{close:`关闭`,confirmTitle:`提示`,okText:`确认`,cancelText:`取消`},message:{close:`关闭`},select:{empty:`暂无选项`},tableSearch:{reset:`重置`,search:`查询`,export:`导出Excel`,expand:`展开`,collapse:`收起`,exportCurrentPage:`当前页`,exportCurrentQuery:`当前查询条件`},upload:{deleteImage:`删除图片`,upload:`上传`}}};exports.defaultLanguageResources=e;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={common:{tip:`提示`,confirm:`确认`,cancel:`取消`,close:`关闭`,submit:`提交`,reset:`重置`},server:{errors:{network:`网络错误`,invalidRequest:`请求不合法`,getProjectFailed:`获取项目异常`,dbNodeSqliteUnavailable:`[db] 默认数据库依赖 Node.js 内置 {sqliteSpecifier},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。{cause}`,dbDatabaseSyncUnavailable:`[db] {sqliteSpecifier} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。`,dbNamespaceRequired:`[db] namespace 不能为空`,dbKeyRequired:`[db] key 不能为空`,dbLimitInvalid:`[db] limit 必须是大于 0 的整数`,dbOffsetInvalid:`[db] offset 必须是大于等于 0 的整数`,dbValueNotSerializable:`[db] value 必须可以被 JSON.stringify 序列化。{cause}`,dbClosed:`[db] SQLite 数据库连接已关闭`}},components:{breadcrumb:{close:`关闭`},confirmDialog:{title:`提示`,okText:`确认`,cancelText:`取消`},dataTable:{noData:`暂无数据`},date:{placeholder:`请选择日期`,placeholderDateTime:`请选择日期时间`,placeholderRange:`选择日期范围`,placeholderDateTimeRange:`选择日期时间范围`,weekDays:[`日`,`一`,`二`,`三`,`四`,`五`,`六`],selectTime:`选择时间`,startTime:`开始时间`,endTime:`结束时间`,confirm:`确认`,monthFormat:`yyyy年 M月`,quickRanges:`快速选择`,quickRangeToday:`今天`,quickRangeYesterday:`昨天`,quickRangeLast7Days:`近7天`,quickRangeLast30Days:`近30天`,quickRangeThisMonth:`本月`,quickRangeLastYear:`最近一年`,clear:`清除`},form:{submit:`提交`,cancel:`取消`},imagePreview:{closePreview:`关闭预览`,previousImage:`上一张`,nextImage:`下一张`,zoomOut:`缩小`,zoomIn:`放大`,reset:`重置`,rotateLeft:`左旋转`,rotateRight:`右旋转`,flipHorizontal:`左右镜像`,flipVertical:`上下镜像`,previewImage:`预览第{index}张`},modal:{close:`关闭`,confirmTitle:`提示`,okText:`确认`,cancelText:`取消`},message:{close:`关闭`},select:{empty:`暂无选项`},tableSearch:{reset:`重置`,search:`查询`,export:`导出Excel`,expand:`展开`,collapse:`收起`,exportCurrentPage:`当前页`,exportCurrentQuery:`当前查询条件`},upload:{deleteImage:`删除图片`,upload:`上传`}}};exports.defaultLanguageResources=e;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={common:{tip:`Prompt`,confirm:`Confirm`,cancel:`Cancel`,close:`Close`,submit:`Submit`,reset:`Reset`},components:{breadcrumb:{close:`Close`},confirmDialog:{title:`Prompt`,okText:`Confirm`,cancelText:`Cancel`},dataTable:{noData:`No Data`},date:{placeholder:`Select date`,placeholderDateTime:`Select date and time`,placeholderRange:`Select date range`,placeholderDateTimeRange:`Select date and time range`,weekDays:[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`],selectTime:`Select time`,startTime:`Start time`,endTime:`End time`,confirm:`Confirm`,monthFormat:`MMM yyyy`,quickRanges:`Quick ranges`,quickRangeToday:`Today`,quickRangeYesterday:`Yesterday`,quickRangeLast7Days:`Last 7 days`,quickRangeLast30Days:`Last 30 days`,quickRangeThisMonth:`This month`,quickRangeLastYear:`Last year`,clear:`Clear`},form:{submit:`Submit`,cancel:`Cancel`},imagePreview:{closePreview:`Close preview`,previousImage:`Previous image`,nextImage:`Next image`,zoomOut:`Zoom out`,zoomIn:`Zoom in`,reset:`Reset`,rotateLeft:`Rotate left`,rotateRight:`Rotate right`,flipHorizontal:`Flip horizontal`,flipVertical:`Flip vertical`,previewImage:`Preview image {index}`},modal:{close:`Close`,confirmTitle:`Prompt`,okText:`Confirm`,cancelText:`Cancel`},message:{close:`Close`},select:{empty:`No options`},tableSearch:{reset:`Reset`,search:`Search`,export:`Export Excel`,expand:`Expand`,collapse:`Collapse`,exportCurrentPage:`Current Page`,exportCurrentQuery:`Current Filters`},upload:{deleteImage:`Delete image`,upload:`Upload`}}};exports.defaultEnglishResources=e;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={common:{tip:`Prompt`,confirm:`Confirm`,cancel:`Cancel`,close:`Close`,submit:`Submit`,reset:`Reset`},server:{errors:{network:`Network error`,invalidRequest:`Invalid request`,getProjectFailed:`Failed to get project`,dbNodeSqliteUnavailable:`[db] The default database depends on Node.js built-in {sqliteSpecifier}, which is unavailable in the current runtime. Upgrade Node.js or override app/extends/db.ts in the business project.{cause}`,dbDatabaseSyncUnavailable:`[db] {sqliteSpecifier} does not provide DatabaseSync, so the default SQLite database cannot be initialized.`,dbNamespaceRequired:`[db] namespace cannot be empty`,dbKeyRequired:`[db] key cannot be empty`,dbLimitInvalid:`[db] limit must be an integer greater than 0`,dbOffsetInvalid:`[db] offset must be an integer greater than or equal to 0`,dbValueNotSerializable:`[db] value must be serializable by JSON.stringify.{cause}`,dbClosed:`[db] SQLite database connection is closed`}},components:{breadcrumb:{close:`Close`},confirmDialog:{title:`Prompt`,okText:`Confirm`,cancelText:`Cancel`},dataTable:{noData:`No Data`},date:{placeholder:`Select date`,placeholderDateTime:`Select date and time`,placeholderRange:`Select date range`,placeholderDateTimeRange:`Select date and time range`,weekDays:[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`],selectTime:`Select time`,startTime:`Start time`,endTime:`End time`,confirm:`Confirm`,monthFormat:`MMM yyyy`,quickRanges:`Quick ranges`,quickRangeToday:`Today`,quickRangeYesterday:`Yesterday`,quickRangeLast7Days:`Last 7 days`,quickRangeLast30Days:`Last 30 days`,quickRangeThisMonth:`This month`,quickRangeLastYear:`Last year`,clear:`Clear`},form:{submit:`Submit`,cancel:`Cancel`},imagePreview:{closePreview:`Close preview`,previousImage:`Previous image`,nextImage:`Next image`,zoomOut:`Zoom out`,zoomIn:`Zoom in`,reset:`Reset`,rotateLeft:`Rotate left`,rotateRight:`Rotate right`,flipHorizontal:`Flip horizontal`,flipVertical:`Flip vertical`,previewImage:`Preview image {index}`},modal:{close:`Close`,confirmTitle:`Prompt`,okText:`Confirm`,cancelText:`Cancel`},message:{close:`Close`},select:{empty:`No options`},tableSearch:{reset:`Reset`,search:`Search`,export:`Export Excel`,expand:`Expand`,collapse:`Collapse`,exportCurrentPage:`Current Page`,exportCurrentQuery:`Current Filters`},upload:{deleteImage:`Delete image`,upload:`Upload`}}};exports.defaultEnglishResources=e;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./i18n/default.js`),t=require(`./i18n/en-US.js`),n=require(`./i18n/locales.js`),r=require(`./i18n/index.js`),i=require(`./guards/index.js`),a=require(`./array/index.js`),o=require(`./cache/LRUCache.js`),s=require(`./http/index.js`),c=require(`./log/index.js`),l=require(`./number/index.js`),u=require(`./object/filterEmpty.js`),d=require(`./object/index.js`),f=require(`./rafTimer.js`),p=require(`./string/index.js`);exports.ANSI_RESET=c.ANSI_RESET,exports.FetchAxios=s.FetchAxios,exports.LRUCache=o.LRUCache,exports.ansiColors=c.ansiColors,exports.axios=s.axios,exports.capitalize=p.capitalize,exports.chunk=a.chunk,exports.clamp=l.clamp,exports.clearRafTimer=f.clearRafTimer,exports.colorLog=c.colorLog,exports.colorize=c.colorize,exports.compact=a.compact,exports.createInstance=s.createInstance,exports.defaultEnglishResources=t.defaultEnglishResources,exports.defaultLanguage=n.defaultLanguage,exports.defaultLanguageResources=e.defaultLanguageResources,exports.filterEmpty=u.filterEmpty,exports.filtereEmpty=u.filtereEmpty,exports.getI18nPathValue=r.getI18nPathValue,exports.getLanguage=r.getLanguage,exports.groupBy=a.groupBy,exports.i18n=r.i18n,exports.i18nStore=r.i18nStore,exports.interpolateI18nMessage=r.interpolateI18nMessage,exports.isBlank=p.isBlank,exports.isBoolean=i.isBoolean,exports.isFunction=i.isFunction,exports.isNil=i.isNil,exports.isNonNullable=i.isNonNullable,exports.isNumber=i.isNumber,exports.isPlainI18nDictionary=r.isPlainI18nDictionary,exports.isPlainObject=i.isPlainObject,exports.isString=i.isString,exports.joinColorized=c.joinColorized,exports.joinStr=p.joinStr,exports.kebabCase=p.kebabCase,exports.languageLocalKey=n.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=r.mergeI18nDictionary,exports.mergeI18nResources=r.mergeI18nResources,exports.omit=d.omit,exports.pick=d.pick,exports.rafClearInterval=f.rafClearInterval,exports.rafClearTimeout=f.rafClearTimeout,exports.rafSetInterval=f.rafSetInterval,exports.rafSetTimeout=f.rafSetTimeout,exports.t=r.t,exports.toArray=a.toArray,exports.toFiniteNumber=l.toFiniteNumber,exports.translate=r.translate,exports.translations=n.translations,exports.uniqueBy=a.uniqueBy;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import e from "./base.js";
|
|
2
|
+
import { requestT as t } from "../utils/i18n.js";
|
|
2
3
|
//#region app/controller/project.ts
|
|
3
|
-
var
|
|
4
|
-
let
|
|
5
|
-
return class extends
|
|
4
|
+
var n = ((n) => {
|
|
5
|
+
let r = e(n);
|
|
6
|
+
return class extends r {
|
|
6
7
|
getModelList = async (e) => {
|
|
7
8
|
let t = (await this.service.project.getModelList()).reduce((e, t) => {
|
|
8
9
|
let { model: n, project: r } = t, { key: i, name: a, desc: o } = n, s = {
|
|
@@ -39,19 +40,19 @@ var t = ((t) => {
|
|
|
39
40
|
this.success(e, n);
|
|
40
41
|
};
|
|
41
42
|
getProject = async (e) => {
|
|
42
|
-
let { key:
|
|
43
|
-
if (!
|
|
44
|
-
this.fail(e, 10001, "
|
|
43
|
+
let { key: n } = e.params;
|
|
44
|
+
if (!n) {
|
|
45
|
+
this.fail(e, 10001, t(e, "server.errors.getProjectFailed"));
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
47
|
-
let
|
|
48
|
-
if (!
|
|
49
|
-
this.fail(e, 10001, "
|
|
48
|
+
let r = this.service.project.getProject(n);
|
|
49
|
+
if (!r) {
|
|
50
|
+
this.fail(e, 10001, t(e, "server.errors.getProjectFailed"));
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
|
-
this.success(e,
|
|
53
|
+
this.success(e, r);
|
|
53
54
|
};
|
|
54
55
|
};
|
|
55
56
|
});
|
|
56
57
|
//#endregion
|
|
57
|
-
export {
|
|
58
|
+
export { n as default };
|
package/esm/app/extends/db.js
CHANGED
|
@@ -1,141 +1,145 @@
|
|
|
1
1
|
import { __require as e } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { createI18nError as t } from "../utils/i18n.js";
|
|
3
|
+
import { mkdirSync as n } from "node:fs";
|
|
4
|
+
import { dirname as r, isAbsolute as i, resolve as a } from "node:path";
|
|
4
5
|
//#region app/extends/db.ts
|
|
5
|
-
var
|
|
6
|
-
function
|
|
7
|
-
let
|
|
8
|
-
dbPath:
|
|
6
|
+
var o = "framework", s = ".template-core/template-core.sqlite";
|
|
7
|
+
function c(e) {
|
|
8
|
+
let t = d(e), i, a = !1, o = 0, s = () => (S(a), i || (n(r(t), { recursive: !0 }), i = l(t), u(i)), i), c = {
|
|
9
|
+
dbPath: t,
|
|
9
10
|
getDBConnection: s,
|
|
10
11
|
execDB: (e) => {
|
|
11
12
|
s().exec(e);
|
|
12
13
|
},
|
|
13
14
|
runDB: (e, t) => {
|
|
14
|
-
let n = s().prepare(e).run(...
|
|
15
|
+
let n = s().prepare(e).run(...m(t));
|
|
15
16
|
return {
|
|
16
17
|
changes: Number(n.changes ?? 0),
|
|
17
18
|
lastInsertRowid: n.lastInsertRowid ?? 0
|
|
18
19
|
};
|
|
19
20
|
},
|
|
20
|
-
queryDB: (e, t) => s().prepare(e).all(...
|
|
21
|
-
getDBFirst: (e, t) => s().prepare(e).get(...
|
|
21
|
+
queryDB: (e, t) => s().prepare(e).all(...m(t)),
|
|
22
|
+
getDBFirst: (e, t) => s().prepare(e).get(...m(t)),
|
|
22
23
|
transactionDB: (e) => {
|
|
23
24
|
let t = s(), n = `tc_savepoint_${o}`, r = o === 0;
|
|
24
25
|
t.exec(r ? "BEGIN IMMEDIATE" : `SAVEPOINT ${n}`), o += 1;
|
|
25
26
|
try {
|
|
26
|
-
let i = e(
|
|
27
|
+
let i = e(c);
|
|
27
28
|
return --o, t.exec(r ? "COMMIT" : `RELEASE SAVEPOINT ${n}`), i;
|
|
28
29
|
} catch (e) {
|
|
29
30
|
throw --o, t.exec(r ? "ROLLBACK" : `ROLLBACK TO SAVEPOINT ${n}`), r || t.exec(`RELEASE SAVEPOINT ${n}`), e;
|
|
30
31
|
}
|
|
31
32
|
},
|
|
32
|
-
getDBData: (e, t) =>
|
|
33
|
+
getDBData: (e, t) => c.getDBDataRecord(e, t)?.value,
|
|
33
34
|
getDBDataRecord: (e, t) => {
|
|
34
|
-
let n =
|
|
35
|
-
return n ?
|
|
35
|
+
let n = c.getDBFirst("SELECT namespace, data_key, data_value, created_at, updated_at FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1", [h(t?.namespace), g(e)]);
|
|
36
|
+
return n ? x(n) : void 0;
|
|
36
37
|
},
|
|
37
38
|
setDBData: (e, t, n) => {
|
|
38
39
|
let r = (/* @__PURE__ */ new Date()).toISOString();
|
|
39
|
-
return
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
return c.runDB("INSERT INTO tc_framework_data (namespace, data_key, data_value, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(namespace, data_key) DO UPDATE SET\n data_value = excluded.data_value,\n updated_at = excluded.updated_at", [
|
|
41
|
+
h(n?.namespace),
|
|
42
|
+
g(e),
|
|
43
|
+
y(t),
|
|
43
44
|
r,
|
|
44
45
|
r
|
|
45
46
|
]);
|
|
46
47
|
},
|
|
47
|
-
hasDBData: (e, t) => !!
|
|
48
|
-
deleteDBData: (e, t) =>
|
|
48
|
+
hasDBData: (e, t) => !!c.getDBFirst("SELECT 1 AS exists_value FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1", [h(t?.namespace), g(e)]),
|
|
49
|
+
deleteDBData: (e, t) => c.runDB("DELETE FROM tc_framework_data WHERE namespace = ? AND data_key = ?", [h(t?.namespace), g(e)]).changes > 0,
|
|
49
50
|
listDBData: (e) => {
|
|
50
|
-
let t =
|
|
51
|
-
return
|
|
52
|
-
|
|
51
|
+
let t = _(e?.limit), n = v(e?.offset);
|
|
52
|
+
return c.queryDB("SELECT namespace, data_key, data_value, created_at, updated_at\n FROM tc_framework_data\n WHERE namespace = ?\n ORDER BY updated_at DESC, data_key ASC\n LIMIT ? OFFSET ?", [
|
|
53
|
+
h(e?.namespace),
|
|
53
54
|
t,
|
|
54
55
|
n
|
|
55
|
-
]).map((e) =>
|
|
56
|
+
]).map((e) => x(e));
|
|
56
57
|
},
|
|
57
58
|
countDBData: (e) => {
|
|
58
|
-
let t =
|
|
59
|
+
let t = c.getDBFirst("SELECT COUNT(1) AS count_value FROM tc_framework_data WHERE namespace = ?", [h(e?.namespace)]);
|
|
59
60
|
return Number(t?.count_value ?? 0);
|
|
60
61
|
},
|
|
61
|
-
clearDBData: (e) =>
|
|
62
|
+
clearDBData: (e) => c.runDB("DELETE FROM tc_framework_data WHERE namespace = ?", [h(e?.namespace)]).changes,
|
|
62
63
|
closeDB: () => {
|
|
63
64
|
a ||= (i?.close(), !0);
|
|
64
65
|
}
|
|
65
66
|
};
|
|
66
|
-
return
|
|
67
|
+
return c;
|
|
67
68
|
}
|
|
68
|
-
function
|
|
69
|
-
let
|
|
69
|
+
function l(n) {
|
|
70
|
+
let r = "node:sqlite", i;
|
|
70
71
|
try {
|
|
71
|
-
|
|
72
|
+
i = e(r);
|
|
72
73
|
} catch (e) {
|
|
73
|
-
throw
|
|
74
|
+
throw t("server.errors.dbNodeSqliteUnavailable", {
|
|
75
|
+
sqliteSpecifier: r,
|
|
76
|
+
cause: C(e)
|
|
77
|
+
});
|
|
74
78
|
}
|
|
75
|
-
if (!
|
|
76
|
-
return new
|
|
77
|
-
}
|
|
78
|
-
function l(e) {
|
|
79
|
-
e.exec("\n CREATE TABLE IF NOT EXISTS tc_framework_data (\n namespace TEXT NOT NULL,\n data_key TEXT NOT NULL,\n data_value TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (namespace, data_key)\n );\n CREATE INDEX IF NOT EXISTS idx_tc_framework_data_namespace_updated_at\n ON tc_framework_data (namespace, updated_at);\n ");
|
|
79
|
+
if (!i.DatabaseSync) throw t("server.errors.dbDatabaseSyncUnavailable", { sqliteSpecifier: r });
|
|
80
|
+
return new i.DatabaseSync(n);
|
|
80
81
|
}
|
|
81
82
|
function u(e) {
|
|
82
|
-
|
|
83
|
-
return n ? r(n) ? n : i(e.baseDir, n) : i(e.baseDir, o);
|
|
83
|
+
e.exec("\n CREATE TABLE IF NOT EXISTS tc_framework_data (\n namespace TEXT NOT NULL,\n data_key TEXT NOT NULL,\n data_value TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (namespace, data_key)\n );\n CREATE INDEX IF NOT EXISTS idx_tc_framework_data_namespace_updated_at\n ON tc_framework_data (namespace, updated_at);\n ");
|
|
84
84
|
}
|
|
85
85
|
function d(e) {
|
|
86
|
+
let t = f(e), n = typeof t == "string" ? t : t?.path ?? t?.filename ?? t?.sqlitePath ?? p(t?.sqlite);
|
|
87
|
+
return n ? i(n) ? n : a(e.baseDir, n) : a(e.baseDir, s);
|
|
88
|
+
}
|
|
89
|
+
function f(e) {
|
|
86
90
|
let t = e.config;
|
|
87
91
|
return t.db ?? (t.sqlite ? { sqlite: t.sqlite } : void 0);
|
|
88
92
|
}
|
|
89
|
-
function
|
|
93
|
+
function p(e) {
|
|
90
94
|
if (e) return typeof e == "string" ? e : e.path ?? e.filename;
|
|
91
95
|
}
|
|
92
|
-
function
|
|
96
|
+
function m(e) {
|
|
93
97
|
return e ? Array.isArray(e) ? e : [e] : [];
|
|
94
98
|
}
|
|
95
|
-
function
|
|
96
|
-
let
|
|
97
|
-
if (!
|
|
98
|
-
return
|
|
99
|
+
function h(e = o) {
|
|
100
|
+
let n = e.trim();
|
|
101
|
+
if (!n) throw t("server.errors.dbNamespaceRequired");
|
|
102
|
+
return n;
|
|
99
103
|
}
|
|
100
|
-
function
|
|
101
|
-
let
|
|
102
|
-
if (!
|
|
103
|
-
return
|
|
104
|
+
function g(e) {
|
|
105
|
+
let n = e.trim();
|
|
106
|
+
if (!n) throw t("server.errors.dbKeyRequired");
|
|
107
|
+
return n;
|
|
104
108
|
}
|
|
105
|
-
function
|
|
106
|
-
if (!Number.isSafeInteger(e) || e <= 0) throw
|
|
109
|
+
function _(e = 100) {
|
|
110
|
+
if (!Number.isSafeInteger(e) || e <= 0) throw t("server.errors.dbLimitInvalid");
|
|
107
111
|
return e;
|
|
108
112
|
}
|
|
109
|
-
function
|
|
110
|
-
if (!Number.isSafeInteger(e) || e < 0) throw
|
|
113
|
+
function v(e = 0) {
|
|
114
|
+
if (!Number.isSafeInteger(e) || e < 0) throw t("server.errors.dbOffsetInvalid");
|
|
111
115
|
return e;
|
|
112
116
|
}
|
|
113
|
-
function
|
|
117
|
+
function y(e) {
|
|
114
118
|
try {
|
|
115
119
|
let t = JSON.stringify(e);
|
|
116
120
|
if (t === void 0) throw Error("value is not JSON serializable");
|
|
117
121
|
return t;
|
|
118
122
|
} catch (e) {
|
|
119
|
-
throw
|
|
123
|
+
throw t("server.errors.dbValueNotSerializable", { cause: C(e) });
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
|
-
function
|
|
126
|
+
function b(e) {
|
|
123
127
|
return JSON.parse(e);
|
|
124
128
|
}
|
|
125
|
-
function
|
|
129
|
+
function x(e) {
|
|
126
130
|
return {
|
|
127
131
|
key: e.data_key,
|
|
128
|
-
value:
|
|
132
|
+
value: b(e.data_value),
|
|
129
133
|
namespace: e.namespace,
|
|
130
134
|
createdAt: e.created_at,
|
|
131
135
|
updatedAt: e.updated_at
|
|
132
136
|
};
|
|
133
137
|
}
|
|
134
|
-
function x(e) {
|
|
135
|
-
if (e) throw Error("[db] SQLite 数据库连接已关闭");
|
|
136
|
-
}
|
|
137
138
|
function S(e) {
|
|
139
|
+
if (e) throw t("server.errors.dbClosed");
|
|
140
|
+
}
|
|
141
|
+
function C(e) {
|
|
138
142
|
return e instanceof Error && e.message ? ` Cause: ${e.message}` : "";
|
|
139
143
|
}
|
|
140
144
|
//#endregion
|
|
141
|
-
export {
|
|
145
|
+
export { c as default };
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
+
import { getRequestErrorMessage as e, requestT as t } from "../utils/i18n.js";
|
|
1
2
|
//#region app/middlewares/error-handle.ts
|
|
2
|
-
var
|
|
3
|
+
var n = {}, r = (r) => async (i, a) => {
|
|
3
4
|
try {
|
|
4
|
-
await
|
|
5
|
-
} catch (
|
|
6
|
-
let { status:
|
|
7
|
-
if (
|
|
8
|
-
let
|
|
9
|
-
if (e
|
|
10
|
-
|
|
5
|
+
await a();
|
|
6
|
+
} catch (a) {
|
|
7
|
+
let o = a, { status: s = 200, message: c, detail: l, code: u = 5e4, returnError: d } = o, f = e(i, o, c);
|
|
8
|
+
if (r.extends.logger?.info(`error info -> ${JSON.stringify(a)}`), r.extends.logger?.error("-- [excption] --", a), r.extends.logger?.error("-- [excption] info --", s, c, l), c?.includes("template not found")) {
|
|
9
|
+
let e = i.path ?? i.req.url ?? i.url;
|
|
10
|
+
if (n[e] === void 0 ? n[e] = 0 : n[e] += 1, n[e] < r.config.notFoundRedirectCount) {
|
|
11
|
+
i.status = 302, i.redirect(r.options?.homePage ?? "/");
|
|
11
12
|
return;
|
|
12
|
-
} else e
|
|
13
|
+
} else n[e] = 0;
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
code:
|
|
16
|
-
message:
|
|
17
|
-
}) : (
|
|
15
|
+
d ? (i.status = s, i.body = {
|
|
16
|
+
code: u,
|
|
17
|
+
message: f
|
|
18
|
+
}) : (i.status = 200, i.body = {
|
|
18
19
|
code: 5e4,
|
|
19
|
-
message: "
|
|
20
|
+
message: t(i, "server.errors.network")
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
};
|
|
23
24
|
//#endregion
|
|
24
|
-
export {
|
|
25
|
+
export { r as default };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { requestT as e } from "../utils/i18n.js";
|
|
1
2
|
//#region app/middlewares/project-handler.ts
|
|
2
|
-
var
|
|
3
|
-
let
|
|
4
|
-
if (
|
|
5
|
-
|
|
3
|
+
var t = (t) => async (n, r) => {
|
|
4
|
+
let i = n.headers.projk, { path: a } = n;
|
|
5
|
+
if (a.indexOf(`${t.options.apiPrefix}/proj/`) !== -1 && (!i || ["undefined", "null"].includes(i))) {
|
|
6
|
+
n.status = 200, n.body = {
|
|
6
7
|
code: 110,
|
|
7
8
|
data: null,
|
|
8
|
-
message: "
|
|
9
|
+
message: e(n, "server.errors.invalidRequest")
|
|
9
10
|
};
|
|
10
11
|
return;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
n.extInfo = { key: i }, await r();
|
|
13
14
|
};
|
|
14
15
|
//#endregion
|
|
15
|
-
export {
|
|
16
|
+
export { t as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { i18n as e, i18nStore as t } from "../../packages/common/i18n/index.js";
|
|
2
|
+
//#region app/utils/i18n.ts
|
|
3
|
+
var n = "x-tc-language", r = "en-US", i = [
|
|
4
|
+
n,
|
|
5
|
+
"tc_language",
|
|
6
|
+
"tc-language",
|
|
7
|
+
"language",
|
|
8
|
+
"lang",
|
|
9
|
+
"locale"
|
|
10
|
+
], a = (e) => Array.isArray(e) ? e[0] : e, o = (e, t) => a(e[t.toLowerCase()]), s = (e) => e ? e.split(",").map((e) => e.trim().split(";")[0]?.trim()).filter((e) => !!e) : [], c = (e) => {
|
|
11
|
+
if (!e) return r;
|
|
12
|
+
let n = Object.keys(t.getState().resources), i = e.trim().toLowerCase(), a = n.find((e) => e.toLowerCase() === i);
|
|
13
|
+
if (a) return a;
|
|
14
|
+
let o = i.split("-")[0];
|
|
15
|
+
return n.find((e) => e.toLowerCase().split("-")[0] === o) ?? r;
|
|
16
|
+
}, l = (e) => {
|
|
17
|
+
for (let t of i) {
|
|
18
|
+
let n = o(e.headers, t);
|
|
19
|
+
if (n) return c(n);
|
|
20
|
+
}
|
|
21
|
+
let t = s(o(e.headers, "accept-language"));
|
|
22
|
+
for (let e of t) {
|
|
23
|
+
let t = c(e);
|
|
24
|
+
if (t) return t;
|
|
25
|
+
}
|
|
26
|
+
return r;
|
|
27
|
+
}, u = (t, n, i, a) => e(n, i, {
|
|
28
|
+
...a,
|
|
29
|
+
language: a?.language ?? l(t),
|
|
30
|
+
fallbackLanguage: a?.fallbackLanguage ?? r
|
|
31
|
+
}), d = (e, t, n) => {
|
|
32
|
+
let r = Error(n ?? e);
|
|
33
|
+
return r.i18nKey = e, r.i18nData = t, r;
|
|
34
|
+
}, f = (e, t, n) => t.i18nKey ? u(e, t.i18nKey, t.i18nData, { fallback: n ?? t.message }) : n ?? t.message;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { n as LANGUAGE_HEADER_KEY, d as createI18nError, f as getRequestErrorMessage, l as getRequestLanguage, c as normalizeI18nLanguage, u as requestT };
|
|
@@ -8,6 +8,19 @@ var e = {
|
|
|
8
8
|
submit: "提交",
|
|
9
9
|
reset: "重置"
|
|
10
10
|
},
|
|
11
|
+
server: { errors: {
|
|
12
|
+
network: "网络错误",
|
|
13
|
+
invalidRequest: "请求不合法",
|
|
14
|
+
getProjectFailed: "获取项目异常",
|
|
15
|
+
dbNodeSqliteUnavailable: "[db] 默认数据库依赖 Node.js 内置 {sqliteSpecifier},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。{cause}",
|
|
16
|
+
dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。",
|
|
17
|
+
dbNamespaceRequired: "[db] namespace 不能为空",
|
|
18
|
+
dbKeyRequired: "[db] key 不能为空",
|
|
19
|
+
dbLimitInvalid: "[db] limit 必须是大于 0 的整数",
|
|
20
|
+
dbOffsetInvalid: "[db] offset 必须是大于等于 0 的整数",
|
|
21
|
+
dbValueNotSerializable: "[db] value 必须可以被 JSON.stringify 序列化。{cause}",
|
|
22
|
+
dbClosed: "[db] SQLite 数据库连接已关闭"
|
|
23
|
+
} },
|
|
11
24
|
components: {
|
|
12
25
|
breadcrumb: { close: "关闭" },
|
|
13
26
|
confirmDialog: {
|
|
@@ -8,6 +8,19 @@ var e = {
|
|
|
8
8
|
submit: "Submit",
|
|
9
9
|
reset: "Reset"
|
|
10
10
|
},
|
|
11
|
+
server: { errors: {
|
|
12
|
+
network: "Network error",
|
|
13
|
+
invalidRequest: "Invalid request",
|
|
14
|
+
getProjectFailed: "Failed to get project",
|
|
15
|
+
dbNodeSqliteUnavailable: "[db] The default database depends on Node.js built-in {sqliteSpecifier}, which is unavailable in the current runtime. Upgrade Node.js or override app/extends/db.ts in the business project.{cause}",
|
|
16
|
+
dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} does not provide DatabaseSync, so the default SQLite database cannot be initialized.",
|
|
17
|
+
dbNamespaceRequired: "[db] namespace cannot be empty",
|
|
18
|
+
dbKeyRequired: "[db] key cannot be empty",
|
|
19
|
+
dbLimitInvalid: "[db] limit must be an integer greater than 0",
|
|
20
|
+
dbOffsetInvalid: "[db] offset must be an integer greater than or equal to 0",
|
|
21
|
+
dbValueNotSerializable: "[db] value must be serializable by JSON.stringify.{cause}",
|
|
22
|
+
dbClosed: "[db] SQLite database connection is closed"
|
|
23
|
+
} },
|
|
11
24
|
components: {
|
|
12
25
|
breadcrumb: { close: "Close" },
|
|
13
26
|
confirmDialog: {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
1
|
+
import { defaultLanguageResources as e } from "./i18n/default.js";
|
|
2
|
+
import { defaultEnglishResources as t } from "./i18n/en-US.js";
|
|
3
|
+
import { defaultLanguage as n, languageLocalKey as r, translations as i } from "./i18n/locales.js";
|
|
4
|
+
import { getI18nPathValue as a, getLanguage as o, i18n as s, i18nStore as c, interpolateI18nMessage as l, isPlainI18nDictionary as u, mergeI18nDictionary as d, mergeI18nResources as f, t as p, translate as m } from "./i18n/index.js";
|
|
5
|
+
import { isBoolean as h, isFunction as g, isNil as _, isNonNullable as v, isNumber as y, isPlainObject as b, isString as x } from "./guards/index.js";
|
|
6
|
+
import { chunk as S, compact as C, groupBy as w, toArray as T, uniqueBy as E } from "./array/index.js";
|
|
7
|
+
import { LRUCache as D } from "./cache/LRUCache.js";
|
|
8
|
+
import { FetchAxios as O, axios as k, createInstance as A } from "./http/index.js";
|
|
9
9
|
import { ANSI_RESET as j, ansiColors as M, colorLog as N, colorize as P, joinColorized as F, logColor as I, logColorized as L, logGreen as R, logJoinColorized as z, logPink as B, logRed as V, logWhite as H, logYellow as U } from "./log/index.js";
|
|
10
10
|
import { clamp as W, toFiniteNumber as G } from "./number/index.js";
|
|
11
11
|
import { filterEmpty as K, filtereEmpty as q } from "./object/filterEmpty.js";
|
|
12
12
|
import { mapValues as J, omit as Y, pick as X } from "./object/index.js";
|
|
13
13
|
import { clearRafTimer as Z, rafClearInterval as Q, rafClearTimeout as $, rafSetInterval as ee, rafSetTimeout as te } from "./rafTimer.js";
|
|
14
14
|
import { capitalize as ne, isBlank as re, joinStr as ie, kebabCase as ae } from "./string/index.js";
|
|
15
|
-
export { j as ANSI_RESET,
|
|
15
|
+
export { j as ANSI_RESET, O as FetchAxios, D as LRUCache, M as ansiColors, k as axios, ne as capitalize, S as chunk, W as clamp, Z as clearRafTimer, N as colorLog, P as colorize, C as compact, A as createInstance, t as defaultEnglishResources, n as defaultLanguage, e as defaultLanguageResources, K as filterEmpty, q as filtereEmpty, a as getI18nPathValue, o as getLanguage, w as groupBy, s as i18n, c as i18nStore, l as interpolateI18nMessage, re as isBlank, h as isBoolean, g as isFunction, _ as isNil, v as isNonNullable, y as isNumber, u as isPlainI18nDictionary, b as isPlainObject, x as isString, F as joinColorized, ie as joinStr, ae as kebabCase, r as languageLocalKey, I as logColor, L as logColorized, R as logGreen, z as logJoinColorized, B as logPink, V as logRed, H as logWhite, U as logYellow, J as mapValues, d as mergeI18nDictionary, f as mergeI18nResources, Y as omit, X as pick, Q as rafClearInterval, $ as rafClearTimeout, ee as rafSetInterval, te as rafSetTimeout, p as t, T as toArray, G as toFiniteNumber, m as translate, i as translations, E as uniqueBy };
|
|
@@ -25,8 +25,8 @@ var registerFrontendI18nResources = async (resources) => {
|
|
|
25
25
|
});
|
|
26
26
|
};
|
|
27
27
|
var getText = (key, fillingData, options) => {
|
|
28
|
-
if (key.
|
|
29
|
-
return key;
|
|
28
|
+
if (key.startsWith("$i18n::")) return i18n(key.slice(i18nKeyPrefix.length), fillingData, options);
|
|
29
|
+
return i18n(key, fillingData, options);
|
|
30
30
|
};
|
|
31
31
|
var t = i18n;
|
|
32
32
|
//#endregion
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { API_AUTH_HEADER_KEY, AUTH_HEADER_KEY, clearAuthToken, getApiAuth, getAuthToken } from "./auth/index.js";
|
|
2
2
|
import { frontendLangKeys } from "../language/index.js";
|
|
3
|
-
import { getText } from "./language.js";
|
|
3
|
+
import { getCurrentLanguage, getText } from "./language.js";
|
|
4
4
|
import { FreezeState, apiFreezerStore } from "../stores/apiFreezer.js";
|
|
5
5
|
import FetchAxios from "../../../packages/common/http/index.js";
|
|
6
6
|
import md5 from "md5";
|
|
7
7
|
//#region frontend/src/common/request.ts
|
|
8
|
+
var LANGUAGE_HEADER_KEY = "x-tc-language";
|
|
8
9
|
var BASE_URL = "/api";
|
|
9
10
|
var NumberConcurrentCalls = 4;
|
|
10
11
|
var isRequestWhitelisted = (api, params) => {
|
|
@@ -102,6 +103,7 @@ api.interceptors.request.use(async (config) => {
|
|
|
102
103
|
config.headers = {
|
|
103
104
|
"Content-Type": "application/json",
|
|
104
105
|
...config.headers,
|
|
106
|
+
[LANGUAGE_HEADER_KEY]: getCurrentLanguage(),
|
|
105
107
|
s_t: time + "",
|
|
106
108
|
s_sign: md5(`${window["_signKey"]}_${time}`),
|
|
107
109
|
[API_AUTH_HEADER_KEY]: aauto
|
|
@@ -6,8 +6,8 @@ import { useCallback } from "react";
|
|
|
6
6
|
var useText = () => {
|
|
7
7
|
const translate = useI18n();
|
|
8
8
|
return useCallback((key, fillingData, options) => {
|
|
9
|
-
if (key.
|
|
10
|
-
return key;
|
|
9
|
+
if (key.startsWith("$i18n::")) return translate(key.slice(i18nKeyPrefix.length), fillingData, options);
|
|
10
|
+
return translate(key, fillingData, options);
|
|
11
11
|
}, [translate]);
|
|
12
12
|
};
|
|
13
13
|
//#endregion
|
|
@@ -7,6 +7,21 @@ export declare const defaultLanguageResources: {
|
|
|
7
7
|
readonly submit: "提交";
|
|
8
8
|
readonly reset: "重置";
|
|
9
9
|
};
|
|
10
|
+
readonly server: {
|
|
11
|
+
readonly errors: {
|
|
12
|
+
readonly network: "网络错误";
|
|
13
|
+
readonly invalidRequest: "请求不合法";
|
|
14
|
+
readonly getProjectFailed: "获取项目异常";
|
|
15
|
+
readonly dbNodeSqliteUnavailable: "[db] 默认数据库依赖 Node.js 内置 {sqliteSpecifier},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。{cause}";
|
|
16
|
+
readonly dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。";
|
|
17
|
+
readonly dbNamespaceRequired: "[db] namespace 不能为空";
|
|
18
|
+
readonly dbKeyRequired: "[db] key 不能为空";
|
|
19
|
+
readonly dbLimitInvalid: "[db] limit 必须是大于 0 的整数";
|
|
20
|
+
readonly dbOffsetInvalid: "[db] offset 必须是大于等于 0 的整数";
|
|
21
|
+
readonly dbValueNotSerializable: "[db] value 必须可以被 JSON.stringify 序列化。{cause}";
|
|
22
|
+
readonly dbClosed: "[db] SQLite 数据库连接已关闭";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
10
25
|
readonly components: {
|
|
11
26
|
readonly breadcrumb: {
|
|
12
27
|
readonly close: "关闭";
|
|
@@ -14,6 +14,19 @@ var defaultLanguageResources = {
|
|
|
14
14
|
submit: "提交",
|
|
15
15
|
reset: "重置"
|
|
16
16
|
},
|
|
17
|
+
server: { errors: {
|
|
18
|
+
network: "网络错误",
|
|
19
|
+
invalidRequest: "请求不合法",
|
|
20
|
+
getProjectFailed: "获取项目异常",
|
|
21
|
+
dbNodeSqliteUnavailable: "[db] 默认数据库依赖 Node.js 内置 {sqliteSpecifier},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。{cause}",
|
|
22
|
+
dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。",
|
|
23
|
+
dbNamespaceRequired: "[db] namespace 不能为空",
|
|
24
|
+
dbKeyRequired: "[db] key 不能为空",
|
|
25
|
+
dbLimitInvalid: "[db] limit 必须是大于 0 的整数",
|
|
26
|
+
dbOffsetInvalid: "[db] offset 必须是大于等于 0 的整数",
|
|
27
|
+
dbValueNotSerializable: "[db] value 必须可以被 JSON.stringify 序列化。{cause}",
|
|
28
|
+
dbClosed: "[db] SQLite 数据库连接已关闭"
|
|
29
|
+
} },
|
|
17
30
|
/** UI 组件内置文案,按组件名分组。 */
|
|
18
31
|
components: {
|
|
19
32
|
breadcrumb: { close: "关闭" },
|
|
@@ -7,6 +7,21 @@ export declare const defaultEnglishResources: {
|
|
|
7
7
|
readonly submit: "Submit";
|
|
8
8
|
readonly reset: "Reset";
|
|
9
9
|
};
|
|
10
|
+
readonly server: {
|
|
11
|
+
readonly errors: {
|
|
12
|
+
readonly network: "Network error";
|
|
13
|
+
readonly invalidRequest: "Invalid request";
|
|
14
|
+
readonly getProjectFailed: "Failed to get project";
|
|
15
|
+
readonly dbNodeSqliteUnavailable: "[db] The default database depends on Node.js built-in {sqliteSpecifier}, which is unavailable in the current runtime. Upgrade Node.js or override app/extends/db.ts in the business project.{cause}";
|
|
16
|
+
readonly dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} does not provide DatabaseSync, so the default SQLite database cannot be initialized.";
|
|
17
|
+
readonly dbNamespaceRequired: "[db] namespace cannot be empty";
|
|
18
|
+
readonly dbKeyRequired: "[db] key cannot be empty";
|
|
19
|
+
readonly dbLimitInvalid: "[db] limit must be an integer greater than 0";
|
|
20
|
+
readonly dbOffsetInvalid: "[db] offset must be an integer greater than or equal to 0";
|
|
21
|
+
readonly dbValueNotSerializable: "[db] value must be serializable by JSON.stringify.{cause}";
|
|
22
|
+
readonly dbClosed: "[db] SQLite database connection is closed";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
10
25
|
readonly components: {
|
|
11
26
|
readonly breadcrumb: {
|
|
12
27
|
readonly close: "Close";
|
|
@@ -14,6 +14,19 @@ var defaultEnglishResources = {
|
|
|
14
14
|
submit: "Submit",
|
|
15
15
|
reset: "Reset"
|
|
16
16
|
},
|
|
17
|
+
server: { errors: {
|
|
18
|
+
network: "Network error",
|
|
19
|
+
invalidRequest: "Invalid request",
|
|
20
|
+
getProjectFailed: "Failed to get project",
|
|
21
|
+
dbNodeSqliteUnavailable: "[db] The default database depends on Node.js built-in {sqliteSpecifier}, which is unavailable in the current runtime. Upgrade Node.js or override app/extends/db.ts in the business project.{cause}",
|
|
22
|
+
dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} does not provide DatabaseSync, so the default SQLite database cannot be initialized.",
|
|
23
|
+
dbNamespaceRequired: "[db] namespace cannot be empty",
|
|
24
|
+
dbKeyRequired: "[db] key cannot be empty",
|
|
25
|
+
dbLimitInvalid: "[db] limit must be an integer greater than 0",
|
|
26
|
+
dbOffsetInvalid: "[db] offset must be an integer greater than or equal to 0",
|
|
27
|
+
dbValueNotSerializable: "[db] value must be serializable by JSON.stringify.{cause}",
|
|
28
|
+
dbClosed: "[db] SQLite database connection is closed"
|
|
29
|
+
} },
|
|
17
30
|
/** UI 组件内置文案,按组件名分组。 */
|
|
18
31
|
components: {
|
|
19
32
|
breadcrumb: { close: "Close" },
|
|
@@ -7,6 +7,21 @@ export declare const defaultLanguageResources: {
|
|
|
7
7
|
readonly submit: "提交";
|
|
8
8
|
readonly reset: "重置";
|
|
9
9
|
};
|
|
10
|
+
readonly server: {
|
|
11
|
+
readonly errors: {
|
|
12
|
+
readonly network: "网络错误";
|
|
13
|
+
readonly invalidRequest: "请求不合法";
|
|
14
|
+
readonly getProjectFailed: "获取项目异常";
|
|
15
|
+
readonly dbNodeSqliteUnavailable: "[db] 默认数据库依赖 Node.js 内置 {sqliteSpecifier},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。{cause}";
|
|
16
|
+
readonly dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。";
|
|
17
|
+
readonly dbNamespaceRequired: "[db] namespace 不能为空";
|
|
18
|
+
readonly dbKeyRequired: "[db] key 不能为空";
|
|
19
|
+
readonly dbLimitInvalid: "[db] limit 必须是大于 0 的整数";
|
|
20
|
+
readonly dbOffsetInvalid: "[db] offset 必须是大于等于 0 的整数";
|
|
21
|
+
readonly dbValueNotSerializable: "[db] value 必须可以被 JSON.stringify 序列化。{cause}";
|
|
22
|
+
readonly dbClosed: "[db] SQLite 数据库连接已关闭";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
10
25
|
readonly components: {
|
|
11
26
|
readonly breadcrumb: {
|
|
12
27
|
readonly close: "关闭";
|
|
@@ -7,6 +7,21 @@ export declare const defaultEnglishResources: {
|
|
|
7
7
|
readonly submit: "Submit";
|
|
8
8
|
readonly reset: "Reset";
|
|
9
9
|
};
|
|
10
|
+
readonly server: {
|
|
11
|
+
readonly errors: {
|
|
12
|
+
readonly network: "Network error";
|
|
13
|
+
readonly invalidRequest: "Invalid request";
|
|
14
|
+
readonly getProjectFailed: "Failed to get project";
|
|
15
|
+
readonly dbNodeSqliteUnavailable: "[db] The default database depends on Node.js built-in {sqliteSpecifier}, which is unavailable in the current runtime. Upgrade Node.js or override app/extends/db.ts in the business project.{cause}";
|
|
16
|
+
readonly dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} does not provide DatabaseSync, so the default SQLite database cannot be initialized.";
|
|
17
|
+
readonly dbNamespaceRequired: "[db] namespace cannot be empty";
|
|
18
|
+
readonly dbKeyRequired: "[db] key cannot be empty";
|
|
19
|
+
readonly dbLimitInvalid: "[db] limit must be an integer greater than 0";
|
|
20
|
+
readonly dbOffsetInvalid: "[db] offset must be an integer greater than or equal to 0";
|
|
21
|
+
readonly dbValueNotSerializable: "[db] value must be serializable by JSON.stringify.{cause}";
|
|
22
|
+
readonly dbClosed: "[db] SQLite database connection is closed";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
10
25
|
readonly components: {
|
|
11
26
|
readonly breadcrumb: {
|
|
12
27
|
readonly close: "Close";
|
package/package.json
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { I18nInterpolationValues, I18nTranslateOptions } from "../../packages/common/i18n/index";
|
|
2
|
+
import type { Ctx } from "../type";
|
|
3
|
+
export declare const LANGUAGE_HEADER_KEY = "x-tc-language";
|
|
4
|
+
export interface RequestI18nError extends Error {
|
|
5
|
+
i18nKey?: string;
|
|
6
|
+
i18nData?: I18nInterpolationValues;
|
|
7
|
+
}
|
|
8
|
+
export declare const normalizeI18nLanguage: (language: string | undefined) => string;
|
|
9
|
+
export declare const getRequestLanguage: (ctx: Pick<Ctx, "headers">) => string;
|
|
10
|
+
export declare const requestT: <T = string>(ctx: Pick<Ctx, "headers">, key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string | T;
|
|
11
|
+
export declare const createI18nError: (key: string, fillingData?: I18nInterpolationValues, fallbackMessage?: string) => RequestI18nError;
|
|
12
|
+
export declare const getRequestErrorMessage: (ctx: Pick<Ctx, "headers">, error: RequestI18nError, fallbackMessage?: string) => string;
|
|
@@ -13,6 +13,21 @@ export declare const defaultLanguageResources: {
|
|
|
13
13
|
readonly submit: "提交";
|
|
14
14
|
readonly reset: "重置";
|
|
15
15
|
};
|
|
16
|
+
readonly server: {
|
|
17
|
+
readonly errors: {
|
|
18
|
+
readonly network: "网络错误";
|
|
19
|
+
readonly invalidRequest: "请求不合法";
|
|
20
|
+
readonly getProjectFailed: "获取项目异常";
|
|
21
|
+
readonly dbNodeSqliteUnavailable: "[db] 默认数据库依赖 Node.js 内置 {sqliteSpecifier},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。{cause}";
|
|
22
|
+
readonly dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。";
|
|
23
|
+
readonly dbNamespaceRequired: "[db] namespace 不能为空";
|
|
24
|
+
readonly dbKeyRequired: "[db] key 不能为空";
|
|
25
|
+
readonly dbLimitInvalid: "[db] limit 必须是大于 0 的整数";
|
|
26
|
+
readonly dbOffsetInvalid: "[db] offset 必须是大于等于 0 的整数";
|
|
27
|
+
readonly dbValueNotSerializable: "[db] value 必须可以被 JSON.stringify 序列化。{cause}";
|
|
28
|
+
readonly dbClosed: "[db] SQLite 数据库连接已关闭";
|
|
29
|
+
};
|
|
30
|
+
};
|
|
16
31
|
/** UI 组件内置文案,按组件名分组。 */
|
|
17
32
|
readonly components: {
|
|
18
33
|
readonly breadcrumb: {
|
|
@@ -13,6 +13,21 @@ export declare const defaultEnglishResources: {
|
|
|
13
13
|
readonly submit: "Submit";
|
|
14
14
|
readonly reset: "Reset";
|
|
15
15
|
};
|
|
16
|
+
readonly server: {
|
|
17
|
+
readonly errors: {
|
|
18
|
+
readonly network: "Network error";
|
|
19
|
+
readonly invalidRequest: "Invalid request";
|
|
20
|
+
readonly getProjectFailed: "Failed to get project";
|
|
21
|
+
readonly dbNodeSqliteUnavailable: "[db] The default database depends on Node.js built-in {sqliteSpecifier}, which is unavailable in the current runtime. Upgrade Node.js or override app/extends/db.ts in the business project.{cause}";
|
|
22
|
+
readonly dbDatabaseSyncUnavailable: "[db] {sqliteSpecifier} does not provide DatabaseSync, so the default SQLite database cannot be initialized.";
|
|
23
|
+
readonly dbNamespaceRequired: "[db] namespace cannot be empty";
|
|
24
|
+
readonly dbKeyRequired: "[db] key cannot be empty";
|
|
25
|
+
readonly dbLimitInvalid: "[db] limit must be an integer greater than 0";
|
|
26
|
+
readonly dbOffsetInvalid: "[db] offset must be an integer greater than or equal to 0";
|
|
27
|
+
readonly dbValueNotSerializable: "[db] value must be serializable by JSON.stringify.{cause}";
|
|
28
|
+
readonly dbClosed: "[db] SQLite database connection is closed";
|
|
29
|
+
};
|
|
30
|
+
};
|
|
16
31
|
/** UI 组件内置文案,按组件名分组。 */
|
|
17
32
|
readonly components: {
|
|
18
33
|
readonly breadcrumb: {
|