emulate 0.5.0 → 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.
Files changed (45) hide show
  1. package/README.md +141 -19
  2. package/dist/api.js +460 -24
  3. package/dist/api.js.map +1 -1
  4. package/dist/{dist-PWGOAQC6.js → dist-2ZZGNPJI.js} +1 -1
  5. package/dist/dist-2ZZGNPJI.js.map +1 -0
  6. package/dist/{dist-4X2KPMAJ.js → dist-CXRPM6BK.js} +1 -3
  7. package/dist/dist-CXRPM6BK.js.map +1 -0
  8. package/dist/{dist-LDUHEJAN.js → dist-DSJSF3GY.js} +1 -3
  9. package/dist/dist-DSJSF3GY.js.map +1 -0
  10. package/dist/{dist-ETHHYBGF.js → dist-IFULY5LE.js} +1 -2
  11. package/dist/dist-IFULY5LE.js.map +1 -0
  12. package/dist/{dist-J6LHUR52.js → dist-IRUBHCZU.js} +1 -2
  13. package/dist/dist-IRUBHCZU.js.map +1 -0
  14. package/dist/{dist-ENKE2S7V.js → dist-NJJLJT2N.js} +1 -3
  15. package/dist/dist-NJJLJT2N.js.map +1 -0
  16. package/dist/dist-OGSAVJ25.js +4874 -0
  17. package/dist/dist-OGSAVJ25.js.map +1 -0
  18. package/dist/{dist-REDHDZ3V.js → dist-PO4CL5SJ.js} +1 -3
  19. package/dist/dist-PO4CL5SJ.js.map +1 -0
  20. package/dist/{dist-IBXD3O6A.js → dist-R3TNKUIE.js} +1 -3
  21. package/dist/dist-R3TNKUIE.js.map +1 -0
  22. package/dist/{dist-CFST4X4K.js → dist-WACHAAVU.js} +1 -2
  23. package/dist/dist-WACHAAVU.js.map +1 -0
  24. package/dist/{dist-5JVGPOL3.js → dist-XWWZVLQQ.js} +1 -2
  25. package/dist/dist-XWWZVLQQ.js.map +1 -0
  26. package/dist/{dist-KKTYBE5S.js → dist-ZY5SZSJ2.js} +8 -3
  27. package/dist/dist-ZY5SZSJ2.js.map +1 -0
  28. package/dist/index.js +464 -26
  29. package/dist/index.js.map +1 -1
  30. package/package.json +14 -15
  31. package/dist/chunk-AQ2CLRU3.js +0 -2146
  32. package/dist/chunk-AQ2CLRU3.js.map +0 -1
  33. package/dist/dist-4X2KPMAJ.js.map +0 -1
  34. package/dist/dist-5JVGPOL3.js.map +0 -1
  35. package/dist/dist-CE6BUCWQ.js +0 -1438
  36. package/dist/dist-CE6BUCWQ.js.map +0 -1
  37. package/dist/dist-CFST4X4K.js.map +0 -1
  38. package/dist/dist-ENKE2S7V.js.map +0 -1
  39. package/dist/dist-ETHHYBGF.js.map +0 -1
  40. package/dist/dist-IBXD3O6A.js.map +0 -1
  41. package/dist/dist-J6LHUR52.js.map +0 -1
  42. package/dist/dist-KKTYBE5S.js.map +0 -1
  43. package/dist/dist-LDUHEJAN.js.map +0 -1
  44. package/dist/dist-PWGOAQC6.js.map +0 -1
  45. package/dist/dist-REDHDZ3V.js.map +0 -1
package/dist/index.js CHANGED
@@ -3,15 +3,12 @@ import {
3
3
  importPKCS8,
4
4
  jwtVerify
5
5
  } from "./chunk-D6EKRYGP.js";
6
- import {
7
- Hono,
8
- cors
9
- } from "./chunk-AQ2CLRU3.js";
10
6
 
11
7
  // src/index.ts
12
8
  import { Command } from "commander";
13
9
 
