@mocklane/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,24 +22,42 @@ Mocklane turns a pasted data model and a plain-language request into a structure
22
22
  - Node.js 20 or newer
23
23
  - A modern browser with WebGPU for Transformers.js and WebLLM
24
24
  - Enough browser storage and memory for the selected local model
25
+ - pnpm 9 when installing from GitHub source
25
26
 
26
27
  Native Browser AI is shown only when the browser exposes the `LanguageModel` API. The first Transformers.js or WebLLM load downloads model assets; later loads can reuse the browser cache.
27
28
 
28
- ## Quick Start
29
+ ## Installation
30
+
31
+ Choose either npm or the GitHub source repository. Both launch the same `mocklane` CLI.
29
32
 
30
- Run Mocklane without installing it globally:
33
+ ### Option 1: npm
34
+
35
+ Run Mocklane once with `npx`:
31
36
 
32
37
  ```bash
33
- npx mocklane
38
+ npx @mocklane/core
34
39
  ```
35
40
 
36
- For a global installation:
41
+ Or install the package globally and run the installed `mocklane` command:
37
42
 
38
43
  ```bash
39
- npm install --global mocklane
44
+ npm install --global @mocklane/core
40
45
  mocklane
41
46
  ```
42
47
 
48
+ ### Option 2: GitHub
49
+
50
+ Clone the source, install dependencies, and launch the locally built CLI:
51
+
52
+ ```bash
53
+ git clone https://github.com/aasispaudel/Mocklane.git
54
+ cd Mocklane
55
+ pnpm install
56
+ pnpm mocklane:build
57
+ ```
58
+
59
+ ## Quick Start
60
+
43
61
  Mocklane starts two local servers and opens the browser workspace automatically:
44
62
 
45
63
  ```text
@@ -48,6 +66,8 @@ Mock API proxy: http://localhost:4000
48
66
  Upstream server: none (standalone mode)
49
67
  ```
50
68
 
69
+ If the default ports are busy, Mocklane automatically tries the next local pair, such as `4002/4003`, then `4004/4005`.
70
+
51
71
  In the browser:
52
72
 
53
73
  1. Select an AI provider and model.
@@ -133,7 +153,7 @@ Invalid JSON cannot be saved. Mocklane displays the parser error in the editor s
133
153
  Standalone mode is the default:
134
154
 
135
155
  ```bash
136
- npx mocklane
156
+ npx @mocklane/core
137
157
  ```
138
158
 
139
159
  Registered routes return their configured mock responses. Unmatched routes return `404`:
@@ -153,7 +173,7 @@ Mocks are matched by HTTP method and exact pathname. Query strings do not affect
153
173
  Use proxy mode when an application already has a backend and only selected routes should be mocked:
154
174
 
155
175
  ```bash
156
- npx mocklane --target http://localhost:8000
176
+ npx @mocklane/core --target http://localhost:8000
157
177
  ```
158
178
 
159
179
  Point the application at `http://localhost:4000` instead of the upstream server:
@@ -192,19 +212,20 @@ Options:
192
212
  ### Custom ports
193
213
 
194
214
  ```bash
195
- npx mocklane --proxy-port 5000 --ui-port 5001
215
+ npx @mocklane/core --proxy-port 5000 --ui-port 5001
196
216
  ```
197
217
 
198
218
  ### Proxy with custom ports
199
219
 
200
220
  ```bash
201
- npx mocklane \
221
+ npx @mocklane/core \
202
222
  --target http://localhost:8000 \
203
223
  --proxy-port 5000 \
204
224
  --ui-port 5001
205
225
  ```
206
226
 
207
227
  The proxy and UI ports must be different. Both servers bind to `127.0.0.1` and are not exposed to the local network.
228
+ When custom ports are provided, Mocklane uses those exact ports.
208
229
 
209
230
  ## Local Control API
210
231
 
