@optique/run 0.5.0-dev.79 → 0.5.0-dev.82

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.
@@ -46,31 +46,34 @@ function path(options = {}) {
46
46
  parse(input) {
47
47
  if (extensions && extensions.length > 0) {
48
48
  const ext = (0, node_path.extname)(input);
49
- if (!extensions.includes(ext)) return {
50
- success: false,
51
- error: __optique_core_message.message`Expected file with extension ${(0, __optique_core_message.text)(extensions.join(", "))}, got ${(0, __optique_core_message.text)(ext || "no extension")}.`
52
- };
49
+ if (!extensions.includes(ext)) {
50
+ const actualExt = ext || "no extension";
51
+ return {
52
+ success: false,
53
+ error: options.errors?.invalidExtension ? typeof options.errors.invalidExtension === "function" ? options.errors.invalidExtension(input, extensions, actualExt) : options.errors.invalidExtension : __optique_core_message.message`Expected file with extension ${(0, __optique_core_message.text)(extensions.join(", "))}, got ${(0, __optique_core_message.text)(actualExt)}.`
54
+ };
55
+ }
53
56
  }
54
57
  if (mustExist) {
55
58
  if (!(0, node_fs.existsSync)(input)) return {
56
59
  success: false,
57
- error: __optique_core_message.message`Path ${(0, __optique_core_message.text)(input)} does not exist.`
60
+ error: options.errors?.pathNotFound ? typeof options.errors.pathNotFound === "function" ? options.errors.pathNotFound(input) : options.errors.pathNotFound : __optique_core_message.message`Path ${(0, __optique_core_message.text)(input)} does not exist.`
58
61
  };
59
62
  const stats = (0, node_fs.statSync)(input);
60
63
  if (type === "file" && !stats.isFile()) return {
61
64
  success: false,
62
- error: __optique_core_message.message`Expected a file, but ${(0, __optique_core_message.text)(input)} is not a file.`
65
+ error: options.errors?.notAFile ? typeof options.errors.notAFile === "function" ? options.errors.notAFile(input) : options.errors.notAFile : __optique_core_message.message`Expected a file, but ${(0, __optique_core_message.text)(input)} is not a file.`
63
66
  };
64
67
  if (type === "directory" && !stats.isDirectory()) return {
65
68
  success: false,
66
- error: __optique_core_message.message`Expected a directory, but ${(0, __optique_core_message.text)(input)} is not a directory.`
69
+ error: options.errors?.notADirectory ? typeof options.errors.notADirectory === "function" ? options.errors.notADirectory(input) : options.errors.notADirectory : __optique_core_message.message`Expected a directory, but ${(0, __optique_core_message.text)(input)} is not a directory.`
67
70
  };
68
71
  }
69
72
  if (allowCreate && !mustExist) {
70
73
  const parentDir = (0, node_path.dirname)(input);
71
74
  if (!(0, node_fs.existsSync)(parentDir)) return {
72
75
  success: false,
73
- error: __optique_core_message.message`Parent directory ${(0, __optique_core_message.text)(parentDir)} does not exist.`
76
+ error: options.errors?.parentNotFound ? typeof options.errors.parentNotFound === "function" ? options.errors.parentNotFound(parentDir) : options.errors.parentNotFound : __optique_core_message.message`Parent directory ${(0, __optique_core_message.text)(parentDir)} does not exist.`
74
77
  };
75
78
  }
76
79
  return {
@@ -1,3 +1,4 @@
1
+ import { Message } from "@optique/core/message";
1
2
  import { ValueParser } from "@optique/core/valueparser";
2
3
 
3
4
  //#region src/valueparser.d.ts
@@ -33,6 +34,42 @@ interface PathOptions {
33
34
  * start with a dot (e.g. `".json"`, `".yaml"`).
34
35
  */
35
36
  readonly extensions?: readonly string[];
37
+ /**
38
+ * Custom error messages for path validation failures.
39
+ * @since 0.5.0
40
+ */
41
+ readonly errors?: {
42
+ /**
43
+ * Custom error message when file extension is invalid.
44
+ * Can be a static message or a function that receives input, expected extensions, and actual extension.
45
+ * @since 0.5.0
46
+ */
47
+ invalidExtension?: Message | ((input: string, extensions: readonly string[], actualExtension: string) => Message);
48
+ /**
49
+ * Custom error message when path does not exist.
50
+ * Can be a static message or a function that receives the input path.
51
+ * @since 0.5.0
52
+ */
53
+ pathNotFound?: Message | ((input: string) => Message);
54
+ /**
55
+ * Custom error message when path is expected to be a file but isn't.
56
+ * Can be a static message or a function that receives the input path.
57
+ * @since 0.5.0
58
+ */
59
+ notAFile?: Message | ((input: string) => Message);
60
+ /**
61
+ * Custom error message when path is expected to be a directory but isn't.
62
+ * Can be a static message or a function that receives the input path.
63
+ * @since 0.5.0
64
+ */
65
+ notADirectory?: Message | ((input: string) => Message);
66
+ /**
67
+ * Custom error message when parent directory does not exist for new files.
68
+ * Can be a static message or a function that receives the parent directory path.
69
+ * @since 0.5.0
70
+ */
71
+ parentNotFound?: Message | ((parentDir: string) => Message);
72
+ };
36
73
  }
37
74
  /**
38
75
  * Creates a ValueParser for file system paths with validation options.
@@ -1,3 +1,4 @@
1
+ import { Message } from "@optique/core/message";
1
2
  import { ValueParser } from "@optique/core/valueparser";
2
3
 
3
4
  //#region src/valueparser.d.ts
@@ -33,6 +34,42 @@ interface PathOptions {
33
34
  * start with a dot (e.g. `".json"`, `".yaml"`).
34
35
  */
35
36
  readonly extensions?: readonly string[];
37
+ /**
38
+ * Custom error messages for path validation failures.
39
+ * @since 0.5.0
40
+ */
41
+ readonly errors?: {
42
+ /**
43
+ * Custom error message when file extension is invalid.
44
+ * Can be a static message or a function that receives input, expected extensions, and actual extension.
45
+ * @since 0.5.0
46
+ */
47
+ invalidExtension?: Message | ((input: string, extensions: readonly string[], actualExtension: string) => Message);
48
+ /**
49
+ * Custom error message when path does not exist.
50
+ * Can be a static message or a function that receives the input path.
51
+ * @since 0.5.0
52
+ */
53
+ pathNotFound?: Message | ((input: string) => Message);
54
+ /**
55
+ * Custom error message when path is expected to be a file but isn't.
56
+ * Can be a static message or a function that receives the input path.
57
+ * @since 0.5.0
58
+ */
59
+ notAFile?: Message | ((input: string) => Message);
60
+ /**
61
+ * Custom error message when path is expected to be a directory but isn't.
62
+ * Can be a static message or a function that receives the input path.
63
+ * @since 0.5.0
64
+ */
65
+ notADirectory?: Message | ((input: string) => Message);
66
+ /**
67
+ * Custom error message when parent directory does not exist for new files.
68
+ * Can be a static message or a function that receives the parent directory path.
69
+ * @since 0.5.0
70
+ */
71
+ parentNotFound?: Message | ((parentDir: string) => Message);
72
+ };
36
73
  }
37
74
  /**
38
75
  * Creates a ValueParser for file system paths with validation options.
@@ -45,31 +45,34 @@ function path(options = {}) {
45
45
  parse(input) {
46
46
  if (extensions && extensions.length > 0) {
47
47
  const ext = extname(input);
48
- if (!extensions.includes(ext)) return {
49
- success: false,
50
- error: message`Expected file with extension ${text(extensions.join(", "))}, got ${text(ext || "no extension")}.`
51
- };
48
+ if (!extensions.includes(ext)) {
49
+ const actualExt = ext || "no extension";
50
+ return {
51
+ success: false,
52
+ error: options.errors?.invalidExtension ? typeof options.errors.invalidExtension === "function" ? options.errors.invalidExtension(input, extensions, actualExt) : options.errors.invalidExtension : message`Expected file with extension ${text(extensions.join(", "))}, got ${text(actualExt)}.`
53
+ };
54
+ }
52
55
  }
53
56
  if (mustExist) {
54
57
  if (!existsSync(input)) return {
55
58
  success: false,
56
- error: message`Path ${text(input)} does not exist.`
59
+ error: options.errors?.pathNotFound ? typeof options.errors.pathNotFound === "function" ? options.errors.pathNotFound(input) : options.errors.pathNotFound : message`Path ${text(input)} does not exist.`
57
60
  };
58
61
  const stats = statSync(input);
59
62
  if (type === "file" && !stats.isFile()) return {
60
63
  success: false,
61
- error: message`Expected a file, but ${text(input)} is not a file.`
64
+ error: options.errors?.notAFile ? typeof options.errors.notAFile === "function" ? options.errors.notAFile(input) : options.errors.notAFile : message`Expected a file, but ${text(input)} is not a file.`
62
65
  };
63
66
  if (type === "directory" && !stats.isDirectory()) return {
64
67
  success: false,
65
- error: message`Expected a directory, but ${text(input)} is not a directory.`
68
+ error: options.errors?.notADirectory ? typeof options.errors.notADirectory === "function" ? options.errors.notADirectory(input) : options.errors.notADirectory : message`Expected a directory, but ${text(input)} is not a directory.`
66
69
  };
67
70
  }
68
71
  if (allowCreate && !mustExist) {
69
72
  const parentDir = dirname(input);
70
73
  if (!existsSync(parentDir)) return {
71
74
  success: false,
72
- error: message`Parent directory ${text(parentDir)} does not exist.`
75
+ error: options.errors?.parentNotFound ? typeof options.errors.parentNotFound === "function" ? options.errors.parentNotFound(parentDir) : options.errors.parentNotFound : message`Parent directory ${text(parentDir)} does not exist.`
73
76
  };
74
77
  }
75
78
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/run",
3
- "version": "0.5.0-dev.79+66aa8134",
3
+ "version": "0.5.0-dev.82+3a10f0da",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "sideEffects": false,
72
72
  "dependencies": {
73
- "@optique/core": "0.5.0-dev.79+66aa8134"
73
+ "@optique/core": "0.5.0-dev.82+3a10f0da"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@types/node": "^20.19.9",