@typescriptprime/parsing 1.0.0 → 1.0.1
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 +145 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
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> =
|
|
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,
|
|
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,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typescriptprime/parsing",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build:esbuild": "esbuild sources/index.ts --bundle --format=esm --splitting --sourcemap --target=es2024 --external:/node_modules --outdir=dist",
|
|
7
7
|
"build:tsc": "tsc sources/index.ts --outDir dist/types --declaration --emitDeclarationOnly",
|