14
10
  // ../@emulators/core/dist/index.js
11
+ import { createServer as createNodeServer } from "http";
15
12
  import { createHmac } from "crypto";
16
13
  import { readFileSync } from "fs";
17
14
  import { fileURLToPath } from "url";
@@ -235,6 +232,397 @@ var Store = class {
235
232
  }
236
233
  }
237
234
  };
235
+ var HonoRequest = class {
236
+ constructor(request, params) {
237
+ this.params = params;
238
+ this.raw = request;
239
+ this.url = request.url;
240
+ this.method = request.method;
241
+ this.path = new URL(request.url).pathname;
242
+ }
243
+ raw;
244
+ url;
245
+ method;
246
+ path;
247
+ header(name) {
248
+ if (name) return this.raw.headers.get(name) ?? void 0;
249
+ const headers = {};
250
+ this.raw.headers.forEach((value, key) => {
251
+ headers[key] = value;
252
+ });
253
+ return headers;
254
+ }
255
+ query(name) {
256
+ return new URL(this.url).searchParams.get(name) ?? void 0;
257
+ }
258
+ queries(name) {
259
+ const values = new URL(this.url).searchParams.getAll(name);
260
+ return values.length > 0 ? values : void 0;
261
+ }
262
+ param(name) {
263
+ if (!name) return { ...this.params };
264
+ return this.params[name] ?? "";
265
+ }
266
+ json() {
267
+ return this.raw.json();
268
+ }
269
+ text() {
270
+ return this.raw.text();
271
+ }
272
+ arrayBuffer() {
273
+ return this.raw.arrayBuffer();
274
+ }
275
+ async parseBody() {
276
+ const contentType = this.header("Content-Type") ?? "";
277
+ if (contentType.includes("multipart/form-data")) {
278
+ return formDataToObject(await this.raw.formData());
279
+ }
280
+ if (contentType.includes("application/x-www-form-urlencoded")) {
281
+ const params = new URLSearchParams(await this.raw.text());
282
+ const out = {};
283
+ for (const [key, value] of params) {
284
+ appendBodyValue(out, key, value);
285
+ }
286
+ return out;
287
+ }
288
+ if (contentType.includes("application/json")) {
289
+ const body = await this.raw.json().catch(() => ({}));
290
+ return body && typeof body === "object" && !Array.isArray(body) ? body : {};
291
+ }
292
+ return {};
293
+ }
294
+ };
295
+ var Context = class {
296
+ constructor(request, params, notFoundHandler) {
297
+ this.notFoundHandler = notFoundHandler;
298
+ this.req = new HonoRequest(request, params);
299
+ }
300
+ req;
301
+ vars = /* @__PURE__ */ new Map();
302
+ responseHeaders = new Headers();
303
+ responseStatus = 200;
304
+ get(key) {
305
+ return this.vars.get(key);
306
+ }
307
+ set(key, value) {
308
+ this.vars.set(key, value);
309
+ }
310
+ header(name, value) {
311
+ this.responseHeaders.set(name, value);
312
+ }
313
+ status(status) {
314
+ this.responseStatus = status;
315
+ }
316
+ json(data, status, headers) {
317
+ return this.response(JSON.stringify(data), status, defaultContentType(headers, "application/json; charset=UTF-8"));
318
+ }
319
+ text(text, status, headers) {
320
+ return this.response(text, status, defaultContentType(headers, "text/plain; charset=UTF-8"));
321
+ }
322
+ html(html, status, headers) {
323
+ return this.response(html, status, defaultContentType(headers, "text/html; charset=UTF-8"));
324
+ }
325
+ body(body, status, headers) {
326
+ return this.response(body, status, headers);
327
+ }
328
+ redirect(location, status = 302) {
329
+ return this.response(null, status, { Location: location });
330
+ }
331
+ notFound() {
332
+ return this.notFoundHandler(this);
333
+ }
334
+ finalize(response) {
335
+ if (!hasHeaders(this.responseHeaders)) return response;
336
+ const headers = new Headers(response.headers);
337
+ this.responseHeaders.forEach((value, key) => {
338
+ headers.set(key, value);
339
+ });
340
+ return new Response(response.body, {
341
+ status: response.status,
342
+ statusText: response.statusText,
343
+ headers
344
+ });
345
+ }
346
+ response(body, status, headers) {
347
+ const merged = new Headers(headers);
348
+ this.responseHeaders.forEach((value, key) => {
349
+ merged.set(key, value);
350
+ });
351
+ return new Response(body, {
352
+ status: status ?? this.responseStatus,
353
+ headers: merged
354
+ });
355
+ }
356
+ };
357
+ var Hono = class {
358
+ middleware = [];
359
+ routes = [];
360
+ errorHandler = (err) => {
361
+ const message = err instanceof Error ? err.message : "Internal Server Error";
362
+ return new Response(message, { status: 500 });
363
+ };
364
+ notFoundHandler = () => new Response("404 Not Found", { status: 404 });
365
+ use(pathOrHandler, ...handlers) {
366
+ if (typeof pathOrHandler === "string") {
367
+ this.middleware.push({ method: "ALL", compiled: compilePath(pathOrHandler), handlers });
368
+ } else {
369
+ this.middleware.push({ method: "ALL", compiled: compilePath("*"), handlers: [pathOrHandler, ...handlers] });
370
+ }
371
+ return this;
372
+ }
373
+ on(method, path, ...handlers) {
374
+ this.routes.push({ method: method.toUpperCase(), compiled: compilePath(path), handlers });
375
+ return this;
376
+ }
377
+ get(path, ...handlers) {
378
+ return this.on("GET", path, ...handlers);
379
+ }
380
+ post(path, ...handlers) {
381
+ return this.on("POST", path, ...handlers);
382
+ }
383
+ put(path, ...handlers) {
384
+ return this.on("PUT", path, ...handlers);
385
+ }
386
+ patch(path, ...handlers) {
387
+ return this.on("PATCH", path, ...handlers);
388
+ }
389
+ delete(path, ...handlers) {
390
+ return this.on("DELETE", path, ...handlers);
391
+ }
392
+ onError(handler) {
393
+ this.errorHandler = handler;
394
+ return this;
395
+ }
396
+ notFound(handler) {
397
+ this.notFoundHandler = handler;
398
+ return this;
399
+ }
400
+ async request(input, init) {
401
+ if (input instanceof Request) return this.fetch(input);
402
+ const url = input.startsWith("/") ? `http://localhost${input}` : input;
403
+ return this.fetch(new Request(url, init));
404
+ }
405
+ fetch = async (request) => {
406
+ const url = new URL(request.url);
407
+ const path = url.pathname;
408
+ const method = request.method.toUpperCase();
409
+ const matched = this.match(method, path);
410
+ const context = new Context(request, matched.params, this.notFoundHandler);
411
+ try {
412
+ const response = await this.dispatch(context, matched.handlers);
413
+ return context.finalize(response ?? await this.notFoundHandler(context));
414
+ } catch (err) {
415
+ return context.finalize(await this.errorHandler(err, context));
416
+ }
417
+ };
418
+ match(method, path) {
419
+ const handlers = [];
420
+ const params = {};
421
+ for (const route2 of this.middleware) {
422
+ const match = matchPath(route2.compiled, path);
423
+ if (!match) continue;
424
+ Object.assign(params, match);
425
+ for (const handler of route2.handlers) {
426
+ handlers.push({ handler, params: match });
427
+ }
428
+ }
429
+ 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);
430
+ if (route) {
431
+ const match = matchPath(route.compiled, path) ?? {};
432
+ Object.assign(params, match);
433
+ for (const handler of route.handlers) {
434
+ handlers.push({ handler, params: match });
435
+ }
436
+ }
437
+ return { handlers, params };
438
+ }
439
+ async dispatch(context, handlers) {
440
+ let index = -1;
441
+ const run = async (nextIndex) => {
442
+ if (nextIndex <= index) throw new Error("next() called multiple times");
443
+ index = nextIndex;
444
+ const matched = handlers[nextIndex];
445
+ if (!matched) return void 0;
446
+ const originalParams = context.req.param();
447
+ Object.assign(originalParams, matched.params);
448
+ let nextResponse = void 0;
449
+ let nextCalled = false;
450
+ const next = async () => {
451
+ nextCalled = true;
452
+ nextResponse = await run(nextIndex + 1);
453
+ };
454
+ const response = await matched.handler(context, next);
455
+ if (response instanceof Response) return response;
456
+ if (nextCalled) return nextResponse;
457
+ return response;
458
+ };
459
+ return run(0);
460
+ }
461
+ };
462
+ function cors(options = {}) {
463
+ const origin = options.origin ?? "*";
464
+ const allowMethods = options.allowMethods ?? ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH", "OPTIONS"];
465
+ return async (c, next) => {
466
+ c.header("Access-Control-Allow-Origin", origin);
467
+ if (options.credentials) c.header("Access-Control-Allow-Credentials", "true");
468
+ if (c.req.method.toUpperCase() === "OPTIONS") {
469
+ c.header("Access-Control-Allow-Methods", allowMethods.join(","));
470
+ const allowHeaders = options.allowHeaders?.join(",") ?? c.req.header("Access-Control-Request-Headers");
471
+ if (allowHeaders) c.header("Access-Control-Allow-Headers", allowHeaders);
472
+ if (options.maxAge != null) c.header("Access-Control-Max-Age", String(options.maxAge));
473
+ return c.body(null, 204);
474
+ }
475
+ await next();
476
+ };
477
+ }
478
+ function serve(options) {
479
+ const port = options.port ?? 3e3;
480
+ const server = createNodeServer(async (req, res) => {
481
+ try {
482
+ const request = nodeRequestToFetchRequest(req);
483
+ const response = await options.fetch(request);
484
+ await writeFetchResponse(res, response, req.method?.toUpperCase() === "HEAD");
485
+ } catch (err) {
486
+ const message = err instanceof Error ? err.message : "Internal Server Error";
487
+ res.statusCode = 500;
488
+ res.setHeader("Content-Type", "text/plain; charset=UTF-8");
489
+ res.end(message);
490
+ }
491
+ });
492
+ server.listen(port, options.hostname);
493
+ return server;
494
+ }
495
+ function compilePath(pattern) {
496
+ if (pattern === "*" || pattern === "/*") {
497
+ return { pattern, regex: /^.*$/, paramNames: [] };
498
+ }
499
+ const paramNames = [];
500
+ let source = "^";
501
+ for (let i = 0; i < pattern.length; i++) {
502
+ const char = pattern[i];
503
+ if (char !== ":") {
504
+ source += escapeRegex(char);
505
+ continue;
506
+ }
507
+ let name = "";
508
+ i++;
509
+ while (i < pattern.length && /[A-Za-z0-9_]/.test(pattern[i])) {
510
+ name += pattern[i];
511
+ i++;
512
+ }
513
+ i--;
514
+ paramNames.push(name);
515
+ if (pattern[i + 1] === "{") {
516
+ const close = pattern.indexOf("}", i + 2);
517
+ if (close < 0) throw new Error(`Invalid route pattern: ${pattern}`);
518
+ const expr = pattern.slice(i + 2, close);
519
+ source += `(${expr})`;
520
+ i = close;
521
+ } else {
522
+ source += "([^/]+)";
523
+ }
524
+ }
525
+ source += "$";
526
+ return { pattern, regex: new RegExp(source), paramNames };
527
+ }
528
+ function matchPath(compiled, path) {
529
+ const match = compiled.regex.exec(path);
530
+ if (!match) return null;
531
+ const params = {};
532
+ for (let i = 0; i < compiled.paramNames.length; i++) {
533
+ params[compiled.paramNames[i]] = decodePathParam(match[i + 1] ?? "");
534
+ }
535
+ return params;
536
+ }
537
+ function decodePathParam(value) {
538
+ try {
539
+ return decodeURIComponent(value);
540
+ } catch {
541
+ return value;
542
+ }
543
+ }
544
+ function escapeRegex(value) {
545
+ return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
546
+ }
547
+ function hasHeaders(headers) {
548
+ for (const _ of headers) return true;
549
+ return false;
550
+ }
551
+ function defaultContentType(headers, contentType) {
552
+ const out = new Headers(headers);
553
+ if (!out.has("Content-Type")) {
554
+ out.set("Content-Type", contentType);
555
+ }
556
+ return out;
557
+ }
558
+ function formDataToObject(formData) {
559
+ const out = {};
560
+ for (const [key, value] of formData) {
561
+ appendBodyValue(out, key, value);
562
+ }
563
+ return out;
564
+ }
565
+ function appendBodyValue(target, key, value) {
566
+ const existing = target[key];
567
+ if (existing === void 0) {
568
+ target[key] = value;
569
+ } else if (Array.isArray(existing)) {
570
+ existing.push(value);
571
+ } else {
572
+ target[key] = [existing, value];
573
+ }
574
+ }
575
+ function nodeRequestToFetchRequest(req) {
576
+ const host = req.headers.host ?? "localhost";
577
+ const url = new URL(req.url ?? "/", `http://${host}`);
578
+ const headers = new Headers();
579
+ for (const [key, value] of Object.entries(req.headers)) {
580
+ if (value == null) continue;
581
+ if (Array.isArray(value)) {
582
+ for (const item of value) headers.append(key, item);
583
+ } else {
584
+ headers.set(key, value);
585
+ }
586
+ }
587
+ const method = req.method ?? "GET";
588
+ const hasBody = method !== "GET" && method !== "HEAD";
589
+ return new Request(url.toString(), {
590
+ method,
591
+ headers,
592
+ body: hasBody ? req : void 0,
593
+ duplex: "half"
594
+ });
595
+ }
596
+ async function writeFetchResponse(res, response, headOnly) {
597
+ res.statusCode = response.status;
598
+ res.statusMessage = response.statusText;
599
+ const headersWithCookies = response.headers;
600
+ const cookies = headersWithCookies.getSetCookie?.();
601
+ response.headers.forEach((value, key) => {
602
+ if (key.toLowerCase() === "set-cookie" && cookies && cookies.length > 0) return;
603
+ res.setHeader(key, value);
604
+ });
605
+ if (cookies && cookies.length > 0) {
606
+ res.setHeader("Set-Cookie", cookies);
607
+ }
608
+ if (headOnly || !response.body) {
609
+ res.end();
610
+ return;
611
+ }
612
+ const reader = response.body.getReader();
613
+ try {
614
+ while (true) {
615
+ const { done, value } = await reader.read();
616
+ if (done) break;
617
+ if (!res.write(value)) {
618
+ await new Promise((resolve3) => res.once("drain", resolve3));
619
+ }
620
+ }
621
+ res.end();
622
+ } catch (err) {
623
+ res.destroy(err instanceof Error ? err : void 0);
624
+ }
625
+ }
238
626
  var MAX_DELIVERIES = 1e3;