package/dist/cli.js CHANGED
@@ -38,28 +38,40 @@ async function startMocklaneServers({
38
38
  proxyPort,
39
39
  uiPort,
40
40
  target,
41
- uiDirectory
41
+ uiDirectory,
42
+ allowPortFallback = false
42
43
  }) {
43
44
  const registry = new MockRegistry();
44
- const proxyServer = createServer((request, response) => {
45
- handleProxyRequest(request, response, registry, target);
46
- });
47
- const uiServer = createServer((request, response) => {
48
- void handleUiRequest(request, response, registry, uiDirectory, proxyPort);
49
- });
50
- try {
51
- await listen(proxyServer, proxyPort, host);
52
- await listen(uiServer, uiPort, host);
53
- } catch (error) {
54
- await closeServer(proxyServer);
55
- await closeServer(uiServer);
56
- throw error;
57
- }
58
- return {
59
- close: async () => {
60
- await Promise.all([closeServer(proxyServer), closeServer(uiServer)]);
45
+ let candidateProxyPort = proxyPort;
46
+ let candidateUiPort = uiPort;
47
+ while (candidateProxyPort <= 65534 && candidateUiPort <= 65535) {
48
+ const activeProxyPort = candidateProxyPort;
49
+ const activeUiPort = candidateUiPort;
50
+ const proxyServer = createServer((request, response) => {
51
+ handleProxyRequest(request, response, registry, target);
52
+ });
53
+ const uiServer = createServer((request, response) => {
54
+ void handleUiRequest(request, response, registry, uiDirectory, activeProxyPort);
55
+ });
56
+ try {
57
+ await listen(proxyServer, activeProxyPort, host);
58
+ await listen(uiServer, activeUiPort, host);
59
+ return {
60
+ proxyPort: activeProxyPort,
61
+ uiPort: activeUiPort,
62
+ close: async () => {
63
+ await Promise.all([closeServer(proxyServer), closeServer(uiServer)]);
64
+ }
65
+ };
66
+ } catch (error) {
67
+ await closeServer(proxyServer);
68
+ await closeServer(uiServer);
69
+ if (!allowPortFallback || !isAddressInUse(error)) throw error;
70
+ candidateProxyPort += 2;
71
+ candidateUiPort += 2;
61
72
  }
62
- };
73
+ }
74
+ throw new Error("Mocklane could not find an available local port pair.");
63
75
  }
64
76
  async function handleUiRequest(request, response, registry, uiDirectory, proxyPort) {
65
77
  const url = new URL(request.url ?? "/", "http://localhost");
@@ -225,6 +237,9 @@ function listen(server, port, host) {
225
237
  });
226
238
  });
227
239
  }
