@mokup/server 1.0.4 → 1.1.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/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const runtime = require('@mokup/runtime');
4
4
  const fetch = require('./shared/server.BdTl0qJd.cjs');
5
- const node_process = require('node:process');
5
+ const process = require('node:process');
6
6
  const hono = require('@mokup/shared/hono');
7
7
  const pathe = require('@mokup/shared/pathe');
8
8
  const node_fs = require('node:fs');
@@ -13,6 +13,10 @@ const esbuild = require('@mokup/shared/esbuild');
13
13
  const jsoncParser = require('@mokup/shared/jsonc-parser');
14
14
 
15
15
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
16
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
17
+
18
+ const process__default = /*#__PURE__*/_interopDefaultCompat(process);
19
+
16
20
  function createConnectMiddleware(options) {
17
21
  const runtime$1 = runtime.createRuntime(fetch.toRuntimeOptions(options));
18
22
  const onNotFound = options.onNotFound ?? "next";
@@ -89,6 +93,7 @@ const supportedExtensions = /* @__PURE__ */ new Set([
89
93
  ".mjs",
90
94
  ".cjs"
91
95
  ]);
96
+ const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
92
97
 
93
98
  function normalizePrefix(prefix) {
94
99
  if (!prefix) {
@@ -358,7 +363,7 @@ function isAncestor(parent, child) {
358
363
  }
359
364
  function resolveGroupRoot(dirs, serverRoot) {
360
365
  if (!dirs || dirs.length === 0) {
361
- return serverRoot ?? node_process.cwd();
366
+ return serverRoot ?? process.cwd();
362
367
  }
363
368
  if (serverRoot) {
364
369
  const normalizedRoot = normalizePath(serverRoot);
@@ -382,7 +387,7 @@ function resolveGroupRoot(dirs, serverRoot) {
382
387
  }
383
388
  }
384
389
  if (!common || common === "/") {
385
- return serverRoot ?? node_process.cwd();
390
+ return serverRoot ?? process.cwd();
386
391
  }
387
392
  return common;
388
393
  }
@@ -394,12 +399,23 @@ const disabledReasonSet = /* @__PURE__ */ new Set([
394
399
  "include",
395
400
  "unknown"
396
401
  ]);
402
+ const ignoredReasonSet = /* @__PURE__ */ new Set([
403
+ "unsupported",
404
+ "invalid-route",
405
+ "unknown"
406
+ ]);
397
407
  function normalizeDisabledReason(reason) {
398
408
  if (reason && disabledReasonSet.has(reason)) {
399
409
  return reason;
400
410
  }
401
411
  return "unknown";
402
412
  }
413
+ function normalizeIgnoredReason(reason) {
414
+ if (reason && ignoredReasonSet.has(reason)) {
415
+ return reason;
416
+ }
417
+ return "unknown";
418
+ }
403
419
  function formatRouteFile(file, root) {
404
420
  if (!root) {
405
421
  return toPosixPath(file);
@@ -462,14 +478,44 @@ function toPlaygroundRoute(route, root, groups) {
462
478
  }
463
479
  function toPlaygroundDisabledRoute(route, root, groups) {
464
480
  const matchedGroup = resolveRouteGroup(route.file, groups);
465
- return {
481
+ const disabled = {
466
482
  file: formatRouteFile(route.file, root),
467
- reason: normalizeDisabledReason(route.reason),
468
- method: route.method,
469
- url: route.url,
470
- groupKey: matchedGroup?.key,
471
- group: matchedGroup?.label
483
+ reason: normalizeDisabledReason(route.reason)
472
484
  };
485
+ if (typeof route.method !== "undefined") {
486
+ disabled.method = route.method;
487
+ }
488
+ if (typeof route.url !== "undefined") {
489
+ disabled.url = route.url;
490
+ }
491
+ if (matchedGroup) {
492
+ disabled.groupKey = matchedGroup.key;
493
+ disabled.group = matchedGroup.label;
494
+ }
495
+ return disabled;
496
+ }
497
+ function toPlaygroundIgnoredRoute(route, root, groups) {
498
+ const matchedGroup = resolveRouteGroup(route.file, groups);
499
+ const ignored = {
500
+ file: formatRouteFile(route.file, root),
501
+ reason: normalizeIgnoredReason(route.reason)
502
+ };
503
+ if (matchedGroup) {
504
+ ignored.groupKey = matchedGroup.key;
505
+ ignored.group = matchedGroup.label;
506
+ }
507
+ return ignored;
508
+ }
509
+ function toPlaygroundConfigFile(entry, root, groups) {
510
+ const matchedGroup = resolveRouteGroup(entry.file, groups);
511
+ const configFile = {
512
+ file: formatRouteFile(entry.file, root)
513
+ };
514
+ if (matchedGroup) {
515
+ configFile.groupKey = matchedGroup.key;
516
+ configFile.group = matchedGroup.label;
517
+ }
518
+ return configFile;
473
519
  }
474
520
  function registerPlaygroundRoutes(params) {
475
521
  if (!params.config.enabled) {
@@ -509,7 +555,12 @@ function registerPlaygroundRoutes(params) {
509
555
  count: params.routes.length,
510
556
  groups: groups.map((group) => ({ key: group.key, label: group.label })),
511
557
  routes: params.routes.map((route) => toPlaygroundRoute(route, baseRoot, groups)),
512
- disabled: (params.disabledRoutes ?? []).map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups))
558
+ disabled: (params.disabledRoutes ?? []).map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups)),
559
+ ignored: (params.ignoredRoutes ?? []).map((route) => toPlaygroundIgnoredRoute(route, baseRoot, groups)),
560
+ configs: (params.configFiles ?? []).map((entry) => toPlaygroundConfigFile(entry, baseRoot, groups)),
561
+ disabledConfigs: (params.disabledConfigFiles ?? []).map(
562
+ (entry) => toPlaygroundConfigFile(entry, baseRoot, groups)
563
+ )
513
564
  });
514
565
  });
515
566
  params.app.get(`${playgroundPath}/*`, async (c) => {
@@ -655,8 +706,78 @@ function sortRoutes(routes) {
655
706
  });
656
707
  }
657
708
 
658
- const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
659
- async function loadModule$1(file) {
709
+ let registerPromise = null;
710
+ let hasLoggedFailure = false;
711
+ async function ensureTsxRegister(logger) {
712
+ if (registerPromise) {
713
+ return registerPromise;
714
+ }
715
+ registerPromise = (async () => {
716
+ try {
717
+ const mod = await import('tsx/esm/api');
718
+ const setSourceMapsEnabled = process__default.setSourceMapsEnabled;
719
+ if (typeof setSourceMapsEnabled === "function") {
720
+ setSourceMapsEnabled(true);
721
+ }
722
+ if (typeof mod.register === "function") {
723
+ mod.register();
724
+ }
725
+ return true;
726
+ } catch (error) {
727
+ if (!hasLoggedFailure && logger) {
728
+ logger.warn(
729
+ "Failed to register tsx loader; falling back to bundled TS loader.",
730
+ error
731
+ );
732
+ hasLoggedFailure = true;
733
+ }
734
+ return false;
735
+ }
736
+ })();
737
+ return registerPromise;
738
+ }
739
+
740
+ function isUnknownFileExtensionError$1(error) {
741
+ if (!error || typeof error !== "object") {
742
+ return false;
743
+ }
744
+ const code = error.code;
745
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
746
+ return true;
747
+ }
748
+ const message = error.message;
749
+ return typeof message === "string" && message.includes("Unknown file extension");
750
+ }
751
+ async function loadTsModule$1(file, logger) {
752
+ const cacheBust = Date.now();
753
+ const fileUrl = `${node_url.pathToFileURL(file).href}?t=${cacheBust}`;
754
+ const registered = await ensureTsxRegister(logger);
755
+ if (registered) {
756
+ try {
757
+ return await import(fileUrl);
758
+ } catch (error) {
759
+ if (!isUnknownFileExtensionError$1(error)) {
760
+ throw error;
761
+ }
762
+ }
763
+ }
764
+ const result = await esbuild.build({
765
+ entryPoints: [file],
766
+ bundle: true,
767
+ format: "esm",
768
+ platform: "node",
769
+ sourcemap: "inline",
770
+ target: "es2020",
771
+ write: false
772
+ });
773
+ const output = result.outputFiles[0];
774
+ const code = output?.text ?? "";
775
+ const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
776
+ "base64"
777
+ )}`;
778
+ return import(`${dataUrl}#${cacheBust}`);
779
+ }
780
+ async function loadModule$1(file, logger) {
660
781
  const ext = configExtensions.find((extension) => file.endsWith(extension));
661
782
  if (ext === ".cjs") {
662
783
  const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
@@ -667,21 +788,7 @@ async function loadModule$1(file) {
667
788
  return import(`${node_url.pathToFileURL(file).href}?t=${Date.now()}`);
668
789
  }
669
790
  if (ext === ".ts") {
670
- const result = await esbuild.build({
671
- entryPoints: [file],
672
- bundle: true,
673
- format: "esm",
674
- platform: "node",
675
- sourcemap: "inline",
676
- target: "es2020",
677
- write: false
678
- });
679
- const output = result.outputFiles[0];
680
- const code = output?.text ?? "";
681
- const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
682
- "base64"
683
- )}`;
684
- return import(`${dataUrl}#${Date.now()}`);
791
+ return loadTsModule$1(file, logger);
685
792
  }
