@typescriptprime/parsing 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/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # @typescriptprime/parsing
2
+
3
+ Lightweight helper utilities for parsing CLI-style arguments, implemented in TypeScript.
4
+
5
+ This package provides two small helpers:
6
+
7
+ - `PreProcessing` — trims `process.argv` to remove the node executable and optional script filename, returning the array of option tokens.
8
+ - `PostProcessing` — parses the token list that looks like `--Name Value` into a typed options object and an array of positional arguments (everything after `--`).
9
+
10
+ ---
11
+
12
+ ## 📦 Install
13
+
14
+ ```bash
15
+ npm install @typescriptprime/parsing
16
+ ```
17
+
18
+ > [!NOTE]
19
+ > This repo is authored as an ES module and fully typed with TypeScript.
20
+
21
+ ---
22
+
23
+ ## Usage
24
+
25
+ Import the helpers from the package and combine them to parse `process.argv`:
26
+
27
+ ```typescript
28
+ import { PreProcessing, PostProcessing } from '@typescriptprime/parsing'
29
+
30
+ async function Main(Argv: string[]) {
31
+ // Step 1: Trim the node executable and optional script path
32
+ const Filtered = PreProcessing(Argv)
33
+
34
+ // Step 2: Parse CLI-style parameters into an options object and positional arguments
35
+ const { Options, Positional } = await PostProcessing(Filtered)
36
+
37
+ console.log('Options:', Options)
38
+ console.log('Positional args:', Positional)
39
+ }
40
+
41
+ Main(process.argv)
42
+ ```
43
+
44
+ ### Naming Convention
45
+
46
+ By default, `PostProcessing` converts parameter names into PascalCase using `es-toolkit` (so `--parameter-name` becomes `ParameterName`). You can supply a custom `NamingConvention` function via `IParsingOptions`:
47
+
48
+ ```typescript
49
+ import * as ESToolkit from 'es-toolkit'
50
+
51
+ await PostProcessing(argv, { NamingConvention: ESToolkit.camelCase })
52
+ // or custom:
53
+ await PostProcessing(argv, { NamingConvention: (s) => s.replace(/^--/, '') })
54
+ ```
55
+
56
+ ---
57
+
58
+ ## ⚡ Quick Examples
59
+
60
+ From `process.argv` in Node.js:
61
+
62
+ ```typescript
63
+ const Argv = ['/usr/local/bin/node', '/path/to/script.js', '--enable-feature', '--parameter', 'value', '--', 'positional1', 'positional2']
64
+
65
+ const Tokens = PreProcessing(Argv)
66
+ // tokens === ['--enable-feature', '--parameter', 'value', '--', 'positional1', 'positional2']
67
+
68
+ const { Options, Positional } = await PostProcessing(Tokens)
69
+ // Options === { EnableFeature: true, Parameter: 'value' }
70
+ // Positional === ['positional1', 'positional2']
71
+ ```
72
+
73
+ Boolean flags example:
74
+
75
+ ```ts
76
+ const Tokens = PreProcessing(['/usr/bin/node', '/script.js', '--flag', '--other', 'value'])
77
+ // tokens === ['--flag', '--other', 'value']
78
+ const { Options } = await PostProcessing(Tokens)
79
+ // Options === { Flag: true, Other: 'value' }
80
+ ```
81
+
82
+ ---
83
+
84
+ ## API
85
+
86
+ - `PreProcessing(argv: typeof process.argv): string[]`
87
+ - Removes the node executable and optional file argument and returns the tokens starting at the first option.
88
+
89
+ - `PostProcessing<I extends JSONValue>(Args: string[], FuncOptions?: IParsingOptions): Promise<{ Options: I, Positional: string[] }>`
90
+ - Converts `--key value` pairs into a typed `Options` object; flags without values are treated as `true`.
91
+ - Stops parsing options when it hits `--` and returns the rest as `Positional` arguments.
92
+
93
+ ### Types
94
+
95
+ - `JSONValue`, `JSONObject`, `JSONArray`, `JSONPrimitive` — standard JSON type helpers
96
+ - `IParsingOptions` — currently supports:
97
+ - `NamingConvention?: (PropertyName: string) => string | Promise<string>`
98
+
99
+ ---
100
+
101
+ ## Scripts
102
+
103
+ - `npm run build` — runs: `esbuild` to bundle the compiled JS and TypeScript compiler to emit declarations.
104
+ - `npm test` — runs AVA tests.
105
+ - `npm run lint` — runs ESLint checks.
106
+
107
+ This project is published as an ES module. If you are developing locally, the following commands are useful:
108
+
109
+ - `npm run build:esbuild` — bundle with esbuild (JS output)
110
+ - `npm run build:tsc` — emit TypeScript declarations only
111
+
112
+ The package `exports` are configured in `package.json` so importing the default entry works with ESM loaders.
113
+
114
+ ---
115
+
116
+ ## Tests
117
+
118
+ The `tests/` directory contains unit tests for both `PreProcessing` and `PostProcessing` with AVA. They include:
119
+
120
+ - PreProcessing: removes node executable and file name using different `process.argv` shapes
121
+ - PostProcessing: parsing single/two parameters, boolean flags, and the `--` positional argument separator.
122
+
123
+ Run tests with:
124
+
125
+ ```bash
126
+ npm test
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Project Layout
132
+
133
+ - `sources/` — TypeScript source files for the package
134
+ - `index.ts` — entry exports
135
+ - `preprocessing/index.ts` — `PreProcessing` implementation
136
+ - `postprocessing/index.ts` — `PostProcessing` implementation
137
+ - `types.ts` — JSON types and `IParsingOptions`
138
+ - `dist/` — build output (ignored in source control)
139
+ - `tests/` — unit tests using AVA
140
+
141
+ ---
142
+
143
+ ## License
144
+
145
+ Licensed under the Apache-2.0 license — see `LICENSE` for details.
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ function pascalCase(str) {
19
19
  async function PostProcessing(Args, FuncOptions = {
20
20
  NamingConvention: pascalCase
21
21
  }) {
22
- const Options = {};
22
+ const Options = /* @__PURE__ */ Object.create(null);
23
23
  const Positional = [];
24
24
  for (let I = 0; I < Args.length; I++) {
25
25
  if (Args[I] === "--") {
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../node_modules/es-toolkit/dist/string/capitalize.mjs", "../node_modules/es-toolkit/dist/string/words.mjs", "../node_modules/es-toolkit/dist/string/pascalCase.mjs", "../sources/postprocessing/index.ts", "../sources/preprocessing/index.ts"],
4
- "sourcesContent": ["function capitalize(str) {\n return (str.charAt(0).toUpperCase() + str.slice(1).toLowerCase());\n}\n\nexport { capitalize };\n", "const CASE_SPLIT_PATTERN = /\\p{Lu}?\\p{Ll}+|[0-9]+|\\p{Lu}+(?!\\p{Ll})|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}|\\p{L}+/gu;\nfunction words(str) {\n return Array.from(str.match(CASE_SPLIT_PATTERN) ?? []);\n}\n\nexport { CASE_SPLIT_PATTERN, words };\n", "import { capitalize } from './capitalize.mjs';\nimport { words } from './words.mjs';\n\nfunction pascalCase(str) {\n const words$1 = words(str);\n return words$1.map(word => capitalize(word)).join('');\n}\n\nexport { pascalCase };\n", "import * as ESToolkit from 'es-toolkit'\nimport type { JSONValue, IParsingOptions } from '../types.js'\n\n/**\n * Parses a list of CLI-style arguments into a structured options object and positional arguments.\n *\n * @typeParam I - The shape of the options object produced from the parsed arguments.\n * @param Args - The raw argument tokens, including option flags and positional values.\n * @param FuncOptions - Configuration for post-processing behavior, such as the naming convention transformer.\n * @returns A promise resolving to an object containing the parsed options and remaining positional arguments.\n */\nexport async function PostProcessing<I extends JSONValue>(Args: string[], FuncOptions: IParsingOptions = {\n NamingConvention: ESToolkit.pascalCase\n}): Promise<{ Options: I, Positional: string[] }> {\n const Options: Record<string, boolean | string> = {}\n const Positional: string[] = []\n\n for (let I = 0; I < Args.length; I++) {\n if (Args[I] === '--') {\n Positional.push(...Args.slice(I + 1))\n break\n }\n\n if (Args[I].startsWith('--')) {\n if (I + 1 === Args.length || Args[I + 1].startsWith('--')) {\n Options[await FuncOptions.NamingConvention(Args[I])] = true\n } else {\n Options[await FuncOptions.NamingConvention(Args[I])] = Args[I + 1]\n I++\n }\n }\n }\n\n return { Options: Options as I, Positional }\n}", "import type * as Process from 'node:process'\n\ntype DropFirstANDTwo<T extends readonly unknown[]> = T extends readonly [unknown, unknown, ...infer Tail] ? Tail : []\ntype DropFirst<T extends readonly unknown[]> = T extends readonly [unknown, ...infer Tail] ? Tail : []\n\n/**\n * Returns a filtered `process.argv` with only options and their values.\n * \n * @param {string} Args - A value of `process.argv`.\n * @returns A filtered `process.argv` with only options and their values.\n */\nexport function PreProcessing<Args extends typeof Process.argv>(Args: Args): DropFirstANDTwo<Args> | DropFirst<Args> {\n if (Args[2].startsWith('--')) {\n return Args.slice(2) as DropFirstANDTwo<Args>\n } else {\n return Args.slice(1) as DropFirst<Args>\n }\n}"],
5
- "mappings": ";AAAA,SAAS,WAAW,KAAK;AACrB,SAAQ,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,EAAE,YAAY;AACnE;;;ACFA,IAAM,qBAAqB;AAC3B,SAAS,MAAM,KAAK;AAChB,SAAO,MAAM,KAAK,IAAI,MAAM,kBAAkB,KAAK,CAAC,CAAC;AACzD;;;ACAA,SAAS,WAAW,KAAK;AACrB,QAAM,UAAU,MAAM,GAAG;AACzB,SAAO,QAAQ,IAAI,UAAQ,WAAW,IAAI,CAAC,EAAE,KAAK,EAAE;AACxD;;;ACKA,eAAsB,eAAoC,MAAgB,cAA+B;AAAA,EACvG,kBAA4B;AAC9B,GAAkD;AAChD,QAAM,UAA4C,CAAC;AACnD,QAAM,aAAuB,CAAC;AAE9B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,CAAC,MAAM,MAAM;AACpB,iBAAW,KAAK,GAAG,KAAK,MAAM,IAAI,CAAC,CAAC;AACpC;AAAA,IACF;AAEA,QAAI,KAAK,CAAC,EAAE,WAAW,IAAI,GAAG;AAC5B,UAAI,IAAI,MAAM,KAAK,UAAU,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,GAAG;AACzD,gBAAQ,MAAM,YAAY,iBAAiB,KAAK,CAAC,CAAC,CAAC,IAAI;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAM,YAAY,iBAAiB,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;AACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAuB,WAAW;AAC7C;;;ACvBO,SAAS,cAAgD,MAAqD;AACnH,MAAI,KAAK,CAAC,EAAE,WAAW,IAAI,GAAG;AAC5B,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB,OAAO;AACL,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB;AACF;",
4
+ "sourcesContent": ["function capitalize(str) {\n return (str.charAt(0).toUpperCase() + str.slice(1).toLowerCase());\n}\n\nexport { capitalize };\n", "const CASE_SPLIT_PATTERN = /\\p{Lu}?\\p{Ll}+|[0-9]+|\\p{Lu}+(?!\\p{Ll})|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}|\\p{L}+/gu;\nfunction words(str) {\n return Array.from(str.match(CASE_SPLIT_PATTERN) ?? []);\n}\n\nexport { CASE_SPLIT_PATTERN, words };\n", "import { capitalize } from './capitalize.mjs';\nimport { words } from './words.mjs';\n\nfunction pascalCase(str) {\n const words$1 = words(str);\n return words$1.map(word => capitalize(word)).join('');\n}\n\nexport { pascalCase };\n", "import * as ESToolkit from 'es-toolkit'\nimport type { JSONValue, IParsingOptions } from '../types.js'\n\n/**\n * Parses a list of CLI-style arguments into a structured options object and positional arguments.\n *\n * @typeParam I - The shape of the options object produced from the parsed arguments.\n * @param Args - The raw argument tokens, including option flags and positional values.\n * @param FuncOptions - Configuration for post-processing behavior, such as the naming convention transformer.\n * @returns A promise resolving to an object containing the parsed options and remaining positional arguments.\n */\nexport async function PostProcessing<I extends JSONValue>(Args: string[], FuncOptions: IParsingOptions = {\n NamingConvention: ESToolkit.pascalCase\n}): Promise<{ Options: I, Positional: string[] }> {\n const Options: Record<string, boolean | string> = Object.create(null)\n const Positional: string[] = []\n\n for (let I = 0; I < Args.length; I++) {\n if (Args[I] === '--') {\n Positional.push(...Args.slice(I + 1))\n break\n }\n\n if (Args[I].startsWith('--')) {\n if (I + 1 === Args.length || Args[I + 1].startsWith('--')) {\n Options[await FuncOptions.NamingConvention(Args[I])] = true\n } else {\n Options[await FuncOptions.NamingConvention(Args[I])] = Args[I + 1]\n I++\n }\n }\n }\n\n return { Options: Options as I, Positional }\n}", "import type * as Process from 'node:process'\n\ntype DropFirstANDTwo<T extends readonly unknown[]> = T extends readonly [unknown, unknown, ...infer Tail] ? Tail : []\ntype DropFirst<T extends readonly unknown[]> = T extends readonly [unknown, ...infer Tail] ? Tail : []\n\n/**\n * Returns a filtered `process.argv` with only options and their values.\n * \n * @param {string} Args - A value of `process.argv`.\n * @returns A filtered `process.argv` with only options and their values.\n */\nexport function PreProcessing<Args extends typeof Process.argv>(Args: Args): DropFirstANDTwo<Args> | DropFirst<Args> {\n if (Args[2].startsWith('--')) {\n return Args.slice(2) as DropFirstANDTwo<Args>\n } else {\n return Args.slice(1) as DropFirst<Args>\n }\n}"],
5
+ "mappings": ";AAAA,SAAS,WAAW,KAAK;AACrB,SAAQ,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,EAAE,YAAY;AACnE;;;ACFA,IAAM,qBAAqB;AAC3B,SAAS,MAAM,KAAK;AAChB,SAAO,MAAM,KAAK,IAAI,MAAM,kBAAkB,KAAK,CAAC,CAAC;AACzD;;;ACAA,SAAS,WAAW,KAAK;AACrB,QAAM,UAAU,MAAM,GAAG;AACzB,SAAO,QAAQ,IAAI,UAAQ,WAAW,IAAI,CAAC,EAAE,KAAK,EAAE;AACxD;;;ACKA,eAAsB,eAAoC,MAAgB,cAA+B;AAAA,EACvG,kBAA4B;AAC9B,GAAkD;AAChD,QAAM,UAA4C,uBAAO,OAAO,IAAI;AACpE,QAAM,aAAuB,CAAC;AAE9B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,CAAC,MAAM,MAAM;AACpB,iBAAW,KAAK,GAAG,KAAK,MAAM,IAAI,CAAC,CAAC;AACpC;AAAA,IACF;AAEA,QAAI,KAAK,CAAC,EAAE,WAAW,IAAI,GAAG;AAC5B,UAAI,IAAI,MAAM,KAAK,UAAU,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,GAAG;AACzD,gBAAQ,MAAM,YAAY,iBAAiB,KAAK,CAAC,CAAC,CAAC,IAAI;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAM,YAAY,iBAAiB,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;AACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAuB,WAAW;AAC7C;;;ACvBO,SAAS,cAAgD,MAAqD;AACnH,MAAI,KAAK,CAAC,EAAE,WAAW,IAAI,GAAG;AAC5B,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB,OAAO;AACL,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB;AACF;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "@typescriptprime/parsing",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
+ "description": "Lightweight helper utilities for parsing CLI-style arguments, implemented in TypeScript",
6
+ "keywords": [
7
+ "cli",
8
+ "helper",
9
+ "utilities",
10
+ "ci"
11
+ ],
5
12
  "scripts": {
6
13
  "build:esbuild": "esbuild sources/index.ts --bundle --format=esm --splitting --sourcemap --target=es2024 --external:/node_modules --outdir=dist",
7
14
  "build:tsc": "tsc sources/index.ts --outDir dist/types --declaration --emitDeclarationOnly",