argv-flags 0.2.1 → 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/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ ## 1.0.1 - 2026-01-30
4
+
5
+ - Publish a formal JSON Schema for ParseResult and add JSON-safe conversion helper.
6
+ - Add schema validation tests and expanded real-world parsing tests.
7
+
8
+ ## 1.0.0 - 2026-01-30
9
+
10
+ - Adopt ESM-only packaging and require Node.js >=24.
11
+ - Replace ad-hoc flag parsing with a schema-driven API.
12
+ - Return structured parse results (`values`, `present`, `issues`, `rest`, `unknown`) instead of sentinel `false`.
13
+ - Add explicit issue codes for machine-handling.
14
+ - Document deterministic parsing rules and migration steps.
package/README.md CHANGED
@@ -1,62 +1,193 @@
1
1
  # argv-flags
2
2
 
3
- Tiny helper for parsing simple CLI flags from `process.argv`.
3
+ Schema-driven CLI flag parsing for Node.js 24+. Deterministic rules, typed output, and a machine-consumable result model.
4
4
 
5
- ## Installation
5
+ ## Install
6
6
 
7
7
  ```sh
8
8
  npm install argv-flags
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Quick start
12
12
 
13
13
  ```js
14
- const parseFlag = require('argv-flags');
14
+ import { defineSchema, parseArgs, toJsonResult } from 'argv-flags';
15
15
 
16
- const name = parseFlag('--name', 'string');
17
- const enabled = parseFlag('--enabled', 'boolean');
18
- const count = parseFlag('--count', 'number');
19
- const items = parseFlag('--items', 'array');
16
+ const schema = defineSchema({
17
+ src: { type: 'string', flags: ['--src'], required: true },
18
+ dest: { type: 'string', flags: ['--dest'], required: true },
19
+ exclude: { type: 'array', flags: ['--exclude'], default: [] },
20
+ verbose: { type: 'boolean', flags: ['--verbose'], default: false }
21
+ });
22
+
23
+ const result = parseArgs(schema);
24
+
25
+ if (!result.ok) {
26
+ console.error(result.issues);
27
+ process.exitCode = 1;
28
+ }
29
+
30
+ console.log(result.values.src, result.values.dest);
31
+ ```
32
+
33
+ ## API
34
+
35
+ ```ts
36
+ defineSchema<T extends Schema>(schema: T): T
37
+ parseArgs<T extends Schema>(schema: T, options?: ParseOptions): ParseResult<T>
38
+ toJsonResult<T extends Schema>(result: ParseResult<T>): ParseResultJson
20
39
  ```
21
40
 
22
- ### Inline values
41
+ ### Schema
23
42
 
24
- Flags can be passed as `--flag=value` for string, number, boolean, and array types:
43
+ ```ts
44
+ type FlagType = 'string' | 'boolean' | 'number' | 'array';
25
45
 
26
- ```sh
27
- --enabled=false
28
- --count=5
29
- --items=a b
46
+ interface FlagSpec<T extends FlagType = FlagType> {
47
+ type: T;
48
+ flags: readonly string[];
49
+ required?: boolean;
50
+ default?: FlagValue<T>;
51
+ allowEmpty?: boolean;
52
+ allowNo?: boolean;
53
+ }
30
54
  ```
31
55
 
32
- ### Boolean flags
56
+ Notes:
57
+ - `flags` must include at least one flag token (`-x` or `--long`).
58
+ - `default` is cloned for arrays to avoid shared references.
59
+ - `allowNo` enables `--no-<flag>` for boolean specs (default: `true`).
60
+ - `allowEmpty` allows empty string/array values (default: `false`).
33
61
 
34
- Boolean flags accept explicit values when provided:
62
+ ### Parse options
35
63
 
