@_tc/template-core 0.2.0-bate.11 → 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/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 参数说明
@@ -1 +1 @@
1
- const e=require(`./base.js`);var t=(t=>{let n=e(t);return class extends n{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:t}=e.params;if(!t){this.fail(e,10001,`获取项目异常`);return}let n=this.service.project.getProject(t);if(!n){this.fail(e,10001,`获取项目异常`);return}this.success(e,n)}}});module.exports=t;
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;
@@ -1,12 +1,12 @@
1
- require(`../../_virtual/_rolldown/runtime.js`);let e=require(`node:fs`),t=require(`node:path`);var n=`framework`,r=`.template-core/template-core.sqlite`;function i(n){let r=s(n),i,c=!1,l=0,g=()=>(v(c),i||((0,e.mkdirSync)((0,t.dirname)(r),{recursive:!0}),i=a(r),o(i)),i),y={dbPath:r,getDBConnection:g,execDB:e=>{g().exec(e)},runDB:(e,t)=>{let n=g().prepare(e).run(...u(t));return{changes:Number(n.changes??0),lastInsertRowid:n.lastInsertRowid??0}},queryDB:(e,t)=>g().prepare(e).all(...u(t)),getDBFirst:(e,t)=>g().prepare(e).get(...u(t)),transactionDB:e=>{let t=g(),n=`tc_savepoint_${l}`,r=l===0;t.exec(r?`BEGIN IMMEDIATE`:`SAVEPOINT ${n}`),l+=1;try{let i=e(y);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)=>y.getDBDataRecord(e,t)?.value,getDBDataRecord:(e,t)=>{let n=y.getDBFirst(`SELECT namespace, data_key, data_value, created_at, updated_at FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1`,[d(t?.namespace),f(e)]);return n?_(n):void 0},setDBData:(e,t,n)=>{let r=new Date().toISOString();return y.runDB(`INSERT INTO tc_framework_data (namespace, data_key, data_value, created_at, updated_at)
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`,[d(n?.namespace),f(e),h(t),r,r])},hasDBData:(e,t)=>!!y.getDBFirst(`SELECT 1 AS exists_value FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1`,[d(t?.namespace),f(e)]),deleteDBData:(e,t)=>y.runDB(`DELETE FROM tc_framework_data WHERE namespace = ? AND data_key = ?`,[d(t?.namespace),f(e)]).changes>0,listDBData:e=>{let t=p(e?.limit),n=m(e?.offset);return y.queryDB(`SELECT namespace, data_key, data_value, created_at, 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 ?`,[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(`
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 s(e){let n=c(e),i=typeof n==`string`?n:n?.path??n?.filename??n?.sqlitePath??l(n?.sqlite);return i?(0,t.isAbsolute)(i)?i:(0,t.resolve)(e.baseDir,i):(0,t.resolve)(e.baseDir,r)}function c(e){let t=e.config;return t.db??(t.sqlite?{sqlite:t.sqlite}:void 0)}function l(e){if(e)return typeof e==`string`?e:e.path??e.filename}function u(e){return e?Array.isArray(e)?e:[e]:[]}function d(e=n){let t=e.trim();if(!t)throw Error(`[db] namespace 不能为空`);return t}function f(e){let t=e.trim();if(!t)throw Error(`[db] key 不能为空`);return t}function p(e=100){if(!Number.isSafeInteger(e)||e<=0)throw Error(`[db] limit 必须是大于 0 的整数`);return e}function m(e=0){if(!Number.isSafeInteger(e)||e<0)throw Error(`[db] offset 必须是大于等于 0 的整数`);return e}function h(e){try{let t=JSON.stringify(e);if(t===void 0)throw Error(`value is not JSON serializable`);return t}catch(e){throw Error(`[db] value 必须可以被 JSON.stringify 序列化。${y(e)}`)}}function g(e){return JSON.parse(e)}function _(e){return{key:e.data_key,value:g(e.data_value),namespace:e.namespace,createdAt:e.created_at,updatedAt:e.updated_at}}function v(e){if(e)throw Error(`[db] SQLite 数据库连接已关闭`)}function y(e){return e instanceof Error&&e.message?` Cause: ${e.message}`:``}module.exports=i;
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
- var e={},t=t=>async(n,r)=>{try{await r()}catch(r){let{status:i=200,message:a,detail:o,code:s=5e4,returnError:c}=r;if(t.extends.logger?.info(`error info -> ${JSON.stringify(r)}`),t.extends.logger?.error(`-- [excption] --`,r),t.extends.logger?.error(`-- [excption] info --`,i,a,o),a?.includes(`template not found`)){let r=n.path??n.req.url??n.url;if(e[r]===void 0?e[r]=0:e[r]+=1,e[r]<t.config.notFoundRedirectCount){n.status=302,n.redirect(t.options?.homePage??`/`);return}else e[r]=0}c?(n.status=i,n.body={code:s,message:a}):(n.status=200,n.body={code:5e4,message:`网络错误`})}};module.exports=t;
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
- var e=e=>async(t,n)=>{let r=t.headers.projk,{path:i}=t;if(i.indexOf(`${e.options.apiPrefix}/proj/`)!==-1&&(!r||[`undefined`,`null`].includes(r))){t.status=200,t.body={code:110,data:null,message:`请求不合法`};return}t.extInfo={key:r},await n()};module.exports=e;
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(`./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(`./rafTimer.js`),p=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=p.capitalize,exports.chunk=t.chunk,exports.clamp=l.clamp,exports.clearRafTimer=f.clearRafTimer,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=p.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=p.joinStr,exports.kebabCase=p.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.rafClearInterval=f.rafClearInterval,exports.rafClearTimeout=f.rafClearTimeout,exports.rafSetInterval=f.rafSetInterval,exports.rafSetTimeout=f.rafSetTimeout,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
+ 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 t = ((t) => {
4
- let n = e(t);
5
- return class extends n {
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: t } = e.params;
43
- if (!t) {
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 n = this.service.project.getProject(t);
48
- if (!n) {
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, n);
53
+ this.success(e, r);
53
54
  };
54
55
  };
55
56
  });
56
57
  //#endregion
57
- export { t as default };
58
+ export { n as default };
@@ -1,141 +1,145 @@
1
1
  import { __require as e } from "../../_virtual/_rolldown/runtime.js";
2
- import { mkdirSync as t } from "node:fs";
3
- import { dirname as n, isAbsolute as r, resolve as i } from "node:path";
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 a = "framework", o = ".template-core/template-core.sqlite";
6
- function s(e) {
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 = {
8
- dbPath: r,
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(...p(t));
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(...p(t)),
21
- getDBFirst: (e, t) => s().prepare(e).get(...p(t)),
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(d);
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) => d.getDBDataRecord(e, t)?.value,
33
+ getDBData: (e, t) => c.getDBDataRecord(e, t)?.value,
33
34
  getDBDataRecord: (e, t) => {
34
- let n = d.getDBFirst("SELECT namespace, data_key, data_value, created_at, updated_at FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1", [m(t?.namespace), h(e)]);
35
- return n ? b(n) : void 0;
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 d.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", [
40
- m(n?.namespace),
41
- h(e),
42
- v(t),
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) => !!d.getDBFirst("SELECT 1 AS exists_value FROM tc_framework_data WHERE namespace = ? AND data_key = ? LIMIT 1", [m(t?.namespace), h(e)]),
48
- deleteDBData: (e, t) => d.runDB("DELETE FROM tc_framework_data WHERE namespace = ? AND data_key = ?", [m(t?.namespace), h(e)]).changes > 0,
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 = g(e?.limit), n = _(e?.offset);
51
- return d.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 ?", [
52
- m(e?.namespace),
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) => b(e));
56
+ ]).map((e) => x(e));
56
57
  },
57
58
  countDBData: (e) => {
58
- let t = d.getDBFirst("SELECT COUNT(1) AS count_value FROM tc_framework_data WHERE namespace = ?", [m(e?.namespace)]);
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) => d.runDB("DELETE FROM tc_framework_data WHERE namespace = ?", [m(e?.namespace)]).changes,
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 d;
67
+ return c;
67
68
  }
68
- function c(t) {
69
- let n = "node:sqlite", r;
69
+ function l(n) {
70
+ let r = "node:sqlite", i;
70
71
  try {
71
- r = e(n);
72
+ i = e(r);
72
73
  } catch (e) {
73
- throw Error(`[db] 默认数据库依赖 Node.js 内置 ${n},当前运行环境不可用。请升级 Node.js,或在业务项目覆盖 app/extends/db.ts。${S(e)}`);
74
+ throw t("server.errors.dbNodeSqliteUnavailable", {
75
+ sqliteSpecifier: r,
76
+ cause: C(e)
77
+ });
74
78
  }
75
- if (!r.DatabaseSync) throw Error(`[db] ${n} 未提供 DatabaseSync,无法初始化默认 SQLite 数据库。`);
76
- return new r.DatabaseSync(t);
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
- let t = d(e), n = typeof t == "string" ? t : t?.path ?? t?.filename ?? t?.sqlitePath ?? f(t?.sqlite);
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 f(e) {
93
+ function p(e) {
90
94
  if (e) return typeof e == "string" ? e : e.path ?? e.filename;
91
95
  }
92
- function p(e) {
96
+ function m(e) {
93
97
  return e ? Array.isArray(e) ? e : [e] : [];
94
98
  }
95
- function m(e = a) {
96
- let t = e.trim();
97
- if (!t) throw Error("[db] namespace 不能为空");
98
- return t;
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 h(e) {
101
- let t = e.trim();
102
- if (!t) throw Error("[db] key 不能为空");
103
- return t;
104
+ function g(e) {
105
+ let n = e.trim();
106
+ if (!n) throw t("server.errors.dbKeyRequired");
107
+ return n;
104
108
  }
105
- function g(e = 100) {
106
- if (!Number.isSafeInteger(e) || e <= 0) throw Error("[db] limit 必须是大于 0 的整数");
109
+ function _(e = 100) {
110
+ if (!Number.isSafeInteger(e) || e <= 0) throw t("server.errors.dbLimitInvalid");
107
111
  return e;
108
112
  }
109
- function _(e = 0) {
110
- if (!Number.isSafeInteger(e) || e < 0) throw Error("[db] offset 必须是大于等于 0 的整数");
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 v(e) {
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 Error(`[db] value 必须可以被 JSON.stringify 序列化。${S(e)}`);
123
+ throw t("server.errors.dbValueNotSerializable", { cause: C(e) });
120
124
  }
121
125
  }
122
- function y(e) {
126
+ function b(e) {
123
127
  return JSON.parse(e);
124
128
  }
125
- function b(e) {
129
+ function x(e) {
126
130
  return {
127
131
  key: e.data_key,
128
- value: y(e.data_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 { s as default };
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 e = {}, t = (t) => async (n, r) => {
3
+ var n = {}, r = (r) => async (i, a) => {
3
4
  try {
4
- await r();
5
- } catch (r) {
6
- let { status: i = 200, message: a, detail: o, code: s = 5e4, returnError: c } = r;
7
- if (t.extends.logger?.info(`error info -> ${JSON.stringify(r)}`), t.extends.logger?.error("-- [excption] --", r), t.extends.logger?.error("-- [excption] info --", i, a, o), a?.includes("template not found")) {
8
- let r = n.path ?? n.req.url ?? n.url;
9
- if (e[r] === void 0 ? e[r] = 0 : e[r] += 1, e[r] < t.config.notFoundRedirectCount) {
10
- n.status = 302, n.redirect(t.options?.homePage ?? "/");
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[r] = 0;
13
+ } else n[e] = 0;
13
14
  }
14
- c ? (n.status = i, n.body = {
15
- code: s,
16
- message: a
17
- }) : (n.status = 200, n.body = {
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 { t as default };
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 e = (e) => async (t, n) => {
3
- let r = t.headers.projk, { path: i } = t;
4
- if (i.indexOf(`${e.options.apiPrefix}/proj/`) !== -1 && (!r || ["undefined", "null"].includes(r))) {
5
- t.status = 200, t.body = {
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
- t.extInfo = { key: r }, await n();
13
+ n.extInfo = { key: i }, await r();
13
14
  };
14
15
  //#endregion
15
- export { e as default };
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 { isBoolean as e, isFunction as t, isNil as n, isNonNullable as r, isNumber as i, isPlainObject as a, isString as o } from "./guards/index.js";
2
- import { chunk as s, compact as c, groupBy as l, toArray as u, uniqueBy as d } from "./array/index.js";
3
- import { LRUCache as f } from "./cache/LRUCache.js";
4
- import { FetchAxios as p, axios as m, createInstance as h } from "./http/index.js";
5
- import { defaultLanguageResources as g } from "./i18n/default.js";
6
- import { defaultEnglishResources as _ } from "./i18n/en-US.js";
7
- import { defaultLanguage as v, languageLocalKey as y, translations as b } from "./i18n/locales.js";
8
- import { getI18nPathValue as x, getLanguage as S, i18n as C, i18nStore as w, interpolateI18nMessage as T, isPlainI18nDictionary as E, mergeI18nDictionary as D, mergeI18nResources as O, t as k, translate as A } from "./i18n/index.js";
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, p as FetchAxios, f as LRUCache, M as ansiColors, m as axios, ne as capitalize, s as chunk, W as clamp, Z as clearRafTimer, N as colorLog, P as colorize, c as compact, h as createInstance, _ as defaultEnglishResources, v as defaultLanguage, g as defaultLanguageResources, K as filterEmpty, q as filtereEmpty, x as getI18nPathValue, S as getLanguage, l as groupBy, C as i18n, w as i18nStore, T as interpolateI18nMessage, re as isBlank, e as isBoolean, t as isFunction, n as isNil, r as isNonNullable, i as isNumber, E as isPlainI18nDictionary, a as isPlainObject, o as isString, F as joinColorized, ie as joinStr, ae as kebabCase, y 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, O as mergeI18nResources, Y as omit, X as pick, Q as rafClearInterval, $ as rafClearTimeout, ee as rafSetInterval, te as rafSetTimeout, k as t, u as toArray, G as toFiniteNumber, A as translate, b as translations, d as uniqueBy };
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 };
@@ -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
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_tc/template-core",
3
- "version": "0.2.0-bate.11",
3
+ "version": "0.2.0-bate.12",
4
4
  "description": "A full-stack TypeScript admin framework powered by Koa, React, and Vite - monorepo root",
5
5
  "types": "./types/index.d.ts",
6
6
  "exports": {
@@ -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: {