@vltpkg/cli-sdk 1.0.0-rc.3 → 1.0.0-rc.31

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 (210) hide show
  1. package/dist/commands/access.d.ts +22 -0
  2. package/dist/commands/access.js +246 -0
  3. package/dist/commands/bugs.d.ts +17 -0
  4. package/dist/commands/bugs.js +163 -0
  5. package/dist/{esm/commands → commands}/build.d.ts +0 -1
  6. package/dist/{esm/commands → commands}/build.js +0 -1
  7. package/dist/{esm/commands → commands}/cache.d.ts +0 -1
  8. package/dist/{esm/commands → commands}/cache.js +0 -1
  9. package/dist/{esm/commands → commands}/ci.d.ts +0 -1
  10. package/dist/{esm/commands → commands}/ci.js +11 -3
  11. package/dist/{esm/commands → commands}/config.d.ts +0 -1
  12. package/dist/{esm/commands → commands}/config.js +6 -1
  13. package/dist/commands/create.d.ts +8 -0
  14. package/dist/commands/create.js +102 -0
  15. package/dist/commands/deprecate.d.ts +13 -0
  16. package/dist/commands/deprecate.js +139 -0
  17. package/dist/commands/dist-tag.d.ts +21 -0
  18. package/dist/commands/dist-tag.js +177 -0
  19. package/dist/{esm/commands → commands}/docs.d.ts +0 -1
  20. package/dist/{esm/commands → commands}/docs.js +2 -3
  21. package/dist/{esm/commands → commands}/exec-cache.d.ts +0 -1
  22. package/dist/{esm/commands → commands}/exec-cache.js +0 -1
  23. package/dist/{esm/commands → commands}/exec-local.d.ts +0 -1
  24. package/dist/{esm/commands → commands}/exec-local.js +23 -1
  25. package/dist/{esm/commands → commands}/exec.d.ts +0 -1
  26. package/dist/{esm/commands → commands}/exec.js +84 -10
  27. package/dist/{esm/commands → commands}/help.d.ts +0 -1
  28. package/dist/{esm/commands → commands}/help.js +5 -1
  29. package/dist/{esm/commands → commands}/init.d.ts +0 -1
  30. package/dist/{esm/commands → commands}/init.js +31 -10
  31. package/dist/{esm/commands → commands}/install/reporter.d.ts +0 -1
  32. package/dist/{esm/commands → commands}/install/reporter.js +0 -1
  33. package/dist/{esm/commands → commands}/install.d.ts +21 -3
  34. package/dist/commands/install.js +140 -0
  35. package/dist/{esm/commands → commands}/list.d.ts +4 -2
  36. package/dist/{esm/commands → commands}/list.js +8 -10
  37. package/dist/{esm/commands → commands}/login.d.ts +0 -1
  38. package/dist/{esm/commands → commands}/login.js +10 -1
  39. package/dist/{esm/commands/token.d.ts → commands/logout.d.ts} +0 -1
  40. package/dist/{esm/commands → commands}/logout.js +10 -1
  41. package/dist/{esm/commands → commands}/pack.d.ts +0 -1
  42. package/dist/{esm/commands → commands}/pack.js +90 -32
  43. package/dist/commands/ping.d.ts +17 -0
  44. package/dist/commands/ping.js +114 -0
  45. package/dist/{esm/commands → commands}/pkg.d.ts +0 -1
  46. package/dist/{esm/commands → commands}/pkg.js +27 -1
  47. package/dist/commands/profile.d.ts +13 -0
  48. package/dist/commands/profile.js +104 -0
  49. package/dist/{esm/commands → commands}/publish.d.ts +1 -2
  50. package/dist/{esm/commands → commands}/publish.js +63 -12
  51. package/dist/{esm/commands → commands}/query.d.ts +4 -2
  52. package/dist/{esm/commands → commands}/query.js +12 -10
  53. package/dist/commands/repo.d.ts +17 -0
  54. package/dist/commands/repo.js +157 -0
  55. package/dist/{esm/commands → commands}/run-exec.d.ts +0 -1
  56. package/dist/commands/run-exec.js +40 -0
  57. package/dist/{esm/commands → commands}/run.d.ts +0 -1
  58. package/dist/{esm/commands → commands}/run.js +27 -1
  59. package/dist/commands/token.d.ts +31 -0
  60. package/dist/commands/token.js +186 -0
  61. package/dist/{esm/commands → commands}/uninstall.d.ts +0 -1
  62. package/dist/{esm/commands → commands}/uninstall.js +16 -3
  63. package/dist/commands/unpublish.d.ts +15 -0
  64. package/dist/commands/unpublish.js +200 -0
  65. package/dist/{esm/commands → commands}/update.d.ts +0 -1
  66. package/dist/{esm/commands → commands}/update.js +6 -1
  67. package/dist/{esm/commands → commands}/version.d.ts +0 -1
  68. package/dist/{esm/commands → commands}/version.js +27 -1
  69. package/dist/commands/view.d.ts +22 -0
  70. package/dist/commands/view.js +334 -0
  71. package/dist/{esm/commands → commands}/whoami.d.ts +0 -1
  72. package/dist/{esm/commands → commands}/whoami.js +10 -1
  73. package/dist/{esm/config → config}/definition.d.ts +39 -19
  74. package/dist/{esm/config → config}/definition.js +74 -39
  75. package/dist/{esm/config → config}/index.d.ts +0 -1
  76. package/dist/{esm/config → config}/index.js +37 -2
  77. package/dist/{esm/config → config}/merge.d.ts +0 -1
  78. package/dist/{esm/config → config}/merge.js +0 -1
  79. package/dist/{esm/config → config}/usage.d.ts +0 -1
  80. package/dist/{esm/config → config}/usage.js +0 -1
  81. package/dist/{esm/custom-help.d.ts → custom-help.d.ts} +0 -1
  82. package/dist/{esm/custom-help.js → custom-help.js} +35 -9
  83. package/dist/{esm/exec-command.d.ts → exec-command.d.ts} +0 -1
  84. package/dist/{esm/exec-command.js → exec-command.js} +14 -8
  85. package/dist/{esm/index.d.ts → index.d.ts} +0 -1
  86. package/dist/{esm/index.js → index.js} +1 -2
  87. package/dist/{esm/load-command.d.ts → load-command.d.ts} +0 -1
  88. package/dist/{esm/load-command.js → load-command.js} +0 -1
  89. package/dist/mermaid-image-view.d.ts +18 -0
  90. package/dist/mermaid-image-view.js +36 -0
  91. package/dist/{esm/output.d.ts → output.d.ts} +2 -2
  92. package/dist/{esm/output.js → output.js} +55 -2
  93. package/dist/{esm/pack-tarball.d.ts → pack-tarball.d.ts} +15 -1
  94. package/dist/{esm/pack-tarball.js → pack-tarball.js} +133 -91
  95. package/dist/{esm/parse-add-remove-args.d.ts → parse-add-remove-args.d.ts} +9 -3
  96. package/dist/{esm/parse-add-remove-args.js → parse-add-remove-args.js} +43 -11
  97. package/dist/{esm/print-err.d.ts → print-err.d.ts} +0 -1
  98. package/dist/{esm/print-err.js → print-err.js} +18 -3
  99. package/dist/query-diff-files.d.ts +17 -0
  100. package/dist/query-diff-files.js +63 -0
  101. package/dist/{esm/query-host-contexts.d.ts → query-host-contexts.d.ts} +0 -1
  102. package/dist/{esm/query-host-contexts.js → query-host-contexts.js} +8 -7
  103. package/dist/{esm/read-password.d.ts → read-password.d.ts} +0 -1
  104. package/dist/{esm/read-password.js → read-password.js} +0 -1
  105. package/dist/read-project-folders.d.ts +17 -0
  106. package/dist/read-project-folders.js +100 -0
  107. package/dist/reload-config.d.ts +2 -0
  108. package/dist/reload-config.js +11 -0
  109. package/dist/render-mermaid.d.ts +22 -0
  110. package/dist/render-mermaid.js +68 -0
  111. package/dist/telemetry.d.ts +58 -0
  112. package/dist/telemetry.js +170 -0
  113. package/dist/{esm/view.d.ts → view.d.ts} +0 -1
  114. package/dist/{esm/view.js → view.js} +1 -2
  115. package/package.json +69 -83
  116. package/dist/esm/commands/build.d.ts.map +0 -1
  117. package/dist/esm/commands/build.js.map +0 -1
  118. package/dist/esm/commands/cache.d.ts.map +0 -1
  119. package/dist/esm/commands/cache.js.map +0 -1
  120. package/dist/esm/commands/ci.d.ts.map +0 -1
  121. package/dist/esm/commands/ci.js.map +0 -1
  122. package/dist/esm/commands/config.d.ts.map +0 -1
  123. package/dist/esm/commands/config.js.map +0 -1
  124. package/dist/esm/commands/docs.d.ts.map +0 -1
  125. package/dist/esm/commands/docs.js.map +0 -1
  126. package/dist/esm/commands/exec-cache.d.ts.map +0 -1
  127. package/dist/esm/commands/exec-cache.js.map +0 -1
  128. package/dist/esm/commands/exec-local.d.ts.map +0 -1
  129. package/dist/esm/commands/exec-local.js.map +0 -1
  130. package/dist/esm/commands/exec.d.ts.map +0 -1
  131. package/dist/esm/commands/exec.js.map +0 -1
  132. package/dist/esm/commands/help.d.ts.map +0 -1
  133. package/dist/esm/commands/help.js.map +0 -1
  134. package/dist/esm/commands/init.d.ts.map +0 -1
  135. package/dist/esm/commands/init.js.map +0 -1
  136. package/dist/esm/commands/install/reporter.d.ts.map +0 -1
  137. package/dist/esm/commands/install/reporter.js.map +0 -1
  138. package/dist/esm/commands/install.d.ts.map +0 -1
  139. package/dist/esm/commands/install.js +0 -45
  140. package/dist/esm/commands/install.js.map +0 -1
  141. package/dist/esm/commands/list.d.ts.map +0 -1
  142. package/dist/esm/commands/list.js.map +0 -1
  143. package/dist/esm/commands/login.d.ts.map +0 -1
  144. package/dist/esm/commands/login.js.map +0 -1
  145. package/dist/esm/commands/logout.d.ts +0 -4
  146. package/dist/esm/commands/logout.d.ts.map +0 -1
  147. package/dist/esm/commands/logout.js.map +0 -1
  148. package/dist/esm/commands/pack.d.ts.map +0 -1
  149. package/dist/esm/commands/pack.js.map +0 -1
  150. package/dist/esm/commands/pkg.d.ts.map +0 -1
  151. package/dist/esm/commands/pkg.js.map +0 -1
  152. package/dist/esm/commands/publish.d.ts.map +0 -1
  153. package/dist/esm/commands/publish.js.map +0 -1
  154. package/dist/esm/commands/query.d.ts.map +0 -1
  155. package/dist/esm/commands/query.js.map +0 -1
  156. package/dist/esm/commands/run-exec.d.ts.map +0 -1
  157. package/dist/esm/commands/run-exec.js +0 -14
  158. package/dist/esm/commands/run-exec.js.map +0 -1
  159. package/dist/esm/commands/run.d.ts.map +0 -1
  160. package/dist/esm/commands/run.js.map +0 -1
  161. package/dist/esm/commands/serve.d.ts +0 -14
  162. package/dist/esm/commands/serve.d.ts.map +0 -1
  163. package/dist/esm/commands/serve.js +0 -103
  164. package/dist/esm/commands/serve.js.map +0 -1
  165. package/dist/esm/commands/token.d.ts.map +0 -1
  166. package/dist/esm/commands/token.js +0 -30
  167. package/dist/esm/commands/token.js.map +0 -1
  168. package/dist/esm/commands/uninstall.d.ts.map +0 -1
  169. package/dist/esm/commands/uninstall.js.map +0 -1
  170. package/dist/esm/commands/update.d.ts.map +0 -1
  171. package/dist/esm/commands/update.js.map +0 -1
  172. package/dist/esm/commands/version.d.ts.map +0 -1
  173. package/dist/esm/commands/version.js.map +0 -1
  174. package/dist/esm/commands/whoami.d.ts.map +0 -1
  175. package/dist/esm/commands/whoami.js.map +0 -1
  176. package/dist/esm/config/definition.d.ts.map +0 -1
  177. package/dist/esm/config/definition.js.map +0 -1
  178. package/dist/esm/config/index.d.ts.map +0 -1
  179. package/dist/esm/config/index.js.map +0 -1
  180. package/dist/esm/config/merge.d.ts.map +0 -1
  181. package/dist/esm/config/merge.js.map +0 -1
  182. package/dist/esm/config/usage.d.ts.map +0 -1
  183. package/dist/esm/config/usage.js.map +0 -1
  184. package/dist/esm/custom-help.d.ts.map +0 -1
  185. package/dist/esm/custom-help.js.map +0 -1
  186. package/dist/esm/exec-command.d.ts.map +0 -1
  187. package/dist/esm/exec-command.js.map +0 -1
  188. package/dist/esm/index.d.ts.map +0 -1
  189. package/dist/esm/index.js.map +0 -1
  190. package/dist/esm/load-command.d.ts.map +0 -1
  191. package/dist/esm/load-command.js.map +0 -1
  192. package/dist/esm/output.d.ts.map +0 -1
  193. package/dist/esm/output.js.map +0 -1
  194. package/dist/esm/pack-tarball.d.ts.map +0 -1
  195. package/dist/esm/pack-tarball.js.map +0 -1
  196. package/dist/esm/package.json +0 -3
  197. package/dist/esm/parse-add-remove-args.d.ts.map +0 -1
  198. package/dist/esm/parse-add-remove-args.js.map +0 -1
  199. package/dist/esm/print-err.d.ts.map +0 -1
  200. package/dist/esm/print-err.js.map +0 -1
  201. package/dist/esm/query-host-contexts.d.ts.map +0 -1
  202. package/dist/esm/query-host-contexts.js.map +0 -1
  203. package/dist/esm/read-password.d.ts.map +0 -1
  204. package/dist/esm/read-password.js.map +0 -1
  205. package/dist/esm/start-gui.d.ts +0 -10
  206. package/dist/esm/start-gui.d.ts.map +0 -1
  207. package/dist/esm/start-gui.js +0 -60
  208. package/dist/esm/start-gui.js.map +0 -1
  209. package/dist/esm/view.d.ts.map +0 -1
  210. package/dist/esm/view.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import type { CommandFn, CommandUsage } from '../index.ts';