36
- ```sh
37
- --enabled true
38
- --enabled false
64
+ ```ts
65
+ interface ParseOptions {
66
+ argv?: readonly string[];
67
+ allowUnknown?: boolean;
68
+ stopAtDoubleDash?: boolean;
69
+ }
39
70
  ```
40
71
 
41
- If no value is provided, the presence of the flag returns `true`.
72
+ - `argv`: defaults to `process.argv.slice(2)`.
73
+ - `allowUnknown`: when `true`, unknown flags are collected instead of erroring.
74
+ - `stopAtDoubleDash`: when `true` (default), `--` stops flag parsing and the rest is returned as `rest`.
75
+
76
+ ## Output contract (machine-readable)
77
+
78
+ ```ts
79
+ interface ParseResult<S extends Schema> {
80
+ values: { [K in keyof S]: FlagValue<S[K]['type']> | undefined };
81
+ present: { [K in keyof S]: boolean };
82
+ rest: string[];
83
+ unknown: string[];
84
+ issues: ParseIssue[];
85
+ ok: boolean;
86
+ }
87
+ ```
88
+
89
+ ### JSON Schema (ParseResult)
42
90
 
43
- ### Array flags
91
+ `schema/parse-result.schema.json` defines the JSON-serializable shape of `ParseResult`.
44
92
 
45
- Array flags collect values until the next `--flag`:
93
+ Use `toJsonResult()` to convert `undefined` values to `null` before validation:
94
+
95
+ ```js
96
+ import { parseArgs, toJsonResult } from 'argv-flags';
97
+ import Ajv from 'ajv';
98
+ import schema from 'argv-flags/schema/parse-result.schema.json' assert { type: 'json' };
99
+
100
+ const result = parseArgs(schemaDef);
101
+ const jsonResult = toJsonResult(result);
102
+
103
+ const ajv = new Ajv({ allErrors: true });
104
+ const validate = ajv.compile(schema);
105
+ console.log(validate(jsonResult)); // true/false
106
+ ```
107
+
108
+ ### `issues`
109
+
110
+ Each issue is explicit and stable:
111
+
112
+ ```ts
113
+ type IssueCode =
114
+ | 'UNKNOWN_FLAG'
115
+ | 'MISSING_VALUE'
116
+ | 'INVALID_VALUE'
117
+ | 'REQUIRED'
118
+ | 'DUPLICATE'
119
+ | 'EMPTY_VALUE';
120
+
121
+ interface ParseIssue {
122
+ code: IssueCode;
123
+ severity: 'error' | 'warning';
124
+ message: string;
125
+ flag?: string;
126
+ key?: string;
127
+ value?: string;
128
+ index?: number;
129
+ }
130
+ ```
131
+
132
+ `ok` is `true` only when no `error`-severity issues exist.
133
+
134
+ ## Parsing rules (deterministic)
135
+
136
+ Rules are applied in order:
137
+ 1. `--` stops flag parsing (when enabled) and the rest becomes `rest`.
138
+ 2. Non-flag tokens (`-` or plain values) become `rest`.
139
+ 3. `--no-<flag>` maps to the matching boolean spec if present and `allowNo !== false`.
140
+ 4. Inline values (`--flag=value`) are parsed before consuming the next argv token.
141
+ 5. Arrays collect values until the next flag token or `--`.
142
+ 6. Duplicate non-array flags are warnings; duplicate arrays append.
143
+ 7. Required flags missing at the end produce `REQUIRED` errors.
144
+
145
+ ## Value parsing
146
+
147
+ - `boolean`: `true|false|1|0|yes|no|on|off` (case-insensitive).
148
+ When no explicit value is provided, presence means `true`.
149
+ - `number`: `Number(value)` must be finite. Negative numbers are accepted.
150
+ - `string`: values are taken as-is; empty strings are rejected unless `allowEmpty`.
151
+ - `array`: collects tokens until the next flag token; empty arrays are rejected unless `allowEmpty`.
152
+
153
+ ## Examples
46
154
 
47
155
  ```sh
