-
Notifications
You must be signed in to change notification settings - Fork 22
feat: intercepts the mock returned by the me interface. #171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| export default { | ||
| id: 'engine.config', | ||
| theme: 'light', | ||
| material: ['/mock/bundle.json'], | ||
| material: ['./mock/bundle.json'], | ||
| scripts: [], | ||
| styles: [] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,12 @@ | |
| "@opentiny/vue-locale": "~3.20.0", | ||
| "@opentiny/vue-renderless": "~3.20.0", | ||
| "@opentiny/vue-theme": "~3.20.0", | ||
| "@opentiny/vue-theme-mobile": "~3.20.0", | ||
| "@vueuse/core": "^9.6.0", | ||
| "dexie": "^4.2.2", | ||
| "monaco-editor": "0.51.0", | ||
| "axios": "^1.12.0", | ||
| "axios-mock-adapter": "^2.1.0", | ||
|
Comment on lines
+25
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: axios-mock-adapter 2.1.0 is intended to work with axios v0.17.0 and above (per the package README). However, there are known TypeScript compatibility issues when used with axios ≥ 1.6.0 — users report errors and note axios 1.5.1 is the last version that did not trigger the type error. [1][2] Sources:
🌐 Web query:
💡 Result: Summary — what you must do to run monaco-editor 0.51.0 with Vite
Sources
References 🌐 Web query:
💡 Result: Short summary — known compatibility problems between axios 1.12.0 (and recent 1.x releases) and axios-mock-adapter:
Recommendations
Sources: If you want, I can search your project’s error message and suggest a concrete fix (pin version, tsconfig change, or import workaround). 🏁 Script executed: cd template/lowcode-designer && find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.vue" \) | head -20Repository: opentiny/tiny-pro Length of output: 538 🏁 Script executed: cd template/lowcode-designer && rg -i "MonacoEnvironment|getWorker" --type ts --type js --type vueRepository: opentiny/tiny-pro Length of output: 88 🏁 Script executed: cd template/lowcode-designer && rg -i "axios-mock-adapter|createMockAdapter" --type ts --type js --type vueRepository: opentiny/tiny-pro Length of output: 88 🏁 Script executed: cd template/lowcode-designer && cat -n vite.config.ts 2>/dev/null || cat -n vite.config.js 2>/dev/null || echo "No vite config found"Repository: opentiny/tiny-pro Length of output: 1643 🏁 Script executed: cd template/lowcode-designer && rg -i "MonacoEnvironment|getWorker" --type-list | grep -E "js|ts" | head -5Repository: opentiny/tiny-pro Length of output: 450 🏁 Script executed: cd template/lowcode-designer && rg "MonacoEnvironment|getWorker"Repository: opentiny/tiny-pro Length of output: 43 🏁 Script executed: cd template/lowcode-designer && rg "axios-mock-adapter|MockAdapter"Repository: opentiny/tiny-pro Length of output: 352 🏁 Script executed: cd template/lowcode-designer && rg "import.*axios|require.*axios" | head -10Repository: opentiny/tiny-pro Length of output: 210 🏁 Script executed: cd template/lowcode-designer && cat -n src/main.js | head -50Repository: opentiny/tiny-pro Length of output: 1202 🏁 Script executed: cd template/lowcode-designer && cat -n tsconfig.json 2>/dev/null || echo "No tsconfig found"Repository: opentiny/tiny-pro Length of output: 78 🏁 Script executed: cd template/lowcode-designer && find . -name "tsconfig.json" -o -name "jsconfig.json" | head -5Repository: opentiny/tiny-pro Length of output: 43 🏁 Script executed: cd template && cat -n tsconfig.json 2>/dev/null | head -30Repository: opentiny/tiny-pro Length of output: 43 🏁 Script executed: cd template/lowcode-designer && rg "monaco-editor|monaco"Repository: opentiny/tiny-pro Length of output: 104 🏁 Script executed: cd template/lowcode-designer && cat -n src/composable/http/httpServices.js | head -40Repository: opentiny/tiny-pro Length of output: 1163 Resolve axios/axios-mock-adapter version conflict; verify Monaco worker configuration is handled by base config. axios-mock-adapter 2.1.0 has confirmed TypeScript compatibility issues with axios ≥ 1.6.0 (see axios-mock-adapter issue #400). axios 1.5.1 is the last version without the ESM-type mismatch, and the project actively uses axios-mock-adapter in For monaco-editor 0.51.0: the dependency requires explicit Vite worker configuration (getWorker implementation and worker URL setup). Verify that |
||
| "vue": "^3.4.21" | ||
| }, | ||
| "devDependencies": { | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,243 @@ | ||||||||||||||||||||||||||
| import { defineService, META_SERVICE } from '@opentiny/tiny-engine'; | ||||||||||||||||||||||||||
| import axios from 'axios'; | ||||||||||||||||||||||||||
| import AxiosMockAdapter from 'axios-mock-adapter'; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let http = null; | ||||||||||||||||||||||||||
| let mock = null; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const createInterceptorHandler = | ||||||||||||||||||||||||||
| (http) => | ||||||||||||||||||||||||||
| ({ data, type }) => { | ||||||||||||||||||||||||||
| if (typeof data === 'function') { | ||||||||||||||||||||||||||
| http.interceptors[type].use(data); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (Array.isArray(data)) { | ||||||||||||||||||||||||||
| data.forEach((item) => { | ||||||||||||||||||||||||||
| if (!item) return; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (Array.isArray(item)) { | ||||||||||||||||||||||||||
| http.interceptors[type].use(...item); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (typeof item === 'function') { | ||||||||||||||||||||||||||
| http.interceptors[type].use(item); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| export default defineService({ | ||||||||||||||||||||||||||
| id: META_SERVICE.Http, | ||||||||||||||||||||||||||
| type: 'MetaService', | ||||||||||||||||||||||||||
| options: { | ||||||||||||||||||||||||||
| axiosConfig: { | ||||||||||||||||||||||||||
| // axios 配置 | ||||||||||||||||||||||||||
| baseURL: '', | ||||||||||||||||||||||||||
| withCredentials: false, // 跨域请求时是否需要使用凭证 | ||||||||||||||||||||||||||
| headers: {}, // 请求头 | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| interceptors: { | ||||||||||||||||||||||||||
| // 拦截器 | ||||||||||||||||||||||||||
| request: [], // 支持配置多个请求拦截器,先注册后执行 | ||||||||||||||||||||||||||
| response: [], // 支持配置多个响应拦截器,先注册先执行 | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| mockConfig: [], | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| init: ({ options = {} }) => { | ||||||||||||||||||||||||||
| const { axiosConfig = {}, interceptors = {}, enableMock } = options; | ||||||||||||||||||||||||||
| const { request = [], response = [] } = interceptors; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| http = axios.create(axiosConfig); | ||||||||||||||||||||||||||
| if (enableMock) { | ||||||||||||||||||||||||||
| mock = new AxiosMockAdapter(http); | ||||||||||||||||||||||||||
| mock.onGet(/\/mock\/bundle\.json$/).passThrough(); | ||||||||||||||||||||||||||
| mock.onPost(/\/app-center\/api\/ai\/chat/).passThrough(); | ||||||||||||||||||||||||||
| // 允许 tiny-pro 的接口通过,不被 mock 拦截 | ||||||||||||||||||||||||||
| mock.onAny(/\/api\/auth\/api-token/).passThrough(); | ||||||||||||||||||||||||||
| mock.onAny(/\/api\/i18n/).passThrough(); | ||||||||||||||||||||||||||
| mock.onAny(/\/api\/menu/).passThrough(); | ||||||||||||||||||||||||||
| mock.onAny(/\/api\/role/).passThrough(); | ||||||||||||||||||||||||||
| mock.onAny(/\/api\/role\/detail/).passThrough(); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| http.interceptors.request.use((config) => { | ||||||||||||||||||||||||||
| const AI_PATH = '/app-center/api/ai/chat'; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (config.url === AI_PATH) { | ||||||||||||||||||||||||||
| config.url = `/tiny-engine${AI_PATH}`; // 修改路径 | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return config; | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
Comment on lines
+67
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AI_PATH interceptor accumulates on repeated This request interceptor is added unconditionally in both Consider tracking whether this interceptor has been added, or eject it before re-adding. Proposed fix: track interceptor registration let http = null;
let mock = null;
+let aiPathInterceptorId = null;
// In init and setOptions, before adding the interceptor:
+if (aiPathInterceptorId !== null) {
+ http.interceptors.request.eject(aiPathInterceptorId);
+}
-http.interceptors.request.use((config) => {
+aiPathInterceptorId = http.interceptors.request.use((config) => {
const AI_PATH = '/app-center/api/ai/chat';
if (config.url === AI_PATH) {
config.url = `/tiny-engine${AI_PATH}`;
}
return config;
});
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| mock.onAny().reply(async (config) => { | ||||||||||||||||||||||||||
| const { mockConfig = [] } = options; | ||||||||||||||||||||||||||
| // 构建完整 URL(包含 baseURL) | ||||||||||||||||||||||||||
| const fullUrl = (config.baseURL || '') + (config.url || ''); | ||||||||||||||||||||||||||
| const method = (config.method || 'GET').toUpperCase(); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const mockItem = mockConfig.find((item) => { | ||||||||||||||||||||||||||
| // 方法匹配 | ||||||||||||||||||||||||||
| if (item.method && method !== item.method.toUpperCase()) { | ||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // URL 匹配 - 同时检查 config.url 和 fullUrl | ||||||||||||||||||||||||||
| if (typeof item.url === 'string') { | ||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||
| item.url === config.url || | ||||||||||||||||||||||||||
| item.url === fullUrl || | ||||||||||||||||||||||||||
| config.url?.includes(item.url) || | ||||||||||||||||||||||||||
| fullUrl.includes(item.url) | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (item.url instanceof RegExp) { | ||||||||||||||||||||||||||
| return item.url.test(config.url) || item.url.test(fullUrl); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (mockItem) { | ||||||||||||||||||||||||||
| if (typeof mockItem.response === 'function') { | ||||||||||||||||||||||||||
| return mockItem.response(config); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return mockItem.response; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // 如果没有匹配到,输出调试信息 | ||||||||||||||||||||||||||
| console.warn( | ||||||||||||||||||||||||||
| `[Mock] 未匹配到接口: ${method} ${fullUrl || config.url}`, | ||||||||||||||||||||||||||
| '可用路由:', | ||||||||||||||||||||||||||
| mockConfig.map((item) => `${item.method || 'ANY'} ${item.url}`) | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||||
| 200, | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| code: 200, | ||||||||||||||||||||||||||
| errMsg: | ||||||||||||||||||||||||||
| '当前 demo 暂未支持该接口,请前往GitHub 或者 Gitee 克隆项目完整体验', | ||||||||||||||||||||||||||
| error: | ||||||||||||||||||||||||||
| '当前 demo 暂未支持该接口,请前往GitHub 或者 Gitee 克隆项目完整体验', | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
Comment on lines
+76
to
+129
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Significant code duplication between The mock handler logic (lines 76-129) is nearly identical to lines 185-239 in Proposed refactor: extract a shared helper+const createMockHandler = (mockConfig) => async (config) => {
+ const fullUrl = (config.baseURL || '') + (config.url || '');
+ const method = (config.method || 'GET').toUpperCase();
+
+ const mockItem = mockConfig.find((item) => {
+ if (item.method && method !== item.method.toUpperCase()) {
+ return false;
+ }
+ if (typeof item.url === 'string') {
+ return (
+ item.url === config.url ||
+ item.url === fullUrl ||
+ config.url?.includes(item.url) ||
+ fullUrl.includes(item.url)
+ );
+ }
+ if (item.url instanceof RegExp) {
+ return item.url.test(config.url) || item.url.test(fullUrl);
+ }
+ return false;
+ });
+
+ if (mockItem) {
+ return typeof mockItem.response === 'function'
+ ? mockItem.response(config)
+ : mockItem.response;
+ }
+
+ console.warn(
+ `[Mock] 未匹配到接口: ${method} ${fullUrl || config.url}`,
+ '可用路由:',
+ mockConfig.map((item) => `${item.method || 'ANY'} ${item.url}`)
+ );
+
+ return [200, { code: 200, errMsg: '...', error: '...' }];
+};
// Then in init and setOptions:
-mock.onAny().reply(async (config) => { /* 50 lines */ });
+mock.onAny().reply(createMockHandler(options.mockConfig));
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const addInterceptors = createInterceptorHandler(http); | ||||||||||||||||||||||||||
| addInterceptors({ data: request, type: 'request' }); | ||||||||||||||||||||||||||
| addInterceptors({ data: response, type: 'response' }); | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| apis: () => ({ | ||||||||||||||||||||||||||
| getHttp: () => http, | ||||||||||||||||||||||||||
| getMock: () => mock, | ||||||||||||||||||||||||||
| get: (...args) => http?.get(...args), | ||||||||||||||||||||||||||
| post: (...args) => http?.post(...args), | ||||||||||||||||||||||||||
| request: (...args) => http?.request(...args), | ||||||||||||||||||||||||||
| put: (...args) => http?.put(...args), | ||||||||||||||||||||||||||
| delete: (...args) => http?.delete(...args), | ||||||||||||||||||||||||||
| setOptions: (options) => { | ||||||||||||||||||||||||||
| // 支持动态设置选项 | ||||||||||||||||||||||||||
| if (options.axiosConfig) { | ||||||||||||||||||||||||||
| Object.assign(http.defaults, options.axiosConfig); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (options.interceptors) { | ||||||||||||||||||||||||||
| const addInterceptors = createInterceptorHandler(http); | ||||||||||||||||||||||||||
| if (options.interceptors.request) { | ||||||||||||||||||||||||||
| addInterceptors({ | ||||||||||||||||||||||||||
| data: options.interceptors.request, | ||||||||||||||||||||||||||
| type: 'request', | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (options.interceptors.response) { | ||||||||||||||||||||||||||
| addInterceptors({ | ||||||||||||||||||||||||||
| data: options.interceptors.response, | ||||||||||||||||||||||||||
| type: 'response', | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| // 重新初始化 mock(如果启用) | ||||||||||||||||||||||||||
| if (options.enableMock && options.mockConfig) { | ||||||||||||||||||||||||||
| // 如果 mock 已存在,先恢复 | ||||||||||||||||||||||||||
| if (mock) { | ||||||||||||||||||||||||||
| mock.restore(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| mock = new AxiosMockAdapter(http); | ||||||||||||||||||||||||||
| mock.onGet(/\/mock\/bundle\.json$/).passThrough(); | ||||||||||||||||||||||||||
| mock.onPost(/\/app-center\/api\/ai\/chat/).passThrough(); | ||||||||||||||||||||||||||
| // 允许 /api/auth/api-token 接口通过,不被 mock 拦截 | ||||||||||||||||||||||||||
| mock.onAny(/\/api\/auth\/api-token/).passThrough(); | ||||||||||||||||||||||||||
|
Comment on lines
+171
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passthrough routes are inconsistent with When
This will cause these endpoints to be unexpectedly mocked after calling Proposed fix: add missing passthrough routes mock = new AxiosMockAdapter(http);
mock.onGet(/\/mock\/bundle\.json$/).passThrough();
mock.onPost(/\/app-center\/api\/ai\/chat/).passThrough();
-// 允许 /api/auth/api-token 接口通过,不被 mock 拦截
+// 允许 tiny-pro 的接口通过,不被 mock 拦截
mock.onAny(/\/api\/auth\/api-token/).passThrough();
+mock.onAny(/\/api\/i18n/).passThrough();
+mock.onAny(/\/api\/menu/).passThrough();
+mock.onAny(/\/api\/role/).passThrough();
+mock.onAny(/\/api\/role\/detail/).passThrough();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| http.interceptors.request.use((config) => { | ||||||||||||||||||||||||||
| const AI_PATH = '/app-center/api/ai/chat'; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (config.url === AI_PATH) { | ||||||||||||||||||||||||||
| config.url = `/tiny-engine${AI_PATH}`; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return config; | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| mock.onAny().reply(async (config) => { | ||||||||||||||||||||||||||
| // 构建完整 URL(包含 baseURL) | ||||||||||||||||||||||||||
| const fullUrl = (config.baseURL || '') + (config.url || ''); | ||||||||||||||||||||||||||
| const method = (config.method || 'GET').toUpperCase(); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const mockItem = options.mockConfig.find((item) => { | ||||||||||||||||||||||||||
| // 方法匹配 | ||||||||||||||||||||||||||
| if (item.method && method !== item.method.toUpperCase()) { | ||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // URL 匹配 - 同时检查 config.url 和 fullUrl | ||||||||||||||||||||||||||
| if (typeof item.url === 'string') { | ||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||
| item.url === config.url || | ||||||||||||||||||||||||||
| item.url === fullUrl || | ||||||||||||||||||||||||||
| config.url?.includes(item.url) || | ||||||||||||||||||||||||||
| fullUrl.includes(item.url) | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (item.url instanceof RegExp) { | ||||||||||||||||||||||||||
| return item.url.test(config.url) || item.url.test(fullUrl); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (mockItem) { | ||||||||||||||||||||||||||
| if (typeof mockItem.response === 'function') { | ||||||||||||||||||||||||||
| return mockItem.response(config); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return mockItem.response; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // 如果没有匹配到,输出调试信息 | ||||||||||||||||||||||||||
| console.warn( | ||||||||||||||||||||||||||
| `[Mock] 未匹配到接口: ${method} ${fullUrl || config.url}`, | ||||||||||||||||||||||||||
| '可用路由:', | ||||||||||||||||||||||||||
| options.mockConfig.map( | ||||||||||||||||||||||||||
| (item) => `${item.method || 'ANY'} ${item.url}` | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||||
| 200, | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| code: 200, | ||||||||||||||||||||||||||
| errMsg: | ||||||||||||||||||||||||||
| '当前 demo 暂未支持该接口,请前往GitHub 或者 Gitee 克隆项目完整体验', | ||||||||||||||||||||||||||
| error: | ||||||||||||||||||||||||||
| '当前 demo 暂未支持该接口,请前往GitHub 或者 Gitee 克隆项目完整体验', | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import Dexie from "dexie" | ||
| import user from '../mock/user.json' | ||
| import appDetail from '../mock/appDetail.json' | ||
| import appSchema from '../mock/appSchema.json' | ||
| import pageList from '../mock/pageList.json' | ||
| import blockList from '../mock/blocks.json' | ||
| import blockGroup from '../mock/block-groups.json' | ||
| import utilsList from '../mock/utilsList.json' | ||
| import blockHistories from '../mock/blockHistories.json' | ||
| import { schema } from './schema' | ||
|
|
||
| export const db = new Dexie('tiny-engine-demo-indexdb') | ||
|
|
||
| // 声明数据库表 | ||
| export const createDB = async () => { | ||
| return db.version(1).stores({ | ||
| ...schema | ||
| }) | ||
| } | ||
|
Comment on lines
+14
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd template/lowcode-designer && find . -name "index.js" -path "*/db/*" | head -20Repository: opentiny/tiny-pro Length of output: 78 🏁 Script executed: cat -n template/lowcode-designer/src/db/index.jsRepository: opentiny/tiny-pro Length of output: 1751 🌐 Web query:
💡 Result: Short answer: Dexie’s version(...).stores(...) must be declared before opening the DB (and you cannot repeatedly add the same version while the DB is open). To make initialization idempotent either (A) ensure you only declare the schema once (e.g. from a single DB singleton/constructor), or (B) guard/skip calls when the DB is already opened or already at the desired version. Documentation: version/stores must be declared before open and Dexie sorts/uses the highest declared version. [1][2] Practical options:
References:
Make DB initialization idempotent— Calling Recommended fix: Move schema declaration to the Dexie instance creation (lines 12–19), so it runs once at app startup: export const db = new Dexie('tiny-engine-demo-indexdb')
db.version(1).stores({
...schema
})
export const initIndexDB = async () => {
await db.open()
// ... rest of function
}Also applies to: 34–46 🤖 Prompt for AI Agents |
||
|
|
||
| // 初始化注入数据 | ||
| const initData = async () => { | ||
| // 添加用户 | ||
| await db.user.add(user) | ||
| await db.appDetail.add(appDetail) | ||
| await db.appSchema.add(appSchema) | ||
| await db.page.bulkPut(pageList) | ||
| await db.block.bulkPut(blockList) | ||
| await db.blockGroup.bulkPut(blockGroup) | ||
| await db.blockHistories.bulkPut(blockHistories) | ||
| await db.utils.bulkPut(utilsList) | ||
| } | ||
| // 初始化 indexdb | ||
| export const initIndexDB = async () => { | ||
| await createDB() | ||
| await db.open() | ||
|
|
||
| const userCount = await db.user.count() | ||
|
|
||
| // 如果有数据了,那就不初始化数据了 | ||
| if (userCount > 0) { | ||
| return | ||
| } | ||
|
|
||
| await initData() | ||
| } | ||
|
|
||
| // 重置表数据 | ||
| export const resetDataBase = async () => { | ||
| await Promise.all( | ||
| db.tables.map(table => table.clear()) | ||
| ) | ||
|
|
||
| await initData() | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 639
Path resolution error: relative path points to non-existent directory.
The file
bundle.jsonactually exists attemplate/lowcode-designer/public/mock/bundle.json, but the relative path./mock/bundle.jsonresolves to a non-existent directory. The correct relative path should be./public/mock/bundle.json.🤖 Prompt for AI Agents