expensify-common 2.0.182 → 2.0.184

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.
Files changed (45) hide show
  1. package/dist/API.js +19 -24
  2. package/dist/APIDeferred.js +5 -5
  3. package/dist/CLI.d.ts +160 -0
  4. package/dist/CLI.js +282 -0
  5. package/dist/CONST.js +1 -1
  6. package/dist/Cookie.d.ts +5 -5
  7. package/dist/Cookie.js +6 -6
  8. package/dist/ExpenseRule.d.ts +10 -10
  9. package/dist/ExpenseRule.js +9 -9
  10. package/dist/ExpensiMark.d.ts +23 -51
  11. package/dist/ExpensiMark.js +311 -333
  12. package/dist/Func.js +3 -1
  13. package/dist/Log.js +1 -1
  14. package/dist/Logger.d.ts +2 -2
  15. package/dist/Logger.js +6 -4
  16. package/dist/Network.js +10 -10
  17. package/dist/Num.d.ts +1 -1
  18. package/dist/Num.js +9 -5
  19. package/dist/PageEvent.d.ts +2 -2
  20. package/dist/PageEvent.js +1 -1
  21. package/dist/PubSub.js +7 -7
  22. package/dist/ReportHistoryStore.d.ts +8 -71
  23. package/dist/ReportHistoryStore.js +106 -180
  24. package/dist/SafeString.d.ts +8 -0
  25. package/dist/SafeString.js +52 -0
  26. package/dist/Templates.d.ts +13 -13
  27. package/dist/Templates.js +157 -183
  28. package/dist/components/StepProgressBar.d.ts +8 -4
  29. package/dist/components/StepProgressBar.js +4 -3
  30. package/dist/components/form/element/combobox.d.ts +1 -8
  31. package/dist/components/form/element/combobox.js +37 -37
  32. package/dist/components/form/element/switch.d.ts +2 -2
  33. package/dist/components/form/element/switch.js +7 -5
  34. package/dist/fastMerge.js +0 -2
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +5 -2
  37. package/dist/jquery.expensifyIframify.d.ts +1 -2
  38. package/dist/jquery.expensifyIframify.js +13 -15
  39. package/dist/md5.js +30 -29
  40. package/dist/mixins/PubSub.js +2 -2
  41. package/dist/str.d.ts +31 -0
  42. package/dist/str.js +69 -19
  43. package/dist/utils.d.ts +4 -4
  44. package/dist/utils.js +6 -6
  45. package/package.json +12 -10