156
+ --flag
157
+ --flag=true
158
+ --count=-3
48
159
  --items a b c --other
160
+ -- --literal --values
161
+ --no-verbose
49
162
  ```
50
163
 
51
- ### Testing / custom argv
164
+ ## Versioning and migration
52
165
 
53
- You can pass a custom argv array (useful for tests):
166
+ ### 1.0.0
54
167
 
55
- ```js
56
- const argv = ['node', 'script.js', '--flag', 'true'];
57
- parseFlag('--flag', 'boolean', argv);
168
+ This release is intentionally strict and schema-driven:
169
+
170
+ - ESM-only (Node.js >=24).
171
+ - Typed schema is the single source of truth.
172
+ - Parsing returns a structured result object rather than sentinel `false` values.
173
+
174
+ Migration from 0.x:
175
+
176
+ ```diff
177
+ - const parseFlag = require('argv-flags');
178
+ - const name = parseFlag('--name', 'string');
179
+ + import { defineSchema, parseArgs } from 'argv-flags';
180
+ + const schema = defineSchema({ name: { type: 'string', flags: ['--name'] } });
181
+ + const result = parseArgs(schema);
182
+ + const name = result.values.name;
58
183
  ```
59
184
 
185
+ ## Guarantees
186
+
187
+ - Deterministic output for a given `argv`.
188
+ - No mutation of the input `argv`.
189
+ - Stable issue codes for programmatic handling.
190
+
60
191
  ## License
61
192
 
62
193
  MIT