686
793
  return null;
687
794
  }
@@ -705,8 +812,8 @@ async function findConfigFile(dir, cache) {
705
812
  cache.set(dir, null);
706
813
  return null;
707
814
  }
708
- async function loadConfig(file) {
709
- const mod = await loadModule$1(file);
815
+ async function loadConfig(file, logger) {
816
+ const mod = await loadModule$1(file, logger);
710
817
  if (!mod) {
711
818
  return null;
712
819
  }
@@ -757,7 +864,7 @@ async function resolveDirectoryConfig(params) {
757
864
  }
758
865
  let config = configCache.get(configPath);
759
866
  if (config === void 0) {
760
- config = await loadConfig(configPath);
867
+ config = await loadConfig(configPath, logger);
761
868
  configCache.set(configPath, config);
762
869
  }
763
870
  if (!config) {
@@ -831,14 +938,65 @@ function isSupportedFile(file) {
831
938
  if (file.endsWith(".d.ts")) {
832
939
  return false;
833
940
  }
834
- if (pathe.basename(file).startsWith("index.config.")) {
941
+ if (isConfigFile(file)) {
835
942
  return false;
836
943
  }
837
944
  const ext = pathe.extname(file).toLowerCase();
838
945
  return supportedExtensions.has(ext);
839
946
  }
947
+ function isConfigFile(file) {
948
+ if (file.endsWith(".d.ts")) {
949
+ return false;
950
+ }
951
+ const base = pathe.basename(file);
952
+ if (!base.startsWith("index.config.")) {
953
+ return false;
954
+ }
955
+ const ext = pathe.extname(file).toLowerCase();
956
+ return configExtensions.includes(ext);
957
+ }
840
958
 
841
- async function loadModule(file) {
959
+ function isUnknownFileExtensionError(error) {
960
+ if (!error || typeof error !== "object") {
961
+ return false;
962
+ }
963
+ const code = error.code;
964
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
965
+ return true;
966
+ }
967
+ const message = error.message;
968
+ return typeof message === "string" && message.includes("Unknown file extension");
969
+ }
970
+ async function loadTsModule(file, logger) {
971
+ const cacheBust = Date.now();
972
+ const fileUrl = `${node_url.pathToFileURL(file).href}?t=${cacheBust}`;
973
+ const registered = await ensureTsxRegister(logger);
974
+ if (registered) {
975
+ try {
976
+ return await import(fileUrl);
977
+ } catch (error) {
978
+ if (!isUnknownFileExtensionError(error)) {
979
+ throw error;
980
+ }
981
+ }
982
+ }
983
+ const result = await esbuild.build({
984
+ entryPoints: [file],
985
+ bundle: true,
986
+ format: "esm",
987
+ platform: "node",
988
+ sourcemap: "inline",
989
+ target: "es2020",
990
+ write: false
991
+ });
992
+ const output = result.outputFiles[0];
993
+ const code = output?.text ?? "";
994
+ const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
995
+ "base64"
996
+ )}`;
997
+ return import(`${dataUrl}#${cacheBust}`);
998
+ }
999
+ async function loadModule(file, logger) {
842
1000
  const ext = pathe.extname(file).toLowerCase();
843
1001
  if (ext === ".cjs") {
844
1002
  const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
@@ -849,21 +1007,7 @@ async function loadModule(file) {
849
1007
  return import(`${node_url.pathToFileURL(file).href}?t=${Date.now()}`);
850
1008
  }
851
1009
  if (ext === ".ts") {
852
- const result = await esbuild.build({
853
- entryPoints: [file],
854
- bundle: true,
855
- format: "esm",
856
- platform: "node",
857
- sourcemap: "inline",
858
- target: "es2020",
859
- write: false
860
- });
861
- const output = result.outputFiles[0];
862
- const code = output?.text ?? "";
863
- const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
864
- "base64"
865
- )}`;
866
- return import(`${dataUrl}#${Date.now()}`);
1010
+ return loadTsModule(file, logger);
867
1011
  }
868
1012
  return null;
869
1013
  }
@@ -898,7 +1042,7 @@ async function loadRules(file, logger) {
898
1042
  }
899
1043
  ];
