@mokup/server 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +157 -74
  2. package/dist/index.mjs +150 -71
  3. package/package.json +3 -2
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";
@@ -358,7 +362,7 @@ function isAncestor(parent, child) {
358
362
  }
359
363
  function resolveGroupRoot(dirs, serverRoot) {
360
364
  if (!dirs || dirs.length === 0) {
361
- return serverRoot ?? node_process.cwd();
365
+ return serverRoot ?? process.cwd();
362
366
  }
363
367
  if (serverRoot) {
364
368
  const normalizedRoot = normalizePath(serverRoot);
@@ -382,7 +386,7 @@ function resolveGroupRoot(dirs, serverRoot) {
382
386
  }
383
387
  }
384
388
  if (!common || common === "/") {
385
- return serverRoot ?? node_process.cwd();
389
+ return serverRoot ?? process.cwd();
386
390
  }
387
391
  return common;
388
392
  }
@@ -462,14 +466,21 @@ function toPlaygroundRoute(route, root, groups) {
462
466
  }
463
467
  function toPlaygroundDisabledRoute(route, root, groups) {
464
468
  const matchedGroup = resolveRouteGroup(route.file, groups);
465
- return {
469
+ const disabled = {
466
470
  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
471
+ reason: normalizeDisabledReason(route.reason)
472
472
  };
473
+ if (typeof route.method !== "undefined") {
474
+ disabled.method = route.method;
475
+ }
476
+ if (typeof route.url !== "undefined") {
477
+ disabled.url = route.url;
478
+ }
479
+ if (matchedGroup) {
480
+ disabled.groupKey = matchedGroup.key;
481
+ disabled.group = matchedGroup.label;
482
+ }
483
+ return disabled;
473
484
  }
474
485
  function registerPlaygroundRoutes(params) {
475
486
  if (!params.config.enabled) {
@@ -655,8 +666,79 @@ function sortRoutes(routes) {
655
666
  });
656
667
  }
657
668
 
669
+ let registerPromise = null;
670
+ let hasLoggedFailure = false;
671
+ async function ensureTsxRegister(logger) {
672
+ if (registerPromise) {
673
+ return registerPromise;
674
+ }
675
+ registerPromise = (async () => {
676
+ try {
677
+ const mod = await import('tsx/esm/api');
678
+ const setSourceMapsEnabled = process__default.setSourceMapsEnabled;
679
+ if (typeof setSourceMapsEnabled === "function") {
680
+ setSourceMapsEnabled(true);
681
+ }
682
+ if (typeof mod.register === "function") {
683
+ mod.register();
684
+ }
685
+ return true;
686
+ } catch (error) {
687
+ if (!hasLoggedFailure && logger) {
688
+ logger.warn(
689
+ "Failed to register tsx loader; falling back to bundled TS loader.",
690
+ error
691
+ );
692
+ hasLoggedFailure = true;
693
+ }
694
+ return false;
695
+ }
696
+ })();
697
+ return registerPromise;
698
+ }
699
+
658
700
  const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
659
- async function loadModule$1(file) {
701
+ function isUnknownFileExtensionError$1(error) {
702
+ if (!error || typeof error !== "object") {
703
+ return false;
704
+ }
705
+ const code = error.code;
706
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
707
+ return true;
708
+ }
709
+ const message = error.message;
710
+ return typeof message === "string" && message.includes("Unknown file extension");
711
+ }
712
+ async function loadTsModule$1(file, logger) {
713
+ const cacheBust = Date.now();
714
+ const fileUrl = `${node_url.pathToFileURL(file).href}?t=${cacheBust}`;
715
+ const registered = await ensureTsxRegister(logger);
716
+ if (registered) {
717
+ try {
718
+ return await import(fileUrl);
719
+ } catch (error) {
720
+ if (!isUnknownFileExtensionError$1(error)) {
721
+ throw error;
722
+ }
723
+ }
724
+ }
725
+ const result = await esbuild.build({
726
+ entryPoints: [file],
727
+ bundle: true,
728
+ format: "esm",
729
+ platform: "node",
730
+ sourcemap: "inline",
731
+ target: "es2020",
732
+ write: false
733
+ });
734
+ const output = result.outputFiles[0];
735
+ const code = output?.text ?? "";
736
+ const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
737
+ "base64"
738
+ )}`;
739
+ return import(`${dataUrl}#${cacheBust}`);
740
+ }
741
+ async function loadModule$1(file, logger) {
660
742
  const ext = configExtensions.find((extension) => file.endsWith(extension));
661
743
  if (ext === ".cjs") {
662
744
  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 +749,7 @@ async function loadModule$1(file) {
667
749
  return import(`${node_url.pathToFileURL(file).href}?t=${Date.now()}`);
668
750
  }
669
751
  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()}`);
752
+ return loadTsModule$1(file, logger);
685
753
  }
686
754
  return null;
687
755
  }
@@ -705,8 +773,8 @@ async function findConfigFile(dir, cache) {
705
773
  cache.set(dir, null);
706
774
  return null;
707
775
  }
708
- async function loadConfig(file) {
709
- const mod = await loadModule$1(file);
776
+ async function loadConfig(file, logger) {
777
+ const mod = await loadModule$1(file, logger);
710
778
  if (!mod) {
711
779
  return null;
712
780
  }
@@ -757,7 +825,7 @@ async function resolveDirectoryConfig(params) {
757
825
  }
758
826
  let config = configCache.get(configPath);
759
827
  if (config === void 0) {
760
- config = await loadConfig(configPath);
828
+ config = await loadConfig(configPath, logger);
761
829
  configCache.set(configPath, config);
762
830
  }
763
831
  if (!config) {
@@ -838,7 +906,47 @@ function isSupportedFile(file) {
838
906
  return supportedExtensions.has(ext);
839
907
  }
840
908
 
841
- async function loadModule(file) {
909
+ function isUnknownFileExtensionError(error) {
910
+ if (!error || typeof error !== "object") {
911
+ return false;
912
+ }
913
+ const code = error.code;
914
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
915
+ return true;
916
+ }
917
+ const message = error.message;
918
+ return typeof message === "string" && message.includes("Unknown file extension");
919
+ }
920
+ async function loadTsModule(file, logger) {
921
+ const cacheBust = Date.now();
922
+ const fileUrl = `${node_url.pathToFileURL(file).href}?t=${cacheBust}`;
923
+ const registered = await ensureTsxRegister(logger);
924
+ if (registered) {
925
+ try {
926
+ return await import(fileUrl);
927
+ } catch (error) {
928
+ if (!isUnknownFileExtensionError(error)) {
929
+ throw error;
930
+ }
931
+ }
932
+ }
933
+ const result = await esbuild.build({
934
+ entryPoints: [file],
935
+ bundle: true,
936
+ format: "esm",
937
+ platform: "node",
938
+ sourcemap: "inline",
939
+ target: "es2020",
940
+ write: false
941
+ });
942
+ const output = result.outputFiles[0];
943
+ const code = output?.text ?? "";
944
+ const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
945
+ "base64"
946
+ )}`;
947
+ return import(`${dataUrl}#${cacheBust}`);
948
+ }
949
+ async function loadModule(file, logger) {
842
950
  const ext = pathe.extname(file).toLowerCase();
843
951
  if (ext === ".cjs") {
844
952
  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 +957,7 @@ async function loadModule(file) {
849
957
  return import(`${node_url.pathToFileURL(file).href}?t=${Date.now()}`);
850
958
  }
851
959
  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()}`);
960
+ return loadTsModule(file, logger);
867
961
  }
868
962
  return null;
869
963
  }
@@ -898,7 +992,7 @@ async function loadRules(file, logger) {
898
992
  }
899
993
  ];
900
994
  }
901
- const mod = await loadModule(file);
995
+ const mod = await loadModule(file, logger);
902
996
  const value = mod?.default ?? mod;
903
997
  if (!value) {
904
998
  return [];
@@ -945,6 +1039,14 @@ function resolveSkipRoute(params) {
945
1039
  url: resolved.template
946
1040
  };
947
1041
  }
1042
+ function buildSkipInfo(file, reason, resolved) {
1043
+ const info = { file, reason };
1044
+ if (resolved) {
1045
+ info.method = resolved.method;
1046
+ info.url = resolved.url;
1047
+ }
1048
+ return info;
1049
+ }
948
1050
  async function scanRoutes(params) {
949
1051
  const routes = [];
950
1052
  const seen = /* @__PURE__ */ new Set();
@@ -968,12 +1070,7 @@ async function scanRoutes(params) {
968
1070
  rootDir: fileInfo.rootDir,
969
1071
  prefix: params.prefix
970
1072
  });
971
- params.onSkip?.({
972
- file: fileInfo.file,
973
- reason: "disabled-dir",
974
- method: resolved?.method,
975
- url: resolved?.url
976
- });
1073
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled-dir", resolved));
977
1074
  }
978
1075
  continue;
979
1076
  }
@@ -985,12 +1082,7 @@ async function scanRoutes(params) {
985
1082
  rootDir: fileInfo.rootDir,
986
1083
  prefix: params.prefix
987
1084
  });
988
- params.onSkip?.({
989
- file: fileInfo.file,
990
- reason: "ignore-prefix",
991
- method: resolved?.method,
992
- url: resolved?.url
993
- });
1085
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "ignore-prefix", resolved));
994
1086
  }
995
1087
  continue;
996
1088
  }
@@ -1007,12 +1099,7 @@ async function scanRoutes(params) {
1007
1099
  prefix: params.prefix
1008
1100
  });
1009
1101
  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
- });
1102
+ params.onSkip?.(buildSkipInfo(fileInfo.file, reason, resolved));
1016
1103
  }
1017
1104
  continue;
1018
1105
  }
@@ -1033,12 +1120,7 @@ async function scanRoutes(params) {
1033
1120
  prefix: params.prefix,
1034
1121
  derived
1035
1122
  });
1036
- params.onSkip?.({
1037
- file: fileInfo.file,
1038
- reason: "disabled",
1039
- method: resolved2?.method,
1040
- url: resolved2?.url
1041
- });
1123
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled", resolved2));
1042
1124
  }
1043
1125
  continue;
1044
1126
  }
@@ -1121,7 +1203,7 @@ function resolveRoot(list) {
1121
1203
  if (deno?.cwd) {
1122
1204
  return deno.cwd();
1123
1205
  }
1124
- return node_process.cwd();
1206
+ return process.cwd();
1125
1207
  }
1126
1208
  function resolveAllDirs(list, root) {
1127
1209
  const dirs = [];
@@ -1152,7 +1234,8 @@ function buildApp(params) {
1152
1234
  app.get(`${params.playground.path}/ws`, params.wsHandler);
1153
1235
  }
1154
1236
  if (params.routes.length > 0) {
1155
- const mockApp = createHonoApp(params.routes, { onResponse: params.onResponse });
1237
+ const mockAppOptions = params.onResponse ? { onResponse: params.onResponse } : {};
1238
+ const mockApp = createHonoApp(params.routes, mockAppOptions);
1156
1239
  app.route("/", mockApp);
1157
1240
  }
1158
1241
  return app;
@@ -1315,7 +1398,7 @@ async function createFetchServer(options = {}) {
1315
1398
  root,
1316
1399
  logger,
1317
1400
  onResponse: handleRouteResponse,
1318
- wsHandler
1401
+ ...wsHandler ? { wsHandler } : {}
1319
1402
  });
1320
1403
  const refreshRoutes = async () => {
1321
1404
  try {
@@ -1351,7 +1434,7 @@ async function createFetchServer(options = {}) {
1351
1434
  root,
1352
1435
  logger,
1353
1436
  onResponse: handleRouteResponse,
1354
- wsHandler
1437
+ ...wsHandler ? { wsHandler } : {}
1355
1438
  });
1356
1439
  logger.info(`Loaded ${routes.length} mock routes.`);
1357
1440
  } catch (error) {
@@ -1377,7 +1460,7 @@ async function createFetchServer(options = {}) {
1377
1460
  fetch,
1378
1461
  refresh: refreshRoutes,
1379
1462
  getRoutes: () => routes,
1380
- injectWebSocket
1463
+ ...injectWebSocket ? { injectWebSocket } : {}
1381
1464
  };
1382
1465
  if (watcher) {
1383
1466
  server.close = async () => {
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';
@@ -459,14 +459,21 @@ function toPlaygroundRoute(route, root, groups) {
459
459
  }
460
460
  function toPlaygroundDisabledRoute(route, root, groups) {
461
461
  const matchedGroup = resolveRouteGroup(route.file, groups);
462
- return {
462
+ const disabled = {
463
463
  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
464
+ reason: normalizeDisabledReason(route.reason)
469
465
  };
466
+ if (typeof route.method !== "undefined") {
467
+ disabled.method = route.method;
468
+ }
469
+ if (typeof route.url !== "undefined") {
470
+ disabled.url = route.url;
471
+ }
472
+ if (matchedGroup) {
473
+ disabled.groupKey = matchedGroup.key;
474
+ disabled.group = matchedGroup.label;
475
+ }
476
+ return disabled;
470
477
  }
471
478
  function registerPlaygroundRoutes(params) {
472
479
  if (!params.config.enabled) {
@@ -652,8 +659,79 @@ function sortRoutes(routes) {
652
659
  });
653
660
  }
654
661
 
662
+ let registerPromise = null;
663
+ let hasLoggedFailure = false;
664
+ async function ensureTsxRegister(logger) {
665
+ if (registerPromise) {
666
+ return registerPromise;
667
+ }
668
+ registerPromise = (async () => {
669
+ try {
670
+ const mod = await import('tsx/esm/api');
671
+ const setSourceMapsEnabled = process.setSourceMapsEnabled;
672
+ if (typeof setSourceMapsEnabled === "function") {
673
+ setSourceMapsEnabled(true);
674
+ }
675
+ if (typeof mod.register === "function") {
676
+ mod.register();
677
+ }
678
+ return true;
679
+ } catch (error) {
680
+ if (!hasLoggedFailure && logger) {
681
+ logger.warn(
682
+ "Failed to register tsx loader; falling back to bundled TS loader.",
683
+ error
684
+ );
685
+ hasLoggedFailure = true;
686
+ }
687
+ return false;
688
+ }
689
+ })();
690
+ return registerPromise;
691
+ }
692
+
655
693
  const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
656
- async function loadModule$1(file) {
694
+ function isUnknownFileExtensionError$1(error) {
695
+ if (!error || typeof error !== "object") {
696
+ return false;
697
+ }
698
+ const code = error.code;
699
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
700
+ return true;
701
+ }
702
+ const message = error.message;
703
+ return typeof message === "string" && message.includes("Unknown file extension");
704
+ }
705
+ async function loadTsModule$1(file, logger) {
706
+ const cacheBust = Date.now();
707
+ const fileUrl = `${pathToFileURL(file).href}?t=${cacheBust}`;
708
+ const registered = await ensureTsxRegister(logger);
709
+ if (registered) {
710
+ try {
711
+ return await import(fileUrl);
712
+ } catch (error) {
713
+ if (!isUnknownFileExtensionError$1(error)) {
714
+ throw error;
715
+ }
716
+ }
717
+ }
718
+ const result = await build({
719
+ entryPoints: [file],
720
+ bundle: true,
721
+ format: "esm",
722
+ platform: "node",
723
+ sourcemap: "inline",
724
+ target: "es2020",
725
+ write: false
726
+ });
727
+ const output = result.outputFiles[0];
728
+ const code = output?.text ?? "";
729
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
730
+ "base64"
731
+ )}`;
732
+ return import(`${dataUrl}#${cacheBust}`);
733
+ }
734
+ async function loadModule$1(file, logger) {
657
735
  const ext = configExtensions.find((extension) => file.endsWith(extension));
658
736
  if (ext === ".cjs") {
659
737
  const require = createRequire(import.meta.url);
@@ -664,21 +742,7 @@ async function loadModule$1(file) {
664
742
  return import(`${pathToFileURL(file).href}?t=${Date.now()}`);
665
743
  }
666
744
  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()}`);
745
+ return loadTsModule$1(file, logger);
682
746
  }
683
747
  return null;
684
748
  }
@@ -702,8 +766,8 @@ async function findConfigFile(dir, cache) {
702
766
  cache.set(dir, null);
703
767
  return null;
704
768
  }
705
- async function loadConfig(file) {
706
- const mod = await loadModule$1(file);
769
+ async function loadConfig(file, logger) {
770
+ const mod = await loadModule$1(file, logger);
707
771
  if (!mod) {
708
772
  return null;
709
773
  }
@@ -754,7 +818,7 @@ async function resolveDirectoryConfig(params) {
754
818
  }
755
819
  let config = configCache.get(configPath);
756
820
  if (config === void 0) {
757
- config = await loadConfig(configPath);
821
+ config = await loadConfig(configPath, logger);
758
822
  configCache.set(configPath, config);
759
823
  }
760
824
  if (!config) {
@@ -835,7 +899,47 @@ function isSupportedFile(file) {
835
899
  return supportedExtensions.has(ext);
836
900
  }
837
901
 
838
- async function loadModule(file) {
902
+ function isUnknownFileExtensionError(error) {
903
+ if (!error || typeof error !== "object") {
904
+ return false;
905
+ }
906
+ const code = error.code;
907
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION") {
908
+ return true;
909
+ }
910
+ const message = error.message;
911
+ return typeof message === "string" && message.includes("Unknown file extension");
912
+ }
913
+ async function loadTsModule(file, logger) {
914
+ const cacheBust = Date.now();
915
+ const fileUrl = `${pathToFileURL(file).href}?t=${cacheBust}`;
916
+ const registered = await ensureTsxRegister(logger);
917
+ if (registered) {
918
+ try {
919
+ return await import(fileUrl);
920
+ } catch (error) {
921
+ if (!isUnknownFileExtensionError(error)) {
922
+ throw error;
923
+ }
924
+ }
925
+ }
926
+ const result = await build({
927
+ entryPoints: [file],
928
+ bundle: true,
929
+ format: "esm",
930
+ platform: "node",
931
+ sourcemap: "inline",
932
+ target: "es2020",
933
+ write: false
934
+ });
935
+ const output = result.outputFiles[0];
936
+ const code = output?.text ?? "";
937
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString(
938
+ "base64"
939
+ )}`;
940
+ return import(`${dataUrl}#${cacheBust}`);
941
+ }
942
+ async function loadModule(file, logger) {
839
943
  const ext = extname(file).toLowerCase();
840
944
  if (ext === ".cjs") {
841
945
  const require = createRequire(import.meta.url);
@@ -846,21 +950,7 @@ async function loadModule(file) {
846
950
  return import(`${pathToFileURL(file).href}?t=${Date.now()}`);
847
951
  }
848
952
  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()}`);
953
+ return loadTsModule(file, logger);
864
954
  }
865
955
  return null;
866
956
  }
@@ -895,7 +985,7 @@ async function loadRules(file, logger) {
895
985
  }
896
986
  ];
897
987
  }
898
- const mod = await loadModule(file);
988
+ const mod = await loadModule(file, logger);
899
989
  const value = mod?.default ?? mod;
900
990
  if (!value) {
901
991
  return [];
@@ -942,6 +1032,14 @@ function resolveSkipRoute(params) {
942
1032
  url: resolved.template
943
1033
  };
944
1034
  }
1035
+ function buildSkipInfo(file, reason, resolved) {
1036
+ const info = { file, reason };
1037
+ if (resolved) {
1038
+ info.method = resolved.method;
1039
+ info.url = resolved.url;
1040
+ }
1041
+ return info;
1042
+ }
945
1043
  async function scanRoutes(params) {
946
1044
  const routes = [];
947
1045
  const seen = /* @__PURE__ */ new Set();
@@ -965,12 +1063,7 @@ async function scanRoutes(params) {
965
1063
  rootDir: fileInfo.rootDir,
966
1064
  prefix: params.prefix
967
1065
  });
968
- params.onSkip?.({
969
- file: fileInfo.file,
970
- reason: "disabled-dir",
971
- method: resolved?.method,
972
- url: resolved?.url
973
- });
1066
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled-dir", resolved));
974
1067
  }
975
1068
  continue;
976
1069
  }
@@ -982,12 +1075,7 @@ async function scanRoutes(params) {
982
1075
  rootDir: fileInfo.rootDir,
983
1076
  prefix: params.prefix
984
1077
  });
985
- params.onSkip?.({
986
- file: fileInfo.file,
987
- reason: "ignore-prefix",
988
- method: resolved?.method,
989
- url: resolved?.url
990
- });
1078
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "ignore-prefix", resolved));
991
1079
  }
992
1080
  continue;
993
1081
  }
@@ -1004,12 +1092,7 @@ async function scanRoutes(params) {
1004
1092
  prefix: params.prefix
1005
1093
  });
1006
1094
  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
- });
1095
+ params.onSkip?.(buildSkipInfo(fileInfo.file, reason, resolved));
1013
1096
  }
1014
1097
  continue;
1015
1098
  }
@@ -1030,12 +1113,7 @@ async function scanRoutes(params) {
1030
1113
  prefix: params.prefix,
1031
1114
  derived
1032
1115
  });
1033
- params.onSkip?.({
1034
- file: fileInfo.file,
1035
- reason: "disabled",
1036
- method: resolved2?.method,
1037
- url: resolved2?.url
1038
- });
1116
+ params.onSkip?.(buildSkipInfo(fileInfo.file, "disabled", resolved2));
1039
1117
  }
1040
1118
  continue;
1041
1119
  }
@@ -1149,7 +1227,8 @@ function buildApp(params) {
1149
1227
  app.get(`${params.playground.path}/ws`, params.wsHandler);
1150
1228
  }
1151
1229
  if (params.routes.length > 0) {
1152
- const mockApp = createHonoApp(params.routes, { onResponse: params.onResponse });
1230
+ const mockAppOptions = params.onResponse ? { onResponse: params.onResponse } : {};
1231
+ const mockApp = createHonoApp(params.routes, mockAppOptions);
1153
1232
  app.route("/", mockApp);
1154
1233
  }
1155
1234
  return app;
@@ -1312,7 +1391,7 @@ async function createFetchServer(options = {}) {
1312
1391
  root,
1313
1392
  logger,
1314
1393
  onResponse: handleRouteResponse,
1315
- wsHandler
1394
+ ...wsHandler ? { wsHandler } : {}
1316
1395
  });
1317
1396
  const refreshRoutes = async () => {
1318
1397
  try {
@@ -1348,7 +1427,7 @@ async function createFetchServer(options = {}) {
1348
1427
  root,
1349
1428
  logger,
1350
1429
  onResponse: handleRouteResponse,
1351
- wsHandler
1430
+ ...wsHandler ? { wsHandler } : {}
1352
1431
  });
1353
1432
  logger.info(`Loaded ${routes.length} mock routes.`);
1354
1433
  } catch (error) {
@@ -1374,7 +1453,7 @@ async function createFetchServer(options = {}) {
1374
1453
  fetch,
1375
1454
  refresh: refreshRoutes,
1376
1455
  getRoutes: () => routes,
1377
- injectWebSocket
1456
+ ...injectWebSocket ? { injectWebSocket } : {}
1378
1457
  };
1379
1458
  if (watcher) {
1380
1459
  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.0",
5
5
  "description": "Server adapters for @mokup/runtime.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://mokup.icebreaker.top",
@@ -39,7 +39,8 @@
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",
42
+ "tsx": "^4.21.0",
43
+ "@mokup/playground": "0.0.9",
43
44
  "@mokup/runtime": "1.0.0",
44
45
  "@mokup/shared": "1.0.0"
45
46
  },