@run0/jiki 0.1.0
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/dist/browser-bundle.d.ts +40 -0
- package/dist/builtins.d.ts +22 -0
- package/dist/code-transform.d.ts +7 -0
- package/dist/config/cdn.d.ts +13 -0
- package/dist/container.d.ts +101 -0
- package/dist/dev-server.d.ts +69 -0
- package/dist/errors.d.ts +19 -0
- package/dist/frameworks/code-transforms.d.ts +32 -0
- package/dist/frameworks/next-api-handler.d.ts +72 -0
- package/dist/frameworks/next-dev-server.d.ts +141 -0
- package/dist/frameworks/next-html-generator.d.ts +36 -0
- package/dist/frameworks/next-route-resolver.d.ts +19 -0
- package/dist/frameworks/next-shims.d.ts +78 -0
- package/dist/frameworks/remix-dev-server.d.ts +47 -0
- package/dist/frameworks/sveltekit-dev-server.d.ts +43 -0
- package/dist/frameworks/vite-dev-server.d.ts +50 -0
- package/dist/fs-errors.d.ts +36 -0
- package/dist/index.cjs +14916 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.mjs +14898 -0
- package/dist/index.mjs.map +1 -0
- package/dist/kernel.d.ts +48 -0
- package/dist/memfs.d.ts +144 -0
- package/dist/metrics.d.ts +78 -0
- package/dist/module-resolver.d.ts +60 -0
- package/dist/network-interceptor.d.ts +71 -0
- package/dist/npm/cache.d.ts +76 -0
- package/dist/npm/index.d.ts +60 -0
- package/dist/npm/lockfile-reader.d.ts +32 -0
- package/dist/npm/pnpm.d.ts +18 -0
- package/dist/npm/registry.d.ts +45 -0
- package/dist/npm/resolver.d.ts +39 -0
- package/dist/npm/sync-installer.d.ts +18 -0
- package/dist/npm/tarball.d.ts +4 -0
- package/dist/npm/workspaces.d.ts +46 -0
- package/dist/persistence.d.ts +94 -0
- package/dist/plugin.d.ts +156 -0
- package/dist/polyfills/assert.d.ts +30 -0
- package/dist/polyfills/child_process.d.ts +116 -0
- package/dist/polyfills/chokidar.d.ts +18 -0
- package/dist/polyfills/crypto.d.ts +49 -0
- package/dist/polyfills/events.d.ts +28 -0
- package/dist/polyfills/fs.d.ts +82 -0
- package/dist/polyfills/http.d.ts +147 -0
- package/dist/polyfills/module.d.ts +29 -0
- package/dist/polyfills/net.d.ts +53 -0
- package/dist/polyfills/os.d.ts +91 -0
- package/dist/polyfills/path.d.ts +96 -0
- package/dist/polyfills/perf_hooks.d.ts +21 -0
- package/dist/polyfills/process.d.ts +99 -0
- package/dist/polyfills/querystring.d.ts +15 -0
- package/dist/polyfills/readdirp.d.ts +18 -0
- package/dist/polyfills/readline.d.ts +32 -0
- package/dist/polyfills/stream.d.ts +106 -0
- package/dist/polyfills/stubs.d.ts +737 -0
- package/dist/polyfills/tty.d.ts +25 -0
- package/dist/polyfills/url.d.ts +41 -0
- package/dist/polyfills/util.d.ts +61 -0
- package/dist/polyfills/v8.d.ts +43 -0
- package/dist/polyfills/vm.d.ts +76 -0
- package/dist/polyfills/worker-threads.d.ts +77 -0
- package/dist/polyfills/ws.d.ts +32 -0
- package/dist/polyfills/zlib.d.ts +87 -0
- package/dist/runtime-helpers.d.ts +4 -0
- package/dist/runtime-interface.d.ts +39 -0
- package/dist/sandbox.d.ts +69 -0
- package/dist/server-bridge.d.ts +55 -0
- package/dist/shell-commands.d.ts +2 -0
- package/dist/shell.d.ts +101 -0
- package/dist/transpiler.d.ts +47 -0
- package/dist/type-checker.d.ts +57 -0
- package/dist/types/package-json.d.ts +17 -0
- package/dist/utils/binary-encoding.d.ts +4 -0
- package/dist/utils/hash.d.ts +6 -0
- package/dist/utils/safe-path.d.ts +6 -0
- package/dist/worker-runtime.d.ts +34 -0
- package/package.json +59 -0
- package/src/browser-bundle.ts +498 -0
- package/src/builtins.ts +222 -0
- package/src/code-transform.ts +183 -0
- package/src/config/cdn.ts +17 -0
- package/src/container.ts +343 -0
- package/src/dev-server.ts +322 -0
- package/src/errors.ts +604 -0
- package/src/frameworks/code-transforms.ts +667 -0
- package/src/frameworks/next-api-handler.ts +366 -0
- package/src/frameworks/next-dev-server.ts +1252 -0
- package/src/frameworks/next-html-generator.ts +585 -0
- package/src/frameworks/next-route-resolver.ts +521 -0
- package/src/frameworks/next-shims.ts +1084 -0
- package/src/frameworks/remix-dev-server.ts +163 -0
- package/src/frameworks/sveltekit-dev-server.ts +197 -0
- package/src/frameworks/vite-dev-server.ts +370 -0
- package/src/fs-errors.ts +118 -0
- package/src/index.ts +188 -0
- package/src/kernel.ts +381 -0
- package/src/memfs.ts +1006 -0
- package/src/metrics.ts +140 -0
- package/src/module-resolver.ts +511 -0
- package/src/network-interceptor.ts +143 -0
- package/src/npm/cache.ts +172 -0
- package/src/npm/index.ts +377 -0
- package/src/npm/lockfile-reader.ts +105 -0
- package/src/npm/pnpm.ts +108 -0
- package/src/npm/registry.ts +120 -0
- package/src/npm/resolver.ts +339 -0
- package/src/npm/sync-installer.ts +217 -0
- package/src/npm/tarball.ts +136 -0
- package/src/npm/workspaces.ts +255 -0
- package/src/persistence.ts +235 -0
- package/src/plugin.ts +293 -0
- package/src/polyfills/assert.ts +164 -0
- package/src/polyfills/child_process.ts +535 -0
- package/src/polyfills/chokidar.ts +52 -0
- package/src/polyfills/crypto.ts +433 -0
- package/src/polyfills/events.ts +178 -0
- package/src/polyfills/fs.ts +297 -0
- package/src/polyfills/http.ts +478 -0
- package/src/polyfills/module.ts +97 -0
- package/src/polyfills/net.ts +123 -0
- package/src/polyfills/os.ts +108 -0
- package/src/polyfills/path.ts +169 -0
- package/src/polyfills/perf_hooks.ts +30 -0
- package/src/polyfills/process.ts +349 -0
- package/src/polyfills/querystring.ts +66 -0
- package/src/polyfills/readdirp.ts +72 -0
- package/src/polyfills/readline.ts +80 -0
- package/src/polyfills/stream.ts +610 -0
- package/src/polyfills/stubs.ts +600 -0
- package/src/polyfills/tty.ts +43 -0
- package/src/polyfills/url.ts +97 -0
- package/src/polyfills/util.ts +173 -0
- package/src/polyfills/v8.ts +62 -0
- package/src/polyfills/vm.ts +111 -0
- package/src/polyfills/worker-threads.ts +189 -0
- package/src/polyfills/ws.ts +73 -0
- package/src/polyfills/zlib.ts +244 -0
- package/src/runtime-helpers.ts +83 -0
- package/src/runtime-interface.ts +46 -0
- package/src/sandbox.ts +178 -0
- package/src/server-bridge.ts +473 -0
- package/src/service-worker.ts +153 -0
- package/src/shell-commands.ts +708 -0
- package/src/shell.ts +795 -0
- package/src/transpiler.ts +282 -0
- package/src/type-checker.ts +241 -0
- package/src/types/package-json.ts +17 -0
- package/src/utils/binary-encoding.ts +38 -0
- package/src/utils/hash.ts +24 -0
- package/src/utils/safe-path.ts +38 -0
- package/src/worker-runtime.ts +42 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js API route handling
|
|
3
|
+
* Standalone functions extracted from NextDevServer for creating mock
|
|
4
|
+
* request/response objects and executing API handlers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ResponseData } from "../dev-server";
|
|
8
|
+
import { BufferImpl as Buffer } from "../polyfills/stream";
|
|
9
|
+
import * as pathPolyfill from "../polyfills/path";
|
|
10
|
+
import * as urlPolyfill from "../polyfills/url";
|
|
11
|
+
import * as querystringPolyfill from "../polyfills/querystring";
|
|
12
|
+
import * as utilPolyfill from "../polyfills/util";
|
|
13
|
+
import * as eventsPolyfill from "../polyfills/events";
|
|
14
|
+
import * as streamPolyfill from "../polyfills/stream";
|
|
15
|
+
import * as cryptoPolyfill from "../polyfills/crypto";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parse cookie header into key-value pairs
|
|
19
|
+
*/
|
|
20
|
+
export function parseCookies(cookieHeader: string): Record<string, string> {
|
|
21
|
+
const cookies: Record<string, string> = {};
|
|
22
|
+
if (!cookieHeader) return cookies;
|
|
23
|
+
|
|
24
|
+
cookieHeader.split(";").forEach(cookie => {
|
|
25
|
+
const [name, value] = cookie.trim().split("=");
|
|
26
|
+
if (name && value) {
|
|
27
|
+
cookies[name] = decodeURIComponent(value);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return cookies;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create mock Next.js request object
|
|
36
|
+
*/
|
|
37
|
+
export function createMockRequest(
|
|
38
|
+
method: string,
|
|
39
|
+
pathname: string,
|
|
40
|
+
headers: Record<string, string>,
|
|
41
|
+
body?: Buffer,
|
|
42
|
+
) {
|
|
43
|
+
const url = new URL(pathname, "http://localhost");
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
method,
|
|
47
|
+
url: pathname,
|
|
48
|
+
headers,
|
|
49
|
+
query: Object.fromEntries(url.searchParams),
|
|
50
|
+
body: body ? JSON.parse(body.toString()) : undefined,
|
|
51
|
+
cookies: parseCookies(headers.cookie || ""),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Create mock Next.js response object with streaming support
|
|
57
|
+
*/
|
|
58
|
+
export function createMockResponse() {
|
|
59
|
+
let statusCode = 200;
|
|
60
|
+
let statusMessage = "OK";
|
|
61
|
+
const headers: Record<string, string> = {};
|
|
62
|
+
let responseBody = "";
|
|
63
|
+
let ended = false;
|
|
64
|
+
let resolveEnded: (() => void) | null = null;
|
|
65
|
+
let headersSent = false;
|
|
66
|
+
|
|
67
|
+
// Promise that resolves when response is ended
|
|
68
|
+
const endedPromise = new Promise<void>(resolve => {
|
|
69
|
+
resolveEnded = resolve;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const markEnded = () => {
|
|
73
|
+
if (!ended) {
|
|
74
|
+
ended = true;
|
|
75
|
+
if (resolveEnded) resolveEnded();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
// Track if headers have been sent (for streaming)
|
|
81
|
+
headersSent: false,
|
|
82
|
+
|
|
83
|
+
status(code: number) {
|
|
84
|
+
statusCode = code;
|
|
85
|
+
return this;
|
|
86
|
+
},
|
|
87
|
+
setHeader(name: string, value: string) {
|
|
88
|
+
headers[name] = value;
|
|
89
|
+
return this;
|
|
90
|
+
},
|
|
91
|
+
getHeader(name: string) {
|
|
92
|
+
return headers[name];
|
|
93
|
+
},
|
|
94
|
+
// Write data to response body (for streaming)
|
|
95
|
+
write(chunk: string | Buffer): boolean {
|
|
96
|
+
if (!headersSent) {
|
|
97
|
+
headersSent = true;
|
|
98
|
+
this.headersSent = true;
|
|
99
|
+
}
|
|
100
|
+
responseBody += typeof chunk === "string" ? chunk : chunk.toString();
|
|
101
|
+
return true;
|
|
102
|
+
},
|
|
103
|
+
// Writable stream interface for AI SDK compatibility
|
|
104
|
+
get writable() {
|
|
105
|
+
return true;
|
|
106
|
+
},
|
|
107
|
+
json(data: unknown) {
|
|
108
|
+
headers["Content-Type"] = "application/json; charset=utf-8";
|
|
109
|
+
responseBody = JSON.stringify(data);
|
|
110
|
+
markEnded();
|
|
111
|
+
return this;
|
|
112
|
+
},
|
|
113
|
+
send(data: string | object) {
|
|
114
|
+
if (typeof data === "object") {
|
|
115
|
+
return this.json(data);
|
|
116
|
+
}
|
|
117
|
+
responseBody = data;
|
|
118
|
+
markEnded();
|
|
119
|
+
return this;
|
|
120
|
+
},
|
|
121
|
+
end(data?: string) {
|
|
122
|
+
if (data) responseBody += data;
|
|
123
|
+
markEnded();
|
|
124
|
+
return this;
|
|
125
|
+
},
|
|
126
|
+
redirect(statusOrUrl: number | string, url?: string) {
|
|
127
|
+
if (typeof statusOrUrl === "number") {
|
|
128
|
+
statusCode = statusOrUrl;
|
|
129
|
+
headers["Location"] = url || "/";
|
|
130
|
+
} else {
|
|
131
|
+
statusCode = 307;
|
|
132
|
+
headers["Location"] = statusOrUrl;
|
|
133
|
+
}
|
|
134
|
+
markEnded();
|
|
135
|
+
return this;
|
|
136
|
+
},
|
|
137
|
+
isEnded() {
|
|
138
|
+
return ended;
|
|
139
|
+
},
|
|
140
|
+
waitForEnd() {
|
|
141
|
+
return endedPromise;
|
|
142
|
+
},
|
|
143
|
+
toResponse(): ResponseData {
|
|
144
|
+
const buffer = Buffer.from(responseBody);
|
|
145
|
+
headers["Content-Length"] = String(buffer.length);
|
|
146
|
+
return {
|
|
147
|
+
statusCode,
|
|
148
|
+
statusMessage,
|
|
149
|
+
headers,
|
|
150
|
+
body: buffer,
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Create a streaming mock response that calls callbacks as data is written
|
|
158
|
+
*/
|
|
159
|
+
export function createStreamingMockResponse(
|
|
160
|
+
onStart: (
|
|
161
|
+
statusCode: number,
|
|
162
|
+
statusMessage: string,
|
|
163
|
+
headers: Record<string, string>,
|
|
164
|
+
) => void,
|
|
165
|
+
onChunk: (chunk: string | Uint8Array) => void,
|
|
166
|
+
onEnd: () => void,
|
|
167
|
+
) {
|
|
168
|
+
let statusCode = 200;
|
|
169
|
+
let statusMessage = "OK";
|
|
170
|
+
const headers: Record<string, string> = {};
|
|
171
|
+
let ended = false;
|
|
172
|
+
let headersSent = false;
|
|
173
|
+
let resolveEnded: (() => void) | null = null;
|
|
174
|
+
|
|
175
|
+
const endedPromise = new Promise<void>(resolve => {
|
|
176
|
+
resolveEnded = resolve;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const sendHeaders = () => {
|
|
180
|
+
if (!headersSent) {
|
|
181
|
+
headersSent = true;
|
|
182
|
+
onStart(statusCode, statusMessage, headers);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const markEnded = () => {
|
|
187
|
+
if (!ended) {
|
|
188
|
+
sendHeaders();
|
|
189
|
+
ended = true;
|
|
190
|
+
onEnd();
|
|
191
|
+
if (resolveEnded) resolveEnded();
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
headersSent: false,
|
|
197
|
+
|
|
198
|
+
status(code: number) {
|
|
199
|
+
statusCode = code;
|
|
200
|
+
return this;
|
|
201
|
+
},
|
|
202
|
+
setHeader(name: string, value: string) {
|
|
203
|
+
headers[name] = value;
|
|
204
|
+
return this;
|
|
205
|
+
},
|
|
206
|
+
getHeader(name: string) {
|
|
207
|
+
return headers[name];
|
|
208
|
+
},
|
|
209
|
+
// Write data and stream it immediately
|
|
210
|
+
write(chunk: string | Buffer): boolean {
|
|
211
|
+
sendHeaders();
|
|
212
|
+
const data = typeof chunk === "string" ? chunk : chunk.toString();
|
|
213
|
+
onChunk(data);
|
|
214
|
+
return true;
|
|
215
|
+
},
|
|
216
|
+
get writable() {
|
|
217
|
+
return true;
|
|
218
|
+
},
|
|
219
|
+
json(data: unknown) {
|
|
220
|
+
headers["Content-Type"] = "application/json; charset=utf-8";
|
|
221
|
+
sendHeaders();
|
|
222
|
+
onChunk(JSON.stringify(data));
|
|
223
|
+
markEnded();
|
|
224
|
+
return this;
|
|
225
|
+
},
|
|
226
|
+
send(data: string | object) {
|
|
227
|
+
if (typeof data === "object") {
|
|
228
|
+
return this.json(data);
|
|
229
|
+
}
|
|
230
|
+
sendHeaders();
|
|
231
|
+
onChunk(data);
|
|
232
|
+
markEnded();
|
|
233
|
+
return this;
|
|
234
|
+
},
|
|
235
|
+
end(data?: string) {
|
|
236
|
+
if (data) {
|
|
237
|
+
sendHeaders();
|
|
238
|
+
onChunk(data);
|
|
239
|
+
}
|
|
240
|
+
markEnded();
|
|
241
|
+
return this;
|
|
242
|
+
},
|
|
243
|
+
redirect(statusOrUrl: number | string, url?: string) {
|
|
244
|
+
if (typeof statusOrUrl === "number") {
|
|
245
|
+
statusCode = statusOrUrl;
|
|
246
|
+
headers["Location"] = url || "/";
|
|
247
|
+
} else {
|
|
248
|
+
statusCode = 307;
|
|
249
|
+
headers["Location"] = statusOrUrl;
|
|
250
|
+
}
|
|
251
|
+
markEnded();
|
|
252
|
+
return this;
|
|
253
|
+
},
|
|
254
|
+
isEnded() {
|
|
255
|
+
return ended;
|
|
256
|
+
},
|
|
257
|
+
waitForEnd() {
|
|
258
|
+
return endedPromise;
|
|
259
|
+
},
|
|
260
|
+
toResponse(): ResponseData {
|
|
261
|
+
// This shouldn't be called for streaming responses
|
|
262
|
+
return {
|
|
263
|
+
statusCode,
|
|
264
|
+
statusMessage,
|
|
265
|
+
headers,
|
|
266
|
+
body: Buffer.from(""),
|
|
267
|
+
};
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Type for mock response objects */
|
|
273
|
+
export type MockResponse = ReturnType<typeof createMockResponse>;
|
|
274
|
+
export type MockRequest = ReturnType<typeof createMockRequest>;
|
|
275
|
+
export type StreamingMockResponse = ReturnType<
|
|
276
|
+
typeof createStreamingMockResponse
|
|
277
|
+
>;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Create builtin modules map for API handler execution.
|
|
281
|
+
*/
|
|
282
|
+
export function createBuiltinModules(): Record<string, unknown> {
|
|
283
|
+
return {
|
|
284
|
+
path: pathPolyfill,
|
|
285
|
+
url: urlPolyfill,
|
|
286
|
+
querystring: querystringPolyfill,
|
|
287
|
+
util: utilPolyfill,
|
|
288
|
+
events: eventsPolyfill,
|
|
289
|
+
stream: streamPolyfill,
|
|
290
|
+
crypto: cryptoPolyfill,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Execute API handler code in a sandboxed context
|
|
296
|
+
*/
|
|
297
|
+
export async function executeApiHandler(
|
|
298
|
+
code: string,
|
|
299
|
+
req: MockRequest,
|
|
300
|
+
res: MockResponse | StreamingMockResponse,
|
|
301
|
+
env: Record<string, string> | undefined,
|
|
302
|
+
builtinModules: Record<string, unknown>,
|
|
303
|
+
vfsRequire?: (id: string) => unknown,
|
|
304
|
+
): Promise<unknown> {
|
|
305
|
+
try {
|
|
306
|
+
const require = (id: string): unknown => {
|
|
307
|
+
// Handle node: prefix
|
|
308
|
+
const modId = id.startsWith("node:") ? id.slice(5) : id;
|
|
309
|
+
if (builtinModules[modId]) {
|
|
310
|
+
return builtinModules[modId];
|
|
311
|
+
}
|
|
312
|
+
// Fall back to VFS-based require (npm packages from node_modules)
|
|
313
|
+
if (vfsRequire) {
|
|
314
|
+
return vfsRequire(modId);
|
|
315
|
+
}
|
|
316
|
+
throw new Error(`Module not found: ${id}`);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// Create module context
|
|
320
|
+
const module = { exports: {} as Record<string, unknown> };
|
|
321
|
+
const exports = module.exports;
|
|
322
|
+
|
|
323
|
+
// Create process object with environment variables
|
|
324
|
+
const process = {
|
|
325
|
+
env: { ...env },
|
|
326
|
+
cwd: () => "/",
|
|
327
|
+
platform: "browser",
|
|
328
|
+
version: "v18.0.0",
|
|
329
|
+
versions: { node: "18.0.0" },
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// Execute the transformed code
|
|
333
|
+
const fn = new Function("exports", "require", "module", "process", code);
|
|
334
|
+
fn(exports, require, module, process);
|
|
335
|
+
|
|
336
|
+
// Get the handler - check both module.exports and module.exports.default
|
|
337
|
+
let handler: unknown = module.exports.default || module.exports;
|
|
338
|
+
|
|
339
|
+
// If handler is still an object with a default property, unwrap it
|
|
340
|
+
if (
|
|
341
|
+
typeof handler === "object" &&
|
|
342
|
+
handler !== null &&
|
|
343
|
+
"default" in handler
|
|
344
|
+
) {
|
|
345
|
+
handler = (handler as { default: unknown }).default;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (typeof handler !== "function") {
|
|
349
|
+
throw new Error("No default export handler found");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Call the handler - it may be async
|
|
353
|
+
let result = (handler as (req: unknown, res: unknown) => unknown)(req, res);
|
|
354
|
+
|
|
355
|
+
// If the handler returns a promise, wait for it
|
|
356
|
+
if (result instanceof Promise) {
|
|
357
|
+
result = await result;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Return the handler's return value so callers can detect Response objects
|
|
361
|
+
return result;
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.error("[NextDevServer] API handler error:", error);
|
|
364
|
+
throw error;
|
|
365
|
+
}
|
|
366
|
+
}
|