@@ -0,0 +1,55 @@
1
+ export type FlagType = 'string' | 'boolean' | 'number' | 'array';
2
+ export type FlagValue<T extends FlagType> = T extends 'string' ? string : T extends 'boolean' ? boolean : T extends 'number' ? number : T extends 'array' ? string[] : never;
3
+ export interface FlagSpec<T extends FlagType = FlagType> {
4
+ type: T;
5
+ flags: readonly string[];
6
+ required?: boolean;
7
+ default?: FlagValue<T>;
8
+ allowEmpty?: boolean;
9
+ allowNo?: boolean;
10
+ }
11
+ export type Schema = Record<string, FlagSpec>;
12
+ export type IssueSeverity = 'error' | 'warning';
13
+ export type IssueCode = 'UNKNOWN_FLAG' | 'MISSING_VALUE' | 'INVALID_VALUE' | 'REQUIRED' | 'DUPLICATE' | 'EMPTY_VALUE';
14
+ export interface ParseIssue {
15
+ code: IssueCode;
16
+ severity: IssueSeverity;
17
+ message: string;
18
+ flag?: string;
19
+ key?: string;
20
+ value?: string;
21
+ index?: number;
22
+ }
23
+ export interface ParseOptions {
24
+ argv?: readonly string[];
25
+ allowUnknown?: boolean;
26
+ stopAtDoubleDash?: boolean;
27
+ }
28
+ export type ParsedValues<S extends Schema> = {
29
+ [K in keyof S]: FlagValue<S[K]['type']> | undefined;
30
+ };
31
+ export type ParsedPresent<S extends Schema> = {
32
+ [K in keyof S]: boolean;
33
+ };
34
+ export interface ParseResult<S extends Schema> {
35
+ values: ParsedValues<S>;
36
+ present: ParsedPresent<S>;
37
+ rest: string[];
38
+ unknown: string[];
39
+ issues: ParseIssue[];
40
+ ok: boolean;
41
+ }
42
+ export type JsonFlagValue = string | number | boolean | string[] | null;
43
+ export interface ParseResultJson {
44
+ values: Record<string, JsonFlagValue>;
45
+ present: Record<string, boolean>;
46
+ rest: string[];
47
+ unknown: string[];
48
+ issues: ParseIssue[];
49
+ ok: boolean;
50
+ }
51
+ export declare const defineSchema: <T extends Schema>(schema: T) => T;
52
+ export declare const parseArgs: <T extends Schema>(schema: T, options?: ParseOptions) => ParseResult<T>;
53
+ export default parseArgs;
54
+ export declare const toJsonResult: <T extends Schema>(result: ParseResult<T>) => ParseResultJson;
55
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,337 @@
1
+ const BOOLEAN_TRUE = new Set(['true', '1', 'yes', 'y', 'on']);
2
+ const BOOLEAN_FALSE = new Set(['false', '0', 'no', 'n', 'off']);
3
+ const isFlagToken = (value) => typeof value === 'string' && value.startsWith('-') && value.length > 1;
4
+ const normalizeBoolean = (value) => {
5
+ if (typeof value !== 'string')
6
+ return undefined;
7
+ const normalized = value.toLowerCase();
8
+ if (BOOLEAN_TRUE.has(normalized))
9
+ return true;
10
+ if (BOOLEAN_FALSE.has(normalized))
11
+ return false;
12
+ return undefined;
13
+ };
14
+ const isNumericValue = (value) => {
15
+ if (typeof value !== 'string' || value.length === 0)
16
+ return false;
17
+ const parsed = Number(value);
18
+ return Number.isFinite(parsed);
19
+ };
20
+ const cloneDefault = (value, type) => {
21
+ if (type === 'array' && Array.isArray(value)) {
22
+ return [...value];
23
+ }
24
+ return value;
25
+ };
26
+ const splitInlineValue = (token) => {
27
+ const eqIndex = token.indexOf('=');
28
+ if (eqIndex <= 0)
29
+ return { flag: token };
30
+ return { flag: token.slice(0, eqIndex), value: token.slice(eqIndex + 1) };
31
+ };
32
+ const validateSchema = (schema) => {
33
+ if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
34
+ throw new TypeError('Schema must be an object.');
35
+ }
36
+ const flagToKey = new Map();
37
+ const normalized = new Map();
38
+ for (const [rawKey, rawSpec] of Object.entries(schema)) {
39
+ const key = rawKey;
40
+ const spec = rawSpec;
41
+ if (!spec || typeof spec !== 'object') {
42
+ throw new TypeError(`Schema entry for "${String(key)}" must be an object.`);
43
+ }
44
+ const type = spec.type;
45
+ if (!['string', 'boolean', 'number', 'array'].includes(type)) {
46
+ throw new TypeError(`Schema entry "${String(key)}" has invalid type "${String(type)}".`);
47
+ }
48
+ const flagsInput = spec.flags;
49
+ if (!Array.isArray(flagsInput) || flagsInput.length === 0) {
50
+ throw new TypeError(`Schema entry "${String(key)}" must define at least one flag.`);
51
+ }
52
+ const flags = [];
53
+ for (const flag of flagsInput) {
54
+ if (typeof flag !== 'string' || flag.length < 2 || !flag.startsWith('-')) {
55
+ throw new TypeError(`Schema entry "${String(key)}" has invalid flag "${String(flag)}".`);
56
+ }
57
+ if (flagToKey.has(flag)) {
58
+ const existing = flagToKey.get(flag);
59
+ throw new TypeError(`Flag "${flag}" is already assigned to "${String(existing)}".`);
60
+ }
61
+ flagToKey.set(flag, key);
62
+ flags.push(flag);
63
+ }
64
+ const longFlag = flags.find((flag) => flag.startsWith('--'));
65
+ const normalizedSpec = {
66
+ ...spec,
67
+ type,
68
+ flags,
69
+ ...(longFlag ? { longFlag } : {})
70
+ };
71
+ normalized.set(key, normalizedSpec);
72
+ }
73
+ return { flagToKey, normalized };
74
+ };
75
+ export const defineSchema = (schema) => schema;
76
+ export const parseArgs = (schema, options = {}) => {
77
+ const { flagToKey, normalized } = validateSchema(schema);
78
+ const argv = Array.isArray(options.argv) ? options.argv : process.argv.slice(2);
79
+ const allowUnknown = options.allowUnknown === true;
80
+ const stopAtDoubleDash = options.stopAtDoubleDash !== false;
81
+ const values = {};
82
+ const present = {};
83
+ const issues = [];
84
+ const unknown = [];
85
+ const rest = [];
86
+ for (const [key, spec] of normalized.entries()) {
87
+ present[key] = false;
88
+ values[key] = cloneDefault(spec.default, spec.type);
89
+ }
90
+ const pushIssue = (issue) => {
91
+ issues.push(issue);
92
+ };
93
+ for (let i = 0; i < argv.length; i += 1) {
94
+ const token = argv[i];
95
+ if (stopAtDoubleDash && token === '--') {
96
+ rest.push(...argv.slice(i + 1));
97
+ break;
98
+ }
99
+ if (!isFlagToken(token)) {
100
+ rest.push(token);
101
+ continue;
102
+ }
103
+ const rawToken = token;
104
+ const { flag, value: inlineValue } = splitInlineValue(token);
105
+ if (flag.startsWith('--no-') && !flagToKey.has(flag)) {
106
+ const base = `--${flag.slice(5)}`;
107
+ const baseKey = flagToKey.get(base);
108
+ if (baseKey) {
109
+ const baseSpec = normalized.get(baseKey);
110
+ if (baseSpec?.type === 'boolean' && baseSpec.allowNo !== false) {
111
+ if (present[baseKey]) {
112
+ pushIssue({
113
+ code: 'DUPLICATE',
114
+ severity: 'warning',
115
+ message: `Duplicate flag ${base}.`,
116
+ flag: base,
117
+ key: String(baseKey),
118
+ index: i
119
+ });
120
+ }
121
+ present[baseKey] = true;
122
+ values[baseKey] = false;
123
+ continue;
124
+ }
125
+ }
126
+ }
127
+ const key = flagToKey.get(flag);
128
+ if (!key) {
129
+ if (!allowUnknown) {
130
+ pushIssue({
131
+ code: 'UNKNOWN_FLAG',
132
+ severity: 'error',
133
+ message: `Unknown flag ${flag}.`,
134
+ flag,
135
+ index: i
136
+ });
137
+ }
138
+ else {
139
+ unknown.push(rawToken);
140
+ }
141
+ continue;
142
+ }
143
+ const spec = normalized.get(key);
144
+ if (!spec) {
145
+ continue;
146
+ }
147
+ const wasPresent = present[key];
148
+ if (wasPresent && spec.type !== 'array') {
149
+ pushIssue({
150
+ code: 'DUPLICATE',
151
+ severity: 'warning',
152
+ message: `Duplicate flag ${flag}.`,
153
+ flag,
154
+ key: String(key),
155
+ index: i
156
+ });
157
+ }
158
+ present[key] = true;
159
+ if (spec.type === 'boolean') {
160
+ let raw = inlineValue;
161
+ let consumedNext = false;
162
+ if (raw === undefined) {
163
+ const nextValue = argv[i + 1];
164
+ const normalizedValue = normalizeBoolean(nextValue);
165
+ if (normalizedValue !== undefined) {
166
+ raw = nextValue;
167
+ consumedNext = true;
168
+ }
169
+ }
170
+ if (raw !== undefined) {
171
+ const normalizedValue = normalizeBoolean(raw);
172
+ if (normalizedValue === undefined) {
173
+ pushIssue({
174
+ code: 'INVALID_VALUE',
175
+ severity: 'error',
176
+ message: `Invalid boolean value for ${flag}: ${raw}.`,
177
+ flag,
178
+ key: String(key),
179
+ value: raw,
180
+ index: i
181
+ });
182
+ }
183
+ else {
184
+ values[key] = normalizedValue;
185
+ if (consumedNext) {
186
+ i += 1;
187
+ }
188
+ }
189
+ }
190
+ else {
191
+ values[key] = true;
192
+ }
193
+ continue;
194
+ }
195
+ if (spec.type === 'string') {
196
+ let raw = inlineValue;
197
+ if (raw === undefined) {
198
+ const nextValue = argv[i + 1];
199
+ if (typeof nextValue !== 'string' || isFlagToken(nextValue)) {
200
+ pushIssue({
201
+ code: 'MISSING_VALUE',
202
+ severity: 'error',
203
+ message: `Missing value for ${flag}.`,
204
+ flag,
205
+ key: String(key),
206
+ index: i
207
+ });
208
+ continue;
209
+ }
210
+ raw = nextValue;
211
+ i += 1;
212
+ }
213
+ if (raw.length === 0 && spec.allowEmpty !== true) {
214
+ pushIssue({
215
+ code: 'EMPTY_VALUE',
216
+ severity: 'error',
217
+ message: `Empty value not allowed for ${flag}.`,
218
+ flag,
219
+ key: String(key),
220
+ index: i
221
+ });
222
+ continue;
223
+ }
224
+ values[key] = raw;
225
+ continue;
226
+ }
227
+ if (spec.type === 'number') {
228
+ let raw = inlineValue;
229
+ if (raw === undefined) {
230
+ const nextValue = argv[i + 1];
231
+ if (typeof nextValue !== 'string' || (!isNumericValue(nextValue) && isFlagToken(nextValue))) {
232
+ pushIssue({
233
+ code: 'MISSING_VALUE',
234
+ severity: 'error',
235
+ message: `Missing value for ${flag}.`,
236
+ flag,
237
+ key: String(key),
238
+ index: i
239
+ });
240
+ continue;
241
+ }
242
+ raw = nextValue;
243
+ i += 1;
244
+ }
245
+ if (!isNumericValue(raw)) {
246
+ pushIssue({
247
+ code: 'INVALID_VALUE',
248
+ severity: 'error',
249
+ message: `Invalid number value for ${flag}: ${raw}.`,
250
+ flag,
251
+ key: String(key),
252
+ value: raw,
253
+ index: i
254
+ });
255
+ continue;
256
+ }
257
+ values[key] = Number(raw);
258
+ continue;
259
+ }
260
+ if (spec.type === 'array') {
261
+ const collected = [];
262
+ if (inlineValue !== undefined && inlineValue.length > 0) {
263
+ collected.push(inlineValue);
264
+ }
265
+ let cursor = i + 1;
266
+ while (cursor < argv.length) {
267
+ const nextValue = argv[cursor];
268
+ if (stopAtDoubleDash && nextValue === '--') {
269
+ break;
270
+ }
271
+ if (isFlagToken(nextValue)) {
272
+ break;
273
+ }
274
+ collected.push(nextValue);
275
+ cursor += 1;
276
+ }
277
+ if (cursor > i + 1) {
278
+ i = cursor - 1;
279
+ }
280
+ if (collected.length === 0 && spec.allowEmpty !== true) {
281
+ pushIssue({
282
+ code: 'MISSING_VALUE',
283
+ severity: 'error',
284
+ message: `Missing value for ${flag}.`,
285
+ flag,
286
+ key: String(key),
287
+ index: i
288
+ });
289
+ continue;
290
+ }
291
+ const existing = Array.isArray(values[key]) ? values[key] : [];
292
+ values[key] = [...existing, ...collected];
293
+ continue;
294
+ }
295
+ }
296
+ for (const [key, spec] of normalized.entries()) {
297
+ if (spec.required && !present[key]) {
298
+ const primaryFlag = spec.flags[0];
299
+ pushIssue({
300
+ code: 'REQUIRED',
301
+ severity: 'error',
302
+ message: `Missing required flag ${primaryFlag ?? ''}.`,
303
+ ...(primaryFlag ? { flag: primaryFlag } : {}),
304
+ key: String(key)
305
+ });
306
+ }
307
+ }
308
+ const ok = issues.every((issue) => issue.severity !== 'error');
309
+ return {
310
+ values,
311
+ present,
312
+ rest,
313
+ unknown,
314
+ issues,
315
+ ok
316
+ };
317
+ };
318
+ export default parseArgs;
319
+ export const toJsonResult = (result) => {
320
+ const values = {};
321
+ for (const [key, value] of Object.entries(result.values)) {
322
+ if (value === undefined) {
323
+ values[key] = null;
324
+ continue;
325
+ }
326
+ values[key] = value;
327
+ }
328
+ return {
329
+ values,
330
+ present: result.present,
331
+ rest: [...result.rest],
332
+ unknown: [...result.unknown],
333
+ issues: [...result.issues],
334
+ ok: result.ok
335
+ };
336
+ };
337
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,17 +1,26 @@
1
1
  {
2
2
  "name": "argv-flags",
3
- "version": "0.2.1",
4
- "description": "Minimal CLI flag parser for strings, booleans, numbers, and arrays.",
5
- "main": "index.js",
6
- "types": "index.d.ts",
3
+ "version": "1.0.1",
4
+ "description": "Schema-based CLI flag parser for Node.js.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
7
14
  "files": [
15
+ "CHANGELOG.md",
8
16
  "LICENSE",
9
17
  "README.md",
10
- "index.js",
11
- "index.d.ts"
18
+ "dist",
19
+ "schema"
12
20
  ],
13
21
  "scripts": {
14
- "test": "node --test"
22
+ "build": "tsc -p tsconfig.json",
23
+ "test": "npm run build && node --test"
15
24
  },
16
25
  "repository": {
17
26
  "type": "git",
@@ -30,6 +39,11 @@
30
39
  },
31
40
  "homepage": "https://github.com/Ismail-elkorchi/argv-flags#readme",
32
41
  "engines": {
33
- "node": ">=18"
42
+ "node": ">=24"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^24.0.0",
46
+ "ajv": "^8.17.1",
47
+ "typescript": "^5.5.4"
34
48
  }
35
49
  }
