emulate 0.4.1 → 0.6.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/README.md +198 -27
- package/dist/api.d.ts +2 -1
- package/dist/api.js +675 -103
- package/dist/api.js.map +1 -1
- package/dist/chunk-WVQMFHQM.js +83 -0
- package/dist/chunk-WVQMFHQM.js.map +1 -0
- package/dist/{dist-B674PYKV.js → dist-2ZZGNPJI.js} +22 -43
- package/dist/dist-2ZZGNPJI.js.map +1 -0
- package/dist/{dist-RDFBZ5O6.js → dist-CXRPM6BK.js} +211 -48
- package/dist/dist-CXRPM6BK.js.map +1 -0
- package/dist/{dist-VVXVP5EZ.js → dist-DSJSF3GY.js} +551 -91
- package/dist/dist-DSJSF3GY.js.map +1 -0
- package/dist/{dist-RMK3BS5M.js → dist-IFULY5LE.js} +196 -33
- package/dist/dist-IFULY5LE.js.map +1 -0
- package/dist/dist-IRUBHCZU.js +1898 -0
- package/dist/dist-IRUBHCZU.js.map +1 -0
- package/dist/{dist-YOVM5HEY.js → dist-NJJLJT2N.js} +520 -61
- package/dist/dist-NJJLJT2N.js.map +1 -0
- package/dist/dist-OGSAVJ25.js +4874 -0
- package/dist/dist-OGSAVJ25.js.map +1 -0
- package/dist/{dist-H6JYGQM4.js → dist-PO4CL5SJ.js} +271 -158
- package/dist/dist-PO4CL5SJ.js.map +1 -0
- package/dist/{dist-QMOJM6DV.js → dist-R3TNKUIE.js} +238 -55
- package/dist/dist-R3TNKUIE.js.map +1 -0
- package/dist/{dist-6JFNJPUU.js → dist-WACHAAVU.js} +171 -22
- package/dist/dist-WACHAAVU.js.map +1 -0
- package/dist/{dist-OTJZRQ3Q.js → dist-XWWZVLQQ.js} +216 -75
- package/dist/dist-XWWZVLQQ.js.map +1 -0
- package/dist/{dist-6EW7SSOZ.js → dist-ZY5SZSJ2.js} +397 -223
- package/dist/dist-ZY5SZSJ2.js.map +1 -0
- package/dist/fonts/favicon.ico +0 -0
- package/dist/helpers-LXLP3DFE-LBOTATT5.js +17 -0
- package/dist/helpers-LXLP3DFE-LBOTATT5.js.map +1 -0
- package/dist/index.js +812 -117
- package/dist/index.js.map +1 -1
- package/package.json +17 -15
- package/dist/chunk-TEPNEZ63.js +0 -2143
- package/dist/chunk-TEPNEZ63.js.map +0 -1
- package/dist/dist-6EW7SSOZ.js.map +0 -1
- package/dist/dist-6JFNJPUU.js.map +0 -1
- package/dist/dist-B674PYKV.js.map +0 -1
- package/dist/dist-G7WQPZ3Y.js +0 -1287
- package/dist/dist-G7WQPZ3Y.js.map +0 -1
- package/dist/dist-H6JYGQM4.js.map +0 -1
- package/dist/dist-OTJZRQ3Q.js.map +0 -1
- package/dist/dist-QMOJM6DV.js.map +0 -1
- package/dist/dist-RDFBZ5O6.js.map +0 -1
- package/dist/dist-RMK3BS5M.js.map +0 -1
- package/dist/dist-VVXVP5EZ.js.map +0 -1
- package/dist/dist-YOVM5HEY.js.map +0 -1
package/dist/api.js
CHANGED
|
@@ -2,12 +2,9 @@ import {
|
|
|
2
2
|
importPKCS8,
|
|
3
3
|
jwtVerify
|
|
4
4
|
} from "./chunk-D6EKRYGP.js";
|
|
5
|
-
import {
|
|
6
|
-
Hono,
|
|
7
|
-
cors
|
|
8
|
-
} from "./chunk-TEPNEZ63.js";
|
|
9
5
|
|
|
10
6
|
// ../@emulators/core/dist/index.js
|
|
7
|
+
import { createServer as createNodeServer } from "http";
|
|
11
8
|
import { createHmac } from "crypto";
|
|
12
9
|
import { readFileSync } from "fs";
|
|
13
10
|
import { fileURLToPath } from "url";
|
|
@@ -231,6 +228,397 @@ var Store = class {
|
|
|
231
228
|
}
|
|
232
229
|
}
|
|
233
230
|
};
|
|
231
|
+
var HonoRequest = class {
|
|
232
|
+
constructor(request, params) {
|
|
233
|
+
this.params = params;
|
|
234
|
+
this.raw = request;
|
|
235
|
+
this.url = request.url;
|
|
236
|
+
this.method = request.method;
|
|
237
|
+
this.path = new URL(request.url).pathname;
|
|
238
|
+
}
|
|
239
|
+
raw;
|
|
240
|
+
url;
|
|
241
|
+
method;
|
|
242
|
+
path;
|
|
243
|
+
header(name) {
|
|
244
|
+
if (name) return this.raw.headers.get(name) ?? void 0;
|
|
245
|
+
const headers = {};
|
|
246
|
+
this.raw.headers.forEach((value, key) => {
|
|
247
|
+
headers[key] = value;
|
|
248
|
+
});
|
|
249
|
+
return headers;
|
|
250
|
+
}
|
|
251
|
+
query(name) {
|
|
252
|
+
return new URL(this.url).searchParams.get(name) ?? void 0;
|
|
253
|
+
}
|
|
254
|
+
queries(name) {
|
|
255
|
+
const values = new URL(this.url).searchParams.getAll(name);
|
|
256
|
+
return values.length > 0 ? values : void 0;
|
|
257
|
+
}
|
|
258
|
+
param(name) {
|
|
259
|
+
if (!name) return { ...this.params };
|
|
260
|
+
return this.params[name] ?? "";
|
|
261
|
+
}
|
|
262
|
+
json() {
|
|
263
|
+
return this.raw.json();
|
|
264
|
+
}
|
|
265
|
+
text() {
|
|
266
|
+
return this.raw.text();
|
|
267
|
+
}
|
|
268
|
+
arrayBuffer() {
|
|
269
|
+
return this.raw.arrayBuffer();
|
|
270
|
+
}
|
|
271
|
+
async parseBody() {
|
|
272
|
+
const contentType = this.header("Content-Type") ?? "";
|
|
273
|
+
if (contentType.includes("multipart/form-data")) {
|
|
274
|
+
return formDataToObject(await this.raw.formData());
|
|
275
|
+
}
|
|
276
|
+
if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
277
|
+
const params = new URLSearchParams(await this.raw.text());
|
|
278
|
+
const out = {};
|
|
279
|
+
for (const [key, value] of params) {
|
|
280
|
+
appendBodyValue(out, key, value);
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
if (contentType.includes("application/json")) {
|
|
285
|
+
const body = await this.raw.json().catch(() => ({}));
|
|
286
|
+
return body && typeof body === "object" && !Array.isArray(body) ? body : {};
|
|
287
|
+
}
|
|
288
|
+
return {};
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
var Context = class {
|
|
292
|
+
constructor(request, params, notFoundHandler) {
|
|
293
|
+
this.notFoundHandler = notFoundHandler;
|
|
294
|
+
this.req = new HonoRequest(request, params);
|
|
295
|
+
}
|
|
296
|
+
req;
|
|
297
|
+
vars = /* @__PURE__ */ new Map();
|
|
298
|
+
responseHeaders = new Headers();
|
|
299
|
+
responseStatus = 200;
|
|
300
|
+
get(key) {
|
|
301
|
+
return this.vars.get(key);
|
|
302
|
+
}
|
|
303
|
+
set(key, value) {
|
|
304
|
+
this.vars.set(key, value);
|
|
305
|
+
}
|
|
306
|
+
header(name, value) {
|
|
307
|
+
this.responseHeaders.set(name, value);
|
|
308
|
+
}
|
|
309
|
+
status(status) {
|
|
310
|
+
this.responseStatus = status;
|
|
311
|
+
}
|
|
312
|
+
json(data, status, headers) {
|
|
313
|
+
return this.response(JSON.stringify(data), status, defaultContentType(headers, "application/json; charset=UTF-8"));
|
|
314
|
+
}
|
|
315
|
+
text(text, status, headers) {
|
|
316
|
+
return this.response(text, status, defaultContentType(headers, "text/plain; charset=UTF-8"));
|
|
317
|
+
}
|
|
318
|
+
html(html, status, headers) {
|
|
319
|
+
return this.response(html, status, defaultContentType(headers, "text/html; charset=UTF-8"));
|
|
320
|
+
}
|
|
321
|
+
body(body, status, headers) {
|
|
322
|
+
return this.response(body, status, headers);
|
|
323
|
+
}
|
|
324
|
+
redirect(location, status = 302) {
|
|
325
|
+
return this.response(null, status, { Location: location });
|
|
326
|
+
}
|
|
327
|
+
notFound() {
|
|
328
|
+
return this.notFoundHandler(this);
|
|
329
|
+
}
|
|
330
|
+
finalize(response) {
|
|
331
|
+
if (!hasHeaders(this.responseHeaders)) return response;
|
|
332
|
+
const headers = new Headers(response.headers);
|
|
333
|
+
this.responseHeaders.forEach((value, key) => {
|
|
334
|
+
headers.set(key, value);
|
|
335
|
+
});
|
|
336
|
+
return new Response(response.body, {
|
|
337
|
+
status: response.status,
|
|
338
|
+
statusText: response.statusText,
|
|
339
|
+
headers
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
response(body, status, headers) {
|
|
343
|
+
const merged = new Headers(headers);
|
|
344
|
+
this.responseHeaders.forEach((value, key) => {
|
|
345
|
+
merged.set(key, value);
|
|
346
|
+
});
|
|
347
|
+
return new Response(body, {
|
|
348
|
+
status: status ?? this.responseStatus,
|
|
349
|
+
headers: merged
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
var Hono = class {
|
|
354
|
+
middleware = [];
|
|
355
|
+
routes = [];
|
|
356
|
+
errorHandler = (err) => {
|
|
357
|
+
const message = err instanceof Error ? err.message : "Internal Server Error";
|
|
358
|
+
return new Response(message, { status: 500 });
|
|
359
|
+
};
|
|
360
|
+
notFoundHandler = () => new Response("404 Not Found", { status: 404 });
|
|
361
|
+
use(pathOrHandler, ...handlers) {
|
|
362
|
+
if (typeof pathOrHandler === "string") {
|
|
363
|
+
this.middleware.push({ method: "ALL", compiled: compilePath(pathOrHandler), handlers });
|
|
364
|
+
} else {
|
|
365
|
+
this.middleware.push({ method: "ALL", compiled: compilePath("*"), handlers: [pathOrHandler, ...handlers] });
|
|
366
|
+
}
|
|
367
|
+
return this;
|
|
368
|
+
}
|
|
369
|
+
on(method, path, ...handlers) {
|
|
370
|
+
this.routes.push({ method: method.toUpperCase(), compiled: compilePath(path), handlers });
|
|
371
|
+
return this;
|
|
372
|
+
}
|
|
373
|
+
get(path, ...handlers) {
|
|
374
|
+
return this.on("GET", path, ...handlers);
|
|
375
|
+
}
|
|
376
|
+
post(path, ...handlers) {
|
|
377
|
+
return this.on("POST", path, ...handlers);
|
|
378
|
+
}
|
|
379
|
+
put(path, ...handlers) {
|
|
380
|
+
return this.on("PUT", path, ...handlers);
|
|
381
|
+
}
|
|
382
|
+
patch(path, ...handlers) {
|
|
383
|
+
return this.on("PATCH", path, ...handlers);
|
|
384
|
+
}
|
|
385
|
+
delete(path, ...handlers) {
|
|
386
|
+
return this.on("DELETE", path, ...handlers);
|
|
387
|
+
}
|
|
388
|
+
onError(handler) {
|
|
389
|
+
this.errorHandler = handler;
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
notFound(handler) {
|
|
393
|
+
this.notFoundHandler = handler;
|
|
394
|
+
return this;
|
|
395
|
+
}
|
|
396
|
+
async request(input, init) {
|
|
397
|
+
if (input instanceof Request) return this.fetch(input);
|
|
398
|
+
const url = input.startsWith("/") ? `http://localhost${input}` : input;
|
|
399
|
+
return this.fetch(new Request(url, init));
|
|
400
|
+
}
|
|
401
|
+
fetch = async (request) => {
|
|
402
|
+
const url = new URL(request.url);
|
|
403
|
+
const path = url.pathname;
|
|
404
|
+
const method = request.method.toUpperCase();
|
|
405
|
+
const matched = this.match(method, path);
|
|
406
|
+
const context = new Context(request, matched.params, this.notFoundHandler);
|
|
407
|
+
try {
|
|
408
|
+
const response = await this.dispatch(context, matched.handlers);
|
|
409
|
+
return context.finalize(response ?? await this.notFoundHandler(context));
|
|
410
|
+
} catch (err) {
|
|
411
|
+
return context.finalize(await this.errorHandler(err, context));
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
match(method, path) {
|
|
415
|
+
const handlers = [];
|
|
416
|
+
const params = {};
|
|
417
|
+
for (const route2 of this.middleware) {
|
|
418
|
+
const match = matchPath(route2.compiled, path);
|
|
419
|
+
if (!match) continue;
|
|
420
|
+
Object.assign(params, match);
|
|
421
|
+
for (const handler of route2.handlers) {
|
|
422
|
+
handlers.push({ handler, params: match });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const route = this.routes.find((candidate) => candidate.method === method && matchPath(candidate.compiled, path) != null) ?? (method === "HEAD" ? this.routes.find((candidate) => candidate.method === "GET" && matchPath(candidate.compiled, path) != null) : void 0);
|
|
426
|
+
if (route) {
|
|
427
|
+
const match = matchPath(route.compiled, path) ?? {};
|
|
428
|
+
Object.assign(params, match);
|
|
429
|
+
for (const handler of route.handlers) {
|
|
430
|
+
handlers.push({ handler, params: match });
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return { handlers, params };
|
|
434
|
+
}
|
|
435
|
+
async dispatch(context, handlers) {
|
|
436
|
+
let index = -1;
|
|
437
|
+
const run = async (nextIndex) => {
|
|
438
|
+
if (nextIndex <= index) throw new Error("next() called multiple times");
|
|
439
|
+
index = nextIndex;
|
|
440
|
+
const matched = handlers[nextIndex];
|
|
441
|
+
if (!matched) return void 0;
|
|
442
|
+
const originalParams = context.req.param();
|
|
443
|
+
Object.assign(originalParams, matched.params);
|
|
444
|
+
let nextResponse = void 0;
|
|
445
|
+
let nextCalled = false;
|
|
446
|
+
const next = async () => {
|
|
447
|
+
nextCalled = true;
|
|
448
|
+
nextResponse = await run(nextIndex + 1);
|
|
449
|
+
};
|
|
450
|
+
const response = await matched.handler(context, next);
|
|
451
|
+
if (response instanceof Response) return response;
|
|
452
|
+
if (nextCalled) return nextResponse;
|
|
453
|
+
return response;
|
|
454
|
+
};
|
|
455
|
+
return run(0);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
function cors(options = {}) {
|
|
459
|
+
const origin = options.origin ?? "*";
|
|
460
|
+
const allowMethods = options.allowMethods ?? ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH", "OPTIONS"];
|
|
461
|
+
return async (c, next) => {
|
|
462
|
+
c.header("Access-Control-Allow-Origin", origin);
|
|
463
|
+
if (options.credentials) c.header("Access-Control-Allow-Credentials", "true");
|
|
464
|
+
if (c.req.method.toUpperCase() === "OPTIONS") {
|
|
465
|
+
c.header("Access-Control-Allow-Methods", allowMethods.join(","));
|
|
466
|
+
const allowHeaders = options.allowHeaders?.join(",") ?? c.req.header("Access-Control-Request-Headers");
|
|
467
|
+
if (allowHeaders) c.header("Access-Control-Allow-Headers", allowHeaders);
|
|
468
|
+
if (options.maxAge != null) c.header("Access-Control-Max-Age", String(options.maxAge));
|
|
469
|
+
return c.body(null, 204);
|
|
470
|
+
}
|
|
471
|
+
await next();
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
function serve(options) {
|
|
475
|
+
const port = options.port ?? 3e3;
|
|
476
|
+
const server = createNodeServer(async (req, res) => {
|
|
477
|
+
try {
|
|
478
|
+
const request = nodeRequestToFetchRequest(req);
|
|
479
|
+
const response = await options.fetch(request);
|
|
480
|
+
await writeFetchResponse(res, response, req.method?.toUpperCase() === "HEAD");
|
|
481
|
+
} catch (err) {
|
|
482
|
+
const message = err instanceof Error ? err.message : "Internal Server Error";
|
|
483
|
+
res.statusCode = 500;
|
|
484
|
+
res.setHeader("Content-Type", "text/plain; charset=UTF-8");
|
|
485
|
+
res.end(message);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
server.listen(port, options.hostname);
|
|
489
|
+
return server;
|
|
490
|
+
}
|
|
491
|
+
function compilePath(pattern) {
|
|
492
|
+
if (pattern === "*" || pattern === "/*") {
|
|
493
|
+
return { pattern, regex: /^.*$/, paramNames: [] };
|
|
494
|
+
}
|
|
495
|
+
const paramNames = [];
|
|
496
|
+
let source = "^";
|
|
497
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
498
|
+
const char = pattern[i];
|
|
499
|
+
if (char !== ":") {
|
|
500
|
+
source += escapeRegex(char);
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
let name = "";
|
|
504
|
+
i++;
|
|
505
|
+
while (i < pattern.length && /[A-Za-z0-9_]/.test(pattern[i])) {
|
|
506
|
+
name += pattern[i];
|
|
507
|
+
i++;
|
|
508
|
+
}
|
|
509
|
+
i--;
|
|
510
|
+
paramNames.push(name);
|
|
511
|
+
if (pattern[i + 1] === "{") {
|
|
512
|
+
const close = pattern.indexOf("}", i + 2);
|
|
513
|
+
if (close < 0) throw new Error(`Invalid route pattern: ${pattern}`);
|
|
514
|
+
const expr = pattern.slice(i + 2, close);
|
|
515
|
+
source += `(${expr})`;
|
|
516
|
+
i = close;
|
|
517
|
+
} else {
|
|
518
|
+
source += "([^/]+)";
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
source += "$";
|
|
522
|
+
return { pattern, regex: new RegExp(source), paramNames };
|
|
523
|
+
}
|
|
524
|
+
function matchPath(compiled, path) {
|
|
525
|
+
const match = compiled.regex.exec(path);
|
|
526
|
+
if (!match) return null;
|
|
527
|
+
const params = {};
|
|
528
|
+
for (let i = 0; i < compiled.paramNames.length; i++) {
|
|
529
|
+
params[compiled.paramNames[i]] = decodePathParam(match[i + 1] ?? "");
|
|
530
|
+
}
|
|
531
|
+
return params;
|
|
532
|
+
}
|
|
533
|
+
function decodePathParam(value) {
|
|
534
|
+
try {
|
|
535
|
+
return decodeURIComponent(value);
|
|
536
|
+
} catch {
|
|
537
|
+
return value;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function escapeRegex(value) {
|
|
541
|
+
return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
|
|
542
|
+
}
|
|
543
|
+
function hasHeaders(headers) {
|
|
544
|
+
for (const _ of headers) return true;
|
|
545
|
+
return false;
|
|
546
|
+
}
|
|
547
|
+
function defaultContentType(headers, contentType) {
|
|
548
|
+
const out = new Headers(headers);
|
|
549
|
+
if (!out.has("Content-Type")) {
|
|
550
|
+
out.set("Content-Type", contentType);
|
|
551
|
+
}
|
|
552
|
+
return out;
|
|
553
|
+
}
|
|
554
|
+
function formDataToObject(formData) {
|
|
555
|
+
const out = {};
|
|
556
|
+
for (const [key, value] of formData) {
|
|
557
|
+
appendBodyValue(out, key, value);
|
|
558
|
+
}
|
|
559
|
+
return out;
|
|
560
|
+
}
|
|
561
|
+
function appendBodyValue(target, key, value) {
|
|
562
|
+
const existing = target[key];
|
|
563
|
+
if (existing === void 0) {
|
|
564
|
+
target[key] = value;
|
|
565
|
+
} else if (Array.isArray(existing)) {
|
|
566
|
+
existing.push(value);
|
|
567
|
+
} else {
|
|
568
|
+
target[key] = [existing, value];
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
function nodeRequestToFetchRequest(req) {
|
|
572
|
+
const host = req.headers.host ?? "localhost";
|
|
573
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
574
|
+
const headers = new Headers();
|
|
575
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
576
|
+
if (value == null) continue;
|
|
577
|
+
if (Array.isArray(value)) {
|
|
578
|
+
for (const item of value) headers.append(key, item);
|
|
579
|
+
} else {
|
|
580
|
+
headers.set(key, value);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
const method = req.method ?? "GET";
|
|
584
|
+
const hasBody = method !== "GET" && method !== "HEAD";
|
|
585
|
+
return new Request(url.toString(), {
|
|
586
|
+
method,
|
|
587
|
+
headers,
|
|
588
|
+
body: hasBody ? req : void 0,
|
|
589
|
+
duplex: "half"
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
async function writeFetchResponse(res, response, headOnly) {
|
|
593
|
+
res.statusCode = response.status;
|
|
594
|
+
res.statusMessage = response.statusText;
|
|
595
|
+
const headersWithCookies = response.headers;
|
|
596
|
+
const cookies = headersWithCookies.getSetCookie?.();
|
|
597
|
+
response.headers.forEach((value, key) => {
|
|
598
|
+
if (key.toLowerCase() === "set-cookie" && cookies && cookies.length > 0) return;
|
|
599
|
+
res.setHeader(key, value);
|
|
600
|
+
});
|
|
601
|
+
if (cookies && cookies.length > 0) {
|
|
602
|
+
res.setHeader("Set-Cookie", cookies);
|
|
603
|
+
}
|
|
604
|
+
if (headOnly || !response.body) {
|
|
605
|
+
res.end();
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
const reader = response.body.getReader();
|
|
609
|
+
try {
|
|
610
|
+
while (true) {
|
|
611
|
+
const { done, value } = await reader.read();
|
|
612
|
+
if (done) break;
|
|
613
|
+
if (!res.write(value)) {
|
|
614
|
+
await new Promise((resolve) => res.once("drain", resolve));
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
res.end();
|
|
618
|
+
} catch (err) {
|
|
619
|
+
res.destroy(err instanceof Error ? err : void 0);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
234
622
|
var MAX_DELIVERIES = 1e3;
|
|
235
623
|
var WebhookDispatcher = class {
|
|
236
624
|
subscriptions = [];
|
|
@@ -387,9 +775,7 @@ function authMiddleware(tokens, appKeyResolver, fallbackUser) {
|
|
|
387
775
|
if (token.startsWith("eyJ") && appKeyResolver) {
|
|
388
776
|
try {
|
|
389
777
|
const [, payloadB64] = token.split(".");
|
|
390
|
-
const payload = JSON.parse(
|
|
391
|
-
Buffer.from(payloadB64, "base64url").toString()
|
|
392
|
-
);
|
|
778
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
|
|
393
779
|
const appId = typeof payload.iss === "string" ? parseInt(payload.iss, 10) : payload.iss;
|
|
394
780
|
if (typeof appId === "number" && !isNaN(appId)) {
|
|
395
781
|
const appInfo = appKeyResolver(appId);
|
|
@@ -426,6 +812,7 @@ var FONTS = {
|
|
|
426
812
|
"geist-sans.woff2": readFileSync(join(__dirname, "fonts", "geist-sans.woff2")),
|
|
427
813
|
"GeistPixel-Square.woff2": readFileSync(join(__dirname, "fonts", "GeistPixel-Square.woff2"))
|
|
428
814
|
};
|
|
815
|
+
var FAVICON = readFileSync(join(__dirname, "fonts", "favicon.ico"));
|
|
429
816
|
function registerFontRoutes(app) {
|
|
430
817
|
app.get("/_emulate/fonts/:name", (c) => {
|
|
431
818
|
const name = c.req.param("name");
|
|
@@ -439,6 +826,14 @@ function registerFontRoutes(app) {
|
|
|
439
826
|
}
|
|
440
827
|
});
|
|
441
828
|
});
|
|
829
|
+
app.get("/_emulate/favicon.ico", (c) => {
|
|
830
|
+
return new Response(FAVICON, {
|
|
831
|
+
headers: {
|
|
832
|
+
"Content-Type": "image/x-icon",
|
|
833
|
+
"Cache-Control": "public, max-age=31536000, immutable"
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
});
|
|
442
837
|
}
|
|
443
838
|
function createServer(plugin, options = {}) {
|
|
444
839
|
const port = options.port ?? 4e3;
|
|
@@ -513,7 +908,7 @@ var SERVICE_REGISTRY = {
|
|
|
513
908
|
label: "Vercel REST API emulator",
|
|
514
909
|
endpoints: "projects, deployments, domains, env vars, users, teams, file uploads, protection bypass",
|
|
515
910
|
async load() {
|
|
516
|
-
const mod = await import("./dist-
|
|
911
|
+
const mod = await import("./dist-CXRPM6BK.js");
|
|
517
912
|
return { plugin: mod.vercelPlugin, seedFromConfig: mod.seedFromConfig };
|
|
518
913
|
},
|
|
519
914
|
defaultFallback(cfg) {
|
|
@@ -525,12 +920,14 @@ var SERVICE_REGISTRY = {
|
|
|
525
920
|
users: [{ username: "developer", name: "Developer", email: "dev@example.com" }],
|
|
526
921
|
teams: [{ slug: "my-team", name: "My Team" }],
|
|
527
922
|
projects: [{ name: "my-app", team: "my-team", framework: "nextjs" }],
|
|
528
|
-
integrations: [
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
923
|
+
integrations: [
|
|
924
|
+
{
|
|
925
|
+
client_id: "oac_example_client_id",
|
|
926
|
+
client_secret: "example_client_secret",
|
|
927
|
+
name: "My Vercel App",
|
|
928
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/vercel"]
|
|
929
|
+
}
|
|
930
|
+
]
|
|
534
931
|
}
|
|
535
932
|
}
|
|
536
933
|
},
|
|
@@ -538,7 +935,7 @@ var SERVICE_REGISTRY = {
|
|
|
538
935
|
label: "GitHub REST API emulator",
|
|
539
936
|
endpoints: "users, repos, issues, PRs, comments, reviews, labels, milestones, branches, git data, orgs, teams, releases, webhooks, search, actions, checks, rate limit",
|
|
540
937
|
async load() {
|
|
541
|
-
const mod = await import("./dist-
|
|
938
|
+
const mod = await import("./dist-PO4CL5SJ.js");
|
|
542
939
|
return {
|
|
543
940
|
plugin: mod.githubPlugin,
|
|
544
941
|
seedFromConfig: mod.seedFromConfig,
|
|
@@ -562,25 +959,42 @@ var SERVICE_REGISTRY = {
|
|
|
562
959
|
},
|
|
563
960
|
initConfig: {
|
|
564
961
|
github: {
|
|
565
|
-
users: [
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
962
|
+
users: [
|
|
963
|
+
{
|
|
964
|
+
login: "octocat",
|
|
965
|
+
name: "The Octocat",
|
|
966
|
+
email: "octocat@github.com",
|
|
967
|
+
bio: "I am the Octocat",
|
|
968
|
+
company: "GitHub",
|
|
969
|
+
location: "San Francisco"
|
|
970
|
+
}
|
|
971
|
+
],
|
|
573
972
|
orgs: [{ login: "my-org", name: "My Organization", description: "A test organization" }],
|
|
574
973
|
repos: [
|
|
575
|
-
{
|
|
576
|
-
|
|
974
|
+
{
|
|
975
|
+
owner: "octocat",
|
|
976
|
+
name: "hello-world",
|
|
977
|
+
description: "My first repository",
|
|
978
|
+
language: "JavaScript",
|
|
979
|
+
topics: ["hello", "world"],
|
|
980
|
+
auto_init: true
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
owner: "my-org",
|
|
984
|
+
name: "org-repo",
|
|
985
|
+
description: "An organization repository",
|
|
986
|
+
language: "TypeScript",
|
|
987
|
+
auto_init: true
|
|
988
|
+
}
|
|
577
989
|
],
|
|
578
|
-
oauth_apps: [
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
990
|
+
oauth_apps: [
|
|
991
|
+
{
|
|
992
|
+
client_id: "Iv1.example_client_id",
|
|
993
|
+
client_secret: "example_client_secret",
|
|
994
|
+
name: "My App",
|
|
995
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/github"]
|
|
996
|
+
}
|
|
997
|
+
]
|
|
584
998
|
}
|
|
585
999
|
}
|
|
586
1000
|
},
|
|
@@ -588,7 +1002,7 @@ var SERVICE_REGISTRY = {
|
|
|
588
1002
|
label: "Google OAuth 2.0 / OpenID Connect + Gmail, Calendar, and Drive emulator",
|
|
589
1003
|
endpoints: "OAuth authorize, token exchange, userinfo, OIDC discovery, token revocation, Gmail messages/drafts/threads/labels/history/settings, Calendar lists/events/freebusy, Drive files/uploads",
|
|
590
1004
|
async load() {
|
|
591
|
-
const mod = await import("./dist-
|
|
1005
|
+
const mod = await import("./dist-ZY5SZSJ2.js");
|
|
592
1006
|
return { plugin: mod.googlePlugin, seedFromConfig: mod.seedFromConfig };
|
|
593
1007
|
},
|
|
594
1008
|
defaultFallback(cfg) {
|
|
@@ -597,59 +1011,153 @@ var SERVICE_REGISTRY = {
|
|
|
597
1011
|
},
|
|
598
1012
|
initConfig: {
|
|
599
1013
|
google: {
|
|
600
|
-
users: [
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
1014
|
+
users: [
|
|
1015
|
+
{
|
|
1016
|
+
email: "testuser@example.com",
|
|
1017
|
+
name: "Test User",
|
|
1018
|
+
picture: "https://lh3.googleusercontent.com/a/default-user",
|
|
1019
|
+
email_verified: true
|
|
1020
|
+
}
|
|
1021
|
+
],
|
|
1022
|
+
oauth_clients: [
|
|
1023
|
+
{
|
|
1024
|
+
client_id: "example-client-id.apps.googleusercontent.com",
|
|
1025
|
+
client_secret: "GOCSPX-example_secret",
|
|
1026
|
+
name: "Code App (Google)",
|
|
1027
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/google"]
|
|
1028
|
+
}
|
|
1029
|
+
],
|
|
1030
|
+
labels: [
|
|
1031
|
+
{
|
|
1032
|
+
id: "Label_ops",
|
|
1033
|
+
user_email: "testuser@example.com",
|
|
1034
|
+
name: "Ops/Review",
|
|
1035
|
+
color_background: "#DDEEFF",
|
|
1036
|
+
color_text: "#111111"
|
|
1037
|
+
}
|
|
1038
|
+
],
|
|
1039
|
+
messages: [
|
|
1040
|
+
{
|
|
1041
|
+
id: "msg_welcome",
|
|
1042
|
+
user_email: "testuser@example.com",
|
|
1043
|
+
from: "welcome@example.com",
|
|
1044
|
+
to: "testuser@example.com",
|
|
1045
|
+
subject: "Welcome to the Gmail emulator",
|
|
1046
|
+
body_text: "You can now test Gmail, Calendar, and Drive flows locally.",
|
|
1047
|
+
label_ids: ["INBOX", "UNREAD", "CATEGORY_UPDATES"],
|
|
1048
|
+
date: "2025-01-04T10:00:00.000Z"
|
|
1049
|
+
}
|
|
1050
|
+
],
|
|
1051
|
+
calendars: [
|
|
1052
|
+
{
|
|
1053
|
+
id: "primary",
|
|
1054
|
+
user_email: "testuser@example.com",
|
|
1055
|
+
summary: "testuser@example.com",
|
|
1056
|
+
primary: true,
|
|
1057
|
+
selected: true,
|
|
1058
|
+
time_zone: "UTC"
|
|
1059
|
+
}
|
|
1060
|
+
],
|
|
1061
|
+
calendar_events: [
|
|
1062
|
+
{
|
|
1063
|
+
id: "evt_kickoff",
|
|
1064
|
+
user_email: "testuser@example.com",
|
|
1065
|
+
calendar_id: "primary",
|
|
1066
|
+
summary: "Project Kickoff",
|
|
1067
|
+
start_date_time: "2025-01-10T09:00:00.000Z",
|
|
1068
|
+
end_date_time: "2025-01-10T09:30:00.000Z"
|
|
1069
|
+
}
|
|
1070
|
+
],
|
|
1071
|
+
drive_items: [
|
|
1072
|
+
{
|
|
1073
|
+
id: "drv_docs",
|
|
1074
|
+
user_email: "testuser@example.com",
|
|
1075
|
+
name: "Docs",
|
|
1076
|
+
mime_type: "application/vnd.google-apps.folder",
|
|
1077
|
+
parent_ids: ["root"]
|
|
1078
|
+
}
|
|
1079
|
+
]
|
|
628
1080
|
}
|
|
629
1081
|
}
|
|
630
1082
|
},
|
|
631
1083
|
slack: {
|
|
632
1084
|
label: "Slack API emulator",
|
|
633
|
-
endpoints: "auth, chat, conversations, users, reactions, team, OAuth, incoming webhooks",
|
|
1085
|
+
endpoints: "auth, chat, conversations, users, profiles, presence, files, pins, bookmarks, views, reactions, team, OAuth, incoming webhooks, inspector",
|
|
634
1086
|
async load() {
|
|
635
|
-
const mod = await import("./dist-
|
|
1087
|
+
const mod = await import("./dist-OGSAVJ25.js");
|
|
636
1088
|
return { plugin: mod.slackPlugin, seedFromConfig: mod.seedFromConfig };
|
|
637
1089
|
},
|
|
638
1090
|
defaultFallback() {
|
|
639
|
-
return {
|
|
1091
|
+
return {
|
|
1092
|
+
login: "U000000001",
|
|
1093
|
+
id: 1,
|
|
1094
|
+
scopes: []
|
|
1095
|
+
};
|
|
640
1096
|
},
|
|
641
1097
|
initConfig: {
|
|
642
1098
|
slack: {
|
|
643
1099
|
team: { name: "My Workspace", domain: "my-workspace" },
|
|
644
|
-
users: [
|
|
645
|
-
|
|
1100
|
+
users: [
|
|
1101
|
+
{
|
|
1102
|
+
name: "developer",
|
|
1103
|
+
real_name: "Developer",
|
|
1104
|
+
email: "dev@example.com",
|
|
1105
|
+
profile: {
|
|
1106
|
+
title: "Local Developer",
|
|
1107
|
+
status_text: "Testing locally",
|
|
1108
|
+
status_emoji: ":computer:"
|
|
1109
|
+
},
|
|
1110
|
+
presence: "active"
|
|
1111
|
+
}
|
|
1112
|
+
],
|
|
1113
|
+
channels: [
|
|
1114
|
+
{ name: "general", topic: "General discussion" },
|
|
1115
|
+
{ name: "random", topic: "Random stuff" }
|
|
1116
|
+
],
|
|
646
1117
|
bots: [{ name: "my-bot" }],
|
|
647
|
-
oauth_apps: [
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
1118
|
+
oauth_apps: [
|
|
1119
|
+
{
|
|
1120
|
+
client_id: "12345.67890",
|
|
1121
|
+
client_secret: "example_client_secret",
|
|
1122
|
+
app_id: "A000000001",
|
|
1123
|
+
name: "My Slack App",
|
|
1124
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/slack"],
|
|
1125
|
+
scopes: [
|
|
1126
|
+
"chat:write",
|
|
1127
|
+
"channels:read",
|
|
1128
|
+
"channels:history",
|
|
1129
|
+
"channels:join",
|
|
1130
|
+
"channels:manage",
|
|
1131
|
+
"channels:write",
|
|
1132
|
+
"groups:read",
|
|
1133
|
+
"groups:history",
|
|
1134
|
+
"groups:write",
|
|
1135
|
+
"im:read",
|
|
1136
|
+
"im:history",
|
|
1137
|
+
"im:write",
|
|
1138
|
+
"mpim:read",
|
|
1139
|
+
"mpim:history",
|
|
1140
|
+
"mpim:write",
|
|
1141
|
+
"users:read",
|
|
1142
|
+
"users:read.email",
|
|
1143
|
+
"users.profile:read",
|
|
1144
|
+
"users.profile:write",
|
|
1145
|
+
"users:write",
|
|
1146
|
+
"files:read",
|
|
1147
|
+
"files:write",
|
|
1148
|
+
"pins:read",
|
|
1149
|
+
"pins:write",
|
|
1150
|
+
"bookmarks:read",
|
|
1151
|
+
"bookmarks:write",
|
|
1152
|
+
"reactions:read",
|
|
1153
|
+
"reactions:write",
|
|
1154
|
+
"team:read"
|
|
1155
|
+
],
|
|
1156
|
+
user_scopes: ["users:read", "users.profile:read"],
|
|
1157
|
+
bot_name: "my-bot"
|
|
1158
|
+
}
|
|
1159
|
+
],
|
|
1160
|
+
strict_scopes: false
|
|
653
1161
|
}
|
|
654
1162
|
}
|
|
655
1163
|
},
|
|
@@ -657,7 +1165,7 @@ var SERVICE_REGISTRY = {
|
|
|
657
1165
|
label: "Apple Sign In / OAuth emulator",
|
|
658
1166
|
endpoints: "OAuth authorize, token exchange, JWKS",
|
|
659
1167
|
async load() {
|
|
660
|
-
const mod = await import("./dist-
|
|
1168
|
+
const mod = await import("./dist-WACHAAVU.js");
|
|
661
1169
|
return { plugin: mod.applePlugin, seedFromConfig: mod.seedFromConfig };
|
|
662
1170
|
},
|
|
663
1171
|
defaultFallback(cfg) {
|
|
@@ -667,12 +1175,14 @@ var SERVICE_REGISTRY = {
|
|
|
667
1175
|
initConfig: {
|
|
668
1176
|
apple: {
|
|
669
1177
|
users: [{ email: "testuser@icloud.com", name: "Test User" }],
|
|
670
|
-
oauth_clients: [
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
1178
|
+
oauth_clients: [
|
|
1179
|
+
{
|
|
1180
|
+
client_id: "com.example.app",
|
|
1181
|
+
team_id: "TEAM001",
|
|
1182
|
+
name: "My Apple App",
|
|
1183
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/apple"]
|
|
1184
|
+
}
|
|
1185
|
+
]
|
|
676
1186
|
}
|
|
677
1187
|
}
|
|
678
1188
|
},
|
|
@@ -680,7 +1190,7 @@ var SERVICE_REGISTRY = {
|
|
|
680
1190
|
label: "Microsoft Entra ID OAuth 2.0 / OpenID Connect emulator",
|
|
681
1191
|
endpoints: "OAuth authorize, token exchange, userinfo, OIDC discovery, Graph /me, logout, token revocation",
|
|
682
1192
|
async load() {
|
|
683
|
-
const mod = await import("./dist-
|
|
1193
|
+
const mod = await import("./dist-IFULY5LE.js");
|
|
684
1194
|
return { plugin: mod.microsoftPlugin, seedFromConfig: mod.seedFromConfig };
|
|
685
1195
|
},
|
|
686
1196
|
defaultFallback(cfg) {
|
|
@@ -690,12 +1200,14 @@ var SERVICE_REGISTRY = {
|
|
|
690
1200
|
initConfig: {
|
|
691
1201
|
microsoft: {
|
|
692
1202
|
users: [{ email: "testuser@outlook.com", name: "Test User" }],
|
|
693
|
-
oauth_clients: [
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
1203
|
+
oauth_clients: [
|
|
1204
|
+
{
|
|
1205
|
+
client_id: "example-client-id",
|
|
1206
|
+
client_secret: "example-client-secret",
|
|
1207
|
+
name: "My Microsoft App",
|
|
1208
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/microsoft-entra-id"]
|
|
1209
|
+
}
|
|
1210
|
+
]
|
|
699
1211
|
}
|
|
700
1212
|
}
|
|
701
1213
|
},
|
|
@@ -703,7 +1215,7 @@ var SERVICE_REGISTRY = {
|
|
|
703
1215
|
label: "Okta OAuth 2.0 / OpenID Connect + management API emulator",
|
|
704
1216
|
endpoints: "OIDC discovery, JWKS, OAuth authorize/token/userinfo/introspect/revoke/logout, users, groups, apps, authorization servers",
|
|
705
1217
|
async load() {
|
|
706
|
-
const mod = await import("./dist-
|
|
1218
|
+
const mod = await import("./dist-XWWZVLQQ.js");
|
|
707
1219
|
return { plugin: mod.oktaPlugin, seedFromConfig: mod.seedFromConfig };
|
|
708
1220
|
},
|
|
709
1221
|
defaultFallback(cfg) {
|
|
@@ -715,13 +1227,15 @@ var SERVICE_REGISTRY = {
|
|
|
715
1227
|
users: [{ login: "testuser@okta.local", email: "testuser@okta.local", first_name: "Test", last_name: "User" }],
|
|
716
1228
|
groups: [{ name: "Everyone", description: "All users", type: "BUILT_IN", okta_id: "00g_everyone" }],
|
|
717
1229
|
authorization_servers: [{ id: "default", name: "default", audiences: ["api://default"] }],
|
|
718
|
-
oauth_clients: [
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1230
|
+
oauth_clients: [
|
|
1231
|
+
{
|
|
1232
|
+
client_id: "okta-test-client",
|
|
1233
|
+
client_secret: "okta-test-secret",
|
|
1234
|
+
name: "Sample OIDC Client",
|
|
1235
|
+
redirect_uris: ["http://localhost:3000/callback"],
|
|
1236
|
+
auth_server_id: "default"
|
|
1237
|
+
}
|
|
1238
|
+
]
|
|
725
1239
|
}
|
|
726
1240
|
}
|
|
727
1241
|
},
|
|
@@ -729,7 +1243,7 @@ var SERVICE_REGISTRY = {
|
|
|
729
1243
|
label: "AWS cloud service emulator",
|
|
730
1244
|
endpoints: "S3 (buckets, objects), SQS (queues, messages), IAM (users, roles, access keys), STS (assume role, caller identity)",
|
|
731
1245
|
async load() {
|
|
732
|
-
const mod = await import("./dist-
|
|
1246
|
+
const mod = await import("./dist-DSJSF3GY.js");
|
|
733
1247
|
return { plugin: mod.awsPlugin, seedFromConfig: mod.seedFromConfig };
|
|
734
1248
|
},
|
|
735
1249
|
defaultFallback() {
|
|
@@ -751,7 +1265,7 @@ var SERVICE_REGISTRY = {
|
|
|
751
1265
|
label: "Resend email API emulator",
|
|
752
1266
|
endpoints: "emails, domains, contacts, API keys, inbox UI",
|
|
753
1267
|
async load() {
|
|
754
|
-
const mod = await import("./dist-
|
|
1268
|
+
const mod = await import("./dist-R3TNKUIE.js");
|
|
755
1269
|
return { plugin: mod.resendPlugin, seedFromConfig: mod.seedFromConfig };
|
|
756
1270
|
},
|
|
757
1271
|
defaultFallback() {
|
|
@@ -766,9 +1280,9 @@ var SERVICE_REGISTRY = {
|
|
|
766
1280
|
},
|
|
767
1281
|
stripe: {
|
|
768
1282
|
label: "Stripe payments emulator",
|
|
769
|
-
endpoints: "customers, payment intents, charges, products, prices, checkout sessions, webhooks",
|
|
1283
|
+
endpoints: "customers, payment methods, customer sessions, payment intents, charges, products, prices, checkout sessions, webhooks",
|
|
770
1284
|
async load() {
|
|
771
|
-
const mod = await import("./dist-
|
|
1285
|
+
const mod = await import("./dist-NJJLJT2N.js");
|
|
772
1286
|
return { plugin: mod.stripePlugin, seedFromConfig: mod.seedFromConfig };
|
|
773
1287
|
},
|
|
774
1288
|
defaultFallback() {
|
|
@@ -786,7 +1300,7 @@ var SERVICE_REGISTRY = {
|
|
|
786
1300
|
label: "MongoDB Atlas service emulator",
|
|
787
1301
|
endpoints: "Atlas Admin API v2 (projects, clusters, database users, databases, collections), Atlas Data API v1 (findOne, find, insertOne, insertMany, updateOne, updateMany, deleteOne, deleteMany, aggregate)",
|
|
788
1302
|
async load() {
|
|
789
|
-
const mod = await import("./dist-
|
|
1303
|
+
const mod = await import("./dist-2ZZGNPJI.js");
|
|
790
1304
|
return { plugin: mod.mongoatlasPlugin, seedFromConfig: mod.seedFromConfig };
|
|
791
1305
|
},
|
|
792
1306
|
defaultFallback() {
|
|
@@ -800,11 +1314,68 @@ var SERVICE_REGISTRY = {
|
|
|
800
1314
|
databases: [{ cluster: "Cluster0", name: "test", collections: ["items"] }]
|
|
801
1315
|
}
|
|
802
1316
|
}
|
|
1317
|
+
},
|
|
1318
|
+
clerk: {
|
|
1319
|
+
label: "Clerk authentication and user management emulator",
|
|
1320
|
+
endpoints: "OIDC discovery, JWKS, OAuth authorize/token/userinfo, users, email addresses, organizations, memberships, invitations, sessions",
|
|
1321
|
+
async load() {
|
|
1322
|
+
const mod = await import("./dist-IRUBHCZU.js");
|
|
1323
|
+
return { plugin: mod.clerkPlugin, seedFromConfig: mod.seedFromConfig };
|
|
1324
|
+
},
|
|
1325
|
+
defaultFallback(cfg) {
|
|
1326
|
+
const firstEmail = cfg?.users?.[0]?.email_addresses?.[0] ?? "test@example.com";
|
|
1327
|
+
return { login: firstEmail, id: 1, scopes: [] };
|
|
1328
|
+
},
|
|
1329
|
+
initConfig: {
|
|
1330
|
+
clerk: {
|
|
1331
|
+
users: [
|
|
1332
|
+
{
|
|
1333
|
+
first_name: "Test",
|
|
1334
|
+
last_name: "User",
|
|
1335
|
+
email_addresses: ["test@example.com"],
|
|
1336
|
+
password: "clerk_test_password"
|
|
1337
|
+
}
|
|
1338
|
+
],
|
|
1339
|
+
organizations: [
|
|
1340
|
+
{
|
|
1341
|
+
name: "My Company",
|
|
1342
|
+
slug: "my-company",
|
|
1343
|
+
members: [{ email: "test@example.com", role: "admin" }]
|
|
1344
|
+
}
|
|
1345
|
+
],
|
|
1346
|
+
oauth_applications: [
|
|
1347
|
+
{
|
|
1348
|
+
client_id: "clerk_emulate_client",
|
|
1349
|
+
client_secret: "clerk_emulate_secret",
|
|
1350
|
+
name: "Emulate App",
|
|
1351
|
+
redirect_uris: ["http://localhost:3000/api/auth/callback/clerk"]
|
|
1352
|
+
}
|
|
1353
|
+
]
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
803
1356
|
}
|
|
804
1357
|
};
|
|
805
1358
|
|
|
1359
|
+
// src/base-url.ts
|
|
1360
|
+
function resolveBaseUrl(opts) {
|
|
1361
|
+
if (opts.seedBaseUrl) {
|
|
1362
|
+
return opts.seedBaseUrl.replace(/\{service\}/g, opts.service);
|
|
1363
|
+
}
|
|
1364
|
+
if (opts.baseUrl) {
|
|
1365
|
+
return opts.baseUrl.replace(/\{service\}/g, opts.service);
|
|
1366
|
+
}
|
|
1367
|
+
const envBaseUrl = process.env.EMULATE_BASE_URL;
|
|
1368
|
+
if (envBaseUrl) {
|
|
1369
|
+
return envBaseUrl.replace(/\{service\}/g, opts.service);
|
|
1370
|
+
}
|
|
1371
|
+
const portlessUrl = process.env.PORTLESS_URL;
|
|
1372
|
+
if (portlessUrl) {
|
|
1373
|
+
return portlessUrl.replace(/\{service\}/g, opts.service);
|
|
1374
|
+
}
|
|
1375
|
+
return `http://localhost:${opts.port}`;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
806
1378
|
// src/api.ts
|
|
807
|
-
import { serve } from "@hono/node-server";
|
|
808
1379
|
async function createEmulator(options) {
|
|
809
1380
|
const { service, port = 4e3, seed: seedConfig } = options;
|
|
810
1381
|
const entry = SERVICE_REGISTRY[service];
|
|
@@ -821,17 +1392,18 @@ async function createEmulator(options) {
|
|
|
821
1392
|
} else {
|
|
822
1393
|
tokens["test_token_admin"] = { login: "admin", id: 2, scopes: ["repo", "user", "admin:org", "admin:repo_hook"] };
|
|
823
1394
|
}
|
|
824
|
-
const
|
|
1395
|
+
const svcSeedConfig = seedConfig?.[service];
|
|
1396
|
+
const seedBaseUrl = typeof svcSeedConfig?.baseUrl === "string" && svcSeedConfig.baseUrl.length > 0 ? svcSeedConfig.baseUrl : void 0;
|
|
1397
|
+
const baseUrl = resolveBaseUrl({ service, port, baseUrl: options.baseUrl, seedBaseUrl });
|
|
825
1398
|
let cachedResolver;
|
|
826
1399
|
const appKeyResolver = loaded.createAppKeyResolver ? (appId) => cachedResolver(appId) : void 0;
|
|
827
|
-
const svcSeedConfig = seedConfig?.[service];
|
|
828
1400
|
const fallbackUser = entry.defaultFallback(svcSeedConfig);
|
|
829
|
-
const { app, store } = createServer(loaded.plugin, { port, baseUrl, tokens, appKeyResolver, fallbackUser });
|
|
1401
|
+
const { app, store, webhooks } = createServer(loaded.plugin, { port, baseUrl, tokens, appKeyResolver, fallbackUser });
|
|
830
1402
|
cachedResolver = loaded.createAppKeyResolver?.(store);
|
|
831
1403
|
const seed = () => {
|
|
832
1404
|
loaded.plugin.seed?.(store, baseUrl);
|
|
833
1405
|
if (svcSeedConfig && loaded.seedFromConfig) {
|
|
834
|
-
loaded.seedFromConfig(store, baseUrl, svcSeedConfig);
|
|
1406
|
+
loaded.seedFromConfig(store, baseUrl, svcSeedConfig, webhooks);
|
|
835
1407
|
}
|
|
836
1408
|
};
|
|
837
1409
|
seed();
|