Skip to content

Commit 1326d38

Browse files
committed
first release, v1.1.0
1 parent a6f3a85 commit 1326d38

File tree

9 files changed

+94
-83
lines changed

9 files changed

+94
-83
lines changed

CHANGELOG.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
# Changelog
22

3-
## 0.1.0-alpha.0 (2025-07-03)
3+
## 1.1.0 (2025-07-04)
44

5-
- feat: optimize npm package for smaller size: 12kB -> 5kB
5+
- first stable release
6+
- feat: rename options for compatibility to yargs-parser options
7+
- feat: optimize npm package for smaller size: 12kB -> ~5kB
68
- feat: add d.ts file
79
- refactor: refactor code, add more comments
810
- chore: add rollup to build clean npm package
11+
- test: add CI workflow via GitHub actions
912
- docs: improve readme
1013

14+
## 1.0.0 (2025-07-04) UNPUBLISHED as not ready for release
15+
1116
## 0.0.2 (2025-07-02)
1217

1318
- fix: resolving files in package.json for CommonJS
1419

15-
## 0.0.1 (2025-07-01)
20+
## 0.0.1 (2025-07-01) UNPUBLISHED as experimental not working version
1621

17-
- feat: create small and fast CLI flag parser with supports of all base formats
22+
- chore(experimental): create small and fast CLI flag parser as lightweight alternative to yargs-parser

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ Supports all standard CLI flag formats.
1919
- Long boolean flag: `--flag`
2020
- Long flag with value: `--key=value` or `--key value`
2121
- Dashed long flag: `--foo-bar` (available as both `flags['foo-bar']` and `flags.fooBar`)
22-
- Multi-value keys: `--files a.js b.js`
23-
- Short-to-long aliases: `-f` = `--files`
22+
- Multi-values: `--files a.js b.js`
23+
- Short-to-long alias: `-f` = `--files`
2424
- Positional arguments and `--` terminator: `cmd -a --key=foo file1.txt -- file2.txt`
2525
- Default values for flags
2626

