@verdaccio/e2e-cli 2.10.4 → 3.1.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.
Files changed (122) hide show
  1. package/build/adapters/index.d.ts +0 -1
  2. package/build/cjs/adapters/index.cjs +0 -2
  3. package/build/cjs/adapters/npm.cjs +10 -0
  4. package/build/cjs/adapters/npm.cjs.map +1 -1
  5. package/build/cjs/adapters/pnpm.cjs +11 -1
  6. package/build/cjs/adapters/pnpm.cjs.map +1 -1
  7. package/build/cjs/index.cjs +28 -8
  8. package/build/cjs/index.cjs.map +1 -1
  9. package/build/cjs/runner.cjs +1 -1
  10. package/build/cjs/runner.cjs.map +1 -1
  11. package/build/cjs/scenarios/index.cjs +16 -1
  12. package/build/cjs/scenarios/index.cjs.map +1 -1
  13. package/build/cjs/scenarios/install-multiple-deps.cjs +25 -23
  14. package/build/cjs/scenarios/install-multiple-deps.cjs.map +1 -1
  15. package/build/cjs/scenarios/metadata.cjs +121 -0
  16. package/build/cjs/scenarios/metadata.cjs.map +1 -0
  17. package/build/cjs/scenarios/minimum-release-age.cjs +6 -8
  18. package/build/cjs/scenarios/minimum-release-age.cjs.map +1 -1
  19. package/build/cjs/scenarios/search.cjs +136 -0
  20. package/build/cjs/scenarios/search.cjs.map +1 -0
  21. package/build/cjs/scenarios/tarballs.cjs +147 -0
  22. package/build/cjs/scenarios/tarballs.cjs.map +1 -0
  23. package/build/cjs/scenarios/uplink-failure.cjs +141 -0
  24. package/build/cjs/scenarios/uplink-failure.cjs.map +1 -0
  25. package/build/cjs/tests/audit.cjs +15 -2
  26. package/build/cjs/tests/audit.cjs.map +1 -1
  27. package/build/cjs/tests/ci.cjs +4 -6
  28. package/build/cjs/tests/ci.cjs.map +1 -1
  29. package/build/cjs/tests/index.cjs +7 -3
  30. package/build/cjs/tests/index.cjs.map +1 -1
  31. package/build/cjs/tests/info.cjs +10 -21
  32. package/build/cjs/tests/info.cjs.map +1 -1
  33. package/build/cjs/tests/install.cjs +4 -1
  34. package/build/cjs/tests/install.cjs.map +1 -1
  35. package/build/cjs/tests/ping.cjs +3 -7
  36. package/build/cjs/tests/ping.cjs.map +1 -1
  37. package/build/cjs/tests/publish.cjs +0 -1
  38. package/build/cjs/tests/publish.cjs.map +1 -1
  39. package/build/cjs/tests/search.cjs +9 -5
  40. package/build/cjs/tests/search.cjs.map +1 -1
  41. package/build/cjs/utils/e2e-config.cjs +59 -0
  42. package/build/cjs/utils/e2e-config.cjs.map +1 -0
  43. package/build/cjs/utils/http-client.cjs +111 -0
  44. package/build/cjs/utils/http-client.cjs.map +1 -0
  45. package/build/cjs/utils/mock-uplink.cjs +196 -0
  46. package/build/cjs/utils/mock-uplink.cjs.map +1 -0
  47. package/build/cjs/utils/process.cjs +11 -0
  48. package/build/cjs/utils/process.cjs.map +1 -1
  49. package/build/cjs/utils/project.cjs +1 -1
  50. package/build/cjs/utils/project.cjs.map +1 -1
  51. package/build/cjs/utils/publish.cjs +117 -0
  52. package/build/cjs/utils/publish.cjs.map +1 -0
  53. package/build/esm/adapters/index.js +1 -2
  54. package/build/esm/adapters/npm.js +10 -0
  55. package/build/esm/adapters/npm.js.map +1 -1
  56. package/build/esm/adapters/pnpm.js +11 -1
  57. package/build/esm/adapters/pnpm.js.map +1 -1
  58. package/build/esm/index.js +29 -8
  59. package/build/esm/index.js.map +1 -1
  60. package/build/esm/runner.js +1 -1
  61. package/build/esm/runner.js.map +1 -1
  62. package/build/esm/scenarios/index.js +13 -2
  63. package/build/esm/scenarios/index.js.map +1 -1
  64. package/build/esm/scenarios/install-multiple-deps.js +25 -22
  65. package/build/esm/scenarios/install-multiple-deps.js.map +1 -1
  66. package/build/esm/scenarios/metadata.js +119 -0
  67. package/build/esm/scenarios/metadata.js.map +1 -0
  68. package/build/esm/scenarios/minimum-release-age.js +6 -7
  69. package/build/esm/scenarios/minimum-release-age.js.map +1 -1
  70. package/build/esm/scenarios/search.js +134 -0
  71. package/build/esm/scenarios/search.js.map +1 -0
  72. package/build/esm/scenarios/tarballs.js +145 -0
  73. package/build/esm/scenarios/tarballs.js.map +1 -0
  74. package/build/esm/scenarios/uplink-failure.js +139 -0
  75. package/build/esm/scenarios/uplink-failure.js.map +1 -0
  76. package/build/esm/tests/audit.js +15 -2
  77. package/build/esm/tests/audit.js.map +1 -1
  78. package/build/esm/tests/ci.js +4 -6
  79. package/build/esm/tests/ci.js.map +1 -1
  80. package/build/esm/tests/index.js +4 -0
  81. package/build/esm/tests/index.js.map +1 -1
  82. package/build/esm/tests/info.js +10 -21
  83. package/build/esm/tests/info.js.map +1 -1
  84. package/build/esm/tests/install.js +4 -1
  85. package/build/esm/tests/install.js.map +1 -1
  86. package/build/esm/tests/ping.js +3 -7
  87. package/build/esm/tests/ping.js.map +1 -1
  88. package/build/esm/tests/publish.js +0 -1
  89. package/build/esm/tests/publish.js.map +1 -1
  90. package/build/esm/tests/search.js +9 -5
  91. package/build/esm/tests/search.js.map +1 -1
  92. package/build/esm/utils/e2e-config.js +58 -0
  93. package/build/esm/utils/e2e-config.js.map +1 -0
  94. package/build/esm/utils/http-client.js +105 -0
  95. package/build/esm/utils/http-client.js.map +1 -0
  96. package/build/esm/utils/mock-uplink.js +194 -0
  97. package/build/esm/utils/mock-uplink.js.map +1 -0
  98. package/build/esm/utils/process.js +11 -1
  99. package/build/esm/utils/process.js.map +1 -1
  100. package/build/esm/utils/project.js +1 -1
  101. package/build/esm/utils/project.js.map +1 -1
  102. package/build/esm/utils/publish.js +113 -0
  103. package/build/esm/utils/publish.js.map +1 -0
  104. package/build/index.d.ts +1 -1
  105. package/build/scenarios/index.d.ts +5 -1
  106. package/build/scenarios/metadata.d.ts +2 -0
  107. package/build/scenarios/search.d.ts +2 -0
  108. package/build/scenarios/tarballs.d.ts +2 -0
  109. package/build/scenarios/uplink-failure.d.ts +2 -0
  110. package/build/tests/index.d.ts +2 -2
  111. package/build/types.d.ts +12 -2
  112. package/build/utils/e2e-config.d.ts +21 -0
  113. package/build/utils/http-client.d.ts +49 -0
  114. package/build/utils/mock-uplink.d.ts +47 -0
  115. package/build/utils/process.d.ts +7 -0
  116. package/build/utils/publish.d.ts +17 -0
  117. package/package.json +1 -1
  118. package/build/adapters/yarn-classic.d.ts +0 -2
  119. package/build/cjs/adapters/yarn-classic.cjs +0 -98
  120. package/build/cjs/adapters/yarn-classic.cjs.map +0 -1
  121. package/build/esm/adapters/yarn-classic.js +0 -96
  122. package/build/esm/adapters/yarn-classic.js.map +0 -1
@@ -2,5 +2,4 @@ export { createBunAdapter } from './bun';
2
2
  export { createDenoAdapter } from './deno';
3
3
  export { createNpmAdapter } from './npm';
4
4
  export { createPnpmAdapter } from './pnpm';
5
- export { createYarnClassicAdapter } from './yarn-classic';
6
5
  export { createYarnModernAdapter } from './yarn-modern';
@@ -2,11 +2,9 @@ const require_bun = require("./bun.cjs");
2
2
  const require_deno = require("./deno.cjs");
3
3
  const require_npm = require("./npm.cjs");
4
4
  const require_pnpm = require("./pnpm.cjs");
5
- const require_yarn_classic = require("./yarn-classic.cjs");
6
5
  const require_yarn_modern = require("./yarn-modern.cjs");
7
6
  exports.createBunAdapter = require_bun.createBunAdapter;
8
7
  exports.createDenoAdapter = require_deno.createDenoAdapter;
9
8
  exports.createNpmAdapter = require_npm.createNpmAdapter;
10
9
  exports.createPnpmAdapter = require_pnpm.createPnpmAdapter;
11
- exports.createYarnClassicAdapter = require_yarn_classic.createYarnClassicAdapter;
12
10
  exports.createYarnModernAdapter = require_yarn_modern.createYarnModernAdapter;
@@ -17,6 +17,11 @@ var NPM_SUPPORTED_COMMANDS = /* @__PURE__ */ new Set([
17
17
  "ping",
18
18
  "search"
19
19
  ]);