239
627
  var WebhookDispatcher = class {
240
628
  subscriptions = [];
@@ -539,7 +927,7 @@ var SERVICE_REGISTRY = {
539
927
  label: "Vercel REST API emulator",
540
928
  endpoints: "projects, deployments, domains, env vars, users, teams, file uploads, protection bypass",
541
929
  async load() {
542
- const mod = await import("./dist-4X2KPMAJ.js");
930
+ const mod = await import("./dist-CXRPM6BK.js");
543
931
  return { plugin: mod.vercelPlugin, seedFromConfig: mod.seedFromConfig };
544
932
  },
545
933
  defaultFallback(cfg) {
@@ -566,7 +954,7 @@ var SERVICE_REGISTRY = {
566
954
  label: "GitHub REST API emulator",
567
955
  endpoints: "users, repos, issues, PRs, comments, reviews, labels, milestones, branches, git data, orgs, teams, releases, webhooks, search, actions, checks, rate limit",
568
956
  async load() {
569
- const mod = await import("./dist-REDHDZ3V.js");
957
+ const mod = await import("./dist-PO4CL5SJ.js");
570
958
  return {
571
959
  plugin: mod.githubPlugin,
572
960
  seedFromConfig: mod.seedFromConfig,
@@ -633,7 +1021,7 @@ var SERVICE_REGISTRY = {
633
1021
  label: "Google OAuth 2.0 / OpenID Connect + Gmail, Calendar, and Drive emulator",
634
1022
  endpoints: "OAuth authorize, token exchange, userinfo, OIDC discovery, token revocation, Gmail messages/drafts/threads/labels/history/settings, Calendar lists/events/freebusy, Drive files/uploads",
635
1023
  async load() {
636
- const mod = await import("./dist-KKTYBE5S.js");
1024
+ const mod = await import("./dist-ZY5SZSJ2.js");
637
1025
  return { plugin: mod.googlePlugin, seedFromConfig: mod.seedFromConfig };
638
1026
  },
639
1027
  defaultFallback(cfg) {
@@ -713,18 +1101,34 @@ var SERVICE_REGISTRY = {
713
1101
  },
714
1102
  slack: {
715
1103
  label: "Slack API emulator",
716
- endpoints: "auth, chat, conversations, users, reactions, team, OAuth, incoming webhooks",
1104
+ endpoints: "auth, chat, conversations, users, profiles, presence, files, pins, bookmarks, views, reactions, team, OAuth, incoming webhooks, inspector",
717
1105
  async load() {
718
- const mod = await import("./dist-CE6BUCWQ.js");
1106
+ const mod = await import("./dist-OGSAVJ25.js");
719
1107
  return { plugin: mod.slackPlugin, seedFromConfig: mod.seedFromConfig };
720
1108
  },
721
1109
  defaultFallback() {
722
- return { login: "U000000001", id: 1, scopes: ["chat:write", "channels:read", "users:read", "reactions:write"] };
1110
+ return {
1111
+ login: "U000000001",
1112
+ id: 1,
1113
+ scopes: []
1114
+ };
723
1115
  },
724
1116
  initConfig: {
725
1117
  slack: {
726
1118
  team: { name: "My Workspace", domain: "my-workspace" },
727
- users: [{ name: "developer", real_name: "Developer", email: "dev@example.com" }],
1119
+ users: [
1120
+ {
1121
+ name: "developer",
1122
+ real_name: "Developer",
1123
+ email: "dev@example.com",
1124
+ profile: {
1125
+ title: "Local Developer",
1126
+ status_text: "Testing locally",
1127
+ status_emoji: ":computer:"
1128
+ },
1129
+ presence: "active"
1130
+ }
1131
+ ],
728
1132
  channels: [
729
1133
  { name: "general", topic: "General discussion" },
730
1134
  { name: "random", topic: "Random stuff" }
@@ -734,10 +1138,45 @@ var SERVICE_REGISTRY = {
734
1138
  {
735
1139
  client_id: "12345.67890",
736
1140
  client_secret: "example_client_secret",
1141
+ app_id: "A000000001",
737
1142
  name: "My Slack App",
738
- redirect_uris: ["http://localhost:3000/api/auth/callback/slack"]
1143
+ redirect_uris: ["http://localhost:3000/api/auth/callback/slack"],
1144
+ scopes: [
1145
+ "chat:write",
1146
+ "channels:read",
1147
+ "channels:history",
1148
+ "channels:join",
1149
+ "channels:manage",
1150
+ "channels:write",
1151
+ "groups:read",
1152
+ "groups:history",
1153
+ "groups:write",
1154
+ "im:read",
1155
+ "im:history",
1156
+ "im:write",
1157
+ "mpim:read",
1158
+ "mpim:history",
1159
+ "mpim:write",
1160
+ "users:read",
1161
+ "users:read.email",
1162
+ "users.profile:read",
1163
+ "users.profile:write",
1164
+ "users:write",
1165
+ "files:read",
1166
+ "files:write",
1167
+ "pins:read",
1168
+ "pins:write",
1169
+ "bookmarks:read",
1170
+ "bookmarks:write",
1171
+ "reactions:read",
1172
+ "reactions:write",
1173
+ "team:read"
1174
+ ],
1175
+ user_scopes: ["users:read", "users.profile:read"],
1176
+ bot_name: "my-bot"
739
1177
  }
740
- ]
1178
+ ],
1179
+ strict_scopes: false
741
1180
  }
742
1181
  }
743
1182
  },
@@ -745,7 +1184,7 @@ var SERVICE_REGISTRY = {
745
1184
  label: "Apple Sign In / OAuth emulator",
746
1185
  endpoints: "OAuth authorize, token exchange, JWKS",
747
1186
  async load() {
748
- const mod = await import("./dist-CFST4X4K.js");
1187
+ const mod = await import("./dist-WACHAAVU.js");
749
1188
  return { plugin: mod.applePlugin, seedFromConfig: mod.seedFromConfig };
750
1189
  },
751
1190
  defaultFallback(cfg) {
@@ -770,7 +1209,7 @@ var SERVICE_REGISTRY = {
770
1209
  label: "Microsoft Entra ID OAuth 2.0 / OpenID Connect emulator",
771
1210
  endpoints: "OAuth authorize, token exchange, userinfo, OIDC discovery, Graph /me, logout, token revocation",
772
1211
  async load() {
773
- const mod = await import("./dist-ETHHYBGF.js");
1212
+ const mod = await import("./dist-IFULY5LE.js");
774
1213
  return { plugin: mod.microsoftPlugin, seedFromConfig: mod.seedFromConfig };
775
1214
  },
776
1215
  defaultFallback(cfg) {
@@ -795,7 +1234,7 @@ var SERVICE_REGISTRY = {
795
1234
  label: "Okta OAuth 2.0 / OpenID Connect + management API emulator",
796
1235
  endpoints: "OIDC discovery, JWKS, OAuth authorize/token/userinfo/introspect/revoke/logout, users, groups, apps, authorization servers",
797
1236
  async load() {
798
- const mod = await import("./dist-5JVGPOL3.js");
1237
+ const mod = await import("./dist-XWWZVLQQ.js");
799
1238
  return { plugin: mod.oktaPlugin, seedFromConfig: mod.seedFromConfig };
800
1239
  },
801
1240
  defaultFallback(cfg) {
@@ -823,7 +1262,7 @@ var SERVICE_REGISTRY = {
823
1262
  label: "AWS cloud service emulator",
824
1263
  endpoints: "S3 (buckets, objects), SQS (queues, messages), IAM (users, roles, access keys), STS (assume role, caller identity)",
825
1264
  async load() {
826
- const mod = await import("./dist-LDUHEJAN.js");
1265
+ const mod = await import("./dist-DSJSF3GY.js");
827
1266
  return { plugin: mod.awsPlugin, seedFromConfig: mod.seedFromConfig };
828
1267
  },
829
1268
  defaultFallback() {
@@ -845,7 +1284,7 @@ var SERVICE_REGISTRY = {
845
1284
  label: "Resend email API emulator",
846
1285
  endpoints: "emails, domains, contacts, API keys, inbox UI",
847
1286
  async load() {
848
- const mod = await import("./dist-IBXD3O6A.js");
1287
+ const mod = await import("./dist-R3TNKUIE.js");
849
1288
  return { plugin: mod.resendPlugin, seedFromConfig: mod.seedFromConfig };
850
1289
  },
851
1290
  defaultFallback() {
@@ -862,7 +1301,7 @@ var SERVICE_REGISTRY = {
862
1301
  label: "Stripe payments emulator",
863
1302
  endpoints: "customers, payment methods, customer sessions, payment intents, charges, products, prices, checkout sessions, webhooks",
864
1303
  async load() {
865
- const mod = await import("./dist-ENKE2S7V.js");
1304
+ const mod = await import("./dist-NJJLJT2N.js");
866
1305
  return { plugin: mod.stripePlugin, seedFromConfig: mod.seedFromConfig };
867
1306
  },
868
1307
  defaultFallback() {
@@ -880,7 +1319,7 @@ var SERVICE_REGISTRY = {
880
1319
  label: "MongoDB Atlas service emulator",
881
1320
  endpoints: "Atlas Admin API v2 (projects, clusters, database users, databases, collections), Atlas Data API v1 (findOne, find, insertOne, insertMany, updateOne, updateMany, deleteOne, deleteMany, aggregate)",
882
1321
  async load() {
883
- const mod = await import("./dist-PWGOAQC6.js");
1322
+ const mod = await import("./dist-2ZZGNPJI.js");
884
1323
  return { plugin: mod.mongoatlasPlugin, seedFromConfig: mod.seedFromConfig };
885
1324
  },
886
1325
  defaultFallback() {
@@ -899,7 +1338,7 @@ var SERVICE_REGISTRY = {
899
1338
  label: "Clerk authentication and user management emulator",
900
1339
  endpoints: "OIDC discovery, JWKS, OAuth authorize/token/userinfo, users, email addresses, organizations, memberships, invitations, sessions",
901
1340
  async load() {
902
- const mod = await import("./dist-J6LHUR52.js");
1341
+ const mod = await import("./dist-IRUBHCZU.js");
903
1342
  return { plugin: mod.clerkPlugin, seedFromConfig: mod.seedFromConfig };
904
1343
  },
905
1344
  defaultFallback(cfg) {
@@ -949,7 +1388,6 @@ var DEFAULT_TOKENS = {
949
1388
  };
950
1389
 
951
1390
  // src/commands/start.ts
952
- import { serve } from "@hono/node-server";
953
1391
  import { readFileSync as readFileSync2, existsSync } from "fs";
954
1392
  import { resolve } from "path";
955
1393
  import { parse as parseYaml } from "yaml";
@@ -1053,7 +1491,7 @@ function resolveBaseUrl(opts) {
1053
1491
  }
1054
1492
 
1055
1493
  // src/commands/start.ts
1056
- var pkg = { version: "0.5.0" };
1494
+ var pkg = { version: "0.6.0" };
1057
1495
  function loadSeedConfig(seedPath) {
1058
1496
  if (seedPath) {
1059
1497
  const fullPath = resolve(seedPath);
@@ -1214,7 +1652,7 @@ function printBanner(services, tokens, configSource) {
1214
1652
  if (configSource) {
1215
1653
  lines.push(` ${pc.dim("Config:")} ${configSource}`);
1216
1654
  } else {
1217
- lines.push(` ${pc.dim("Config:")} defaults ${pc.dim("(run")} emulate init ${pc.dim("to customize)")}`);
1655
+ lines.push(` ${pc.dim("Config:")} defaults ${pc.dim("(run")} npx emulate init ${pc.dim("to customize)")}`);
1218
1656
  }
1219
1657
  lines.push("");
1220
1658
  console.log(lines.join("\n"));
@@ -1249,7 +1687,7 @@ function initCommand(options) {
1249
1687
  writeFileSync(fullPath, content, "utf-8");
1250
1688
  console.log(`Created ${filename}`);
1251
1689
  console.log(`
1252
- Run 'emulate' to start the emulator.`);
1690
+ Run 'npx emulate' to start the emulator.`);
1253
1691
  }
1254
1692
 
1255
1693
  // src/commands/list.ts
@@ -1263,7 +1701,7 @@ function listCommand() {
1263
1701
  }
1264
1702
 
1265
1703
  // src/index.ts
1266
- var pkg2 = { version: "0.5.0" };
1704
+ var pkg2 = { version: "0.6.0" };
1267
1705
  var defaultPort = process.env.EMULATE_PORT ?? process.env.PORT ?? "4000";
1268
1706
  var program = new Command();
1269
1707
  program.name("emulate").description("Local drop-in replacement services for CI and no-network sandboxes").version(pkg2.version);