package/dist/API.js CHANGED
@@ -106,18 +106,18 @@ function API(network, args) {
106
106
  * @param {String} apiDeferred
107
107
  */
108
108
  function attachJSONCodeCallbacks(apiDeferred) {
109
- Object.entries(defaultHandlers).forEach(([code, callbacks]) => {
109
+ for (const [code, callbacks] of Object.entries(defaultHandlers)) {
110
110
  // The key, `code`, is returned as a string, so we must cast it to an Integer
111
111
  const jsonCode = parseInt(code, 10);
112
- callbacks.forEach((callback) => {
112
+ for (const callback of callbacks) {
113
113
  if (jsonCode === 200) {
114
114
  apiDeferred.done(callback);
115
115
  }
116
116
  else {
117
117
  apiDeferred.handle([jsonCode], callback);
118
118
  }
119
- });
120
- });
119
+ }
120
+ }
121
121
  }
122
122
  /**
123
123
  * @private
@@ -174,10 +174,9 @@ function API(network, args) {
174
174
  * @param {String} commandName The name of the API command
175
175
  */
176
176
  function requireParameters(parameterNames, parameters, commandName) {
177
- // eslint-disable-next-line rulesdir/prefer-early-return
178
- parameterNames.forEach((parameterName) => {
177
+ for (const parameterName of parameterNames) {
179
178
  if ((0, has_1.default)(parameters, parameterName) && parameters[parameterName] !== null && parameters[parameterName] !== undefined) {
180
- return;
179
+ continue;
181
180
  }
182
181
  const parametersCopy = Object.assign({}, parameters);
183
182
  if ((0, has_1.default)(parametersCopy, 'authToken')) {
@@ -188,7 +187,7 @@ function API(network, args) {
188
187
  }
189
188
  const keys = Object.keys(parametersCopy).join(', ') || 'none';
190
189
  throw new Error(`Parameter ${parameterName} is required for "${commandName}". Supplied parameters: ${keys}`);
191
- });
190
+ }
192
191
  }
193
192
  return {
194
193
  /**
@@ -199,12 +198,12 @@ function API(network, args) {
199
198
  if (!Utils.isFunction(callback)) {
200
199
  return;
201
200
  }
202
- jsonCodes.forEach((jsonCode) => {
201
+ for (const jsonCode of jsonCodes) {
203
202
  if (!defaultHandlers[jsonCode]) {
204
203
  defaultHandlers[jsonCode] = [];
205
204
  }
206
205
  defaultHandlers[jsonCode].push(callback);
207
- });
206
+ }
208
207
  },
209
208
  /**
210
209
  * Whether or not the JS code version has changed on the server compared to what was loaded on the page.
@@ -240,7 +239,7 @@ function API(network, args) {
240
239
  * @param {String} [data.returnedPropertyType]
241
240
  * @param {Boolean} [data.checkCodeRevision]
242
241
  *
243
- * @return {Function}
242
+ * @returns {Function}
244
243
  */
245
244
  extendMethod: (data) => {
246
245
  if (!data.commandName) {
@@ -256,14 +255,14 @@ function API(network, args) {
256
255
  };
257
256
  },
258
257
  /**
259
- * @return {Network}
258
+ * @returns {Network}
260
259
  */
261
260
  getNetwork() {
262
261
  return network;
263
262
  },
264
263
  /**
265
264
  * @param {Object} parameters
266
- * @return {ExpensifyAPIDeferred}
265
+ * @returns {ExpensifyAPIDeferred}
267
266
  */
268
267
  logToServer(parameters) {
269
268
  const commandName = 'Log';
@@ -272,7 +271,7 @@ function API(network, args) {
272
271
  /**
273
272
  * @param {Object} parameters
274
273
  * @param {String} parameters.email
275
- * @return {ExpensifyAPIDeferred}
274
+ * @returns {ExpensifyAPIDeferred}
276
275
  */
277
276
  getAccountStatus(parameters) {
278
277
  const commandName = 'GetAccountStatus';
@@ -284,7 +283,7 @@ function API(network, args) {
284
283
  /**
285
284
  * @param {Object} parameters
286
285
  * @param {String} parameters.email
287
- * @return {ExpensifyAPIDeferred}
286
+ * @returns {ExpensifyAPIDeferred}
288
287
  */
289
288
  Domain_RequestAccess(parameters) {
290
289
  const commandName = 'Domain_RequestAccess';
@@ -327,9 +326,7 @@ function API(network, args) {
327
326
  /**
328
327
  * Performs API command "Get"
329
328
  *
330
- * @param {Object} parameters The API call parameters, must contain "returnValueList"
331
- * @param {Domain} [domain] If you want to run this command as the domain account of this domain
332
- * @param {DomainMember} [domainMember] If you want to run this command as specified domain member
329
+ * @param {Object} parameters The API call parameters, must contain "returnValueList". May also include "domain" and "domainMember".
333
330
  *
334
331
  * @returns {APIDeferred} An APIDeferred representing the promise of this request
335
332
  */
@@ -394,7 +391,7 @@ function API(network, args) {
394
391
  * @param {Object} parameters
395
392
  * @param {String} [parameters.email]
396
393
  *
397
- * @return {ExpensifyAPIDeferred}
394
+ * @returns {ExpensifyAPIDeferred}
398
395
  */
399
396
  resendValidateCode(parameters = {}) {
400
397
  const commandName = 'ResendValidateCode';
@@ -406,7 +403,7 @@ function API(network, args) {
406
403
  * @param {Object} parameters
407
404
  * @param {String} parameters.email
408
405
  *
409
- * @return {ExpensifyAPIDeferred}
406
+ * @returns {ExpensifyAPIDeferred}
410
407
  */
411
408
  reopenAccount(parameters) {
412
409
  const commandName = 'User_ReopenAccount';
@@ -442,9 +439,7 @@ function API(network, args) {
442
439
  /**
443
440
  * Validate a user
444
441
  *
445
- * @param {Object} parameters
446
- * @param {String} validateCode
447
- * @param {Number} accountID
442
+ * @param {Object} parameters Must contain validateCode and accountID
448
443
  * @returns {ExpensifyAPIDeferred}
449
444
  */
450
445
  validateEmail(parameters) {
@@ -517,7 +512,7 @@ function API(network, args) {
517
512
  * Performs API command GetRequestCountryCode
518
513
  * Fetches the country code based on the location of the request
519
514
  *
520
- * @return {APIDeferred}
515
+ * @returns {APIDeferred}
521
516
  */
522
517
  getRequestCountryCode() {
523
518
  const commandName = 'GetRequestCountryCode';
@@ -42,6 +42,7 @@ exports.default = APIDeferred;
42
42
  * WIP, This is in the process of migration from web-e. Please add methods to this as is needed.|
43
43
  * ----------------------------------------------------------------------------------------------
44
44
  */
45
+ const get_1 = __importDefault(require("lodash/get"));
45
46
  const once_1 = __importDefault(require("lodash/once"));
46
47
  const Utils = __importStar(require("./utils"));
47
48
  const Func = __importStar(require("./Func"));
@@ -83,9 +84,8 @@ function APIDeferred(promise, extractedProperty) {
83
84
  * @param {Object} [response]
84
85
  */
85
86
  function handleError(jsonCode, response) {
86
- var _a;
87
87
  // Look for handlers for this error code
88
- const handlers = (_a = errorHandlers[jsonCode]) !== null && _a !== void 0 ? _a : [];
88
+ const handlers = (0, get_1.default)(errorHandlers, jsonCode, []);
89
89
  if (handlers.length > 0) {
90
90
  Func.bulkInvoke(handlers, [jsonCode, response]);
91
91
  }
@@ -192,15 +192,15 @@ function APIDeferred(promise, extractedProperty) {
192
192
  */
193
193
  handle(jsonCodes, callback) {
194
194
  if (Utils.isFunction(callback)) {
195
- jsonCodes.forEach((code) => {
195
+ for (const code of jsonCodes) {
196
196
  if (code === 200) {
197
- return;
197
+ continue;
198
198
  }
199
199
  if (!errorHandlers[code]) {
200
200
  errorHandlers[code] = [];
201
201
  }
202
202
  errorHandlers[code].push((0, once_1.default)(callback));
203
- });
203
+ }
204
204
  ensureFutureCallbacksFire();
205
205
  }
206
206
  return this;
package/dist/CLI.d.ts ADDED
@@ -0,0 +1,160 @@
1
+ import type { NonEmptyObject, NonEmptyTuple } from 'type-fest';
2
+ /**
3
+ * A base CLI arg has only a description, which we will use in the help/usage message (built-in to any CLI).
4
+ */
5
+ type CLIArg = {
6
+ description: string;
7
+ };
8
+ /**
9
+ * A boolean arg is characterized only by its presence or absence so has no other fields,
10
+ * but we'll create a type alias to clearly distinguish it from other argument types.
11
+ */
12
+ type BooleanArg = CLIArg;
13
+ /**
14
+ * Any other argument is provided raw in process.argv as a string.
15
+ * It can remain a string, or can be transformed into another type by a custom `parse` function.
16
+ * It can be optional (by providing a default) or required (no default value).
17
+ * It can also supersede other named arguments when provided.
18
+ */
19
+ type StringArg<T = unknown> = CLIArg & {
20
+ default?: T;
21
+ parse?: (val: string) => T;
22
+ supersedes?: string[];
23
+ required?: boolean;
24
+ };
25
+ /**
26
+ * A positional argument is just a string arg, but also must be assigned a name which we will eventually expose the CLI consumer.
27
+ * If `variadic` is true, this must be the last positional arg and it collects all remaining positional args into a string[].
28
+ */
29
+ type PositionalArg<T = unknown> = StringArg<T> & {
30
+ name: string;
31
+ variadic?: true;
32
+ };
33
+ /**
34
+ * This type represents the config for a CLI.
35
+ * The last positional arg can be marked `variadic: true` to collect all remaining positional args into a string[].
36
+ */
37
+ type CLIConfig = NonEmptyObject<{
38
+ /**
39
+ * Record of named flags that are fully characterized by their presence or absence (present=true,absent=false).
40
+ * @example `--verbose`
41
+ */
42
+ flags?: Record<string, BooleanArg>;
43
+ /**
44
+ * Record of named arguments that are represented by a key and a value.
45
+ * @example `--threads=8`
46
+ * @example `--name Rory`
47
+ */
48
+ namedArgs?: Record<string, StringArg>;
49
+ /**
50
+ * Tuple of positional args.
51
+ * @example `myScript.ts arg1 arg2 arg3`
52
+ */
53
+ positionalArgs?: NonEmptyTuple<PositionalArg>;
54
+ }>;
55
+ /**
56
+ * Record of flags to boolean after parsing.
57
+ */
58
+ type ParsedFlags<Flags extends CLIConfig['flags']> = {
59
+ [K in keyof NonNullable<Flags>]: boolean;
60
+ };
61
+ /**
62
+ * Utility type to infer the final value of a string param. Either:
63
+ * - it's a plain string, or
64
+ * - it has a parse function and the final value is inferred from the return type of that function
65
+ */
66
+ type InferStringArgParsedValue<T extends StringArg> = T extends {
67
+ parse: (val: string) => infer R;
68
+ } ? R : string;
69
+ /**
70
+ * Record of named args after parsing.
71
+ */
72
+ type ParsedNamedArgs<NamedArgs extends CLIConfig['namedArgs']> = {
73
+ [K in keyof NonNullable<NamedArgs>]: InferStringArgParsedValue<NonNullable<NamedArgs>[K]>;
74
+ };
75
+ /**
76
+ * Record of positional args after parsing.
77
+ * Variadic args are parsed as string[]; all others use InferStringArgParsedValue.
78
+ */
79
+ type ParsedPositionalArgs<PositionalArgs extends CLIConfig['positionalArgs']> = {
80
+ [K in NonNullable<PositionalArgs>[number] as K['name']]: K extends {
81
+ variadic: true;
82
+ } ? string[] : InferStringArgParsedValue<K>;
83
+ };
84
+ /**
85
+ * Utility to parse command-line arguments to a script.
86
+ *
87
+ * @example
88
+ * ```
89
+ * const cli = new CLI({
90
+ * flags: {
91
+ * verbose: {
92
+ * description: 'Enable verbose logging',
93
+ * },
94
+ * },
95
+ * namedArgs: {
96
+ * time: {
97
+ * description: 'Time of day to greet (morning or evening)',
98
+ * default: 'morning',
99
+ * parse: (val) => {
100
+ * if (val !== 'morning' && val !== 'evening') {
101
+ * throw new Error('Must be "morning" or "evening"');
102
+ * }
103
+ * return val as 'morning' | 'evening';
104
+ * },
105
+ * },
106
+ * },
107
+ * positionalArgs: [
108
+ * {
109
+ * name: 'firstName'
110
+ * description: 'First name to greet',
111
+ * },
112
+ * {
113
+ * name: 'lastName',
114
+ * description: 'Last name to greet',
115
+ * default: '',
116
+ * },
117
+ * ],
118
+ * });
119
+ *
120
+ * let fullName = cli.positionalArgs.firstName;
121
+ * if (cli.flags.verbose) {
122
+ * fullName += cli.positionalArgs.lastName;
123
+ * }
124
+ * console.log(fullName);
125
+ * console.log(cli.namedArgs.time);
126
+ * ```
127
+ */
128
+ /**
129
+ * Built-in flags that are always available on any CLI.
130
+ */
131
+ type BuiltInFlags = {
132
+ yes: boolean;
133
+ no: boolean;
134
+ help: boolean;
135
+ };
136
+ declare class CLI<TConfig extends CLIConfig> {
137
+ private readonly config;
138
+ /**
139
+ * Flags after parsing (includes built-in flags like --yes, --no, and --help).
140
+ */
141
+ readonly flags: ParsedFlags<TConfig['flags']> & BuiltInFlags;
142
+ /**
143
+ * Named args after parsing.
144
+ */
145
+ readonly namedArgs: ParsedNamedArgs<TConfig['namedArgs']>;
146
+ /**
147
+ * Positional args after parsing, collected into a record keyed by the name of each arg.
148
+ */
149
+ readonly positionalArgs: ParsedPositionalArgs<TConfig['positionalArgs']>;
150
+ constructor(config: TConfig);
151
+ private printHelp;
152
+ private static parseStringArg;
153
+ /**
154
+ * Prompts the user for confirmation and returns true if they confirm (y/yes), false otherwise.
155
+ * If --yes flag was passed, returns true immediately without prompting.
156
+ * If --no flag was passed, returns false immediately without prompting.
157
+ */
158
+ promptUserConfirmation(message: string): Promise<boolean>;
159
+ }
160
+ export default CLI;
package/dist/CLI.js ADDED
@@ -0,0 +1,282 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ /**
49
+ * This file contains a CLI utility class which can be used to declaratively implement a strongly-typed CLI.
50
+ * You provide a CLIConfig defining your arguments, then the class will handle parsing argv, type validation, error handling, and help messages.
51
+ */
52
+ const readline = __importStar(require("readline"));
53
+ const SafeString_1 = __importDefault(require("./SafeString"));
54
+ class CLI {
55
+ constructor(config) {
56
+ var _a, _b, _c, _d, _e, _f;
57
+ this.config = config;
58
+ const rawArgs = process.argv.slice(2);
59
+ // Initialize all flags to false by default (including built-in flags)
60
+ this.flags = Object.assign(Object.assign({}, Object.fromEntries(Object.keys((_a = config.flags) !== null && _a !== void 0 ? _a : {}).map((key) => [key, false]))), { yes: false, no: false, help: false });
61
+ try {
62
+ const parsedNamedArgs = {};
63
+ const parsedPositionalArgs = {};
64
+ const providedNamedArgs = new Set();
65
+ let positionalIndex = 0;
66
+ for (let i = 0; i < rawArgs.length; i++) {
67
+ const rawArg = rawArgs.at(i);
68
+ if (rawArg === undefined) {
69
+ continue;
70
+ }
71
+ if (rawArg.startsWith('--')) {
72
+ // Either a flag or a named param
73
+ const [rawArgName, rawArgValue] = rawArg.slice(2).split('=');
74
+ if (rawArgName in this.flags) {
75
+ // Arg is a flag
76
+ this.flags[rawArgName] = true;
77
+ }
78
+ else if (config.namedArgs && rawArgName in config.namedArgs) {
79
+ // Arg is a named arg
80
+ providedNamedArgs.add(rawArgName);
81
+ // Grab the value from the split token, otherwise go for the next token
82
+ let argValueBeforeParse = '';
83
+ if (rawArgValue) {
84
+ argValueBeforeParse = rawArgValue;
85
+ }
86
+ else {
87
+ argValueBeforeParse = (_b = rawArgs.at(++i)) !== null && _b !== void 0 ? _b : '';
88
+ if (!argValueBeforeParse || argValueBeforeParse.startsWith('--')) {
89
+ throw new Error(`Missing value for --${rawArgName}`);
90
+ }
91
+ }
92
+ const spec = config.namedArgs[rawArgName];
93
+ parsedNamedArgs[rawArgName] = CLI.parseStringArg(argValueBeforeParse, rawArgName, spec);
94
+ }
95
+ else {
96
+ console.error(`Unknown flag: --${rawArgName}`);
97
+ process.exit(1);
98
+ }
99
+ }
100
+ else {
101
+ // Arg is a positional arg
102
+ const spec = (_c = config.positionalArgs) === null || _c === void 0 ? void 0 : _c.at(positionalIndex);
103
+ if (spec === undefined) {
104
+ throw new Error(`Unexpected arg: ${rawArg}`);
105
+ }
106
+ if (spec.variadic) {
107
+ // Variadic: collect this and all remaining non-flag args into an array
108
+ const collected = [];
109
+ for (let j = i; j < rawArgs.length; j++) {
110
+ const remaining = rawArgs.at(j);
111
+ if (remaining === undefined || remaining.startsWith('--')) {
112
+ break;
113
+ }
114
+ collected.push(remaining);
115
+ }
116
+ parsedPositionalArgs[spec.name] = collected;
117
+ break;
118
+ }
119
+ parsedPositionalArgs[spec.name] = CLI.parseStringArg(rawArg, spec.name, spec);
120
+ positionalIndex++;
121
+ }
122
+ }
123
+ // Handle help command
124
+ if (this.flags.help) {
125
+ this.printHelp();
126
+ process.exit(0);
127
+ }
128
+ // Handle supersession logic
129
+ const supersededArgs = new Set();
130
+ for (const [name, spec] of Object.entries((_d = config.namedArgs) !== null && _d !== void 0 ? _d : {})) {
131
+ if (providedNamedArgs.has(name) && spec.supersedes) {
132
+ for (const supersededArg of spec.supersedes) {
133
+ supersededArgs.add(supersededArg);
134
+ if (providedNamedArgs.has(supersededArg)) {
135
+ console.warn(`⚠️ Warning: --${supersededArg} is superseded by --${name} and will be ignored.`);
136
+ }
137
+ }
138
+ }
139
+ }
140
+ // Validate that all required args are present, assign defaults where values are not parsed
141
+ for (const [name, spec] of Object.entries((_e = config.namedArgs) !== null && _e !== void 0 ? _e : {})) {
142
+ if (name in parsedNamedArgs) {
143
+ if (supersededArgs.has(name)) {
144
+ parsedNamedArgs[name] = undefined;
145
+ }
146
+ }
147
+ else if (supersededArgs.has(name)) {
148
+ // This arg was superseded, so don't require it and don't assign a default
149
+ continue;
150
+ }
151
+ else if (spec.default !== undefined) {
152
+ parsedNamedArgs[name] = spec.default;
153
+ }
154
+ else if (spec.required === false) {
155
+ // Explicitly marked as optional, leave undefined
156
+ continue;
157
+ }
158
+ else {
159
+ // Arguments without defaults are required by default (unless explicitly marked as optional)
160
+ throw new Error(`Missing required named argument --${name}`);
161
+ }
162
+ }
163
+ for (const spec of (_f = config.positionalArgs) !== null && _f !== void 0 ? _f : []) {
164
+ if (!(spec.name in parsedPositionalArgs)) {
165
+ if (spec.default !== undefined) {
166
+ parsedPositionalArgs[spec.name] = spec.default;
167
+ }
168
+ else if (spec.variadic) {
169
+ parsedPositionalArgs[spec.name] = [];
170
+ }
171
+ else {
172
+ throw new Error(`Missing required positional argument --${spec.name}`);
173
+ }
174
+ }
175
+ }
176
+ this.namedArgs = parsedNamedArgs;
177
+ this.positionalArgs = parsedPositionalArgs;
178
+ }
179
+ catch (err) {
180
+ // If help flag was set, the error is from process.exit(0) in tests (where it's mocked to throw) - just rethrow it
181
+ if (this.flags.help) {
182
+ throw err;
183
+ }
184
+ if (err instanceof Error) {
185
+ console.error(err.message);
186
+ this.printHelp();
187
+ }
188
+ else {
189
+ console.error('An unexpected error occurred initializing the CLI.');
190
+ }
191
+ process.exit(1);
192
+ }
193
+ }
194
+ printHelp() {
195
+ var _a;
196
+ const { flags = {}, namedArgs = {}, positionalArgs = [] } = this.config;
197
+ const scriptName = (_a = process.argv.at(1)) !== null && _a !== void 0 ? _a : 'script.ts';
198
+ const positionalUsage = positionalArgs
199
+ .map((arg) => {
200
+ const label = arg.variadic ? `${arg.name}...` : arg.name;
201
+ return arg.default === undefined ? `<${label}>` : `[${label}]`;
202
+ })
203
+ .join(' ');
204
+ const namedArgUsage = Object.keys(namedArgs)
205
+ .map((key) => `[--${key} <value>]`)
206
+ .join(' ');
207
+ const flagUsage = [...Object.keys(flags), '--yes', '--no', '--help'].map((key) => `[${key.startsWith('--') ? key : `--${key}`}]`).join(' ');
208
+ console.log(`\nUsage: npx ts-node ${scriptName} ${flagUsage} ${namedArgUsage} ${positionalUsage}\n`);
209
+ console.log('Flags:');
210
+ for (const [name, spec] of Object.entries(flags)) {
211
+ console.log(` --${name.padEnd(20)} ${spec.description}`);
212
+ }
213
+ // Built-in flags
214
+ console.log(` --${'yes'.padEnd(20)} Automatically answer "yes" to all confirmation prompts.`);
215
+ console.log(` --${'no'.padEnd(20)} Automatically answer "no" to all confirmation prompts.`);
216
+ console.log(` --${'help'.padEnd(20)} Show this help message.`);
217
+ console.log('');
218
+ if (Object.keys(namedArgs).length > 0) {
219
+ console.log('Named Arguments:');
220
+ for (const [name, spec] of Object.entries(namedArgs)) {
221
+ const defaultLabel = spec.default !== undefined ? ` (default: ${(0, SafeString_1.default)(spec.default)})` : '';
222
+ const supersededLabel = spec.supersedes && spec.supersedes.length > 0 ? ` (supersedes: ${spec.supersedes.join(', ')})` : '';
223
+ console.log(` --${name.padEnd(20)} ${spec.description}${defaultLabel}${supersededLabel}`);
224
+ }
225
+ console.log('');
226
+ }
227
+ if (positionalArgs.length > 0) {
228
+ console.log('Positional Arguments:');
229
+ for (const arg of positionalArgs) {
230
+ const defaultLabel = arg.default !== undefined ? ` (default: ${(0, SafeString_1.default)(arg.default)})` : '';
231
+ console.log(` ${arg.name.padEnd(22)} ${arg.description}${defaultLabel}`);
232
+ }
233
+ console.log('');
234
+ }
235
+ }
236
+ static parseStringArg(rawString, paramName, spec) {
237
+ if ('parse' in spec && !!spec.parse) {
238
+ try {
239
+ return spec.parse(rawString);
240
+ }
241
+ catch (error) {
242
+ let errorMessage = '';
243
+ if (error instanceof Error) {
244
+ errorMessage = error.message;
245
+ }
246
+ console.error(`Invalid value for --${paramName}: ${errorMessage}`);
247
+ process.exit(1);
248
+ }
249
+ }
250
+ else {
251
+ return rawString;
252
+ }
253
+ }
254
+ /**
255
+ * Prompts the user for confirmation and returns true if they confirm (y/yes), false otherwise.
256
+ * If --yes flag was passed, returns true immediately without prompting.
257
+ * If --no flag was passed, returns false immediately without prompting.
258
+ */
259
+ promptUserConfirmation(message) {
260
+ return __awaiter(this, void 0, void 0, function* () {
261
+ // Check for built-in flags first
262
+ if (this.flags.yes) {
263
+ return true;
264
+ }
265
+ if (this.flags.no) {
266
+ return false;
267
+ }
268
+ const rl = readline.createInterface({
269
+ input: process.stdin,
270
+ output: process.stdout,
271
+ });
272
+ return new Promise((resolve) => {
273
+ rl.question(message, (answer) => {
274
+ rl.close();
275
+ const normalizedAnswer = answer.trim().toLowerCase();
276
+ resolve(normalizedAnswer === 'y' || normalizedAnswer === 'yes');
277
+ });
278
+ });
279
+ });
280
+ }
281
+ }
282
+ exports.default = CLI;
package/dist/CONST.js CHANGED
@@ -390,7 +390,7 @@ const CONST = {
390
390
  *
391
391
  * @type RegExp
392
392
  */
393
- HYPERLINK: new RegExp('^(?:(?:(?:https?|ftp):)?\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62})?[a-z0-9\\u00a1-\\uffff]\\.)+(?:[a-z\\u00a1-\\uffff]{2,}\\.?))(?::\\d{2,5})?(?:[/?#]\\S*)?$', 'i'),
393
+ HYPERLINK: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i,
394
394
  /**
395
395
  * Regex to match valid emails during markdown transformations
396
396
  *
package/dist/Cookie.d.ts CHANGED
@@ -19,7 +19,7 @@ export default _default;
19
19
  * Detects if cookies are currently enabled in the browser
20
20
  * by trying to create a cookie, see if it exists, and delete it afterwards again.
21
21
  *
22
- * @return {Boolean} True if cookies are enabled, otherwise false.
22
+ * @returns {Boolean} True if cookies are enabled, otherwise false.
23
23
  */
24
24
  declare function enabled(): boolean;
25
25
  /**
@@ -32,7 +32,7 @@ declare function remove(name: string): void;
32
32
  * Fetches the value of a cookie.
33
33
  *
34
34
  * @param {String} name The name of the cookie to fetch.
35
- * @return {String|null} The value of the cookie.
35
+ * @returns {String|null} The value of the cookie.
36
36
  */
37
37
  declare function get(name: string): string | null;
38
38
  /**
@@ -42,20 +42,20 @@ declare function get(name: string): string | null;
42
42
  * @param {String} name
43
43
  * @param {Any|null} defaultValue
44
44
  *
45
- * @return {Any|null}
45
+ * @returns {Any|null}
46
46
  */
47
47
  declare function getJSON(name: string, defaultValue?: Any | null): Any | null;
48
48
  /**
49
49
  * Find a cookie that has been set.
50
50
  *
51
51
  * @param {String} name Name of the cookie to find
52
- * @return {Boolean} Whether or not the cookie is set
52
+ * @returns {Boolean} Whether or not the cookie is set
53
53
  */
54
54
  declare function has(name: string): boolean;
55
55
  /**
56
56
  * Returns help link when cookies are enabled or null.
57
57
  *
58
- * @return {(String|null)}
58
+ * @returns {(String|null)}
59
59
  */
60
60
  declare function getHelpLink(): (string | null);
61
61
  /**