@@ -0,0 +1,65 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schema.argv-flags.dev/parse-result.schema.json",
4
+ "title": "argv-flags ParseResult (JSON)",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["values", "present", "rest", "unknown", "issues", "ok"],
8
+ "properties": {
9
+ "values": {
10
+ "type": "object",
11
+ "additionalProperties": {
12
+ "anyOf": [
13
+ { "type": "string" },
14
+ { "type": "number" },
15
+ { "type": "boolean" },
16
+ {
17
+ "type": "array",
18
+ "items": { "type": "string" }
19
+ },
20
+ { "type": "null" }
21
+ ]
22
+ }
23
+ },
24
+ "present": {
25
+ "type": "object",
26
+ "additionalProperties": { "type": "boolean" }
27
+ },
28
+ "rest": {
29
+ "type": "array",
30
+ "items": { "type": "string" }
31
+ },
32
+ "unknown": {
33
+ "type": "array",
34
+ "items": { "type": "string" }
35
+ },
36
+ "issues": {
37
+ "type": "array",
38
+ "items": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "required": ["code", "severity", "message"],
42
+ "properties": {
43
+ "code": {
44
+ "type": "string",
45
+ "enum": [
46
+ "UNKNOWN_FLAG",
47
+ "MISSING_VALUE",
48
+ "INVALID_VALUE",
49
+ "REQUIRED",
50
+ "DUPLICATE",
51
+ "EMPTY_VALUE"
52
+ ]
53
+ },
54
+ "severity": { "type": "string", "enum": ["error", "warning"] },
55
+ "message": { "type": "string" },
56
+ "flag": { "type": "string" },
57
+ "key": { "type": "string" },
58
+ "value": { "type": "string" },
59
+ "index": { "type": "integer", "minimum": 0 }
60
+ }
61
+ }
62
+ },
63
+ "ok": { "type": "boolean" }
64
+ }
65
+ }
package/index.d.ts DELETED
@@ -1,7 +0,0 @@
1
- declare function parseFlag(
2
- flag: string,
3
- type?: 'string' | 'boolean' | 'array' | 'number',
4
- argv?: string[]
5
- ): string | boolean | string[] | number | false;
6
-
7
- export = parseFlag;
package/index.js DELETED
@@ -1,95 +0,0 @@
1
- 'use strict';
2
-
3
- const isLongFlag = ( value ) => typeof value === 'string' && value.startsWith( '--' );
4
-
5
- const normalizeBooleanValue = ( value ) => {
6
- if ( typeof value !== 'string' ) {
7
- return undefined;
8
- }
9
- const normalized = value.toLowerCase();
10
- if ( normalized === 'true' ) {
11
- return true;
12
- }
13
- if ( normalized === 'false' ) {
14
- return false;
15
- }
16
- return undefined;
17
- };
18
-
19
- const findFlagMatch = ( argv, targetArgument ) => {
20
- const directIndex = argv.indexOf( targetArgument );
21
- if ( directIndex !== -1 ) {
22
- return { index: directIndex };
23
- }
24
-
25
- const prefix = `${targetArgument}=`;
26
- const inlineIndex = argv.findIndex( ( value ) => typeof value === 'string' && value.startsWith( prefix ) );
27
- if ( inlineIndex === -1 ) {
28
- return null;
29
- }
30
-
31
- return {
32
- index: inlineIndex,
33
- inlineValue: argv[ inlineIndex ].slice( prefix.length )
34
- };
35
- };
36
-
37
- function parseFlag( targetArgument, argumentType, argv = process.argv ) {
38
- const processArguments = Array.isArray( argv ) ? argv : process.argv;
39
- const match = findFlagMatch( processArguments, targetArgument );
40
-
41
- if ( ! match ) {
42
- return false;
43
- }
44
-
45
- const inlineValue = Object.prototype.hasOwnProperty.call( match, 'inlineValue' )
46
- ? match.inlineValue
47
- : undefined;
48
- const nextValue = processArguments[ match.index + 1 ];
49
-
50
- if ( argumentType === 'string' ) {
51
- if ( typeof inlineValue === 'string' ) {
52
- return inlineValue;
53
- }
54
- if ( typeof nextValue !== 'string' || isLongFlag( nextValue ) ) {
55
- return false;
56
- }
57
- return nextValue;
58
- }
59
-
60
- if ( argumentType === 'array' ) {
61
- const values = [];
62
- if ( typeof inlineValue === 'string' && inlineValue.length > 0 ) {
63
- values.push( inlineValue );
64
- }
65
- for ( let i = match.index + 1; i < processArguments.length; i++ ) {
66
- const value = processArguments[ i ];
67
- if ( isLongFlag( value ) ) {
68
- break;
69
- }
70
- values.push( value );
71
- }
72
- return values;
73
- }
74
-
75
- if ( argumentType === 'boolean' ) {
76
- const normalizedValue = normalizeBooleanValue( typeof inlineValue === 'string' ? inlineValue : nextValue );
77
- if ( typeof normalizedValue === 'boolean' ) {
78
- return normalizedValue;
79
- }
80
- return true;
81
- }
82
-
83
- if ( argumentType === 'number' ) {
84
- const candidate = typeof inlineValue === 'string' ? inlineValue : nextValue;
85
- if ( typeof candidate !== 'string' || isLongFlag( candidate ) ) {
86
- return false;
87
- }
88
- const parsed = Number( candidate );
89
- return Number.isNaN( parsed ) ? false : parsed;
90
- }
91
-
92
- return false;
93
- }
94
-
95
- module.exports = parseFlag;