@mokup/cli 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -9,8 +9,8 @@ const node_url = require('node:url');
9
9
  const esbuild = require('@mokup/shared/esbuild');
10
10
  const runtime = require('@mokup/runtime');
11
11
  const jsoncParser = require('@mokup/shared/jsonc-parser');
12
- const nodeServer = require('@hono/node-server');
13
12
  const server = require('@mokup/server');
13
+ const node = require('@mokup/server/node');
14
14
  const commander = require('commander');
15
15
 
16
16
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -195,6 +195,15 @@ async function resolveDirectoryConfig(params) {
195
195
  if (typeof config.enabled === "boolean") {
196
196
  merged.enabled = config.enabled;
197
197
  }
198
+ if (typeof config.ignorePrefix !== "undefined") {
199
+ merged.ignorePrefix = config.ignorePrefix;
200
+ }
201
+ if (typeof config.include !== "undefined") {
202
+ merged.include = config.include;
203
+ }
204
+ if (typeof config.exclude !== "undefined") {
205
+ merged.exclude = config.exclude;
206
+ }
198
207
  const normalized = normalizeMiddlewares(config.middleware, configPath, log);
199
208
  if (normalized.length > 0) {
200
209
  merged.middlewares.push(...normalized);
@@ -271,6 +280,20 @@ function matchesFilter(file, include, exclude) {
271
280
  }
272
281
  return true;
273
282
  }
283
+ function normalizeIgnorePrefix(value, fallback = ["."]) {
284
+ const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
285
+ return list.filter((entry) => typeof entry === "string" && entry.length > 0);
286
+ }
287
+ function hasIgnoredPrefix(file, rootDir, prefixes) {
288
+ if (prefixes.length === 0) {
289
+ return false;
290
+ }
291
+ const relativePath = toPosix(pathe.relative(rootDir, file));
292
+ const segments = relativePath.split("/");
293
+ return segments.some(
294
+ (segment) => prefixes.some((prefix) => segment.startsWith(prefix))
295
+ );
296
+ }
274
297
  function isSupportedFile(file) {
275
298
  if (file.endsWith(".d.ts")) {
276
299
  return false;
@@ -592,13 +615,8 @@ async function buildManifest(options = {}) {
592
615
  const handlerModuleMap = /* @__PURE__ */ new Map();
593
616
  const configCache = /* @__PURE__ */ new Map();
594
617
  const configFileCache = /* @__PURE__ */ new Map();
618
+ const globalIgnorePrefix = normalizeIgnorePrefix(options.ignorePrefix);
595
619
  for (const fileInfo of files) {
596
- if (!isSupportedFile(fileInfo.file)) {
597
- continue;
598
- }
599
- if (!matchesFilter(fileInfo.file, options.include, options.exclude)) {
600
- continue;
601
- }
602
620
  const configParams = {
603
621
  file: fileInfo.file,
604
622
  rootDir: fileInfo.rootDir,
@@ -612,6 +630,18 @@ async function buildManifest(options = {}) {
612
630
  if (config.enabled === false) {
613
631
  continue;
614
632
  }
633
+ const effectiveIgnorePrefix = typeof config.ignorePrefix !== "undefined" ? normalizeIgnorePrefix(config.ignorePrefix, []) : globalIgnorePrefix;
634
+ if (hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix)) {
635
+ continue;
636
+ }
637
+ if (!isSupportedFile(fileInfo.file)) {
638
+ continue;
639
+ }
640
+ const effectiveInclude = typeof config.include !== "undefined" ? config.include : options.include;
641
+ const effectiveExclude = typeof config.exclude !== "undefined" ? config.exclude : options.exclude;
642
+ if (!matchesFilter(fileInfo.file, effectiveInclude, effectiveExclude)) {
643
+ continue;
644
+ }
615
645
  const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, options.log);
616
646
  if (!derived) {
617
647
  continue;
@@ -621,6 +651,9 @@ async function buildManifest(options = {}) {
621
651
  if (!rule || typeof rule !== "object") {
622
652
  continue;
623
653
  }
654
+ if (rule.enabled === false) {
655
+ continue;
656
+ }
624
657
  const ruleValue = rule;
625
658
  const unsupportedKeys = ["response", "url", "method"].filter(
626
659
  (key2) => key2 in ruleValue
@@ -761,6 +794,9 @@ function toBuildOptions(options) {
761
794
  if (options.exclude && options.exclude.length > 0) {
762
795
  buildOptions.exclude = options.exclude;
763
796
  }
797
+ if (options.ignorePrefix && options.ignorePrefix.length > 0) {
798
+ buildOptions.ignorePrefix = options.ignorePrefix;
799
+ }
764
800
  return buildOptions;
765
801
  }
766
802
  function toServeOptions(options) {
@@ -780,6 +816,9 @@ function toServeOptions(options) {
780
816
  if (options.exclude && options.exclude.length > 0) {
781
817
  serveOptions.exclude = options.exclude;
782
818
  }
819
+ if (options.ignorePrefix && options.ignorePrefix.length > 0) {
820
+ serveOptions.ignorePrefix = options.ignorePrefix;
821
+ }
783
822
  if (options.host) {
784
823
  serveOptions.host = options.host;
785
824
  }
@@ -798,18 +837,18 @@ function toServeOptions(options) {
798
837
  function createCli() {
799
838
  const program = new commander.Command();
800
839
  program.name("mokup").description("Mock utilities for file-based routes.").showHelpAfterError();
801
- program.command("build").description("Generate .mokup build output").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("-o, --out <dir>", "Output directory (default: .mokup)").option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--no-handlers", "Skip function handler output").action(async (options) => {
840
+ program.command("build").description("Generate .mokup build output").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("-o, --out <dir>", "Output directory (default: .mokup)").option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--ignore-prefix <prefix>", "Ignore path segment prefix (repeatable)", collectValues).option("--no-handlers", "Skip function handler output").action(async (options) => {
802
841
  const buildOptions = toBuildOptions(options);
803
842
  await buildManifest(buildOptions);
804
843
  });
805
- program.command("serve").description("Start a Node.js mock server").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--host <host>", "Hostname (default: localhost)").option("--port <port>", "Port (default: 8080)").option("--no-watch", "Disable file watching").option("--no-playground", "Disable Playground").option("--no-log", "Disable logging").action(async (options) => {
844
+ program.command("serve").description("Start a Node.js mock server").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--ignore-prefix <prefix>", "Ignore path segment prefix (repeatable)", collectValues).option("--host <host>", "Hostname (default: localhost)").option("--port <port>", "Port (default: 8080)").option("--no-watch", "Disable file watching").option("--no-playground", "Disable Playground").option("--no-log", "Disable logging").action(async (options) => {
806
845
  const serveOptions = toServeOptions(options);
807
846
  const host = serveOptions.host ?? "localhost";
808
847
  const port = serveOptions.port ?? 8080;
809
848
  const playgroundEnabled = serveOptions.playground !== false;
810
849
  const playgroundPath = "/_mokup";
811
850
  const server$1 = await server.createFetchServer(serveOptions);
812
- const nodeServer$1 = nodeServer.serve(
851
+ const nodeServer = node.serve(
813
852
  {
814
853
  fetch: server$1.fetch,
815
854
  hostname: host,
@@ -824,13 +863,14 @@ function createCli() {
824
863
  }
825
864
  }
826
865
  );
866
+ server$1.injectWebSocket?.(nodeServer);
827
867
  const shutdown = async () => {
828
868
  try {
829
869
  if (server$1.close) {
830
870
  await server$1.close();
831
871
  }
832
872
  await new Promise((resolve, reject) => {
833
- nodeServer$1.close((error) => {
873
+ nodeServer.close((error) => {
834
874
  if (error) {
835
875
  reject(error);
836
876
  return;
package/dist/index.d.cts CHANGED
@@ -7,6 +7,7 @@ interface BuildOptions {
7
7
  prefix?: string;
8
8
  include?: RegExp | RegExp[];
9
9
  exclude?: RegExp | RegExp[];
10
+ ignorePrefix?: string | string[];
10
11
  handlers?: boolean;
11
12
  root?: string;
12
13
  log?: (message: string) => void;
package/dist/index.d.mts CHANGED
@@ -7,6 +7,7 @@ interface BuildOptions {
7
7
  prefix?: string;
8
8
  include?: RegExp | RegExp[];
9
9
  exclude?: RegExp | RegExp[];
10
+ ignorePrefix?: string | string[];
10
11
  handlers?: boolean;
11
12
  root?: string;
12
13
  log?: (message: string) => void;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ interface BuildOptions {
7
7
  prefix?: string;
8
8
  include?: RegExp | RegExp[];
9
9
  exclude?: RegExp | RegExp[];
10
+ ignorePrefix?: string | string[];
10
11
  handlers?: boolean;
11
12
  root?: string;
12
13
  log?: (message: string) => void;
package/dist/index.mjs CHANGED
@@ -1,14 +1,14 @@
1
1
  import { promises } from 'node:fs';
2
2
  import process, { cwd } from 'node:process';
3
- import { join, normalize, dirname, resolve, isAbsolute, basename, extname, relative } from '@mokup/shared/pathe';
3
+ import { join, normalize, dirname, resolve, isAbsolute, relative, basename, extname } from '@mokup/shared/pathe';
4
4
  import { Buffer } from 'node:buffer';
5
5
  import { createRequire } from 'node:module';
6
6
  import { pathToFileURL } from 'node:url';
7
7
  import { build } from '@mokup/shared/esbuild';
8
8
  import { parseRouteTemplate, compareRouteScore } from '@mokup/runtime';
9
9
  import { parse } from '@mokup/shared/jsonc-parser';
10
- import { serve } from '@hono/node-server';
11
10
  import { createFetchServer } from '@mokup/server';
11
+ import { serve } from '@mokup/server/node';
12
12
  import { Command } from 'commander';
13
13
 
14
14
  async function writeBundle(outDir, hasHandlers) {
@@ -188,6 +188,15 @@ async function resolveDirectoryConfig(params) {
188
188
  if (typeof config.enabled === "boolean") {
189
189
  merged.enabled = config.enabled;
190
190
  }
191
+ if (typeof config.ignorePrefix !== "undefined") {
192
+ merged.ignorePrefix = config.ignorePrefix;
193
+ }
194
+ if (typeof config.include !== "undefined") {
195
+ merged.include = config.include;
196
+ }
197
+ if (typeof config.exclude !== "undefined") {
198
+ merged.exclude = config.exclude;
199
+ }
191
200
  const normalized = normalizeMiddlewares(config.middleware, configPath, log);
192
201
  if (normalized.length > 0) {
193
202
  merged.middlewares.push(...normalized);
@@ -264,6 +273,20 @@ function matchesFilter(file, include, exclude) {
264
273
  }
265
274
  return true;
266
275
  }
276
+ function normalizeIgnorePrefix(value, fallback = ["."]) {
277
+ const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
278
+ return list.filter((entry) => typeof entry === "string" && entry.length > 0);
279
+ }
280
+ function hasIgnoredPrefix(file, rootDir, prefixes) {
281
+ if (prefixes.length === 0) {
282
+ return false;
283
+ }
284
+ const relativePath = toPosix(relative(rootDir, file));
285
+ const segments = relativePath.split("/");
286
+ return segments.some(
287
+ (segment) => prefixes.some((prefix) => segment.startsWith(prefix))
288
+ );
289
+ }
267
290
  function isSupportedFile(file) {
268
291
  if (file.endsWith(".d.ts")) {
269
292
  return false;
@@ -585,13 +608,8 @@ async function buildManifest(options = {}) {
585
608
  const handlerModuleMap = /* @__PURE__ */ new Map();
586
609
  const configCache = /* @__PURE__ */ new Map();
587
610
  const configFileCache = /* @__PURE__ */ new Map();
611
+ const globalIgnorePrefix = normalizeIgnorePrefix(options.ignorePrefix);
588
612
  for (const fileInfo of files) {
589
- if (!isSupportedFile(fileInfo.file)) {
590
- continue;
591
- }
592
- if (!matchesFilter(fileInfo.file, options.include, options.exclude)) {
593
- continue;
594
- }
595
613
  const configParams = {
596
614
  file: fileInfo.file,
597
615
  rootDir: fileInfo.rootDir,
@@ -605,6 +623,18 @@ async function buildManifest(options = {}) {
605
623
  if (config.enabled === false) {
606
624
  continue;
607
625
  }
626
+ const effectiveIgnorePrefix = typeof config.ignorePrefix !== "undefined" ? normalizeIgnorePrefix(config.ignorePrefix, []) : globalIgnorePrefix;
627
+ if (hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix)) {
628
+ continue;
629
+ }
630
+ if (!isSupportedFile(fileInfo.file)) {
631
+ continue;
632
+ }
633
+ const effectiveInclude = typeof config.include !== "undefined" ? config.include : options.include;
634
+ const effectiveExclude = typeof config.exclude !== "undefined" ? config.exclude : options.exclude;
635
+ if (!matchesFilter(fileInfo.file, effectiveInclude, effectiveExclude)) {
636
+ continue;
637
+ }
608
638
  const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, options.log);
609
639
  if (!derived) {
610
640
  continue;
@@ -614,6 +644,9 @@ async function buildManifest(options = {}) {
614
644
  if (!rule || typeof rule !== "object") {
615
645
  continue;
616
646
  }
647
+ if (rule.enabled === false) {
648
+ continue;
649
+ }
617
650
  const ruleValue = rule;
618
651
  const unsupportedKeys = ["response", "url", "method"].filter(
619
652
  (key2) => key2 in ruleValue
@@ -754,6 +787,9 @@ function toBuildOptions(options) {
754
787
  if (options.exclude && options.exclude.length > 0) {
755
788
  buildOptions.exclude = options.exclude;
756
789
  }
790
+ if (options.ignorePrefix && options.ignorePrefix.length > 0) {
791
+ buildOptions.ignorePrefix = options.ignorePrefix;
792
+ }
757
793
  return buildOptions;
758
794
  }
759
795
  function toServeOptions(options) {
@@ -773,6 +809,9 @@ function toServeOptions(options) {
773
809
  if (options.exclude && options.exclude.length > 0) {
774
810
  serveOptions.exclude = options.exclude;
775
811
  }
812
+ if (options.ignorePrefix && options.ignorePrefix.length > 0) {
813
+ serveOptions.ignorePrefix = options.ignorePrefix;
814
+ }
776
815
  if (options.host) {
777
816
  serveOptions.host = options.host;
778
817
  }
@@ -791,11 +830,11 @@ function toServeOptions(options) {
791
830
  function createCli() {
792
831
  const program = new Command();
793
832
  program.name("mokup").description("Mock utilities for file-based routes.").showHelpAfterError();
794
- program.command("build").description("Generate .mokup build output").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("-o, --out <dir>", "Output directory (default: .mokup)").option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--no-handlers", "Skip function handler output").action(async (options) => {
833
+ program.command("build").description("Generate .mokup build output").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("-o, --out <dir>", "Output directory (default: .mokup)").option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--ignore-prefix <prefix>", "Ignore path segment prefix (repeatable)", collectValues).option("--no-handlers", "Skip function handler output").action(async (options) => {
795
834
  const buildOptions = toBuildOptions(options);
796
835
  await buildManifest(buildOptions);
797
836
  });
798
- program.command("serve").description("Start a Node.js mock server").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--host <host>", "Hostname (default: localhost)").option("--port <port>", "Port (default: 8080)").option("--no-watch", "Disable file watching").option("--no-playground", "Disable Playground").option("--no-log", "Disable logging").action(async (options) => {
837
+ program.command("serve").description("Start a Node.js mock server").option("-d, --dir <dir>", "Mock directory (repeatable)", collectValues).option("--prefix <prefix>", "URL prefix").option("--include <pattern>", "Include regex (repeatable)", collectRegex).option("--exclude <pattern>", "Exclude regex (repeatable)", collectRegex).option("--ignore-prefix <prefix>", "Ignore path segment prefix (repeatable)", collectValues).option("--host <host>", "Hostname (default: localhost)").option("--port <port>", "Port (default: 8080)").option("--no-watch", "Disable file watching").option("--no-playground", "Disable Playground").option("--no-log", "Disable logging").action(async (options) => {
799
838
  const serveOptions = toServeOptions(options);
800
839
  const host = serveOptions.host ?? "localhost";
801
840
  const port = serveOptions.port ?? 8080;
@@ -817,6 +856,7 @@ function createCli() {
817
856
  }
818
857
  }
819
858
  );
859
+ server.injectWebSocket?.(nodeServer);
820
860
  const shutdown = async () => {
821
861
  try {
822
862
  if (server.close) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mokup/cli",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
5
  "description": "CLI for building mokup manifests and handlers.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://mokup.icebreaker.top",
@@ -27,14 +27,13 @@
27
27
  "dist"
28
28
  ],
29
29
  "dependencies": {
30
- "@hono/node-server": "^1.19.9",
31
30
  "commander": "^14.0.0",
32
31
  "@mokup/runtime": "1.0.0",
33
- "@mokup/server": "1.0.2",
32
+ "@mokup/server": "1.0.4",
34
33
  "@mokup/shared": "1.0.0"
35
34
  },
36
35
  "devDependencies": {
37
- "@types/node": "^25.0.9",
36
+ "@types/node": "^25.0.10",
38
37
  "typescript": "^5.9.3",
39
38
  "unbuild": "^3.6.1"
40
39
  },