cli-argv-util 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022-2025 Individual contributors to cli-argv-util
3
+ Copyright (c) 2022-2026 Individual contributors to cli-argv-util
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -33,7 +33,7 @@ if (cli.flagOn.noSummary)
33
33
  console.info('You supplied', cli.params.length , 'CLI parameter(s).');
34
34
  ```
35
35
  For a real world example, see:
36
- [cli.js](https://github.com/center-key/copy-file-util/blob/main/bin/cli.js)
36
+ [copy-file.ts](https://github.com/center-key/copy-file-util/blob/main/src/copy-file.ts)
37
37
 
38
38
  If your CLI tool is named `my-program` and a user runs it like:
39
39
  ```shell
@@ -45,6 +45,9 @@ the resulting `cli` object will be:
45
45
  flagMap: {
46
46
  cd: 'src',
47
47
  },
48
+ flagMapRaw: {
49
+ cd: 'src',
50
+ },
48
51
  flagOn: {
49
52
  cd: true,
50
53
  find: false,
@@ -58,13 +61,18 @@ the resulting `cli` object will be:
58
61
  > [!NOTE]
59
62
  > _Single quotes in commands are normalized so they work cross-platform and avoid the errors often encountered on Microsoft Windows._
60
63
 
64
+ > [!NOTE]
65
+ > _CLI flag values support escaped charcters and macros._<br>
66
+ > _For documentation, see:_ https://github.com/center-key/replacer-util
67
+
61
68
  ## C) Results
62
69
  The `cliArgvUtil.parse()` returns an object of type `Result`:
63
70
  ```typescript
64
71
  export type StringFlagMap = { [flag: string]: string | undefined };
65
72
  export type BooleanFlagMap = { [flag: string]: boolean };
66
73
  export type Result = {
67
- flagMap: StringFlagMap, //map of flag values for each user supplied flag
74
+ flagMap: StringFlagMap, //map of unescaped flag values for each user supplied flag
75
+ flagMapRaw: StringFlagMap, //map of flag values for each user supplied flag
68
76
  flagOn: BooleanFlagMap, //map of the enabled status for all valid flags
69
77
  invalidFlag: string | null, //name of the first invalid flag
70
78
  invalidFlagMsg: string | null, //error message for the invalid flag
@@ -1,4 +1,4 @@
1
- //! cli-argv-util v1.4.0 ~~ https://github.com/center-key/cli-argv-util ~~ MIT License
1
+ //! cli-argv-util v1.5.0 ~~ https://github.com/center-key/cli-argv-util ~~ MIT License
2
2
 
3
3
  export type StringFlagMap = {
4
4
  [flag: string]: string | undefined;
@@ -10,17 +10,27 @@ export type Ancestor = {
10
10
  common: string;
11
11
  source: string;
12
12
  target: string;
13
+ renamed: boolean;
14
+ filename: string | null;
13
15
  message: string;
14
16
  };
15
17
  export type Result = {
16
18
  flagMap: StringFlagMap;
19
+ flagMapRaw: StringFlagMap;
17
20
  flagOn: BooleanFlagMap;
18
21
  invalidFlag: string | null;
19
22
  invalidFlagMsg: string | null;
20
- params: string[];
21
23
  paramCount: number;
24
+ params: string[];
25
+ };
26
+ type Json = string | number | boolean | null | undefined | JsonObject | Json[];
27
+ type JsonObject = {
28
+ [key: string]: Json;
22
29
  };
23
30
  declare const cliArgvUtil: {
31
+ assert(ok: unknown, message: string | null): void;
32
+ readPackageJson(): JsonObject | null;
33
+ unescape(flags: StringFlagMap): StringFlagMap;
24
34
  parse(validFlags: string[]): Result;
25
35
  run(packageJson: {
26
36
  [key: string]: unknown;
@@ -1,4 +1,4 @@
1
- //! cli-argv-util v1.4.0 ~~ https://github.com/center-key/cli-argv-util ~~ MIT License
1
+ //! cli-argv-util v1.5.0 ~~ https://github.com/center-key/cli-argv-util ~~ MIT License
2
2
 
3
3
  import { execSync } from 'node:child_process';
4
4
  import chalk from 'chalk';
@@ -6,6 +6,60 @@ import fs from 'fs';
6
6
  import path from 'path';
7
7
  import slash from 'slash';
8
8
  const cliArgvUtil = {
9
+ assert(ok, message) {
10
+ if (!ok)
11
+ throw new Error(`[replacer-util] ${message}`);
12
+ },
13
+ readPackageJson() {
14
+ const pkgExists = fs.existsSync('package.json');
15
+ const pkg = pkgExists ? JSON.parse(fs.readFileSync('package.json', 'utf-8')) : null;
16
+ const fixHiddenKeys = (pkgObj) => {
17
+ const unhide = (key) => {
18
+ const newKey = key.replace(/[@./]/g, '-');
19
+ if (!pkgObj[newKey])
20
+ pkgObj[newKey] = pkgObj[key];
21
+ };
22
+ Object.keys(pkgObj).forEach(unhide);
23
+ };
24
+ if (pkg?.dependencies)
25
+ fixHiddenKeys(pkg.dependencies);
26
+ if (pkg?.devDependencies)
27
+ fixHiddenKeys(pkg.devDependencies);
28
+ return pkg;
29
+ },
30
+ unescape(flags) {
31
+ const escapers = [
32
+ [/{{apos}}/g, "'"],
33
+ [/{{bang}}/g, '!'],
34
+ [/{{close-curly}}/g, '}'],
35
+ [/{{equals}}/g, '='],
36
+ [/{{gt}}/g, '>'],
37
+ [/{{hash}}/g, '#'],
38
+ [/{{lt}}/g, '<'],
39
+ [/{{open-curly}}/g, '{'],
40
+ [/{{pipe}}/g, '|'],
41
+ [/{{quote}}/g, '"'],
42
+ [/{{semi}}/g, ';'],
43
+ [/{{space}}/g, ' '],
44
+ ];
45
+ const macroPattern = /^{{macro:(.*)}}$/;
46
+ const flagEntries = Object.entries(flags);
47
+ const usesMacros = flagEntries.some(entry => entry[1]?.match(macroPattern));
48
+ const pkg = usesMacros ? cliArgvUtil.readPackageJson() : {};
49
+ if (!pkg.cliConfig && pkg.replacerConfig)
50
+ pkg.cliConfig = pkg.replacerConfig;
51
+ const macros = pkg.cliConfig?.macros;
52
+ const unescapeOne = (flagValue, escaper) => flagValue.replace(escaper[0], escaper[1]);
53
+ const expandMacro = (flagValue) => {
54
+ const macroName = flagValue.match(macroPattern)?.[1];
55
+ const macroValue = macros?.[macroName];
56
+ const missing = macroName && !macroValue;
57
+ cliArgvUtil.assert(!missing, `Macro "${macroName}" used but not defined in package.json`);
58
+ return macroName ? macroValue : flagValue;
59
+ };
60
+ const doReplacements = (flagValue) => !flagValue ? undefined : escapers.reduce(unescapeOne, expandMacro(flagValue));
61
+ return Object.fromEntries(flagEntries.map(pair => [pair[0], doReplacements(pair[1])]));
62
+ },
9
63
  parse(validFlags) {
10
64
  const toCamel = (token) => token.replace(/-./g, char => char[1].toUpperCase());
11
65
  const toEntry = (pair) => [toCamel(pair[0]), pair[1]];
@@ -19,7 +73,8 @@ const cliArgvUtil = {
19
73
  const helpMsg = '\nValid flags are --' + validFlags.join(' --');
20
74
  const params = args.filter(arg => !/^--/.test(arg));
21
75
  return {
22
- flagMap: flagMap,
76
+ flagMap: cliArgvUtil.unescape(flagMap),
77
+ flagMapRaw: flagMap,
23
78
  flagOn: flagOn,
24
79
  invalidFlag: invalidFlag,
25
80
  invalidFlagMsg: invalidFlag ? 'Invalid flag: --' + invalidFlag + helpMsg : null,
@@ -46,8 +101,12 @@ const cliArgvUtil = {
46
101
  const source = sourceFile.substring(len);
47
102
  const target = targetFile.substring(len);
48
103
  const intro = common ? chalk.blue(common) + chalk.gray.bold(': ') : '';
49
- const message = intro + chalk.white(source) + chalk.gray.bold(' → ') + chalk.green(target);
50
- return { common, source, target, message };
104
+ const renamed = path.basename(sourceFile) !== path.basename(targetFile);
105
+ const filename = renamed ? null : path.basename(sourceFile);
106
+ const folder = path.dirname(target);
107
+ const dest = renamed ? target : (folder === '.' ? filename : folder + '/');
108
+ const message = intro + chalk.white(source) + chalk.gray.bold(' → ') + chalk.green(dest);
109
+ return { common, source, target, renamed, filename, message };
51
110
  },
52
111
  unquoteArgs(args) {
53
112
  const unquote = (builder, nextArg) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-argv-util",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Simple utility to parse command line parameters and flags (arguments vector)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,6 +34,11 @@
34
34
  "node": true,
35
35
  "mocha": true
36
36
  },
37
+ "cliConfig": {
38
+ "macros": {
39
+ "lucky-number": "777"
40
+ }
41
+ },
37
42
  "runScriptsConfig": {
38
43
  "clean": [
39
44
  "rimraf build dist"
@@ -67,6 +72,6 @@
67
72
  "rimraf": "~6.1",
68
73
  "run-scripts-util": "~1.3",
69
74
  "typescript": "~5.9",
70
- "typescript-eslint": "~8.49"
75
+ "typescript-eslint": "~8.54"
71
76
  }
72
77
  }