900
1044
  }
901
- const mod = await loadModule(file);
1045
+ const mod = await loadModule(file, logger);
902
1046
  const value = mod?.default ?? mod;
903
1047
  if (!value) {
904
1048
  return [];
@@ -945,6 +1089,14 @@ function resolveSkipRoute(params) {
945
1089
  url: resolved.template
946
1090
  };
947
1091
  }
1092
+ function buildSkipInfo(file, reason, resolved) {
1093
+ const info = { file, reason };
1094
+ if (resolved) {
1095
+ info.method = resolved.method;
1096
+ info.url = resolved.url;
1097
+ }
1098
+ return info;
1099
+ }
948
1100
  async function scanRoutes(params) {
949
1101
  const routes = [];
950
1102
  const seen = /* @__PURE__ */ new Set();
@@ -953,7 +1105,22 @@ async function scanRoutes(params) {
953
1105
  const configCache = /* @__PURE__ */ new Map();
954
1106
  const fileCache = /* @__PURE__ */ new Map();
955
1107
  const shouldCollectSkip = typeof params.onSkip === "function";
1108
+ const shouldCollectIgnore = typeof params.onIgnore === "function";
1109
+ const shouldCollectConfig = typeof params.onConfig === "function";
956
1110
  for (const fileInfo of files) {
1111
+ if (isConfigFile(fileInfo.file)) {
1112
+ if (shouldCollectConfig) {
1113
+ const config2 = await resolveDirectoryConfig({
1114
+ file: fileInfo.file,
1115
+ rootDir: fileInfo.rootDir,
1116
+ logger: params.logger,
1117
+ configCache,
1118
+ fileCache
1119
+ });
1120
+ params.onConfig?.({ file: fileInfo.file, enabled: config2.enabled !== false });
1121
+ }
1122
+ continue;
1123
+ }
957
1124
  const config = await resolveDirectoryConfig({
958
1125
  file: fileInfo.file,
959
1126
  rootDir: fileInfo.rootDir,
@@ -968,12 +1135,7 @@ async function scanRoutes(params) {
968
1135
  rootDir: fileInfo.rootDir,
969
1136
  prefix: params.prefix
970
1137
  });
971
- params.onSkip?.({
972
- file: fileInfo.file,
973
- reason: "disabled-dir",
974
- method: resolved?.method,
975
- url: resolved?.url
976
- });
1138
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled-dir", resolved));
977
1139
  }
978
1140
  continue;
979
1141
  }
@@ -985,16 +1147,14 @@ async function scanRoutes(params) {
985
1147
  rootDir: fileInfo.rootDir,
986
1148
  prefix: params.prefix
987
1149
  });
988
- params.onSkip?.({
989
- file: fileInfo.file,
990
- reason: "ignore-prefix",
991
- method: resolved?.method,
992
- url: resolved?.url
993
- });
1150
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "ignore-prefix", resolved));
994
1151
  }
995
1152
  continue;
996
1153
  }
997
1154
  if (!isSupportedFile(fileInfo.file)) {
1155
+ if (shouldCollectIgnore) {
1156
+ params.onIgnore?.({ file: fileInfo.file, reason: "unsupported" });
1157
+ }
998
1158
  continue;
999
1159
  }
1000
1160
  const effectiveInclude = typeof config.include !== "undefined" ? config.include : params.include;
@@ -1007,17 +1167,15 @@ async function scanRoutes(params) {
1007
1167
  prefix: params.prefix
1008
1168
  });
1009
1169
  const reason = effectiveExclude && matchesFilter(fileInfo.file, void 0, effectiveExclude) ? "exclude" : "include";
1010
- params.onSkip?.({
1011
- file: fileInfo.file,
1012
- reason,
1013
- method: resolved?.method,
1014
- url: resolved?.url
1015
- });
1170
+ params.onSkip?.(buildSkipInfo(fileInfo.file, reason, resolved));
1016
1171
  }
1017
1172
  continue;
1018
1173
  }
1019
1174
  const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, params.logger);
1020
1175
  if (!derived) {
1176
+ if (shouldCollectIgnore) {
1177
+ params.onIgnore?.({ file: fileInfo.file, reason: "invalid-route" });
1178
+ }
1021
1179
  continue;
1022
1180
  }
1023
1181
  const rules = await loadRules(fileInfo.file, params.logger);
@@ -1033,12 +1191,7 @@ async function scanRoutes(params) {
1033
1191
  prefix: params.prefix,
1034
1192
  derived
1035
1193
  });
