@avandar/acclimate 0.1.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 +21 -0
- package/README.md +289 -0
- package/dist/index.cjs +381 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +223 -0
- package/dist/index.d.ts +223 -0
- package/dist/index.js +379 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { camelCase } from 'change-case';
|
|
2
|
+
import { match } from 'ts-pattern';
|
|
3
|
+
|
|
4
|
+
// src/CLIError.ts
|
|
5
|
+
var CLIError = class _CLIError extends Error {
|
|
6
|
+
static invalidCLIParamValue(options) {
|
|
7
|
+
return new _CLIError({
|
|
8
|
+
message: options.message ?? `Invalid value for CLI param "${options.paramName}"`,
|
|
9
|
+
code: "invalid_cli_param_value",
|
|
10
|
+
details: { paramName: options.paramName, paramValue: options.paramValue }
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
static missingRequiredOption(options) {
|
|
14
|
+
return new _CLIError({
|
|
15
|
+
message: options.message ?? `Required option "${options.optionName}" is missing`,
|
|
16
|
+
code: "missing_required_option",
|
|
17
|
+
details: { optionName: options.optionName }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
static missingRequiredPositionalArg(options) {
|
|
21
|
+
return new _CLIError({
|
|
22
|
+
message: options.message ?? `Required positional argument "${options.positionalArgName}" is missing`,
|
|
23
|
+
code: "missing_required_positional_arg",
|
|
24
|
+
details: { positionalArgName: options.positionalArgName }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
static unknownOption(options) {
|
|
28
|
+
return new _CLIError({
|
|
29
|
+
message: options.message ?? `Option "${options.optionName}" not found`,
|
|
30
|
+
code: "unknown_option",
|
|
31
|
+
details: { optionName: options.optionName }
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
static tooManyPositionalArgs(options) {
|
|
35
|
+
return new _CLIError({
|
|
36
|
+
message: options.message ?? "Too many positional arguments provided.",
|
|
37
|
+
code: "too_many_positional_args",
|
|
38
|
+
details: { count: options.count }
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
static invalidPositionalArgConfig(options) {
|
|
42
|
+
return new _CLIError({
|
|
43
|
+
message: options.message ?? `Positional argument configuration for "${options.positionalArgName}" is invalid`,
|
|
44
|
+
code: "invalid_positional_arg_config",
|
|
45
|
+
details: { positionalArgName: options.positionalArgName }
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
static unknownCommand(options) {
|
|
49
|
+
return new _CLIError({
|
|
50
|
+
message: options.message ?? `Command "${options.commandName}" not found`,
|
|
51
|
+
code: "unknown_command",
|
|
52
|
+
details: { commandName: options.commandName }
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
static alreadyRun(options = {}) {
|
|
56
|
+
return new _CLIError({
|
|
57
|
+
message: options.message ?? "CLI has already been run",
|
|
58
|
+
code: "already_run",
|
|
59
|
+
details: void 0
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
constructor(options) {
|
|
63
|
+
super(`\u274C ${options.message}`);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// src/AcclimateCLI/AcclimateCLI.ts
|
|
68
|
+
function AcclimateCLI(state) {
|
|
69
|
+
return {
|
|
70
|
+
state,
|
|
71
|
+
action: (action) => {
|
|
72
|
+
return AcclimateCLI({
|
|
73
|
+
...state,
|
|
74
|
+
action
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
description: (description) => {
|
|
78
|
+
return AcclimateCLI({
|
|
79
|
+
...state,
|
|
80
|
+
description
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
addPositionalArg: (param) => {
|
|
84
|
+
if (param.required && state.positionalArgs.some((p) => {
|
|
85
|
+
return !p.required;
|
|
86
|
+
})) {
|
|
87
|
+
throw CLIError.invalidPositionalArgConfig({
|
|
88
|
+
positionalArgName: param.name,
|
|
89
|
+
message: "Required positional arguments must be before optional positional arguments"
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return AcclimateCLI({
|
|
93
|
+
...state,
|
|
94
|
+
positionalArgs: [
|
|
95
|
+
...state.positionalArgs,
|
|
96
|
+
{ ...param, required: param.required ?? true }
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
addGlobalOption: (param) => {
|
|
101
|
+
const newAliases = (param.aliases ?? []).reduce(
|
|
102
|
+
(acc, alias) => {
|
|
103
|
+
acc[alias] = param.name;
|
|
104
|
+
return acc;
|
|
105
|
+
},
|
|
106
|
+
{}
|
|
107
|
+
);
|
|
108
|
+
return AcclimateCLI({
|
|
109
|
+
...state,
|
|
110
|
+
aliases: { ...state.aliases, ...newAliases },
|
|
111
|
+
globalOptionArgs: {
|
|
112
|
+
...state.globalOptionArgs,
|
|
113
|
+
[param.name]: param
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
addOption: (param) => {
|
|
118
|
+
const newAliases = (param.aliases ?? []).reduce(
|
|
119
|
+
(acc, alias) => {
|
|
120
|
+
acc[alias] = param.name;
|
|
121
|
+
return acc;
|
|
122
|
+
},
|
|
123
|
+
{}
|
|
124
|
+
);
|
|
125
|
+
return AcclimateCLI({
|
|
126
|
+
...state,
|
|
127
|
+
aliases: { ...state.aliases, ...newAliases },
|
|
128
|
+
optionArgs: { ...state.optionArgs, [param.name]: param }
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
addCommand: (commandName, cli) => {
|
|
132
|
+
return AcclimateCLI({
|
|
133
|
+
...state,
|
|
134
|
+
commands: {
|
|
135
|
+
...state.commands,
|
|
136
|
+
[commandName]: cli
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
getCommandCLI: (commandName) => {
|
|
141
|
+
const cmd = state.commands[commandName];
|
|
142
|
+
if (!cmd) {
|
|
143
|
+
throw CLIError.unknownCommand({
|
|
144
|
+
commandName,
|
|
145
|
+
message: `Command "${commandName}" not found`
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return cmd;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/AcclimateCLI/createCLI/defaultCLIState.ts
|
|
154
|
+
var defaultCLIState = {
|
|
155
|
+
aliases: {},
|
|
156
|
+
description: void 0,
|
|
157
|
+
commands: {},
|
|
158
|
+
positionalArgs: [],
|
|
159
|
+
optionArgs: {},
|
|
160
|
+
globalOptionArgs: {},
|
|
161
|
+
action: () => {
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// src/AcclimateCLI/createCLI/createCLI.ts
|
|
166
|
+
function createCLI(name) {
|
|
167
|
+
return AcclimateCLI({ ...defaultCLIState, name });
|
|
168
|
+
}
|
|
169
|
+
function _isValidFullOptionName(name) {
|
|
170
|
+
return name.startsWith("--");
|
|
171
|
+
}
|
|
172
|
+
function _isValidOptionAlias(name) {
|
|
173
|
+
return name.startsWith("-");
|
|
174
|
+
}
|
|
175
|
+
function isEmptyObject(obj) {
|
|
176
|
+
return Object.keys(obj).length === 0;
|
|
177
|
+
}
|
|
178
|
+
function _validateParsedValue(options) {
|
|
179
|
+
const { parsedValue, paramConfig } = options;
|
|
180
|
+
if (paramConfig.validator) {
|
|
181
|
+
const validator = paramConfig.validator;
|
|
182
|
+
const validationResult = validator(parsedValue);
|
|
183
|
+
if (validationResult === true) {
|
|
184
|
+
return parsedValue;
|
|
185
|
+
}
|
|
186
|
+
throw CLIError.invalidCLIParamValue({
|
|
187
|
+
paramName: paramConfig.name,
|
|
188
|
+
paramValue: parsedValue,
|
|
189
|
+
message: typeof validationResult === "string" ? validationResult : void 0
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return parsedValue;
|
|
193
|
+
}
|
|
194
|
+
function _parseAndValidateValue(options) {
|
|
195
|
+
const { inputValue, defaultValue, paramConfig } = options;
|
|
196
|
+
if (inputValue === void 0) {
|
|
197
|
+
if (defaultValue === void 0) {
|
|
198
|
+
if (_isValidFullOptionName(paramConfig.name)) {
|
|
199
|
+
throw CLIError.missingRequiredOption({
|
|
200
|
+
optionName: paramConfig.name
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
throw CLIError.missingRequiredPositionalArg({
|
|
204
|
+
positionalArgName: paramConfig.name
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return _validateParsedValue({
|
|
209
|
+
parsedValue: defaultValue,
|
|
210
|
+
paramConfig
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
const parsedValue = paramConfig.parser ? paramConfig.parser(inputValue) : match(paramConfig.type).with("boolean", () => {
|
|
214
|
+
return inputValue === "false" ? false : true;
|
|
215
|
+
}).with("number", () => {
|
|
216
|
+
return Number.parseInt(inputValue, 10);
|
|
217
|
+
}).with("string", () => {
|
|
218
|
+
return inputValue;
|
|
219
|
+
}).exhaustive(() => {
|
|
220
|
+
return inputValue;
|
|
221
|
+
});
|
|
222
|
+
return _validateParsedValue({
|
|
223
|
+
parsedValue,
|
|
224
|
+
paramConfig
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function _replaceAliases({
|
|
228
|
+
aliasedOptionArgs,
|
|
229
|
+
cli
|
|
230
|
+
}) {
|
|
231
|
+
const aliasMap = cli.state.aliases;
|
|
232
|
+
return Object.entries(aliasedOptionArgs).reduce(
|
|
233
|
+
(acc, [aliasKey, value]) => {
|
|
234
|
+
const alias = aliasKey;
|
|
235
|
+
const optionName = aliasMap[alias] ?? alias;
|
|
236
|
+
acc[optionName] = value;
|
|
237
|
+
return acc;
|
|
238
|
+
},
|
|
239
|
+
{}
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
function _runCLIHelper(options) {
|
|
243
|
+
const { rawGlobalOptionArgs, rawOptionArgs, rawPositionalArgs, cli } = {
|
|
244
|
+
...options,
|
|
245
|
+
rawGlobalOptionArgs: _replaceAliases({
|
|
246
|
+
aliasedOptionArgs: options.rawGlobalOptionArgs,
|
|
247
|
+
cli: options.cli
|
|
248
|
+
}),
|
|
249
|
+
rawOptionArgs: _replaceAliases({
|
|
250
|
+
aliasedOptionArgs: options.rawOptionArgs,
|
|
251
|
+
// TODO(jpsyx): fix that this does not have the CLI may not have all
|
|
252
|
+
cli: options.cli
|
|
253
|
+
})
|
|
254
|
+
};
|
|
255
|
+
const firstArg = rawPositionalArgs[0];
|
|
256
|
+
if (firstArg && !isEmptyObject(cli.state.commands) && cli.state.commands[firstArg]) {
|
|
257
|
+
const commandCLI = Object.values(
|
|
258
|
+
cli.state.globalOptionArgs
|
|
259
|
+
).reduce(
|
|
260
|
+
(newCmd, argConfig) => {
|
|
261
|
+
return newCmd.addGlobalOption(argConfig);
|
|
262
|
+
},
|
|
263
|
+
cli.getCommandCLI(firstArg)
|
|
264
|
+
);
|
|
265
|
+
return _runCLIHelper({
|
|
266
|
+
rawPositionalArgs: rawPositionalArgs.slice(1),
|
|
267
|
+
rawOptionArgs,
|
|
268
|
+
rawGlobalOptionArgs,
|
|
269
|
+
cli: commandCLI
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (rawPositionalArgs.length > cli.state.positionalArgs.length) {
|
|
273
|
+
throw CLIError.tooManyPositionalArgs({
|
|
274
|
+
count: rawPositionalArgs.length
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
const parsedPositionalArgs = cli.state.positionalArgs.reduce(
|
|
278
|
+
(acc, argConfig, idx) => {
|
|
279
|
+
const rawVal = rawPositionalArgs[idx];
|
|
280
|
+
if (argConfig.required && rawVal === void 0) {
|
|
281
|
+
throw CLIError.missingRequiredPositionalArg({
|
|
282
|
+
positionalArgName: argConfig.name
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
acc[argConfig.name] = _parseAndValidateValue({
|
|
286
|
+
inputValue: rawVal,
|
|
287
|
+
defaultValue: argConfig.defaultValue,
|
|
288
|
+
paramConfig: argConfig
|
|
289
|
+
});
|
|
290
|
+
return acc;
|
|
291
|
+
},
|
|
292
|
+
{}
|
|
293
|
+
);
|
|
294
|
+
const parsedOptionArgs = Object.values(
|
|
295
|
+
cli.state.optionArgs
|
|
296
|
+
).reduce(
|
|
297
|
+
(acc, argConfig) => {
|
|
298
|
+
const rawVal = rawOptionArgs[argConfig.name];
|
|
299
|
+
if (argConfig.required && rawVal === void 0) {
|
|
300
|
+
throw CLIError.missingRequiredOption({
|
|
301
|
+
optionName: argConfig.name
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
acc[camelCase(argConfig.name)] = _parseAndValidateValue({
|
|
305
|
+
inputValue: rawVal,
|
|
306
|
+
defaultValue: argConfig.defaultValue,
|
|
307
|
+
paramConfig: argConfig
|
|
308
|
+
});
|
|
309
|
+
return acc;
|
|
310
|
+
},
|
|
311
|
+
{}
|
|
312
|
+
);
|
|
313
|
+
const parsedGlobalOptionArgs = Object.values(
|
|
314
|
+
cli.state.globalOptionArgs
|
|
315
|
+
).reduce(
|
|
316
|
+
(acc, argConfig) => {
|
|
317
|
+
const rawVal = rawGlobalOptionArgs[argConfig.name];
|
|
318
|
+
if (argConfig.required && rawVal === void 0) {
|
|
319
|
+
throw CLIError.missingRequiredOption({
|
|
320
|
+
optionName: argConfig.name
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
acc[camelCase(argConfig.name)] = _parseAndValidateValue({
|
|
324
|
+
inputValue: rawVal,
|
|
325
|
+
defaultValue: argConfig.defaultValue,
|
|
326
|
+
paramConfig: argConfig
|
|
327
|
+
});
|
|
328
|
+
return acc;
|
|
329
|
+
},
|
|
330
|
+
{}
|
|
331
|
+
);
|
|
332
|
+
cli.state.action({
|
|
333
|
+
...parsedPositionalArgs,
|
|
334
|
+
...parsedOptionArgs,
|
|
335
|
+
...parsedGlobalOptionArgs
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
function runCLI(options) {
|
|
339
|
+
const { input, cli } = options;
|
|
340
|
+
const firstOptionIdx = input.findIndex((token) => {
|
|
341
|
+
return token.startsWith("-");
|
|
342
|
+
});
|
|
343
|
+
const [rawPositionalArgs, rest] = firstOptionIdx === -1 ? [input, []] : [input.slice(0, firstOptionIdx), input.slice(firstOptionIdx)];
|
|
344
|
+
const rawOptionArgs = {};
|
|
345
|
+
const rawGlobalOptionArgs = {};
|
|
346
|
+
let currentAlias;
|
|
347
|
+
let currentVals = [];
|
|
348
|
+
const { aliases, globalOptionArgs } = cli.state;
|
|
349
|
+
for (const argVal of rest.concat("-")) {
|
|
350
|
+
if (_isValidOptionAlias(argVal)) {
|
|
351
|
+
if (currentAlias) {
|
|
352
|
+
const rawValue = currentVals.join(" ");
|
|
353
|
+
const optionName = aliases[currentAlias] ?? currentAlias;
|
|
354
|
+
if (_isValidFullOptionName(optionName) && !isEmptyObject(globalOptionArgs) && globalOptionArgs[optionName]) {
|
|
355
|
+
rawGlobalOptionArgs[optionName] = rawValue;
|
|
356
|
+
} else {
|
|
357
|
+
rawOptionArgs[optionName] = rawValue;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
currentAlias = argVal;
|
|
361
|
+
currentVals = [];
|
|
362
|
+
} else {
|
|
363
|
+
currentVals.push(argVal);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
_runCLIHelper({ rawPositionalArgs, rawOptionArgs, rawGlobalOptionArgs, cli });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/Acclimate.ts
|
|
370
|
+
var Acclimate = {
|
|
371
|
+
createCLI,
|
|
372
|
+
run: (cli) => {
|
|
373
|
+
runCLI({ cli, input: process.argv.slice(2) });
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
export { Acclimate };
|
|
378
|
+
//# sourceMappingURL=index.js.map
|
|
379
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/CLIError.ts","../src/AcclimateCLI/AcclimateCLI.ts","../src/AcclimateCLI/createCLI/defaultCLIState.ts","../src/AcclimateCLI/createCLI/createCLI.ts","../src/AcclimateCLI/runCLI/runCLI.ts","../src/Acclimate.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { CLIParamDataType } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype CLIErrorInfo =\n | {\n code: \"already_run\";\n details: undefined;\n }\n | {\n code: \"unknown_command\";\n details: { commandName: string };\n }\n | {\n code: \"invalid_positional_arg_config\";\n details: { positionalArgName: string };\n }\n | {\n code: \"too_many_positional_args\";\n details: { count: number };\n }\n | {\n code: \"missing_required_positional_arg\";\n details: { positionalArgName: string };\n }\n | {\n code: \"missing_required_option\";\n details: { optionName: string };\n }\n | {\n code: \"unknown_option\";\n details: {\n optionName: string;\n };\n }\n | {\n code: \"invalid_cli_param_value\";\n details: {\n paramName: string;\n paramValue: CLIParamDataType;\n };\n }\n | { code: \"unknown_error\"; details: undefined };\n\ntype CLIErrorOptions = { message: string } & CLIErrorInfo;\n\nexport class CLIError extends Error {\n static invalidCLIParamValue(options: {\n paramName: string;\n paramValue: CLIParamDataType;\n message?: string;\n }): CLIError {\n return new CLIError({\n message:\n options.message ?? `Invalid value for CLI param \"${options.paramName}\"`,\n code: \"invalid_cli_param_value\",\n details: { paramName: options.paramName, paramValue: options.paramValue },\n });\n }\n static missingRequiredOption(options: {\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n message:\n options.message ?? `Required option \"${options.optionName}\" is missing`,\n code: \"missing_required_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static missingRequiredPositionalArg(options: {\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n message:\n options.message ??\n `Required positional argument \"${options.positionalArgName}\" is missing`,\n code: \"missing_required_positional_arg\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownOption(options: {\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n message: options.message ?? `Option \"${options.optionName}\" not found`,\n code: \"unknown_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static tooManyPositionalArgs(options: {\n count: number;\n message?: string;\n }): CLIError {\n return new CLIError({\n message: options.message ?? \"Too many positional arguments provided.\",\n code: \"too_many_positional_args\",\n details: { count: options.count },\n });\n }\n\n static invalidPositionalArgConfig(options: {\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n message:\n options.message ??\n `Positional argument configuration for \"${options.positionalArgName}\" is invalid`,\n code: \"invalid_positional_arg_config\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownCommand(options: {\n commandName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n message: options.message ?? `Command \"${options.commandName}\" not found`,\n code: \"unknown_command\",\n details: { commandName: options.commandName },\n });\n }\n\n static alreadyRun(options: { message?: string } = {}): CLIError {\n return new CLIError({\n message: options.message ?? \"CLI has already been run\",\n code: \"already_run\",\n details: undefined,\n });\n }\n\n constructor(options: CLIErrorOptions) {\n super(`❌ ${options.message}`);\n }\n}\n","import { CLIError } from \"@/CLIError\";\nimport type {\n AddEntry,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n} from \"./AcclimateCLI.types\";\nimport type { EmptyObject, Simplify } from \"type-fest\";\n\nexport function AcclimateCLI<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, IAcclimateCLI> | EmptyObject,\n>(\n state: CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n> {\n return {\n state,\n\n action: (\n action: (\n args: Simplify<\n FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >\n >,\n ) => void,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n action,\n });\n },\n\n description: (\n description: string,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n description,\n });\n },\n\n addPositionalArg: <\n PName extends CLIPositionalParamName,\n P extends CLIPositionalParam<PName>,\n >(\n param: P,\n ) => {\n if (\n param.required &&\n state.positionalArgs.some((p) => {\n return !p.required;\n })\n ) {\n throw CLIError.invalidPositionalArgConfig({\n positionalArgName: param.name,\n message:\n \"Required positional arguments must be before optional positional arguments\",\n });\n }\n\n return AcclimateCLI({\n ...state,\n positionalArgs: [\n ...state.positionalArgs,\n { ...param, required: param.required ?? true },\n ],\n } as unknown as CLIState<\n AddEntry<TPositionalParams, P[\"name\"], P>,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addGlobalOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n globalOptionArgs: {\n ...state.globalOptionArgs,\n [param.name]: param,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >);\n },\n\n addOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n optionArgs: { ...state.optionArgs, [param.name]: param },\n } as unknown as CLIState<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addCommand: <C extends CLICommandName, CommandCLI extends IAcclimateCLI>(\n commandName: C,\n cli: CommandCLI,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n > => {\n return AcclimateCLI({\n ...state,\n commands: {\n ...state.commands,\n [commandName]: cli,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n >);\n },\n\n getCommandCLI: <C extends Extract<keyof TCommands, CLICommandName>>(\n commandName: C,\n ): C extends keyof TCommands ? TCommands[C] : never => {\n const cmd = state.commands[commandName];\n if (!cmd) {\n throw CLIError.unknownCommand({\n commandName,\n message: `Command \"${commandName}\" not found`,\n });\n }\n return cmd as C extends keyof TCommands ? TCommands[C] : never;\n },\n };\n}\n","import type { CLIState } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nexport const defaultCLIState: Omit<\n CLIState<EmptyObject, EmptyObject, EmptyObject, EmptyObject>,\n \"name\"\n> = {\n aliases: {},\n description: undefined,\n commands: {},\n positionalArgs: [],\n optionArgs: {},\n globalOptionArgs: {},\n action: () => {},\n};\n","import { AcclimateCLI } from \"../AcclimateCLI\";\nimport { defaultCLIState } from \"./defaultCLIState\";\nimport type { IAcclimateCLI } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\n/**\n * Builder function to create a new CLI instance with a given name.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\nexport function createCLI(\n name: string,\n): IAcclimateCLI<EmptyObject, EmptyObject, EmptyObject, EmptyObject> {\n return AcclimateCLI({ ...defaultCLIState, name });\n}\n","import { camelCase } from \"change-case\";\nimport { match } from \"ts-pattern\";\nimport { CLIError } from \"@/CLIError\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionAlias,\n CLIOptionParam,\n CLIParam,\n CLIParamDataType,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n ValueOfParam,\n} from \"@/AcclimateCLI/AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nfunction _isValidFullOptionName(name: string): name is CLIFullOptionName {\n return name.startsWith(\"--\");\n}\n\nfunction _isValidOptionAlias(name: string): name is CLIOptionAlias {\n return name.startsWith(\"-\");\n}\n\nfunction isEmptyObject(obj: object): obj is EmptyObject {\n return Object.keys(obj).length === 0;\n}\n\nfunction _validateParsedValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: { parsedValue: PValue; paramConfig: P }): PValue {\n const { parsedValue, paramConfig } = options;\n if (paramConfig.validator) {\n const validator = paramConfig.validator as (\n value: PValue,\n ) => boolean | string;\n const validationResult = validator(parsedValue);\n if (validationResult === true) {\n return parsedValue;\n }\n throw CLIError.invalidCLIParamValue({\n paramName: paramConfig.name,\n paramValue: parsedValue,\n message:\n typeof validationResult === \"string\" ? validationResult : undefined,\n });\n }\n return parsedValue;\n}\n\nfunction _parseAndValidateValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: {\n inputValue: string | undefined;\n defaultValue: PValue | undefined;\n paramConfig: P;\n}): PValue {\n const { inputValue, defaultValue, paramConfig } = options;\n if (inputValue === undefined) {\n // if there is no input value, we use the default value for validation.\n // if there is no default value, we throw an error.\n if (defaultValue === undefined) {\n if (_isValidFullOptionName(paramConfig.name)) {\n throw CLIError.missingRequiredOption({\n optionName: paramConfig.name,\n });\n } else {\n throw CLIError.missingRequiredPositionalArg({\n positionalArgName: paramConfig.name,\n });\n }\n }\n\n // and then just validate it. (no need to parse it first)\n return _validateParsedValue({\n parsedValue: defaultValue,\n paramConfig,\n });\n }\n\n const parsedValue =\n paramConfig.parser ?\n (paramConfig.parser(inputValue) as PValue)\n // if no parser was set, we use the default parser\n : (match(paramConfig.type)\n .with(\"boolean\", () => {\n return inputValue === \"false\" ? false : true;\n })\n .with(\"number\", () => {\n return Number.parseInt(inputValue, 10);\n })\n .with(\"string\", () => {\n return inputValue;\n })\n .exhaustive(() => {\n return inputValue;\n }) as PValue);\n return _validateParsedValue({\n parsedValue,\n paramConfig,\n });\n}\n\nfunction _replaceAliases<\n TGlobalOptionArgs extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TOptionArgs extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TPositionalArgs extends\n | Record<CLIPositionalParamName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>({\n aliasedOptionArgs,\n cli,\n}: {\n aliasedOptionArgs: Record<CLIOptionAlias, string>;\n cli: IAcclimateCLI<\n TGlobalOptionArgs,\n TOptionArgs,\n TPositionalArgs,\n TCommands\n >;\n}): Record<CLIOptionAlias, string> {\n const aliasMap = cli.state.aliases;\n return Object.entries(aliasedOptionArgs).reduce(\n (acc, [aliasKey, value]) => {\n const alias = aliasKey as CLIOptionAlias;\n const optionName = aliasMap[alias] ?? alias;\n acc[optionName] = value;\n return acc;\n },\n {} as Record<CLIOptionAlias, string>,\n );\n}\n\nfunction _runCLIHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(options: {\n rawPositionalArgs: string[];\n rawOptionArgs: Record<CLIOptionAlias, string>;\n rawGlobalOptionArgs: Record<CLIFullOptionName, string>;\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >;\n}): void {\n const { rawGlobalOptionArgs, rawOptionArgs, rawPositionalArgs, cli } = {\n ...options,\n rawGlobalOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawGlobalOptionArgs,\n cli: options.cli,\n }),\n rawOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawOptionArgs,\n\n // TODO(jpsyx): fix that this does not have the CLI may not have all\n cli: options.cli,\n }),\n };\n\n // is the first argument a command?\n const firstArg = rawPositionalArgs[0];\n if (\n firstArg &&\n !isEmptyObject(cli.state.commands) &&\n cli.state.commands[firstArg]\n ) {\n // add the parent's global options to the sub-command\n const commandCLI = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (newCmd, argConfig) => {\n return newCmd.addGlobalOption(argConfig);\n },\n cli.getCommandCLI(firstArg as Extract<keyof TCommands, string>) as AnyCLI,\n );\n\n // run the sub-command\n return _runCLIHelper({\n rawPositionalArgs: rawPositionalArgs.slice(1),\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli: commandCLI,\n });\n }\n\n // build the positional arguments dictionary\n // first check that we haven't supplied too many positional arguments\n if (rawPositionalArgs.length > cli.state.positionalArgs.length) {\n throw CLIError.tooManyPositionalArgs({\n count: rawPositionalArgs.length,\n });\n }\n\n // parse positional arguments\n const parsedPositionalArgs = cli.state.positionalArgs.reduce(\n (acc, argConfig, idx) => {\n const rawVal = rawPositionalArgs[idx];\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredPositionalArg({\n positionalArgName: argConfig.name,\n });\n }\n acc[argConfig.name] = _parseAndValidateValue({\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n return acc;\n },\n {} as Record<string, CLIParamDataType>,\n );\n\n // parse the options\n const parsedOptionArgs = Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (acc, argConfig) => {\n const rawVal = rawOptionArgs[argConfig.name];\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n optionName: argConfig.name,\n });\n }\n\n acc[camelCase(argConfig.name)] = _parseAndValidateValue({\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n return acc;\n },\n {} as Record<string, CLIParamDataType>,\n );\n\n // parse the global options\n const parsedGlobalOptionArgs = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (acc, argConfig) => {\n const rawVal = rawGlobalOptionArgs[argConfig.name];\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n optionName: argConfig.name,\n });\n }\n acc[camelCase(argConfig.name)] = _parseAndValidateValue({\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n return acc;\n },\n {} as Record<string, CLIParamDataType>,\n );\n\n // run the action\n cli.state.action({\n ...parsedPositionalArgs,\n ...parsedOptionArgs,\n ...parsedGlobalOptionArgs,\n } as FullCLIArgValues<TPositionalParams, TOptionParams, TGlobalOptionParams>);\n}\n\n/**\n * Run a CLI instance given an array of inputs.\n *\n * @param options - The options for running the CLI.\n */\nexport function runCLI(options: { input: string[]; cli: AnyCLI }): void {\n const { input, cli } = options;\n const firstOptionIdx = input.findIndex((token) => {\n return token.startsWith(\"-\");\n });\n\n const [rawPositionalArgs, rest] =\n firstOptionIdx === -1 ?\n [input, []]\n : [input.slice(0, firstOptionIdx), input.slice(firstOptionIdx)];\n\n const rawOptionArgs: Record<CLIOptionAlias, string> = {};\n const rawGlobalOptionArgs: Record<CLIFullOptionName, string> = {};\n let currentAlias: CLIOptionAlias | undefined;\n let currentVals: string[] = [];\n\n const { aliases, globalOptionArgs } = cli.state as CLIState<\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIPositionalParamName, CLIOptionParam>,\n Record<CLICommandName, AnyCLI>\n >;\n\n for (const argVal of rest.concat(\"-\")) {\n if (_isValidOptionAlias(argVal)) {\n if (currentAlias) {\n const rawValue = currentVals.join(\" \");\n const optionName = aliases[currentAlias] ?? currentAlias;\n if (\n _isValidFullOptionName(optionName) &&\n !isEmptyObject(globalOptionArgs) &&\n globalOptionArgs[optionName]\n ) {\n rawGlobalOptionArgs[optionName] = rawValue;\n } else {\n rawOptionArgs[optionName] = rawValue;\n }\n }\n currentAlias = argVal;\n currentVals = [];\n } else {\n currentVals.push(argVal);\n }\n }\n\n _runCLIHelper({ rawPositionalArgs, rawOptionArgs, rawGlobalOptionArgs, cli });\n}\n","import { createCLI } from \"./AcclimateCLI\";\nimport { runCLI } from \"./AcclimateCLI/runCLI/runCLI\";\nimport type { IAcclimateCLI } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype Acclimate = {\n /**\n * Create a new Acclimate CLI instance.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\n createCLI: (name: string) => IAcclimateCLI;\n\n /**\n * Run a CLI instance.\n *\n * It can only be run once. Calling any other methods after `.run()` will\n * throw an error.\n *\n * @param cli - The CLI instance to run.\n */\n run: (cli: IAcclimateCLI) => void;\n};\n\nexport const Acclimate: Acclimate = {\n createCLI,\n run: (cli: IAcclimateCLI) => {\n runCLI({ cli, input: process.argv.slice(2) });\n },\n};\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@avandar/acclimate",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight TypeScript framework for building CLI tools.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"dev": "tsup --watch",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"lint:fix": "eslint . --fix",
|
|
28
|
+
"format": "prettier . --write",
|
|
29
|
+
"format:fix": "prettier . --write",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest watch",
|
|
32
|
+
"demo": "tsx examples/basic.ts",
|
|
33
|
+
"prepare": "npm run build",
|
|
34
|
+
"type": "tsc -p tsconfig.json --noEmit"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"cli",
|
|
38
|
+
"framework",
|
|
39
|
+
"typescript"
|
|
40
|
+
],
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": ""
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"change-case": "^5.4.4",
|
|
47
|
+
"ts-pattern": "^5.9.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@eslint/js": "^9.39.1",
|
|
51
|
+
"@ianvs/prettier-plugin-sort-imports": "^4.7.0",
|
|
52
|
+
"@types/node": "^22.19.2",
|
|
53
|
+
"eslint": "^9.39.1",
|
|
54
|
+
"eslint-config-prettier": "^9.1.2",
|
|
55
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
56
|
+
"eslint-plugin-import-x": "^4.16.1",
|
|
57
|
+
"eslint-plugin-unused-imports": "^4.3.0",
|
|
58
|
+
"prettier": "^3.7.4",
|
|
59
|
+
"tsup": "^8.5.1",
|
|
60
|
+
"tsx": "^4.21.0",
|
|
61
|
+
"type-fest": "^5.3.1",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"typescript-eslint": "^8.49.0",
|
|
64
|
+
"vitest": "^2.1.9"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
}
|
|
69
|
+
}
|