-
Notifications
You must be signed in to change notification settings - Fork 26
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 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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
🌐 Web query:
axios-mock-adapter 2.1.0 supported axios versions compatibility💡 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:
monaco-editor 0.51.0 Vite worker configuration requirements💡 Result:
Summary — what you must do to run monaco-editor 0.51.0 with Vite
Use the ESM integration pattern: set self.MonacoEnvironment.getWorker (Vite expects getWorker, not getWorkerUrl) and return a Worker constructed from the Vite-built worker module (type: 'module'). Example pattern and label → file mapping shown in the Monaco ESM integration docs. [1][2]
Worker label → module mapping (use these labels in getWorker):
Construct the Worker using the Vite worker entry URL (append ?worker or use Vite’s worker API) and set { type: 'module', name: label } so the worker is an ES module. Example: new Worker('/monaco-editor/esm/vs/language/typescript/ts.worker?worker', { type: 'module', name: 'typescript' }). [1][3]
If you prefer convenience, use a Vite plugin (vite-plugin-monaco-editor) which bundles/outputs worker scripts and exposes options (languageWorkers, customWorkers, publicPath, globalAPI). The plugin also enforces including editorWorkerService when using other language workers. [3][4]
Be aware of the 0.51.0-specific worker issues reported by users: some users saw importScripts / invalid-URL errors when upgrading to 0.51.0 (fallback to main-thread workers). If you hit worker-creation errors after upgrading, check your getWorker implementation / public base path and consider using the plugin or a package that bundles Monaco workers for ESM (monaco-esm / monaco-editor-workers). [5][6]
Sources
References
[1] Integrating the ESM version of the Monaco Editor — Vite example.
[2] Integrate-ESM docs / examples (getWorker + ?worker usage).
[3] vite-plugin-monaco-editor (npm / README).
[4] vite-plugin-monaco-editor (GitHub).
[5] microsoft/monaco-editor Issue: "0.51.0 only: Could not create web worker".
[6] monaco-esm / monaco-editor-workers (bundled-workers packages).
🌐 Web query:
axios 1.12.0 axios-mock-adapter compatibility known issues💡 Result:
Short summary — known compatibility problems between axios 1.12.0 (and recent 1.x releases) and axios-mock-adapter:
TypeScript type incompatibility: axios introduced ESM/typing changes (starting around 1.6.0) that cause TypeScript errors when using axios-mock-adapter’s types (errors reported when the axios import uses the newer ESM types). This is a long-running issue on the axios-mock-adapter repo (see issue #400). [1]
Axios 1.12.0-specific type/build problems: people reported TypeScript build errors after upgrading to axios 1.12.0 (missing global DOM types like RequestInfo/BodyInit in some Node setups), which can surface when using libraries that depend on axios types. See axios issue #7016. [2]
Adapter/behavior changes in axios 1.12.0: the fetch adapter behavior in recent axios releases changed and has caused compatibility problems with some mocking/interception tools (e.g., MSW) — reported in axios issue #7015. While this is not axios-mock-adapter directly, it can affect test setups that rely on different adapters. [3]
Recommendations
Sources:
[1] axios-mock-adapter issue discussing TS errors with axios >=1.6.0: ctimmerm/axios-mock-adapter#400
[2] axios issue: TypeScript build errors reported for 1.12.0: axios/axios#7016
[3] axios issue: fetch adapter breaks compatibility with MSW in 1.12.0: axios/axios#7015
[4] (context) axios-mock-adapter repo / discussions about compatibility with newer axios typings. https://github.com/ctimmerm/axios-mock-adapter
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:
Repository: opentiny/tiny-pro
Length of output: 538
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 88
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 88
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 1643
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 450
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 43
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 352
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 210
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 1202
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 78
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 43
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 43
🏁 Script executed:
Repository: opentiny/tiny-pro
Length of output: 104
🏁 Script executed:
Repository: 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
src/composable/http/httpServices.js. Either downgrade axios to 1.5.1 or use a different testing approach.For monaco-editor 0.51.0: the dependency requires explicit Vite worker configuration (getWorker implementation and worker URL setup). Verify that
useTinyEngineBaseConfigfrom@opentiny/tiny-engine-vite-configalready handles Monaco's ESM worker requirements; if not, you'll see runtime worker errors when the editor loads.