mokup 1.0.2 → 1.0.4

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.d.cts CHANGED
@@ -6,6 +6,7 @@ type RequestHandler = (context: Context) => Response | Promise<Response> | unkno
6
6
  type RouteResponse = unknown | RequestHandler;
7
7
  interface RouteRule {
8
8
  handler: RouteResponse;
9
+ enabled?: boolean;
9
10
  status?: number;
10
11
  headers?: Record<string, string>;
11
12
  delay?: number;
@@ -24,6 +25,9 @@ interface RouteDirectoryConfig {
24
25
  status?: number;
25
26
  delay?: number;
26
27
  enabled?: boolean;
28
+ ignorePrefix?: string | string[];
29
+ include?: RegExp | RegExp[];
30
+ exclude?: RegExp | RegExp[];
27
31
  middleware?: MiddlewareHandler | MiddlewareHandler[];
28
32
  }
29
33
  interface VitePluginOptions {
@@ -31,6 +35,7 @@ interface VitePluginOptions {
31
35
  prefix?: string;
32
36
  include?: RegExp | RegExp[];
33
37
  exclude?: RegExp | RegExp[];
38
+ ignorePrefix?: string | string[];
34
39
  watch?: boolean;
35
40
  log?: boolean;
36
41
  mode?: RuntimeMode;
package/dist/index.d.mts CHANGED
@@ -6,6 +6,7 @@ type RequestHandler = (context: Context) => Response | Promise<Response> | unkno
6
6
  type RouteResponse = unknown | RequestHandler;
7
7
  interface RouteRule {
8
8
  handler: RouteResponse;
9
+ enabled?: boolean;
9
10
  status?: number;
10
11
  headers?: Record<string, string>;
11
12
  delay?: number;
@@ -24,6 +25,9 @@ interface RouteDirectoryConfig {
24
25
  status?: number;
25
26
  delay?: number;
26
27
  enabled?: boolean;
28
+ ignorePrefix?: string | string[];
29
+ include?: RegExp | RegExp[];
30
+ exclude?: RegExp | RegExp[];
27
31
  middleware?: MiddlewareHandler | MiddlewareHandler[];
28
32
  }
29
33
  interface VitePluginOptions {
@@ -31,6 +35,7 @@ interface VitePluginOptions {
31
35
  prefix?: string;
32
36
  include?: RegExp | RegExp[];
33
37
  exclude?: RegExp | RegExp[];
38
+ ignorePrefix?: string | string[];
34
39
  watch?: boolean;
35
40
  log?: boolean;
36
41
  mode?: RuntimeMode;
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ type RequestHandler = (context: Context) => Response | Promise<Response> | unkno
6
6
  type RouteResponse = unknown | RequestHandler;
7
7
  interface RouteRule {
8
8
  handler: RouteResponse;
9
+ enabled?: boolean;
9
10
  status?: number;
10
11
  headers?: Record<string, string>;
11
12
  delay?: number;
@@ -24,6 +25,9 @@ interface RouteDirectoryConfig {
24
25
  status?: number;
25
26
  delay?: number;
26
27
  enabled?: boolean;
28
+ ignorePrefix?: string | string[];
29
+ include?: RegExp | RegExp[];
30
+ exclude?: RegExp | RegExp[];
27
31
  middleware?: MiddlewareHandler | MiddlewareHandler[];
28
32
  }
29
33
  interface VitePluginOptions {
@@ -31,6 +35,7 @@ interface VitePluginOptions {
31
35
  prefix?: string;
32
36
  include?: RegExp | RegExp[];
33
37
  exclude?: RegExp | RegExp[];
38
+ ignorePrefix?: string | string[];
34
39
  watch?: boolean;
35
40
  log?: boolean;
36
41
  mode?: RuntimeMode;
@@ -114,6 +114,20 @@ function matchesFilter(file, include, exclude) {
114
114
  }
115
115
  return true;
116
116
  }
117
+ function normalizeIgnorePrefix(value, fallback = ["."]) {
118
+ const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
119
+ return list.filter((entry) => typeof entry === "string" && entry.length > 0);
120
+ }
121
+ function hasIgnoredPrefix(file, rootDir, prefixes) {
122
+ if (prefixes.length === 0) {
123
+ return false;
124
+ }
125
+ const relativePath = toPosix(pathe.relative(rootDir, file));
126
+ const segments = relativePath.split("/");
127
+ return segments.some(
128
+ (segment) => prefixes.some((prefix) => segment.startsWith(prefix))
129
+ );
130
+ }
117
131
  function delay(ms) {
118
132
  return new Promise((resolve2) => setTimeout(resolve2, ms));
119
133
  }
@@ -336,7 +350,7 @@ function createMiddleware(getApp, logger) {
336
350
  };
337
351
  }
338
352
 
339
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.Cvbs0IQE.cjs', document.baseURI).href)));
353
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.C7VW7pSP.cjs', document.baseURI).href)));
340
354
  const mimeTypes = {
341
355
  ".html": "text/html; charset=utf-8",
342
356
  ".css": "text/css; charset=utf-8",
@@ -494,6 +508,20 @@ function resolveGroupRoot(dirs, serverRoot) {
494
508
  }
495
509
  return common;
496
510
  }
511
+ const disabledReasonSet = /* @__PURE__ */ new Set([
512
+ "disabled",
513
+ "disabled-dir",
514
+ "exclude",
515
+ "ignore-prefix",
516
+ "include",
517
+ "unknown"
518
+ ]);
519
+ function normalizeDisabledReason(reason) {
520
+ if (reason && disabledReasonSet.has(reason)) {
521
+ return reason;
522
+ }
523
+ return "unknown";
524
+ }
497
525
  function formatRouteFile(file, root) {
498
526
  if (!root) {
499
527
  return toPosixPath(file);
@@ -554,6 +582,17 @@ function toPlaygroundRoute(route, root, groups) {
554
582
  group: matchedGroup?.label
555
583
  };
556
584
  }
585
+ function toPlaygroundDisabledRoute(route, root, groups) {
586
+ const matchedGroup = resolveRouteGroup(route.file, groups);
587
+ return {
588
+ file: formatRouteFile(route.file, root),
589
+ reason: normalizeDisabledReason(route.reason),
590
+ method: route.method,
591
+ url: route.url,
592
+ groupKey: matchedGroup?.key,
593
+ group: matchedGroup?.label
594
+ };
595
+ }
557
596
  function createPlaygroundMiddleware(params) {
558
597
  const distDir = resolvePlaygroundDist();
559
598
  const playgroundPath = params.config.path;
@@ -601,12 +640,14 @@ function createPlaygroundMiddleware(params) {
601
640
  const baseRoot = resolveGroupRoot(dirs, server?.config?.root);
602
641
  const groups = resolveGroups(dirs, baseRoot);
603
642
  const routes = params.getRoutes();
643
+ const disabledRoutes = params.getDisabledRoutes?.() ?? [];
604
644
  sendJson(res, {
605
645
  basePath: matchedPath,
606
646
  root: baseRoot,
607
647
  count: routes.length,
608
648
  groups: groups.map((group) => ({ key: group.key, label: group.label })),
609
- routes: routes.map((route) => toPlaygroundRoute(route, baseRoot, groups))
649
+ routes: routes.map((route) => toPlaygroundRoute(route, baseRoot, groups)),
650
+ disabled: disabledRoutes.map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups))
610
651
  });
611
652
  return;
612
653
  }
@@ -754,7 +795,7 @@ const configExtensions = [".ts", ".js", ".mjs", ".cjs"];
754
795
  async function loadModule$1(file) {
755
796
  const ext = configExtensions.find((extension) => file.endsWith(extension));
756
797
  if (ext === ".cjs") {
757
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.Cvbs0IQE.cjs', document.baseURI).href)));
798
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.C7VW7pSP.cjs', document.baseURI).href)));
758
799
  delete require$1.cache[file];
759
800
  return require$1(file);
760
801
  }
@@ -882,6 +923,15 @@ async function resolveDirectoryConfig(params) {
882
923
  if (typeof config.enabled === "boolean") {
883
924
  merged.enabled = config.enabled;
884
925
  }
926
+ if (typeof config.ignorePrefix !== "undefined") {
927
+ merged.ignorePrefix = config.ignorePrefix;
928
+ }
929
+ if (typeof config.include !== "undefined") {
930
+ merged.include = config.include;
931
+ }
932
+ if (typeof config.exclude !== "undefined") {
933
+ merged.exclude = config.exclude;
934
+ }
885
935
  const normalized = normalizeMiddlewares(config.middleware, configPath, logger);
886
936
  if (normalized.length > 0) {
887
937
  merged.middlewares.push(...normalized);
@@ -938,7 +988,7 @@ function isSupportedFile(file) {
938
988
  async function loadModule(file) {
939
989
  const ext = pathe.extname(file).toLowerCase();
940
990
  if (ext === ".cjs") {
941
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.Cvbs0IQE.cjs', document.baseURI).href)));
991
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.C7VW7pSP.cjs', document.baseURI).href)));
942
992
  delete require$1.cache[file];
943
993
  return require$1(file);
944
994
  }
@@ -1024,19 +1074,44 @@ async function loadRules(file, server, logger) {
1024
1074
  return [value];
1025
1075
  }
1026
1076
 
1077
+ const silentLogger = {
1078
+ info: () => {
1079
+ },
1080
+ warn: () => {
1081
+ },
1082
+ error: () => {
1083
+ }
1084
+ };
1085
+ function resolveSkipRoute(params) {
1086
+ const derived = params.derived ?? deriveRouteFromFile(params.file, params.rootDir, silentLogger);
1087
+ if (!derived?.method) {
1088
+ return null;
1089
+ }
1090
+ const resolved = resolveRule({
1091
+ rule: { handler: null },
1092
+ derivedTemplate: derived.template,
1093
+ derivedMethod: derived.method,
1094
+ prefix: params.prefix,
1095
+ file: params.file,
1096
+ logger: silentLogger
1097
+ });
1098
+ if (!resolved) {
1099
+ return null;
1100
+ }
1101
+ return {
1102
+ method: resolved.method,
1103
+ url: resolved.template
1104
+ };
1105
+ }
1027
1106
  async function scanRoutes(params) {
1028
1107
  const routes = [];
1029
1108
  const seen = /* @__PURE__ */ new Set();
1030
1109
  const files = await collectFiles(params.dirs);
1110
+ const globalIgnorePrefix = normalizeIgnorePrefix(params.ignorePrefix);
1031
1111
  const configCache = /* @__PURE__ */ new Map();
1032
1112
  const fileCache = /* @__PURE__ */ new Map();
1113
+ const shouldCollectSkip = typeof params.onSkip === "function";
1033
1114
  for (const fileInfo of files) {
1034
- if (!isSupportedFile(fileInfo.file)) {
1035
- continue;
1036
- }
1037
- if (!matchesFilter(fileInfo.file, params.include, params.exclude)) {
1038
- continue;
1039
- }
1040
1115
  const configParams = {
1041
1116
  file: fileInfo.file,
1042
1117
  rootDir: fileInfo.rootDir,
@@ -1049,6 +1124,58 @@ async function scanRoutes(params) {
1049
1124
  }
1050
1125
  const config = await resolveDirectoryConfig(configParams);
1051
1126
  if (config.enabled === false) {
1127
+ if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
1128
+ const resolved = resolveSkipRoute({
1129
+ file: fileInfo.file,
1130
+ rootDir: fileInfo.rootDir,
1131
+ prefix: params.prefix
1132
+ });
1133
+ params.onSkip?.({
1134
+ file: fileInfo.file,
1135
+ reason: "disabled-dir",
1136
+ method: resolved?.method,
1137
+ url: resolved?.url
1138
+ });
1139
+ }
1140
+ continue;
1141
+ }
1142
+ const effectiveIgnorePrefix = typeof config.ignorePrefix !== "undefined" ? normalizeIgnorePrefix(config.ignorePrefix, []) : globalIgnorePrefix;
1143
+ if (hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix)) {
1144
+ if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
1145
+ const resolved = resolveSkipRoute({
1146
+ file: fileInfo.file,
1147
+ rootDir: fileInfo.rootDir,
1148
+ prefix: params.prefix
1149
+ });
1150
+ params.onSkip?.({
1151
+ file: fileInfo.file,
1152
+ reason: "ignore-prefix",
1153
+ method: resolved?.method,
1154
+ url: resolved?.url
1155
+ });
1156
+ }
1157
+ continue;
1158
+ }
1159
+ if (!isSupportedFile(fileInfo.file)) {
1160
+ continue;
1161
+ }
1162
+ const effectiveInclude = typeof config.include !== "undefined" ? config.include : params.include;
1163
+ const effectiveExclude = typeof config.exclude !== "undefined" ? config.exclude : params.exclude;
1164
+ if (!matchesFilter(fileInfo.file, effectiveInclude, effectiveExclude)) {
1165
+ if (shouldCollectSkip) {
1166
+ const resolved = resolveSkipRoute({
1167
+ file: fileInfo.file,
1168
+ rootDir: fileInfo.rootDir,
1169
+ prefix: params.prefix
1170
+ });
1171
+ const reason = effectiveExclude && matchesFilter(fileInfo.file, void 0, effectiveExclude) ? "exclude" : "include";
1172
+ params.onSkip?.({
1173
+ file: fileInfo.file,
1174
+ reason,
1175
+ method: resolved?.method,
1176
+ url: resolved?.url
1177
+ });
1178
+ }
1052
1179
  continue;
1053
1180
  }
1054
1181
  const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, params.logger);
@@ -1060,6 +1187,23 @@ async function scanRoutes(params) {
1060
1187
  if (!rule || typeof rule !== "object") {
1061
1188
  continue;
1062
1189
  }
1190
+ if (rule.enabled === false) {
1191
+ if (shouldCollectSkip) {
1192
+ const resolved2 = resolveSkipRoute({
1193
+ file: fileInfo.file,
1194
+ rootDir: fileInfo.rootDir,
1195
+ prefix: params.prefix,
1196
+ derived
1197
+ });
1198
+ params.onSkip?.({
1199
+ file: fileInfo.file,
1200
+ reason: "disabled",
1201
+ method: resolved2?.method,
1202
+ url: resolved2?.url
1203
+ });
1204
+ }
1205
+ continue;
1206
+ }
1063
1207
  const ruleValue = rule;
1064
1208
  const unsupportedKeys = ["response", "url", "method"].filter(
1065
1209
  (key2) => key2 in ruleValue
@@ -3,7 +3,7 @@ import { Hono, PatternRouter } from '@mokup/shared/hono';
3
3
  import { promises } from 'node:fs';
4
4
  import { createRequire } from 'node:module';
5
5
  import { cwd } from 'node:process';
6
- import { resolve, isAbsolute, join, normalize, extname, dirname, relative, basename } from '@mokup/shared/pathe';
6
+ import { resolve, isAbsolute, relative, join, normalize, extname, dirname, basename } from '@mokup/shared/pathe';
7
7
  import { pathToFileURL } from 'node:url';
8
8
  import { build } from '@mokup/shared/esbuild';
9
9
  import { parse } from '@mokup/shared/jsonc-parser';
@@ -111,6 +111,20 @@ function matchesFilter(file, include, exclude) {
111
111
  }
112
112
  return true;
113
113
  }
114
+ function normalizeIgnorePrefix(value, fallback = ["."]) {
115
+ const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
116
+ return list.filter((entry) => typeof entry === "string" && entry.length > 0);
117
+ }
118
+ function hasIgnoredPrefix(file, rootDir, prefixes) {
119
+ if (prefixes.length === 0) {
120
+ return false;
121
+ }
122
+ const relativePath = toPosix(relative(rootDir, file));
123
+ const segments = relativePath.split("/");
124
+ return segments.some(
125
+ (segment) => prefixes.some((prefix) => segment.startsWith(prefix))
126
+ );
127
+ }
114
128
  function delay(ms) {
115
129
  return new Promise((resolve2) => setTimeout(resolve2, ms));
116
130
  }
@@ -491,6 +505,20 @@ function resolveGroupRoot(dirs, serverRoot) {
491
505
  }
492
506
  return common;
493
507
  }
508
+ const disabledReasonSet = /* @__PURE__ */ new Set([
509
+ "disabled",
510
+ "disabled-dir",
511
+ "exclude",
512
+ "ignore-prefix",
513
+ "include",
514
+ "unknown"
515
+ ]);
516
+ function normalizeDisabledReason(reason) {
517
+ if (reason && disabledReasonSet.has(reason)) {
518
+ return reason;
519
+ }
520
+ return "unknown";
521
+ }
494
522
  function formatRouteFile(file, root) {
495
523
  if (!root) {
496
524
  return toPosixPath(file);
@@ -551,6 +579,17 @@ function toPlaygroundRoute(route, root, groups) {
551
579
  group: matchedGroup?.label
552
580
  };
553
581
  }
582
+ function toPlaygroundDisabledRoute(route, root, groups) {
583
+ const matchedGroup = resolveRouteGroup(route.file, groups);
584
+ return {
585
+ file: formatRouteFile(route.file, root),
586
+ reason: normalizeDisabledReason(route.reason),
587
+ method: route.method,
588
+ url: route.url,
589
+ groupKey: matchedGroup?.key,
590
+ group: matchedGroup?.label
591
+ };
592
+ }
554
593
  function createPlaygroundMiddleware(params) {
555
594
  const distDir = resolvePlaygroundDist();
556
595
  const playgroundPath = params.config.path;
@@ -598,12 +637,14 @@ function createPlaygroundMiddleware(params) {
598
637
  const baseRoot = resolveGroupRoot(dirs, server?.config?.root);
599
638
  const groups = resolveGroups(dirs, baseRoot);
600
639
  const routes = params.getRoutes();
640
+ const disabledRoutes = params.getDisabledRoutes?.() ?? [];
601
641
  sendJson(res, {
602
642
  basePath: matchedPath,
603
643
  root: baseRoot,
604
644
  count: routes.length,
605
645
  groups: groups.map((group) => ({ key: group.key, label: group.label })),
606
- routes: routes.map((route) => toPlaygroundRoute(route, baseRoot, groups))
646
+ routes: routes.map((route) => toPlaygroundRoute(route, baseRoot, groups)),
647
+ disabled: disabledRoutes.map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups))
607
648
  });
608
649
  return;
609
650
  }
@@ -879,6 +920,15 @@ async function resolveDirectoryConfig(params) {
879
920
  if (typeof config.enabled === "boolean") {
880
921
  merged.enabled = config.enabled;
881
922
  }
923
+ if (typeof config.ignorePrefix !== "undefined") {
924
+ merged.ignorePrefix = config.ignorePrefix;
925
+ }
926
+ if (typeof config.include !== "undefined") {
927
+ merged.include = config.include;
928
+ }
929
+ if (typeof config.exclude !== "undefined") {
930
+ merged.exclude = config.exclude;
931
+ }
882
932
  const normalized = normalizeMiddlewares(config.middleware, configPath, logger);
883
933
  if (normalized.length > 0) {
884
934
  merged.middlewares.push(...normalized);
@@ -1021,19 +1071,44 @@ async function loadRules(file, server, logger) {
1021
1071
  return [value];
1022
1072
  }
1023
1073
 
1074
+ const silentLogger = {
1075
+ info: () => {
1076
+ },
1077
+ warn: () => {
1078
+ },
1079
+ error: () => {
1080
+ }
1081
+ };
1082
+ function resolveSkipRoute(params) {
1083
+ const derived = params.derived ?? deriveRouteFromFile(params.file, params.rootDir, silentLogger);
1084
+ if (!derived?.method) {
1085
+ return null;
1086
+ }
1087
+ const resolved = resolveRule({
1088
+ rule: { handler: null },
1089
+ derivedTemplate: derived.template,
1090
+ derivedMethod: derived.method,
1091
+ prefix: params.prefix,
1092
+ file: params.file,
1093
+ logger: silentLogger
1094
+ });
1095
+ if (!resolved) {
1096
+ return null;
1097
+ }
1098
+ return {
1099
+ method: resolved.method,
1100
+ url: resolved.template
1101
+ };
1102
+ }
1024
1103
  async function scanRoutes(params) {
1025
1104
  const routes = [];
1026
1105
  const seen = /* @__PURE__ */ new Set();
1027
1106
  const files = await collectFiles(params.dirs);
1107
+ const globalIgnorePrefix = normalizeIgnorePrefix(params.ignorePrefix);
1028
1108
  const configCache = /* @__PURE__ */ new Map();
1029
1109
  const fileCache = /* @__PURE__ */ new Map();
1110
+ const shouldCollectSkip = typeof params.onSkip === "function";
1030
1111
  for (const fileInfo of files) {
1031
- if (!isSupportedFile(fileInfo.file)) {
1032
- continue;
1033
- }
1034
- if (!matchesFilter(fileInfo.file, params.include, params.exclude)) {
1035
- continue;
1036
- }
1037
1112
  const configParams = {
1038
1113
  file: fileInfo.file,
1039
1114
  rootDir: fileInfo.rootDir,
@@ -1046,6 +1121,58 @@ async function scanRoutes(params) {
1046
1121
  }
1047
1122
  const config = await resolveDirectoryConfig(configParams);
1048
1123
  if (config.enabled === false) {
1124
+ if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
1125
+ const resolved = resolveSkipRoute({
1126
+ file: fileInfo.file,
1127
+ rootDir: fileInfo.rootDir,
1128
+ prefix: params.prefix
1129
+ });
1130
+ params.onSkip?.({
1131
+ file: fileInfo.file,
1132
+ reason: "disabled-dir",
1133
+ method: resolved?.method,
1134
+ url: resolved?.url
1135
+ });
1136
+ }
1137
+ continue;
1138
+ }
1139
+ const effectiveIgnorePrefix = typeof config.ignorePrefix !== "undefined" ? normalizeIgnorePrefix(config.ignorePrefix, []) : globalIgnorePrefix;
1140
+ if (hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix)) {
1141
+ if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
1142
+ const resolved = resolveSkipRoute({
1143
+ file: fileInfo.file,
1144
+ rootDir: fileInfo.rootDir,
1145
+ prefix: params.prefix
1146
+ });
1147
+ params.onSkip?.({
1148
+ file: fileInfo.file,
1149
+ reason: "ignore-prefix",
1150
+ method: resolved?.method,
1151
+ url: resolved?.url
1152
+ });
1153
+ }
1154
+ continue;
1155
+ }
1156
+ if (!isSupportedFile(fileInfo.file)) {
1157
+ continue;
1158
+ }
1159
+ const effectiveInclude = typeof config.include !== "undefined" ? config.include : params.include;
1160
+ const effectiveExclude = typeof config.exclude !== "undefined" ? config.exclude : params.exclude;
1161
+ if (!matchesFilter(fileInfo.file, effectiveInclude, effectiveExclude)) {
1162
+ if (shouldCollectSkip) {
1163
+ const resolved = resolveSkipRoute({
1164
+ file: fileInfo.file,
1165
+ rootDir: fileInfo.rootDir,
1166
+ prefix: params.prefix
1167
+ });
1168
+ const reason = effectiveExclude && matchesFilter(fileInfo.file, void 0, effectiveExclude) ? "exclude" : "include";
1169
+ params.onSkip?.({
1170
+ file: fileInfo.file,
1171
+ reason,
1172
+ method: resolved?.method,
1173
+ url: resolved?.url
1174
+ });
1175
+ }
1049
1176
  continue;
1050
1177
  }
1051
1178
  const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, params.logger);
@@ -1057,6 +1184,23 @@ async function scanRoutes(params) {
1057
1184
  if (!rule || typeof rule !== "object") {
1058
1185
  continue;
1059
1186
  }
1187
+ if (rule.enabled === false) {
1188
+ if (shouldCollectSkip) {
1189
+ const resolved2 = resolveSkipRoute({
1190
+ file: fileInfo.file,
1191
+ rootDir: fileInfo.rootDir,
1192
+ prefix: params.prefix,
1193
+ derived
1194
+ });
1195
+ params.onSkip?.({
1196
+ file: fileInfo.file,
1197
+ reason: "disabled",
1198
+ method: resolved2?.method,
1199
+ url: resolved2?.url
1200
+ });
1201
+ }
1202
+ continue;
1203
+ }
1060
1204
  const ruleValue = rule;
1061
1205
  const unsupportedKeys = ["response", "url", "method"].filter(
1062
1206
  (key2) => key2 in ruleValue
package/dist/vite.cjs CHANGED
@@ -4,7 +4,7 @@ const node_fs = require('node:fs');
4
4
  const process = require('node:process');
5
5
  const node_url = require('node:url');
6
6
  const chokidar = require('@mokup/shared/chokidar');
7
- const sw = require('./shared/mokup.Cvbs0IQE.cjs');
7
+ const sw = require('./shared/mokup.C7VW7pSP.cjs');
8
8
  require('node:buffer');
9
9
  require('@mokup/shared/hono');
10
10
  require('node:module');
@@ -18,7 +18,7 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
18
18
 
19
19
  const chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
20
20
 
21
- function buildRouteSignature(routes) {
21
+ function buildRouteSignature(routes, disabledRoutes) {
22
22
  return routes.map(
23
23
  (route) => [
24
24
  route.method,
@@ -28,6 +28,15 @@ function buildRouteSignature(routes) {
28
28
  route.status ?? "",
29
29
  route.delay ?? ""
30
30
  ].join("|")
31
+ ).concat(
32
+ disabledRoutes.map(
33
+ (route) => [
34
+ route.reason,
35
+ route.file,
36
+ route.method ?? "",
37
+ route.url ?? ""
38
+ ].join("|")
39
+ )
31
40
  ).join("\n");
32
41
  }
33
42
  function isViteDevServer(server) {
@@ -114,6 +123,7 @@ function createMokupPlugin(options = {}) {
114
123
  let routes = [];
115
124
  let serverRoutes = [];
116
125
  let swRoutes = [];
126
+ let disabledRoutes = [];
117
127
  let app = null;
118
128
  let previewWatcher = null;
119
129
  let currentServer = null;
@@ -209,6 +219,7 @@ function createMokupPlugin(options = {}) {
209
219
  }
210
220
  const playgroundMiddleware = sw.createPlaygroundMiddleware({
211
221
  getRoutes: () => routes,
222
+ getDisabledRoutes: () => disabledRoutes,
212
223
  config: playgroundConfig,
213
224
  logger,
214
225
  getServer: () => currentServer,
@@ -219,12 +230,14 @@ function createMokupPlugin(options = {}) {
219
230
  const collected = [];
220
231
  const collectedServer = [];
221
232
  const collectedSw = [];
233
+ const collectedDisabled = [];
222
234
  for (const entry of optionList) {
223
235
  const dirs = sw.resolveDirs(entry.dir, root);
224
236
  const scanParams = {
225
237
  dirs,
226
238
  prefix: entry.prefix ?? "",
227
- logger
239
+ logger,
240
+ onSkip: (info) => collectedDisabled.push(info)
228
241
  };
229
242
  if (entry.include) {
230
243
  scanParams.include = entry.include;
@@ -232,6 +245,9 @@ function createMokupPlugin(options = {}) {
232
245
  if (entry.exclude) {
233
246
  scanParams.exclude = entry.exclude;
234
247
  }
248
+ if (typeof entry.ignorePrefix !== "undefined") {
249
+ scanParams.ignorePrefix = entry.ignorePrefix;
250
+ }
235
251
  if (server) {
236
252
  scanParams.server = server;
237
253
  }
@@ -249,8 +265,9 @@ function createMokupPlugin(options = {}) {
249
265
  routes = sw.sortRoutes(collected);
250
266
  serverRoutes = sw.sortRoutes(collectedServer);
251
267
  swRoutes = sw.sortRoutes(collectedSw);
268
+ disabledRoutes = collectedDisabled;
252
269
  app = serverRoutes.length > 0 ? sw.createHonoApp(serverRoutes) : null;
253
- const signature = buildRouteSignature(routes);
270
+ const signature = buildRouteSignature(routes, disabledRoutes);
254
271
  if (isViteDevServer(server) && server.ws) {
255
272
  if (lastSignature && signature !== lastSignature) {
256
273
  server.ws.send({
package/dist/vite.mjs CHANGED
@@ -2,7 +2,7 @@ import { existsSync } from 'node:fs';
2
2
  import { cwd } from 'node:process';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import chokidar from '@mokup/shared/chokidar';
5
- import { r as resolvePlaygroundOptions, a as resolveSwConfig, b as resolveSwUnregisterConfig, c as createPlaygroundMiddleware, d as buildSwScript, e as createLogger, f as createMiddleware, g as createDebouncer, i as isInDirs, h as resolveDirs, s as scanRoutes, j as sortRoutes, k as createHonoApp } from './shared/mokup.BJg257y9.mjs';
5
+ import { r as resolvePlaygroundOptions, a as resolveSwConfig, b as resolveSwUnregisterConfig, c as createPlaygroundMiddleware, d as buildSwScript, e as createLogger, f as createMiddleware, g as createDebouncer, i as isInDirs, h as resolveDirs, s as scanRoutes, j as sortRoutes, k as createHonoApp } from './shared/mokup.Da2mv7KS.mjs';
6
6
  import 'node:buffer';
7
7
  import '@mokup/shared/hono';
8
8
  import 'node:module';
@@ -11,7 +11,7 @@ import '@mokup/shared/esbuild';
11
11
  import '@mokup/shared/jsonc-parser';
12
12
  import '@mokup/runtime';
13
13
 
14
- function buildRouteSignature(routes) {
14
+ function buildRouteSignature(routes, disabledRoutes) {
15
15
  return routes.map(
16
16
  (route) => [
17
17
  route.method,
@@ -21,6 +21,15 @@ function buildRouteSignature(routes) {
21
21
  route.status ?? "",
22
22
  route.delay ?? ""
23
23
  ].join("|")
24
+ ).concat(
25
+ disabledRoutes.map(
26
+ (route) => [
27
+ route.reason,
28
+ route.file,
29
+ route.method ?? "",
30
+ route.url ?? ""
31
+ ].join("|")
32
+ )
24
33
  ).join("\n");
25
34
  }
26
35
  function isViteDevServer(server) {
@@ -107,6 +116,7 @@ function createMokupPlugin(options = {}) {
107
116
  let routes = [];
108
117
  let serverRoutes = [];
109
118
  let swRoutes = [];
119
+ let disabledRoutes = [];
110
120
  let app = null;
111
121
  let previewWatcher = null;
112
122
  let currentServer = null;
@@ -202,6 +212,7 @@ function createMokupPlugin(options = {}) {
202
212
  }
203
213
  const playgroundMiddleware = createPlaygroundMiddleware({
204
214
  getRoutes: () => routes,
215
+ getDisabledRoutes: () => disabledRoutes,
205
216
  config: playgroundConfig,
206
217
  logger,
207
218
  getServer: () => currentServer,
@@ -212,12 +223,14 @@ function createMokupPlugin(options = {}) {
212
223
  const collected = [];
213
224
  const collectedServer = [];
214
225
  const collectedSw = [];
226
+ const collectedDisabled = [];
215
227
  for (const entry of optionList) {
216
228
  const dirs = resolveDirs(entry.dir, root);
217
229
  const scanParams = {
218
230
  dirs,
219
231
  prefix: entry.prefix ?? "",
220
- logger
232
+ logger,
233
+ onSkip: (info) => collectedDisabled.push(info)
221
234
  };
222
235
  if (entry.include) {
223
236
  scanParams.include = entry.include;
@@ -225,6 +238,9 @@ function createMokupPlugin(options = {}) {
225
238
  if (entry.exclude) {
226
239
  scanParams.exclude = entry.exclude;
227
240
  }
241
+ if (typeof entry.ignorePrefix !== "undefined") {
242
+ scanParams.ignorePrefix = entry.ignorePrefix;
243
+ }
228
244
  if (server) {
229
245
  scanParams.server = server;
230
246
  }
@@ -242,8 +258,9 @@ function createMokupPlugin(options = {}) {
242
258
  routes = sortRoutes(collected);
243
259
  serverRoutes = sortRoutes(collectedServer);
244
260
  swRoutes = sortRoutes(collectedSw);
261
+ disabledRoutes = collectedDisabled;
245
262
  app = serverRoutes.length > 0 ? createHonoApp(serverRoutes) : null;
246
- const signature = buildRouteSignature(routes);
263
+ const signature = buildRouteSignature(routes, disabledRoutes);
247
264
  if (isViteDevServer(server) && server.ws) {
248
265
  if (lastSignature && signature !== lastSignature) {
249
266
  server.ws.send({
package/dist/webpack.cjs CHANGED
@@ -7,7 +7,7 @@ const process = require('node:process');
7
7
  const chokidar = require('@mokup/shared/chokidar');
8
8
  const esbuild = require('@mokup/shared/esbuild');
9
9
  const pathe = require('@mokup/shared/pathe');
10
- const sw = require('./shared/mokup.Cvbs0IQE.cjs');
10
+ const sw = require('./shared/mokup.C7VW7pSP.cjs');
11
11
  require('node:buffer');
12
12
  require('@mokup/shared/hono');
13
13
  require('node:fs');
@@ -179,6 +179,7 @@ function createMokupWebpackPlugin(options = {}) {
179
179
  let routes = [];
180
180
  let serverRoutes = [];
181
181
  let swRoutes = [];
182
+ let disabledRoutes = [];
182
183
  let app = null;
183
184
  let watcher = null;
184
185
  let watchingCompiler = null;
@@ -206,12 +207,14 @@ function createMokupWebpackPlugin(options = {}) {
206
207
  const collected = [];
207
208
  const collectedServer = [];
208
209
  const collectedSw = [];
210
+ const collectedDisabled = [];
209
211
  for (const entry of optionList) {
210
212
  const dirs = sw.resolveDirs(entry.dir, root);
211
213
  const scanParams = {
212
214
  dirs,
213
215
  prefix: entry.prefix ?? "",
214
- logger
216
+ logger,
217
+ onSkip: (info) => collectedDisabled.push(info)
215
218
  };
216
219
  if (entry.include) {
217
220
  scanParams.include = entry.include;
@@ -219,6 +222,9 @@ function createMokupWebpackPlugin(options = {}) {
219
222
  if (entry.exclude) {
220
223
  scanParams.exclude = entry.exclude;
221
224
  }
225
+ if (typeof entry.ignorePrefix !== "undefined") {
226
+ scanParams.ignorePrefix = entry.ignorePrefix;
227
+ }
222
228
  const scanned = await sw.scanRoutes(scanParams);
223
229
  collected.push(...scanned);
224
230
  if (entry.mode === "sw") {
@@ -233,6 +239,7 @@ function createMokupWebpackPlugin(options = {}) {
233
239
  routes = sw.sortRoutes(collected);
234
240
  serverRoutes = sw.sortRoutes(collectedServer);
235
241
  swRoutes = sw.sortRoutes(collectedSw);
242
+ disabledRoutes = collectedDisabled;
236
243
  app = serverRoutes.length > 0 ? sw.createHonoApp(serverRoutes) : null;
237
244
  };
238
245
  const rebuildBundles = async () => {
@@ -281,6 +288,7 @@ function createMokupWebpackPlugin(options = {}) {
281
288
  };
282
289
  const playgroundMiddleware = sw.createPlaygroundMiddleware({
283
290
  getRoutes: () => routes,
291
+ getDisabledRoutes: () => disabledRoutes,
284
292
  config: playgroundConfig,
285
293
  logger,
286
294
  getDirs: () => resolveAllDirs(),
package/dist/webpack.mjs CHANGED
@@ -3,7 +3,7 @@ import { cwd } from 'node:process';
3
3
  import chokidar from '@mokup/shared/chokidar';
4
4
  import { build } from '@mokup/shared/esbuild';
5
5
  import { isAbsolute, resolve } from '@mokup/shared/pathe';
6
- import { r as resolvePlaygroundOptions, a as resolveSwConfig, b as resolveSwUnregisterConfig, c as createPlaygroundMiddleware, e as createLogger, f as createMiddleware, i as isInDirs, g as createDebouncer, h as resolveDirs, s as scanRoutes, j as sortRoutes, k as createHonoApp, d as buildSwScript, t as toPosix } from './shared/mokup.BJg257y9.mjs';
6
+ import { r as resolvePlaygroundOptions, a as resolveSwConfig, b as resolveSwUnregisterConfig, c as createPlaygroundMiddleware, e as createLogger, f as createMiddleware, i as isInDirs, g as createDebouncer, h as resolveDirs, s as scanRoutes, j as sortRoutes, k as createHonoApp, d as buildSwScript, t as toPosix } from './shared/mokup.Da2mv7KS.mjs';
7
7
  import 'node:buffer';
8
8
  import '@mokup/shared/hono';
9
9
  import 'node:fs';
@@ -170,6 +170,7 @@ function createMokupWebpackPlugin(options = {}) {
170
170
  let routes = [];
171
171
  let serverRoutes = [];
172
172
  let swRoutes = [];
173
+ let disabledRoutes = [];
173
174
  let app = null;
174
175
  let watcher = null;
175
176
  let watchingCompiler = null;
@@ -197,12 +198,14 @@ function createMokupWebpackPlugin(options = {}) {
197
198
  const collected = [];
198
199
  const collectedServer = [];
199
200
  const collectedSw = [];
201
+ const collectedDisabled = [];
200
202
  for (const entry of optionList) {
201
203
  const dirs = resolveDirs(entry.dir, root);
202
204
  const scanParams = {
203
205
  dirs,
204
206
  prefix: entry.prefix ?? "",
205
- logger
207
+ logger,
208
+ onSkip: (info) => collectedDisabled.push(info)
206
209
  };
207
210
  if (entry.include) {
208
211
  scanParams.include = entry.include;
@@ -210,6 +213,9 @@ function createMokupWebpackPlugin(options = {}) {
210
213
  if (entry.exclude) {
211
214
  scanParams.exclude = entry.exclude;
212
215
  }
216
+ if (typeof entry.ignorePrefix !== "undefined") {
217
+ scanParams.ignorePrefix = entry.ignorePrefix;
218
+ }
213
219
  const scanned = await scanRoutes(scanParams);
214
220
  collected.push(...scanned);
215
221
  if (entry.mode === "sw") {
@@ -224,6 +230,7 @@ function createMokupWebpackPlugin(options = {}) {
224
230
  routes = sortRoutes(collected);
225
231
  serverRoutes = sortRoutes(collectedServer);
226
232
  swRoutes = sortRoutes(collectedSw);
233
+ disabledRoutes = collectedDisabled;
227
234
  app = serverRoutes.length > 0 ? createHonoApp(serverRoutes) : null;
228
235
  };
229
236
  const rebuildBundles = async () => {
@@ -272,6 +279,7 @@ function createMokupWebpackPlugin(options = {}) {
272
279
  };
273
280
  const playgroundMiddleware = createPlaygroundMiddleware({
274
281
  getRoutes: () => routes,
282
+ getDisabledRoutes: () => disabledRoutes,
275
283
  config: playgroundConfig,
276
284
  logger,
277
285
  getDirs: () => resolveAllDirs(),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mokup",
3
3
  "type": "module",
4
- "version": "1.0.2",
4
+ "version": "1.0.4",
5
5
  "description": "Mock utilities and Vite plugin for mokup.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://mokup.icebreaker.top",
@@ -81,14 +81,14 @@
81
81
  }
82
82
  },
83
83
  "dependencies": {
84
- "@mokup/cli": "1.0.0",
85
- "@mokup/playground": "0.0.6",
84
+ "@mokup/cli": "1.0.2",
85
+ "@mokup/playground": "0.0.8",
86
86
  "@mokup/runtime": "1.0.0",
87
- "@mokup/server": "1.0.2",
87
+ "@mokup/server": "1.0.4",
88
88
  "@mokup/shared": "1.0.0"
89
89
  },
90
90
  "devDependencies": {
91
- "@types/node": "^25.0.9",
91
+ "@types/node": "^25.0.10",
92
92
  "typescript": "^5.9.3",
93
93
  "unbuild": "^3.6.1",
94
94
  "vite": "^7.3.1"