@vltpkg/cli-sdk 0.0.0-10

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 (132) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +23 -0
  3. package/dist/esm/commands/cache.d.ts +65 -0
  4. package/dist/esm/commands/cache.d.ts.map +1 -0
  5. package/dist/esm/commands/cache.js +256 -0
  6. package/dist/esm/commands/cache.js.map +1 -0
  7. package/dist/esm/commands/config.d.ts +5 -0
  8. package/dist/esm/commands/config.d.ts.map +1 -0
  9. package/dist/esm/commands/config.js +153 -0
  10. package/dist/esm/commands/config.js.map +1 -0
  11. package/dist/esm/commands/exec-cache.d.ts +49 -0
  12. package/dist/esm/commands/exec-cache.d.ts.map +1 -0
  13. package/dist/esm/commands/exec-cache.js +125 -0
  14. package/dist/esm/commands/exec-cache.js.map +1 -0
  15. package/dist/esm/commands/exec-local.d.ts +6 -0
  16. package/dist/esm/commands/exec-local.d.ts.map +1 -0
  17. package/dist/esm/commands/exec-local.js +24 -0
  18. package/dist/esm/commands/exec-local.js.map +1 -0
  19. package/dist/esm/commands/exec.d.ts +9 -0
  20. package/dist/esm/commands/exec.d.ts.map +1 -0
  21. package/dist/esm/commands/exec.js +78 -0
  22. package/dist/esm/commands/exec.js.map +1 -0
  23. package/dist/esm/commands/gui.d.ts +6 -0
  24. package/dist/esm/commands/gui.d.ts.map +1 -0
  25. package/dist/esm/commands/gui.js +13 -0
  26. package/dist/esm/commands/gui.js.map +1 -0
  27. package/dist/esm/commands/help.d.ts +4 -0
  28. package/dist/esm/commands/help.d.ts.map +1 -0
  29. package/dist/esm/commands/help.js +10 -0
  30. package/dist/esm/commands/help.js.map +1 -0
  31. package/dist/esm/commands/init.d.ts +8 -0
  32. package/dist/esm/commands/init.d.ts.map +1 -0
  33. package/dist/esm/commands/init.js +25 -0
  34. package/dist/esm/commands/init.js.map +1 -0
  35. package/dist/esm/commands/install/reporter.d.ts +10 -0
  36. package/dist/esm/commands/install/reporter.d.ts.map +1 -0
  37. package/dist/esm/commands/install/reporter.js +67 -0
  38. package/dist/esm/commands/install/reporter.js.map +1 -0
  39. package/dist/esm/commands/install.d.ts +10 -0
  40. package/dist/esm/commands/install.d.ts.map +1 -0
  41. package/dist/esm/commands/install.js +21 -0
  42. package/dist/esm/commands/install.js.map +1 -0
  43. package/dist/esm/commands/list.d.ts +15 -0
  44. package/dist/esm/commands/list.d.ts.map +1 -0
  45. package/dist/esm/commands/list.js +109 -0
  46. package/dist/esm/commands/list.js.map +1 -0
  47. package/dist/esm/commands/login.d.ts +4 -0
  48. package/dist/esm/commands/login.d.ts.map +1 -0
  49. package/dist/esm/commands/login.js +13 -0
  50. package/dist/esm/commands/login.js.map +1 -0
  51. package/dist/esm/commands/logout.d.ts +4 -0
  52. package/dist/esm/commands/logout.d.ts.map +1 -0
  53. package/dist/esm/commands/logout.js +13 -0
  54. package/dist/esm/commands/logout.js.map +1 -0
  55. package/dist/esm/commands/pkg.d.ts +7 -0
  56. package/dist/esm/commands/pkg.d.ts.map +1 -0
  57. package/dist/esm/commands/pkg.js +123 -0
  58. package/dist/esm/commands/pkg.js.map +1 -0
  59. package/dist/esm/commands/query.d.ts +16 -0
  60. package/dist/esm/commands/query.d.ts.map +1 -0
  61. package/dist/esm/commands/query.js +124 -0
  62. package/dist/esm/commands/query.js.map +1 -0
  63. package/dist/esm/commands/run-exec.d.ts +6 -0
  64. package/dist/esm/commands/run-exec.d.ts.map +1 -0
  65. package/dist/esm/commands/run-exec.js +14 -0
  66. package/dist/esm/commands/run-exec.js.map +1 -0
  67. package/dist/esm/commands/run.d.ts +6 -0
  68. package/dist/esm/commands/run.d.ts.map +1 -0
  69. package/dist/esm/commands/run.js +37 -0
  70. package/dist/esm/commands/run.js.map +1 -0
  71. package/dist/esm/commands/token.d.ts +4 -0
  72. package/dist/esm/commands/token.d.ts.map +1 -0
  73. package/dist/esm/commands/token.js +30 -0
  74. package/dist/esm/commands/token.js.map +1 -0
  75. package/dist/esm/commands/uninstall.d.ts +10 -0
  76. package/dist/esm/commands/uninstall.d.ts.map +1 -0
  77. package/dist/esm/commands/uninstall.js +21 -0
  78. package/dist/esm/commands/uninstall.js.map +1 -0
  79. package/dist/esm/commands/whoami.d.ts +13 -0
  80. package/dist/esm/commands/whoami.d.ts.map +1 -0
  81. package/dist/esm/commands/whoami.js +19 -0
  82. package/dist/esm/commands/whoami.js.map +1 -0
  83. package/dist/esm/config/definition.d.ts +306 -0
  84. package/dist/esm/config/definition.d.ts.map +1 -0
  85. package/dist/esm/config/definition.js +517 -0
  86. package/dist/esm/config/definition.js.map +1 -0
  87. package/dist/esm/config/index.d.ts +206 -0
  88. package/dist/esm/config/index.d.ts.map +1 -0
  89. package/dist/esm/config/index.js +489 -0
  90. package/dist/esm/config/index.js.map +1 -0
  91. package/dist/esm/config/merge.d.ts +2 -0
  92. package/dist/esm/config/merge.d.ts.map +1 -0
  93. package/dist/esm/config/merge.js +23 -0
  94. package/dist/esm/config/merge.js.map +1 -0
  95. package/dist/esm/config/usage.d.ts +19 -0
  96. package/dist/esm/config/usage.d.ts.map +1 -0
  97. package/dist/esm/config/usage.js +40 -0
  98. package/dist/esm/config/usage.js.map +1 -0
  99. package/dist/esm/exec-command.d.ts +51 -0
  100. package/dist/esm/exec-command.d.ts.map +1 -0
  101. package/dist/esm/exec-command.js +199 -0
  102. package/dist/esm/exec-command.js.map +1 -0
  103. package/dist/esm/index.d.ts +17 -0
  104. package/dist/esm/index.d.ts.map +1 -0
  105. package/dist/esm/index.js +47 -0
  106. package/dist/esm/index.js.map +1 -0
  107. package/dist/esm/output.d.ts +21 -0
  108. package/dist/esm/output.d.ts.map +1 -0
  109. package/dist/esm/output.js +121 -0
  110. package/dist/esm/output.js.map +1 -0
  111. package/dist/esm/package.json +3 -0
  112. package/dist/esm/parse-add-remove-args.d.ts +22 -0
  113. package/dist/esm/parse-add-remove-args.d.ts.map +1 -0
  114. package/dist/esm/parse-add-remove-args.js +71 -0
  115. package/dist/esm/parse-add-remove-args.js.map +1 -0
  116. package/dist/esm/print-err.d.ts +7 -0
  117. package/dist/esm/print-err.d.ts.map +1 -0
  118. package/dist/esm/print-err.js +115 -0
  119. package/dist/esm/print-err.js.map +1 -0
  120. package/dist/esm/read-password.d.ts +8 -0
  121. package/dist/esm/read-password.d.ts.map +1 -0
  122. package/dist/esm/read-password.js +33 -0
  123. package/dist/esm/read-password.js.map +1 -0
  124. package/dist/esm/start-gui.d.ts +9 -0
  125. package/dist/esm/start-gui.d.ts.map +1 -0
  126. package/dist/esm/start-gui.js +40 -0
  127. package/dist/esm/start-gui.js.map +1 -0
  128. package/dist/esm/view.d.ts +30 -0
  129. package/dist/esm/view.d.ts.map +1 -0
  130. package/dist/esm/view.js +31 -0
  131. package/dist/esm/view.js.map +1 -0
  132. package/package.json +125 -0
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Module that handles all vlt configuration needs
3
+ *
4
+ * Project-level configs are set in a `vlt.json` file in the local project
5
+ * if present. This will override the user-level configs in the appropriate
6
+ * XDG config path.
7
+ *
8
+ * Command-specific configuration can be specified by putting options in a
9
+ * field in the `command` object. For example:
10
+ *
11
+ * ```json
12
+ * {
13
+ * "registry": "https://registry.npmjs.org/",
14
+ * "command": {
15
+ * "publish": {
16
+ * "registry": "http://registry.internal"
17
+ * }
18
+ * }
19
+ * }
20
+ * ```
21
+ * @module
22
+ */
23
+ import { PackageInfoClient } from '@vltpkg/package-info';
24
+ import { PackageJson } from '@vltpkg/package-json';
25
+ import { Monorepo } from '@vltpkg/workspaces';
26
+ import type { Jack, OptionsResults, Unwrap } from 'jackspeak';
27
+ import { PathScurry } from 'path-scurry';
28
+ import { kIndent, kNewline } from 'polite-json';
29
+ import type { Commands, RecordField } from './definition.ts';
30
+ import { commands, definition, isRecordField, recordFields } from './definition.ts';
31
+ export { commands, definition, isRecordField, recordFields, type Commands, };
32
+ export declare const kCustomInspect: unique symbol;
33
+ export type RecordPairs = Record<string, unknown>;
34
+ export type RecordString = Record<string, string>;
35
+ export type ConfigFiles = Record<string, ConfigFileData>;
36
+ export type PairsAsRecords = Omit<ConfigOptions, 'projectRoot' | 'scurry' | 'packageJson' | 'monorepo' | 'packageInfo'> & {
37
+ command?: Record<string, ConfigOptions>;
38
+ };
39
+ export declare const pairsToRecords: (obj: ConfigFileData) => PairsAsRecords;
40
+ export declare const recordsToPairs: (obj: RecordPairs) => RecordPairs;
41
+ /**
42
+ * Config data can be any options, and also a 'command' field which
43
+ * contains command names and override options for that command.
44
+ */
45
+ export type ConfigData = OptionsResults<ConfigDefinitions> & {
46
+ command?: Record<string, OptionsResults<ConfigDefinitions>>;
47
+ };
48
+ /**
49
+ * Config data as it appears in config files, with kv pair lists
50
+ * stored as `Record<string, string>`.
51
+ */
52
+ export type ConfigFileData = {
53
+ [k in keyof ConfigData]?: k extends OptListKeys<ConfigData> ? RecordString | string[] : k extends 'command' ? ConfigFiles : ConfigData[k];
54
+ };
55
+ export type ConfigOptions = {
56
+ [k in keyof ConfigData]: k extends RecordField ? RecordString : k extends 'command' ? never : ConfigData[k];
57
+ } & {
58
+ packageJson: PackageJson;
59
+ scurry: PathScurry;
60
+ projectRoot: string;
61
+ monorepo?: Monorepo;
62
+ packageInfo: PackageInfoClient;
63
+ };
64
+ /**
65
+ * The base config definition set as a type
66
+ */
67
+ export type ConfigDefinitions = Unwrap<typeof definition>;
68
+ export type StringListKeys<O> = {
69
+ [k in keyof O]: O[k] extends string[] | undefined ? k : never;
70
+ };
71
+ export type OptListKeys<O> = Exclude<StringListKeys<O>[keyof StringListKeys<O>], undefined>;
72
+ /**
73
+ * Class that handles configuration for vlt.
74
+ *
75
+ * Call {@link Config.load} to get one of these.
76
+ */
77
+ export declare class Config {
78
+ #private;
79
+ /**
80
+ * The {@link https://npmjs.com/jackspeak | JackSpeak} object
81
+ * representing vlt's configuration
82
+ */
83
+ jack: Jack<ConfigDefinitions>;
84
+ stringifyOptions: {
85
+ [kIndent]: string;
86
+ [kNewline]: string;
87
+ };
88
+ configFiles: ConfigFiles;
89
+ /**
90
+ * Parsed values in effect
91
+ */
92
+ values?: OptionsResults<ConfigDefinitions>;
93
+ /**
94
+ * Command-specific config values
95
+ */
96
+ commandValues: {
97
+ [cmd in Commands[keyof Commands]]?: ConfigData;
98
+ };
99
+ /**
100
+ * A flattened object of the parsed configuration
101
+ */
102
+ get options(): ConfigOptions;
103
+ /**
104
+ * Reset the options value, optionally setting a new project root
105
+ * to recalculate the options.
106
+ */
107
+ resetOptions(projectRoot?: string): void;
108
+ /**
109
+ * positional arguments to the vlt process
110
+ */
111
+ positionals?: string[];
112
+ /**
113
+ * The root of the project where a vlt.json, vlt-workspaces.json,
114
+ * package.json, or .git was found. Not necessarily the `process.cwd()`,
115
+ * though that is the default location.
116
+ *
117
+ * Never walks up as far as `$HOME`. So for example, if a project is in
118
+ * `~/projects/xyz`, then the highest dir it will check is `~/projects`
119
+ */
120
+ projectRoot: string;
121
+ /**
122
+ * `Record<alias, canonical name>` to dereference command aliases.
123
+ */
124
+ commands: Commands;
125
+ /**
126
+ * Which command name to use for overriding with command-specific values,
127
+ * determined from the argv when parse() is called.
128
+ */
129
+ command?: Commands[keyof Commands];
130
+ constructor(jack?: Jack<ConfigDefinitions>, projectRoot?: string);
131
+ /**
132
+ * Parse the arguments and set configuration and positionals accordingly.
133
+ */
134
+ parse(args?: string[]): this & ParsedConfig;
135
+ /**
136
+ * Get a `key=value` list option value as an object.
137
+ *
138
+ * For example, a list option with a vlaue of `['key=value', 'xyz=as=df' ]`
139
+ * would be returned as `{key: 'value', xyz: 'as=df'}`
140
+ *
141
+ * Results are memoized, so subsequent calls for the same key will return the
142
+ * same object. If new strings are added to the list, then the memoized value
143
+ * is *not* updated, so only use once configurations have been fully loaded.
144
+ *
145
+ * If the config value is not set at all, an empty object is returned.
146
+ */
147
+ getRecord(k: OptListKeys<ConfigData>): RecordString;
148
+ /**
149
+ * Get a configuration value.
150
+ *
151
+ * Note: `key=value` pair configs are returned as a string array. To get them
152
+ * as an object, use {@link Config#getRecord}.
153
+ */
154
+ get<K extends keyof OptionsResults<ConfigDefinitions>>(k: K): OptionsResults<ConfigDefinitions>[K];
155
+ /**
156
+ * Write the config values to the user or project config file.
157
+ */
158
+ writeConfigFile(which: 'project' | 'user', values: ConfigFileData): Promise<ConfigFileData>;
159
+ /**
160
+ * Fold in the provided fields with the existing properties
161
+ * in the config file.
162
+ */
163
+ addConfigToFile(which: 'project' | 'user', values: ConfigFileData): Promise<ConfigFileData>;
164
+ getFilename(which?: 'project' | 'user'): string;
165
+ deleteConfigKeys(which: 'project' | 'user', fields: string[]): Promise<boolean>;
166
+ /**
167
+ * Edit the user or project configuration file.
168
+ *
169
+ * If the file isn't present, then it starts with `{}` so the user has
170
+ * something to work with.
171
+ *
172
+ * If the result is not valid, or no config settings are contained in the
173
+ * file after editing, then it's restored to what it was before, which might
174
+ * mean deleting the file.
175
+ */
176
+ editConfigFile(which: 'project' | 'user', edit: (file: string) => Promise<void> | void): Promise<void>;
177
+ /**
178
+ * Find the local config file and load both it and the user-level config in
179
+ * the XDG config home.
180
+ *
181
+ * Note: if working in a workspaces monorepo, then the vlt.json file MUST
182
+ * be in the same folder as the vlt-workspaces.json file, because we stop
183
+ * looking when we find either one.
184
+ */
185
+ loadConfigFile(): Promise<this>;
186
+ /**
187
+ * Load the configuration and return a Promise to a
188
+ * {@link Config} object
189
+ */
190
+ static load(projectRoot?: string, argv?: string[],
191
+ /**
192
+ * only used in tests, resets the memoization
193
+ * @internal
194
+ */
195
+ reload?: boolean): Promise<LoadedConfig>;
196
+ }
197
+ export type ParsedConfig = Config & {
198
+ command: NonNullable<Config['command']>;
199
+ values: OptionsResults<ConfigDefinitions>;
200
+ positionals: string[];
201
+ };
202
+ /**
203
+ * A fully loaded {@link Config} object
204
+ */
205
+ export type LoadedConfig = ParsedConfig;
206
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAE7C,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAK7D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAGL,OAAO,EACP,QAAQ,EACT,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EACL,QAAQ,EACR,UAAU,EAEV,aAAa,EACb,YAAY,EACb,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,YAAY,EACZ,KAAK,QAAQ,GACd,CAAA;AAED,eAAO,MAAM,cAAc,eAA2C,CAAA;AAEtE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AACjD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AACjD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AAwBxD,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,aAAa,EACX,aAAa,GACb,QAAQ,GACR,aAAa,GACb,UAAU,GACV,aAAa,CAChB,GAAG;IACF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CACxC,CAAA;AAED,eAAO,MAAM,cAAc,QACpB,cAAc,KAClB,cAgBF,CAAA;AAED,eAAO,MAAM,cAAc,QAAS,WAAW,KAAG,WA2BjD,CAAA;AAYD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,iBAAiB,CAAC,GAAG;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAA;CAC5D,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;KAC1B,CAAC,IAAI,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,GACzD,YAAY,GAAG,MAAM,EAAE,GACvB,CAAC,SAAS,SAAS,GAAG,WAAW,GACjC,UAAU,CAAC,CAAC,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;KACzB,CAAC,IAAI,MAAM,UAAU,GAAG,CAAC,SAAS,WAAW,GAAG,YAAY,GAC3D,CAAC,SAAS,SAAS,GAAG,KAAK,GAC3B,UAAU,CAAC,CAAC,CAAC;CAChB,GAAG;IACF,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,UAAU,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,WAAW,EAAE,iBAAiB,CAAA;CAC/B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAA;AAEzD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;KAC7B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,CAAC,GAAG,KAAK;CAC9D,CAAA;AACD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,CAClC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC,EAC1C,SAAS,CACV,CAAA;AAED;;;;GAIG;AACH,qBAAa,MAAM;;IACjB;;;OAGG;IACH,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAE7B,gBAAgB,EAAE;QAChB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;QACjB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KACnB,CAAwC;IAEzC,WAAW,EAAE,WAAW,CAAK;IAE7B;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAA;IAE1C;;OAEG;IACH,aAAa,EAAE;SACZ,GAAG,IAAI,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU;KAC/C,CAAK;IAEN;;OAEG;IACH,IAAI,OAAO,IAAI,aAAa,CAiC3B;IAED;;;OAGG;IACH,YAAY,CAAC,WAAW,GAAE,MAAsB;IAQhD;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IAEtB;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAA;IAElB;;;OAGG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAA;gBAGhC,IAAI,GAAE,IAAI,CAAC,iBAAiB,CAAc,EAC1C,WAAW,SAAgB;IAO7B;;OAEG;IACH,KAAK,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,IAAI,GAAG,YAAY;IAgCzD;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,YAAY;IAkBnD;;;;;OAKG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,cAAc,CAAC,iBAAiB,CAAC,EACnD,CAAC,EAAE,CAAC,GACH,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAKvC;;OAEG;IACG,eAAe,CACnB,KAAK,EAAE,SAAS,GAAG,MAAM,EACzB,MAAM,EAAE,cAAc;IAaxB;;;OAGG;IACG,eAAe,CACnB,KAAK,EAAE,SAAS,GAAG,MAAM,EACzB,MAAM,EAAE,cAAc;IAoExB,WAAW,CAAC,KAAK,GAAE,SAAS,GAAG,MAAkB,GAAG,MAAM;IAMpD,gBAAgB,CACpB,KAAK,EAAE,SAAS,GAAG,MAAM,EACzB,MAAM,EAAE,MAAM,EAAE;IAiDlB;;;;;;;;;OASG;IACG,cAAc,CAClB,KAAK,EAAE,SAAS,GAAG,MAAM,EACzB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAqC9C;;;;;;;OAOG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAgDrC;;;OAGG;WACU,IAAI,CACf,WAAW,SAAgB,EAC3B,IAAI,WAAe;IACnB;;;OAGG;IACH,MAAM,UAAQ,GACb,OAAO,CAAC,YAAY,CAAC;CAOzB;AAKD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAClC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;IACvC,MAAM,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAA;IACzC,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,CAAA"}
@@ -0,0 +1,489 @@
1
+ /**
2
+ * Module that handles all vlt configuration needs
3
+ *
4
+ * Project-level configs are set in a `vlt.json` file in the local project
5
+ * if present. This will override the user-level configs in the appropriate
6
+ * XDG config path.
7
+ *
8
+ * Command-specific configuration can be specified by putting options in a
9
+ * field in the `command` object. For example:
10
+ *
11
+ * ```json
12
+ * {
13
+ * "registry": "https://registry.npmjs.org/",
14
+ * "command": {
15
+ * "publish": {
16
+ * "registry": "http://registry.internal"
17
+ * }
18
+ * }
19
+ * }
20
+ * ```
21
+ * @module
22
+ */
23
+ import { error } from '@vltpkg/error-cause';
24
+ import { PackageInfoClient } from '@vltpkg/package-info';
25
+ import { PackageJson } from '@vltpkg/package-json';
26
+ import { Monorepo } from '@vltpkg/workspaces';
27
+ import { XDG } from '@vltpkg/xdg';
28
+ import { readFileSync, rmSync, writeFileSync } from 'node:fs';
29
+ import { lstat, mkdir, readFile, writeFile } from 'node:fs/promises';
30
+ import { homedir } from 'node:os';
31
+ import { dirname, resolve } from 'node:path';
32
+ import { PathScurry } from 'path-scurry';
33
+ import { parse as jsonParse, stringify as jsonStringify, kIndent, kNewline, } from 'polite-json';
34
+ import { walkUp } from 'walk-up-path';
35
+ import { commands, definition, getCommand, isRecordField, recordFields, } from "./definition.js";
36
+ import { merge } from "./merge.js";
37
+ export { commands, definition, isRecordField, recordFields, };
38
+ export const kCustomInspect = Symbol.for('nodejs.util.inspect.custom');
39
+ // turn a set of pairs into a Record object.
40
+ // if a kv pair doesn't have a = character, set to `''`
41
+ const reducePairs = (pairs) => {
42
+ const record = {};
43
+ for (const kv of pairs) {
44
+ const eq = kv.indexOf('=');
45
+ if (eq === -1)
46
+ record[kv] = '';
47
+ else {
48
+ const key = kv.substring(0, eq);
49
+ const val = kv.substring(eq + 1);
50
+ record[key] = val;
51
+ }
52
+ }
53
+ return record;
54
+ };
55
+ const isRecordFieldValue = (k, v) => Array.isArray(v) &&
56
+ recordFields.includes(k);
57
+ export const pairsToRecords = (obj) => {
58
+ return Object.fromEntries(Object.entries(obj).map(([k, v]) => [
59
+ k,
60
+ k === 'command' && v && typeof v === 'object' ?
61
+ Object.fromEntries(Object.entries(v).map(([k, v]) => [
62
+ k,
63
+ pairsToRecords(v),
64
+ ]))
65
+ : isRecordFieldValue(k, v) ? reducePairs(v)
66
+ : v,
67
+ ]));
68
+ };
69
+ export const recordsToPairs = (obj) => {
70
+ return Object.fromEntries(Object.entries(obj)
71
+ .filter(([k]) => !(k === 'scurry' ||
72
+ k === 'packageJson' ||
73
+ k === 'monorepo' ||
74
+ k === 'projectRoot' ||
75
+ k === 'packageInfo'))
76
+ .map(([k, v]) => [
77
+ k,
78
+ k === 'command' && v && typeof v === 'object' ?
79
+ recordsToPairs(v)
80
+ : (!v ||
81
+ typeof v !== 'object' ||
82
+ Array.isArray(v) ||
83
+ !isRecordField(k)) ?
84
+ v
85
+ : Object.entries(v).map(([k, v]) => `${k}=${v}`),
86
+ ]));
87
+ };
88
+ const kRecord = Symbol('parsed key=value record');
89
+ const exists = (f) => lstat(f).then(() => true, () => false);
90
+ const home = homedir();
91
+ const xdg = new XDG('vlt');
92
+ /**
93
+ * Class that handles configuration for vlt.
94
+ *
95
+ * Call {@link Config.load} to get one of these.
96
+ */
97
+ export class Config {
98
+ /**
99
+ * The {@link https://npmjs.com/jackspeak | JackSpeak} object
100
+ * representing vlt's configuration
101
+ */
102
+ jack;
103
+ stringifyOptions = { [kIndent]: ' ', [kNewline]: '\n' };
104
+ configFiles = {};
105
+ /**
106
+ * Parsed values in effect
107
+ */
108
+ values;
109
+ /**
110
+ * Command-specific config values
111
+ */
112
+ commandValues = {};
113
+ /**
114
+ * A flattened object of the parsed configuration
115
+ */
116
+ get options() {
117
+ if (this.#options)
118
+ return this.#options;
119
+ const scurry = new PathScurry(this.projectRoot);
120
+ const packageJson = new PackageJson();
121
+ const asRecords = pairsToRecords(this.parse().values);
122
+ const extras = {
123
+ projectRoot: this.projectRoot,
124
+ scurry,
125
+ packageJson,
126
+ monorepo: Monorepo.maybeLoad(this.projectRoot, {
127
+ scurry,
128
+ packageJson,
129
+ }),
130
+ };
131
+ const options = Object.assign(asRecords, extras);
132
+ this.#options = Object.assign(options, {
133
+ packageInfo: new PackageInfoClient(options),
134
+ [kCustomInspect]() {
135
+ return Object.fromEntries(Object.entries(options).filter(([k]) => k !== 'monorepo' &&
136
+ k !== 'scurry' &&
137
+ k !== 'packageJson' &&
138
+ k !== 'packageInfo'));
139
+ },
140
+ });
141
+ return this.#options;
142
+ }
143
+ /**
144
+ * Reset the options value, optionally setting a new project root
145
+ * to recalculate the options.
146
+ */
147
+ resetOptions(projectRoot = process.cwd()) {
148
+ this.projectRoot = projectRoot;
149
+ this.#options = undefined;
150
+ }
151
+ // memoized options() getter value
152
+ #options;
153
+ /**
154
+ * positional arguments to the vlt process
155
+ */
156
+ positionals;
157
+ /**
158
+ * The root of the project where a vlt.json, vlt-workspaces.json,
159
+ * package.json, or .git was found. Not necessarily the `process.cwd()`,
160
+ * though that is the default location.
161
+ *
162
+ * Never walks up as far as `$HOME`. So for example, if a project is in
163
+ * `~/projects/xyz`, then the highest dir it will check is `~/projects`
164
+ */
165
+ projectRoot;
166
+ /**
167
+ * `Record<alias, canonical name>` to dereference command aliases.
168
+ */
169
+ commands;
170
+ /**
171
+ * Which command name to use for overriding with command-specific values,
172
+ * determined from the argv when parse() is called.
173
+ */
174
+ command;
175
+ constructor(jack = definition, projectRoot = process.cwd()) {
176
+ this.projectRoot = projectRoot;
177
+ this.commands = commands;
178
+ this.jack = jack;
179
+ }
180
+ /**
181
+ * Parse the arguments and set configuration and positionals accordingly.
182
+ */
183
+ parse(args = process.argv) {
184
+ if (isParsed(this))
185
+ return this;
186
+ this.jack.loadEnvDefaults();
187
+ const p = this.jack.parseRaw(args);
188
+ const fallback = getCommand(p.values['fallback-command']);
189
+ this.command = getCommand(p.positionals[0]);
190
+ const cmdOrFallback = this.command ?? fallback;
191
+ const cmdSpecific = cmdOrFallback && this.commandValues[cmdOrFallback];
192
+ if (cmdSpecific) {
193
+ this.jack.setConfigValues(recordsToPairs(cmdSpecific));
194
+ }
195
+ // ok, applied cmd-specific defaults, do rest of the parse
196
+ this.jack.applyDefaults(p);
197
+ this.jack.writeEnv(p);
198
+ if (this.command)
199
+ p.positionals.shift();
200
+ else
201
+ this.command = getCommand(p.values['fallback-command']);
202
+ Object.assign(this, p);
203
+ /* c8 ignore start - unpossible */
204
+ if (!isParsed(this))
205
+ throw error('failed to parse config');
206
+ /* c8 ignore stop */
207
+ return this;
208
+ }
209
+ /**
210
+ * Get a `key=value` list option value as an object.
211
+ *
212
+ * For example, a list option with a vlaue of `['key=value', 'xyz=as=df' ]`
213
+ * would be returned as `{key: 'value', xyz: 'as=df'}`
214
+ *
215
+ * Results are memoized, so subsequent calls for the same key will return the
216
+ * same object. If new strings are added to the list, then the memoized value
217
+ * is *not* updated, so only use once configurations have been fully loaded.
218
+ *
219
+ * If the config value is not set at all, an empty object is returned.
220
+ */
221
+ getRecord(k) {
222
+ const pairs = this.get(k);
223
+ if (!pairs)
224
+ return {};
225
+ if (pairs[kRecord])
226
+ return pairs[kRecord];
227
+ const kv = pairs.reduce((kv, pair) => {
228
+ const eq = pair.indexOf('=');
229
+ if (eq === -1)
230
+ return kv;
231
+ const key = pair.substring(0, eq);
232
+ const val = pair.substring(eq + 1);
233
+ kv[key] = val;
234
+ return kv;
235
+ }, {});
236
+ Object.assign(pairs, { [kRecord]: kv });
237
+ return kv;
238
+ }
239
+ /**
240
+ * Get a configuration value.
241
+ *
242
+ * Note: `key=value` pair configs are returned as a string array. To get them
243
+ * as an object, use {@link Config#getRecord}.
244
+ */
245
+ get(k) {
246
+ /* c8 ignore next -- impossible but TS doesn't know that */
247
+ return (this.values ?? this.parse().values)[k];
248
+ }
249
+ /**
250
+ * Write the config values to the user or project config file.
251
+ */
252
+ async writeConfigFile(which, values) {
253
+ const f = this.getFilename(which);
254
+ await mkdir(dirname(f), { recursive: true });
255
+ const vals = Object.assign(pairsToRecords(values), this.stringifyOptions);
256
+ await writeFile(f, jsonStringify(vals));
257
+ this.configFiles[f] = vals;
258
+ return values;
259
+ }
260
+ /**
261
+ * Fold in the provided fields with the existing properties
262
+ * in the config file.
263
+ */
264
+ async addConfigToFile(which, values) {
265
+ const f = this.getFilename(which);
266
+ return this.writeConfigFile(which, merge((await this.#maybeLoadConfigFile(f)) ?? {}, values));
267
+ }
268
+ /**
269
+ * if the file exists, parse and load it. returns object if data was
270
+ * loaded, or undefined if not.
271
+ */
272
+ async #maybeLoadConfigFile(file) {
273
+ const result = await this.#readConfigFile(file);
274
+ if (result) {
275
+ try {
276
+ const { command, ...values } = recordsToPairs(result);
277
+ if (command) {
278
+ for (const [c, opts] of Object.entries(command)) {
279
+ const cmd = getCommand(c);
280
+ if (cmd) {
281
+ this.commandValues[cmd] = merge(this.commandValues[cmd] ?? {}, opts);
282
+ }
283
+ }
284
+ }
285
+ this.jack.setConfigValues(values, file);
286
+ return result;
287
+ }
288
+ catch (er) {
289
+ throw error('failed to load config values from file', {
290
+ path: file,
291
+ cause: er,
292
+ });
293
+ }
294
+ }
295
+ }
296
+ async #readConfigFile(file) {
297
+ if (this.configFiles[file])
298
+ return this.configFiles[file];
299
+ const data = await readFile(file, 'utf8').catch(() => { });
300
+ if (!data)
301
+ return undefined;
302
+ let result;
303
+ try {
304
+ result = jsonParse(data);
305
+ if (result && typeof result === 'object') {
306
+ if (result[kIndent] !== undefined)
307
+ this.stringifyOptions[kIndent] = result[kIndent];
308
+ if (result[kNewline] !== undefined)
309
+ this.stringifyOptions[kNewline] = result[kNewline];
310
+ }
311
+ }
312
+ catch (er) {
313
+ throw error('failed to parse vlt config file', {
314
+ path: file,
315
+ cause: er,
316
+ });
317
+ }
318
+ this.configFiles[file] = result;
319
+ return result;
320
+ }
321
+ getFilename(which = 'project') {
322
+ return which === 'user' ?
323
+ xdg.config('vlt.json')
324
+ : resolve(this.projectRoot, 'vlt.json');
325
+ }
326
+ async deleteConfigKeys(which, fields) {
327
+ const file = this.getFilename(which);
328
+ const data = await this.#maybeLoadConfigFile(file);
329
+ if (!data) {
330
+ rmSync(file, { force: true });
331
+ return false;
332
+ }
333
+ let didSomething = false;
334
+ for (const f of fields) {
335
+ const [key, ...sk] = f.split('.');
336
+ const subs = sk.join('.');
337
+ const k = key;
338
+ const v = data[k];
339
+ if (v === undefined)
340
+ continue;
341
+ if (subs && v && typeof v === 'object') {
342
+ if (Array.isArray(v)) {
343
+ const i = v.findIndex(subvalue => subvalue.startsWith(`${subs}=`));
344
+ if (i !== -1) {
345
+ v.splice(i, 1);
346
+ if (v.length === 0)
347
+ delete data[k];
348
+ didSomething = true;
349
+ }
350
+ }
351
+ else {
352
+ if (v[subs] !== undefined) {
353
+ delete v[subs];
354
+ if (Object.keys(v).length === 0)
355
+ delete data[k];
356
+ didSomething = true;
357
+ }
358
+ }
359
+ }
360
+ else {
361
+ didSomething = true;
362
+ delete data[k];
363
+ }
364
+ }
365
+ const d = jsonStringify(data);
366
+ if (d.trim() === '{}') {
367
+ rmSync(file, { force: true });
368
+ }
369
+ else {
370
+ writeFileSync(file, jsonStringify(data));
371
+ }
372
+ return didSomething;
373
+ }
374
+ /**
375
+ * Edit the user or project configuration file.
376
+ *
377
+ * If the file isn't present, then it starts with `{}` so the user has
378
+ * something to work with.
379
+ *
380
+ * If the result is not valid, or no config settings are contained in the
381
+ * file after editing, then it's restored to what it was before, which might
382
+ * mean deleting the file.
383
+ */
384
+ async editConfigFile(which, edit) {
385
+ const file = this.getFilename(which);
386
+ const backup = this.configFiles[file];
387
+ if (!backup) {
388
+ writeFileSync(file, '{\n\n}\n');
389
+ }
390
+ let valid = false;
391
+ try {
392
+ await edit(file);
393
+ const res = jsonParse(readFileSync(file, 'utf8'));
394
+ if (!res || typeof res !== 'object' || Array.isArray(res)) {
395
+ throw error('Invalid configuration, expected object', {
396
+ path: file,
397
+ found: res,
398
+ });
399
+ }
400
+ if (Object.keys(res).length === 0) {
401
+ // nothing there, remove file
402
+ delete this.configFiles[file];
403
+ rmSync(file, { force: true });
404
+ }
405
+ else {
406
+ this.jack.setConfigValues(recordsToPairs(res));
407
+ this.configFiles[file] = res;
408
+ }
409
+ valid = true;
410
+ }
411
+ finally {
412
+ if (!valid) {
413
+ if (backup) {
414
+ writeFileSync(file, jsonStringify(backup));
415
+ }
416
+ else {
417
+ rmSync(file, { force: true });
418
+ }
419
+ }
420
+ }
421
+ }
422
+ /**
423
+ * Find the local config file and load both it and the user-level config in
424
+ * the XDG config home.
425
+ *
426
+ * Note: if working in a workspaces monorepo, then the vlt.json file MUST
427
+ * be in the same folder as the vlt-workspaces.json file, because we stop
428
+ * looking when we find either one.
429
+ */
430
+ async loadConfigFile() {
431
+ const userConfig = xdg.config('vlt.json');
432
+ await this.#maybeLoadConfigFile(userConfig);
433
+ let lastKnownRoot = resolve(this.projectRoot);
434
+ for (const dir of walkUp(this.projectRoot)) {
435
+ // don't look in ~
436
+ if (dir === home)
437
+ break;
438
+ // finding a project config file stops the search
439
+ const projectConfig = resolve(dir, 'vlt.json');
440
+ if (projectConfig === userConfig)
441
+ break;
442
+ if ((await exists(projectConfig)) &&
443
+ (await this.#maybeLoadConfigFile(projectConfig))) {
444
+ lastKnownRoot = dir;
445
+ break;
446
+ }
447
+ // stat existence of these files
448
+ const [hasPackage, hasModules, hasWorkspaces, hasGit] = await Promise.all([
449
+ exists(resolve(dir, 'package.json')),
450
+ exists(resolve(dir, 'node_modules')),
451
+ exists(resolve(dir, 'vlt-workspaces.json')),
452
+ exists(resolve(dir, '.git')),
453
+ ]);
454
+ // treat these as potential roots
455
+ if (hasPackage || hasModules || hasWorkspaces) {
456
+ lastKnownRoot = dir;
457
+ }
458
+ // define backstops
459
+ if (hasWorkspaces || hasGit) {
460
+ break;
461
+ }
462
+ }
463
+ this.projectRoot = lastKnownRoot;
464
+ return this;
465
+ }
466
+ /**
467
+ * cache of the loaded config
468
+ */
469
+ static #loaded;
470
+ /**
471
+ * Load the configuration and return a Promise to a
472
+ * {@link Config} object
473
+ */
474
+ static async load(projectRoot = process.cwd(), argv = process.argv,
475
+ /**
476
+ * only used in tests, resets the memoization
477
+ * @internal
478
+ */
479
+ reload = false) {
480
+ if (this.#loaded && !reload)
481
+ return this.#loaded;
482
+ const a = new Config(definition, projectRoot);
483
+ const b = await a.loadConfigFile();
484
+ this.#loaded = b.parse(argv);
485
+ return this.#loaded;
486
+ }
487
+ }
488
+ const isParsed = (c) => !!(c.values && c.positionals && c.command);
489
+ //# sourceMappingURL=index.js.map