index.d.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import { inspect, InspectOptions, ParseArgsConfig } from 'node:util';
  2. export type ParseArgsOptions = Exclude<ParseArgsConfig['options'], undefined>;
  3. export type ParseArgsOption = ParseArgsOptions[string];
  4. export type ParseArgsDefault = Exclude<ConfigValue, number | number[]>;
  5. export type ConfigType = 'number' | 'string' | 'boolean';
  6. export declare const isConfigType: (t: unknown) => t is ConfigType;
  7. export type ConfigValuePrimitive = string | boolean | number;
  8. export type ConfigValueArray = string[] | boolean[] | number[];
  9. export type ConfigValue = ConfigValuePrimitive | ConfigValueArray;
  10. /**
  11. * Given a Jack object, get the typeof its ConfigSet
  12. */
  13. export type Unwrap<J> = J extends Jack<infer C> ? C : never;
  14. /**
  15. * Defines the type of value that is valid, given a config definition's
  16. * {@link ConfigType} and boolean multiple setting
  17. */
  18. export type ValidValue<T extends ConfigType = ConfigType, M extends boolean = boolean> = [
  19. T,
  20. M
  21. ] extends ['number', true] ? number[] : [T, M] extends ['string', true] ? string[] : [T, M] extends ['boolean', true] ? boolean[] : [T, M] extends ['number', false] ? number : [T, M] extends ['string', false] ? string : [T, M] extends ['boolean', false] ? boolean : [T, M] extends ['string', boolean] ? string | string[] : [T, M] extends ['boolean', boolean] ? boolean | boolean[] : [T, M] extends ['number', boolean] ? number | number[] : [T, M] extends [ConfigType, false] ? ConfigValuePrimitive : [T, M] extends [ConfigType, true] ? ConfigValueArray : ConfigValue;
  22. export type ReadonlyArrays = readonly number[] | readonly string[];
  23. /**
  24. * Defines the type of validOptions that are valid, given a config definition's
  25. * {@link ConfigType}
  26. */
  27. export type ValidOptions<T extends ConfigType> = T extends 'boolean' ? undefined : T extends 'string' ? readonly string[] : T extends 'number' ? readonly number[] : ReadonlyArrays;
  28. /**
  29. * A config field definition, in its full representation.
  30. * This is what is passed in to addFields so `type` is required.
  31. */
  32. export type ConfigOption<T extends ConfigType = ConfigType, M extends boolean = boolean, O extends undefined | ValidOptions<T> = undefined | ValidOptions<T>> = {
  33. type: T;
  34. short?: string;
  35. default?: ValidValue<T, M> & (O extends ReadonlyArrays ? M extends false ? O[number] : O[number][] : unknown);
  36. description?: string;
  37. hint?: T extends 'boolean' ? undefined : string;
  38. validate?: ((v: unknown) => v is ValidValue<T, M>) | ((v: unknown) => boolean);
  39. validOptions?: O;
  40. delim?: M extends false ? undefined : string;
  41. multiple?: M;
  42. };
  43. /**
  44. * Determine whether an unknown object is a {@link ConfigOption} based only
  45. * on its `type` and `multiple` property
  46. */
  47. export declare const isConfigOptionOfType: <T extends ConfigType, M extends boolean>(o: any, type: T, multi: M) => o is ConfigOption<T, M>;
  48. /**
  49. * Determine whether an unknown object is a {@link ConfigOption} based on
  50. * it having all valid properties
  51. */
  52. export declare const isConfigOption: <T extends ConfigType, M extends boolean>(o: any, type: T, multi: M) => o is ConfigOption<T, M>;
  53. /**
  54. * The meta information for a config option definition, when the
  55. * type and multiple values can be inferred by the method being used
  56. */
  57. export type ConfigOptionMeta<T extends ConfigType, M extends boolean, O extends ConfigOption<T, M> = ConfigOption<T, M>> = Pick<Partial<O>, 'type'> & Omit<O, 'type'>;
  58. /**
  59. * A set of {@link ConfigOption} objects, referenced by their longOption
  60. * string values.
  61. */
  62. export type ConfigSet = {
  63. [longOption: string]: ConfigOption;
  64. };
  65. /**
  66. * A set of {@link ConfigOptionMeta} fields, referenced by their longOption
  67. * string values.
  68. */
  69. export type ConfigMetaSet<T extends ConfigType, M extends boolean> = {
  70. [longOption: string]: ConfigOptionMeta<T, M>;
  71. };
  72. /**
  73. * Infer {@link ConfigSet} fields from a given {@link ConfigMetaSet}
  74. */
  75. export type ConfigSetFromMetaSet<T extends ConfigType, M extends boolean, S extends ConfigMetaSet<T, M>> = S & {
  76. [longOption in keyof S]: ConfigOption<T, M>;
  77. };
  78. /**
  79. * The 'values' field returned by {@link Jack#parse}. If a value has
  80. * a default field it will be required on the object otherwise it is optional.
  81. */
  82. export type OptionsResults<T extends ConfigSet> = {
  83. [K in keyof T]: (T[K]['validOptions'] extends ReadonlyArrays ? T[K] extends ConfigOption<'string' | 'number', false> ? T[K]['validOptions'][number] : T[K] extends ConfigOption<'string' | 'number', true> ? T[K]['validOptions'][number][] : never : T[K] extends ConfigOption<'string', false> ? string : T[K] extends ConfigOption<'string', true> ? string[] : T[K] extends ConfigOption<'number', false> ? number : T[K] extends ConfigOption<'number', true> ? number[] : T[K] extends ConfigOption<'boolean', false> ? boolean : T[K] extends ConfigOption<'boolean', true> ? boolean[] : never) | (T[K]['default'] extends ConfigValue ? never : undefined);
  84. };
  85. /**
  86. * The object retured by {@link Jack#parse}
  87. */
  88. export type Parsed<T extends ConfigSet> = {
  89. values: OptionsResults<T>;
  90. positionals: string[];
  91. };
  92. /**
  93. * A row used when generating the {@link Jack#usage} string
  94. */
  95. export interface Row {
  96. left?: string;
  97. text: string;
  98. skipLine?: boolean;
  99. type?: string;
  100. }
  101. /**
  102. * A heading for a section in the usage, created by the jack.heading()
  103. * method.
  104. *
  105. * First heading is always level 1, subsequent headings default to 2.
  106. *
  107. * The level of the nearest heading level sets the indentation of the
  108. * description that follows.
  109. */
  110. export interface Heading extends Row {
  111. type: 'heading';
  112. text: string;
  113. left?: '';
  114. skipLine?: boolean;
  115. level: number;
  116. pre?: boolean;
  117. }
  118. /**
  119. * An arbitrary blob of text describing some stuff, set by the
  120. * jack.description() method.
  121. *
  122. * Indentation determined by level of the nearest header.
  123. */
  124. export interface Description extends Row {
  125. type: 'description';
  126. text: string;
  127. left?: '';
  128. skipLine?: boolean;
  129. pre?: boolean;
  130. }
  131. /**
  132. * A heading or description row used when generating the {@link Jack#usage}
  133. * string
  134. */
  135. export type TextRow = Heading | Description;
  136. /**
  137. * Either a {@link TextRow} or a reference to a {@link ConfigOption}
  138. */
  139. export type UsageField = TextRow | {
  140. type: 'config';
  141. name: string;
  142. value: ConfigOption;
  143. };
  144. /**
  145. * Options provided to the {@link Jack} constructor
  146. */
  147. export interface JackOptions {
  148. /**
  149. * Whether to allow positional arguments
  150. *
  151. * @default true
  152. */
  153. allowPositionals?: boolean;
  154. /**
  155. * Prefix to use when reading/writing the environment variables
  156. *
  157. * If not specified, environment behavior will not be available.
  158. */
  159. envPrefix?: string;
  160. /**
  161. * Environment object to read/write. Defaults `process.env`.
  162. * No effect if `envPrefix` is not set.
  163. */
  164. env?: Record<string, string | undefined>;
  165. /**
  166. * A short usage string. If not provided, will be generated from the
  167. * options provided, but that can of course be rather verbose if
  168. * there are a lot of options.
  169. */
  170. usage?: string;
  171. /**
  172. * Stop parsing flags and opts at the first positional argument.
  173. * This is to support cases like `cmd [flags] <subcmd> [options]`, where
  174. * each subcommand may have different options. This effectively treats
  175. * any positional as a `--` argument. Only relevant if `allowPositionals`
  176. * is true.
  177. *
  178. * To do subcommands, set this option, look at the first positional, and
  179. * parse the remaining positionals as appropriate.
  180. *
  181. * @default false
  182. */
  183. stopAtPositional?: boolean;
  184. /**
  185. * Conditional `stopAtPositional`. If set to a `(string)=>boolean` function,
  186. * will be called with each positional argument encountered. If the function
  187. * returns true, then parsing will stop at that point.
  188. */
  189. stopAtPositionalTest?: (arg: string) => boolean;
  190. }
  191. /**
  192. * Class returned by the {@link jack} function and all configuration
  193. * definition methods. This is what gets chained together.
  194. */
  195. export declare class Jack<C extends ConfigSet = {}> {
  196. #private;
  197. constructor(options?: JackOptions);
  198. /**
  199. * Set the default value (which will still be overridden by env or cli)
  200. * as if from a parsed config file. The optional `source` param, if
  201. * provided, will be included in error messages if a value is invalid or
  202. * unknown.
  203. */
  204. setConfigValues(values: Partial<OptionsResults<C>>, source?: string): this;
  205. /**
  206. * Parse a string of arguments, and return the resulting
  207. * `{ values, positionals }` object.
  208. *
  209. * If an {@link JackOptions#envPrefix} is set, then it will read default
  210. * values from the environment, and write the resulting values back
  211. * to the environment as well.
  212. *
  213. * Environment values always take precedence over any other value, except
  214. * an explicit CLI setting.
  215. */
  216. parse(args?: string[]): Parsed<C>;
  217. loadEnvDefaults(): void;
  218. applyDefaults(p: Parsed<C>): void;
  219. /**
  220. * Only parse the command line arguments passed in.
  221. * Does not strip off the `node script.js` bits, so it must be just the
  222. * arguments you wish to have parsed.
  223. * Does not read from or write to the environment, or set defaults.
  224. */
  225. parseRaw(args: string[]): Parsed<C>;
  226. /**
  227. * Validate that any arbitrary object is a valid configuration `values`
  228. * object. Useful when loading config files or other sources.
  229. */
  230. validate(o: unknown): asserts o is Parsed<C>['values'];
  231. writeEnv(p: Parsed<C>): void;
  232. /**
  233. * Add a heading to the usage output banner
  234. */
  235. heading(text: string, level?: 1 | 2 | 3 | 4 | 5 | 6, { pre }?: {
  236. pre?: boolean;
  237. }): Jack<C>;
  238. /**
  239. * Add a long-form description to the usage output at this position.
  240. */
  241. description(text: string, { pre }?: {
  242. pre?: boolean;
  243. }): Jack<C>;
  244. /**
  245. * Add one or more number fields.
  246. */
  247. num<F extends ConfigMetaSet<'number', false>>(fields: F): Jack<C & ConfigSetFromMetaSet<'number', false, F>>;
  248. /**
  249. * Add one or more multiple number fields.
  250. */
  251. numList<F extends ConfigMetaSet<'number', true>>(fields: F): Jack<C & ConfigSetFromMetaSet<'number', true, F>>;
  252. /**
  253. * Add one or more string option fields.
  254. */
  255. opt<F extends ConfigMetaSet<'string', false>>(fields: F): Jack<C & ConfigSetFromMetaSet<'string', false, F>>;
  256. /**
  257. * Add one or more multiple string option fields.
  258. */
  259. optList<F extends ConfigMetaSet<'string', true>>(fields: F): Jack<C & ConfigSetFromMetaSet<'string', true, F>>;
  260. /**
  261. * Add one or more flag fields.
  262. */
  263. flag<F extends ConfigMetaSet<'boolean', false>>(fields: F): Jack<C & ConfigSetFromMetaSet<'boolean', false, F>>;
  264. /**
  265. * Add one or more multiple flag fields.
  266. */
  267. flagList<F extends ConfigMetaSet<'boolean', true>>(fields: F): Jack<C & ConfigSetFromMetaSet<'boolean', true, F>>;
  268. /**
  269. * Generic field definition method. Similar to flag/flagList/number/etc,
  270. * but you must specify the `type` (and optionally `multiple` and `delim`)
  271. * fields on each one, or Jack won't know how to define them.
  272. */
  273. addFields<F extends ConfigSet>(fields: F): Jack<C & F>;
  274. /**
  275. * Return the usage banner for the given configuration
  276. */
  277. usage(): string;
  278. /**
  279. * Return the usage banner markdown for the given configuration
  280. */
  281. usageMarkdown(): string;
  282. /**
  283. * Return the configuration options as a plain object
  284. */
  285. toJSON(): {
  286. [k: string]: {
  287. hint?: string | undefined;
  288. default?: ConfigValue | undefined;
  289. validOptions?: readonly number[] | readonly string[] | undefined;
  290. validate?: ((v: unknown) => boolean) | ((v: unknown) => v is ValidValue<ConfigType, boolean>) | undefined;
  291. description?: string | undefined;
  292. short?: string | undefined;
  293. delim?: string | undefined;
  294. multiple?: boolean | undefined;
  295. type: ConfigType;
  296. };
  297. };
  298. /**
  299. * Custom printer for `util.inspect`
  300. */
  301. [inspect.custom](_: number, options: InspectOptions): string;
  302. }
  303. /**
  304. * Main entry point. Create and return a {@link Jack} object.
  305. */
  306. export declare const jack: (options?: JackOptions) => Jack<{}>;
  307. //# sourceMappingURL=index.d.ts.map