@node-core/utils 6.1.0 → 6.2.0

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.
@@ -4,7 +4,7 @@ import ReleasePreparation from '../../lib/prepare_release.js';
4
4
  import ReleasePromotion from '../../lib/promote_release.js';
5
5
  import TeamInfo from '../../lib/team_info.js';
6
6
  import Request from '../../lib/request.js';
7
- import { runPromise } from '../../lib/run.js';
7
+ import { forceRunAsync, runPromise } from '../../lib/run.js';
8
8
 
9
9
  export const command = 'release [prid..]';
10
10
  export const describe = 'Manage an in-progress release or start a new one.';
@@ -87,8 +87,8 @@ export function builder(yargs) {
87
87
  'Prepare a new security release of Node.js with auto-determined version')
88
88
  .example('git node release --prepare --newVersion=1.2.3',
89
89
  'Prepare a new release of Node.js tagged v1.2.3')
90
- .example('git node release --promote 12345',
91
- 'Promote a prepared release of Node.js with PR #12345')
90
+ .example('git node release --promote https://github.com/nodejs/node/pull/12345 https://github.com/nodejs/node/pull/54321',
91
+ 'Promote two prepared releases of Node.js with PR #12345 and #54321')
92
92
  .example('git node --prepare --startLTS',
93
93
  'Prepare the first LTS release');
94
94
  }
@@ -114,7 +114,7 @@ function release(state, argv) {
114
114
  cli.setAssumeYes();
115
115
  }
116
116
 