2
+ export declare const usage: CommandUsage;
3
+ export type AccessResult = {
4
+ package: string;
5
+ access: string;
6
+ } | {
7
+ packages: Record<string, string>;
8
+ } | {
9
+ granted: {
10
+ team: string;
11
+ permissions: string;
12
+ };
13
+ } | {
14
+ revoked: {
15
+ team: string;
16
+ };
17
+ };
18
+ export declare const views: {
19
+ readonly human: (result: AccessResult) => string;
20
+ readonly json: (r: AccessResult) => AccessResult;
21
+ };
22
+ export declare const command: CommandFn<AccessResult>;
@@ -0,0 +1,246 @@
1
+ import { error } from '@vltpkg/error-cause';
2
+ import { RegistryClient } from '@vltpkg/registry-client';
3
+ import { commandUsage } from "../config/usage.js";
4
+ export const usage = () => commandUsage({
5
+ command: 'access',
6
+ usage: '<command> [<args>]',
7
+ description: `Set or get access levels for published packages
8
+ and manage team-based package permissions.`,
9
+ subcommands: {
10
+ 'list packages': {
11
+ usage: '[<scope|user|org>]',
12
+ description: 'List packages with access info for a scope, user, or org.',
13
+ },
14
+ 'get status': {
15
+ usage: '<package>',
16
+ description: 'Get the access/visibility status of a package.',
17
+ },
18
+ 'set status': {
19
+ usage: '<package>',
20
+ description: `Set the access/visibility of a package. Use --access to specify the level.`,
21
+ },
22
+ grant: {
23
+ usage: '<read-only|read-write> <scope:team> [<package>]',
24
+ description: 'Grant access to a scope:team for a package.',
25
+ },
26
+ revoke: {
27
+ usage: '<scope:team> [<package>]',
28
+ description: 'Revoke access from a scope:team for a package.',
29
+ },
30
+ },
31
+ options: {
32
+ registry: {
33
+ value: '<url>',
34
+ description: 'Registry URL to manage access on.',
35
+ },
36
+ otp: {
37
+ description: 'Provide an OTP for access changes.',
38
+ value: '<otp>',
39
+ },
40
+ },
41
+ });
42
+ export const views = {
43
+ human: (result) => {
44
+ if ('packages' in result) {
45
+ const entries = Object.entries(result.packages);
46
+ if (entries.length === 0)
47
+ return 'No packages found.';
48
+ return entries
49
+ .map(([name, access]) => `${name}: ${access}`)
50
+ .join('\n');
51
+ }
52
+ if ('granted' in result) {
53
+ return `Granted ${result.granted.permissions} access to ${result.granted.team}.`;
54
+ }
55
+ if ('revoked' in result) {
56
+ return `Revoked access from ${result.revoked.team}.`;
57
+ }
58
+ return `${result.package}: ${result.access}`;
59
+ },
60
+ json: (r) => r,
61
+ };
62
+ export const command = async (conf) => {
63
+ const [sub, ...args] = conf.positionals;
64
+ switch (sub) {
65
+ case 'list':
66
+ return listPackages(conf, args);
67
+ case 'get':
68
+ return getStatus(conf, args);
69
+ case 'set':
70
+ return setStatus(conf, args);
71
+ case 'grant':
72
+ return grant(conf, args);
73
+ case 'revoke':
74
+ return revoke(conf, args);
75
+ default: {
76
+ throw error('Invalid access subcommand', {
77
+ found: sub,
78
+ validOptions: ['list', 'get', 'set', 'grant', 'revoke'],
79
+ code: 'EUSAGE',
80
+ });
81
+ }
82
+ }
83
+ };
84
+ const encodePkgName = (name) => name.startsWith('@') ?
85
+ `@${encodeURIComponent(name.slice(1))}`
86
+ : encodeURIComponent(name);
87
+ const listPackages = async (conf, args) => {
88
+ const [keyword, entity] = args;
89
+ if (keyword !== 'packages') {
90
+ throw error('Expected `list packages [<scope|user|org>]`', {
91
+ found: keyword,
92
+ code: 'EUSAGE',
93
+ });
94
+ }
95
+ const rc = new RegistryClient(conf.options);
96
+ const registryUrl = new URL(conf.options.registry);
97
+ // Determine who to list for — use entity arg or fall back to scope from package.json
98
+ const scope = entity ?? getDefaultScope(conf);
99
+ const url = new URL(`-/org/${encodeURIComponent(scope)}/package`, registryUrl);
100
+ const response = await rc.request(url, { useCache: false });
101
+ const data = response.json();
102
+ return { packages: data };
103
+ };
104
+ const getStatus = async (conf, args) => {
105
+ const [keyword, pkg] = args;
106
+ if (keyword !== 'status') {
107
+ throw error('Expected `get status <package>`', {
108
+ found: keyword,
109
+ code: 'EUSAGE',
110
+ });
111
+ }
112
+ if (!pkg) {
113
+ throw error('Package name is required for `get status`', {
114
+ code: 'EUSAGE',
115
+ });
116
+ }
117
+ const rc = new RegistryClient(conf.options);
118
+ const registryUrl = new URL(conf.options.registry);
119
+ const url = new URL(`-/package/${encodePkgName(pkg)}/access`, registryUrl);
120
+ const response = await rc.request(url, { useCache: false });
121
+ const data = response.json();
122
+ return { package: pkg, access: data.access };
123
+ };
124
+ const setStatus = async (conf, args) => {
125
+ // vlt access set status=<public|restricted> <package>
126
+ const [statusArg, pkg] = args;
127
+ if (!statusArg?.startsWith('status=')) {
128
+ throw error('Expected `set status=<public|restricted> <package>`', { found: statusArg, code: 'EUSAGE' });
129
+ }
130
+ const accessLevel = statusArg.slice('status='.length);
131
+ if (accessLevel !== 'public' && accessLevel !== 'restricted') {
132
+ throw error('Access level must be `public` or `restricted`', {
133
+ found: accessLevel,
134
+ validOptions: ['public', 'restricted'],
135
+ code: 'EUSAGE',
136
+ });
137
+ }
138
+ if (!pkg) {
139
+ throw error('Package name is required for `set status`', {
140
+ code: 'EUSAGE',
141
+ });
142
+ }
143
+ const rc = new RegistryClient(conf.options);
144
+ const registryUrl = new URL(conf.options.registry);
145
+ const url = new URL(`-/package/${encodePkgName(pkg)}/access`, registryUrl);
146
+ await rc.request(url, {
147
+ method: 'PUT',
148
+ headers: { 'content-type': 'application/json' },
149
+ body: JSON.stringify({ access: accessLevel }),
150
+ otp: conf.options.otp,
151
+ useCache: false,
152
+ });
153
+ return { package: pkg, access: accessLevel };
154
+ };
155
+ const grant = async (conf, args) => {
156
+ // vlt access grant <read-only|read-write> <scope:team> [<package>]
157
+ const [permissions, scopeTeam, pkg] = args;
158
+ if (permissions !== 'read-only' && permissions !== 'read-write') {
159
+ throw error('Permissions must be `read-only` or `read-write`', {
160
+ found: permissions,
161
+ validOptions: ['read-only', 'read-write'],
162
+ code: 'EUSAGE',
163
+ });
164
+ }
165
+ if (!scopeTeam?.includes(':')) {
166
+ throw error('Team must be in the format `<scope>:<team>`', {
167
+ found: scopeTeam,
168
+ code: 'EUSAGE',
169
+ });
170
+ }
171
+ const [scope, team] = scopeTeam.split(':');
172
+ if (!scope || !team) {
173
+ throw error('Team must be in the format `<scope>:<team>`', {
174
+ found: scopeTeam,
175
+ code: 'EUSAGE',
176
+ });
177
+ }
178
+ const pkgName = pkg ?? getDefaultPkgName(conf);
179
+ const rc = new RegistryClient(conf.options);
180
+ const registryUrl = new URL(conf.options.registry);
181
+ const url = new URL(`-/team/${encodeURIComponent(scope)}/${encodeURIComponent(team)}/package`, registryUrl);
182
+ await rc.request(url, {
183
+ method: 'PUT',
184
+ headers: { 'content-type': 'application/json' },
185
+ body: JSON.stringify({
186
+ package: pkgName,
187
+ permissions,
188
+ }),
189
+ otp: conf.options.otp,
190
+ useCache: false,
191
+ });
192
+ return {
193
+ granted: {
194
+ team: `${scope}:${team}`,
195
+ permissions,
196
+ },
197
+ };
198
+ };
199
+ const revoke = async (conf, args) => {
200
+ // vlt access revoke <scope:team> [<package>]
201
+ const [scopeTeam, pkg] = args;
202
+ if (!scopeTeam?.includes(':')) {
203
+ throw error('Team must be in the format `<scope>:<team>`', {
204
+ found: scopeTeam,
205
+ code: 'EUSAGE',
206
+ });
207
+ }
208
+ const [scope, team] = scopeTeam.split(':');
209
+ if (!scope || !team) {
210
+ throw error('Team must be in the format `<scope>:<team>`', {
211
+ found: scopeTeam,
212
+ code: 'EUSAGE',
213
+ });
214
+ }
215
+ const pkgName = pkg ?? getDefaultPkgName(conf);
216
+ const rc = new RegistryClient(conf.options);
217
+ const registryUrl = new URL(conf.options.registry);
218
+ const url = new URL(`-/team/${encodeURIComponent(scope)}/${encodeURIComponent(team)}/package`, registryUrl);
219
+ await rc.request(url, {
220
+ method: 'DELETE',
221
+ headers: { 'content-type': 'application/json' },
222
+ body: JSON.stringify({ package: pkgName }),
223
+ otp: conf.options.otp,
224
+ useCache: false,
225
+ });
226
+ return {
227
+ revoked: {
228
+ team: `${scope}:${team}`,
229
+ },
230
+ };
231
+ };
232
+ const getDefaultScope = (conf) => {
233
+ const name = conf.options.packageJson.maybeRead(conf.projectRoot)?.name;
234
+ if (name?.startsWith('@')) {
235
+ const scope = name.split('/')[0];
236
+ if (scope)
237
+ return scope;
238
+ }
239
+ throw error('Could not determine scope. Provide a scope, user, or org.', { code: 'EUSAGE' });
240
+ };
241
+ const getDefaultPkgName = (conf) => {
242
+ const name = conf.options.packageJson.maybeRead(conf.projectRoot)?.name;
243
+ if (name)
244
+ return name;
245
+ throw error('Could not determine package name. Provide a package name or run from a package directory.', { code: 'EUSAGE' });
246
+ };
@@ -0,0 +1,17 @@
1
+ import type { CommandFn, CommandUsage } from '../index.ts';
2
+ export declare const usage: CommandUsage;
3
+ type CommandResultSingle = {
4
+ url: string;
5
+ name: string;
6
+ };
7
+ type CommandResultMultiple = {
8
+ url: string;
9
+ name: string;
10
+ }[];
11
+ export type CommandResult = CommandResultSingle | CommandResultMultiple;
12
+ export declare const views: {
13
+ readonly human: (r: CommandResult) => string;
14
+ readonly json: (r: CommandResult) => CommandResult;
15
+ };
16
+ export declare const command: CommandFn<CommandResult>;
17
+ export {};
@@ -0,0 +1,163 @@
1
+ import { error } from '@vltpkg/error-cause';
2
+ import { PackageInfoClient } from '@vltpkg/package-info';
3
+ import { Spec } from '@vltpkg/spec';
4
+ import { urlOpen } from '@vltpkg/url-open';
5
+ import { actual } from '@vltpkg/graph';
6
+ import { Query } from '@vltpkg/query';
7
+ import { SecurityArchive } from '@vltpkg/security-archive';
8
+ import { createHostContextsMap } from "../query-host-contexts.js";
9
+ import { commandUsage } from "../config/usage.js";
10
+ import hostedGitInfo from 'hosted-git-info';
11
+ const { fromUrl: hostedGitInfoFromUrl } = hostedGitInfo;
12
+ export const usage = () => commandUsage({
13
+ command: 'bugs',
14
+ usage: ['[<spec>]', '[--target=<query>]'],
15
+ description: `Open bug tracker for a package in a web browser.
16
+ Reads bug tracker information from package.json or fetches
17
+ manifest data for the specified package.`,
18
+ options: {
19
+ target: {
20
+ value: '<query>',
21
+ description: 'Query selector to filter packages using DSS syntax.',
22
+ },
23
+ },
24
+ examples: {
25
+ '': {
26
+ description: 'Open bugs for the current package (reads local package.json)',
27
+ },
28
+ 'abbrev@2.0.0': {
29
+ description: 'Open bugs for a specific package version',
30
+ },
31
+ '--target=":root > *"': {
32
+ description: 'List bug tracker URLs for all direct dependencies',
33
+ },
34
+ },
35
+ });
36
+ export const views = {
37
+ human: r => {
38
+ if (Array.isArray(r)) {
39
+ let msg = 'Multiple package bug trackers found:\n';
40
+ msg += r.map(item => `• ${item.name}: ${item.url}`).join('\n');
41
+ return msg;
42
+ }
43
+ return '';
44
+ },
45
+ json: r => r,
46
+ };
47
+ const getUrlFromManifest = (manifest) => {
48
+ const { name, bugs, repository } = manifest;
49
+ if (!name) {
50
+ throw error('No package name found');
51
+ }
52
+ let url;
53
+ // Check bugs field first
54
+ if (bugs) {
55
+ if (typeof bugs === 'string') {
56
+ url = bugs;
57
+ }
58
+ else if (typeof bugs === 'object') {
59
+ if ('url' in bugs && bugs.url) {
60
+ url = bugs.url;
61
+ }
62
+ else if ('email' in bugs && bugs.email) {
63
+ url = `mailto:${bugs.email}`;
64
+ }
65
+ }
66
+ }
67
+ // Try repository if no bugs field
68
+ if (!url && repository) {
69
+ const repoUrl = typeof repository === 'string' ? repository
70
+ : typeof repository === 'object' && 'url' in repository ?
71
+ repository.url
72
+ : /* c8 ignore next */ undefined;
73
+ if (repoUrl) {
74
+ const info = hostedGitInfoFromUrl(repoUrl.replace(/^git\+/, ''));
75
+ if (info?.bugs && typeof info.bugs === 'function') {
76
+ url = info.bugs();
77
+ }
78
+ }
79
+ }
80
+ // Fallback to vlt.io package page
81
+ if (!url) {
82
+ url = `https://vlt.io/explore/npm/${name}/overview`;
83
+ }
84
+ return url;
85
+ };
86
+ export const command = async (conf) => {
87
+ const { projectRoot, packageJson } = conf.options;
88
+ const targetOption = conf.get('target');
89
+ // Handle --target query
90
+ if (targetOption) {
91
+ const mainManifest = packageJson.maybeRead(projectRoot);
92
+ if (!mainManifest) {
93
+ throw error('No package.json found in project root', {
94
+ path: projectRoot,
95
+ });
96
+ }
97
+ const graph = actual.load({
98
+ ...conf.options,
99
+ mainManifest,
100
+ monorepo: conf.options.monorepo,
101
+ loadManifests: true,
102
+ });
103
+ const securityArchive = Query.hasSecuritySelectors(targetOption) ?
104
+ await SecurityArchive.start({
105
+ nodes: [...graph.nodes.values()],
106
+ })
107
+ : undefined;
108
+ const hostContexts = await createHostContextsMap(conf);
109
+ const query = new Query({
110
+ nodes: new Set(graph.nodes.values()),
111
+ edges: graph.edges,
112
+ importers: graph.importers,
113
+ securityArchive,
114
+ hostContexts,
115
+ });
116
+ const { nodes } = await query.search(targetOption, {
117
+ signal: new AbortController().signal,
118
+ });
119
+ const results = [];
120
+ for (const node of nodes) {
121
+ if (!node.manifest)
122
+ continue;
123
+ const url = getUrlFromManifest(node.manifest);
124
+ results.push({
125
+ url,
126
+ name: node.name /* c8 ignore next */ ?? '(unknown)',
127
+ });
128
+ }
129
+ if (results.length === 0) {
130
+ throw error('No packages found matching target query', {
131
+ found: targetOption,
132
+ });
133
+ }
134
+ // If single result, open it
135
+ if (results.length === 1) {
136
+ const result = results[0];
137
+ /* c8 ignore next 3 */
138
+ if (!result) {
139
+ throw error('Unexpected empty result');
140
+ }
141
+ await urlOpen(result.url);
142
+ return result;
143
+ }
144
+ // Multiple results, return the list
145
+ return results;
146
+ }
147
+ // read the package spec from a positional argument or local package.json
148
+ const specArg = conf.positionals[0];
149
+ const manifest = conf.positionals.length === 0 ? packageJson.read(projectRoot)
150
+ : specArg ?
151
+ await new PackageInfoClient(conf.options).manifest(Spec.parseArgs(specArg, conf.options))
152
+ : /* c8 ignore next */ packageJson.read(projectRoot);
153
+ const url = getUrlFromManifest(manifest);
154
+ const { name } = manifest;
155
+ /* c8 ignore start - getUrlFromManifest already validates name */
156
+ if (!name) {
157
+ throw error('No package name found');
158
+ }
159
+ /* c8 ignore stop */
160
+ // Open the URL
161
+ await urlOpen(url);
162
+ return { url, name };
163
+ };
@@ -22,4 +22,3 @@ export declare const usage: CommandUsage;
22
22
  * lifecycle scripts and binary linking.