1036
- params.onSkip?.({
1037
- file: fileInfo.file,
1038
- reason: "disabled",
1039
- method: resolved2?.method,
1040
- url: resolved2?.url
1041
- });
1194
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled", resolved2));
1042
1195
  }
1043
1196
  continue;
1044
1197
  }
@@ -1121,7 +1274,7 @@ function resolveRoot(list) {
1121
1274
  if (deno?.cwd) {
1122
1275
  return deno.cwd();
1123
1276
  }
1124
- return node_process.cwd();
1277
+ return process.cwd();
1125
1278
  }
1126
1279
  function resolveAllDirs(list, root) {
1127
1280
  const dirs = [];
@@ -1143,6 +1296,9 @@ function buildApp(params) {
1143
1296
  app,
1144
1297
  routes: params.routes,
1145
1298
  disabledRoutes: params.disabledRoutes,
1299
+ ignoredRoutes: params.ignoredRoutes,
1300
+ configFiles: params.configFiles,
1301
+ disabledConfigFiles: params.disabledConfigFiles,
1146
1302
  dirs: params.dirs,
1147
1303
  logger: params.logger,
1148
1304
  config: params.playground,
@@ -1152,7 +1308,8 @@ function buildApp(params) {
1152
1308
  app.get(`${params.playground.path}/ws`, params.wsHandler);
1153
1309
  }
1154
1310
  if (params.routes.length > 0) {
1155
- const mockApp = createHonoApp(params.routes, { onResponse: params.onResponse });
1311
+ const mockAppOptions = params.onResponse ? { onResponse: params.onResponse } : {};
1312
+ const mockApp = createHonoApp(params.routes, mockAppOptions);
1156
1313
  app.route("/", mockApp);
1157
1314
  }
1158
1315
  return app;
@@ -1307,26 +1464,36 @@ async function createFetchServer(options = {}) {
1307
1464
  }
1308
1465
  let routes = [];
1309
1466
  let disabledRoutes = [];
1467
+ let ignoredRoutes = [];
1468
+ let configFiles = [];
1469
+ let disabledConfigFiles = [];
1310
1470
  let app = buildApp({
1311
1471
  routes,
1312
1472
  disabledRoutes,
1473
+ ignoredRoutes,
1474
+ configFiles,
1475
+ disabledConfigFiles,
1313
1476
  dirs,
1314
1477
  playground: playgroundConfig,
1315
1478
  root,
1316
1479
  logger,
1317
1480
  onResponse: handleRouteResponse,
1318
- wsHandler
1481
+ ...wsHandler ? { wsHandler } : {}
1319
1482
  });
1320
1483
  const refreshRoutes = async () => {
1321
1484
  try {
1322
1485
  const collected = [];
1323
1486
  const collectedDisabled = [];
1487
+ const collectedIgnored = [];
1488
+ const collectedConfigs = [];
1324
1489
  for (const entry of optionList) {
1325
1490
  const scanParams = {
1326
1491
  dirs: resolveDirs(entry.dir, root),
1327
1492
  prefix: entry.prefix ?? "",
1328
1493
  logger,
1329
- onSkip: (info) => collectedDisabled.push(info)
1494
+ onSkip: (info) => collectedDisabled.push(info),
1495
+ onIgnore: (info) => collectedIgnored.push(info),
1496
+ onConfig: (info) => collectedConfigs.push(info)
1330
1497
  };
1331
1498
  if (entry.include) {
1332
1499
  scanParams.include = entry.include;
@@ -1343,15 +1510,23 @@ async function createFetchServer(options = {}) {
1343
1510
  const resolvedRoutes = sortRoutes(collected);
1344
1511
  routes = resolvedRoutes;
1345
1512
  disabledRoutes = collectedDisabled;
1513
+ ignoredRoutes = collectedIgnored;
1514
+ const configMap = new Map(collectedConfigs.map((entry) => [entry.file, entry]));
1515
+ const resolvedConfigs = Array.from(configMap.values());
1516
+ configFiles = resolvedConfigs.filter((entry) => entry.enabled);
1517
+ disabledConfigFiles = resolvedConfigs.filter((entry) => !entry.enabled);
1346
1518
  app = buildApp({
1347
1519
  routes,
1348
1520
  disabledRoutes,
1521
+ ignoredRoutes,
1522
+ configFiles,
1523
+ disabledConfigFiles,
1349
1524
  dirs,
1350
1525
  playground: playgroundConfig,
1351
1526
  root,
1352
1527
  logger,
1353
1528
  onResponse: handleRouteResponse,
1354
- wsHandler
1529
+ ...wsHandler ? { wsHandler } : {}
1355
1530
  });
1356
1531
  logger.info(`Loaded ${routes.length} mock routes.`);
1357
1532
  } catch (error) {
@@ -1377,7 +1552,7 @@ async function createFetchServer(options = {}) {
1377
1552
  fetch,
1378
1553
  refresh: refreshRoutes,
1379
1554
  getRoutes: () => routes,
1380
- injectWebSocket
1555
+ ...injectWebSocket ? { injectWebSocket } : {}
1381
1556
  };
1382
1557
  if (watcher) {
1383
1558
  server.close = async () => {
package/dist/index.d.cts CHANGED
@@ -41,8 +41,10 @@ declare function createFastifyPlugin(options: ServerOptions): (instance: Fastify
41
41
  declare function createFetchHandler(options: ServerOptions): FetchHandler;
42
42
 
43
43
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
44
- type RequestHandler = (context: Context) => Response | Promise<Response> | unknown;
45
- type RouteResponse = unknown | RequestHandler;
44
+ type RouteStaticResponse = string | number | boolean | bigint | symbol | null | undefined | object;
45
+ type RouteHandlerResult = RouteStaticResponse | Response;
46
+ type RequestHandler = (context: Context) => RouteHandlerResult | Promise<RouteHandlerResult>;
47
+ type RouteResponse = RouteStaticResponse | RequestHandler;
46
48
  interface ResolvedMiddleware {
47
49
  handle: MiddlewareHandler;
48
50
  source: string;
package/dist/index.d.mts CHANGED
@@ -41,8 +41,10 @@ declare function createFastifyPlugin(options: ServerOptions): (instance: Fastify
41
41
  declare function createFetchHandler(options: ServerOptions): FetchHandler;
42
42
 
43
43
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
44
- type RequestHandler = (context: Context) => Response | Promise<Response> | unknown;
45
- type RouteResponse = unknown | RequestHandler;
44
+ type RouteStaticResponse = string | number | boolean | bigint | symbol | null | undefined | object;
45
+ type RouteHandlerResult = RouteStaticResponse | Response;
46
+ type RequestHandler = (context: Context) => RouteHandlerResult | Promise<RouteHandlerResult>;
47
+ type RouteResponse = RouteStaticResponse | RequestHandler;
46
48
  interface ResolvedMiddleware {
47
49
  handle: MiddlewareHandler;
48
50
  source: string;
package/dist/index.d.ts CHANGED
@@ -41,8 +41,10 @@ declare function createFastifyPlugin(options: ServerOptions): (instance: Fastify
41
41
  declare function createFetchHandler(options: ServerOptions): FetchHandler;
42
42
 
43
43
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
44
- type RequestHandler = (context: Context) => Response | Promise<Response> | unknown;
45
- type RouteResponse = unknown | RequestHandler;
44
+ type RouteStaticResponse = string | number | boolean | bigint | symbol | null | undefined | object;
45
+ type RouteHandlerResult = RouteStaticResponse | Response;
46
+ type RequestHandler = (context: Context) => RouteHandlerResult | Promise<RouteHandlerResult>;
47
+ type RouteResponse = RouteStaticResponse | RequestHandler;
46
48
  interface ResolvedMiddleware {
47
49
  handle: MiddlewareHandler;
48
50
  source: string;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createRuntime, compareRouteScore, parseRouteTemplate } from '@mokup/runtime';
2
2
  import { t as toRuntimeOptions, a as toRuntimeRequestFromNode, b as applyRuntimeResultToNode, d as toBinaryBody, c as createFetchHandler } from './shared/server.Dje1y79O.mjs';
3
- import { cwd } from 'node:process';
3
+ import process, { cwd } from 'node:process';
4
4
  import { Hono, PatternRouter } from '@mokup/shared/hono';
5
5
  import { resolve, isAbsolute, relative, join, normalize, extname, dirname, basename } from '@mokup/shared/pathe';
6
6
  import { promises } from 'node:fs';
@@ -86,6 +86,7 @@ const supportedExtensions = /* @__PURE__ */ new Set([
86
86
  ".mjs",
87
87
  ".cjs"
88
88
  ]);
89
+ const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
89
90
 
90
91
  function normalizePrefix(prefix) {
91
92
  if (!prefix) {
@@ -391,12 +392,23 @@ const disabledReasonSet = /* @__PURE__ */ new Set([
391
392
  "include",
392
393
  "unknown"
393
394
  ]);
395
+ const ignoredReasonSet = /* @__PURE__ */ new Set([
396
+ "unsupported",
397
+ "invalid-route",
398
+ "unknown"
399
+ ]);
394
400
  function normalizeDisabledReason(reason) {
395
401
  if (reason && disabledReasonSet.has(reason)) {
396
402
  return reason;
397
403
  }
398
404
  return "unknown";
399
405
  }
406
+ function normalizeIgnoredReason(reason) {
407
+ if (reason && ignoredReasonSet.has(reason)) {
408
+ return reason;
409
+ }
410
+ return "unknown";
411
+ }
400
412
  function formatRouteFile(file, root) {
401
413
  if (!root) {
402
414
  return toPosixPath(file);
@@ -459,14 +471,44 @@ function toPlaygroundRoute(route, root, groups) {
459
471
  }
460
472
  function toPlaygroundDisabledRoute(route, root, groups) {
461
473
  const matchedGroup = resolveRouteGroup(route.file, groups);
462
- return {
474
+ const disabled = {
463
475
  file: formatRouteFile(route.file, root),
464
- reason: normalizeDisabledReason(route.reason),
465
- method: route.method,
466
- url: route.url,
467
- groupKey: matchedGroup?.key,
468
- group: matchedGroup?.label
476
+ reason: normalizeDisabledReason(route.reason)
477
+ };
478
+ if (typeof route.method !== "undefined") {
479
+ disabled.method = route.method;
480
+ }
481
+ if (typeof route.url !== "undefined") {
482
+ disabled.url = route.url;
483
+ }
484
+ if (matchedGroup) {
485
+ disabled.groupKey = matchedGroup.key;
486
+ disabled.group = matchedGroup.label;
487
+ }
488
+ return disabled;
489
+ }
490
+ function toPlaygroundIgnoredRoute(route, root, groups) {
491
+ const matchedGroup = resolveRouteGroup(route.file, groups);
492
+ const ignored = {
493
+ file: formatRouteFile(route.file, root),
494
+ reason: normalizeIgnoredReason(route.reason)
495
+ };
496
+ if (matchedGroup) {
497
+ ignored.groupKey = matchedGroup.key;
498
+ ignored.group = matchedGroup.label;
499
+ }
500
+ return ignored;
501
+ }
502
+ function toPlaygroundConfigFile(entry, root, groups) {
503
+ const matchedGroup = resolveRouteGroup(entry.file, groups);
504
+ const configFile = {
505
+ file: formatRouteFile(entry.file, root)
469
506
  };
507
+ if (matchedGroup) {
508
+ configFile.groupKey = matchedGroup.key;
509
+ configFile.group = matchedGroup.label;
510
+ }
511
+ return configFile;
470
512
  }
471
513
  function registerPlaygroundRoutes(params) {
472
514
  if (!params.config.enabled) {
@@ -506,7 +548,12 @@ function registerPlaygroundRoutes(params) {
506
548
  count: params.routes.length,
507
549
  groups: groups.map((group) => ({ key: group.key, label: group.label })),
508
550
  routes: params.routes.map((route) => toPlaygroundRoute(route, baseRoot, groups)),
509
- disabled: (params.disabledRoutes ?? []).map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups))
551
+ disabled: (params.disabledRoutes ?? []).map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups)),
552
+ ignored: (params.ignoredRoutes ?? []).map((route) => toPlaygroundIgnoredRoute(route, baseRoot, groups)),
553
+ configs: (params.configFiles ?? []).map((entry) => toPlaygroundConfigFile(entry, baseRoot, groups)),
554
+ disabledConfigs: (params.disabledConfigFiles ?? []).map(
555
+ (entry) => toPlaygroundConfigFile(entry, baseRoot, groups)
556
+ )
510
557
  });
511
558
  });
512
559
  params.app.get(`${playgroundPath}/*`, async (c) => {
@@ -652,8 +699,78 @@ function sortRoutes(routes) {
652
699
  });
653
700
  }
654
701
 
655
- const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
656
- async function loadModule$1(file) {
702
+ let registerPromise = null;
703
+ let hasLoggedFailure = false;
704
+ async function ensureTsxRegister(logger) {
705
+ if (registerPromise) {
706
+ return registerPromise;
707
+ }
708
+ registerPromise = (async () => {
709
+ try {
710
+ const mod = await import('tsx/esm/api');
711
+ const setSourceMapsEnabled = process.setSourceMapsEnabled;
712
+ if (typeof setSourceMapsEnabled === "function") {
713
+ setSourceMapsEnabled(true);
714
+ }
715
+ if (typeof mod.register === "function") {
716
+ mod.register();
717
+ }
718
+ return true;
719
+ } catch (error) {
720
+ if (!hasLoggedFailure && logger) {
721
+ logger.warn(
722
+ "Failed to register tsx loader; falling back to bundled TS loader.",
723
+ error
724
+ );
725
+ hasLoggedFailure = true;
726
+ }
727
+ return false;
728
+ }
729
+ })();
730
+ return registerPromise;
731
+ }
732
+
733
+ function isUnknownFileExtensionError$1(error) {
734
+ if (!error || typeof error !== "object") {
735
+ return false;
736
+ }
737
+ const code = error.code;
738
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
739
+ return true;
740
+ }
741
+ const message = error.message;
742
+ return typeof message === "string" && message.includes("Unknown file extension");
743
+ }
744
+ async function loadTsModule$1(file, logger) {
745
+ const cacheBust = Date.now();
746
+ const fileUrl = `${pathToFileURL(file).href}?t=${cacheBust}`;
747
+ const registered = await ensureTsxRegister(logger);
748
+ if (registered) {
749
+ try {
750
+ return await import(fileUrl);
751
+ } catch (error) {
752
+ if (!isUnknownFileExtensionError$1(error)) {
753
+ throw error;
754
+ }
755
+ }
756
+ }
757
+ const result = await build({
758
+ entryPoints: [file],
759
+ bundle: true,
760
+ format: "esm",
761
+ platform: "node",
762
+ sourcemap: "inline",
763
+ target: "es2020",
764
+ write: false
765
+ });
766
+ const output = result.outputFiles[0];
767
+ const code = output?.text ?? "";
768
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
769
+ "base64"
770
+ )}`;
771
+ return import(`${dataUrl}#${cacheBust}`);
772
+ }
773
+ async function loadModule$1(file, logger) {
657
774
  const ext = configExtensions.find((extension) => file.endsWith(extension));
658
775
  if (ext === ".cjs") {
659
776
  const require = createRequire(import.meta.url);
@@ -664,21 +781,7 @@ async function loadModule$1(file) {
664
781
  return import(`${pathToFileURL(file).href}?t=${Date.now()}`);
665
782
  }
666
783
  if (ext === ".ts") {
667
- const result = await build({
668
- entryPoints: [file],
669
- bundle: true,
670
- format: "esm",
671
- platform: "node",
672
- sourcemap: "inline",
673
- target: "es2020",
674
- write: false
675
- });
676
- const output = result.outputFiles[0];
677
- const code = output?.text ?? "";
678
- const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
679
- "base64"
680
- )}`;
681
- return import(`${dataUrl}#${Date.now()}`);
784
+ return loadTsModule$1(file, logger);
682
785
  }
683
786
  return null;
684
787
  }
@@ -702,8 +805,8 @@ async function findConfigFile(dir, cache) {
702
805
  cache.set(dir, null);
703
806
  return null;
704
807
  }
705
- async function loadConfig(file) {
706
- const mod = await loadModule$1(file);
808
+ async function loadConfig(file, logger) {
809
+ const mod = await loadModule$1(file, logger);
707
810
  if (!mod) {
708
811
  return null;
709
812
  }
@@ -754,7 +857,7 @@ async function resolveDirectoryConfig(params) {
754
857
  }
755
858
  let config = configCache.get(configPath);
756
859
  if (config === void 0) {
757
- config = await loadConfig(configPath);
860
+ config = await loadConfig(configPath, logger);
758
861
  configCache.set(configPath, config);
759
862
  }
760
863
  if (!config) {
@@ -828,14 +931,65 @@ function isSupportedFile(file) {
828
931
  if (file.endsWith(".d.ts")) {
829
932
  return false;
830
933
  }
831
- if (basename(file).startsWith("index.config.")) {
934
+ if (isConfigFile(file)) {
832
935
  return false;
833
936
  }
834
937
  const ext = extname(file).toLowerCase();
835
938
  return supportedExtensions.has(ext);
836
939
  }
940
+ function isConfigFile(file) {
941
+ if (file.endsWith(".d.ts")) {
942
+ return false;
943
+ }
944
+ const base = basename(file);
945
+ if (!base.startsWith("index.config.")) {
946
+ return false;
947
+ }
948
+ const ext = extname(file).toLowerCase();
949
+ return configExtensions.includes(ext);
950
+ }
837
951
 
838
- async function loadModule(file) {
952
+ function isUnknownFileExtensionError(error) {
953
+ if (!error || typeof error !== "object") {
954
+ return false;
955
+ }
956
+ const code = error.code;
957
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
958
+ return true;
959
+ }
960
+ const message = error.message;
961
+ return typeof message === "string" && message.includes("Unknown file extension");
962
+ }
963
+ async function loadTsModule(file, logger) {
964
+ const cacheBust = Date.now();
965
+ const fileUrl = `${pathToFileURL(file).href}?t=${cacheBust}`;
966
+ const registered = await ensureTsxRegister(logger);
967
+ if (registered) {
968
+ try {
969
+ return await import(fileUrl);
970
+ } catch (error) {
971
+ if (!isUnknownFileExtensionError(error)) {
972
+ throw error;
973
+ }
974
+ }
975
+ }
976
+ const result = await build({
977
+ entryPoints: [file],
978
+ bundle: true,
979
+ format: "esm",
980
+ platform: "node",
981
+ sourcemap: "inline",
982
+ target: "es2020",
983
+ write: false
984
+ });
985
+ const output = result.outputFiles[0];
986
+ const code = output?.text ?? "";
987
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
988
+ "base64"
989
+ )}`;
990
+ return import(`${dataUrl}#${cacheBust}`);
991
+ }
992
+ async function loadModule(file, logger) {
839
993
  const ext = extname(file).toLowerCase();
840
994
  if (ext === ".cjs") {
841
995
  const require = createRequire(import.meta.url);
@@ -846,21 +1000,7 @@ async function loadModule(file) {
846
1000
  return import(`${pathToFileURL(file).href}?t=${Date.now()}`);
847
1001
  }
848
1002
  if (ext === ".ts") {
849
- const result = await build({
850
- entryPoints: [file],
851
- bundle: true,
852
- format: "esm",
853
- platform: "node",
854
- sourcemap: "inline",
855
- target: "es2020",
856
- write: false
857
- });
858
- const output = result.outputFiles[0];
859
- const code = output?.text ?? "";
860
- const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
861
- "base64"
862
- )}`;
863
- return import(`${dataUrl}#${Date.now()}`);
1003
+ return loadTsModule(file, logger);
864
1004
  }
865
1005
  return null;
866
1006
  }
@@ -895,7 +1035,7 @@ async function loadRules(file, logger) {
895
1035
  }
896
1036
  ];
897
1037
  }
898
- const mod = await loadModule(file);
1038
+ const mod = await loadModule(file, logger);
899
1039
  const value = mod?.default ?? mod;
900
1040
  if (!value) {
901
1041
  return [];
@@ -942,6 +1082,14 @@ function resolveSkipRoute(params) {
942
1082
  url: resolved.template
943
1083
  };
944
1084
  }
1085
+ function buildSkipInfo(file, reason, resolved) {
1086
+ const info = { file, reason };
1087
+ if (resolved) {
1088
+ info.method = resolved.method;
1089
+ info.url = resolved.url;
1090
+ }
1091
+ return info;
1092
+ }
945
1093
  async function scanRoutes(params) {
946
1094
  const routes = [];
947
1095
  const seen = /* @__PURE__ */ new Set();
@@ -950,7 +1098,22 @@ async function scanRoutes(params) {
950
1098
  const configCache = /* @__PURE__ */ new Map();
951
1099
  const fileCache = /* @__PURE__ */ new Map();
952
1100
  const shouldCollectSkip = typeof params.onSkip === "function";
1101
+ const shouldCollectIgnore = typeof params.onIgnore === "function";
1102
+ const shouldCollectConfig = typeof params.onConfig === "function";
953
1103
  for (const fileInfo of files) {
1104
+ if (isConfigFile(fileInfo.file)) {
1105
+ if (shouldCollectConfig) {
1106
+ const config2 = await resolveDirectoryConfig({
1107
+ file: fileInfo.file,
1108
+ rootDir: fileInfo.rootDir,
1109
+ logger: params.logger,
1110
+ configCache,
1111
+ fileCache
1112
+ });
1113
+ params.onConfig?.({ file: fileInfo.file, enabled: config2.enabled !== false });
1114
+ }
1115
+ continue;
1116
+ }
954
1117
  const config = await resolveDirectoryConfig({
955
1118
  file: fileInfo.file,
956
1119
  rootDir: fileInfo.rootDir,
@@ -965,12 +1128,7 @@ async function scanRoutes(params) {
965
1128
  rootDir: fileInfo.rootDir,
966
1129
  prefix: params.prefix
967
1130
  });
968
- params.onSkip?.({
969
- file: fileInfo.file,
970
- reason: "disabled-dir",
971
- method: resolved?.method,
972
- url: resolved?.url
973
- });
1131
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled-dir", resolved));
974
1132
  }
975
1133
  continue;
976
1134
  }
@@ -982,16 +1140,14 @@ async function scanRoutes(params) {
982
1140
  rootDir: fileInfo.rootDir,
983
1141
  prefix: params.prefix
984
1142
  });
985
- params.onSkip?.({
986
- file: fileInfo.file,
987
- reason: "ignore-prefix",
988
- method: resolved?.method,
989
- url: resolved?.url
990
- });
1143
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "ignore-prefix", resolved));
991
1144
  }
992
1145
  continue;
993
1146
  }
994
1147
  if (!isSupportedFile(fileInfo.file)) {
1148
+ if (shouldCollectIgnore) {
1149
+ params.onIgnore?.({ file: fileInfo.file, reason: "unsupported" });
1150
+ }
995
1151
  continue;
996
1152
  }
997
1153
  const effectiveInclude = typeof config.include !== "undefined" ? config.include : params.include;
@@ -1004,17 +1160,15 @@ async function scanRoutes(params) {
1004
1160
  prefix: params.prefix
1005
1161
  });
1006
1162
  const reason = effectiveExclude && matchesFilter(fileInfo.file, void 0, effectiveExclude) ? "exclude" : "include";
1007
- params.onSkip?.({
1008
- file: fileInfo.file,
1009
- reason,
1010
- method: resolved?.method,
1011
- url: resolved?.url
1012
- });
1163
+ params.onSkip?.(buildSkipInfo(fileInfo.file, reason, resolved));
1013
1164
  }
1014
1165
  continue;
1015
1166
  }
1016
1167
  const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, params.logger);
1017
1168
  if (!derived) {
1169
+ if (shouldCollectIgnore) {
1170
+ params.onIgnore?.({ file: fileInfo.file, reason: "invalid-route" });
1171
+ }
1018
1172
  continue;
1019
1173
  }
1020
1174
  const rules = await loadRules(fileInfo.file, params.logger);
@@ -1030,12 +1184,7 @@ async function scanRoutes(params) {
1030
1184
  prefix: params.prefix,
1031
1185
  derived
1032
1186
  });
1033
- params.onSkip?.({
1034
- file: fileInfo.file,
1035
- reason: "disabled",
1036
- method: resolved2?.method,
1037
- url: resolved2?.url
1038
- });
1187
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled", resolved2));
1039
1188
  }
1040
1189
  continue;
1041
1190
  }
