index.d.ts 10 KB

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