23
23
  */
24
24
  export declare const command: CommandFn<BuildResult>;
25
- //# sourceMappingURL=build.d.ts.map
@@ -99,4 +99,3 @@ export const command = async (conf) => {
99
99
  throw error('Build failed', { cause });
100
100
  }
101
101
  };
102
- //# sourceMappingURL=build.js.map
@@ -62,4 +62,3 @@ declare const usageDef: {
62
62
  export declare const usage: CommandUsage;
63
63
  export declare const command: CommandFn<void | CacheMap>;
64
64
  export {};
65
- //# sourceMappingURL=cache.d.ts.map
@@ -254,4 +254,3 @@ const add = async (conf, specs, view) => {
254
254
  }
255
255
  await Promise.all(promises);
256
256
  };
257
- //# sourceMappingURL=cache.js.map
@@ -8,4 +8,3 @@ export declare const views: {
8
8
  readonly human: typeof InstallReporter;
9
9
  };
10
10
  export declare const command: CommandFn<CIResult>;
11
- //# sourceMappingURL=ci.d.ts.map
@@ -11,6 +11,15 @@ export const usage = () => commandUsage({
11
11
  examples: {
12
12
  '': { description: 'Clean install from lockfile' },
13
13
  },
14
+ options: {
15
+ 'allow-scripts': {
16
+ value: '<query>',
17
+ description: 'Filter which packages are allowed to run lifecycle scripts using DSS query syntax.',
18
+ },
19
+ 'lockfile-only': {
20
+ description: 'Only update lockfile and package.json files; skip node_modules operations.',
21
+ },
22
+ },
14
23
  });