117
- return runPromise(main(state, argv, cli, dir)).catch((err) => {
117
+ return runPromise(wrapStash(() => main(state, argv, cli, dir))).catch((err) => {
118
118
  if (cli.spinner.enabled) {
119
119
  cli.spinner.fail();
120
120
  }
@@ -122,6 +122,22 @@ function release(state, argv) {
122
122
  });
123
123
  }
124
124
 
125
+ async function wrapStash(fn) {
126
+ const stashTip = await forceRunAsync('git', ['stash', 'list', '-1', '--format="%gd"'],
127
+ { ignoreFailure: false, captureStdout: true });
128
+ await forceRunAsync('git', ['stash', '--include-untracked'], { ignoreFailure: false });
129
+ const newStashTip = await forceRunAsync('git', ['stash', 'list', '-1', '--format="%gd"'],
130
+ { ignoreFailure: false, captureStdout: true });
131
+ const hasStashed = newStashTip !== stashTip && newStashTip.trim();
132
+ try {
133
+ await fn();
134
+ } finally {
135
+ if (hasStashed) {
136
+ await forceRunAsync('git', ['stash', 'pop'], { ignoreFailure: false });
137
+ }
138
+ }
139
+ }
140
+
125
141
  async function main(state, argv, cli, dir) {
126
142
  if (state === PREPARE) {
127
143
  const release = new ReleasePreparation(argv, cli, dir);
@@ -182,7 +198,11 @@ async function main(state, argv, cli, dir) {
182
198
  console.info(`E.g. --fetch-from=git@github.com:${owner}/${repo}.git`);
183
199
  throw new Error('You need to tell what remote use to fetch security release proposal.');
184
200
  }
185
- releases.push(await release.preparePromotion({ owner, repo, prid: Number(prid) }));
201
+ releases.push(await release.preparePromotion({
202
+ owner: owner ?? release.owner,
203
+ repo: repo ?? release.repo,
204
+ prid: Number(prid)
205
+ }));
186
206
  }
187
207
  return release.promote(releases);
188
208
  }
@@ -48,7 +48,9 @@ async function main(argv) {
48
48
  let supported = [
49
49
  'dom',
50
50
  'html',
51
- 'webcrypto'
51
+ 'webcrypto',
52
+ 'webcrypto-secure-curves',
53
+ 'webcrypto-modern-algos',
52
54
  ];
53
55
  if (fs.existsSync(statusFolder)) {
54
56
  const jsons = fs.readdirSync(statusFolder);
package/lib/auth.js CHANGED
@@ -12,7 +12,7 @@ function errorExit(message) {
12
12
  process.exit(1);
13
13
  }
14
14
 
15
- function check(username, token) {
15
+ function check(username, token, format = /^[A-Za-z0-9_]+$/) {
16
16
  if (typeof username !== 'string') {
17
17
  errorExit(`username must be a string, received ${typeof username}`);
18
18
  }
@@ -25,7 +25,7 @@ function check(username, token) {
25
25
  if (typeof token !== 'string') {
26
26
  errorExit(`token must be a string, received ${typeof token}`);
27
27
  }
28
- if (!/^[A-Za-z0-9_]+$/.test(token)) {
28
+ if (!format.test(token)) {
29
29
  errorExit(`token is misformatted: ${token}`);
30
30
  }
31
31
  }
@@ -107,7 +107,7 @@ async function auth(
107
107
 
108
108
  get h1() {
109
109
  const { h1_username, h1_token } = getMergedConfig();
110
- check(h1_username, h1_token);
110
+ check(h1_username, h1_token, /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/);
111
111
  const h1 = encode(h1_username, h1_token);
112
112
  setOwnProperty(result, 'h1', h1);
113
113
  return h1;
package/lib/pr_checker.js CHANGED
@@ -128,20 +128,26 @@ export default class PRChecker {
128
128
  }
129
129
  }
130
130
 
131
- checkReviewsAndWait(now, checkComments) {
131
+ checkReviewsAndWait(now, checkComments, isReleaseProposal) {
132
132
  const {
133
133
  pr, cli, reviewers
134
134
  } = this;
135
135
  const { requestedChanges, approved } = reviewers;
136
+
137
+ const dateStr = new Date(pr.createdAt).toUTCString();
138
+ cli.info(`This PR was created on ${dateStr}`);
139
+ this.displayReviews(checkComments);
140
+
141
+ if (isReleaseProposal) {
142
+ cli.info('This PR is a release proposal');
143
+ return approved.length !== 0;
144
+ }
145
+
136
146
  const labels = pr.labels.nodes.map((l) => l.name);
137
147
 
138
148
  let isFastTracked = labels.includes('fast-track');
139
149
  const isCodeAndLearn = labels.includes('code-and-learn');
140
150
  const isSemverMajor = labels.includes('semver-major');
141
-
142
- const dateStr = new Date(pr.createdAt).toUTCString();
143
- cli.info(`This PR was created on ${dateStr}`);
144
- this.displayReviews(checkComments);
145
151
  // NOTE: a semver-major PR with fast-track should have either one of
146
152
  // these labels removed because that doesn't make sense
147
153
  if (isFastTracked) {
@@ -359,8 +365,13 @@ export default class PRChecker {
359
365
  return false;
360
366
  }
361
367
 
368
+ let hasFailures = false;
369
+ const failedJobs = [];
370
+ const cancelledJobs = [];
371
+ const pendingJobs = [];
372
+
362
373
  // GitHub new Check API
363
- for (const { status, conclusion, app } of checkSuites.nodes) {
374
+ for (const { status, conclusion, app, checkRuns } of checkSuites.nodes) {
364
375
  if (app.slug !== 'github-actions') {
365
376
  // Ignore all non-github check suites, such as Dependabot and Codecov.
366
377
  // They are expected to show up on PRs whose head branch is not on a
@@ -369,16 +380,80 @@ export default class PRChecker {
369
380
  }
370
381
 
371
382
  if (status !== 'COMPLETED') {
372
- cli.error('GitHub CI is still running');
373
- return false;
383
+ pendingJobs.push({ app: app.slug, status, conclusion });
384
+ continue;
374
385
  }
375
386
 
376
387
  if (!GITHUB_SUCCESS_CONCLUSIONS.includes(conclusion)) {
377
- cli.error('Last GitHub CI failed');
378
- return false;
388
+ hasFailures = true;
389
+
390
+ // If we have detailed checkRuns, show specific failing jobs
391
+ if (checkRuns && checkRuns.nodes && checkRuns.nodes.length > 0) {
392
+ for (const checkRun of checkRuns.nodes) {
393
+ if (checkRun.status === 'COMPLETED' &&
394
+ !GITHUB_SUCCESS_CONCLUSIONS.includes(checkRun.conclusion)) {
395
+ if (checkRun.conclusion === 'CANCELLED') {
396
+ cancelledJobs.push({
397
+ name: checkRun.name,
398
+ conclusion: checkRun.conclusion,
399
+ url: checkRun.detailsUrl
400
+ });
401
+ } else {
402
+ failedJobs.push({
403
+ name: checkRun.name,
404
+ conclusion: checkRun.conclusion,
405
+ url: checkRun.detailsUrl
406
+ });
407
+ }
408
+ }
409
+ }
410
+ } else {
411
+ // Fallback to check suite level information if no checkRuns
412
+ if (conclusion === 'CANCELLED') {
413
+ cancelledJobs.push({
414
+ name: app.slug,
415
+ conclusion,
416
+ url: null
417
+ });
418
+ } else {
419
+ failedJobs.push({
420
+ name: app.slug,
421
+ conclusion,
422
+ url: null
423
+ });
424
+ }
425
+ }
426
+ }
427
+ }
428
+
429
+ // Report pending jobs
430
+ if (pendingJobs.length > 0) {
431
+ cli.error('GitHub CI is still running');
432
+ return false;
433
+ }
434
+
435
+ // Report failed jobs
436
+ if (failedJobs.length > 0) {
437
+ cli.error(`${failedJobs.length} GitHub CI job(s) failed:`);
438
+ for (const job of failedJobs) {
439
+ const urlInfo = job.url ? ` (${job.url})` : '';
440
+ cli.error(` - ${job.name}: ${job.conclusion}${urlInfo}`);
441
+ }
442
+ }
443
+
444
+ // Report cancelled jobs
445
+ if (cancelledJobs.length > 0) {
446
+ cli.error(`${cancelledJobs.length} GitHub CI job(s) cancelled:`);
447
+ for (const job of cancelledJobs) {
448
+ const urlInfo = job.url ? ` (${job.url})` : '';
449
+ cli.error(` - ${job.name}: ${job.conclusion}${urlInfo}`);
379
450
  }
380
451
  }
381
452
 
453
+ if (hasFailures) {
454
+ return false;
455
+ }
456
+
382
457
  // GitHub old commit status API
383
458
  if (commit.status) {
384
459
  const { state } = commit.status;
@@ -388,7 +463,7 @@ export default class PRChecker {
388
463
  }
389
464
 
390
465
  if (!['SUCCESS', 'EXPECTED'].includes(state)) {
391
- cli.error('Last GitHub CI failed');
466
+ cli.error(`GitHub CI failed with status: ${state}`);
392
467
  return false;
393
468
  }
394
469
  }
@@ -56,18 +56,12 @@ export default class ReleasePromotion extends Session {
56
56
  cli.warn('Current HEAD is not the release commit');
57
57
  localCloneIsClean = false;
58
58
  }
59
- try {
60
- await forceRunAsync('git', ['--no-pager', 'diff', '--exit-code'], { ignoreFailure: false });
61
- } catch {
62
- cli.warn('Some local changes have not been committed');
63
- localCloneIsClean = false;
64
- }
65
59
  if (!localCloneIsClean) {
66
- if (await cli.prompt('Should we reset the local HEAD to be the release proposal?')) {
60
+ if (await cli.prompt('Should we checkout the release proposal?')) {
67
61
  cli.startSpinner('Fetching the proposal upstream...');
68
62
  await forceRunAsync('git', ['fetch', proposalUpstreamRemote, releaseCommitSha],
69
63
  { ignoreFailure: false });
70
- await forceRunAsync('git', ['reset', releaseCommitSha, '--hard'], { ignoreFailure: false });
64
+ await forceRunAsync('git', ['checkout', releaseCommitSha], { ignoreFailure: false });
71
65
  cli.stopSpinner('Local HEAD is now in sync with the proposal');
72
66
  } else {
73
67
  cli.error('Local clone is not ready');
@@ -248,7 +242,7 @@ export default class ReleasePromotion extends Session {
248
242
  const checker = new PRChecker(cli, data, { prid, owner, repo }, { maxCommits: 0 });
249
243
  const jenkinsReady = checker.checkJenkinsCI();
250
244
  const githubCIReady = checker.checkGitHubCI();
251
- const isApproved = checker.checkReviewsAndWait(new Date(), false);
245
+ const isApproved = checker.checkReviewsAndWait(new Date(), false, true);
252
246
 
253
247
  return {
254
248
  githubCIReady,
@@ -31,7 +31,15 @@ query Commits($prid: Int!, $owner: String!, $repo: String!, $after: String) {
31
31
  slug
32
32
  }
33
33
  conclusion,
34
- status
34
+ status,
35
+ checkRuns(first: 40) {
36
+ nodes {
37
+ name
38
+ status
39
+ conclusion
40
+ detailsUrl
41
+ }
42
+ }
35
43
  }
36
44
  }
37
45
  status {
@@ -141,46 +141,55 @@ export default class UpdateSecurityRelease extends SecurityRelease {
141
141
  const vulnerabilitiesJSONPath = this.getVulnerabilitiesJSONPath();
142
142
  const content = this.readVulnerabilitiesJSON(vulnerabilitiesJSONPath);
143
143
  const { reports } = content;
144
+ this.validateReportsForCVE(reports);
144
145
  const req = new Request(credentials);
145
146
  const programId = await this.getNodeProgramId(req);
146
- const cves = await this.promptCVECreation(req, reports, programId);
147
- this.assignCVEtoReport(cves, reports);
148
- this.updateVulnerabilitiesJSON(content);
149
- this.updateHackonerReportCve(req, reports);
147
+ await this.promptCVECreation(req, reports, programId, content);
150
148
  }
151
149
 
152
- assignCVEtoReport(cves, reports) {
153
- for (const cve of cves) {
154
- const report = reports.find(report => report.id === cve.reportId);
155
- report.cveIds = [cve.cve_identifier];
156
- report.patchedVersions = cve.patchedVersions;
150
+ validateReportsForCVE(reports) {
151
+ const invalid = [];
152
+ for (const report of reports) {
153
+ if (report.cveIds?.length) continue;
154
+ const missing = [];
155
+ if (!report.summary) missing.push('description');
156
+ if (!report.severity?.weakness_id) missing.push('weakness_id');
157
+ if (!report.severity?.cvss_vector_string) missing.push('cvss_vector_string');
158
+ if (missing.length) {
159
+ invalid.push({ id: report.id, missing });
160
+ }
161
+ }
162
+ if (invalid.length) {
163
+ for (const { id, missing } of invalid) {
164
+ this.cli.error(`Report ${id} is missing: ${missing.join(', ')}`);
165
+ }
166
+ throw new Error('Some reports are missing required fields for CVE request. ' +
167
+ 'Run `git node security --sync` to update them.');
157
168
  }
158
169
  }
159
170
 
160
- async updateHackonerReportCve(req, reports) {
161
- for (const report of reports) {
162
- const { id, cveIds } = report;
163
- this.cli.startSpinner(`Updating report ${id} with CVEs ${cveIds}..`);
164
- const body = {
165
- data: {
166
- type: 'report-cves',
167
- attributes: {
168
- cve_ids: cveIds
169
- }
171
+ async updateHackonerReportCve(req, report) {
172
+ const { id, cveIds } = report;
173
+ this.cli.startSpinner(`Updating report ${id} with CVEs ${cveIds}..`);
174
+ const body = {
175
+ data: {
176
+ type: 'report-cves',
177
+ attributes: {
178
+ cve_ids: cveIds
170
179
  }
171
- };
172
- const response = await req.updateReportCVE(id, body);
173
- if (response.errors) {
174
- this.cli.error(`Error updating report ${id}`);
175
- this.cli.error(JSON.stringify(response.errors, null, 2));
176
180
  }
177
- this.cli.stopSpinner(`Done updating report ${id} with CVEs ${cveIds}..`);
181
+ };
182
+ const response = await req.updateReportCVE(id, body);
183
+ if (response.errors) {
184
+ this.cli.error(`Error updating report ${id}`);
185
+ this.cli.error(JSON.stringify(response.errors, null, 2));
178
186
  }
187
+ this.cli.stopSpinner(`Done updating report ${id} with CVEs ${cveIds}..`);
179
188
  }
180
189
 
181
- async promptCVECreation(req, reports, programId) {
190
+ async promptCVECreation(req, reports, programId, content) {
182
191
  const supportedVersions = (await nv('supported'));
183
- const cves = [];
192
+ const eolVersions = (await nv('eol'));
184
193
  for (const report of reports) {
185
194
  const { id, summary, title, affectedVersions, cveIds, link } = report;
186
195
  // skip if already has a CVE
@@ -222,7 +231,7 @@ Summary: ${summary}\n`,
222
231
  if (!create) continue;
223
232
 
224
233
  const { h1AffectedVersions, patchedVersions } =
225
- await this.calculateVersions(affectedVersions, supportedVersions);
234
+ await this.calculateVersions(affectedVersions, supportedVersions, eolVersions);
226
235
  const body = {
227
236
  data: {
228
237
  type: 'cve-request',
@@ -243,16 +252,18 @@ Summary: ${summary}\n`,
243
252
  }
244
253
  }
245
254
  };
246
- const { data } = await req.requestCVE(programId, body);
247
- if (data.errors) {
255
+ const response = await req.requestCVE(programId, body);
256
+ if (response.errors) {
248
257
  this.cli.error(`Error requesting CVE for report ${id}`);
249
- this.cli.error(JSON.stringify(data.errors, null, 2));
258
+ this.cli.error(JSON.stringify(response.errors, null, 2));
250
259
  continue;
251
260
  }
252
- const { cve_identifier } = data.attributes;
253
- cves.push({ cve_identifier, reportId: id, patchedVersions });
261
+ const { cve_identifier } = response.data.attributes;
262
+ report.cveIds = [cve_identifier];
263
+ report.patchedVersions = patchedVersions;
264
+ this.updateVulnerabilitiesJSON(content);
265
+ await this.updateHackonerReportCve(req, report);
254
266
  }
255
- return cves;
256
267
  }
257
268
 
258
269
  async getNodeProgramId(req) {
@@ -266,7 +277,7 @@ Summary: ${summary}\n`,
266
277
  }
267
278
  }
268
279
 
269
- async calculateVersions(affectedVersions, supportedVersions) {
280
+ async calculateVersions(affectedVersions, supportedVersions, eolVersions) {
270
281
  const h1AffectedVersions = [];
271
282
  const patchedVersions = [];
272
283
  let isPatchRelease = true;
@@ -300,6 +311,22 @@ Summary: ${summary}\n`,
300
311
  affected: true
301
312
  });
302
313
  }
314
+
315
+ // All EOL versions are affected since they no longer receive security patches
316
+ for (const eolVersion of eolVersions) {
317
+ const version = semver.valid(eolVersion.version);
318
+ if (version) {
319
+ h1AffectedVersions.push({
320
+ vendor: 'nodejs',
321
+ product: 'node',
322
+ func: '<=',
323
+ version,
324
+ versionType: 'semver',
325
+ affected: true
326
+ });
327
+ }
328
+ }
329
+
303
330
  return { h1AffectedVersions, patchedVersions };
304
331
  }
305
332
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@node-core/utils",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@node-core/utils",
9
- "version": "6.1.0",
9
+ "version": "6.2.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@inquirer/prompts": "^7.4.1",
@@ -17,7 +17,7 @@
17
17
  "chalk": "^5.4.1",
18
18
  "changelog-maker": "^4.4.1",
19
19
  "cheerio": "^1.0.0",
20
- "clipboardy": "^4.0.0",
20
+ "clipboardy": "^5.0.2",
21
21
  "core-validate-commit": "^4.1.0",
22
22
  "figures": "^6.1.0",
23
23
  "ghauth": "^6.0.12",
@@ -296,9 +296,9 @@
296
296
  }
297
297
  },
298
298
  "node_modules/@eslint/js": {
299
- "version": "9.39.1",
300
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
301
- "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
299
+ "version": "9.39.2",
300
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
301
+ "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
302
302
  "dev": true,
303
303
  "license": "MIT",
304
304
  "engines": {
@@ -1209,6 +1209,12 @@
1209
1209
  "dev": true,
1210
1210
  "license": "MIT"
1211
1211
  },
1212
+ "node_modules/@sec-ant/readable-stream": {
1213
+ "version": "0.4.1",
1214
+ "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
1215
+ "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
1216
+ "license": "MIT"
1217
+ },
1212
1218
  "node_modules/@sindresorhus/is": {
1213
1219
  "version": "4.6.0",
1214
1220
  "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@@ -1221,6 +1227,18 @@
1221
1227
  "url": "https://github.com/sindresorhus/is?sponsor=1"
1222
1228
  }
1223
1229
  },
1230
+ "node_modules/@sindresorhus/merge-streams": {
1231
+ "version": "4.0.0",
1232
+ "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
1233
+ "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
1234
+ "license": "MIT",
1235
+ "engines": {
1236
+ "node": ">=18"
1237
+ },
1238
+ "funding": {
1239
+ "url": "https://github.com/sponsors/sindresorhus"
1240
+ }
1241
+ },
1224
1242
  "node_modules/@sinonjs/commons": {
1225
1243
  "version": "3.0.1",
1226
1244
  "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
@@ -2867,17 +2885,18 @@
2867
2885
  }
2868
2886
  },
2869
2887
  "node_modules/clipboardy": {
2870
- "version": "4.0.0",
2871
- "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz",
2872
- "integrity": "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==",
2888
+ "version": "5.0.2",
2889
+ "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-5.0.2.tgz",
2890
+ "integrity": "sha512-3IG8i8Yfb410yqDlCx9Ve3lYLFN3bD1IkrWcowT1kyTo6y4bwYf2guK9Q8a6zck5vWm7afm6Y61i7BG/Ir3FMA==",
2873
2891
  "license": "MIT",
2874
2892
  "dependencies": {
2875
- "execa": "^8.0.1",
2893
+ "execa": "^9.6.0",
2894
+ "is-wayland": "^0.1.0",
2876
2895
  "is-wsl": "^3.1.0",
2877
2896
  "is64bit": "^2.0.0"
2878
2897
  },
2879
2898
  "engines": {
2880
- "node": ">=18"
2899
+ "node": ">=20"
2881
2900
  },
2882
2901
  "funding": {
2883
2902
  "url": "https://github.com/sponsors/sindresorhus"
@@ -3757,9 +3776,9 @@
3757
3776
  }
3758
3777
  },
3759
3778
  "node_modules/eslint": {
3760
- "version": "9.39.0",
3761
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.0.tgz",
3762
- "integrity": "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg==",
3779
+ "version": "9.39.2",
3780
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
3781
+ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
3763
3782
  "dev": true,
3764
3783
  "license": "MIT",
3765
3784
  "dependencies": {
@@ -3769,7 +3788,7 @@
3769
3788
  "@eslint/config-helpers": "^0.4.2",
3770
3789
  "@eslint/core": "^0.17.0",
3771
3790
  "@eslint/eslintrc": "^3.3.1",
3772
- "@eslint/js": "9.39.0",
3791
+ "@eslint/js": "9.39.2",
3773
3792
  "@eslint/plugin-kit": "^0.4.1",
3774
3793
  "@humanfs/node": "^0.16.6",
3775
3794
  "@humanwhocodes/module-importer": "^1.0.1",
@@ -4222,19 +4241,6 @@
4222
4241
  "url": "https://opencollective.com/eslint"
4223
4242
  }
4224
4243
  },
4225
- "node_modules/eslint/node_modules/@eslint/js": {
4226
- "version": "9.39.0",
4227
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.0.tgz",
4228
- "integrity": "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==",
4229
- "dev": true,
4230
- "license": "MIT",
4231
- "engines": {
4232
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4233
- },
4234
- "funding": {
4235
- "url": "https://eslint.org/donate"
4236
- }
4237
- },
4238
4244
  "node_modules/eslint/node_modules/ansi-styles": {
4239
4245
  "version": "4.3.0",
4240
4246
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -4339,23 +4345,26 @@
4339
4345
  "license": "MIT"
4340
4346
  },
4341
4347
  "node_modules/execa": {
4342
- "version": "8.0.1",
4343
- "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
4344
- "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
4348
+ "version": "9.6.1",
4349
+ "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz",
4350
+ "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==",
4345
4351
  "license": "MIT",
4346
4352
  "dependencies": {
4347
- "cross-spawn": "^7.0.3",
4348
- "get-stream": "^8.0.1",
4349
- "human-signals": "^5.0.0",
4350
- "is-stream": "^3.0.0",
4351
- "merge-stream": "^2.0.0",
4352
- "npm-run-path": "^5.1.0",
4353
- "onetime": "^6.0.0",
4353
+ "@sindresorhus/merge-streams": "^4.0.0",
4354
+ "cross-spawn": "^7.0.6",
4355
+ "figures": "^6.1.0",
4356
+ "get-stream": "^9.0.0",
4357
+ "human-signals": "^8.0.1",
4358
+ "is-plain-obj": "^4.1.0",
4359
+ "is-stream": "^4.0.1",
4360
+ "npm-run-path": "^6.0.0",
4361
+ "pretty-ms": "^9.2.0",
4354
4362
  "signal-exit": "^4.1.0",
4355
- "strip-final-newline": "^3.0.0"
4363
+ "strip-final-newline": "^4.0.0",
4364
+ "yoctocolors": "^2.1.1"
4356
4365
  },
4357
4366
  "engines": {
4358
- "node": ">=16.17"
4367
+ "node": "^18.19.0 || >=20.5.0"
4359
4368
  },
4360
4369
  "funding": {
4361
4370
  "url": "https://github.com/sindresorhus/execa?sponsor=1"
@@ -4640,12 +4649,16 @@
4640
4649
  }
4641
4650
  },
4642
4651
  "node_modules/get-stream": {
4643
- "version": "8.0.1",
4644
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
4645
- "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
4652
+ "version": "9.0.1",
4653
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
4654
+ "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
4646
4655
  "license": "MIT",
4656
+ "dependencies": {
4657
+ "@sec-ant/readable-stream": "^0.4.1",
4658
+ "is-stream": "^4.0.1"
4659
+ },
4647
4660
  "engines": {
4648
- "node": ">=16"
4661
+ "node": ">=18"
4649
4662
  },
4650
4663
  "funding": {
4651
4664
  "url": "https://github.com/sponsors/sindresorhus"
@@ -4683,9 +4696,9 @@
4683
4696
  }
4684
4697
  },
4685
4698
  "node_modules/ghauth": {
4686
- "version": "6.0.13",
4687
- "resolved": "https://registry.npmjs.org/ghauth/-/ghauth-6.0.13.tgz",
4688
- "integrity": "sha512-wdeDPCl3RBSoYEhZ4J/PXK7/b1xYQj1zKgWx9QyUEo0ZGvwFiwe8HWMkpbtuDgo6kwaRUYw7izV7LtO233J5iw==",
4699
+ "version": "6.0.19",
4700
+ "resolved": "https://registry.npmjs.org/ghauth/-/ghauth-6.0.19.tgz",
4701
+ "integrity": "sha512-eiZtW8EyJjk++Gs8vdY1/gJccbaPl3cH40z9VikfvBou5dkI4L/m9bbauLiGnQ6SdYhu0wT4DlDuoRpUMwbyIg==",
4689
4702
  "license": "MIT",
4690
4703
  "dependencies": {
4691
4704
  "application-config": "^2.0.0",
@@ -5397,12 +5410,12 @@
5397
5410
  }
5398
5411
  },
5399
5412
  "node_modules/human-signals": {
5400
- "version": "5.0.0",
5401
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
5402
- "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
5413
+ "version": "8.0.1",
5414
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz",
5415
+ "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==",
5403
5416
  "license": "Apache-2.0",
5404
5417
  "engines": {
5405
- "node": ">=16.17.0"
5418
+ "node": ">=18.18.0"
5406
5419
  }
5407
5420
  },
5408
5421
  "node_modules/hyperquest": {
@@ -5997,12 +6010,12 @@
5997
6010
  }
5998
6011
  },
5999
6012
  "node_modules/is-stream": {
6000
- "version": "3.0.0",
6001
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
6002
- "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
6013
+ "version": "4.0.1",
6014
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
6015
+ "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
6003
6016
  "license": "MIT",
6004
6017
  "engines": {
6005
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
6018
+ "node": ">=18"
6006
6019
  },
6007
6020
  "funding": {
6008
6021
  "url": "https://github.com/sponsors/sindresorhus"
@@ -6083,6 +6096,18 @@
6083
6096
  "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==",
6084
6097
  "license": "MIT"
6085
6098
  },
6099
+ "node_modules/is-wayland": {
6100
+ "version": "0.1.0",
6101
+ "resolved": "https://registry.npmjs.org/is-wayland/-/is-wayland-0.1.0.tgz",
6102
+ "integrity": "sha512-QkbMsWkIfkrzOPxenwye0h56iAXirZYHG9eHVPb22fO9y+wPbaX/CHacOWBa/I++4ohTcByimhM1/nyCsH8KNA==",
6103
+ "license": "MIT",
6104
+ "engines": {
6105
+ "node": ">=20"
6106
+ },
6107
+ "funding": {
6108
+ "url": "https://github.com/sponsors/sindresorhus"
6109
+ }
6110
+ },
6086
6111
  "node_modules/is-weakmap": {
6087
6112
  "version": "2.0.2",
6088
6113
  "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -6957,12 +6982,6 @@
6957
6982
  "url": "https://opencollective.com/unified"
6958
6983
  }
6959
6984
  },
6960
- "node_modules/merge-stream": {
6961
- "version": "2.0.0",
6962
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
6963
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
6964
- "license": "MIT"
6965
- },
6966
6985
  "node_modules/merge2": {
6967
6986
  "version": "1.4.1",
6968
6987
  "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -7550,18 +7569,6 @@
7550
7569
  "node": ">=8.6"
7551
7570
  }
7552
7571
  },
7553
- "node_modules/mimic-fn": {
7554
- "version": "4.0.0",
7555
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
7556
- "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
7557
- "license": "MIT",
7558
- "engines": {
7559
- "node": ">=12"
7560
- },
7561
- "funding": {
7562
- "url": "https://github.com/sponsors/sindresorhus"
7563
- }
7564
- },
7565
7572
  "node_modules/mimic-function": {
7566
7573
  "version": "5.0.1",
7567
7574
  "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
@@ -7743,15 +7750,16 @@
7743
7750
  }
7744
7751
  },
7745
7752
  "node_modules/npm-run-path": {
7746
- "version": "5.3.0",
7747
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
7748
- "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
7753
+ "version": "6.0.0",
7754
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
7755
+ "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
7749
7756
  "license": "MIT",
7750
7757
  "dependencies": {
7751
- "path-key": "^4.0.0"
7758
+ "path-key": "^4.0.0",
7759
+ "unicorn-magic": "^0.3.0"
7752
7760
  },
7753
7761
  "engines": {
7754
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
7762
+ "node": ">=18"
7755
7763
  },
7756
7764
  "funding": {
7757
7765
  "url": "https://github.com/sponsors/sindresorhus"
@@ -7922,21 +7930,6 @@
7922
7930
  "wrappy": "1"
7923
7931
  }
7924
7932
  },
7925
- "node_modules/onetime": {
7926
- "version": "6.0.0",
7927
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
7928
- "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
7929
- "license": "MIT",
7930
- "dependencies": {
7931
- "mimic-fn": "^4.0.0"
7932
- },
7933
- "engines": {
7934
- "node": ">=12"
7935
- },
7936
- "funding": {
7937
- "url": "https://github.com/sponsors/sindresorhus"
7938
- }
7939
- },
7940
7933
  "node_modules/optionator": {
7941
7934
  "version": "0.9.4",
7942
7935
  "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -8139,6 +8132,18 @@
8139
8132
  "url": "https://github.com/sponsors/sindresorhus"
8140
8133
  }
8141
8134
  },
8135
+ "node_modules/parse-ms": {
8136
+ "version": "4.0.0",
8137
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
8138
+ "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
8139
+ "license": "MIT",
8140
+ "engines": {
8141
+ "node": ">=18"
8142
+ },
8143
+ "funding": {
8144
+ "url": "https://github.com/sponsors/sindresorhus"
8145
+ }
8146
+ },
8142
8147
  "node_modules/parse5": {
8143
8148
  "version": "7.3.0",
8144
8149
  "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
@@ -8337,6 +8342,21 @@
8337
8342
  "node": ">= 0.8.0"
8338
8343
  }
8339
8344
  },
8345
+ "node_modules/pretty-ms": {
8346
+ "version": "9.3.0",
8347
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
8348
+ "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
8349
+ "license": "MIT",
8350
+ "dependencies": {
8351
+ "parse-ms": "^4.0.0"
8352
+ },
8353
+ "engines": {
8354
+ "node": ">=18"
8355
+ },
8356
+ "funding": {
8357
+ "url": "https://github.com/sponsors/sindresorhus"
8358
+ }
8359
+ },
8340
8360
  "node_modules/prop-types": {
8341
8361
  "version": "15.8.1",
8342
8362
  "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -9898,9 +9918,9 @@
9898
9918
  "license": "MIT"
9899
9919
  },
9900
9920
  "node_modules/semver": {
9901
- "version": "7.7.2",
9902
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
9903
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
9921
+ "version": "7.7.3",
9922
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
9923
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
9904
9924
  "license": "ISC",
9905
9925
  "bin": {
9906
9926
  "semver": "bin/semver.js"
@@ -10483,12 +10503,12 @@
10483
10503
  }
10484
10504
  },
10485
10505
  "node_modules/strip-final-newline": {
10486
- "version": "3.0.0",
10487
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
10488
- "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
10506
+ "version": "4.0.0",
10507
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
10508
+ "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
10489
10509
  "license": "MIT",
10490
10510
  "engines": {
10491
- "node": ">=12"
10511
+ "node": ">=18"
10492
10512
  },
10493
10513
  "funding": {
10494
10514
  "url": "https://github.com/sponsors/sindresorhus"
@@ -10944,6 +10964,18 @@
10944
10964
  "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
10945
10965
  "license": "MIT"
10946
10966
  },
10967
+ "node_modules/unicorn-magic": {
10968
+ "version": "0.3.0",
10969
+ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
10970
+ "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
10971
+ "license": "MIT",
10972
+ "engines": {
10973
+ "node": ">=18"
10974
+ },
10975
+ "funding": {
10976
+ "url": "https://github.com/sponsors/sindresorhus"
10977
+ }
10978
+ },
10947
10979
  "node_modules/unified": {
10948
10980
  "version": "11.0.5",
10949
10981
  "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-core/utils",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "Utilities for Node.js core collaborators",
5
5
  "type": "module",
6
6
  "engines": {
@@ -43,7 +43,7 @@
43
43
  "chalk": "^5.4.1",
44
44
  "changelog-maker": "^4.4.1",
45
45
  "cheerio": "^1.0.0",
46
- "clipboardy": "^4.0.0",
46
+ "clipboardy": "^5.0.2",
47
47
  "core-validate-commit": "^4.1.0",
48
48
  "figures": "^6.1.0",
49
49
  "ghauth": "^6.0.12",