240
+ function isAddressInUse(error) {
241
+ return error instanceof Error && "code" in error && error.code === "EADDRINUSE";
242
+ }
228
243
  function closeServer(server) {
229
244
  return new Promise((resolvePromise) => {
230
245
  if (!server.listening) {
@@ -251,11 +266,15 @@ async function main() {
251
266
  proxyPort: options.proxyPort,
252
267
  uiPort: options.uiPort,
253
268
  target: options.target,
254
- uiDirectory
269
+ uiDirectory,
270
+ allowPortFallback: !options.hasCustomPorts
255
271
  });
256
- const uiUrl = `http://localhost:${options.uiPort}`;
272
+ const uiUrl = `http://localhost:${servers.uiPort}`;
273
+ if (!options.hasCustomPorts && (servers.proxyPort !== DEFAULT_PROXY_PORT || servers.uiPort !== DEFAULT_UI_PORT)) {
274
+ console.log(red(`Port ${DEFAULT_PROXY_PORT} is in use. Using ${servers.proxyPort} instead.`));
275
+ }
257
276
  console.log(`Mocklane UI: ${uiUrl}`);
258
- console.log(`Mock API proxy: http://localhost:${options.proxyPort}`);
277
+ console.log(`Mock API proxy: http://localhost:${servers.proxyPort}`);
259
278
  console.log(`Upstream server: ${options.target?.origin ?? "none (standalone mode)"}`);
260
279
  console.log("Press Ctrl+C to stop.");
261
280
  openBrowser(uiUrl);
@@ -271,16 +290,21 @@ function parseArguments(argumentsList) {
271
290
  let proxyPort = DEFAULT_PROXY_PORT;
272
291
  let uiPort = DEFAULT_UI_PORT;
273
292
  let help = false;
293
+ let hasCustomPorts = false;
274
294
  for (let index = 0; index < argumentsList.length; index += 1) {
275
295
  const argument = argumentsList[index];
276
296
  if (argument === "--target") target = new URL(requireValue(argumentsList, ++index, argument));
277
- else if (argument === "--proxy-port") proxyPort = parsePort(requireValue(argumentsList, ++index, argument));
278
- else if (argument === "--ui-port") uiPort = parsePort(requireValue(argumentsList, ++index, argument));
279
- else if (argument === "--help" || argument === "-h") help = true;
297
+ else if (argument === "--proxy-port") {
298
+ proxyPort = parsePort(requireValue(argumentsList, ++index, argument));
299
+ hasCustomPorts = true;
300
+ } else if (argument === "--ui-port") {
301
+ uiPort = parsePort(requireValue(argumentsList, ++index, argument));
302
+ hasCustomPorts = true;
303
+ } else if (argument === "--help" || argument === "-h") help = true;
280
304
  else throw new Error(`Unknown argument: ${argument}`);
281
305
  }
282
306
  if (proxyPort === uiPort) throw new Error("Proxy and UI ports must be different.");
283
- return { target, proxyPort, uiPort, help };
307
+ return { target, proxyPort, uiPort, help, hasCustomPorts };
284
308
  }
285
309
  function requireValue(argumentsList, index, flag) {
286
310
  const value = argumentsList[index];
@@ -299,6 +323,9 @@ function openBrowser(url) {
299
323
  const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
300
324
  spawn(command, args, { detached: true, stdio: "ignore" }).unref();
301
325
  }
326
+ function red(message) {
327
+ return `\x1B[31m${message}\x1B[0m`;
328
+ }
302
329
  function printHelp() {
303
330
  console.log(`Mocklane local mock proxy
304
331
 
package/dist/cli.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../cli/index.ts", "../cli/server.ts", "../cli/mockRegistry.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { startMocklaneServers } from \"./server\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PROXY_PORT = 4000;\nconst DEFAULT_UI_PORT = 4001;\n\nasync function main() {\n const options = parseArguments(process.argv.slice(2));\n if (options.help) {\n printHelp();\n return;\n }\n\n const uiDirectory = fileURLToPath(new URL(\"../build/client\", import.meta.url));\n const servers = await startMocklaneServers({\n host: DEFAULT_HOST,\n proxyPort: options.proxyPort,\n uiPort: options.uiPort,\n target: options.target,\n uiDirectory,\n });\n const uiUrl = `http://localhost:${options.uiPort}`;\n\n console.log(`Mocklane UI: ${uiUrl}`);\n console.log(`Mock API proxy: http://localhost:${options.proxyPort}`);\n console.log(`Upstream server: ${options.target?.origin ?? \"none (standalone mode)\"}`);\n console.log(\"Press Ctrl+C to stop.\");\n\n openBrowser(uiUrl);\n\n const shutdown = async () => {\n await servers.close();\n process.exit(0);\n };\n process.once(\"SIGINT\", () => void shutdown());\n process.once(\"SIGTERM\", () => void shutdown());\n}\n\nfunction parseArguments(argumentsList: string[]) {\n let target: URL | null = null;\n let proxyPort = DEFAULT_PROXY_PORT;\n let uiPort = DEFAULT_UI_PORT;\n let help = false;\n\n for (let index = 0; index < argumentsList.length; index += 1) {\n const argument = argumentsList[index];\n if (argument === \"--target\") target = new URL(requireValue(argumentsList, ++index, argument));\n else if (argument === \"--proxy-port\") proxyPort = parsePort(requireValue(argumentsList, ++index, argument));\n else if (argument === \"--ui-port\") uiPort = parsePort(requireValue(argumentsList, ++index, argument));\n else if (argument === \"--help\" || argument === \"-h\") help = true;\n else throw new Error(`Unknown argument: ${argument}`);\n }\n\n if (proxyPort === uiPort) throw new Error(\"Proxy and UI ports must be different.\");\n return { target, proxyPort, uiPort, help };\n}\n\nfunction requireValue(argumentsList: string[], index: number, flag: string) {\n const value = argumentsList[index];\n if (!value) throw new Error(`${flag} requires a value.`);\n return value;\n}\n\nfunction parsePort(value: string) {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid port: ${value}`);\n }\n return port;\n}\n\nfunction openBrowser(url: string) {\n const command = process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"cmd\" : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n spawn(command, args, { detached: true, stdio: \"ignore\" }).unref();\n}\n\nfunction printHelp() {\n console.log(`Mocklane local mock proxy\n\nUsage:\n mocklane [options]\n\nOptions:\n --target <url> Optional upstream API URL for unmatched routes\n --proxy-port <port> Mock/proxy port (default: 4000)\n --ui-port <port> Mocklane UI port (default: 4001)\n -h, --help Show this help`);\n}\n\nvoid main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n});\n", "import { createReadStream, existsSync, statSync } from \"node:fs\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport { request as requestHttp } from \"node:http\";\nimport { request as requestHttps } from \"node:https\";\nimport { extname, resolve } from \"node:path\";\n\nimport type { MockHttpResponse } from \"../src/types/mockApi\";\nimport { MockRegistry } from \"./mockRegistry\";\n\nconst MAX_CONTROL_BODY_BYTES = 10 * 1024 * 1024;\n\nexport type MocklaneServers = {\n close: () => Promise<void>;\n};\n\nexport async function startMocklaneServers({\n host,\n proxyPort,\n uiPort,\n target,\n uiDirectory,\n}: {\n host: string;\n proxyPort: number;\n uiPort: number;\n target: URL | null;\n uiDirectory: string;\n}): Promise<MocklaneServers> {\n const registry = new MockRegistry();\n const proxyServer = createServer((request, response) => {\n handleProxyRequest(request, response, registry, target);\n });\n const uiServer = createServer((request, response) => {\n void handleUiRequest(request, response, registry, uiDirectory, proxyPort);\n });\n\n try {\n await listen(proxyServer, proxyPort, host);\n await listen(uiServer, uiPort, host);\n } catch (error) {\n await closeServer(proxyServer);\n await closeServer(uiServer);\n throw error;\n }\n\n return {\n close: async () => {\n await Promise.all([closeServer(proxyServer), closeServer(uiServer)]);\n },\n };\n}\n\nasync function handleUiRequest(\n request: IncomingMessage,\n response: ServerResponse,\n registry: MockRegistry,\n uiDirectory: string,\n proxyPort: number,\n) {\n const url = new URL(request.url ?? \"/\", \"http://localhost\");\n\n if (url.pathname === \"/__mocklane/health\" && request.method === \"GET\") {\n sendJson(response, 200, { ready: true, proxyPort, mocks: registry.list().length });\n return;\n }\n\n if (url.pathname === \"/__mocklane/mocks\" && request.method === \"GET\") {\n sendJson(response, 200, registry.list());\n return;\n }\n\n if (url.pathname === \"/__mocklane/mocks\" && request.method === \"PUT\") {\n try {\n const mock = validateMockResponse(await readJsonBody(request));\n registry.set(mock);\n sendJson(response, 200, { active: true, method: mock.method, path: mock.path, proxyPort });\n } catch (error) {\n sendJson(response, 400, {\n error: error instanceof Error ? error.message : \"Invalid mock response.\",\n });\n }\n return;\n }\n\n if (url.pathname === \"/__mocklane/mocks\" && request.method === \"DELETE\") {\n try {\n const mock = validateMockResponse(await readJsonBody(request));\n registry.delete(mock.method, mock.path);\n sendJson(response, 200, { active: false, method: mock.method, path: mock.path });\n } catch (error) {\n sendJson(response, 400, {\n error: error instanceof Error ? error.message : \"Invalid mock response.\",\n });\n }\n return;\n }\n\n serveUiFile(response, uiDirectory, url.pathname, request.method === \"HEAD\");\n}\n\nfunction handleProxyRequest(\n request: IncomingMessage,\n response: ServerResponse,\n registry: MockRegistry,\n target: URL | null,\n) {\n const requestUrl = new URL(request.url ?? \"/\", target ?? \"http://localhost\");\n const preflightMethod = request.headers[\"access-control-request-method\"];\n const preflightMock =\n request.method === \"OPTIONS\" && typeof preflightMethod === \"string\"\n ? registry.get(preflightMethod, requestUrl.pathname)\n : undefined;\n if (preflightMock && typeof preflightMethod === \"string\") {\n response.writeHead(204, {\n \"access-control-allow-origin\": \"*\",\n \"access-control-allow-methods\": preflightMethod.toUpperCase(),\n \"access-control-allow-headers\": request.headers[\"access-control-request-headers\"] ?? \"content-type\",\n });\n response.end();\n return;\n }\n\n const mock = registry.get(request.method ?? \"GET\", requestUrl.pathname);\n\n if (mock) {\n response.writeHead(mock.status, {\n ...mock.headers,\n \"access-control-allow-origin\": mock.headers[\"access-control-allow-origin\"] ?? \"*\",\n });\n response.end(JSON.stringify(mock.body));\n return;\n }\n\n if (!target) {\n sendJson(response, 404, {\n error: \"No Mocklane mock matches this route.\",\n method: request.method ?? \"GET\",\n path: requestUrl.pathname,\n });\n return;\n }\n\n const upstreamUrl = new URL(request.url ?? \"/\", target);\n const upstreamRequest = (upstreamUrl.protocol === \"https:\" ? requestHttps : requestHttp)(\n upstreamUrl,\n {\n method: request.method,\n headers: { ...request.headers, host: upstreamUrl.host },\n },\n (upstreamResponse) => {\n response.writeHead(upstreamResponse.statusCode ?? 502, upstreamResponse.headers);\n upstreamResponse.pipe(response);\n },\n );\n\n upstreamRequest.on(\"error\", (error) => {\n if (!response.headersSent) {\n sendJson(response, 502, {\n error: \"Mocklane could not reach the upstream server.\",\n detail: error.message,\n });\n return;\n }\n response.destroy(error);\n });\n request.pipe(upstreamRequest);\n}\n\nfunction serveUiFile(\n response: ServerResponse,\n uiDirectory: string,\n pathname: string,\n headOnly: boolean,\n) {\n const requestedPath = pathname === \"/\" ? \"/index.html\" : pathname;\n const candidate = resolve(uiDirectory, `.${decodeURIComponent(requestedPath)}`);\n const uiRoot = resolve(uiDirectory);\n const filePath =\n candidate.startsWith(`${uiRoot}/`) && existsSync(candidate) && statSync(candidate).isFile()\n ? candidate\n : resolve(uiDirectory, \"index.html\");\n\n if (!existsSync(filePath)) {\n sendJson(response, 503, {\n error: \"Mocklane UI has not been built. Run `pnpm build` first.\",\n });\n return;\n }\n\n response.writeHead(200, {\n \"content-type\": contentType(filePath),\n \"cache-control\": filePath.endsWith(\"index.html\") ? \"no-cache\" : \"public, max-age=31536000, immutable\",\n });\n if (headOnly) {\n response.end();\n return;\n }\n createReadStream(filePath).pipe(response);\n}\n\nasync function readJsonBody(request: IncomingMessage) {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.length;\n if (size > MAX_CONTROL_BODY_BYTES) {\n throw new Error(\"Mock response exceeds the 10 MB limit.\");\n }\n chunks.push(buffer);\n }\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n}\n\nfunction validateMockResponse(value: unknown): MockHttpResponse {\n if (!value || typeof value !== \"object\") throw new Error(\"Mock response must be an object.\");\n const mock = value as Partial<MockHttpResponse>;\n if (typeof mock.method !== \"string\" || !mock.method.trim()) throw new Error(\"Method is required.\");\n if (typeof mock.path !== \"string\" || !mock.path.startsWith(\"/\")) {\n throw new Error(\"Path must begin with `/`.\");\n }\n if (!Number.isInteger(mock.status) || Number(mock.status) < 100 || Number(mock.status) > 599) {\n throw new Error(\"Status must be a valid HTTP status code.\");\n }\n if (!mock.headers || typeof mock.headers !== \"object\" || Array.isArray(mock.headers)) {\n throw new Error(\"Headers must be an object.\");\n }\n return mock as MockHttpResponse;\n}\n\nfunction sendJson(response: ServerResponse, status: number, body: unknown) {\n response.writeHead(status, { \"content-type\": \"application/json; charset=utf-8\" });\n response.end(JSON.stringify(body));\n}\n\nfunction contentType(filePath: string) {\n const types: Record<string, string> = {\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n \".wasm\": \"application/wasm\",\n };\n return types[extname(filePath)] ?? \"application/octet-stream\";\n}\n\nfunction listen(server: Server, port: number, host: string) {\n return new Promise<void>((resolvePromise, reject) => {\n server.once(\"error\", reject);\n server.listen(port, host, () => {\n server.off(\"error\", reject);\n resolvePromise();\n });\n });\n}\n\nfunction closeServer(server: Server) {\n return new Promise<void>((resolvePromise) => {\n if (!server.listening) {\n resolvePromise();\n return;\n }\n server.close(() => resolvePromise());\n });\n}\n", "import type { MockHttpResponse } from \"../src/types/mockApi\";\n\nexport class MockRegistry {\n readonly #mocks = new Map<string, MockHttpResponse>();\n\n set(response: MockHttpResponse) {\n this.#mocks.set(mockKey(response.method, response.path), response);\n }\n\n get(method: string, path: string) {\n return this.#mocks.get(mockKey(method, path));\n }\n\n delete(method: string, path: string) {\n return this.#mocks.delete(mockKey(method, path));\n }\n\n list() {\n return [...this.#mocks.values()];\n }\n}\n\nfunction mockKey(method: string, path: string) {\n return `${method.toUpperCase()} ${path}`;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\n\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { startMocklaneServers } from \"./server\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PROXY_PORT = 4000;\nconst DEFAULT_UI_PORT = 4001;\n\nasync function main() {\n const options = parseArguments(process.argv.slice(2));\n if (options.help) {\n printHelp();\n return;\n }\n\n const uiDirectory = fileURLToPath(new URL(\"../build/client\", import.meta.url));\n const servers = await startMocklaneServers({\n host: DEFAULT_HOST,\n proxyPort: options.proxyPort,\n uiPort: options.uiPort,\n target: options.target,\n uiDirectory,\n allowPortFallback: !options.hasCustomPorts,\n });\n const uiUrl = `http://localhost:${servers.uiPort}`;\n\n if (!options.hasCustomPorts && (servers.proxyPort !== DEFAULT_PROXY_PORT || servers.uiPort !== DEFAULT_UI_PORT)) {\n console.log(red(`Port ${DEFAULT_PROXY_PORT} is in use. Using ${servers.proxyPort} instead.`));\n }\n console.log(`Mocklane UI: ${uiUrl}`);\n console.log(`Mock API proxy: http://localhost:${servers.proxyPort}`);\n console.log(`Upstream server: ${options.target?.origin ?? \"none (standalone mode)\"}`);\n console.log(\"Press Ctrl+C to stop.\");\n\n openBrowser(uiUrl);\n\n const shutdown = async () => {\n await servers.close();\n process.exit(0);\n };\n process.once(\"SIGINT\", () => void shutdown());\n process.once(\"SIGTERM\", () => void shutdown());\n}\n\nfunction parseArguments(argumentsList: string[]) {\n let target: URL | null = null;\n let proxyPort = DEFAULT_PROXY_PORT;\n let uiPort = DEFAULT_UI_PORT;\n let help = false;\n let hasCustomPorts = false;\n\n for (let index = 0; index < argumentsList.length; index += 1) {\n const argument = argumentsList[index];\n if (argument === \"--target\") target = new URL(requireValue(argumentsList, ++index, argument));\n else if (argument === \"--proxy-port\") {\n proxyPort = parsePort(requireValue(argumentsList, ++index, argument));\n hasCustomPorts = true;\n } else if (argument === \"--ui-port\") {\n uiPort = parsePort(requireValue(argumentsList, ++index, argument));\n hasCustomPorts = true;\n }\n else if (argument === \"--help\" || argument === \"-h\") help = true;\n else throw new Error(`Unknown argument: ${argument}`);\n }\n\n if (proxyPort === uiPort) throw new Error(\"Proxy and UI ports must be different.\");\n return { target, proxyPort, uiPort, help, hasCustomPorts };\n}\n\nfunction requireValue(argumentsList: string[], index: number, flag: string) {\n const value = argumentsList[index];\n if (!value) throw new Error(`${flag} requires a value.`);\n return value;\n}\n\nfunction parsePort(value: string) {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid port: ${value}`);\n }\n return port;\n}\n\nfunction openBrowser(url: string) {\n const command = process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"cmd\" : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n spawn(command, args, { detached: true, stdio: \"ignore\" }).unref();\n}\n\nfunction red(message: string) {\n return `\\x1b[31m${message}\\x1b[0m`;\n}\n\nfunction printHelp() {\n console.log(`Mocklane local mock proxy\n\nUsage:\n mocklane [options]\n\nOptions:\n --target <url> Optional upstream API URL for unmatched routes\n --proxy-port <port> Mock/proxy port (default: 4000)\n --ui-port <port> Mocklane UI port (default: 4001)\n -h, --help Show this help`);\n}\n\nvoid main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n});\n", "import { createReadStream, existsSync, statSync } from \"node:fs\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport { request as requestHttp } from \"node:http\";\nimport { request as requestHttps } from \"node:https\";\nimport { extname, resolve } from \"node:path\";\n\nimport type { MockHttpResponse } from \"../src/types/mockApi\";\nimport { MockRegistry } from \"./mockRegistry\";\n\nconst MAX_CONTROL_BODY_BYTES = 10 * 1024 * 1024;\n\nexport type MocklaneServers = {\n proxyPort: number;\n uiPort: number;\n close: () => Promise<void>;\n};\n\nexport async function startMocklaneServers({\n host,\n proxyPort,\n uiPort,\n target,\n uiDirectory,\n allowPortFallback = false,\n}: {\n host: string;\n proxyPort: number;\n uiPort: number;\n target: URL | null;\n uiDirectory: string;\n allowPortFallback?: boolean;\n}): Promise<MocklaneServers> {\n const registry = new MockRegistry();\n let candidateProxyPort = proxyPort;\n let candidateUiPort = uiPort;\n\n while (candidateProxyPort <= 65534 && candidateUiPort <= 65535) {\n const activeProxyPort = candidateProxyPort;\n const activeUiPort = candidateUiPort;\n const proxyServer = createServer((request, response) => {\n handleProxyRequest(request, response, registry, target);\n });\n const uiServer = createServer((request, response) => {\n void handleUiRequest(request, response, registry, uiDirectory, activeProxyPort);\n });\n\n try {\n await listen(proxyServer, activeProxyPort, host);\n await listen(uiServer, activeUiPort, host);\n return {\n proxyPort: activeProxyPort,\n uiPort: activeUiPort,\n close: async () => {\n await Promise.all([closeServer(proxyServer), closeServer(uiServer)]);\n },\n };\n } catch (error) {\n await closeServer(proxyServer);\n await closeServer(uiServer);\n if (!allowPortFallback || !isAddressInUse(error)) throw error;\n candidateProxyPort += 2;\n candidateUiPort += 2;\n }\n }\n\n throw new Error(\"Mocklane could not find an available local port pair.\");\n}\n\nasync function handleUiRequest(\n request: IncomingMessage,\n response: ServerResponse,\n registry: MockRegistry,\n uiDirectory: string,\n proxyPort: number,\n) {\n const url = new URL(request.url ?? \"/\", \"http://localhost\");\n\n if (url.pathname === \"/__mocklane/health\" && request.method === \"GET\") {\n sendJson(response, 200, { ready: true, proxyPort, mocks: registry.list().length });\n return;\n }\n\n if (url.pathname === \"/__mocklane/mocks\" && request.method === \"GET\") {\n sendJson(response, 200, registry.list());\n return;\n }\n\n if (url.pathname === \"/__mocklane/mocks\" && request.method === \"PUT\") {\n try {\n const mock = validateMockResponse(await readJsonBody(request));\n registry.set(mock);\n sendJson(response, 200, { active: true, method: mock.method, path: mock.path, proxyPort });\n } catch (error) {\n sendJson(response, 400, {\n error: error instanceof Error ? error.message : \"Invalid mock response.\",\n });\n }\n return;\n }\n\n if (url.pathname === \"/__mocklane/mocks\" && request.method === \"DELETE\") {\n try {\n const mock = validateMockResponse(await readJsonBody(request));\n registry.delete(mock.method, mock.path);\n sendJson(response, 200, { active: false, method: mock.method, path: mock.path });\n } catch (error) {\n sendJson(response, 400, {\n error: error instanceof Error ? error.message : \"Invalid mock response.\",\n });\n }\n return;\n }\n\n serveUiFile(response, uiDirectory, url.pathname, request.method === \"HEAD\");\n}\n\nfunction handleProxyRequest(\n request: IncomingMessage,\n response: ServerResponse,\n registry: MockRegistry,\n target: URL | null,\n) {\n const requestUrl = new URL(request.url ?? \"/\", target ?? \"http://localhost\");\n const preflightMethod = request.headers[\"access-control-request-method\"];\n const preflightMock =\n request.method === \"OPTIONS\" && typeof preflightMethod === \"string\"\n ? registry.get(preflightMethod, requestUrl.pathname)\n : undefined;\n if (preflightMock && typeof preflightMethod === \"string\") {\n response.writeHead(204, {\n \"access-control-allow-origin\": \"*\",\n \"access-control-allow-methods\": preflightMethod.toUpperCase(),\n \"access-control-allow-headers\": request.headers[\"access-control-request-headers\"] ?? \"content-type\",\n });\n response.end();\n return;\n }\n\n const mock = registry.get(request.method ?? \"GET\", requestUrl.pathname);\n\n if (mock) {\n response.writeHead(mock.status, {\n ...mock.headers,\n \"access-control-allow-origin\": mock.headers[\"access-control-allow-origin\"] ?? \"*\",\n });\n response.end(JSON.stringify(mock.body));\n return;\n }\n\n if (!target) {\n sendJson(response, 404, {\n error: \"No Mocklane mock matches this route.\",\n method: request.method ?? \"GET\",\n path: requestUrl.pathname,\n });\n return;\n }\n\n const upstreamUrl = new URL(request.url ?? \"/\", target);\n const upstreamRequest = (upstreamUrl.protocol === \"https:\" ? requestHttps : requestHttp)(\n upstreamUrl,\n {\n method: request.method,\n headers: { ...request.headers, host: upstreamUrl.host },\n },\n (upstreamResponse) => {\n response.writeHead(upstreamResponse.statusCode ?? 502, upstreamResponse.headers);\n upstreamResponse.pipe(response);\n },\n );\n\n upstreamRequest.on(\"error\", (error) => {\n if (!response.headersSent) {\n sendJson(response, 502, {\n error: \"Mocklane could not reach the upstream server.\",\n detail: error.message,\n });\n return;\n }\n response.destroy(error);\n });\n request.pipe(upstreamRequest);\n}\n\nfunction serveUiFile(\n response: ServerResponse,\n uiDirectory: string,\n pathname: string,\n headOnly: boolean,\n) {\n const requestedPath = pathname === \"/\" ? \"/index.html\" : pathname;\n const candidate = resolve(uiDirectory, `.${decodeURIComponent(requestedPath)}`);\n const uiRoot = resolve(uiDirectory);\n const filePath =\n candidate.startsWith(`${uiRoot}/`) && existsSync(candidate) && statSync(candidate).isFile()\n ? candidate\n : resolve(uiDirectory, \"index.html\");\n\n if (!existsSync(filePath)) {\n sendJson(response, 503, {\n error: \"Mocklane UI has not been built. Run `pnpm build` first.\",\n });\n return;\n }\n\n response.writeHead(200, {\n \"content-type\": contentType(filePath),\n \"cache-control\": filePath.endsWith(\"index.html\") ? \"no-cache\" : \"public, max-age=31536000, immutable\",\n });\n if (headOnly) {\n response.end();\n return;\n }\n createReadStream(filePath).pipe(response);\n}\n\nasync function readJsonBody(request: IncomingMessage) {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.length;\n if (size > MAX_CONTROL_BODY_BYTES) {\n throw new Error(\"Mock response exceeds the 10 MB limit.\");\n }\n chunks.push(buffer);\n }\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n}\n\nfunction validateMockResponse(value: unknown): MockHttpResponse {\n if (!value || typeof value !== \"object\") throw new Error(\"Mock response must be an object.\");\n const mock = value as Partial<MockHttpResponse>;\n if (typeof mock.method !== \"string\" || !mock.method.trim()) throw new Error(\"Method is required.\");\n if (typeof mock.path !== \"string\" || !mock.path.startsWith(\"/\")) {\n throw new Error(\"Path must begin with `/`.\");\n }\n if (!Number.isInteger(mock.status) || Number(mock.status) < 100 || Number(mock.status) > 599) {\n throw new Error(\"Status must be a valid HTTP status code.\");\n }\n if (!mock.headers || typeof mock.headers !== \"object\" || Array.isArray(mock.headers)) {\n throw new Error(\"Headers must be an object.\");\n }\n return mock as MockHttpResponse;\n}\n\nfunction sendJson(response: ServerResponse, status: number, body: unknown) {\n response.writeHead(status, { \"content-type\": \"application/json; charset=utf-8\" });\n response.end(JSON.stringify(body));\n}\n\nfunction contentType(filePath: string) {\n const types: Record<string, string> = {\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n \".wasm\": \"application/wasm\",\n };\n return types[extname(filePath)] ?? \"application/octet-stream\";\n}\n\nfunction listen(server: Server, port: number, host: string) {\n return new Promise<void>((resolvePromise, reject) => {\n server.once(\"error\", reject);\n server.listen(port, host, () => {\n server.off(\"error\", reject);\n resolvePromise();\n });\n });\n}\n\nfunction isAddressInUse(error: unknown) {\n return error instanceof Error && \"code\" in error && error.code === \"EADDRINUSE\";\n}\n\nfunction closeServer(server: Server) {\n return new Promise<void>((resolvePromise) => {\n if (!server.listening) {\n resolvePromise();\n return;\n }\n server.close(() => resolvePromise());\n });\n}\n", "import type { MockHttpResponse } from \"../src/types/mockApi\";\n\nexport class MockRegistry {\n readonly #mocks = new Map<string, MockHttpResponse>();\n\n set(response: MockHttpResponse) {\n this.#mocks.set(mockKey(response.method, response.path), response);\n }\n\n get(method: string, path: string) {\n return this.#mocks.get(mockKey(method, path));\n }\n\n delete(method: string, path: string) {\n return this.#mocks.delete(mockKey(method, path));\n }\n\n list() {\n return [...this.#mocks.values()];\n }\n}\n\nfunction mockKey(method: string, path: string) {\n return `${method.toUpperCase()} ${path}`;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mocklane/core",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Browser-local AI mock API generator and proxy.",
5
5
  "author": "Asis Paudel",
6
6
  "license": "MIT",