15
24
  export const views = {
16
25
  json: i => i.graph.toJSON(),
@@ -19,8 +28,8 @@ export const views = {
19
28
  export const command = async (conf) => {
20
29
  const ciOptions = {
21
30
  ...conf.options,
22
- // allow all scripts by default on ci (unless user specifies a filter)
23
- allowScripts: conf.get('allow-scripts') ?? '*',
31
+ // allow scripts but filter out malware via security archive
32
+ allowScripts: conf.get('allow-scripts') ?? ':scripts:not(:malware)',
24
33
  expectLockfile: true,
25
34
  frozenLockfile: true,
26
35
  cleanInstall: true,
@@ -29,4 +38,3 @@ export const command = async (conf) => {
29
38
  const { graph } = await install(ciOptions);
30
39
  return { graph };
31
40
  };
32
- //# sourceMappingURL=ci.js.map
@@ -3,4 +3,3 @@ import type { Views } from '../view.ts';
3
3
  export declare const views: Views;
4
4
  export declare const usage: CommandUsage;
5
5
  export declare const command: CommandFn;
6
- //# sourceMappingURL=config.d.ts.map
@@ -18,6 +18,12 @@ export const usage = () => commandUsage({
18
18
  command: 'config',
19
19
  usage: '[<command>] [<args>]',
20
20
  description: 'Get or manipulate vlt configuration values',
21
+ options: {
22
+ config: {
23
+ value: '<all | user | project>',
24
+ description: 'Specify which configuration to show or operate on.',
25
+ },
26
+ },
21
27
  subcommands: {
22
28
  get: {
23
29
  usage: '[<key>] [--config=<all | user | project>]',
@@ -421,4 +427,3 @@ const configLocation = (conf) => {
421
427
  const configPath = find(effectiveConfig);
422
428
  return configPath;
423
429
  };
424
- //# sourceMappingURL=config.js.map
@@ -0,0 +1,8 @@
1
+ import type { PromptFn } from '@vltpkg/vlx';
2
+ import type { ExecResult } from '../exec-command.ts';
3
+ import type { CommandFn, CommandUsage } from '../index.ts';
4
+ export { views } from '../exec-command.ts';
5
+ export declare const usage: CommandUsage;
6
+ export declare const prettyPath: (path: string) => string;
7
+ export declare const promptFn: PromptFn;
8
+ export declare const command: CommandFn<ExecResult>;
@@ -0,0 +1,102 @@
1
+ import { exec, execFG } from '@vltpkg/run';
2
+ import * as vlx from '@vltpkg/vlx';
3
+ import { homedir } from 'node:os';
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { commandUsage } from "../config/usage.js";
6
+ import { ExecCommand } from "../exec-command.js";
7
+ import { styleTextStdout } from "../output.js";
8
+ export { views } from "../exec-command.js";
9
+ export const usage = () => commandUsage({
10
+ command: 'create',
11
+ usage: '<initializer> [args...]',
12
+ description: `Initialize a new project from a template package.
13
+
14
+ Works like \`npm create\` and \`bun create\`, automatically
15
+ prepending "create-" to the package name and executing it.
16
+
17
+ For example, \`vlt create react-app my-app\` will fetch and
18
+ execute the \`create-react-app\` package with the arguments
19
+ \`my-app\`.
20
+
21
+ If a satisfying instance of the create package exists in the
22
+ local \`node_modules\` folder, then that will be used.
23
+
24
+ At no point will \`vlt create\` change the locally installed
25
+ dependencies. Any installs it performs is done in vlt's XDG
26
+ data directory.
27
+ `,
28
+ examples: {
29
+ 'react-app my-app': {
30
+ description: 'Create a new React app using create-react-app',
31
+ },
32
+ 'vite my-project': {
33
+ description: 'Create a new Vite project using create-vite',
34
+ },
35
+ '@scope/template my-app': {
36
+ description: 'Create a new project using @scope/create-template',
37
+ },
38
+ },
39
+ options: {
40
+ 'allow-scripts': {
41
+ value: '<query>',
42
+ description: 'Filter which packages are allowed to run lifecycle scripts using DSS query syntax.',
43
+ },
44
+ yes: {
45
+ description: 'Skip interactive prompts and accept defaults.',
46
+ },
47
+ },
48
+ });
49
+ const HOME = homedir();
50
+ export const prettyPath = (path) => path.startsWith(HOME) ? `~${path.substring(HOME.length)}` : path;
51
+ export const promptFn = async (pkgSpec, path, resolution) => {
52
+ const response = await createInterface(process.stdin, process.stdout).question(`About to install: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], String(pkgSpec))}
53
+ from: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], resolution)}
54
+ into: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], prettyPath(path))}
55
+ Is this ok? (y) `);
56
+ process.stdin.pause();
57
+ return response;
58
+ };
59
+ export const command = async (conf) => {
60
+ const [initializer, ...args] = conf.positionals;
61
+ if (!initializer) {
62
+ throw new Error('Missing required argument: <initializer>\n\nUsage: vlt create <initializer> [args...]');
63
+ }
64
+ // Transform the initializer to a create-* package name
65
+ // e.g., "react-app" -> "create-react-app"
66
+ // or "@scope/template" -> "@scope/create-template"
67
+ let packageName;
68
+ if (initializer.startsWith('@')) {
69
+ // Handle scoped packages: @scope/name -> @scope/create-name
70
+ const [scope, name] = initializer.split('/');
71
+ packageName = name ? `${scope}/create-${name}` : `${scope}/create`;
72
+ }
73
+ else {
74
+ // Handle regular packages: name -> create-name
75
+ packageName = `create-${initializer}`;
76
+ }
77
+ /* c8 ignore start */
78
+ const allowScripts = conf.get('allow-scripts') ?
79
+ String(conf.get('allow-scripts'))
80
+ : ':not(*)';
81
+ /* c8 ignore stop */
82
+ const yesFlag = conf.get('yes');
83
+ // Resolve the create-* package using vlx. We pass the package name as
84
+ // a synthetic positional so vlx treats it as the command to resolve —
85
+ // NOT the user's args (like "app"). Without this, vlx would mistake
86
+ // the first user arg as the executable to spawn.
87
+ const arg0 = await vlx.resolve([packageName], {
88
+ ...conf.options,
89
+ query: undefined,
90
+ allowScripts,
91
+ }, yesFlag ? async () => 'y' : promptFn);
92
+ // Set positionals to the resolved executable and the user's args
93
+ if (arg0) {
94
+ conf.positionals = [arg0, ...args];
95
+ }
96
+ else {
97
+ throw new Error(`Could not resolve executable for package "${packageName}"`);
98
+ }
99
+ // Execute the create package
100
+ delete conf.options['script-shell'];
101
+ return await new ExecCommand(conf, exec, execFG).run();
102
+ };
@@ -0,0 +1,13 @@
1
+ import type { CommandFn, CommandUsage } from '../index.ts';
2
+ export declare const usage: CommandUsage;
3
+ export type CommandResult = {
4
+ name: string;
5
+ version: string;
6
+ message: string;
7
+ versions: string[];
8
+ };
9
+ export declare const views: {
10
+ readonly human: (result: CommandResult) => string;
11
+ readonly json: (r: CommandResult) => CommandResult;
12
+ };
13
+ export declare const command: CommandFn<CommandResult>;