@@ -1140,6 +1289,9 @@ function buildApp(params) {
1140
1289
  app,
1141
1290
  routes: params.routes,
1142
1291
  disabledRoutes: params.disabledRoutes,
1292
+ ignoredRoutes: params.ignoredRoutes,
1293
+ configFiles: params.configFiles,
1294
+ disabledConfigFiles: params.disabledConfigFiles,
1143
1295
  dirs: params.dirs,
1144
1296
  logger: params.logger,
1145
1297
  config: params.playground,
@@ -1149,7 +1301,8 @@ function buildApp(params) {
1149
1301
  app.get(`${params.playground.path}/ws`, params.wsHandler);
1150
1302
  }
1151
1303
  if (params.routes.length > 0) {
1152
- const mockApp = createHonoApp(params.routes, { onResponse: params.onResponse });
1304
+ const mockAppOptions = params.onResponse ? { onResponse: params.onResponse } : {};
1305
+ const mockApp = createHonoApp(params.routes, mockAppOptions);
1153
1306
  app.route("/", mockApp);
1154
1307
  }
1155
1308
  return app;
@@ -1304,26 +1457,36 @@ async function createFetchServer(options = {}) {
1304
1457
  }
1305
1458
  let routes = [];
1306
1459
  let disabledRoutes = [];
1460
+ let ignoredRoutes = [];
1461
+ let configFiles = [];
1462
+ let disabledConfigFiles = [];
1307
1463
  let app = buildApp({
1308
1464
  routes,
1309
1465
  disabledRoutes,
1466
+ ignoredRoutes,
1467
+ configFiles,
1468
+ disabledConfigFiles,
1310
1469
  dirs,
1311
1470
  playground: playgroundConfig,
1312
1471
  root,
1313
1472
  logger,
1314
1473
  onResponse: handleRouteResponse,
1315
- wsHandler
1474
+ ...wsHandler ? { wsHandler } : {}
1316
1475
  });
1317
1476
  const refreshRoutes = async () => {
1318
1477
  try {
1319
1478
  const collected = [];
1320
1479
  const collectedDisabled = [];
1480
+ const collectedIgnored = [];
1481
+ const collectedConfigs = [];
1321
1482
  for (const entry of optionList) {
1322
1483
  const scanParams = {
1323
1484
  dirs: resolveDirs(entry.dir, root),
1324
1485
  prefix: entry.prefix ?? "",
1325
1486
  logger,
1326
- onSkip: (info) => collectedDisabled.push(info)
1487
+ onSkip: (info) => collectedDisabled.push(info),
1488
+ onIgnore: (info) => collectedIgnored.push(info),
1489
+ onConfig: (info) => collectedConfigs.push(info)
1327
1490
  };
1328
1491
  if (entry.include) {
1329
1492
  scanParams.include = entry.include;
@@ -1340,15 +1503,23 @@ async function createFetchServer(options = {}) {
1340
1503
  const resolvedRoutes = sortRoutes(collected);
1341
1504
  routes = resolvedRoutes;
1342
1505
  disabledRoutes = collectedDisabled;
1506
+ ignoredRoutes = collectedIgnored;
1507
+ const configMap = new Map(collectedConfigs.map((entry) => [entry.file, entry]));
1508
+ const resolvedConfigs = Array.from(configMap.values());
1509
+ configFiles = resolvedConfigs.filter((entry) => entry.enabled);
1510
+ disabledConfigFiles = resolvedConfigs.filter((entry) => !entry.enabled);
1343
1511
  app = buildApp({
1344
1512
  routes,
1345
1513
  disabledRoutes,
1514
+ ignoredRoutes,
1515
+ configFiles,
1516
+ disabledConfigFiles,
1346
1517
  dirs,
1347
1518
  playground: playgroundConfig,
1348
1519
  root,
1349
1520
  logger,
1350
1521
  onResponse: handleRouteResponse,
1351
- wsHandler
1522
+ ...wsHandler ? { wsHandler } : {}
1352
1523
  });
1353
1524
  logger.info(`Loaded ${routes.length} mock routes.`);
1354
1525
  } catch (error) {
@@ -1374,7 +1545,7 @@ async function createFetchServer(options = {}) {
1374
1545
  fetch,
1375
1546
  refresh: refreshRoutes,
1376
1547
  getRoutes: () => routes,
1377
- injectWebSocket
1548
+ ...injectWebSocket ? { injectWebSocket } : {}
1378
1549
  };
1379
1550
  if (watcher) {
1380
1551
  server.close = async () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mokup/server",
3
3
  "type": "module",
4
- "version": "1.0.4",
4
+ "version": "1.1.1",
5
5
  "description": "Server adapters for @mokup/runtime.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://mokup.icebreaker.top",
@@ -39,8 +39,9 @@
39
39
  "dependencies": {
40
40
  "@hono/node-server": "^1.19.9",
41
41
  "@hono/node-ws": "^1.1.1",
42
- "@mokup/playground": "0.0.8",
43
- "@mokup/runtime": "1.0.0",
42
+ "tsx": "^4.21.0",
43
+ "@mokup/playground": "0.0.10",
44
+ "@mokup/runtime": "1.0.1",
44
45
  "@mokup/shared": "1.0.0"
45
46
  },
46
47
  "devDependencies": {