@objectstack/plugin-msw 1.0.10 → 1.0.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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +22 -0
- package/dist/index.d.mts +5 -26
- package/dist/index.d.ts +5 -26
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -7
- package/src/msw-plugin.ts +7 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/plugin-msw@1.0.
|
|
2
|
+
> @objectstack/plugin-msw@1.0.12 build /home/runner/work/spec/spec/packages/plugins/plugin-msw
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
13
|
+
[32mCJS[39m [1mdist/index.js [22m[32m9.57 KB[39m
|
|
14
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m19.83 KB[39m
|
|
15
|
+
[32mCJS[39m ⚡️ Build success in 39ms
|
|
16
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m7.83 KB[39m
|
|
17
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m18.44 KB[39m
|
|
18
|
+
[32mESM[39m ⚡️ Build success in 40ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 7208ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m2.67 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m2.67 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @objectstack/plugin-msw
|
|
2
2
|
|
|
3
|
+
## 1.0.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @objectstack/spec@1.0.12
|
|
9
|
+
- @objectstack/core@1.0.12
|
|
10
|
+
- @objectstack/runtime@1.0.12
|
|
11
|
+
- @objectstack/objectql@1.0.12
|
|
12
|
+
- @objectstack/types@1.0.12
|
|
13
|
+
|
|
14
|
+
## 1.0.11
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 3a9b0f6: Fix metadata path compatibility by rebuilding with latest runtime changes.
|
|
19
|
+
- @objectstack/spec@1.0.11
|
|
20
|
+
- @objectstack/core@1.0.11
|
|
21
|
+
- @objectstack/types@1.0.11
|
|
22
|
+
- @objectstack/objectql@1.0.11
|
|
23
|
+
- @objectstack/runtime@1.0.11
|
|
24
|
+
|
|
3
25
|
## 1.0.10
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -90,44 +90,23 @@ declare class ObjectStackServer {
|
|
|
90
90
|
static init(protocol: ObjectStackProtocol): void;
|
|
91
91
|
private static getProtocol;
|
|
92
92
|
static findData(objectName: string, query?: any): Promise<{
|
|
93
|
-
data:
|
|
94
|
-
object: string;
|
|
95
|
-
records: Record<string, any>[];
|
|
96
|
-
total?: number | undefined;
|
|
97
|
-
hasMore?: boolean | undefined;
|
|
98
|
-
};
|
|
93
|
+
data: any;
|
|
99
94
|
status: number;
|
|
100
95
|
}>;
|
|
101
96
|
static getData(objectName: string, id: string): Promise<{
|
|
102
|
-
data:
|
|
103
|
-
object: string;
|
|
104
|
-
record: Record<string, any>;
|
|
105
|
-
id: string;
|
|
106
|
-
};
|
|
97
|
+
data: any;
|
|
107
98
|
status: number;
|
|
108
99
|
}>;
|
|
109
100
|
static createData(objectName: string, data: any): Promise<{
|
|
110
|
-
data:
|
|
111
|
-
object: string;
|
|
112
|
-
record: Record<string, any>;
|
|
113
|
-
id: string;
|
|
114
|
-
};
|
|
101
|
+
data: any;
|
|
115
102
|
status: number;
|
|
116
103
|
}>;
|
|
117
104
|
static updateData(objectName: string, id: string, data: any): Promise<{
|
|
118
|
-
data:
|
|
119
|
-
object: string;
|
|
120
|
-
record: Record<string, any>;
|
|
121
|
-
id: string;
|
|
122
|
-
};
|
|
105
|
+
data: any;
|
|
123
106
|
status: number;
|
|
124
107
|
}>;
|
|
125
108
|
static deleteData(objectName: string, id: string): Promise<{
|
|
126
|
-
data:
|
|
127
|
-
object: string;
|
|
128
|
-
id: string;
|
|
129
|
-
success: boolean;
|
|
130
|
-
};
|
|
109
|
+
data: any;
|
|
131
110
|
status: number;
|
|
132
111
|
}>;
|
|
133
112
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -90,44 +90,23 @@ declare class ObjectStackServer {
|
|
|
90
90
|
static init(protocol: ObjectStackProtocol): void;
|
|
91
91
|
private static getProtocol;
|
|
92
92
|
static findData(objectName: string, query?: any): Promise<{
|
|
93
|
-
data:
|
|
94
|
-
object: string;
|
|
95
|
-
records: Record<string, any>[];
|
|
96
|
-
total?: number | undefined;
|
|
97
|
-
hasMore?: boolean | undefined;
|
|
98
|
-
};
|
|
93
|
+
data: any;
|
|
99
94
|
status: number;
|
|
100
95
|
}>;
|
|
101
96
|
static getData(objectName: string, id: string): Promise<{
|
|
102
|
-
data:
|
|
103
|
-
object: string;
|
|
104
|
-
record: Record<string, any>;
|
|
105
|
-
id: string;
|
|
106
|
-
};
|
|
97
|
+
data: any;
|
|
107
98
|
status: number;
|
|
108
99
|
}>;
|
|
109
100
|
static createData(objectName: string, data: any): Promise<{
|
|
110
|
-
data:
|
|
111
|
-
object: string;
|
|
112
|
-
record: Record<string, any>;
|
|
113
|
-
id: string;
|
|
114
|
-
};
|
|
101
|
+
data: any;
|
|
115
102
|
status: number;
|
|
116
103
|
}>;
|
|
117
104
|
static updateData(objectName: string, id: string, data: any): Promise<{
|
|
118
|
-
data:
|
|
119
|
-
object: string;
|
|
120
|
-
record: Record<string, any>;
|
|
121
|
-
id: string;
|
|
122
|
-
};
|
|
105
|
+
data: any;
|
|
123
106
|
status: number;
|
|
124
107
|
}>;
|
|
125
108
|
static deleteData(objectName: string, id: string): Promise<{
|
|
126
|
-
data:
|
|
127
|
-
object: string;
|
|
128
|
-
id: string;
|
|
129
|
-
success: boolean;
|
|
130
|
-
};
|
|
109
|
+
data: any;
|
|
131
110
|
status: number;
|
|
132
111
|
}>;
|
|
133
112
|
}
|
package/dist/index.js
CHANGED
|
@@ -180,6 +180,9 @@ var MSWPlugin = class {
|
|
|
180
180
|
if (path.startsWith(baseUrl)) {
|
|
181
181
|
path = path.slice(baseUrl.length);
|
|
182
182
|
}
|
|
183
|
+
if (this.options.logRequests) {
|
|
184
|
+
console.log(`[MSW] Intercepted: ${request.method} ${url.pathname}`, { path });
|
|
185
|
+
}
|
|
183
186
|
let body = void 0;
|
|
184
187
|
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
185
188
|
try {
|
|
@@ -215,8 +218,8 @@ var MSWPlugin = class {
|
|
|
215
218
|
return void 0;
|
|
216
219
|
};
|
|
217
220
|
this.handlers.push(
|
|
218
|
-
import_msw.http.all(
|
|
219
|
-
import_msw.http.all(
|
|
221
|
+
import_msw.http.all(`*${baseUrl}/*`, catchAll),
|
|
222
|
+
import_msw.http.all(`*${baseUrl}`, catchAll)
|
|
220
223
|
// Handle root if needed
|
|
221
224
|
);
|
|
222
225
|
ctx.logger.info("MSW handlers set up using HttpDispatcher", { baseUrl });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/msw-plugin.ts"],"sourcesContent":["/**\n * @objectstack/plugin-msw\n * \n * MSW (Mock Service Worker) Plugin for ObjectStack Runtime\n * \n * This plugin enables seamless integration with Mock Service Worker for\n * testing and development environments. It automatically generates MSW\n * handlers for all ObjectStack API endpoints.\n * \n * @example\n * ```typescript\n * import { MSWPlugin, ObjectStackServer } from '@objectstack/plugin-msw';\n * import { ObjectStackRuntime } from '@objectstack/runtime';\n * \n * // Use with runtime\n * const runtime = new ObjectStackRuntime({\n * plugins: [\n * new MSWPlugin({\n * enableBrowser: true,\n * baseUrl: '/api/v1'\n * })\n * ]\n * });\n * \n * // Or use standalone in browser\n * import { setupWorker, http } from 'msw/browser';\n * \n * ObjectStackServer.init(protocol);\n * \n * const handlers = [\n * http.get('/api/user/:id', async ({ params }) => {\n * const result = await ObjectStackServer.getData('user', params.id);\n * return HttpResponse.json(result.data, { status: result.status });\n * })\n * ];\n * \n * const worker = setupWorker(...handlers);\n * await worker.start();\n * ```\n */\n\nexport { MSWPlugin, ObjectStackServer } from './msw-plugin';\nexport type { MSWPluginOptions } from './msw-plugin';\n\n// Re-export MSW types for convenience\nexport type { HttpHandler, HttpResponse } from 'msw';\n","import { http, HttpResponse, passthrough } from 'msw';\nimport { setupWorker } from 'msw/browser';\nimport { \n Plugin, \n PluginContext, \n ObjectKernel,\n HttpDispatcher,\n HttpDispatcherResult\n} from '@objectstack/runtime';\n// import { ObjectStackProtocolImplementation } from '@objectstack/objectql';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\n\n// Helper for parsing query parameters\nfunction parseQueryParams(url: URL): Record<string, any> {\n const params: Record<string, any> = {};\n const keys = Array.from(new Set(url.searchParams.keys()));\n\n for (const key of keys) {\n const values = url.searchParams.getAll(key);\n // If single value, use it directly. If multiple, keep as array.\n const rawValue = values.length === 1 ? values[0] : values;\n \n // Helper to parse individual value\n const parseValue = (val: string) => {\n if (val === 'true') return true;\n if (val === 'false') return false;\n if (val === 'null') return null;\n if (val === 'undefined') return undefined;\n \n // Try number (integers only or floats)\n // Safety check: Don't convert if it loses information (like leading zeros)\n const num = Number(val);\n if (!isNaN(num) && val.trim() !== '' && String(num) === val) {\n return num;\n }\n \n // Try JSON\n if ((val.startsWith('{') && val.endsWith('}')) || (val.startsWith('[') && val.endsWith(']'))) {\n try {\n return JSON.parse(val);\n } catch {}\n }\n \n return val;\n };\n\n if (Array.isArray(rawValue)) {\n params[key] = rawValue.map(parseValue);\n } else {\n params[key] = parseValue(rawValue as string);\n }\n }\n \n return params;\n}\n\nexport interface MSWPluginOptions {\n /**\n * Enable MSW in the browser environment\n */\n enableBrowser?: boolean;\n \n /**\n * Custom handlers to add to MSW\n */\n customHandlers?: Array<any>;\n \n /**\n * Base URL for API endpoints\n */\n baseUrl?: string;\n \n /**\n * Whether to log requests\n */\n logRequests?: boolean;\n}\n\n/**\n * MSW Plugin for ObjectStack\n\n * \n * This plugin enables Mock Service Worker integration for testing and development.\n * It automatically mocks API endpoints using the ObjectStack runtime protocol.\n * \n * @example\n * ```typescript\n * import { MSWPlugin } from '@objectstack/plugin-msw';\n * \n * // With ObjectKernel\n * const kernel = new ObjectKernel();\n * kernel.use(new MSWPlugin({\n * enableBrowser: true,\n * baseUrl: '/api/v1'\n * }));\n * ```\n */\nexport class MSWPlugin implements Plugin {\n name = 'com.objectstack.plugin.msw';\n type = 'server';\n version = '0.9.0';\n \n private options: MSWPluginOptions;\n private worker: any;\n private handlers: Array<any> = [];\n private protocol?: ObjectStackProtocol;\n private dispatcher?: HttpDispatcher;\n\n constructor(options: MSWPluginOptions = {}) {\n this.options = {\n enableBrowser: true,\n baseUrl: '/api/v1',\n logRequests: true,\n ...options\n };\n }\n\n /**\n * Init phase\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing MSW plugin', { \n enableBrowser: this.options.enableBrowser,\n baseUrl: this.options.baseUrl,\n logRequests: this.options.logRequests\n });\n // Protocol will be created in start phase\n ctx.logger.info('MSW plugin initialized');\n }\n\n /**\n * Start phase\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting MSW plugin');\n \n try {\n // 1. Try to get existing protocol service\n try {\n this.protocol = ctx.getService<ObjectStackProtocol>('protocol');\n ctx.logger.debug('Protocol service found from context');\n } catch (e) {\n // Ignore, will try to create default implementation\n }\n\n // 2. If not found, try to instantiate default implementation dynamically\n if (!this.protocol) {\n try {\n const dataEngine = ctx.getService<IDataEngine>('objectql');\n // Dynamically import ObjectStackProtocolImplementation to avoid hard dependency\n const { ObjectStackProtocolImplementation } = await import('@objectstack/objectql');\n this.protocol = new ObjectStackProtocolImplementation(dataEngine);\n ctx.logger.debug('Protocol implementation created dynamically');\n } catch (e: any) {\n if (e.code === 'ERR_MODULE_NOT_FOUND') {\n ctx.logger.warn('Module @objectstack/objectql not found. Protocol not initialized.');\n } else {\n throw e;\n }\n }\n }\n \n if (!this.protocol) {\n // Without a protocol, MSW can't serve data APIs\n ctx.logger.warn('No ObjectStackProtocol service available. MSW will only serve static/custom handlers if configured.');\n }\n\n } catch (e) {\n ctx.logger.error('Failed to initialize protocol', e as Error);\n throw new Error('[MSWPlugin] Failed to initialize protocol');\n }\n \n this.setupHandlers(ctx);\n await this.startWorker(ctx);\n }\n\n /**\n * Destroy phase\n */\n async destroy() {\n await this.stopWorker();\n }\n\n /**\n * Setup MSW handlers\n */\n private setupHandlers(ctx: PluginContext) {\n // Initialize HttpDispatcher\n try {\n this.dispatcher = new HttpDispatcher(ctx.getKernel());\n } catch (e) {\n ctx.logger.warn('[MSWPlugin] Could not initialize HttpDispatcher via Kernel. Falling back to simple handlers.');\n }\n\n const baseUrl = this.options.baseUrl || '/api/v1';\n\n // Custom handlers have priority\n this.handlers = [\n ...(this.options.customHandlers || [])\n ];\n\n // Discovery Endpoint\n this.handlers.push(\n http.get('*/.well-known/objectstack', () => {\n if (this.dispatcher) {\n return HttpResponse.json({\n data: this.dispatcher.getDiscoveryInfo(baseUrl)\n });\n }\n return HttpResponse.json({\n data: {\n version: 'v1',\n apiName: 'ObjectStack API',\n url: baseUrl,\n capabilities: {\n graphql: false,\n search: false,\n websockets: false,\n files: false,\n analytics: false,\n hub: false\n }\n }\n });\n })\n );\n\n if (this.dispatcher) {\n const dispatcher = this.dispatcher;\n \n // Catch-all handler for ObjectStack Runtime\n // We use a wildcard to capture all methods and paths under baseUrl\n const catchAll = async ({ request, params }: any) => {\n const url = new URL(request.url);\n // Calculate path relative to API prefix\n // e.g. /api/v1/data/contacts -> /data/contacts\n let path = url.pathname;\n if (path.startsWith(baseUrl)) {\n path = path.slice(baseUrl.length);\n }\n \n // Parse Body if present\n let body: any = undefined;\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n try {\n body = await request.clone().json();\n } catch (e) {\n try {\n // Try form data if json fails? \n // Dispatcher expects objects usually.\n // For file upload, body might be FormData logic needed?\n // For now assume JSON or text\n } catch (e2) {}\n }\n }\n\n // Parse Query\n const query = parseQueryParams(url);\n \n // Dispatch\n const result = await dispatcher.dispatch(\n request.method, \n path, \n body, \n query, \n { request }\n );\n\n if (result.handled) {\n if (result.response) {\n return HttpResponse.json(result.response.body, { \n status: result.response.status,\n headers: result.response.headers as any\n });\n }\n if (result.result) {\n // Handle special results (streams/redirects - unlikely in MSW but possible)\n if (result.result.type === 'redirect') {\n return HttpResponse.redirect(result.result.url);\n }\n // Fallback for others\n return HttpResponse.json(result.result);\n }\n }\n \n // Not handled by dispatcher (404 for this route subset)\n return undefined; // Let MSW pass through or handle next\n };\n\n this.handlers.push(\n http.all(`${baseUrl}/*`, catchAll),\n http.all(`${baseUrl}`, catchAll) // Handle root if needed\n );\n \n ctx.logger.info('MSW handlers set up using HttpDispatcher', { baseUrl });\n } else {\n ctx.logger.warn('[MSWPlugin] No dispatcher available. No API routes registered.');\n }\n }\n\n\n /**\n * Start the MSW worker\n */\n private async startWorker(ctx: PluginContext) {\n if (this.options.enableBrowser && typeof window !== 'undefined') {\n // Browser environment\n ctx.logger.debug('Starting MSW in browser mode');\n this.worker = setupWorker(...this.handlers);\n await this.worker.start({\n onUnhandledRequest: 'bypass',\n });\n ctx.logger.info('MSW started in browser mode');\n } else {\n ctx.logger.debug('MSW browser mode disabled or not in browser environment');\n }\n }\n\n /**\n * Stop the MSW worker\n */\n private async stopWorker() {\n if (this.worker) {\n this.worker.stop();\n console.log('[MSWPlugin] Stopped MSW worker');\n }\n }\n\n /**\n * Get the MSW worker instance for advanced use cases\n */\n getWorker() {\n return this.worker;\n }\n\n /**\n * Get registered handlers\n */\n getHandlers() {\n return this.handlers;\n }\n}\n\n/**\n * Static helper for interacting with ObjectStack protocol in MSW handlers\n */\nexport class ObjectStackServer {\n private static protocol: ObjectStackProtocol;\n\n static init(protocol: ObjectStackProtocol) {\n this.protocol = protocol;\n }\n\n private static getProtocol(): ObjectStackProtocol {\n if (!this.protocol) {\n throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init(protocol) first.');\n }\n return this.protocol;\n }\n\n static async findData(objectName: string, query?: any) {\n const body = await this.getProtocol().findData({ object: objectName, query });\n return { data: body, status: 200 };\n }\n\n static async getData(objectName: string, id: string) {\n const body = await this.getProtocol().getData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n\n static async createData(objectName: string, data: any) {\n const body = await this.getProtocol().createData({ object: objectName, data });\n return { data: body, status: 201 };\n }\n\n static async updateData(objectName: string, id: string, data: any) {\n const body = await this.getProtocol().updateData({ object: objectName, id, data });\n return { data: body, status: 200 };\n }\n\n static async deleteData(objectName: string, id: string) {\n const body = await this.getProtocol().deleteData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/msw-plugin.ts"],"sourcesContent":["/**\n * @objectstack/plugin-msw\n * \n * MSW (Mock Service Worker) Plugin for ObjectStack Runtime\n * \n * This plugin enables seamless integration with Mock Service Worker for\n * testing and development environments. It automatically generates MSW\n * handlers for all ObjectStack API endpoints.\n * \n * @example\n * ```typescript\n * import { MSWPlugin, ObjectStackServer } from '@objectstack/plugin-msw';\n * import { ObjectStackRuntime } from '@objectstack/runtime';\n * \n * // Use with runtime\n * const runtime = new ObjectStackRuntime({\n * plugins: [\n * new MSWPlugin({\n * enableBrowser: true,\n * baseUrl: '/api/v1'\n * })\n * ]\n * });\n * \n * // Or use standalone in browser\n * import { setupWorker, http } from 'msw/browser';\n * \n * ObjectStackServer.init(protocol);\n * \n * const handlers = [\n * http.get('/api/user/:id', async ({ params }) => {\n * const result = await ObjectStackServer.getData('user', params.id);\n * return HttpResponse.json(result.data, { status: result.status });\n * })\n * ];\n * \n * const worker = setupWorker(...handlers);\n * await worker.start();\n * ```\n */\n\nexport { MSWPlugin, ObjectStackServer } from './msw-plugin';\nexport type { MSWPluginOptions } from './msw-plugin';\n\n// Re-export MSW types for convenience\nexport type { HttpHandler, HttpResponse } from 'msw';\n","import { http, HttpResponse, passthrough } from 'msw';\nimport { setupWorker } from 'msw/browser';\nimport { \n Plugin, \n PluginContext, \n ObjectKernel,\n HttpDispatcher,\n HttpDispatcherResult\n} from '@objectstack/runtime';\n// import { ObjectStackProtocolImplementation } from '@objectstack/objectql';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\n\n// Helper for parsing query parameters\nfunction parseQueryParams(url: URL): Record<string, any> {\n const params: Record<string, any> = {};\n const keys = Array.from(new Set(url.searchParams.keys()));\n\n for (const key of keys) {\n const values = url.searchParams.getAll(key);\n // If single value, use it directly. If multiple, keep as array.\n const rawValue = values.length === 1 ? values[0] : values;\n \n // Helper to parse individual value\n const parseValue = (val: string) => {\n if (val === 'true') return true;\n if (val === 'false') return false;\n if (val === 'null') return null;\n if (val === 'undefined') return undefined;\n \n // Try number (integers only or floats)\n // Safety check: Don't convert if it loses information (like leading zeros)\n const num = Number(val);\n if (!isNaN(num) && val.trim() !== '' && String(num) === val) {\n return num;\n }\n \n // Try JSON\n if ((val.startsWith('{') && val.endsWith('}')) || (val.startsWith('[') && val.endsWith(']'))) {\n try {\n return JSON.parse(val);\n } catch {}\n }\n \n return val;\n };\n\n if (Array.isArray(rawValue)) {\n params[key] = rawValue.map(parseValue);\n } else {\n params[key] = parseValue(rawValue as string);\n }\n }\n \n return params;\n}\n\nexport interface MSWPluginOptions {\n /**\n * Enable MSW in the browser environment\n */\n enableBrowser?: boolean;\n \n /**\n * Custom handlers to add to MSW\n */\n customHandlers?: Array<any>;\n \n /**\n * Base URL for API endpoints\n */\n baseUrl?: string;\n \n /**\n * Whether to log requests\n */\n logRequests?: boolean;\n}\n\n/**\n * MSW Plugin for ObjectStack\n\n * \n * This plugin enables Mock Service Worker integration for testing and development.\n * It automatically mocks API endpoints using the ObjectStack runtime protocol.\n * \n * @example\n * ```typescript\n * import { MSWPlugin } from '@objectstack/plugin-msw';\n * \n * // With ObjectKernel\n * const kernel = new ObjectKernel();\n * kernel.use(new MSWPlugin({\n * enableBrowser: true,\n * baseUrl: '/api/v1'\n * }));\n * ```\n */\nexport class MSWPlugin implements Plugin {\n name = 'com.objectstack.plugin.msw';\n type = 'server';\n version = '0.9.0';\n \n private options: MSWPluginOptions;\n private worker: any;\n private handlers: Array<any> = [];\n private protocol?: ObjectStackProtocol;\n private dispatcher?: HttpDispatcher;\n\n constructor(options: MSWPluginOptions = {}) {\n this.options = {\n enableBrowser: true,\n baseUrl: '/api/v1',\n logRequests: true,\n ...options\n };\n }\n\n /**\n * Init phase\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing MSW plugin', { \n enableBrowser: this.options.enableBrowser,\n baseUrl: this.options.baseUrl,\n logRequests: this.options.logRequests\n });\n // Protocol will be created in start phase\n ctx.logger.info('MSW plugin initialized');\n }\n\n /**\n * Start phase\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting MSW plugin');\n \n try {\n // 1. Try to get existing protocol service\n try {\n this.protocol = ctx.getService<ObjectStackProtocol>('protocol');\n ctx.logger.debug('Protocol service found from context');\n } catch (e) {\n // Ignore, will try to create default implementation\n }\n\n // 2. If not found, try to instantiate default implementation dynamically\n if (!this.protocol) {\n try {\n const dataEngine = ctx.getService<IDataEngine>('objectql');\n // Dynamically import ObjectStackProtocolImplementation to avoid hard dependency\n const { ObjectStackProtocolImplementation } = await import('@objectstack/objectql');\n this.protocol = new ObjectStackProtocolImplementation(dataEngine);\n ctx.logger.debug('Protocol implementation created dynamically');\n } catch (e: any) {\n if (e.code === 'ERR_MODULE_NOT_FOUND') {\n ctx.logger.warn('Module @objectstack/objectql not found. Protocol not initialized.');\n } else {\n throw e;\n }\n }\n }\n \n if (!this.protocol) {\n // Without a protocol, MSW can't serve data APIs\n ctx.logger.warn('No ObjectStackProtocol service available. MSW will only serve static/custom handlers if configured.');\n }\n\n } catch (e) {\n ctx.logger.error('Failed to initialize protocol', e as Error);\n throw new Error('[MSWPlugin] Failed to initialize protocol');\n }\n \n this.setupHandlers(ctx);\n await this.startWorker(ctx);\n }\n\n /**\n * Destroy phase\n */\n async destroy() {\n await this.stopWorker();\n }\n\n /**\n * Setup MSW handlers\n */\n private setupHandlers(ctx: PluginContext) {\n // Initialize HttpDispatcher\n try {\n this.dispatcher = new HttpDispatcher(ctx.getKernel());\n } catch (e) {\n ctx.logger.warn('[MSWPlugin] Could not initialize HttpDispatcher via Kernel. Falling back to simple handlers.');\n }\n\n const baseUrl = this.options.baseUrl || '/api/v1';\n\n // Custom handlers have priority\n this.handlers = [\n ...(this.options.customHandlers || [])\n ];\n\n // Discovery Endpoint\n this.handlers.push(\n http.get('*/.well-known/objectstack', () => {\n if (this.dispatcher) {\n return HttpResponse.json({\n data: this.dispatcher.getDiscoveryInfo(baseUrl)\n });\n }\n return HttpResponse.json({\n data: {\n version: 'v1',\n apiName: 'ObjectStack API',\n url: baseUrl,\n capabilities: {\n graphql: false,\n search: false,\n websockets: false,\n files: false,\n analytics: false,\n hub: false\n }\n }\n });\n })\n );\n\n if (this.dispatcher) {\n const dispatcher = this.dispatcher;\n \n // Catch-all handler for ObjectStack Runtime\n // We use a wildcard to capture all methods and paths under baseUrl\n const catchAll = async ({ request, params }: any) => {\n const url = new URL(request.url);\n // Calculate path relative to API prefix\n // e.g. /api/v1/data/contacts -> /data/contacts\n let path = url.pathname;\n if (path.startsWith(baseUrl)) {\n path = path.slice(baseUrl.length);\n }\n \n if (this.options.logRequests) {\n // eslint-disable-next-line no-console\n console.log(`[MSW] Intercepted: ${request.method} ${url.pathname}`, { path });\n }\n \n // Parse Body if present\n let body: any = undefined;\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n try {\n body = await request.clone().json();\n } catch (e) {\n try {\n // Try form data if json fails? \n // Dispatcher expects objects usually.\n // For file upload, body might be FormData logic needed?\n // For now assume JSON or text\n } catch (e2) {}\n }\n }\n\n // Parse Query\n const query = parseQueryParams(url);\n \n // Dispatch\n const result = await dispatcher.dispatch(\n request.method, \n path, \n body, \n query, \n { request }\n );\n\n if (result.handled) {\n if (result.response) {\n return HttpResponse.json(result.response.body, { \n status: result.response.status,\n headers: result.response.headers as any\n });\n }\n if (result.result) {\n // Handle special results (streams/redirects - unlikely in MSW but possible)\n if (result.result.type === 'redirect') {\n return HttpResponse.redirect(result.result.url);\n }\n // Fallback for others\n return HttpResponse.json(result.result);\n }\n }\n \n // Not handled by dispatcher (404 for this route subset)\n return undefined; // Let MSW pass through or handle next\n };\n\n this.handlers.push(\n http.all(`*${baseUrl}/*`, catchAll),\n http.all(`*${baseUrl}`, catchAll) // Handle root if needed\n );\n \n ctx.logger.info('MSW handlers set up using HttpDispatcher', { baseUrl });\n } else {\n ctx.logger.warn('[MSWPlugin] No dispatcher available. No API routes registered.');\n }\n }\n\n\n /**\n * Start the MSW worker\n */\n private async startWorker(ctx: PluginContext) {\n if (this.options.enableBrowser && typeof window !== 'undefined') {\n // Browser environment\n ctx.logger.debug('Starting MSW in browser mode');\n this.worker = setupWorker(...this.handlers);\n await this.worker.start({\n onUnhandledRequest: 'bypass',\n });\n ctx.logger.info('MSW started in browser mode');\n } else {\n ctx.logger.debug('MSW browser mode disabled or not in browser environment');\n }\n }\n\n /**\n * Stop the MSW worker\n */\n private async stopWorker() {\n if (this.worker) {\n this.worker.stop();\n console.log('[MSWPlugin] Stopped MSW worker');\n }\n }\n\n /**\n * Get the MSW worker instance for advanced use cases\n */\n getWorker() {\n return this.worker;\n }\n\n /**\n * Get registered handlers\n */\n getHandlers() {\n return this.handlers;\n }\n}\n\n/**\n * Static helper for interacting with ObjectStack protocol in MSW handlers\n */\nexport class ObjectStackServer {\n private static protocol: ObjectStackProtocol;\n\n static init(protocol: ObjectStackProtocol) {\n this.protocol = protocol;\n }\n\n private static getProtocol(): ObjectStackProtocol {\n if (!this.protocol) {\n throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init(protocol) first.');\n }\n return this.protocol;\n }\n\n static async findData(objectName: string, query?: any) {\n const body = await this.getProtocol().findData({ object: objectName, query });\n return { data: body, status: 200 };\n }\n\n static async getData(objectName: string, id: string) {\n const body = await this.getProtocol().getData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n\n static async createData(objectName: string, data: any) {\n const body = await this.getProtocol().createData({ object: objectName, data });\n return { data: body, status: 201 };\n }\n\n static async updateData(objectName: string, id: string, data: any) {\n const body = await this.getProtocol().updateData({ object: objectName, id, data });\n return { data: body, status: 200 };\n }\n\n static async deleteData(objectName: string, id: string) {\n const body = await this.getProtocol().deleteData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -145,6 +145,9 @@ var MSWPlugin = class {
|
|
|
145
145
|
if (path.startsWith(baseUrl)) {
|
|
146
146
|
path = path.slice(baseUrl.length);
|
|
147
147
|
}
|
|
148
|
+
if (this.options.logRequests) {
|
|
149
|
+
console.log(`[MSW] Intercepted: ${request.method} ${url.pathname}`, { path });
|
|
150
|
+
}
|
|
148
151
|
let body = void 0;
|
|
149
152
|
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
150
153
|
try {
|
|
@@ -180,8 +183,8 @@ var MSWPlugin = class {
|
|
|
180
183
|
return void 0;
|
|
181
184
|
};
|
|
182
185
|
this.handlers.push(
|
|
183
|
-
http.all(
|
|
184
|
-
http.all(
|
|
186
|
+
http.all(`*${baseUrl}/*`, catchAll),
|
|
187
|
+
http.all(`*${baseUrl}`, catchAll)
|
|
185
188
|
// Handle root if needed
|
|
186
189
|
);
|
|
187
190
|
ctx.logger.info("MSW handlers set up using HttpDispatcher", { baseUrl });
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/msw-plugin.ts"],"sourcesContent":["import { http, HttpResponse, passthrough } from 'msw';\nimport { setupWorker } from 'msw/browser';\nimport { \n Plugin, \n PluginContext, \n ObjectKernel,\n HttpDispatcher,\n HttpDispatcherResult\n} from '@objectstack/runtime';\n// import { ObjectStackProtocolImplementation } from '@objectstack/objectql';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\n\n// Helper for parsing query parameters\nfunction parseQueryParams(url: URL): Record<string, any> {\n const params: Record<string, any> = {};\n const keys = Array.from(new Set(url.searchParams.keys()));\n\n for (const key of keys) {\n const values = url.searchParams.getAll(key);\n // If single value, use it directly. If multiple, keep as array.\n const rawValue = values.length === 1 ? values[0] : values;\n \n // Helper to parse individual value\n const parseValue = (val: string) => {\n if (val === 'true') return true;\n if (val === 'false') return false;\n if (val === 'null') return null;\n if (val === 'undefined') return undefined;\n \n // Try number (integers only or floats)\n // Safety check: Don't convert if it loses information (like leading zeros)\n const num = Number(val);\n if (!isNaN(num) && val.trim() !== '' && String(num) === val) {\n return num;\n }\n \n // Try JSON\n if ((val.startsWith('{') && val.endsWith('}')) || (val.startsWith('[') && val.endsWith(']'))) {\n try {\n return JSON.parse(val);\n } catch {}\n }\n \n return val;\n };\n\n if (Array.isArray(rawValue)) {\n params[key] = rawValue.map(parseValue);\n } else {\n params[key] = parseValue(rawValue as string);\n }\n }\n \n return params;\n}\n\nexport interface MSWPluginOptions {\n /**\n * Enable MSW in the browser environment\n */\n enableBrowser?: boolean;\n \n /**\n * Custom handlers to add to MSW\n */\n customHandlers?: Array<any>;\n \n /**\n * Base URL for API endpoints\n */\n baseUrl?: string;\n \n /**\n * Whether to log requests\n */\n logRequests?: boolean;\n}\n\n/**\n * MSW Plugin for ObjectStack\n\n * \n * This plugin enables Mock Service Worker integration for testing and development.\n * It automatically mocks API endpoints using the ObjectStack runtime protocol.\n * \n * @example\n * ```typescript\n * import { MSWPlugin } from '@objectstack/plugin-msw';\n * \n * // With ObjectKernel\n * const kernel = new ObjectKernel();\n * kernel.use(new MSWPlugin({\n * enableBrowser: true,\n * baseUrl: '/api/v1'\n * }));\n * ```\n */\nexport class MSWPlugin implements Plugin {\n name = 'com.objectstack.plugin.msw';\n type = 'server';\n version = '0.9.0';\n \n private options: MSWPluginOptions;\n private worker: any;\n private handlers: Array<any> = [];\n private protocol?: ObjectStackProtocol;\n private dispatcher?: HttpDispatcher;\n\n constructor(options: MSWPluginOptions = {}) {\n this.options = {\n enableBrowser: true,\n baseUrl: '/api/v1',\n logRequests: true,\n ...options\n };\n }\n\n /**\n * Init phase\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing MSW plugin', { \n enableBrowser: this.options.enableBrowser,\n baseUrl: this.options.baseUrl,\n logRequests: this.options.logRequests\n });\n // Protocol will be created in start phase\n ctx.logger.info('MSW plugin initialized');\n }\n\n /**\n * Start phase\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting MSW plugin');\n \n try {\n // 1. Try to get existing protocol service\n try {\n this.protocol = ctx.getService<ObjectStackProtocol>('protocol');\n ctx.logger.debug('Protocol service found from context');\n } catch (e) {\n // Ignore, will try to create default implementation\n }\n\n // 2. If not found, try to instantiate default implementation dynamically\n if (!this.protocol) {\n try {\n const dataEngine = ctx.getService<IDataEngine>('objectql');\n // Dynamically import ObjectStackProtocolImplementation to avoid hard dependency\n const { ObjectStackProtocolImplementation } = await import('@objectstack/objectql');\n this.protocol = new ObjectStackProtocolImplementation(dataEngine);\n ctx.logger.debug('Protocol implementation created dynamically');\n } catch (e: any) {\n if (e.code === 'ERR_MODULE_NOT_FOUND') {\n ctx.logger.warn('Module @objectstack/objectql not found. Protocol not initialized.');\n } else {\n throw e;\n }\n }\n }\n \n if (!this.protocol) {\n // Without a protocol, MSW can't serve data APIs\n ctx.logger.warn('No ObjectStackProtocol service available. MSW will only serve static/custom handlers if configured.');\n }\n\n } catch (e) {\n ctx.logger.error('Failed to initialize protocol', e as Error);\n throw new Error('[MSWPlugin] Failed to initialize protocol');\n }\n \n this.setupHandlers(ctx);\n await this.startWorker(ctx);\n }\n\n /**\n * Destroy phase\n */\n async destroy() {\n await this.stopWorker();\n }\n\n /**\n * Setup MSW handlers\n */\n private setupHandlers(ctx: PluginContext) {\n // Initialize HttpDispatcher\n try {\n this.dispatcher = new HttpDispatcher(ctx.getKernel());\n } catch (e) {\n ctx.logger.warn('[MSWPlugin] Could not initialize HttpDispatcher via Kernel. Falling back to simple handlers.');\n }\n\n const baseUrl = this.options.baseUrl || '/api/v1';\n\n // Custom handlers have priority\n this.handlers = [\n ...(this.options.customHandlers || [])\n ];\n\n // Discovery Endpoint\n this.handlers.push(\n http.get('*/.well-known/objectstack', () => {\n if (this.dispatcher) {\n return HttpResponse.json({\n data: this.dispatcher.getDiscoveryInfo(baseUrl)\n });\n }\n return HttpResponse.json({\n data: {\n version: 'v1',\n apiName: 'ObjectStack API',\n url: baseUrl,\n capabilities: {\n graphql: false,\n search: false,\n websockets: false,\n files: false,\n analytics: false,\n hub: false\n }\n }\n });\n })\n );\n\n if (this.dispatcher) {\n const dispatcher = this.dispatcher;\n \n // Catch-all handler for ObjectStack Runtime\n // We use a wildcard to capture all methods and paths under baseUrl\n const catchAll = async ({ request, params }: any) => {\n const url = new URL(request.url);\n // Calculate path relative to API prefix\n // e.g. /api/v1/data/contacts -> /data/contacts\n let path = url.pathname;\n if (path.startsWith(baseUrl)) {\n path = path.slice(baseUrl.length);\n }\n \n // Parse Body if present\n let body: any = undefined;\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n try {\n body = await request.clone().json();\n } catch (e) {\n try {\n // Try form data if json fails? \n // Dispatcher expects objects usually.\n // For file upload, body might be FormData logic needed?\n // For now assume JSON or text\n } catch (e2) {}\n }\n }\n\n // Parse Query\n const query = parseQueryParams(url);\n \n // Dispatch\n const result = await dispatcher.dispatch(\n request.method, \n path, \n body, \n query, \n { request }\n );\n\n if (result.handled) {\n if (result.response) {\n return HttpResponse.json(result.response.body, { \n status: result.response.status,\n headers: result.response.headers as any\n });\n }\n if (result.result) {\n // Handle special results (streams/redirects - unlikely in MSW but possible)\n if (result.result.type === 'redirect') {\n return HttpResponse.redirect(result.result.url);\n }\n // Fallback for others\n return HttpResponse.json(result.result);\n }\n }\n \n // Not handled by dispatcher (404 for this route subset)\n return undefined; // Let MSW pass through or handle next\n };\n\n this.handlers.push(\n http.all(`${baseUrl}/*`, catchAll),\n http.all(`${baseUrl}`, catchAll) // Handle root if needed\n );\n \n ctx.logger.info('MSW handlers set up using HttpDispatcher', { baseUrl });\n } else {\n ctx.logger.warn('[MSWPlugin] No dispatcher available. No API routes registered.');\n }\n }\n\n\n /**\n * Start the MSW worker\n */\n private async startWorker(ctx: PluginContext) {\n if (this.options.enableBrowser && typeof window !== 'undefined') {\n // Browser environment\n ctx.logger.debug('Starting MSW in browser mode');\n this.worker = setupWorker(...this.handlers);\n await this.worker.start({\n onUnhandledRequest: 'bypass',\n });\n ctx.logger.info('MSW started in browser mode');\n } else {\n ctx.logger.debug('MSW browser mode disabled or not in browser environment');\n }\n }\n\n /**\n * Stop the MSW worker\n */\n private async stopWorker() {\n if (this.worker) {\n this.worker.stop();\n console.log('[MSWPlugin] Stopped MSW worker');\n }\n }\n\n /**\n * Get the MSW worker instance for advanced use cases\n */\n getWorker() {\n return this.worker;\n }\n\n /**\n * Get registered handlers\n */\n getHandlers() {\n return this.handlers;\n }\n}\n\n/**\n * Static helper for interacting with ObjectStack protocol in MSW handlers\n */\nexport class ObjectStackServer {\n private static protocol: ObjectStackProtocol;\n\n static init(protocol: ObjectStackProtocol) {\n this.protocol = protocol;\n }\n\n private static getProtocol(): ObjectStackProtocol {\n if (!this.protocol) {\n throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init(protocol) first.');\n }\n return this.protocol;\n }\n\n static async findData(objectName: string, query?: any) {\n const body = await this.getProtocol().findData({ object: objectName, query });\n return { data: body, status: 200 };\n }\n\n static async getData(objectName: string, id: string) {\n const body = await this.getProtocol().getData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n\n static async createData(objectName: string, data: any) {\n const body = await this.getProtocol().createData({ object: objectName, data });\n return { data: body, status: 201 };\n }\n\n static async updateData(objectName: string, id: string, data: any) {\n const body = await this.getProtocol().updateData({ object: objectName, id, data });\n return { data: body, status: 200 };\n }\n\n static async deleteData(objectName: string, id: string) {\n const body = await this.getProtocol().deleteData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/msw-plugin.ts"],"sourcesContent":["import { http, HttpResponse, passthrough } from 'msw';\nimport { setupWorker } from 'msw/browser';\nimport { \n Plugin, \n PluginContext, \n ObjectKernel,\n HttpDispatcher,\n HttpDispatcherResult\n} from '@objectstack/runtime';\n// import { ObjectStackProtocolImplementation } from '@objectstack/objectql';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\n\n// Helper for parsing query parameters\nfunction parseQueryParams(url: URL): Record<string, any> {\n const params: Record<string, any> = {};\n const keys = Array.from(new Set(url.searchParams.keys()));\n\n for (const key of keys) {\n const values = url.searchParams.getAll(key);\n // If single value, use it directly. If multiple, keep as array.\n const rawValue = values.length === 1 ? values[0] : values;\n \n // Helper to parse individual value\n const parseValue = (val: string) => {\n if (val === 'true') return true;\n if (val === 'false') return false;\n if (val === 'null') return null;\n if (val === 'undefined') return undefined;\n \n // Try number (integers only or floats)\n // Safety check: Don't convert if it loses information (like leading zeros)\n const num = Number(val);\n if (!isNaN(num) && val.trim() !== '' && String(num) === val) {\n return num;\n }\n \n // Try JSON\n if ((val.startsWith('{') && val.endsWith('}')) || (val.startsWith('[') && val.endsWith(']'))) {\n try {\n return JSON.parse(val);\n } catch {}\n }\n \n return val;\n };\n\n if (Array.isArray(rawValue)) {\n params[key] = rawValue.map(parseValue);\n } else {\n params[key] = parseValue(rawValue as string);\n }\n }\n \n return params;\n}\n\nexport interface MSWPluginOptions {\n /**\n * Enable MSW in the browser environment\n */\n enableBrowser?: boolean;\n \n /**\n * Custom handlers to add to MSW\n */\n customHandlers?: Array<any>;\n \n /**\n * Base URL for API endpoints\n */\n baseUrl?: string;\n \n /**\n * Whether to log requests\n */\n logRequests?: boolean;\n}\n\n/**\n * MSW Plugin for ObjectStack\n\n * \n * This plugin enables Mock Service Worker integration for testing and development.\n * It automatically mocks API endpoints using the ObjectStack runtime protocol.\n * \n * @example\n * ```typescript\n * import { MSWPlugin } from '@objectstack/plugin-msw';\n * \n * // With ObjectKernel\n * const kernel = new ObjectKernel();\n * kernel.use(new MSWPlugin({\n * enableBrowser: true,\n * baseUrl: '/api/v1'\n * }));\n * ```\n */\nexport class MSWPlugin implements Plugin {\n name = 'com.objectstack.plugin.msw';\n type = 'server';\n version = '0.9.0';\n \n private options: MSWPluginOptions;\n private worker: any;\n private handlers: Array<any> = [];\n private protocol?: ObjectStackProtocol;\n private dispatcher?: HttpDispatcher;\n\n constructor(options: MSWPluginOptions = {}) {\n this.options = {\n enableBrowser: true,\n baseUrl: '/api/v1',\n logRequests: true,\n ...options\n };\n }\n\n /**\n * Init phase\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing MSW plugin', { \n enableBrowser: this.options.enableBrowser,\n baseUrl: this.options.baseUrl,\n logRequests: this.options.logRequests\n });\n // Protocol will be created in start phase\n ctx.logger.info('MSW plugin initialized');\n }\n\n /**\n * Start phase\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting MSW plugin');\n \n try {\n // 1. Try to get existing protocol service\n try {\n this.protocol = ctx.getService<ObjectStackProtocol>('protocol');\n ctx.logger.debug('Protocol service found from context');\n } catch (e) {\n // Ignore, will try to create default implementation\n }\n\n // 2. If not found, try to instantiate default implementation dynamically\n if (!this.protocol) {\n try {\n const dataEngine = ctx.getService<IDataEngine>('objectql');\n // Dynamically import ObjectStackProtocolImplementation to avoid hard dependency\n const { ObjectStackProtocolImplementation } = await import('@objectstack/objectql');\n this.protocol = new ObjectStackProtocolImplementation(dataEngine);\n ctx.logger.debug('Protocol implementation created dynamically');\n } catch (e: any) {\n if (e.code === 'ERR_MODULE_NOT_FOUND') {\n ctx.logger.warn('Module @objectstack/objectql not found. Protocol not initialized.');\n } else {\n throw e;\n }\n }\n }\n \n if (!this.protocol) {\n // Without a protocol, MSW can't serve data APIs\n ctx.logger.warn('No ObjectStackProtocol service available. MSW will only serve static/custom handlers if configured.');\n }\n\n } catch (e) {\n ctx.logger.error('Failed to initialize protocol', e as Error);\n throw new Error('[MSWPlugin] Failed to initialize protocol');\n }\n \n this.setupHandlers(ctx);\n await this.startWorker(ctx);\n }\n\n /**\n * Destroy phase\n */\n async destroy() {\n await this.stopWorker();\n }\n\n /**\n * Setup MSW handlers\n */\n private setupHandlers(ctx: PluginContext) {\n // Initialize HttpDispatcher\n try {\n this.dispatcher = new HttpDispatcher(ctx.getKernel());\n } catch (e) {\n ctx.logger.warn('[MSWPlugin] Could not initialize HttpDispatcher via Kernel. Falling back to simple handlers.');\n }\n\n const baseUrl = this.options.baseUrl || '/api/v1';\n\n // Custom handlers have priority\n this.handlers = [\n ...(this.options.customHandlers || [])\n ];\n\n // Discovery Endpoint\n this.handlers.push(\n http.get('*/.well-known/objectstack', () => {\n if (this.dispatcher) {\n return HttpResponse.json({\n data: this.dispatcher.getDiscoveryInfo(baseUrl)\n });\n }\n return HttpResponse.json({\n data: {\n version: 'v1',\n apiName: 'ObjectStack API',\n url: baseUrl,\n capabilities: {\n graphql: false,\n search: false,\n websockets: false,\n files: false,\n analytics: false,\n hub: false\n }\n }\n });\n })\n );\n\n if (this.dispatcher) {\n const dispatcher = this.dispatcher;\n \n // Catch-all handler for ObjectStack Runtime\n // We use a wildcard to capture all methods and paths under baseUrl\n const catchAll = async ({ request, params }: any) => {\n const url = new URL(request.url);\n // Calculate path relative to API prefix\n // e.g. /api/v1/data/contacts -> /data/contacts\n let path = url.pathname;\n if (path.startsWith(baseUrl)) {\n path = path.slice(baseUrl.length);\n }\n \n if (this.options.logRequests) {\n // eslint-disable-next-line no-console\n console.log(`[MSW] Intercepted: ${request.method} ${url.pathname}`, { path });\n }\n \n // Parse Body if present\n let body: any = undefined;\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n try {\n body = await request.clone().json();\n } catch (e) {\n try {\n // Try form data if json fails? \n // Dispatcher expects objects usually.\n // For file upload, body might be FormData logic needed?\n // For now assume JSON or text\n } catch (e2) {}\n }\n }\n\n // Parse Query\n const query = parseQueryParams(url);\n \n // Dispatch\n const result = await dispatcher.dispatch(\n request.method, \n path, \n body, \n query, \n { request }\n );\n\n if (result.handled) {\n if (result.response) {\n return HttpResponse.json(result.response.body, { \n status: result.response.status,\n headers: result.response.headers as any\n });\n }\n if (result.result) {\n // Handle special results (streams/redirects - unlikely in MSW but possible)\n if (result.result.type === 'redirect') {\n return HttpResponse.redirect(result.result.url);\n }\n // Fallback for others\n return HttpResponse.json(result.result);\n }\n }\n \n // Not handled by dispatcher (404 for this route subset)\n return undefined; // Let MSW pass through or handle next\n };\n\n this.handlers.push(\n http.all(`*${baseUrl}/*`, catchAll),\n http.all(`*${baseUrl}`, catchAll) // Handle root if needed\n );\n \n ctx.logger.info('MSW handlers set up using HttpDispatcher', { baseUrl });\n } else {\n ctx.logger.warn('[MSWPlugin] No dispatcher available. No API routes registered.');\n }\n }\n\n\n /**\n * Start the MSW worker\n */\n private async startWorker(ctx: PluginContext) {\n if (this.options.enableBrowser && typeof window !== 'undefined') {\n // Browser environment\n ctx.logger.debug('Starting MSW in browser mode');\n this.worker = setupWorker(...this.handlers);\n await this.worker.start({\n onUnhandledRequest: 'bypass',\n });\n ctx.logger.info('MSW started in browser mode');\n } else {\n ctx.logger.debug('MSW browser mode disabled or not in browser environment');\n }\n }\n\n /**\n * Stop the MSW worker\n */\n private async stopWorker() {\n if (this.worker) {\n this.worker.stop();\n console.log('[MSWPlugin] Stopped MSW worker');\n }\n }\n\n /**\n * Get the MSW worker instance for advanced use cases\n */\n getWorker() {\n return this.worker;\n }\n\n /**\n * Get registered handlers\n */\n getHandlers() {\n return this.handlers;\n }\n}\n\n/**\n * Static helper for interacting with ObjectStack protocol in MSW handlers\n */\nexport class ObjectStackServer {\n private static protocol: ObjectStackProtocol;\n\n static init(protocol: ObjectStackProtocol) {\n this.protocol = protocol;\n }\n\n private static getProtocol(): ObjectStackProtocol {\n if (!this.protocol) {\n throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init(protocol) first.');\n }\n return this.protocol;\n }\n\n static async findData(objectName: string, query?: any) {\n const body = await this.getProtocol().findData({ object: objectName, query });\n return { data: body, status: 200 };\n }\n\n static async getData(objectName: string, id: string) {\n const body = await this.getProtocol().getData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n\n static async createData(objectName: string, data: any) {\n const body = await this.getProtocol().createData({ object: objectName, data });\n return { data: body, status: 201 };\n }\n\n static async updateData(objectName: string, id: string, data: any) {\n const body = await this.getProtocol().updateData({ object: objectName, id, data });\n return { data: body, status: 200 };\n }\n\n static async deleteData(objectName: string, id: string) {\n const body = await this.getProtocol().deleteData({ object: objectName, id });\n return { data: body, status: 200 };\n }\n}\n"],"mappings":";AAAA,SAAS,MAAM,oBAAiC;AAChD,SAAS,mBAAmB;AAC5B;AAAA,EAII;AAAA,OAEG;AAMP,SAAS,iBAAiB,KAA+B;AACrD,QAAM,SAA8B,CAAC;AACrC,QAAM,OAAO,MAAM,KAAK,IAAI,IAAI,IAAI,aAAa,KAAK,CAAC,CAAC;AAExD,aAAW,OAAO,MAAM;AACpB,UAAM,SAAS,IAAI,aAAa,OAAO,GAAG;AAE1C,UAAM,WAAW,OAAO,WAAW,IAAI,OAAO,CAAC,IAAI;AAGnD,UAAM,aAAa,CAAC,QAAgB;AAChC,UAAI,QAAQ,OAAQ,QAAO;AAC3B,UAAI,QAAQ,QAAS,QAAO;AAC5B,UAAI,QAAQ,OAAQ,QAAO;AAC3B,UAAI,QAAQ,YAAa,QAAO;AAIhC,YAAM,MAAM,OAAO,GAAG;AACtB,UAAI,CAAC,MAAM,GAAG,KAAK,IAAI,KAAK,MAAM,MAAM,OAAO,GAAG,MAAM,KAAK;AACzD,eAAO;AAAA,MACX;AAGA,UAAK,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,KAAO,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAI;AAC1F,YAAI;AACA,iBAAO,KAAK,MAAM,GAAG;AAAA,QACzB,QAAQ;AAAA,QAAC;AAAA,MACb;AAEA,aAAO;AAAA,IACX;AAEA,QAAI,MAAM,QAAQ,QAAQ,GAAG;AACzB,aAAO,GAAG,IAAI,SAAS,IAAI,UAAU;AAAA,IACzC,OAAO;AACH,aAAO,GAAG,IAAI,WAAW,QAAkB;AAAA,IAC/C;AAAA,EACJ;AAEA,SAAO;AACX;AA2CO,IAAM,YAAN,MAAkC;AAAA,EAWrC,YAAY,UAA4B,CAAC,GAAG;AAV5C,gBAAO;AACP,gBAAO;AACP,mBAAU;AAIV,SAAQ,WAAuB,CAAC;AAgBhC;AAAA;AAAA;AAAA,gBAAO,OAAO,QAAuB;AACjC,UAAI,OAAO,MAAM,2BAA2B;AAAA,QACxC,eAAe,KAAK,QAAQ;AAAA,QAC5B,SAAS,KAAK,QAAQ;AAAA,QACtB,aAAa,KAAK,QAAQ;AAAA,MAC9B,CAAC;AAED,UAAI,OAAO,KAAK,wBAAwB;AAAA,IAC5C;AAKA;AAAA;AAAA;AAAA,iBAAQ,OAAO,QAAuB;AAClC,UAAI,OAAO,MAAM,qBAAqB;AAEtC,UAAI;AAEA,YAAI;AACA,eAAK,WAAW,IAAI,WAAgC,UAAU;AAC9D,cAAI,OAAO,MAAM,qCAAqC;AAAA,QAC1D,SAAS,GAAG;AAAA,QAEZ;AAGA,YAAI,CAAC,KAAK,UAAU;AAChB,cAAI;AACA,kBAAM,aAAa,IAAI,WAAwB,UAAU;AAEzD,kBAAM,EAAE,kCAAkC,IAAI,MAAM,OAAO,uBAAuB;AAClF,iBAAK,WAAW,IAAI,kCAAkC,UAAU;AAChE,gBAAI,OAAO,MAAM,6CAA6C;AAAA,UAClE,SAAS,GAAQ;AACb,gBAAI,EAAE,SAAS,wBAAwB;AAClC,kBAAI,OAAO,KAAK,mEAAmE;AAAA,YACxF,OAAO;AACF,oBAAM;AAAA,YACX;AAAA,UACJ;AAAA,QACJ;AAEA,YAAI,CAAC,KAAK,UAAU;AAEhB,cAAI,OAAO,KAAK,qGAAqG;AAAA,QACzH;AAAA,MAEJ,SAAS,GAAG;AACR,YAAI,OAAO,MAAM,iCAAiC,CAAU;AAC5D,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC/D;AAEA,WAAK,cAAc,GAAG;AACtB,YAAM,KAAK,YAAY,GAAG;AAAA,IAC9B;AAjEI,SAAK,UAAU;AAAA,MACX,eAAe;AAAA,MACf,SAAS;AAAA,MACT,aAAa;AAAA,MACb,GAAG;AAAA,IACP;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAgEA,MAAM,UAAU;AACZ,UAAM,KAAK,WAAW;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,KAAoB;AAEtC,QAAI;AACA,WAAK,aAAa,IAAI,eAAe,IAAI,UAAU,CAAC;AAAA,IACxD,SAAS,GAAG;AACR,UAAI,OAAO,KAAK,8FAA8F;AAAA,IAClH;AAEA,UAAM,UAAU,KAAK,QAAQ,WAAW;AAGxC,SAAK,WAAW;AAAA,MACZ,GAAI,KAAK,QAAQ,kBAAkB,CAAC;AAAA,IACxC;AAGA,SAAK,SAAS;AAAA,MACV,KAAK,IAAI,6BAA6B,MAAM;AACxC,YAAI,KAAK,YAAY;AACjB,iBAAO,aAAa,KAAK;AAAA,YACrB,MAAM,KAAK,WAAW,iBAAiB,OAAO;AAAA,UAClD,CAAC;AAAA,QACL;AACA,eAAO,aAAa,KAAK;AAAA,UACrB,MAAM;AAAA,YACF,SAAS;AAAA,YACT,SAAS;AAAA,YACT,KAAK;AAAA,YACL,cAAc;AAAA,cACV,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,WAAW;AAAA,cACX,KAAK;AAAA,YACT;AAAA,UACJ;AAAA,QACJ,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAEA,QAAI,KAAK,YAAY;AACjB,YAAM,aAAa,KAAK;AAIxB,YAAM,WAAW,OAAO,EAAE,SAAS,OAAO,MAAW;AACjD,cAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAG/B,YAAI,OAAO,IAAI;AACf,YAAI,KAAK,WAAW,OAAO,GAAG;AAC1B,iBAAO,KAAK,MAAM,QAAQ,MAAM;AAAA,QACpC;AAEA,YAAI,KAAK,QAAQ,aAAa;AAE1B,kBAAQ,IAAI,sBAAsB,QAAQ,MAAM,IAAI,IAAI,QAAQ,IAAI,EAAE,KAAK,CAAC;AAAA,QAChF;AAGA,YAAI,OAAY;AAChB,YAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,QAAQ;AACvD,cAAI;AACA,mBAAO,MAAM,QAAQ,MAAM,EAAE,KAAK;AAAA,UACtC,SAAS,GAAG;AACR,gBAAI;AAAA,YAKJ,SAAS,IAAI;AAAA,YAAC;AAAA,UAClB;AAAA,QACJ;AAGA,cAAM,QAAQ,iBAAiB,GAAG;AAGlC,cAAM,SAAS,MAAM,WAAW;AAAA,UAC5B,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA,EAAE,QAAQ;AAAA,QACd;AAEA,YAAI,OAAO,SAAS;AAChB,cAAI,OAAO,UAAU;AACjB,mBAAO,aAAa,KAAK,OAAO,SAAS,MAAM;AAAA,cAC3C,QAAQ,OAAO,SAAS;AAAA,cACxB,SAAS,OAAO,SAAS;AAAA,YAC7B,CAAC;AAAA,UACL;AACA,cAAI,OAAO,QAAQ;AAEd,gBAAI,OAAO,OAAO,SAAS,YAAY;AACnC,qBAAO,aAAa,SAAS,OAAO,OAAO,GAAG;AAAA,YAClD;AAEA,mBAAO,aAAa,KAAK,OAAO,MAAM;AAAA,UAC3C;AAAA,QACJ;AAGA,eAAO;AAAA,MACX;AAEA,WAAK,SAAS;AAAA,QACV,KAAK,IAAI,IAAI,OAAO,MAAM,QAAQ;AAAA,QAClC,KAAK,IAAI,IAAI,OAAO,IAAI,QAAQ;AAAA;AAAA,MACpC;AAEA,UAAI,OAAO,KAAK,4CAA4C,EAAE,QAAQ,CAAC;AAAA,IAC3E,OAAO;AACF,UAAI,OAAO,KAAK,gEAAgE;AAAA,IACrF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAY,KAAoB;AAC1C,QAAI,KAAK,QAAQ,iBAAiB,OAAO,WAAW,aAAa;AAE7D,UAAI,OAAO,MAAM,8BAA8B;AAC/C,WAAK,SAAS,YAAY,GAAG,KAAK,QAAQ;AAC1C,YAAM,KAAK,OAAO,MAAM;AAAA,QACpB,oBAAoB;AAAA,MACxB,CAAC;AACD,UAAI,OAAO,KAAK,6BAA6B;AAAA,IACjD,OAAO;AACH,UAAI,OAAO,MAAM,yDAAyD;AAAA,IAC9E;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAAa;AACvB,QAAI,KAAK,QAAQ;AACb,WAAK,OAAO,KAAK;AACjB,cAAQ,IAAI,gCAAgC;AAAA,IAChD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY;AACR,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACV,WAAO,KAAK;AAAA,EAChB;AACJ;AAKO,IAAM,oBAAN,MAAwB;AAAA,EAG3B,OAAO,KAAK,UAA+B;AACvC,SAAK,WAAW;AAAA,EACpB;AAAA,EAEA,OAAe,cAAmC;AAC9C,QAAI,CAAC,KAAK,UAAU;AAChB,YAAM,IAAI,MAAM,iFAAiF;AAAA,IACrG;AACA,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,aAAa,SAAS,YAAoB,OAAa;AACnD,UAAM,OAAO,MAAM,KAAK,YAAY,EAAE,SAAS,EAAE,QAAQ,YAAY,MAAM,CAAC;AAC5E,WAAO,EAAE,MAAM,MAAM,QAAQ,IAAI;AAAA,EACrC;AAAA,EAEA,aAAa,QAAQ,YAAoB,IAAY;AACjD,UAAM,OAAO,MAAM,KAAK,YAAY,EAAE,QAAQ,EAAE,QAAQ,YAAY,GAAG,CAAC;AACxE,WAAO,EAAE,MAAM,MAAM,QAAQ,IAAI;AAAA,EACrC;AAAA,EAEA,aAAa,WAAW,YAAoB,MAAW;AACnD,UAAM,OAAO,MAAM,KAAK,YAAY,EAAE,WAAW,EAAE,QAAQ,YAAY,KAAK,CAAC;AAC7E,WAAO,EAAE,MAAM,MAAM,QAAQ,IAAI;AAAA,EACrC;AAAA,EAEA,aAAa,WAAW,YAAoB,IAAY,MAAW;AAC/D,UAAM,OAAO,MAAM,KAAK,YAAY,EAAE,WAAW,EAAE,QAAQ,YAAY,IAAI,KAAK,CAAC;AACjF,WAAO,EAAE,MAAM,MAAM,QAAQ,IAAI;AAAA,EACrC;AAAA,EAEA,aAAa,WAAW,YAAoB,IAAY;AACpD,UAAM,OAAO,MAAM,KAAK,YAAY,EAAE,WAAW,EAAE,QAAQ,YAAY,GAAG,CAAC;AAC3E,WAAO,EAAE,MAAM,MAAM,QAAQ,IAAI;AAAA,EACrC;AACJ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/plugin-msw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "MSW (Mock Service Worker) Plugin for ObjectStack Runtime",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
8
15
|
"peerDependencies": {
|
|
9
|
-
"@objectstack/runtime": "1.0.
|
|
16
|
+
"@objectstack/runtime": "1.0.12"
|
|
10
17
|
},
|
|
11
18
|
"dependencies": {
|
|
12
19
|
"msw": "^2.0.0",
|
|
13
|
-
"@objectstack/core": "1.0.
|
|
14
|
-
"@objectstack/objectql": "1.0.
|
|
15
|
-
"@objectstack/spec": "1.0.
|
|
16
|
-
"@objectstack/types": "1.0.
|
|
20
|
+
"@objectstack/core": "1.0.12",
|
|
21
|
+
"@objectstack/objectql": "1.0.12",
|
|
22
|
+
"@objectstack/spec": "1.0.12",
|
|
23
|
+
"@objectstack/types": "1.0.12"
|
|
17
24
|
},
|
|
18
25
|
"devDependencies": {
|
|
19
26
|
"@types/node": "^25.1.0",
|
|
20
27
|
"typescript": "^5.0.0",
|
|
21
28
|
"vitest": "^4.0.18",
|
|
22
|
-
"@objectstack/runtime": "1.0.
|
|
29
|
+
"@objectstack/runtime": "1.0.12"
|
|
23
30
|
},
|
|
24
31
|
"scripts": {
|
|
25
32
|
"build": "tsup --config ../../../tsup.config.ts",
|
package/src/msw-plugin.ts
CHANGED
|
@@ -240,6 +240,11 @@ export class MSWPlugin implements Plugin {
|
|
|
240
240
|
path = path.slice(baseUrl.length);
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
if (this.options.logRequests) {
|
|
244
|
+
// eslint-disable-next-line no-console
|
|
245
|
+
console.log(`[MSW] Intercepted: ${request.method} ${url.pathname}`, { path });
|
|
246
|
+
}
|
|
247
|
+
|
|
243
248
|
// Parse Body if present
|
|
244
249
|
let body: any = undefined;
|
|
245
250
|
if (request.method !== 'GET' && request.method !== 'HEAD') {
|
|
@@ -289,8 +294,8 @@ export class MSWPlugin implements Plugin {
|
|
|
289
294
|
};
|
|
290
295
|
|
|
291
296
|
this.handlers.push(
|
|
292
|
-
http.all(
|
|
293
|
-
http.all(
|
|
297
|
+
http.all(`*${baseUrl}/*`, catchAll),
|
|
298
|
+
http.all(`*${baseUrl}`, catchAll) // Handle root if needed
|
|
294
299
|
);
|
|
295
300
|
|
|
296
301
|
ctx.logger.info('MSW handlers set up using HttpDispatcher', { baseUrl });
|