@mokup/server 1.1.5 → 1.1.8

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.
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike, a as NodeResponseLike } from './shared/server.D0gAciOr.cjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.cjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.cjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  type NextFunction = (error?: unknown) => void;
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike, a as NodeResponseLike } from './shared/server.D0gAciOr.mjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.mjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.mjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  type NextFunction = (error?: unknown) => void;
package/dist/connect.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike, a as NodeResponseLike } from './shared/server.D0gAciOr.js';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.js';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.js';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  type NextFunction = (error?: unknown) => void;
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike, a as NodeResponseLike } from './shared/server.D0gAciOr.cjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.cjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.cjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike, a as NodeResponseLike } from './shared/server.D0gAciOr.mjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.mjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.mjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  /**
package/dist/express.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike, a as NodeResponseLike } from './shared/server.D0gAciOr.js';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.js';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.js';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike } from './shared/server.D0gAciOr.cjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.cjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.cjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  interface FastifyRequestLike extends NodeRequestLike {
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike } from './shared/server.D0gAciOr.mjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.mjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.mjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  interface FastifyRequestLike extends NodeRequestLike {
package/dist/fastify.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike } from './shared/server.D0gAciOr.js';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.js';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.js';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  interface FastifyRequestLike extends NodeRequestLike {
@@ -3,11 +3,14 @@
3
3
  const pathe = require('@mokup/shared/pathe');
4
4
  const node_fs = require('node:fs');
5
5
  const node_module = require('node:module');
6
- const process = require('node:process');
6
+ const playgroundGrouping = require('@mokup/shared/playground-grouping');
7
7
  const runtime = require('@mokup/runtime');
8
+ const pathUtils = require('@mokup/shared/path-utils');
9
+ const timing = require('@mokup/shared/timing');
8
10
  const node_buffer = require('node:buffer');
9
11
  const node_url = require('node:url');
10
12
  const esbuild = require('@mokup/shared/esbuild');
13
+ const process = require('node:process');
11
14
  const jsoncParser = require('@mokup/shared/jsonc-parser');
12
15
  const hono = require('@mokup/shared/hono');
13
16
 
@@ -117,92 +120,6 @@ async function readPlaygroundAsset(distDir, relPath) {
117
120
  return new Response(content, { headers: { "Content-Type": contentType } });
118
121
  }
119
122
 
120
- function toPosixPath(value) {
121
- return value.replace(/\\/g, "/");
122
- }
123
- function normalizePath(value) {
124
- return toPosixPath(pathe.normalize(value));
125
- }
126
- function isAncestor(parent, child) {
127
- const normalizedParent = normalizePath(parent).replace(/\/$/, "");
128
- const normalizedChild = normalizePath(child);
129
- return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);
130
- }
131
- function resolveGroupRoot(dirs, serverRoot) {
132
- if (!dirs || dirs.length === 0) {
133
- return serverRoot ?? process.cwd();
134
- }
135
- if (serverRoot) {
136
- const normalizedRoot = normalizePath(serverRoot);
137
- const canUseRoot = dirs.every((dir) => isAncestor(normalizedRoot, dir));
138
- if (canUseRoot) {
139
- return normalizedRoot;
140
- }
141
- }
142
- if (dirs.length === 1) {
143
- return normalizePath(pathe.dirname(dirs[0]));
144
- }
145
- let common = normalizePath(dirs[0]);
146
- for (const dir of dirs.slice(1)) {
147
- const normalizedDir = normalizePath(dir);
148
- while (common && !isAncestor(common, normalizedDir)) {
149
- const parent = normalizePath(pathe.dirname(common));
150
- if (parent === common) {
151
- break;
152
- }
153
- common = parent;
154
- }
155
- }
156
- if (!common || common === "/") {
157
- return serverRoot ?? process.cwd();
158
- }
159
- return common;
160
- }
161
- function resolveGroups(dirs, root) {
162
- const groups = [];
163
- const seen = /* @__PURE__ */ new Set();
164
- for (const dir of dirs) {
165
- const normalized = normalizePath(dir);
166
- if (seen.has(normalized)) {
167
- continue;
168
- }
169
- seen.add(normalized);
170
- const rel = toPosixPath(pathe.relative(root, normalized));
171
- const label = rel && !rel.startsWith("..") ? rel : normalized;
172
- groups.push({
173
- key: normalized,
174
- label,
175
- path: normalized
176
- });
177
- }
178
- return groups;
179
- }
180
- function resolveRouteGroup(routeFile, groups) {
181
- if (groups.length === 0) {
182
- return void 0;
183
- }
184
- const normalizedFile = toPosixPath(pathe.normalize(routeFile));
185
- let matched;
186
- for (const group of groups) {
187
- if (normalizedFile === group.path || normalizedFile.startsWith(`${group.path}/`)) {
188
- if (!matched || group.path.length > matched.path.length) {
189
- matched = group;
190
- }
191
- }
192
- }
193
- return matched;
194
- }
195
- function formatRouteFile(file, root) {
196
- if (!root) {
197
- return toPosixPath(file);
198
- }
199
- const rel = toPosixPath(pathe.relative(root, file));
200
- if (!rel || rel.startsWith("..")) {
201
- return toPosixPath(file);
202
- }
203
- return rel;
204
- }
205
-
206
123
  const disabledReasonSet = /* @__PURE__ */ new Set([
207
124
  "disabled",
208
125
  "disabled-dir",
@@ -229,10 +146,10 @@ function normalizeIgnoredReason(reason) {
229
146
  return "unknown";
230
147
  }
231
148
  function toPlaygroundRoute(route, root, groups) {
232
- const matchedGroup = resolveRouteGroup(route.file, groups);
233
- const preSources = route.middlewares?.filter((entry) => entry.position === "pre").map((entry) => formatRouteFile(entry.source, root)) ?? [];
234
- const postSources = route.middlewares?.filter((entry) => entry.position === "post").map((entry) => formatRouteFile(entry.source, root)) ?? [];
235
- const normalSources = route.middlewares?.filter((entry) => entry.position !== "pre" && entry.position !== "post").map((entry) => formatRouteFile(entry.source, root)) ?? [];
149
+ const matchedGroup = playgroundGrouping.resolveRouteGroup(route.file, groups);
150
+ const preSources = route.middlewares?.filter((entry) => entry.position === "pre").map((entry) => playgroundGrouping.formatRouteFile(entry.source, root)) ?? [];
151
+ const postSources = route.middlewares?.filter((entry) => entry.position === "post").map((entry) => playgroundGrouping.formatRouteFile(entry.source, root)) ?? [];
152
+ const normalSources = route.middlewares?.filter((entry) => entry.position !== "pre" && entry.position !== "post").map((entry) => playgroundGrouping.formatRouteFile(entry.source, root)) ?? [];
236
153
  const combinedSources = [
237
154
  ...preSources,
238
155
  ...normalSources,
@@ -241,7 +158,7 @@ function toPlaygroundRoute(route, root, groups) {
241
158
  return {
242
159
  method: route.method,
243
160
  url: route.template,
244
- file: formatRouteFile(route.file, root),
161
+ file: playgroundGrouping.formatRouteFile(route.file, root),
245
162
  type: typeof route.handler === "function" ? "handler" : "static",
246
163
  status: route.status,
247
164
  delay: route.delay,
@@ -258,9 +175,9 @@ function toPlaygroundRoute(route, root, groups) {
258
175
  };
259
176
  }
260
177
  function toPlaygroundDisabledRoute(route, root, groups) {
261
- const matchedGroup = resolveRouteGroup(route.file, groups);
178
+ const matchedGroup = playgroundGrouping.resolveRouteGroup(route.file, groups);
262
179
  const disabled = {
263
- file: formatRouteFile(route.file, root),
180
+ file: playgroundGrouping.formatRouteFile(route.file, root),
264
181
  reason: normalizeDisabledReason(route.reason)
265
182
  };
266
183
  if (typeof route.method !== "undefined") {
@@ -276,9 +193,9 @@ function toPlaygroundDisabledRoute(route, root, groups) {
276
193
  return disabled;
277
194
  }
278
195
  function toPlaygroundIgnoredRoute(route, root, groups) {
279
- const matchedGroup = resolveRouteGroup(route.file, groups);
196
+ const matchedGroup = playgroundGrouping.resolveRouteGroup(route.file, groups);
280
197
  const ignored = {
281
- file: formatRouteFile(route.file, root),
198
+ file: playgroundGrouping.formatRouteFile(route.file, root),
282
199
  reason: normalizeIgnoredReason(route.reason)
283
200
  };
284
201
  if (matchedGroup) {
@@ -288,9 +205,9 @@ function toPlaygroundIgnoredRoute(route, root, groups) {
288
205
  return ignored;
289
206
  }
290
207
  function toPlaygroundConfigFile(entry, root, groups) {
291
- const matchedGroup = resolveRouteGroup(entry.file, groups);
208
+ const matchedGroup = playgroundGrouping.resolveRouteGroup(entry.file, groups);
292
209
  const configFile = {
293
- file: formatRouteFile(entry.file, root)
210
+ file: playgroundGrouping.formatRouteFile(entry.file, root)
294
211
  };
295
212
  if (matchedGroup) {
296
213
  configFile.groupKey = matchedGroup.key;
@@ -327,8 +244,8 @@ function registerPlaygroundRoutes(params) {
327
244
  params.app.get(`${playgroundPath}/`, () => serveIndex());
328
245
  params.app.get(`${playgroundPath}/index.html`, () => serveIndex());
329
246
  params.app.get(`${playgroundPath}/routes`, (c) => {
330
- const baseRoot = resolveGroupRoot(params.dirs, params.root);
331
- const groups = resolveGroups(params.dirs, baseRoot);
247
+ const baseRoot = playgroundGrouping.resolveGroupRoot(params.dirs, params.root);
248
+ const groups = playgroundGrouping.resolveGroups(params.dirs, baseRoot);
332
249
  return c.json({
333
250
  basePath: playgroundPath,
334
251
  root: baseRoot,
@@ -394,59 +311,10 @@ function resolveDirs(dir, root) {
394
311
  );
395
312
  return Array.from(new Set(normalized));
396
313
  }
397
- function createDebouncer(delayMs, fn) {
398
- let timer = null;
399
- return () => {
400
- if (timer) {
401
- clearTimeout(timer);
402
- }
403
- timer = setTimeout(() => {
404
- timer = null;
405
- fn();
406
- }, delayMs);
407
- };
408
- }
409
- function toPosix(value) {
410
- return value.replace(/\\/g, "/");
411
- }
412
- function isInDirs(file, dirs) {
413
- const normalized = toPosix(file);
414
- return dirs.some((dir) => {
415
- const normalizedDir = toPosix(dir).replace(/\/$/, "");
416
- return normalized === normalizedDir || normalized.startsWith(`${normalizedDir}/`);
417
- });
418
- }
419
- function testPatterns(patterns, value) {
420
- const list = Array.isArray(patterns) ? patterns : [patterns];
421
- return list.some((pattern) => pattern.test(value));
422
- }
423
- function matchesFilter(file, include, exclude) {
424
- const normalized = toPosix(file);
425
- if (exclude && testPatterns(exclude, normalized)) {
426
- return false;
427
- }
428
- if (include) {
429
- return testPatterns(include, normalized);
430
- }
431
- return true;
432
- }
433
314
  function normalizeIgnorePrefix(value, fallback = ["."]) {
434
315
  const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
435
316
  return list.filter((entry) => typeof entry === "string" && entry.length > 0);
436
317
  }
437
- function hasIgnoredPrefix(file, rootDir, prefixes) {
438
- if (prefixes.length === 0) {
439
- return false;
440
- }
441
- const relativePath = toPosix(pathe.relative(rootDir, file));
442
- const segments = relativePath.split("/");
443
- return segments.some(
444
- (segment) => prefixes.some((prefix) => segment.startsWith(prefix))
445
- );
446
- }
447
- function delay(ms) {
448
- return new Promise((resolve2) => setTimeout(resolve2, ms));
449
- }
450
318
 
451
319
  const jsonExtensions = /* @__PURE__ */ new Set([".json", ".jsonc"]);
452
320
  function resolveTemplate(template, prefix) {
@@ -482,7 +350,7 @@ function stripMethodSuffix(base) {
482
350
  };
483
351
  }
484
352
  function deriveRouteFromFile(file, rootDir, logger) {
485
- const rel = toPosix(pathe.relative(rootDir, file));
353
+ const rel = pathUtils.toPosix(pathe.relative(rootDir, file));
486
354
  const ext = pathe.extname(rel);
487
355
  const withoutExt = rel.slice(0, rel.length - ext.length);
488
356
  const dir = pathe.dirname(withoutExt);
@@ -498,7 +366,7 @@ function deriveRouteFromFile(file, rootDir, logger) {
498
366
  return null;
499
367
  }
500
368
  const joined = dir === "." ? name : pathe.join(dir, name);
501
- const segments = toPosix(joined).split("/");
369
+ const segments = pathUtils.toPosix(joined).split("/");
502
370
  if (segments.at(-1) === "index") {
503
371
  segments.pop();
504
372
  }
@@ -854,26 +722,26 @@ async function collectFiles(dirs) {
854
722
  }
855
723
  return files;
856
724
  }
857
- function isSupportedFile(file) {
725
+ function isConfigFile(file) {
858
726
  if (file.endsWith(".d.ts")) {
859
727
  return false;
860
728
  }
861
- if (isConfigFile(file)) {
729
+ const base = pathe.basename(file);
730
+ if (!base.startsWith("index.config.")) {
862
731
  return false;
863
732
  }
864
733
  const ext = pathe.extname(file).toLowerCase();
865
- return supportedExtensions.has(ext);
734
+ return configExtensions.includes(ext);
866
735
  }
867
- function isConfigFile(file) {
736
+ function isSupportedFile(file) {
868
737
  if (file.endsWith(".d.ts")) {
869
738
  return false;
870
739
  }
871
- const base = pathe.basename(file);
872
- if (!base.startsWith("index.config.")) {
740
+ if (isConfigFile(file)) {
873
741
  return false;
874
742
  }
875
743
  const ext = pathe.extname(file).toLowerCase();
876
- return configExtensions.includes(ext);
744
+ return supportedExtensions.has(ext);
877
745
  }
878
746
 
879
747
  function isUnknownFileExtensionError(error) {
@@ -1062,7 +930,7 @@ async function scanRoutes(params) {
1062
930
  continue;
1063
931
  }
1064
932
  const effectiveIgnorePrefix = typeof config.ignorePrefix !== "undefined" ? normalizeIgnorePrefix(config.ignorePrefix, []) : globalIgnorePrefix;
1065
- if (hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix)) {
933
+ if (pathUtils.hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix)) {
1066
934
  if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
1067
935
  const resolved = resolveSkipRoute({
1068
936
  file: fileInfo.file,
@@ -1081,14 +949,14 @@ async function scanRoutes(params) {
1081
949
  }
1082
950
  const effectiveInclude = typeof config.include !== "undefined" ? config.include : params.include;
1083
951
  const effectiveExclude = typeof config.exclude !== "undefined" ? config.exclude : params.exclude;
1084
- if (!matchesFilter(fileInfo.file, effectiveInclude, effectiveExclude)) {
952
+ if (!pathUtils.matchesFilter(fileInfo.file, effectiveInclude, effectiveExclude)) {
1085
953
  if (shouldCollectSkip) {
1086
954
  const resolved = resolveSkipRoute({
1087
955
  file: fileInfo.file,
1088
956
  rootDir: fileInfo.rootDir,
1089
957
  prefix: params.prefix
1090
958
  });
1091
- const reason = effectiveExclude && matchesFilter(fileInfo.file, void 0, effectiveExclude) ? "exclude" : "include";
959
+ const reason = effectiveExclude && pathUtils.matchesFilter(fileInfo.file, void 0, effectiveExclude) ? "exclude" : "include";
1092
960
  params.onSkip?.(buildSkipInfo(fileInfo.file, reason, resolved));
1093
961
  }
1094
962
  continue;
@@ -1259,7 +1127,7 @@ function createFinalizeMiddleware(route, onResponse) {
1259
1127
  const response = await next();
1260
1128
  const resolved = resolveResponse(response, c.res);
1261
1129
  if (route.delay && route.delay > 0) {
1262
- await delay(route.delay);
1130
+ await timing.delay(route.delay);
1263
1131
  }
1264
1132
  const overridden = applyRouteOverrides(resolved, route);
1265
1133
  c.res = overridden;
@@ -1495,17 +1363,17 @@ async function createChokidarWatcher(params) {
1495
1363
  const { default: chokidar } = await import('@mokup/shared/chokidar');
1496
1364
  const watcher = chokidar.watch(params.dirs, { ignoreInitial: true });
1497
1365
  watcher.on("add", (file) => {
1498
- if (isInDirs(file, params.dirs)) {
1366
+ if (pathUtils.isInDirs(file, params.dirs)) {
1499
1367
  params.onChange();
1500
1368
  }
1501
1369
  });
1502
1370
  watcher.on("change", (file) => {
1503
- if (isInDirs(file, params.dirs)) {
1371
+ if (pathUtils.isInDirs(file, params.dirs)) {
1504
1372
  params.onChange();
1505
1373
  }
1506
1374
  });
1507
1375
  watcher.on("unlink", (file) => {
1508
- if (isInDirs(file, params.dirs)) {
1376
+ if (pathUtils.isInDirs(file, params.dirs)) {
1509
1377
  params.onChange();
1510
1378
  }
1511
1379
  });
@@ -1629,7 +1497,7 @@ async function createFetchServer(options = {}) {
1629
1497
  if (wsHandler && playgroundConfig.enabled) {
1630
1498
  app.get(`${playgroundConfig.path}/ws`, wsHandler);
1631
1499
  }
1632
- const scheduleRefresh = createDebouncer(80, () => {
1500
+ const scheduleRefresh = timing.createDebouncer(80, () => {
1633
1501
  void refreshRoutes();
1634
1502
  });
1635
1503
  const watcher = await createWatcher({
@@ -1,11 +1,14 @@
1
- import { join, normalize, extname, dirname, relative, resolve, isAbsolute, basename } from '@mokup/shared/pathe';
1
+ import { join, normalize, extname, resolve, isAbsolute, relative, dirname, basename } from '@mokup/shared/pathe';
2
2
  import { promises } from 'node:fs';
3
3
  import { createRequire } from 'node:module';
4
- import process, { cwd } from 'node:process';
4
+ import { resolveRouteGroup, formatRouteFile, resolveGroupRoot, resolveGroups } from '@mokup/shared/playground-grouping';
5
5
  import { compareRouteScore, parseRouteTemplate } from '@mokup/runtime';
6
+ import { toPosix, hasIgnoredPrefix, matchesFilter, isInDirs } from '@mokup/shared/path-utils';
7
+ import { delay, createDebouncer } from '@mokup/shared/timing';
6
8
  import { Buffer } from 'node:buffer';
7
9
  import { pathToFileURL } from 'node:url';
8
10
  import { build } from '@mokup/shared/esbuild';
11
+ import process, { cwd } from 'node:process';
9
12
  import { parse } from '@mokup/shared/jsonc-parser';
10
13
  import { Hono, PatternRouter } from '@mokup/shared/hono';
11
14
 
@@ -110,92 +113,6 @@ async function readPlaygroundAsset(distDir, relPath) {
110
113
  return new Response(content, { headers: { "Content-Type": contentType } });
111
114
  }
112
115
 
113
- function toPosixPath(value) {
114
- return value.replace(/\\/g, "/");
115
- }
116
- function normalizePath(value) {
117
- return toPosixPath(normalize(value));
118
- }
119
- function isAncestor(parent, child) {
120
- const normalizedParent = normalizePath(parent).replace(/\/$/, "");
121
- const normalizedChild = normalizePath(child);
122
- return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);
123
- }
124
- function resolveGroupRoot(dirs, serverRoot) {
125
- if (!dirs || dirs.length === 0) {
126
- return serverRoot ?? cwd();
127
- }
128
- if (serverRoot) {
129
- const normalizedRoot = normalizePath(serverRoot);
130
- const canUseRoot = dirs.every((dir) => isAncestor(normalizedRoot, dir));
131
- if (canUseRoot) {
132
- return normalizedRoot;
133
- }
134
- }
135
- if (dirs.length === 1) {
136
- return normalizePath(dirname(dirs[0]));
137
- }
138
- let common = normalizePath(dirs[0]);
139
- for (const dir of dirs.slice(1)) {
140
- const normalizedDir = normalizePath(dir);
141
- while (common && !isAncestor(common, normalizedDir)) {
142
- const parent = normalizePath(dirname(common));
143
- if (parent === common) {
144
- break;
145
- }
146
- common = parent;
147
- }
148
- }
149
- if (!common || common === "/") {
150
- return serverRoot ?? cwd();
151
- }
152
- return common;
153
- }
154
- function resolveGroups(dirs, root) {
155
- const groups = [];
156
- const seen = /* @__PURE__ */ new Set();
157
- for (const dir of dirs) {
158
- const normalized = normalizePath(dir);
159
- if (seen.has(normalized)) {
160
- continue;
161
- }
162
- seen.add(normalized);
163
- const rel = toPosixPath(relative(root, normalized));
164
- const label = rel && !rel.startsWith("..") ? rel : normalized;
165
- groups.push({
166
- key: normalized,
167
- label,
168
- path: normalized
169
- });
170
- }
171
- return groups;
172
- }
173
- function resolveRouteGroup(routeFile, groups) {
174
- if (groups.length === 0) {
175
- return void 0;
176
- }
177
- const normalizedFile = toPosixPath(normalize(routeFile));
178
- let matched;
179
- for (const group of groups) {
180
- if (normalizedFile === group.path || normalizedFile.startsWith(`${group.path}/`)) {
181
- if (!matched || group.path.length > matched.path.length) {
182
- matched = group;
183
- }
184
- }
185
- }
186
- return matched;
187
- }
188
- function formatRouteFile(file, root) {
189
- if (!root) {
190
- return toPosixPath(file);
191
- }
192
- const rel = toPosixPath(relative(root, file));
193
- if (!rel || rel.startsWith("..")) {
194
- return toPosixPath(file);
195
- }
196
- return rel;
197
- }
198
-
199
116
  const disabledReasonSet = /* @__PURE__ */ new Set([
200
117
  "disabled",
201
118
  "disabled-dir",
@@ -387,59 +304,10 @@ function resolveDirs(dir, root) {
387
304
  );
388
305
  return Array.from(new Set(normalized));
389
306
  }
390
- function createDebouncer(delayMs, fn) {
391
- let timer = null;
392
- return () => {
393
- if (timer) {
394
- clearTimeout(timer);
395
- }
396
- timer = setTimeout(() => {
397
- timer = null;
398
- fn();
399
- }, delayMs);
400
- };
401
- }
402
- function toPosix(value) {
403
- return value.replace(/\\/g, "/");
404
- }
405
- function isInDirs(file, dirs) {
406
- const normalized = toPosix(file);
407
- return dirs.some((dir) => {
408
- const normalizedDir = toPosix(dir).replace(/\/$/, "");
409
- return normalized === normalizedDir || normalized.startsWith(`${normalizedDir}/`);
410
- });
411
- }
412
- function testPatterns(patterns, value) {
413
- const list = Array.isArray(patterns) ? patterns : [patterns];
414
- return list.some((pattern) => pattern.test(value));
415
- }
416
- function matchesFilter(file, include, exclude) {
417
- const normalized = toPosix(file);
418
- if (exclude && testPatterns(exclude, normalized)) {
419
- return false;
420
- }
421
- if (include) {
422
- return testPatterns(include, normalized);
423
- }
424
- return true;
425
- }
426
307
  function normalizeIgnorePrefix(value, fallback = ["."]) {
427
308
  const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
428
309
  return list.filter((entry) => typeof entry === "string" && entry.length > 0);
429
310
  }
430
- function hasIgnoredPrefix(file, rootDir, prefixes) {
431
- if (prefixes.length === 0) {
432
- return false;
433
- }
434
- const relativePath = toPosix(relative(rootDir, file));
435
- const segments = relativePath.split("/");
436
- return segments.some(
437
- (segment) => prefixes.some((prefix) => segment.startsWith(prefix))
438
- );
439
- }
440
- function delay(ms) {
441
- return new Promise((resolve2) => setTimeout(resolve2, ms));
442
- }
443
311
 
444
312
  const jsonExtensions = /* @__PURE__ */ new Set([".json", ".jsonc"]);
445
313
  function resolveTemplate(template, prefix) {
@@ -847,26 +715,26 @@ async function collectFiles(dirs) {
847
715
  }
848
716
  return files;
849
717
  }
850
- function isSupportedFile(file) {
718
+ function isConfigFile(file) {
851
719
  if (file.endsWith(".d.ts")) {
852
720
  return false;
853
721
  }
854
- if (isConfigFile(file)) {
722
+ const base = basename(file);
723
+ if (!base.startsWith("index.config.")) {
855
724
  return false;
856
725
  }
857
726
  const ext = extname(file).toLowerCase();
858
- return supportedExtensions.has(ext);
727
+ return configExtensions.includes(ext);
859
728
  }
860
- function isConfigFile(file) {
729
+ function isSupportedFile(file) {
861
730
  if (file.endsWith(".d.ts")) {
862
731
  return false;
863
732
  }
864
- const base = basename(file);
865
- if (!base.startsWith("index.config.")) {
733
+ if (isConfigFile(file)) {
866
734
  return false;
867
735
  }
868
736
  const ext = extname(file).toLowerCase();
869
- return configExtensions.includes(ext);
737
+ return supportedExtensions.has(ext);
870
738
  }
871
739
 
872
740
  function isUnknownFileExtensionError(error) {
package/dist/fetch.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as ServerOptions, F as FetchHandler } from './shared/server.DkerfsA-.cjs';
1
+ import { S as ServerOptions, F as FetchHandler } from './shared/server.LMr0or7K.cjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
package/dist/fetch.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as ServerOptions, F as FetchHandler } from './shared/server.DkerfsA-.mjs';
1
+ import { S as ServerOptions, F as FetchHandler } from './shared/server.LMr0or7K.mjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
package/dist/fetch.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as ServerOptions, F as FetchHandler } from './shared/server.DkerfsA-.js';
1
+ import { S as ServerOptions, F as FetchHandler } from './shared/server.LMr0or7K.js';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
package/dist/hono.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as ServerOptions } from './shared/server.DkerfsA-.cjs';
1
+ import { S as ServerOptions } from './shared/server.LMr0or7K.cjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  interface HonoContextLike {
package/dist/hono.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as ServerOptions } from './shared/server.DkerfsA-.mjs';
1
+ import { S as ServerOptions } from './shared/server.LMr0or7K.mjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  interface HonoContextLike {
package/dist/hono.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as ServerOptions } from './shared/server.DkerfsA-.js';
1
+ import { S as ServerOptions } from './shared/server.LMr0or7K.js';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  interface HonoContextLike {
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { R as RouteDirectoryConfig, M as MiddlewareRegistry } from './shared/server.CyVIKPsp.cjs';
2
2
  export { a as MiddlewarePosition, b as ResolvedMiddleware, c as RouteRule } from './shared/server.CyVIKPsp.cjs';
3
3
  export { createFetchHandler } from './fetch.cjs';
4
- export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.DkerfsA-.cjs';
4
+ export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.LMr0or7K.cjs';
5
5
  export { createMokupWorker } from './worker.cjs';
6
6
  export { Manifest, ManifestRoute, ModuleMap, RuntimeOptions } from '@mokup/runtime';
7
7
  export { MiddlewareHandler } from '@mokup/shared/hono';
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { R as RouteDirectoryConfig, M as MiddlewareRegistry } from './shared/server.CyVIKPsp.mjs';
2
2
  export { a as MiddlewarePosition, b as ResolvedMiddleware, c as RouteRule } from './shared/server.CyVIKPsp.mjs';
3
3
  export { createFetchHandler } from './fetch.mjs';
4
- export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.DkerfsA-.mjs';
4
+ export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.LMr0or7K.mjs';
5
5
  export { createMokupWorker } from './worker.mjs';
6
6
  export { Manifest, ManifestRoute, ModuleMap, RuntimeOptions } from '@mokup/runtime';
7
7
  export { MiddlewareHandler } from '@mokup/shared/hono';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { R as RouteDirectoryConfig, M as MiddlewareRegistry } from './shared/server.CyVIKPsp.js';
2
2
  export { a as MiddlewarePosition, b as ResolvedMiddleware, c as RouteRule } from './shared/server.CyVIKPsp.js';
3
3
  export { createFetchHandler } from './fetch.js';
4
- export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.DkerfsA-.js';
4
+ export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.LMr0or7K.js';
5
5
  export { createMokupWorker } from './worker.js';
6
6
  export { Manifest, ManifestRoute, ModuleMap, RuntimeOptions } from '@mokup/runtime';
7
7
  export { MiddlewareHandler } from '@mokup/shared/hono';
package/dist/koa.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike } from './shared/server.D0gAciOr.cjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.cjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.cjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  interface KoaContextLike {
package/dist/koa.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike } from './shared/server.D0gAciOr.mjs';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.mjs';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.mjs';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  interface KoaContextLike {
package/dist/koa.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as NodeRequestLike } from './shared/server.D0gAciOr.js';
2
- import { S as ServerOptions } from './shared/server.DkerfsA-.js';
2
+ import { S as ServerOptions } from './shared/server.LMr0or7K.js';
3
3
  import '@mokup/runtime';
4
4
 
5
5
  interface KoaContextLike {
package/dist/node.cjs CHANGED
@@ -13,13 +13,17 @@ require('./shared/server.aaygIV2Q.cjs');
13
13
  require('@mokup/shared/pathe');
14
14
  require('node:fs');
15
15
  require('node:module');
16
- require('node:process');
16
+ require('@mokup/shared/playground-grouping');
17
+ require('@mokup/shared/path-utils');
18
+ require('@mokup/shared/timing');
17
19
  require('node:buffer');
18
20
  require('node:url');
19
21
  require('@mokup/shared/esbuild');
22
+ require('node:process');
20
23
  require('@mokup/shared/jsonc-parser');
21
24
  require('@mokup/shared/hono');
22
25
  require('./fetch.cjs');
26
+ require('node:path');
23
27
 
24
28
 
25
29
 
package/dist/node.d.cts CHANGED
@@ -7,7 +7,7 @@ export { createKoaMiddleware } from './koa.cjs';
7
7
  export { NodeWorkerInput, createMokupWorker } from './worker-node.cjs';
8
8
  export { serve } from '@hono/node-server';
9
9
  import './shared/server.D0gAciOr.cjs';
10
- import './shared/server.DkerfsA-.cjs';
10
+ import './shared/server.LMr0or7K.cjs';
11
11
  import '@mokup/runtime';
12
12
  import './shared/server.CyVIKPsp.cjs';
13
13
  import '@mokup/shared/hono';
package/dist/node.d.mts CHANGED
@@ -7,7 +7,7 @@ export { createKoaMiddleware } from './koa.mjs';
7
7
  export { NodeWorkerInput, createMokupWorker } from './worker-node.mjs';
8
8
  export { serve } from '@hono/node-server';
9
9
  import './shared/server.D0gAciOr.mjs';
10
- import './shared/server.DkerfsA-.mjs';
10
+ import './shared/server.LMr0or7K.mjs';
11
11
  import '@mokup/runtime';
12
12
  import './shared/server.CyVIKPsp.mjs';
13
13
  import '@mokup/shared/hono';
package/dist/node.d.ts CHANGED
@@ -7,7 +7,7 @@ export { createKoaMiddleware } from './koa.js';
7
7
  export { NodeWorkerInput, createMokupWorker } from './worker-node.js';
8
8
  export { serve } from '@hono/node-server';
9
9
  import './shared/server.D0gAciOr.js';
10
- import './shared/server.DkerfsA-.js';
10
+ import './shared/server.LMr0or7K.js';
11
11
  import '@mokup/runtime';
12
12
  import './shared/server.CyVIKPsp.js';
13
13
  import '@mokup/shared/hono';
package/dist/node.mjs CHANGED
@@ -11,10 +11,14 @@ import './shared/server.LbftO9Jh.mjs';
11
11
  import '@mokup/shared/pathe';
12
12
  import 'node:fs';
13
13
  import 'node:module';
14
- import 'node:process';
14
+ import '@mokup/shared/playground-grouping';
15
+ import '@mokup/shared/path-utils';
16
+ import '@mokup/shared/timing';
15
17
  import 'node:buffer';
16
18
  import 'node:url';
17
19
  import '@mokup/shared/esbuild';
20
+ import 'node:process';
18
21
  import '@mokup/shared/jsonc-parser';
19
22
  import '@mokup/shared/hono';
20
23
  import './fetch.mjs';
24
+ import 'node:path';
@@ -46,13 +46,13 @@ interface WorkerBundle {
46
46
  *
47
47
  * @default undefined
48
48
  */
49
- moduleMap?: ModuleMap;
49
+ moduleMap?: ModuleMap | undefined;
50
50
  /**
51
51
  * Base directory for module resolution.
52
52
  *
53
53
  * @default undefined
54
54
  */
55
- moduleBase?: string | URL;
55
+ moduleBase?: string | URL | undefined;
56
56
  /**
57
57
  * Behavior when no route matches.
58
58
  *
@@ -46,13 +46,13 @@ interface WorkerBundle {
46
46
  *
47
47
  * @default undefined
48
48
  */
49
- moduleMap?: ModuleMap;
49
+ moduleMap?: ModuleMap | undefined;
50
50
  /**
51
51
  * Base directory for module resolution.
52
52
  *
53
53
  * @default undefined
54
54
  */
55
- moduleBase?: string | URL;
55
+ moduleBase?: string | URL | undefined;
56
56
  /**
57
57
  * Behavior when no route matches.
58
58
  *
@@ -46,13 +46,13 @@ interface WorkerBundle {
46
46
  *
47
47
  * @default undefined
48
48
  */
49
- moduleMap?: ModuleMap;
49
+ moduleMap?: ModuleMap | undefined;
50
50
  /**
51
51
  * Base directory for module resolution.
52
52
  *
53
53
  * @default undefined
54
54
  */
55
- moduleBase?: string | URL;
55
+ moduleBase?: string | URL | undefined;
56
56
  /**
57
57
  * Behavior when no route matches.
58
58
  *
@@ -1,9 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ const node_path = require('node:path');
4
+ const node_url = require('node:url');
3
5
  const fetch = require('./fetch.cjs');
4
6
  require('@mokup/runtime');
5
7
  require('./shared/server.aaygIV2Q.cjs');
6
8
 
9
+ function ensureTrailingSlash(value) {
10
+ return value.endsWith("/") ? value : `${value}/`;
11
+ }
12
+ function resolveModuleBase(dir) {
13
+ const absolute = node_path.resolve(dir);
14
+ return ensureTrailingSlash(node_url.pathToFileURL(absolute).href);
15
+ }
7
16
  function isManifest(value) {
8
17
  return typeof value === "object" && value !== null && !Array.isArray(value) && "version" in value && "routes" in value;
9
18
  }
@@ -27,23 +36,21 @@ async function loadBundleFromDir(dir) {
27
36
  throw new TypeError("createMokupWorker(dir) is only supported in Node runtimes.");
28
37
  }
29
38
  const { readFile, access } = await import('node:fs/promises');
30
- const { resolve, join } = await import('node:path');
31
- const { pathToFileURL } = await import('node:url');
32
- const manifestPath = resolve(dir, "mokup.manifest.json");
39
+ const manifestPath = node_path.resolve(dir, "mokup.manifest.json");
33
40
  const manifestRaw = await readFile(manifestPath, "utf8");
34
41
  const manifest = JSON.parse(manifestRaw);
35
- const handlersIndexPath = resolve(dir, "mokup-handlers", "index.mjs");
42
+ const handlersIndexPath = node_path.resolve(dir, "mokup-handlers", "index.mjs");
36
43
  let moduleMap;
37
44
  try {
38
45
  await access(handlersIndexPath);
39
- const module = await import(pathToFileURL(handlersIndexPath).href);
46
+ const module = await import(node_url.pathToFileURL(handlersIndexPath).href);
40
47
  moduleMap = module.mokupModuleMap;
41
48
  } catch {
42
49
  moduleMap = void 0;
43
50
  }
44
51
  const bundle = {
45
52
  manifest,
46
- moduleBase: join(dir, "/")
53
+ moduleBase: resolveModuleBase(dir)
47
54
  };
48
55
  if (typeof moduleMap !== "undefined") {
49
56
  bundle.moduleMap = moduleMap;
@@ -72,3 +79,4 @@ function createMokupWorker(input) {
72
79
  }
73
80
 
74
81
  exports.createMokupWorker = createMokupWorker;
82
+ exports.resolveModuleBase = resolveModuleBase;
@@ -1,4 +1,4 @@
1
- import { a as WorkerInput } from './shared/server.DkerfsA-.cjs';
1
+ import { a as WorkerInput } from './shared/server.LMr0or7K.cjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
@@ -22,6 +22,7 @@ interface FetchWorker {
22
22
  * const input: NodeWorkerInput = '.mokup'
23
23
  */
24
24
  type NodeWorkerInput = string | WorkerInput;
25
+ declare function resolveModuleBase(dir: string): string;
25
26
  /**
26
27
  * Create a Worker-compatible fetch handler for Node.
27
28
  *
@@ -36,5 +37,5 @@ type NodeWorkerInput = string | WorkerInput;
36
37
  declare function createMokupWorker(input: string): Promise<FetchWorker>;
37
38
  declare function createMokupWorker(input: WorkerInput): FetchWorker;
38
39
 
39
- export { createMokupWorker };
40
+ export { createMokupWorker, resolveModuleBase };
40
41
  export type { FetchWorker, NodeWorkerInput };
@@ -1,4 +1,4 @@
1
- import { a as WorkerInput } from './shared/server.DkerfsA-.mjs';
1
+ import { a as WorkerInput } from './shared/server.LMr0or7K.mjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
@@ -22,6 +22,7 @@ interface FetchWorker {
22
22
  * const input: NodeWorkerInput = '.mokup'
23
23
  */
24
24
  type NodeWorkerInput = string | WorkerInput;
25
+ declare function resolveModuleBase(dir: string): string;
25
26
  /**
26
27
  * Create a Worker-compatible fetch handler for Node.
27
28
  *
@@ -36,5 +37,5 @@ type NodeWorkerInput = string | WorkerInput;
36
37
  declare function createMokupWorker(input: string): Promise<FetchWorker>;
37
38
  declare function createMokupWorker(input: WorkerInput): FetchWorker;
38
39
 
39
- export { createMokupWorker };
40
+ export { createMokupWorker, resolveModuleBase };
40
41
  export type { FetchWorker, NodeWorkerInput };
@@ -1,4 +1,4 @@
1
- import { a as WorkerInput } from './shared/server.DkerfsA-.js';
1
+ import { a as WorkerInput } from './shared/server.LMr0or7K.js';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
@@ -22,6 +22,7 @@ interface FetchWorker {
22
22
  * const input: NodeWorkerInput = '.mokup'
23
23
  */
24
24
  type NodeWorkerInput = string | WorkerInput;
25
+ declare function resolveModuleBase(dir: string): string;
25
26
  /**
26
27
  * Create a Worker-compatible fetch handler for Node.
27
28
  *
@@ -36,5 +37,5 @@ type NodeWorkerInput = string | WorkerInput;
36
37
  declare function createMokupWorker(input: string): Promise<FetchWorker>;
37
38
  declare function createMokupWorker(input: WorkerInput): FetchWorker;
38
39
 
39
- export { createMokupWorker };
40
+ export { createMokupWorker, resolveModuleBase };
40
41
  export type { FetchWorker, NodeWorkerInput };
@@ -1,7 +1,16 @@
1
+ import { resolve } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
1
3
  import { createFetchHandler } from './fetch.mjs';
2
4
  import '@mokup/runtime';
3
5
  import './shared/server.LbftO9Jh.mjs';
4
6
 
7
+ function ensureTrailingSlash(value) {
8
+ return value.endsWith("/") ? value : `${value}/`;
9
+ }
10
+ function resolveModuleBase(dir) {
11
+ const absolute = resolve(dir);
12
+ return ensureTrailingSlash(pathToFileURL(absolute).href);
13
+ }
5
14
  function isManifest(value) {
6
15
  return typeof value === "object" && value !== null && !Array.isArray(value) && "version" in value && "routes" in value;
7
16
  }
@@ -25,8 +34,6 @@ async function loadBundleFromDir(dir) {
25
34
  throw new TypeError("createMokupWorker(dir) is only supported in Node runtimes.");
26
35
  }
27
36
  const { readFile, access } = await import('node:fs/promises');
28
- const { resolve, join } = await import('node:path');
29
- const { pathToFileURL } = await import('node:url');
30
37
  const manifestPath = resolve(dir, "mokup.manifest.json");
31
38
  const manifestRaw = await readFile(manifestPath, "utf8");
32
39
  const manifest = JSON.parse(manifestRaw);
@@ -41,7 +48,7 @@ async function loadBundleFromDir(dir) {
41
48
  }
42
49
  const bundle = {
43
50
  manifest,
44
- moduleBase: join(dir, "/")
51
+ moduleBase: resolveModuleBase(dir)
45
52
  };
46
53
  if (typeof moduleMap !== "undefined") {
47
54
  bundle.moduleMap = moduleMap;
@@ -69,4 +76,4 @@ function createMokupWorker(input) {
69
76
  return createWorker(normalizeWorkerOptions(input));
70
77
  }
71
78
 
72
- export { createMokupWorker };
79
+ export { createMokupWorker, resolveModuleBase };
package/dist/worker.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as WorkerInput } from './shared/server.DkerfsA-.cjs';
1
+ import { a as WorkerInput } from './shared/server.LMr0or7K.cjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
package/dist/worker.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as WorkerInput } from './shared/server.DkerfsA-.mjs';
1
+ import { a as WorkerInput } from './shared/server.LMr0or7K.mjs';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
package/dist/worker.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as WorkerInput } from './shared/server.DkerfsA-.js';
1
+ import { a as WorkerInput } from './shared/server.LMr0or7K.js';
2
2
  import '@mokup/runtime';
3
3
 
4
4
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mokup/server",
3
3
  "type": "module",
4
- "version": "1.1.5",
4
+ "version": "1.1.8",
5
5
  "description": "Server adapters for @mokup/runtime.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://mokup.icebreaker.top",
@@ -80,9 +80,9 @@
80
80
  "@hono/node-server": "^1.19.9",
81
81
  "@hono/node-ws": "^1.1.1",
82
82
  "tsx": "^4.21.0",
83
- "@mokup/playground": "0.0.13",
84
- "@mokup/runtime": "1.0.4",
85
- "@mokup/shared": "1.1.0"
83
+ "@mokup/playground": "0.0.15",
84
+ "@mokup/runtime": "1.0.6",
85
+ "@mokup/shared": "1.1.1"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@types/node": "^25.0.10",