@@ -53,9 +53,9 @@ console.log(flags);
5353
```js
5454
const flags = getFlags({
5555
// argv: process.argv.slice(2), // parses by default
56-
aliases: { f: 'files', l: 'limit' }, // -f = --files, -l = --limit
57-
arrays: ['files'], // collect multiple values for --files and -f
58-
defaults: { type: 'yaml', verbose: false } // default values if not set in CLI
56+
alias: { f: 'files', l: 'limit' }, // -f = --files, -l = --limit
57+
array: ['files'], // collect multiple values for --files and -f
58+
default: { type: 'yaml', verbose: false } // default values if not set in CLI
5959
});
6060

6161
console.log(flags);
@@ -90,19 +90,19 @@ Result:
9090

9191
## Options
9292

93-
| Option | Type | Default | Description |
94-
|------------|------------| ------------------------ |---------------------------------------------------------------|
95-
| `argv` | string[] | `process.argv.slice(2)` | Array of CLI arguments to parse |
96-
| `aliases` | Object | `{}` | Map of short keys to long keys.<br>Example: `{ f: 'files' }` |
97-
| `arrays` | string[] | `[]` | Keys that should collect multiple values as arrays |
98-
| `defaults` | Object | `{}` | Default values for flags, if not set on the CLI |
93+
| Option | Type | Default | Description |
94+
|------------|------------| ------------------------ |--------------------------------------------------------------|
95+
| `argv` | string[] | `process.argv.slice(2)` | Array of CLI arguments to parse |
96+
| `alias` | Object | `{}` | Map of short keys to long keys.<br>Example: `{ f: 'files' }` |
97+
| `array` | string[] | `[]` | Keys that should collect multiple values as array |
98+
| `default` | Object | `{}` | Default values for flags, if not set on the CLI |
9999

100100
**Notes**
101101

102102
- All dashed keys are also available as camelCase (e.g. `--foo-bar` sets both `foo-bar` and `fooBar`).
103-
- Use the `aliases` option to map short flags to long names.
104-
- Specify keys in `arrays` to collect an array of multi-values.
105-
- Use the `defaults` option for fallback values.
103+
- Use the `alias` option to map short flags to long names.
104+
- Specify keys in `array` to collect an array of multi-values.
105+
- Use the `default` option for fallback values.
106106

107107

108108
## Examples

README.npm.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<img width="400" src="docs/logo.png" alt="Flaget">
33
</h1>
44

5-
Minimal, fast CLI flag parser for Node.js.
5+
Small and fast CLI flag parser for Node.js.
66
Supports all standard CLI flag formats.
77

88
## Features
@@ -13,8 +13,8 @@ Supports all standard CLI flag formats.
1313
- Long boolean flag: `--flag`
1414
- Long flag with value: `--key=value` or `--key value`
1515
- Dashed long flag: `--foo-bar` (available as both `flags['foo-bar']` and `flags.fooBar`)
16-
- Multi-value keys: `--files a.js b.js`
17-
- Short-to-long aliases: `-f` = `--files`
16+
- Multi-values: `--files a.js b.js`
17+
- Short-to-long alias: `-f` = `--files`
1818
- Positional arguments and `--` terminator: `cmd -a --key=foo file1.txt -- file2.txt`
1919
- Default values for flags
2020

index.d.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
* Parses CLI arguments into a flags object.
33
*
44
* @param options
5-
* @param options.argv The arguments to parse (defaults to process.argv.slice(2)).
6-
* @param options.aliases Map of short keys to long keys, e.g. { f: 'files' }.
7-
* @param options.arrays Keys that should collect multiple values.
8-
* @param options.defaults Map of default values.
5+
* @param options.argv The arguments to parse (defaults is process.argv.slice(2)).
6+
* @param options.alias Map of short keys to long keys, e.g. { f: 'files' }.
7+
* @param options.array Keys that should collect multiple values.
8+
* @param options.default Map of default values.
99
* @returns Parsed flags object.
1010
*/
1111
declare function getFlags(options?: {
1212
argv?: string[];
13-
aliases?: Record<string, string>;
14-
arrays?: string[];
15-
defaults?: Record<string, unknown>;
13+
alias?: Record<string, string>;
14+
array?: string[];
15+
default?: Record<string, unknown>;
1616
}): {
1717
[key: string]: string | number | boolean | Array<string | number | boolean> | undefined;
1818
_: string[];

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "flaget",
3-
"version": "0.1.0-alpha.0",
4-
"description": "Small, fast CLI flag parser for Node.js, supported all standard CLI flag formats.",
3+
"version": "1.1.0",
4+
"description": "Small CLI flag parser for Node.js supporting all standard flag formats.",
55
"keywords": [
66
"cli",
7-
"flags",
7+
"flag",
88
"parser",
9-
"command-line",
9+
"argument",
10+
"argv",
1011
"args"
1112
],
1213
"license": "ISC",

package.npm.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "flaget",
3-
"version": "0.1.0-alpha.0",
4-
"description": "Small, fast CLI flag parser",
3+
"version": "1.1.0",
4+
"description": "Small CLI flag parser supporting all standard formats.",
55
"keywords": [
66
"cli",
7-
"flags",
7+
"flag",
88
"parser",
9-
"command-line",
9+
"argument",
10+
"argv",
1011
"args"
1112
],
1213
"license": "ISC",

rollup.config.js

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ const terserMinifyOptions = (ecma) => ({
3939
});
4040

4141
const terserPrettyOptions = (ecma) => ({
42-
compress: false, // disables code compression/minification
43-
mangle: false, // disables name mangling (shortening)
42+
compress: false,
43+
mangle: false, // disables name shortening
4444
format: {
45+
comments: false,
4546
beautify: true, // pretty output (optional, for better readability)
4647
indent_level: 2, // force 2-space indentation
47-
}
48+
},
4849
});
4950

5051
/**
@@ -79,18 +80,17 @@ function removeEmptyLines(input, replacement = '') {
7980
}
8081

8182
/**
82-
* Rollup plugin to replace space indents to tabs.
83-
*
84-
* @param {number} spacesPerTab Number of spaces per tab (default 2).
85-
* @return {{name: string, generateBundle(*, *): void}}
83+
* Rollup plugin that applies a user transform function to code.
84+
* @param {(code: string, file: object) => string} transform A function to transform code.
85+
* @returns {import('rollup').Plugin}
8686
*/
87-
function spacesToTabsPlugin(spacesPerTab = 2) {
87+
function transform(transform) {
8888
return {
89-
name: 'spaces-to-tabs',
89+
name: 'plugin-transform',
9090
generateBundle(options, bundle) {
9191
for (const file of Object.values(bundle)) {
92-
if (file.type === 'chunk') {
93-
file.code = indentSpacesToTabs(file.code, spacesPerTab);
92+
if (file.type === 'chunk' && typeof transform === 'function') {
93+
file.code = transform(file.code, file);
9494
}
9595
}
9696
}
@@ -125,7 +125,15 @@ function buildConfig({ output, ecma }) {
125125
plugins: [
126126
...(ecma < 2020 ? [babel(babelOptions)] : []),
127127
terser(terserPrettyOptions(ecma)),
128-
spacesToTabsPlugin(),
128+
transform((code) => {
129+
return indentSpacesToTabs(code, 2)
130+
// remove needles destructed variables after terser
131+
.replaceAll('argv: argv', 'argv')
132+
.replaceAll('alias: alias', 'alias')
133+
.replaceAll('array: array', 'array')
134+
.replaceAll('flags: flags', 'flags')
135+
.replaceAll('argOffset: argOffset', 'argOffset');
136+
}),
129137
copy({
130138
targets: [
131139
{

src/getFlags.js

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ const setFlag = (flags, key, value) => {
4848
/**
4949
* Map an alias to its full key name if defined.
5050
* @param {string} key The key or alias to resolve.
51-
* @param {object} aliases The aliases mapping object.
51+
* @param {object} alias The alias mapping object.
5252
* @returns {string} The resolved key.
5353
*/
54-
const getKey = (key, aliases) => (
55-
aliases[key] || key
54+
const getKey = (key, alias) => (
55+
alias[key] || key
5656
);
5757

5858
/**
@@ -82,17 +82,17 @@ const readMultiValues = (argv, startIndex, rawVal) => {
8282
* Parse a long flag argument (e.g., --key or --key=value).
8383
* @param {string} arg The argument to parse.
8484
* @param {number} index The current argv index.
85-
* @param {object} context Parsing context (argv, aliases, arrays, flags).
85+
* @param {object} context Parsing context (argv, alias, array, flags).
8686
* @returns {number} The updated index.
8787
*/
8888
const parseLongFlag = (arg, index, context) => {
89-
const { argv, aliases, arrays, flags } = context;
89+
const { argv, alias, array, flags } = context;
9090
const [rawKey, rawVal] = arg.includes('=')
9191
? arg.slice(2).split('=')
9292
: [arg.slice(2)];
93-
const key = getKey(rawKey, aliases);
93+
const key = getKey(rawKey, alias);
9494

95-
if (arrays.includes(key)) {
95+
if (array.includes(key)) {
9696
const { values, argOffset } = readMultiValues(argv, index, rawVal);
9797
setFlag(flags, key, (flags[key] || []).concat(values));
9898
return index + argOffset;
@@ -114,12 +114,12 @@ const parseLongFlag = (arg, index, context) => {
114114
/**
115115
* Parse grouped short flags (e.g., -abc -> -a -b -c).
116116
* @param {string} arg The argument to parse.
117-
* @param {object} context Parsing context (aliases, flags).
117+
* @param {object} context Parsing context (alias, flags).
118118
*/
119119
const parseShortGroup = (arg, context) => {
120-
const { aliases, flags } = context;
120+
const { alias, flags } = context;
121121
for (const char of arg.slice(1)) {
122-
const key = getKey(char, aliases);
122+
const key = getKey(char, alias);
123123
setFlag(flags, key, true);
124124
}
125125
};
@@ -128,17 +128,17 @@ const parseShortGroup = (arg, context) => {
128128
* Parse a single short flag (e.g., -f or -f value).
129129
* @param {string} arg The argument to parse.
130130
* @param {number} index The current argv index.
131-
* @param {object} context Parsing context (argv, aliases, arrays, flags).
131+
* @param {object} context Parsing context (argv, alias, array, flags).
132132
* @returns {number} The updated index.
133133
*/
134134
const parseShortFlag = (arg, index, context) => {
135-
const { argv, aliases, arrays, flags } = context;
135+
const { argv, alias, array, flags } = context;
136136
const short = arg[1];
137-
const key = getKey(short, aliases);
137+
const key = getKey(short, alias);
138138
const next = argv[index + 1];
139139
const isNextValue = next && !isFlag(next);
140140

141-
if (arrays.includes(key)) {
141+
if (array.includes(key)) {
142142
const values = [];
143143
let i = index;
144144
while (argv[i + 1] && !isFlag(argv[i + 1])) {
@@ -159,19 +159,15 @@ const parseShortFlag = (arg, index, context) => {
159159
*
160160
* @param {object} [options] Parsing options.
161161
* @param {Array} [options.argv=process.argv.slice(2)] The argv array to parse.
162-
* @param {object} [options.aliases={}] Mapping of flag aliases.
163-
* @param {Array} [options.arrays=[]] Keys that should always produce arrays.
164-
* @param {object} [options.defaults={}] Default values for missing flags.
162+
* @param {object} [options.alias={}] Mapping of flag alias.
163+
* @param {Array} [options.array=[]] Keys that should always produce array.
164+
* @param {object} [options.default={}] Default values for missing flags.
165165
* @returns {object} Parsed flags object.
166166
*/
167-
const getFlags = ({
168-
argv = process.argv.slice(2),
169-
aliases = {},
170-
arrays = [],
171-
defaults = {},
172-
} = {}) => {
167+
const getFlags = (options = {}) => {
168+
const { argv= process.argv.slice(2), alias= {}, array = []} = options;
173169
const flags = { _: [] };
174-
const context = { argv, aliases, arrays, flags };
170+
const context = { argv, alias, array, flags };
175171

176172
for (let i = 0; i < argv.length; i++) {
177173
const arg = argv[i];
@@ -202,7 +198,7 @@ const getFlags = ({
202198
}
203199

204200
// apply default values for missing flags
205-
for (const [key, val] of Object.entries(defaults)) {
201+
for (const [key, val] of Object.entries(options.default || {})) {
206202
if (!(key in flags)) {
207203
setFlag(flags, key, val);
208204
}

test/getFlags.test.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ describe('getFlags', () => {
7979
// example: cmd --tag a b --tag=c
8080
const result = getFlags({
8181
argv: ['--tag', 'a', 'b', '--tag=c'],
82-
arrays: ['tag'],
82+
array: ['tag'],
8383
});
8484
expect(result).toEqual({ tag: ['a', 'b', 'c'], _: [] });
8585
});
@@ -107,7 +107,7 @@ describe('getFlags', () => {
107107
// example: cmd --f val (alias: f => foo)
108108
const result = getFlags({
109109
argv: ['--f', 'val'],
110-
aliases: { f: 'foo' },
110+
alias: { f: 'foo' },
111111
});
112112
expect(result).toEqual({ foo: 'val', _: [] });
113113
});
@@ -124,7 +124,7 @@ describe('getFlags', () => {
124124
// example: cmd --f a.js --file b.js (alias: f => file), will be parsed latest value
125125
const result = getFlags({
126126
argv: ['-f', 'a.js', '--file', 'b.js'],
127-
aliases: { f: 'file' },
127+
alias: { f: 'file' },
128128
});
129129
expect(result).toEqual({ 'file': 'b.js', _: [] });
130130
});
@@ -133,8 +133,8 @@ describe('getFlags', () => {
133133
// example: cmd --f a.js --files b.js (alias: f => files), collects all values
134134
const result = getFlags({
135135
argv: ['-f', 'a.js', '--files', 'b.js'],
136-
aliases: { f: 'files' },
137-
arrays: ['files'],
136+
alias: { f: 'files' },
137+
array: ['files'],
138138
});
139139
expect(result).toEqual({ 'files': ['a.js', 'b.js'], _: [] });
140140
});
@@ -143,9 +143,9 @@ describe('getFlags', () => {
143143
// example: cmd --f a.js --file b.js (alias: f => file), will be parsed latest value
144144
const result = getFlags({
145145
argv: ['report', '-abc', '--type=json', '--dash-flag', 'value', '--force', '--cached=false', '-l', '20', '-f', 'a.js', 'b.js', '--files', 'c.js', 'd.js', '--', 'out.json'],
146-
aliases: { f: 'files', l: 'limit' },
147-
arrays: ['files'],
148-
defaults: { type: 'yaml', verbose: false },
146+
alias: { f: 'files', l: 'limit' },
147+
array: ['files'],
148+
default: { type: 'yaml', verbose: false },
149149
});
150150
expect(result).toEqual({
151151
'a': true,
@@ -171,11 +171,11 @@ describe('getFlags', () => {
171171
});
172172
});
173173

174-
test('apply defaults', () => {
174+
test('apply default', () => {
175175
// example: cmd (env=production by default)
176176
const result = getFlags({
177177
argv: [],
178-
defaults: { env: 'production' },
178+
default: { env: 'production' },
179179
});
180180
expect(result).toEqual({ env: 'production', _: [] });
181181
});

0 commit comments

Comments
 (0)