20
+ var NPM_SUPPORTED_MAJORS = [
21
+ 10,
22
+ 11,
23
+ 12
24
+ ];
20
25
  function detectVersion(bin) {
21
26
  try {
22
27
  return (0, child_process.execSync)(`${bin} --version`, {
@@ -27,6 +32,10 @@ function detectVersion(bin) {
27
32
  return "unknown";
28
33
  }
29
34
  }
35
+ function assertSupportedVersion(resolved) {
36
+ const major = parseInt(resolved.split(".")[0], 10);
37
+ if (!Number.isNaN(major) && !NPM_SUPPORTED_MAJORS.includes(major)) throw new Error(`npm@${resolved} is not supported. Supported majors: ${NPM_SUPPORTED_MAJORS.join(", ")}`);
38
+ }
30
39
  function installNpm(version) {
31
40
  const pkg = `npm@${version}`;
32
41
  debug$1("installing %s into temp dir", pkg);
@@ -49,6 +58,7 @@ function resolveNpmBin(binPath, version) {
49
58
  function createNpmAdapter(binPath, version) {
50
59
  const bin = resolveNpmBin(binPath, version);
51
60
  const resolved = detectVersion(bin);
61
+ assertSupportedVersion(resolved);
52
62
  debug$1("creating npm adapter with bin: %s (%s)", bin, resolved);
53
63
  return {
54
64
  name: `npm@${resolved}`,
@@ -1 +1 @@
1
- {"version":3,"file":"npm.cjs","names":[],"sources":["../../../src/adapters/npm.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { prepareGenericEmptyProject } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:npm');\n\nconst NPM_SUPPORTED_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n 'dist-tag',\n 'ping',\n 'search',\n]);\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, { encoding: 'utf8', timeout: 5000 }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction installNpm(version: string): string {\n const pkg = `npm@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/.bin/npm`;\n const installed = detectVersion(bin);\n debug('installed npm %s at %s', installed, bin);\n console.log(` Auto-installed npm ${installed}`);\n return bin;\n}\n\nfunction resolveNpmBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n if (version) return installNpm(version);\n return 'npm';\n}\n\nexport function createNpmAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolveNpmBin(binPath, version);\n const resolved = detectVersion(bin);\n debug('creating npm adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `npm@${resolved}`,\n type: 'npm',\n bin,\n supports: NPM_SUPPORTED_COMMANDS,\n\n registryArg(url: string): string[] {\n return ['--registry', url];\n },\n\n prefixArg(folder: string): string[] {\n return ['--prefix', folder];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n return exec(options, bin, args);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n return prepareGenericEmptyProject(\n packageName,\n version,\n port,\n token,\n registryUrl,\n dependencies,\n devDependencies\n );\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;AAOA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,uBAAuB;AAEhD,IAAM,yCAAyB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,cAAc,KAAqB;CAC1C,IAAI;EACF,QAAA,GAAO,cAAA,SAAA,CAAS,GAAG,IAAI,aAAa;GAAE,UAAU;GAAQ,SAAS;EAAK,CAAC,CAAC,CAAC,KAAK;CAChF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,WAAW,SAAyB;CAC3C,MAAM,MAAM,OAAO;CACnB,QAAM,+BAA+B,GAAG;CACxC,MAAM,UAAA,GAAS,cAAA,SAAA,CAAS,aAAa,EAAE,UAAU,OAAO,CAAC,CAAC,CAAC,KAAK;CAChE,CAAA,GAAA,cAAA,SAAA,CAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;CACX,CAAC;CACD,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,GAAG;CACnC,QAAM,0BAA0B,WAAW,GAAG;CAC9C,QAAQ,IAAI,wBAAwB,WAAW;CAC/C,OAAO;AACT;AAEA,SAAS,cAAc,SAAkB,SAA0B;CACjE,IAAI,SAAS,OAAO;CACpB,IAAI,SAAS,OAAO,WAAW,OAAO;CACtC,OAAO;AACT;AAEA,SAAgB,iBAAiB,SAAkB,SAAyC;CAC1F,MAAM,MAAM,cAAc,SAAS,OAAO;CAC1C,MAAM,WAAW,cAAc,GAAG;CAClC,QAAM,0CAA0C,KAAK,QAAQ;CAyC7D,OAAO;EAtCL,MAAM,OAAO;EACb,MAAM;EACN;EACA,UAAU;EAEV,YAAY,KAAuB;GACjC,OAAO,CAAC,cAAc,GAAG;EAC3B;EAEA,UAAU,QAA0B;GAClC,OAAO,CAAC,YAAY,MAAM;EAC5B;EAEA,KAAK,SAAuB,GAAG,MAAqC;GAClE,OAAO,gBAAA,KAAK,SAAS,KAAK,IAAI;EAChC;EAEA,MAAM,eACJ,aACA,SACA,aACA,MACA,OACA,eAAuC,CAAC,GACxC,kBAA0C,CAAC,GACV;GACjC,OAAO,gBAAA,2BACL,aACA,SACA,MACA,OACA,aACA,cACA,eACF;EACF;CAGK;AACT"}
1
+ {"version":3,"file":"npm.cjs","names":[],"sources":["../../../src/adapters/npm.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { prepareGenericEmptyProject } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:npm');\n\nconst NPM_SUPPORTED_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n 'dist-tag',\n 'ping',\n 'search',\n]);\n\n// Only currently maintained npm majors are supported by the suite.\nconst NPM_SUPPORTED_MAJORS = [10, 11, 12];\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, { encoding: 'utf8', timeout: 5000 }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction assertSupportedVersion(resolved: string): void {\n const major = parseInt(resolved.split('.')[0], 10);\n if (!Number.isNaN(major) && !NPM_SUPPORTED_MAJORS.includes(major)) {\n throw new Error(\n `npm@${resolved} is not supported. Supported majors: ${NPM_SUPPORTED_MAJORS.join(', ')}`\n );\n }\n}\n\nfunction installNpm(version: string): string {\n const pkg = `npm@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/.bin/npm`;\n const installed = detectVersion(bin);\n debug('installed npm %s at %s', installed, bin);\n console.log(` Auto-installed npm ${installed}`);\n return bin;\n}\n\nfunction resolveNpmBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n if (version) return installNpm(version);\n return 'npm';\n}\n\nexport function createNpmAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolveNpmBin(binPath, version);\n const resolved = detectVersion(bin);\n assertSupportedVersion(resolved);\n debug('creating npm adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `npm@${resolved}`,\n type: 'npm',\n bin,\n supports: NPM_SUPPORTED_COMMANDS,\n\n registryArg(url: string): string[] {\n return ['--registry', url];\n },\n\n prefixArg(folder: string): string[] {\n return ['--prefix', folder];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n return exec(options, bin, args);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n return prepareGenericEmptyProject(\n packageName,\n version,\n port,\n token,\n registryUrl,\n dependencies,\n devDependencies\n );\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;AAOA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,uBAAuB;AAEhD,IAAM,yCAAyB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAGD,IAAM,uBAAuB;CAAC;CAAI;CAAI;AAAE;AAExC,SAAS,cAAc,KAAqB;CAC1C,IAAI;EACF,QAAA,GAAO,cAAA,SAAA,CAAS,GAAG,IAAI,aAAa;GAAE,UAAU;GAAQ,SAAS;EAAK,CAAC,CAAC,CAAC,KAAK;CAChF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,uBAAuB,UAAwB;CACtD,MAAM,QAAQ,SAAS,SAAS,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE;CACjD,IAAI,CAAC,OAAO,MAAM,KAAK,KAAK,CAAC,qBAAqB,SAAS,KAAK,GAC9D,MAAM,IAAI,MACR,OAAO,SAAS,uCAAuC,qBAAqB,KAAK,IAAI,GACvF;AAEJ;AAEA,SAAS,WAAW,SAAyB;CAC3C,MAAM,MAAM,OAAO;CACnB,QAAM,+BAA+B,GAAG;CACxC,MAAM,UAAA,GAAS,cAAA,SAAA,CAAS,aAAa,EAAE,UAAU,OAAO,CAAC,CAAC,CAAC,KAAK;CAChE,CAAA,GAAA,cAAA,SAAA,CAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;CACX,CAAC;CACD,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,GAAG;CACnC,QAAM,0BAA0B,WAAW,GAAG;CAC9C,QAAQ,IAAI,wBAAwB,WAAW;CAC/C,OAAO;AACT;AAEA,SAAS,cAAc,SAAkB,SAA0B;CACjE,IAAI,SAAS,OAAO;CACpB,IAAI,SAAS,OAAO,WAAW,OAAO;CACtC,OAAO;AACT;AAEA,SAAgB,iBAAiB,SAAkB,SAAyC;CAC1F,MAAM,MAAM,cAAc,SAAS,OAAO;CAC1C,MAAM,WAAW,cAAc,GAAG;CAClC,uBAAuB,QAAQ;CAC/B,QAAM,0CAA0C,KAAK,QAAQ;CAyC7D,OAAO;EAtCL,MAAM,OAAO;EACb,MAAM;EACN;EACA,UAAU;EAEV,YAAY,KAAuB;GACjC,OAAO,CAAC,cAAc,GAAG;EAC3B;EAEA,UAAU,QAA0B;GAClC,OAAO,CAAC,YAAY,MAAM;EAC5B;EAEA,KAAK,SAAuB,GAAG,MAAqC;GAClE,OAAO,gBAAA,KAAK,SAAS,KAAK,IAAI;EAChC;EAEA,MAAM,eACJ,aACA,SACA,aACA,MACA,OACA,eAAuC,CAAC,GACxC,kBAA0C,CAAC,GACV;GACjC,OAAO,gBAAA,2BACL,aACA,SACA,MACA,OACA,aACA,cACA,eACF;EACF;CAGK;AACT"}
@@ -4,6 +4,8 @@ const require_project = require("../utils/project.cjs");
4
4
  let debug = require("debug");
5
5
  debug = require_runtime.__toESM(debug, 1);
6
6
  let child_process = require("child_process");
7
+ let path = require("path");
8
+ let fs_promises = require("fs/promises");
7
9
  //#region src/adapters/pnpm.ts
8
10
  var debug$1 = (0, debug.default)("verdaccio:e2e-cli:pnpm");
9
11
  var PNPM_V10_COMMANDS = /* @__PURE__ */ new Set([
@@ -33,6 +35,7 @@ function getSupportedCommands(version) {
33
35
  }
34
36
  return PNPM_V10_COMMANDS;
35
37
  }
38
+ var PNPM_MIN_SUPPORTED_MAJOR = 10;
36
39
  function detectVersion(bin) {
37
40
  try {
38
41
  return (0, child_process.execSync)(`${bin} --version`, {
@@ -43,6 +46,10 @@ function detectVersion(bin) {
43
46
  return "unknown";
44
47
  }
45
48
  }
49
+ function assertSupportedVersion(resolved) {
50
+ const major = parseInt(resolved.split(".")[0], 10);
51
+ if (!Number.isNaN(major) && major < PNPM_MIN_SUPPORTED_MAJOR) throw new Error(`pnpm@${resolved} is not supported. Minimum supported major: ${PNPM_MIN_SUPPORTED_MAJOR}`);
52
+ }
46
53
  function installPnpm(version) {
47
54
  const pkg = `pnpm@${version}`;
48
55
  debug$1("installing %s into temp dir", pkg);
@@ -65,6 +72,7 @@ function resolvePnpmBin(binPath, version) {
65
72
  function createPnpmAdapter(binPath, version) {
66
73
  const bin = resolvePnpmBin(binPath, version);
67
74
  const resolved = detectVersion(bin);
75
+ assertSupportedVersion(resolved);
68
76
  debug$1("creating pnpm adapter with bin: %s (%s)", bin, resolved);
69
77
  return {
70
78
  name: `pnpm@${resolved}`,
@@ -94,7 +102,9 @@ function createPnpmAdapter(binPath, version) {
94
102
  return require_process.exec(options, bin, args);
95
103
  },
96
104
  async prepareProject(packageName, version, registryUrl, port, token, dependencies = {}, devDependencies = {}) {
97
- return require_project.prepareGenericEmptyProject(packageName, version, port, token, registryUrl, dependencies, devDependencies);
105
+ const project = await require_project.prepareGenericEmptyProject(packageName, version, port, token, registryUrl, dependencies, devDependencies);
106
+ await (0, fs_promises.writeFile)((0, path.join)(project.tempFolder, "pnpm-workspace.yaml"), "minimumReleaseAge: 0\n");
107
+ return project;
98
108
  }
99
109
  };
100
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pnpm.cjs","names":[],"sources":["../../../src/adapters/pnpm.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { prepareGenericEmptyProject } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:pnpm');\n\nconst PNPM_V10_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n 'dist-tag',\n 'ping',\n 'search',\n]);\n\n// pnpm v11 removed ping and search\n// dist-tag output format changed (no --json), needs adapted assertions\nconst PNPM_V11_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n]);\n\nfunction getSupportedCommands(version: string): Set<string> {\n const major = parseInt(version.split('.')[0], 10);\n if (major >= 11) {\n debug('pnpm v%d detected, using v11 command set', major);\n return PNPM_V11_COMMANDS;\n }\n return PNPM_V10_COMMANDS;\n}\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, { encoding: 'utf8', timeout: 5000 }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction installPnpm(version: string): string {\n const pkg = `pnpm@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/.bin/pnpm`;\n const installed = detectVersion(bin);\n debug('installed pnpm %s at %s', installed, bin);\n console.log(` Auto-installed pnpm ${installed}`);\n return bin;\n}\n\nfunction resolvePnpmBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n if (version) return installPnpm(version);\n return 'pnpm';\n}\n\nexport function createPnpmAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolvePnpmBin(binPath, version);\n const resolved = detectVersion(bin);\n debug('creating pnpm adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `pnpm@${resolved}`,\n type: 'pnpm',\n bin,\n supports: getSupportedCommands(resolved),\n\n registryArg(url: string): string[] {\n return ['--registry', url];\n },\n\n prefixArg(folder: string): string[] {\n return ['--prefix', folder];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n const major = parseInt(resolved.split('.')[0], 10);\n if (major >= 11) {\n // pnpm v11: native deprecate/unpublish don't support --json\n const cmd = args[0];\n if (cmd === 'deprecate' || cmd === 'unpublish' || cmd === 'publish' || cmd === 'dist-tag') {\n args = args.filter((a) => a !== '--json' && !a.startsWith('--loglevel'));\n }\n // pnpm v11: un-deprecate uses `undeprecate` command instead of `deprecate pkg \"\"`\n if (cmd === 'deprecate') {\n // Check if message arg is empty string (un-deprecate)\n // args: ['deprecate', 'pkg@version', '', ...flags]\n const msgIdx = 2; // message is the third arg\n if (args.length > msgIdx && args[msgIdx] === '') {\n args = ['undeprecate', args[1], ...args.slice(3)];\n }\n }\n // pnpm v11: native version command doesn't accept --registry, --loglevel, or --no--git-tag-version\n if (cmd === 'version') {\n args = args.filter(\n (a) =>\n !a.startsWith('--registry') &&\n !a.startsWith('--loglevel') &&\n !a.startsWith('--no--git-tag-version')\n );\n }\n }\n return exec(options, bin, args);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n return prepareGenericEmptyProject(\n packageName,\n version,\n port,\n token,\n registryUrl,\n dependencies,\n devDependencies\n );\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;AAOA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,wBAAwB;AAEjD,IAAM,oCAAoB,IAAI,IAAI;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAID,IAAM,oCAAoB,IAAI,IAAI;CAChC;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,qBAAqB,SAA8B;CAC1D,MAAM,QAAQ,SAAS,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE;CAChD,IAAI,SAAS,IAAI;EACf,QAAM,4CAA4C,KAAK;EACvD,OAAO;CACT;CACA,OAAO;AACT;AAEA,SAAS,cAAc,KAAqB;CAC1C,IAAI;EACF,QAAA,GAAO,cAAA,SAAA,CAAS,GAAG,IAAI,aAAa;GAAE,UAAU;GAAQ,SAAS;EAAK,CAAC,CAAC,CAAC,KAAK;CAChF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,YAAY,SAAyB;CAC5C,MAAM,MAAM,QAAQ;CACpB,QAAM,+BAA+B,GAAG;CACxC,MAAM,UAAA,GAAS,cAAA,SAAA,CAAS,aAAa,EAAE,UAAU,OAAO,CAAC,CAAC,CAAC,KAAK;CAChE,CAAA,GAAA,cAAA,SAAA,CAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;CACX,CAAC;CACD,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,GAAG;CACnC,QAAM,2BAA2B,WAAW,GAAG;CAC/C,QAAQ,IAAI,yBAAyB,WAAW;CAChD,OAAO;AACT;AAEA,SAAS,eAAe,SAAkB,SAA0B;CAClE,IAAI,SAAS,OAAO;CACpB,IAAI,SAAS,OAAO,YAAY,OAAO;CACvC,OAAO;AACT;AAEA,SAAgB,kBAAkB,SAAkB,SAAyC;CAC3F,MAAM,MAAM,eAAe,SAAS,OAAO;CAC3C,MAAM,WAAW,cAAc,GAAG;CAClC,QAAM,2CAA2C,KAAK,QAAQ;CAmE9D,OAAO;EAhEL,MAAM,QAAQ;EACd,MAAM;EACN;EACA,UAAU,qBAAqB,QAAQ;EAEvC,YAAY,KAAuB;GACjC,OAAO,CAAC,cAAc,GAAG;EAC3B;EAEA,UAAU,QAA0B;GAClC,OAAO,CAAC,YAAY,MAAM;EAC5B;EAEA,KAAK,SAAuB,GAAG,MAAqC;GAElE,IADc,SAAS,SAAS,MAAM,GAAG,CAAC,CAAC,IAAI,EAC3C,KAAS,IAAI;IAEf,MAAM,MAAM,KAAK;IACjB,IAAI,QAAQ,eAAe,QAAQ,eAAe,QAAQ,aAAa,QAAQ,YAC7E,OAAO,KAAK,QAAQ,MAAM,MAAM,YAAY,CAAC,EAAE,WAAW,YAAY,CAAC;IAGzE,IAAI,QAAQ,aAAa;KAGvB,MAAM,SAAS;KACf,IAAI,KAAK,SAAS,UAAU,KAAK,YAAY,IAC3C,OAAO;MAAC;MAAe,KAAK;MAAI,GAAG,KAAK,MAAM,CAAC;KAAC;IAEpD;IAEA,IAAI,QAAQ,WACV,OAAO,KAAK,QACT,MACC,CAAC,EAAE,WAAW,YAAY,KAC1B,CAAC,EAAE,WAAW,YAAY,KAC1B,CAAC,EAAE,WAAW,uBAAuB,CACzC;GAEJ;GACA,OAAO,gBAAA,KAAK,SAAS,KAAK,IAAI;EAChC;EAEA,MAAM,eACJ,aACA,SACA,aACA,MACA,OACA,eAAuC,CAAC,GACxC,kBAA0C,CAAC,GACV;GACjC,OAAO,gBAAA,2BACL,aACA,SACA,MACA,OACA,aACA,cACA,eACF;EACF;CAGK;AACT"}
1
+ {"version":3,"file":"pnpm.cjs","names":[],"sources":["../../../src/adapters/pnpm.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { prepareGenericEmptyProject } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:pnpm');\n\nconst PNPM_V10_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n 'dist-tag',\n 'ping',\n 'search',\n]);\n\n// pnpm v11 removed ping and search\n// dist-tag output format changed (no --json), needs adapted assertions\nconst PNPM_V11_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n]);\n\nfunction getSupportedCommands(version: string): Set<string> {\n const major = parseInt(version.split('.')[0], 10);\n if (major >= 11) {\n debug('pnpm v%d detected, using v11 command set', major);\n return PNPM_V11_COMMANDS;\n }\n return PNPM_V10_COMMANDS;\n}\n\n// pnpm 8 and 9 are end-of-life and no longer supported by the suite.\nconst PNPM_MIN_SUPPORTED_MAJOR = 10;\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, { encoding: 'utf8', timeout: 5000 }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction assertSupportedVersion(resolved: string): void {\n const major = parseInt(resolved.split('.')[0], 10);\n if (!Number.isNaN(major) && major < PNPM_MIN_SUPPORTED_MAJOR) {\n throw new Error(\n `pnpm@${resolved} is not supported. Minimum supported major: ${PNPM_MIN_SUPPORTED_MAJOR}`\n );\n }\n}\n\nfunction installPnpm(version: string): string {\n const pkg = `pnpm@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/.bin/pnpm`;\n const installed = detectVersion(bin);\n debug('installed pnpm %s at %s', installed, bin);\n console.log(` Auto-installed pnpm ${installed}`);\n return bin;\n}\n\nfunction resolvePnpmBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n if (version) return installPnpm(version);\n return 'pnpm';\n}\n\nexport function createPnpmAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolvePnpmBin(binPath, version);\n const resolved = detectVersion(bin);\n assertSupportedVersion(resolved);\n debug('creating pnpm adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `pnpm@${resolved}`,\n type: 'pnpm',\n bin,\n supports: getSupportedCommands(resolved),\n\n registryArg(url: string): string[] {\n return ['--registry', url];\n },\n\n prefixArg(folder: string): string[] {\n return ['--prefix', folder];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n const major = parseInt(resolved.split('.')[0], 10);\n if (major >= 11) {\n // pnpm v11: native deprecate/unpublish don't support --json\n const cmd = args[0];\n if (cmd === 'deprecate' || cmd === 'unpublish' || cmd === 'publish' || cmd === 'dist-tag') {\n args = args.filter((a) => a !== '--json' && !a.startsWith('--loglevel'));\n }\n // pnpm v11: un-deprecate uses `undeprecate` command instead of `deprecate pkg \"\"`\n if (cmd === 'deprecate') {\n // Check if message arg is empty string (un-deprecate)\n // args: ['deprecate', 'pkg@version', '', ...flags]\n const msgIdx = 2; // message is the third arg\n if (args.length > msgIdx && args[msgIdx] === '') {\n args = ['undeprecate', args[1], ...args.slice(3)];\n }\n }\n // pnpm v11: native version command doesn't accept --registry, --loglevel, or --no--git-tag-version\n if (cmd === 'version') {\n args = args.filter(\n (a) =>\n !a.startsWith('--registry') &&\n !a.startsWith('--loglevel') &&\n !a.startsWith('--no--git-tag-version')\n );\n }\n }\n return exec(options, bin, args);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n const project = await prepareGenericEmptyProject(\n packageName,\n version,\n port,\n token,\n registryUrl,\n dependencies,\n devDependencies\n );\n // pnpm 11.24+ enforces a minimumReleaseAge cooldown by default, which\n // rejects the just-published packages these tests install\n // (ERR_PNPM_NO_MATURE_MATCHING_VERSION). Disable it per project via\n // pnpm-workspace.yaml — the file also marks the temp folder as its own\n // workspace root, isolating it from any parent workspace. Tests that\n // exercise the cooldown itself overwrite this file with their own config.\n await writeFile(join(project.tempFolder, 'pnpm-workspace.yaml'), 'minimumReleaseAge: 0\\n');\n return project;\n },\n };\n\n return adapter;\n}\n"],"mappings":"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"}
@@ -4,7 +4,6 @@ const require_bun = require("./adapters/bun.cjs");
4
4
  const require_deno = require("./adapters/deno.cjs");
5
5
  const require_npm = require("./adapters/npm.cjs");
6
6
  const require_pnpm = require("./adapters/pnpm.cjs");
7
- const require_yarn_classic = require("./adapters/yarn-classic.cjs");
8
7
  const require_yarn_modern = require("./adapters/yarn-modern.cjs");
9
8
  require("./adapters/index.cjs");
10
9
  const require_runner = require("./runner.cjs");
@@ -35,11 +34,11 @@ function parseAdapters(pmFilters) {
35
34
  const { name, version, binPath } = parsePmSpec(filter);
36
35
  if (name === "npm") adapters.push(require_npm.createNpmAdapter(binPath, version));
37
36
  else if (name === "pnpm") adapters.push(require_pnpm.createPnpmAdapter(binPath, version));
38
- else if (name === "yarn-classic" || name === "yarn1") adapters.push(require_yarn_classic.createYarnClassicAdapter(binPath, version));
37
+ else if (name === "yarn-classic" || name === "yarn1") throw new Error("yarn classic (v1) is no longer supported. Use yarn-modern (Yarn 3+) instead.");
39
38
  else if (name === "yarn-modern" || name === "yarn") adapters.push(require_yarn_modern.createYarnModernAdapter(binPath, version));
40
39
  else if (name === "bun") adapters.push(require_bun.createBunAdapter(binPath, version));
41
40
  else if (name === "deno") adapters.push(require_deno.createDenoAdapter(binPath, version));
42
- else throw new Error(`Unknown package manager: "${name}". Supported: npm, pnpm, yarn-classic, yarn-modern, bun, deno`);
41
+ else throw new Error(`Unknown package manager: "${name}". Supported: npm, pnpm, yarn-modern, bun, deno`);
43
42
  }
44
43
  return adapters;
45
44
  }
@@ -60,6 +59,8 @@ function parseArgs(argv) {
60
59
  else if (arg === "--concurrency" || arg === "-c") options.concurrency = parseInt(argv[++i], 10);
61
60
  else if (arg === "--timeout") options.timeout = parseInt(argv[++i], 10);
62
61
  else if (arg === "--token") options.token = argv[++i];
62
+ else if (arg === "--uplink-port") options.uplinkPort = parseInt(argv[++i], 10);
63
+ else if (arg === "--print-config") options.printConfig = true;
63
64
  else if (arg === "--verbose" || arg === "-v") options.verbose = true;
64
65
  else if (arg === "--help" || arg === "-h") {
65
66
  printHelp();
@@ -69,6 +70,7 @@ function parseArgs(argv) {
69
70
  else if (arg.startsWith("--test=")) options.test.push(arg.split("=")[1]);
70
71
  else if (arg.startsWith("--token=")) options.token = arg.split("=")[1];
71
72
  else if (arg.startsWith("--timeout=")) options.timeout = parseInt(arg.split("=")[1], 10);
73
+ else if (arg.startsWith("--uplink-port=")) options.uplinkPort = parseInt(arg.split("=")[1], 10);
72
74
  else {
73
75
  console.error(`Unknown argument: ${arg}`);
74
76
  printHelp();
@@ -89,11 +91,11 @@ function printHelp() {
89
91
 
90
92
  Options:
91
93
  --pm <name[@version]> Package manager to test (can be repeated)
92
- Supported: npm, pnpm, yarn-classic, yarn-modern (or yarn), bun, deno
93
- Examples: --pm npm@10 --pm pnpm@9
94
+ Supported: npm (10-12), pnpm (10+),
95
+ yarn-modern (or yarn, Yarn 3+), bun, deno
96
+ Examples: --pm npm@10 --pm pnpm@11
94
97
  --pm yarn-modern@4
95
98
  --pm yarn-modern@3
96
- --pm yarn-classic
97
99
  --pm bun
98
100
  --pm npm --pm pnpm (uses system version)
99
101
  Auto-installs the requested yarn version if needed
@@ -103,17 +105,36 @@ function printHelp() {
103
105
  Available: publish, install, ci, audit, info, deprecate,
104
106
  dist-tags, ping, search, unpublish
105
107
  Scenarios: scenario:install-multiple-deps,
106
- scenario:minimum-release-age (pnpm 11.1+)
108
+ scenario:minimum-release-age (pnpm 11.1+),
109
+ scenario:tarballs (npm adapter),
110
+ scenario:metadata (npm adapter),
111
+ scenario:search (npm adapter; the
112
+ uplink sub-tests also need
113
+ --uplink-port / E2E_UPLINK_PORT),
114
+ scenario:uplink-failure (npm adapter,
115
+ needs --uplink-port / E2E_UPLINK_PORT
116
+ and a registry started with the config
117
+ from --print-config)
107
118
  Default: all supported by the PM
108
119
 
109
120
  --token <token> Auth token (skips user creation)
110
121
  --timeout <ms> Per-test timeout (default: 50000)
122
+ --uplink-port <port> Port for the mock uplink used by
123
+ scenario:uplink-failure (default: $E2E_UPLINK_PORT)
124
+ --print-config Print the recommended Verdaccio config for the full
125
+ battery (max_body_size, mock uplink) and exit
111
126
  -v, --verbose Enable debug output
112
127
  -h, --help Show this help
113
128
  `);
114
129
  }
115
130
  async function main(argv = process.argv) {
116
131
  const options = parseArgs(argv);
132
+ if (options.printConfig) {
133
+ const { buildE2EConfig, DEFAULT_UPLINK_PORT } = await Promise.resolve().then(() => require("./utils/e2e-config.cjs"));
134
+ process.stdout.write(buildE2EConfig(options.uplinkPort ?? DEFAULT_UPLINK_PORT));
135
+ process.exit(0);
136
+ }
137
+ if (options.uplinkPort) process.env.E2E_UPLINK_PORT = String(options.uplinkPort);
117
138
  if (!options.registry) {
118
139
  console.error("Error: --registry is required\n");
119
140
  printHelp();
@@ -157,7 +178,6 @@ exports.createBunAdapter = require_bun.createBunAdapter;
157
178
  exports.createDenoAdapter = require_deno.createDenoAdapter;
158
179
  exports.createNpmAdapter = require_npm.createNpmAdapter;
159
180
  exports.createPnpmAdapter = require_pnpm.createPnpmAdapter;
160
- exports.createYarnClassicAdapter = require_yarn_classic.createYarnClassicAdapter;
161
181
  exports.createYarnModernAdapter = require_yarn_modern.createYarnModernAdapter;
162
182
  exports.main = main;
163
183
  exports.runAll = require_runner.runAll;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport {\n createBunAdapter,\n createDenoAdapter,\n createNpmAdapter,\n createPnpmAdapter,\n createYarnClassicAdapter,\n createYarnModernAdapter,\n} from './adapters';\nimport { runAll } from './runner';\nimport { allTests } from './tests';\nimport { CliOptions, PackageManagerAdapter } from './types';\nimport { createUser, pingRegistry } from './utils/registry-client';\n\nconst debug = buildDebug('verdaccio:e2e-cli');\n\nfunction parsePmSpec(filter: string): { name: string; version?: string; binPath?: string } {\n // --pm yarn-modern@3, --pm yarn-classic@1.22.22, --pm npm=/path/to/bin\n const eqIdx = filter.indexOf('=');\n if (eqIdx !== -1) {\n return { name: filter.slice(0, eqIdx).toLowerCase(), binPath: filter.slice(eqIdx + 1) };\n }\n const atIdx = filter.indexOf('@');\n if (atIdx !== -1) {\n return { name: filter.slice(0, atIdx).toLowerCase(), version: filter.slice(atIdx + 1) };\n }\n return { name: filter.toLowerCase() };\n}\n\nfunction parseAdapters(pmFilters?: string[]): PackageManagerAdapter[] {\n if (!pmFilters || pmFilters.length === 0) {\n return [createNpmAdapter()];\n }\n\n const adapters: PackageManagerAdapter[] = [];\n\n for (const filter of pmFilters) {\n const { name, version, binPath } = parsePmSpec(filter);\n\n if (name === 'npm') {\n adapters.push(createNpmAdapter(binPath, version));\n } else if (name === 'pnpm') {\n adapters.push(createPnpmAdapter(binPath, version));\n } else if (name === 'yarn-classic' || name === 'yarn1') {\n adapters.push(createYarnClassicAdapter(binPath, version));\n } else if (name === 'yarn-modern' || name === 'yarn') {\n adapters.push(createYarnModernAdapter(binPath, version));\n } else if (name === 'bun') {\n adapters.push(createBunAdapter(binPath, version));\n } else if (name === 'deno') {\n adapters.push(createDenoAdapter(binPath, version));\n } else {\n throw new Error(\n `Unknown package manager: \"${name}\". Supported: npm, pnpm, yarn-classic, yarn-modern, bun, deno`\n );\n }\n }\n\n return adapters;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n registry: '',\n pm: [],\n test: [],\n concurrency: 1,\n timeout: 50000,\n verbose: false,\n };\n\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === '--registry' || arg === '-r') {\n options.registry = argv[++i];\n } else if (arg === '--pm') {\n options.pm!.push(argv[++i]);\n } else if (arg === '--test' || arg === '-t') {\n options.test!.push(argv[++i]);\n } else if (arg === '--concurrency' || arg === '-c') {\n options.concurrency = parseInt(argv[++i], 10);\n } else if (arg === '--timeout') {\n options.timeout = parseInt(argv[++i], 10);\n } else if (arg === '--token') {\n options.token = argv[++i];\n } else if (arg === '--verbose' || arg === '-v') {\n options.verbose = true;\n } else if (arg === '--help' || arg === '-h') {\n printHelp();\n process.exit(0);\n } else if (arg.startsWith('--registry=')) {\n options.registry = arg.split('=')[1];\n } else if (arg.startsWith('--pm=')) {\n options.pm!.push(arg.split('=')[1]);\n } else if (arg.startsWith('--test=')) {\n options.test!.push(arg.split('=')[1]);\n } else if (arg.startsWith('--token=')) {\n options.token = arg.split('=')[1];\n } else if (arg.startsWith('--timeout=')) {\n options.timeout = parseInt(arg.split('=')[1], 10);\n } else {\n console.error(`Unknown argument: ${arg}`);\n printHelp();\n process.exit(1);\n }\n }\n\n return options;\n}\n\nfunction printHelp(): void {\n console.log(`\n @verdaccio/e2e-cli - Run Verdaccio e2e tests against any running registry\n\n Usage:\n verdaccio-e2e --registry <url> [options]\n\n Required:\n -r, --registry <url> Verdaccio registry URL (e.g. http://localhost:4873)\n\n Options:\n --pm <name[@version]> Package manager to test (can be repeated)\n Supported: npm, pnpm, yarn-classic, yarn-modern (or yarn), bun, deno\n Examples: --pm npm@10 --pm pnpm@9\n --pm yarn-modern@4\n --pm yarn-modern@3\n --pm yarn-classic\n --pm bun\n --pm npm --pm pnpm (uses system version)\n Auto-installs the requested yarn version if needed\n Default: npm\n\n -t, --test <name> Filter tests by name (can be repeated)\n Available: publish, install, ci, audit, info, deprecate,\n dist-tags, ping, search, unpublish\n Scenarios: scenario:install-multiple-deps,\n scenario:minimum-release-age (pnpm 11.1+)\n Default: all supported by the PM\n\n --token <token> Auth token (skips user creation)\n --timeout <ms> Per-test timeout (default: 50000)\n -v, --verbose Enable debug output\n -h, --help Show this help\n `);\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const options = parseArgs(argv);\n\n if (!options.registry) {\n console.error('Error: --registry is required\\n');\n printHelp();\n process.exit(1);\n }\n\n // Run from a temp dir to isolate from the host project's packageManager, .yarnrc.yml, etc.\n const { createTempFolder } = await import('./utils/project');\n const runDir = await createTempFolder('e2e-run');\n process.chdir(runDir);\n\n if (options.verbose) {\n const { setVerbose } = await import('./utils/process');\n setVerbose(true);\n }\n\n // Ensure registry is reachable\n console.log(`Checking registry at ${options.registry}...`);\n const alive = await pingRegistry(options.registry);\n if (!alive) {\n console.error(`Error: Registry at ${options.registry} is not reachable`);\n process.exit(1);\n }\n console.log(`Registry is alive.`);\n\n // Get auth token\n let token = options.token;\n if (!token) {\n console.log('Creating test user...');\n const auth = await createUser(options.registry);\n token = auth.token;\n console.log(`User \"${auth.user}\" created.`);\n }\n\n // Build adapter list\n const adapters = parseAdapters(options.pm);\n console.log(`Adapters: ${adapters.map((a) => a.name).join(', ')}`);\n\n // Filter tests\n const tests =\n options.test && options.test.length > 0\n ? allTests.filter((t) => options.test!.includes(t.name))\n : allTests;\n\n console.log(`Tests: ${tests.map((t) => t.name).join(', ')}`);\n\n // Run\n const { exitCode } = await runAll(adapters, tests, options.registry, token, {\n timeout: options.timeout,\n concurrency: options.concurrency,\n testFilter: options.test,\n });\n\n process.exit(exitCode);\n}\n\n// Re-export for programmatic usage\nexport { allTests } from './tests';\nexport { allScenarios } from './scenarios';\nexport {\n createBunAdapter,\n createDenoAdapter,\n createNpmAdapter,\n createPnpmAdapter,\n createYarnClassicAdapter,\n createYarnModernAdapter,\n} from './adapters';\nexport { runAll, runSuite } from './runner';\nexport type { PackageManagerAdapter, TestDefinition, TestContext, CliOptions } from './types';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport {\n createBunAdapter,\n createDenoAdapter,\n createNpmAdapter,\n createPnpmAdapter,\n createYarnModernAdapter,\n} from './adapters';\nimport { runAll } from './runner';\nimport { allTests } from './tests';\nimport { CliOptions, PackageManagerAdapter } from './types';\nimport { createUser, pingRegistry } from './utils/registry-client';\n\nconst debug = buildDebug('verdaccio:e2e-cli');\n\nfunction parsePmSpec(filter: string): { name: string; version?: string; binPath?: string } {\n // --pm yarn-modern@3, --pm npm@10, --pm npm=/path/to/bin\n const eqIdx = filter.indexOf('=');\n if (eqIdx !== -1) {\n return { name: filter.slice(0, eqIdx).toLowerCase(), binPath: filter.slice(eqIdx + 1) };\n }\n const atIdx = filter.indexOf('@');\n if (atIdx !== -1) {\n return { name: filter.slice(0, atIdx).toLowerCase(), version: filter.slice(atIdx + 1) };\n }\n return { name: filter.toLowerCase() };\n}\n\nfunction parseAdapters(pmFilters?: string[]): PackageManagerAdapter[] {\n if (!pmFilters || pmFilters.length === 0) {\n return [createNpmAdapter()];\n }\n\n const adapters: PackageManagerAdapter[] = [];\n\n for (const filter of pmFilters) {\n const { name, version, binPath } = parsePmSpec(filter);\n\n if (name === 'npm') {\n adapters.push(createNpmAdapter(binPath, version));\n } else if (name === 'pnpm') {\n adapters.push(createPnpmAdapter(binPath, version));\n } else if (name === 'yarn-classic' || name === 'yarn1') {\n throw new Error(\n 'yarn classic (v1) is no longer supported. Use yarn-modern (Yarn 3+) instead.'\n );\n } else if (name === 'yarn-modern' || name === 'yarn') {\n adapters.push(createYarnModernAdapter(binPath, version));\n } else if (name === 'bun') {\n adapters.push(createBunAdapter(binPath, version));\n } else if (name === 'deno') {\n adapters.push(createDenoAdapter(binPath, version));\n } else {\n throw new Error(\n `Unknown package manager: \"${name}\". Supported: npm, pnpm, yarn-modern, bun, deno`\n );\n }\n }\n\n return adapters;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n registry: '',\n pm: [],\n test: [],\n concurrency: 1,\n timeout: 50000,\n verbose: false,\n };\n\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === '--registry' || arg === '-r') {\n options.registry = argv[++i];\n } else if (arg === '--pm') {\n options.pm!.push(argv[++i]);\n } else if (arg === '--test' || arg === '-t') {\n options.test!.push(argv[++i]);\n } else if (arg === '--concurrency' || arg === '-c') {\n options.concurrency = parseInt(argv[++i], 10);\n } else if (arg === '--timeout') {\n options.timeout = parseInt(argv[++i], 10);\n } else if (arg === '--token') {\n options.token = argv[++i];\n } else if (arg === '--uplink-port') {\n options.uplinkPort = parseInt(argv[++i], 10);\n } else if (arg === '--print-config') {\n options.printConfig = true;\n } else if (arg === '--verbose' || arg === '-v') {\n options.verbose = true;\n } else if (arg === '--help' || arg === '-h') {\n printHelp();\n process.exit(0);\n } else if (arg.startsWith('--registry=')) {\n options.registry = arg.split('=')[1];\n } else if (arg.startsWith('--pm=')) {\n options.pm!.push(arg.split('=')[1]);\n } else if (arg.startsWith('--test=')) {\n options.test!.push(arg.split('=')[1]);\n } else if (arg.startsWith('--token=')) {\n options.token = arg.split('=')[1];\n } else if (arg.startsWith('--timeout=')) {\n options.timeout = parseInt(arg.split('=')[1], 10);\n } else if (arg.startsWith('--uplink-port=')) {\n options.uplinkPort = parseInt(arg.split('=')[1], 10);\n } else {\n console.error(`Unknown argument: ${arg}`);\n printHelp();\n process.exit(1);\n }\n }\n\n return options;\n}\n\nfunction printHelp(): void {\n console.log(`\n @verdaccio/e2e-cli - Run Verdaccio e2e tests against any running registry\n\n Usage:\n verdaccio-e2e --registry <url> [options]\n\n Required:\n -r, --registry <url> Verdaccio registry URL (e.g. http://localhost:4873)\n\n Options:\n --pm <name[@version]> Package manager to test (can be repeated)\n Supported: npm (10-12), pnpm (10+),\n yarn-modern (or yarn, Yarn 3+), bun, deno\n Examples: --pm npm@10 --pm pnpm@11\n --pm yarn-modern@4\n --pm yarn-modern@3\n --pm bun\n --pm npm --pm pnpm (uses system version)\n Auto-installs the requested yarn version if needed\n Default: npm\n\n -t, --test <name> Filter tests by name (can be repeated)\n Available: publish, install, ci, audit, info, deprecate,\n dist-tags, ping, search, unpublish\n Scenarios: scenario:install-multiple-deps,\n scenario:minimum-release-age (pnpm 11.1+),\n scenario:tarballs (npm adapter),\n scenario:metadata (npm adapter),\n scenario:search (npm adapter; the\n uplink sub-tests also need\n --uplink-port / E2E_UPLINK_PORT),\n scenario:uplink-failure (npm adapter,\n needs --uplink-port / E2E_UPLINK_PORT\n and a registry started with the config\n from --print-config)\n Default: all supported by the PM\n\n --token <token> Auth token (skips user creation)\n --timeout <ms> Per-test timeout (default: 50000)\n --uplink-port <port> Port for the mock uplink used by\n scenario:uplink-failure (default: $E2E_UPLINK_PORT)\n --print-config Print the recommended Verdaccio config for the full\n battery (max_body_size, mock uplink) and exit\n -v, --verbose Enable debug output\n -h, --help Show this help\n `);\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const options = parseArgs(argv);\n\n if (options.printConfig) {\n const { buildE2EConfig, DEFAULT_UPLINK_PORT } = await import('./utils/e2e-config');\n process.stdout.write(buildE2EConfig(options.uplinkPort ?? DEFAULT_UPLINK_PORT));\n process.exit(0);\n }\n\n // Expose the mock uplink port to scenarios (scenario:uplink-failure gates on it).\n if (options.uplinkPort) {\n process.env.E2E_UPLINK_PORT = String(options.uplinkPort);\n }\n\n if (!options.registry) {\n console.error('Error: --registry is required\\n');\n printHelp();\n process.exit(1);\n }\n\n // Run from a temp dir to isolate from the host project's packageManager, .yarnrc.yml, etc.\n const { createTempFolder } = await import('./utils/project');\n const runDir = await createTempFolder('e2e-run');\n process.chdir(runDir);\n\n if (options.verbose) {\n const { setVerbose } = await import('./utils/process');\n setVerbose(true);\n }\n\n // Ensure registry is reachable\n console.log(`Checking registry at ${options.registry}...`);\n const alive = await pingRegistry(options.registry);\n if (!alive) {\n console.error(`Error: Registry at ${options.registry} is not reachable`);\n process.exit(1);\n }\n console.log(`Registry is alive.`);\n\n // Get auth token\n let token = options.token;\n if (!token) {\n console.log('Creating test user...');\n const auth = await createUser(options.registry);\n token = auth.token;\n console.log(`User \"${auth.user}\" created.`);\n }\n\n // Build adapter list\n const adapters = parseAdapters(options.pm);\n console.log(`Adapters: ${adapters.map((a) => a.name).join(', ')}`);\n\n // Filter tests\n const tests =\n options.test && options.test.length > 0\n ? allTests.filter((t) => options.test!.includes(t.name))\n : allTests;\n\n console.log(`Tests: ${tests.map((t) => t.name).join(', ')}`);\n\n // Run\n const { exitCode } = await runAll(adapters, tests, options.registry, token, {\n timeout: options.timeout,\n concurrency: options.concurrency,\n testFilter: options.test,\n });\n\n process.exit(exitCode);\n}\n\n// Re-export for programmatic usage\nexport { allTests } from './tests';\nexport { allScenarios } from './scenarios';\nexport {\n createBunAdapter,\n createDenoAdapter,\n createNpmAdapter,\n createPnpmAdapter,\n createYarnModernAdapter,\n} from './adapters';\nexport { runAll, runSuite } from './runner';\nexport type { PackageManagerAdapter, TestDefinition, TestContext, CliOptions } from './types';\n"],"mappings":"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"}
@@ -106,7 +106,7 @@ async function runSuite(adapter, tests, registryUrl, token, options) {
106
106
  continue;
107
107
  }
108
108
  require_reporter.reportTestStart(adapter.name, test.name);
109
- const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);
109
+ const result = await runSingleTest(adapter, test, registryUrl, token, Math.max(options.timeout, test.timeout ?? 0));
110
110
  results.push(result);
111
111
  require_reporter.reportTestResult(result, result.hasSubTests);
112
112
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runner.cjs","names":[],"sources":["../../src/runner.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\n\nimport {\n reportSkipped,\n reportSubTestResult,\n reportSuiteStart,\n reportSummary,\n reportTestResult,\n reportTestStart,\n} from './reporter';\nimport {\n PackageManagerAdapter,\n SubTestResult,\n SuiteResult,\n TestContext,\n TestDefinition,\n TestResult,\n} from './types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:runner');\n\nfunction getPort(registryUrl: string): number {\n try {\n const url = new URL(registryUrl);\n return parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80);\n } catch {\n return 4873;\n }\n}\n\nasync function runSingleTest(\n adapter: PackageManagerAdapter,\n test: TestDefinition,\n registryUrl: string,\n token: string,\n timeout: number\n): Promise<TestResult & { hasSubTests: boolean }> {\n const port = getPort(registryUrl);\n let hasSubTests = false;\n const subResults: SubTestResult[] = [];\n const ctx: TestContext = {\n registryUrl,\n token,\n port,\n exec: adapter.exec.bind(adapter),\n adapter,\n runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,\n async subTest(label: string, fn: () => Promise<void>): Promise<void> {\n hasSubTests = true;\n const subStart = Date.now();\n try {\n await fn();\n const duration = Date.now() - subStart;\n subResults.push({ label, passed: true, duration });\n reportSubTestResult(label, true, duration);\n } catch (err) {\n const duration = Date.now() - subStart;\n const error = err instanceof Error ? err.message : String(err);\n subResults.push({ label, passed: false, duration, error });\n reportSubTestResult(label, false, duration);\n throw err;\n }\n },\n };\n\n const start = Date.now();\n\n return new Promise<TestResult & { hasSubTests: boolean }>((resolve) => {\n const timer = setTimeout(() => {\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: `Test timed out after ${timeout}ms`,\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n }, timeout);\n\n test\n .run(ctx)\n .then(() => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: true,\n duration: Date.now() - start,\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n })\n .catch((err) => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n });\n });\n}\n\nexport async function runSuite(\n adapter: PackageManagerAdapter,\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; testFilter?: string[] }\n): Promise<SuiteResult> {\n const suiteStart = Date.now();\n const results: TestResult[] = [];\n let skipped = 0;\n\n reportSuiteStart(adapter.name);\n\n for (const test of tests) {\n // Filter by test name if specified\n if (options.testFilter && options.testFilter.length > 0) {\n if (!options.testFilter.includes(test.name)) {\n continue;\n }\n }\n\n // Check if adapter supports required commands\n if (test.requires) {\n const unsupported = test.requires.filter((cmd) => !adapter.supports.has(cmd));\n if (unsupported.length > 0) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n }\n\n // Check adapter/version gate (e.g. pnpm-only tests)\n if (test.appliesTo && !test.appliesTo(adapter)) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n\n reportTestStart(adapter.name, test.name);\n const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);\n results.push(result);\n reportTestResult(result, result.hasSubTests);\n }\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n\n return {\n adapter: adapter.name,\n tests: results,\n passed,\n failed,\n skipped,\n duration: Date.now() - suiteStart,\n };\n}\n\nexport async function runAll(\n adapters: PackageManagerAdapter[],\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; concurrency: number; testFilter?: string[] }\n): Promise<{ results: SuiteResult[]; exitCode: number }> {\n debug('running %d adapters with %d tests', adapters.length, tests.length);\n const results: SuiteResult[] = [];\n\n // Run adapters sequentially (each suite is already complex enough)\n for (const adapter of adapters) {\n const result = await runSuite(adapter, tests, registryUrl, token, options);\n results.push(result);\n }\n\n reportSummary(results);\n\n const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);\n return { results, exitCode: totalFailed > 0 ? 1 : 0 };\n}\n"],"mappings":";;;;;;AAoBA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,0BAA0B;AAEnD,SAAS,QAAQ,aAA6B;CAC5C,IAAI;EACF,MAAM,QAAM,IAAI,IAAA,IAAI,WAAW;EAC/B,OAAO,SAAS,MAAI,MAAM,EAAE,MAAM,MAAI,aAAa,WAAW,MAAM;CACtE,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAe,cACb,SACA,MACA,aACA,OACA,SACgD;CAChD,MAAM,OAAO,QAAQ,WAAW;CAChC,IAAI,cAAc;CAClB,MAAM,aAA8B,CAAC;CACrC,MAAM,MAAmB;EACvB;EACA;EACA;EACA,MAAM,QAAQ,KAAK,KAAK,OAAO;EAC/B;EACA,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;EACzE,MAAM,QAAQ,OAAe,IAAwC;GACnE,cAAc;GACd,MAAM,WAAW,KAAK,IAAI;GAC1B,IAAI;IACF,MAAM,GAAG;IACT,MAAM,WAAW,KAAK,IAAI,IAAI;IAC9B,WAAW,KAAK;KAAE;KAAO,QAAQ;KAAM;IAAS,CAAC;IACjD,iBAAA,oBAAoB,OAAO,MAAM,QAAQ;GAC3C,SAAS,KAAK;IACZ,MAAM,WAAW,KAAK,IAAI,IAAI;IAC9B,MAAM,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;IAC7D,WAAW,KAAK;KAAE;KAAO,QAAQ;KAAO;KAAU;IAAM,CAAC;IACzD,iBAAA,oBAAoB,OAAO,OAAO,QAAQ;IAC1C,MAAM;GACR;EACF;CACF;CAEA,MAAM,QAAQ,KAAK,IAAI;CAEvB,OAAO,IAAI,SAAgD,YAAY;EACrE,MAAM,QAAQ,iBAAiB;GAC7B,QAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,IAAI,IAAI;IACvB,OAAO,wBAAwB,QAAQ;IACvC;IACA,UAAU,WAAW,SAAS,IAAI,aAAa,KAAA;GACjD,CAAC;EACH,GAAG,OAAO;EAEV,KACG,IAAI,GAAG,CAAC,CACR,WAAW;GACV,aAAa,KAAK;GAClB,QAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,IAAI,IAAI;IACvB;IACA,UAAU,WAAW,SAAS,IAAI,aAAa,KAAA;GACjD,CAAC;EACH,CAAC,CAAC,CACD,OAAO,QAAQ;GACd,aAAa,KAAK;GAClB,QAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,IAAI,IAAI;IACvB,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;IACtD;IACA,UAAU,WAAW,SAAS,IAAI,aAAa,KAAA;GACjD,CAAC;EACH,CAAC;CACL,CAAC;AACH;AAEA,eAAsB,SACpB,SACA,OACA,aACA,OACA,SACsB;CACtB,MAAM,aAAa,KAAK,IAAI;CAC5B,MAAM,UAAwB,CAAC;CAC/B,IAAI,UAAU;CAEd,iBAAA,iBAAiB,QAAQ,IAAI;CAE7B,KAAK,MAAM,QAAQ,OAAO;EAExB,IAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS,GAChD;OAAA,CAAC,QAAQ,WAAW,SAAS,KAAK,IAAI,GACxC;EAAA;EAKJ,IAAI,KAAK,UACa;OAAA,KAAK,SAAS,QAAQ,QAAQ,CAAC,QAAQ,SAAS,IAAI,GAAG,CACvE,CAAA,CAAY,SAAS,GAAG;IAC1B,iBAAA,cAAc,KAAK,IAAI;IACvB;IACA;GACF;;EAIF,IAAI,KAAK,aAAa,CAAC,KAAK,UAAU,OAAO,GAAG;GAC9C,iBAAA,cAAc,KAAK,IAAI;GACvB;GACA;EACF;EAEA,iBAAA,gBAAgB,QAAQ,MAAM,KAAK,IAAI;EACvC,MAAM,SAAS,MAAM,cAAc,SAAS,MAAM,aAAa,OAAO,QAAQ,OAAO;EACrF,QAAQ,KAAK,MAAM;EACnB,iBAAA,iBAAiB,QAAQ,OAAO,WAAW;CAC7C;CAEA,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/C,MAAM,SAAS,QAAQ,QAAQ,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;CAEhD,OAAO;EACL,SAAS,QAAQ;EACjB,OAAO;EACP;EACA;EACA;EACA,UAAU,KAAK,IAAI,IAAI;CACzB;AACF;AAEA,eAAsB,OACpB,UACA,OACA,aACA,OACA,SACuD;CACvD,QAAM,qCAAqC,SAAS,QAAQ,MAAM,MAAM;CACxE,MAAM,UAAyB,CAAC;CAGhC,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,MAAM,SAAS,SAAS,OAAO,aAAa,OAAO,OAAO;EACzE,QAAQ,KAAK,MAAM;CACrB;CAEA,iBAAA,cAAc,OAAO;CAGrB,OAAO;EAAE;EAAS,UADE,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,CACnC,IAAc,IAAI,IAAI;CAAE;AACtD"}
1
+ {"version":3,"file":"runner.cjs","names":[],"sources":["../../src/runner.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\n\nimport {\n reportSkipped,\n reportSubTestResult,\n reportSuiteStart,\n reportSummary,\n reportTestResult,\n reportTestStart,\n} from './reporter';\nimport {\n PackageManagerAdapter,\n SubTestResult,\n SuiteResult,\n TestContext,\n TestDefinition,\n TestResult,\n} from './types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:runner');\n\nfunction getPort(registryUrl: string): number {\n try {\n const url = new URL(registryUrl);\n return parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80);\n } catch {\n return 4873;\n }\n}\n\nasync function runSingleTest(\n adapter: PackageManagerAdapter,\n test: TestDefinition,\n registryUrl: string,\n token: string,\n timeout: number\n): Promise<TestResult & { hasSubTests: boolean }> {\n const port = getPort(registryUrl);\n let hasSubTests = false;\n const subResults: SubTestResult[] = [];\n const ctx: TestContext = {\n registryUrl,\n token,\n port,\n exec: adapter.exec.bind(adapter),\n adapter,\n runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,\n async subTest(label: string, fn: () => Promise<void>): Promise<void> {\n hasSubTests = true;\n const subStart = Date.now();\n try {\n await fn();\n const duration = Date.now() - subStart;\n subResults.push({ label, passed: true, duration });\n reportSubTestResult(label, true, duration);\n } catch (err) {\n const duration = Date.now() - subStart;\n const error = err instanceof Error ? err.message : String(err);\n subResults.push({ label, passed: false, duration, error });\n reportSubTestResult(label, false, duration);\n throw err;\n }\n },\n };\n\n const start = Date.now();\n\n return new Promise<TestResult & { hasSubTests: boolean }>((resolve) => {\n const timer = setTimeout(() => {\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: `Test timed out after ${timeout}ms`,\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n }, timeout);\n\n test\n .run(ctx)\n .then(() => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: true,\n duration: Date.now() - start,\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n })\n .catch((err) => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n });\n });\n}\n\nexport async function runSuite(\n adapter: PackageManagerAdapter,\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; testFilter?: string[] }\n): Promise<SuiteResult> {\n const suiteStart = Date.now();\n const results: TestResult[] = [];\n let skipped = 0;\n\n reportSuiteStart(adapter.name);\n\n for (const test of tests) {\n // Filter by test name if specified\n if (options.testFilter && options.testFilter.length > 0) {\n if (!options.testFilter.includes(test.name)) {\n continue;\n }\n }\n\n // Check if adapter supports required commands\n if (test.requires) {\n const unsupported = test.requires.filter((cmd) => !adapter.supports.has(cmd));\n if (unsupported.length > 0) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n }\n\n // Check adapter/version gate (e.g. pnpm-only tests)\n if (test.appliesTo && !test.appliesTo(adapter)) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n\n reportTestStart(adapter.name, test.name);\n const timeout = Math.max(options.timeout, test.timeout ?? 0);\n const result = await runSingleTest(adapter, test, registryUrl, token, timeout);\n results.push(result);\n reportTestResult(result, result.hasSubTests);\n }\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n\n return {\n adapter: adapter.name,\n tests: results,\n passed,\n failed,\n skipped,\n duration: Date.now() - suiteStart,\n };\n}\n\nexport async function runAll(\n adapters: PackageManagerAdapter[],\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; concurrency: number; testFilter?: string[] }\n): Promise<{ results: SuiteResult[]; exitCode: number }> {\n debug('running %d adapters with %d tests', adapters.length, tests.length);\n const results: SuiteResult[] = [];\n\n // Run adapters sequentially (each suite is already complex enough)\n for (const adapter of adapters) {\n const result = await runSuite(adapter, tests, registryUrl, token, options);\n results.push(result);\n }\n\n reportSummary(results);\n\n const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);\n return { results, exitCode: totalFailed > 0 ? 1 : 0 };\n}\n"],"mappings":"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"}
@@ -1,10 +1,25 @@
1
1
  const require_install_multiple_deps = require("./install-multiple-deps.cjs");
2
+ const require_metadata = require("./metadata.cjs");
2
3
  const require_minimum_release_age = require("./minimum-release-age.cjs");
4
+ const require_search = require("./search.cjs");
5
+ const require_tarballs = require("./tarballs.cjs");
6
+ const require_uplink_failure = require("./uplink-failure.cjs");
3
7
  //#region src/scenarios/index.ts
4
- var allScenarios = [require_install_multiple_deps.installMultipleDepsScenario, require_minimum_release_age.minimumReleaseAgeScenario];
8
+ var allScenarios = [
9
+ require_install_multiple_deps.installMultipleDepsScenario,
10
+ require_minimum_release_age.minimumReleaseAgeScenario,
11
+ require_tarballs.tarballsScenario,
12
+ require_metadata.metadataScenario,
13
+ require_search.searchScenario,
14
+ require_uplink_failure.uplinkFailureScenario
15
+ ];
5
16
  //#endregion
6
17
  exports.allScenarios = allScenarios;
7
18
  exports.installMultipleDepsScenario = require_install_multiple_deps.installMultipleDepsScenario;
19
+ exports.metadataScenario = require_metadata.metadataScenario;
8
20
  exports.minimumReleaseAgeScenario = require_minimum_release_age.minimumReleaseAgeScenario;
21
+ exports.searchScenario = require_search.searchScenario;
22
+ exports.tarballsScenario = require_tarballs.tarballsScenario;
23
+ exports.uplinkFailureScenario = require_uplink_failure.uplinkFailureScenario;
9
24
 
10
25
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/scenarios/index.ts"],"sourcesContent":["import { TestDefinition } from '../types';\nimport { installMultipleDepsScenario } from './install-multiple-deps';\nimport { minimumReleaseAgeScenario } from './minimum-release-age';\n\nexport const allScenarios: TestDefinition[] = [\n installMultipleDepsScenario,\n minimumReleaseAgeScenario,\n];\n\nexport { installMultipleDepsScenario, minimumReleaseAgeScenario };\n"],"mappings":";;;AAIA,IAAa,eAAiC,CAC5C,8BAAA,6BACA,4BAAA,yBACF"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/scenarios/index.ts"],"sourcesContent":["import { TestDefinition } from '../types';\nimport { installMultipleDepsScenario } from './install-multiple-deps';\nimport { metadataScenario } from './metadata';\nimport { minimumReleaseAgeScenario } from './minimum-release-age';\nimport { searchScenario } from './search';\nimport { tarballsScenario } from './tarballs';\nimport { uplinkFailureScenario } from './uplink-failure';\n\nexport const allScenarios: TestDefinition[] = [\n installMultipleDepsScenario,\n minimumReleaseAgeScenario,\n tarballsScenario,\n metadataScenario,\n searchScenario,\n uplinkFailureScenario,\n];\n\nexport {\n installMultipleDepsScenario,\n minimumReleaseAgeScenario,\n searchScenario,\n tarballsScenario,\n metadataScenario,\n uplinkFailureScenario,\n};\n"],"mappings":";;;;;;;AAQA,IAAa,eAAiC;CAC5C,8BAAA;CACA,4BAAA;CACA,iBAAA;CACA,iBAAA;CACA,eAAA;CACA,uBAAA;AACF"}
@@ -1,11 +1,11 @@
1
1
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_process = require("../utils/process.cjs");
2
3
  const require_info = require("../utils/info.cjs");
3
- let debug = require("debug");
4
- debug = require_runtime.__toESM(debug, 1);
4
+ let path = require("path");
5
+ let fs_promises = require("fs/promises");
5
6
  let assert = require("assert");
6
7
  assert = require_runtime.__toESM(assert, 1);
7
8
  //#region src/scenarios/install-multiple-deps.ts
8
- var debug$1 = (0, debug.default)("verdaccio:e2e-cli:scenario:install-multiple-deps");
9
9
  /**
10
10
  * Scenario: install-multiple-deps
11
11
  *
@@ -22,25 +22,16 @@ var debug$1 = (0, debug.default)("verdaccio:e2e-cli:scenario:install-multiple-de
22
22
  var SEED_PACKAGES_COUNT = 5;
23
23
  /**
24
24
  * Parse `info --json` output across all adapters.
25
- * Yarn classic wraps the result in NDJSON lines with `{ type: "inspect", data: { ... } }`.
26
25
  */
27
- function parseInfoOutput(stdout, adapterType) {
28
- if (adapterType === "yarn-classic") {
29
- const lines = stdout.split("\n").filter(Boolean);
30
- for (const line of lines) try {
31
- const obj = JSON.parse(line);
32
- if (obj.type === "inspect" && obj.data) return obj.data;
33
- } catch {}
34
- return require_info.normalizeInfo(JSON.parse(stdout));
35
- }
26
+ function parseInfoOutput(stdout) {
36
27
  return require_info.normalizeInfo(JSON.parse(stdout));
37
28
  }
38
29
  async function publishSeedPackage(ctx, pkgName, version, dependencies = {}) {
39
- debug$1("publishing seed package %s@%s", pkgName, version);
30
+ require_process.trace("publishing seed package %s@%s", pkgName, version);
40
31
  const { tempFolder } = await ctx.adapter.prepareProject(pkgName, version, ctx.registryUrl, ctx.port, ctx.token, dependencies);
41
32
  if (ctx.adapter.type === "yarn-modern") await ctx.adapter.exec({ cwd: tempFolder }, "install");
42
33
  await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
43
- debug$1("published %s@%s", pkgName, version);
34
+ require_process.trace("published %s@%s", pkgName, version);
44
35
  }
45
36
  async function testInstallMultipleDeps(ctx) {
46
37
  const id = ctx.runId;
@@ -54,7 +45,7 @@ async function testInstallMultipleDeps(ctx) {
54
45
  [`@verdaccio/seed-${id}-2`]: "1.0.0",
55
46
  [sharedPkg]: "1.0.0"
56
47
  });
57
- debug$1("all seed packages published");
48
+ require_process.trace("all seed packages published");
58
49
  });
59
50
  await ctx.subTest("install all dependencies in consumer project", async () => {
60
51
  const consumerDeps = {};
@@ -64,26 +55,26 @@ async function testInstallMultipleDeps(ctx) {
64
55
  const consumerName = `@verdaccio/consumer-${id}`;
65
56
  const { tempFolder } = await ctx.adapter.prepareProject(consumerName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, consumerDeps);
66
57
  projectCwd = tempFolder;
67
- debug$1("installing %d dependencies in consumer project", Object.keys(consumerDeps).length);
58
+ require_process.trace("installing %d dependencies in consumer project", Object.keys(consumerDeps).length);
68
59
  const args = ["install", ...ctx.adapter.registryArg(ctx.registryUrl)];
69
60
  await ctx.adapter.exec({ cwd: tempFolder }, ...args);
70
- debug$1("install completed for consumer project");
61
+ require_process.trace("install completed for consumer project");
71
62
  });
72
63
  await ctx.subTest("verify installed packages", async () => {
73
64
  for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {
74
65
  const name = `@verdaccio/seed-${id}-${i}`;
75
- const info = parseInfoOutput((await ctx.adapter.exec({ cwd: projectCwd }, "info", name, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout, ctx.adapter.type);
66
+ const info = parseInfoOutput((await ctx.adapter.exec({ cwd: projectCwd }, "info", name, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout);
76
67
  assert.default.strictEqual(info.name, name, `Expected package name "${name}"`);
77
68
  assert.default.strictEqual(info.version, "1.0.0", `Expected version 1.0.0 for ${name}`);
78
69
  }
79
70
  const midName = `@verdaccio/seed-mid-${id}`;
80
- const midInfo = parseInfoOutput((await ctx.adapter.exec({ cwd: projectCwd }, "info", midName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout, ctx.adapter.type);
71
+ const midInfo = parseInfoOutput((await ctx.adapter.exec({ cwd: projectCwd }, "info", midName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout);
81
72
  assert.default.strictEqual(midInfo.name, midName);
82
73
  const deps = midInfo.dependencies || {};
83
74
  assert.default.strictEqual(deps[`@verdaccio/seed-${id}-1`], "1.0.0", "Intermediate should depend on seed-1");
84
75
  assert.default.strictEqual(deps[`@verdaccio/seed-${id}-2`], "1.0.0", "Intermediate should depend on seed-2");
85
76
  assert.default.strictEqual(deps[`@verdaccio/seed-shared-${id}`], "1.0.0", "Intermediate should depend on shared");
86
- debug$1("all packages verified");
77
+ require_process.trace("all packages verified");
87
78
  });
88
79
  await ctx.subTest("update and re-install", async () => {
89
80
  const leafName = `@verdaccio/seed-${id}-1`;
@@ -97,9 +88,20 @@ async function testInstallMultipleDeps(ctx) {
97
88
  const consumerName = `@verdaccio/consumer-update-${id}`;
98
89
  const { tempFolder } = await ctx.adapter.prepareProject(consumerName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, consumerDeps);
99
90
  await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
100
- const leafInfo = parseInfoOutput((await ctx.adapter.exec({ cwd: tempFolder }, "info", leafName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout, ctx.adapter.type);
91
+ if ([
92
+ "npm",
93
+ "pnpm",
94
+ "bun"
95
+ ].includes(ctx.adapter.type)) for (const name of [leafName, sharedName]) {
96
+ const manifestPath = (0, path.join)(tempFolder, "node_modules", name, "package.json");
97
+ const installed = JSON.parse(await (0, fs_promises.readFile)(manifestPath, "utf8"));
98
+ require_process.trace("on disk: %s@%s (%s)", installed.name, installed.version, manifestPath);
99
+ assert.default.strictEqual(installed.version, "1.0.0", `Expected ${name}@1.0.0 installed for range ^1.0.0 (latest is 2.0.0), got ${installed.version}`);
100
+ }
101
+ const leafInfo = parseInfoOutput((await ctx.adapter.exec({ cwd: tempFolder }, "info", leafName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout);
102
+ require_process.trace("registry info for %s: version=%s dist-tags=%j", leafName, leafInfo.version, leafInfo["dist-tags"]);
101
103
  assert.default.strictEqual(leafInfo["dist-tags"]?.latest ?? leafInfo.version, "2.0.0", `Expected latest version of ${leafName} to be 2.0.0`);
102
- debug$1("update and re-install verified");
104
+ require_process.trace("update and re-install verified");
103
105
  });
104
106
  }
105
107
  var installMultipleDepsScenario = {
@@ -1 +1 @@
1
- {"version":3,"file":"install-multiple-deps.cjs","names":[],"sources":["../../../src/scenarios/install-multiple-deps.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { normalizeInfo } from '../utils/info';\n\nconst debug = buildDebug('verdaccio:e2e-cli:scenario:install-multiple-deps');\n\n/**\n * Scenario: install-multiple-deps\n *\n * Publishes several packages to the registry (some scoped, some unscoped,\n * some with inter-dependencies), then creates a consumer project that\n * depends on all of them and runs `install`.\n *\n * This exercises the registry under realistic load:\n * - many parallel tarball downloads\n * - metadata resolution for multiple packages\n * - scoped-package authentication\n * - transitive dependency resolution\n */\n\nconst SEED_PACKAGES_COUNT = 5;\n\n/**\n * Parse `info --json` output across all adapters.\n * Yarn classic wraps the result in NDJSON lines with `{ type: \"inspect\", data: { ... } }`.\n */\nfunction parseInfoOutput(stdout: string, adapterType: string): any {\n if (adapterType === 'yarn-classic') {\n // Yarn classic outputs NDJSON — find the \"inspect\" line that holds package data\n const lines = stdout.split('\\n').filter(Boolean);\n for (const line of lines) {\n try {\n const obj = JSON.parse(line);\n if (obj.type === 'inspect' && obj.data) {\n return obj.data;\n }\n } catch {\n // skip non-JSON lines\n }\n }\n // Fallback: try parsing the whole output\n return normalizeInfo(JSON.parse(stdout));\n }\n return normalizeInfo(JSON.parse(stdout));\n}\n\nasync function publishSeedPackage(\n ctx: TestContext,\n pkgName: string,\n version: string,\n dependencies: Record<string, string> = {}\n): Promise<void> {\n debug('publishing seed package %s@%s', pkgName, version);\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n version,\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n dependencies\n );\n\n if (ctx.adapter.type === 'yarn-modern') {\n await ctx.adapter.exec({ cwd: tempFolder }, 'install');\n }\n\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n debug('published %s@%s', pkgName, version);\n}\n\nasync function testInstallMultipleDeps(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Shared project folder used as cwd for info commands across subtests.\n // Yarn modern requires a project context (package.json + .yarnrc.yml) for `yarn npm info`.\n let projectCwd = '';\n\n // --- Phase 1: Publish a tree of seed packages ---\n await ctx.subTest('publish seed packages', async () => {\n // Leaf packages (no dependencies of their own)\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n const name = `@verdaccio/seed-${id}-${i}`;\n await publishSeedPackage(ctx, name, '1.0.0');\n }\n\n // A \"shared\" package that multiple consumers will pull in\n const sharedPkg = `@verdaccio/seed-shared-${id}`;\n await publishSeedPackage(ctx, sharedPkg, '1.0.0');\n\n // An intermediate package that depends on some leaf packages + shared\n const intermediatePkg = `@verdaccio/seed-mid-${id}`;\n await publishSeedPackage(ctx, intermediatePkg, '1.0.0', {\n [`@verdaccio/seed-${id}-1`]: '1.0.0',\n [`@verdaccio/seed-${id}-2`]: '1.0.0',\n [sharedPkg]: '1.0.0',\n });\n\n debug('all seed packages published');\n });\n\n // --- Phase 2: Create a consumer project that depends on everything ---\n await ctx.subTest('install all dependencies in consumer project', async () => {\n const consumerDeps: Record<string, string> = {};\n\n // Direct deps on all leaf packages\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n consumerDeps[`@verdaccio/seed-${id}-${i}`] = '1.0.0';\n }\n\n // Also depend on the intermediate (pulls in transitive deps)\n consumerDeps[`@verdaccio/seed-mid-${id}`] = '1.0.0';\n\n // And the shared package directly (already a transitive dep of mid)\n consumerDeps[`@verdaccio/seed-shared-${id}`] = '1.0.0';\n\n const consumerName = `@verdaccio/consumer-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n consumerDeps\n );\n\n projectCwd = tempFolder;\n\n debug('installing %d dependencies in consumer project', Object.keys(consumerDeps).length);\n\n const args = ['install', ...ctx.adapter.registryArg(ctx.registryUrl)];\n await ctx.adapter.exec({ cwd: tempFolder }, ...args);\n\n debug('install completed for consumer project');\n });\n\n // --- Phase 3: Verify all packages resolved correctly ---\n await ctx.subTest('verify installed packages', async () => {\n // Check that each seed package is retrievable via `info`\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n const name = `@verdaccio/seed-${id}-${i}`;\n const resp = await ctx.adapter.exec(\n { cwd: projectCwd },\n 'info',\n name,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const info = parseInfoOutput(resp.stdout, ctx.adapter.type);\n assert.strictEqual(info.name, name, `Expected package name \"${name}\"`);\n assert.strictEqual(info.version, '1.0.0', `Expected version 1.0.0 for ${name}`);\n }\n\n // Verify intermediate package has correct dependencies in registry metadata\n const midName = `@verdaccio/seed-mid-${id}`;\n const resp = await ctx.adapter.exec(\n { cwd: projectCwd },\n 'info',\n midName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const midInfo = parseInfoOutput(resp.stdout, ctx.adapter.type);\n assert.strictEqual(midInfo.name, midName);\n\n const deps = midInfo.dependencies || {};\n assert.strictEqual(\n deps[`@verdaccio/seed-${id}-1`],\n '1.0.0',\n 'Intermediate should depend on seed-1'\n );\n assert.strictEqual(\n deps[`@verdaccio/seed-${id}-2`],\n '1.0.0',\n 'Intermediate should depend on seed-2'\n );\n assert.strictEqual(\n deps[`@verdaccio/seed-shared-${id}`],\n '1.0.0',\n 'Intermediate should depend on shared'\n );\n\n debug('all packages verified');\n });\n\n // --- Phase 4: Publish updated versions and re-install ---\n await ctx.subTest('update and re-install', async () => {\n // Publish v2 of a leaf and the shared package\n const leafName = `@verdaccio/seed-${id}-1`;\n await publishSeedPackage(ctx, leafName, '2.0.0');\n\n const sharedName = `@verdaccio/seed-shared-${id}`;\n await publishSeedPackage(ctx, sharedName, '2.0.0');\n\n // Create a new consumer that uses ^ ranges — should pick up 2.0.0\n const consumerDeps: Record<string, string> = {\n [leafName]: '^1.0.0',\n [sharedName]: '^1.0.0',\n };\n\n const consumerName = `@verdaccio/consumer-update-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n consumerDeps\n );\n\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n // Verify that the registry now serves both versions\n const leafResp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'info',\n leafName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const leafInfo = parseInfoOutput(leafResp.stdout, ctx.adapter.type);\n\n // dist-tags.latest should be 2.0.0\n assert.strictEqual(\n leafInfo['dist-tags']?.latest ?? leafInfo.version,\n '2.0.0',\n `Expected latest version of ${leafName} to be 2.0.0`\n );\n\n debug('update and re-install verified');\n });\n}\n\nexport const installMultipleDepsScenario: TestDefinition = {\n name: 'scenario:install-multiple-deps',\n requires: ['publish', 'install', 'info'],\n run: testInstallMultipleDeps,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"install-multiple-deps.cjs","names":[],"sources":["../../../src/scenarios/install-multiple-deps.ts"],"sourcesContent":["import assert from 'assert';\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { normalizeInfo } from '../utils/info';\nimport { trace } from '../utils/process';\n\n/**\n * Scenario: install-multiple-deps\n *\n * Publishes several packages to the registry (some scoped, some unscoped,\n * some with inter-dependencies), then creates a consumer project that\n * depends on all of them and runs `install`.\n *\n * This exercises the registry under realistic load:\n * - many parallel tarball downloads\n * - metadata resolution for multiple packages\n * - scoped-package authentication\n * - transitive dependency resolution\n */\n\nconst SEED_PACKAGES_COUNT = 5;\n\n/**\n * Parse `info --json` output across all adapters.\n */\nfunction parseInfoOutput(stdout: string): any {\n return normalizeInfo(JSON.parse(stdout));\n}\n\nasync function publishSeedPackage(\n ctx: TestContext,\n pkgName: string,\n version: string,\n dependencies: Record<string, string> = {}\n): Promise<void> {\n trace('publishing seed package %s@%s', pkgName, version);\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n version,\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n dependencies\n );\n\n if (ctx.adapter.type === 'yarn-modern') {\n await ctx.adapter.exec({ cwd: tempFolder }, 'install');\n }\n\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n trace('published %s@%s', pkgName, version);\n}\n\nasync function testInstallMultipleDeps(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Shared project folder used as cwd for info commands across subtests.\n // Yarn modern requires a project context (package.json + .yarnrc.yml) for `yarn npm info`.\n let projectCwd = '';\n\n // --- Phase 1: Publish a tree of seed packages ---\n await ctx.subTest('publish seed packages', async () => {\n // Leaf packages (no dependencies of their own)\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n const name = `@verdaccio/seed-${id}-${i}`;\n await publishSeedPackage(ctx, name, '1.0.0');\n }\n\n // A \"shared\" package that multiple consumers will pull in\n const sharedPkg = `@verdaccio/seed-shared-${id}`;\n await publishSeedPackage(ctx, sharedPkg, '1.0.0');\n\n // An intermediate package that depends on some leaf packages + shared\n const intermediatePkg = `@verdaccio/seed-mid-${id}`;\n await publishSeedPackage(ctx, intermediatePkg, '1.0.0', {\n [`@verdaccio/seed-${id}-1`]: '1.0.0',\n [`@verdaccio/seed-${id}-2`]: '1.0.0',\n [sharedPkg]: '1.0.0',\n });\n\n trace('all seed packages published');\n });\n\n // --- Phase 2: Create a consumer project that depends on everything ---\n await ctx.subTest('install all dependencies in consumer project', async () => {\n const consumerDeps: Record<string, string> = {};\n\n // Direct deps on all leaf packages\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n consumerDeps[`@verdaccio/seed-${id}-${i}`] = '1.0.0';\n }\n\n // Also depend on the intermediate (pulls in transitive deps)\n consumerDeps[`@verdaccio/seed-mid-${id}`] = '1.0.0';\n\n // And the shared package directly (already a transitive dep of mid)\n consumerDeps[`@verdaccio/seed-shared-${id}`] = '1.0.0';\n\n const consumerName = `@verdaccio/consumer-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n consumerDeps\n );\n\n projectCwd = tempFolder;\n\n trace('installing %d dependencies in consumer project', Object.keys(consumerDeps).length);\n\n const args = ['install', ...ctx.adapter.registryArg(ctx.registryUrl)];\n await ctx.adapter.exec({ cwd: tempFolder }, ...args);\n\n trace('install completed for consumer project');\n });\n\n // --- Phase 3: Verify all packages resolved correctly ---\n await ctx.subTest('verify installed packages', async () => {\n // Check that each seed package is retrievable via `info`\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n const name = `@verdaccio/seed-${id}-${i}`;\n const resp = await ctx.adapter.exec(\n { cwd: projectCwd },\n 'info',\n name,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const info = parseInfoOutput(resp.stdout);\n assert.strictEqual(info.name, name, `Expected package name \"${name}\"`);\n assert.strictEqual(info.version, '1.0.0', `Expected version 1.0.0 for ${name}`);\n }\n\n // Verify intermediate package has correct dependencies in registry metadata\n const midName = `@verdaccio/seed-mid-${id}`;\n const resp = await ctx.adapter.exec(\n { cwd: projectCwd },\n 'info',\n midName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const midInfo = parseInfoOutput(resp.stdout);\n assert.strictEqual(midInfo.name, midName);\n\n const deps = midInfo.dependencies || {};\n assert.strictEqual(\n deps[`@verdaccio/seed-${id}-1`],\n '1.0.0',\n 'Intermediate should depend on seed-1'\n );\n assert.strictEqual(\n deps[`@verdaccio/seed-${id}-2`],\n '1.0.0',\n 'Intermediate should depend on seed-2'\n );\n assert.strictEqual(\n deps[`@verdaccio/seed-shared-${id}`],\n '1.0.0',\n 'Intermediate should depend on shared'\n );\n\n trace('all packages verified');\n });\n\n // --- Phase 4: Publish updated versions and re-install ---\n await ctx.subTest('update and re-install', async () => {\n // Publish v2 of a leaf and the shared package\n const leafName = `@verdaccio/seed-${id}-1`;\n await publishSeedPackage(ctx, leafName, '2.0.0');\n\n const sharedName = `@verdaccio/seed-shared-${id}`;\n await publishSeedPackage(ctx, sharedName, '2.0.0');\n\n // Create a new consumer that uses ^1.0.0 ranges. With 2.0.0 published,\n // the range must still resolve to 1.0.0 (^1.0.0 excludes 2.x) even though\n // dist-tags.latest now points at 2.0.0 — this catches registries that\n // serve range resolution from `latest` instead of the full version list.\n const consumerDeps: Record<string, string> = {\n [leafName]: '^1.0.0',\n [sharedName]: '^1.0.0',\n };\n\n const consumerName = `@verdaccio/consumer-update-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n consumerDeps\n );\n\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n // Verify what actually landed on disk, not just the registry metadata.\n // yarn-modern uses PnP (no node_modules), so the on-disk check applies to\n // the linkers that materialize it.\n if (['npm', 'pnpm', 'bun'].includes(ctx.adapter.type)) {\n for (const name of [leafName, sharedName]) {\n const manifestPath = join(tempFolder, 'node_modules', name, 'package.json');\n const installed = JSON.parse(await readFile(manifestPath, 'utf8'));\n trace('on disk: %s@%s (%s)', installed.name, installed.version, manifestPath);\n assert.strictEqual(\n installed.version,\n '1.0.0',\n `Expected ${name}@1.0.0 installed for range ^1.0.0 (latest is 2.0.0), ` +\n `got ${installed.version}`\n );\n }\n }\n\n // Verify that the registry now serves both versions\n const leafResp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'info',\n leafName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const leafInfo = parseInfoOutput(leafResp.stdout);\n trace(\n 'registry info for %s: version=%s dist-tags=%j',\n leafName,\n leafInfo.version,\n leafInfo['dist-tags']\n );\n\n // dist-tags.latest should be 2.0.0\n assert.strictEqual(\n leafInfo['dist-tags']?.latest ?? leafInfo.version,\n '2.0.0',\n `Expected latest version of ${leafName} to be 2.0.0`\n );\n\n trace('update and re-install verified');\n });\n}\n\nexport const installMultipleDepsScenario: TestDefinition = {\n name: 'scenario:install-multiple-deps',\n requires: ['publish', 'install', 'info'],\n run: testInstallMultipleDeps,\n};\n"],"mappings":"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"}