@verdaccio/e2e-cli 2.10.1 → 3.0.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 (164) hide show
  1. package/Cargo.lock +1591 -0
  2. package/Cargo.toml +19 -0
  3. package/bin/e2e-cli.js +26 -6
  4. package/build/bin/verdaccio-e2e +0 -0
  5. package/build/cjs/index.cjs +11 -166
  6. package/build/esm/index.js +10 -153
  7. package/build/index.d.ts +15 -6
  8. package/package.json +14 -16
  9. package/scripts/build-js-package.mjs +25 -0
  10. package/src/e2e_tests/audit.rs +51 -0
  11. package/src/e2e_tests/ci.rs +32 -0
  12. package/src/e2e_tests/deprecate.rs +64 -0
  13. package/src/e2e_tests/dist_tags.rs +56 -0
  14. package/src/e2e_tests/info.rs +43 -0
  15. package/src/e2e_tests/install.rs +27 -0
  16. package/src/e2e_tests/login.rs +64 -0
  17. package/src/e2e_tests/mod.rs +104 -0
  18. package/src/e2e_tests/ping.rs +33 -0
  19. package/src/e2e_tests/publish.rs +68 -0
  20. package/src/e2e_tests/search.rs +14 -0
  21. package/src/e2e_tests/unpublish.rs +37 -0
  22. package/src/main.rs +1411 -0
  23. package/src/scenarios/install_multiple_deps.rs +99 -0
  24. package/src/scenarios/minimum_release_age.rs +45 -0
  25. package/src/scenarios/mod.rs +11 -0
  26. package/build/adapters/adapter.d.ts +0 -1
  27. package/build/adapters/bun.d.ts +0 -2
  28. package/build/adapters/deno.d.ts +0 -2
  29. package/build/adapters/index.d.ts +0 -6
  30. package/build/adapters/npm.d.ts +0 -2
  31. package/build/adapters/pnpm.d.ts +0 -2
  32. package/build/adapters/yarn-classic.d.ts +0 -2
  33. package/build/adapters/yarn-modern.d.ts +0 -2
  34. package/build/cjs/_virtual/_rolldown/runtime.cjs +0 -23
  35. package/build/cjs/adapters/bun.cjs +0 -63
  36. package/build/cjs/adapters/bun.cjs.map +0 -1
  37. package/build/cjs/adapters/deno.cjs +0 -58
  38. package/build/cjs/adapters/deno.cjs.map +0 -1
  39. package/build/cjs/adapters/index.cjs +0 -6
  40. package/build/cjs/adapters/npm.cjs +0 -75
  41. package/build/cjs/adapters/npm.cjs.map +0 -1
  42. package/build/cjs/adapters/pnpm.cjs +0 -104
  43. package/build/cjs/adapters/pnpm.cjs.map +0 -1
  44. package/build/cjs/adapters/yarn-classic.cjs +0 -98
  45. package/build/cjs/adapters/yarn-classic.cjs.map +0 -1
  46. package/build/cjs/adapters/yarn-modern.cjs +0 -206
  47. package/build/cjs/adapters/yarn-modern.cjs.map +0 -1
  48. package/build/cjs/index.cjs.map +0 -1
  49. package/build/cjs/reporter.cjs +0 -113
  50. package/build/cjs/reporter.cjs.map +0 -1
  51. package/build/cjs/runner.cjs +0 -141
  52. package/build/cjs/runner.cjs.map +0 -1
  53. package/build/cjs/scenarios/index.cjs +0 -8
  54. package/build/cjs/scenarios/index.cjs.map +0 -1
  55. package/build/cjs/scenarios/install-multiple-deps.cjs +0 -116
  56. package/build/cjs/scenarios/install-multiple-deps.cjs.map +0 -1
  57. package/build/cjs/scenarios/minimum-release-age.cjs +0 -112
  58. package/build/cjs/scenarios/minimum-release-age.cjs.map +0 -1
  59. package/build/cjs/tests/audit.cjs +0 -47
  60. package/build/cjs/tests/audit.cjs.map +0 -1
  61. package/build/cjs/tests/ci.cjs +0 -83
  62. package/build/cjs/tests/ci.cjs.map +0 -1
  63. package/build/cjs/tests/deprecate.cjs +0 -107
  64. package/build/cjs/tests/deprecate.cjs.map +0 -1
  65. package/build/cjs/tests/dist-tags.cjs +0 -43
  66. package/build/cjs/tests/dist-tags.cjs.map +0 -1
  67. package/build/cjs/tests/index.cjs +0 -33
  68. package/build/cjs/tests/index.cjs.map +0 -1
  69. package/build/cjs/tests/info.cjs +0 -41
  70. package/build/cjs/tests/info.cjs.map +0 -1
  71. package/build/cjs/tests/install.cjs +0 -27
  72. package/build/cjs/tests/install.cjs.map +0 -1
  73. package/build/cjs/tests/login.cjs +0 -117
  74. package/build/cjs/tests/login.cjs.map +0 -1
  75. package/build/cjs/tests/ping.cjs +0 -30
  76. package/build/cjs/tests/ping.cjs.map +0 -1
  77. package/build/cjs/tests/publish.cjs +0 -37
  78. package/build/cjs/tests/publish.cjs.map +0 -1
  79. package/build/cjs/tests/search.cjs +0 -19
  80. package/build/cjs/tests/search.cjs.map +0 -1
  81. package/build/cjs/tests/unpublish.cjs +0 -40
  82. package/build/cjs/tests/unpublish.cjs.map +0 -1
  83. package/build/cjs/utils/process.cjs +0 -85
  84. package/build/cjs/utils/process.cjs.map +0 -1
  85. package/build/cjs/utils/project.cjs +0 -55
  86. package/build/cjs/utils/project.cjs.map +0 -1
  87. package/build/cjs/utils/registry-client.cjs +0 -56
  88. package/build/cjs/utils/registry-client.cjs.map +0 -1
  89. package/build/esm/adapters/bun.js +0 -61
  90. package/build/esm/adapters/bun.js.map +0 -1
  91. package/build/esm/adapters/deno.js +0 -56
  92. package/build/esm/adapters/deno.js.map +0 -1
  93. package/build/esm/adapters/index.js +0 -7
  94. package/build/esm/adapters/npm.js +0 -73
  95. package/build/esm/adapters/npm.js.map +0 -1
  96. package/build/esm/adapters/pnpm.js +0 -102
  97. package/build/esm/adapters/pnpm.js.map +0 -1
  98. package/build/esm/adapters/yarn-classic.js +0 -96
  99. package/build/esm/adapters/yarn-classic.js.map +0 -1
  100. package/build/esm/adapters/yarn-modern.js +0 -203
  101. package/build/esm/adapters/yarn-modern.js.map +0 -1
  102. package/build/esm/index.js.map +0 -1
  103. package/build/esm/reporter.js +0 -107
  104. package/build/esm/reporter.js.map +0 -1
  105. package/build/esm/runner.js +0 -138
  106. package/build/esm/runner.js.map +0 -1
  107. package/build/esm/scenarios/index.js +0 -8
  108. package/build/esm/scenarios/index.js.map +0 -1
  109. package/build/esm/scenarios/install-multiple-deps.js +0 -113
  110. package/build/esm/scenarios/install-multiple-deps.js.map +0 -1
  111. package/build/esm/scenarios/minimum-release-age.js +0 -109
  112. package/build/esm/scenarios/minimum-release-age.js.map +0 -1
  113. package/build/esm/tests/audit.js +0 -44
  114. package/build/esm/tests/audit.js.map +0 -1
  115. package/build/esm/tests/ci.js +0 -80
  116. package/build/esm/tests/ci.js.map +0 -1
  117. package/build/esm/tests/deprecate.js +0 -104
  118. package/build/esm/tests/deprecate.js.map +0 -1
  119. package/build/esm/tests/dist-tags.js +0 -41
  120. package/build/esm/tests/dist-tags.js.map +0 -1
  121. package/build/esm/tests/index.js +0 -33
  122. package/build/esm/tests/index.js.map +0 -1
  123. package/build/esm/tests/info.js +0 -39
  124. package/build/esm/tests/info.js.map +0 -1
  125. package/build/esm/tests/install.js +0 -25
  126. package/build/esm/tests/install.js.map +0 -1
  127. package/build/esm/tests/login.js +0 -113
  128. package/build/esm/tests/login.js.map +0 -1
  129. package/build/esm/tests/ping.js +0 -28
  130. package/build/esm/tests/ping.js.map +0 -1
  131. package/build/esm/tests/publish.js +0 -35
  132. package/build/esm/tests/publish.js.map +0 -1
  133. package/build/esm/tests/search.js +0 -17
  134. package/build/esm/tests/search.js.map +0 -1
  135. package/build/esm/tests/unpublish.js +0 -38
  136. package/build/esm/tests/unpublish.js.map +0 -1
  137. package/build/esm/utils/process.js +0 -82
  138. package/build/esm/utils/process.js.map +0 -1
  139. package/build/esm/utils/project.js +0 -50
  140. package/build/esm/utils/project.js.map +0 -1
  141. package/build/esm/utils/registry-client.js +0 -53
  142. package/build/esm/utils/registry-client.js.map +0 -1
  143. package/build/reporter.d.ts +0 -7
  144. package/build/runner.d.ts +0 -13
  145. package/build/scenarios/index.d.ts +0 -5
  146. package/build/scenarios/install-multiple-deps.d.ts +0 -2
  147. package/build/scenarios/minimum-release-age.d.ts +0 -11
  148. package/build/tests/audit.d.ts +0 -2
  149. package/build/tests/ci.d.ts +0 -2
  150. package/build/tests/deprecate.d.ts +0 -2
  151. package/build/tests/dist-tags.d.ts +0 -2
  152. package/build/tests/index.d.ts +0 -15
  153. package/build/tests/info.d.ts +0 -2
  154. package/build/tests/install.d.ts +0 -2
  155. package/build/tests/login.d.ts +0 -2
  156. package/build/tests/ping.d.ts +0 -2
  157. package/build/tests/publish.d.ts +0 -2
  158. package/build/tests/search.d.ts +0 -2
  159. package/build/tests/unpublish.d.ts +0 -2
  160. package/build/types.d.ts +0 -81
  161. package/build/utils/index.d.ts +0 -3
  162. package/build/utils/process.d.ts +0 -4
  163. package/build/utils/project.d.ts +0 -6
  164. package/build/utils/registry-client.d.ts +0 -15
package/Cargo.toml ADDED
@@ -0,0 +1,19 @@
1
+ [package]
2
+ name = "verdaccio-e2e-cli"
3
+ version = "2.10.2"
4
+ edition = "2021"
5
+ license = "MIT"
6
+
7
+ [[bin]]
8
+ name = "verdaccio-e2e"
9
+ path = "src/main.rs"
10
+
11
+ [dependencies]
12
+ anyhow = "1.0.100"
13
+ clap = { version = "4.5.53", features = ["derive"] }
14
+ reqwest = { version = "0.12.26", features = ["blocking", "json"] }
15
+ serde = { version = "1.0.228", features = ["derive"] }
16
+ serde_json = "1.0.147"
17
+ serde_yaml = "0.9.34"
18
+ tempfile = "3.23.0"
19
+ url = "2.5.8"
package/bin/e2e-cli.js CHANGED
@@ -1,8 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import('../build/esm/index.js')
4
- .then((mod) => mod.main())
5
- .catch((err) => {
6
- console.error(err);
7
- process.exit(1);
8
- });
3
+ import { spawnSync } from 'node:child_process';
4
+ import { existsSync } from 'node:fs';
5
+ import { dirname, resolve } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const here = dirname(fileURLToPath(import.meta.url));
9
+ const binaryName = process.platform === 'win32' ? 'verdaccio-e2e.exe' : 'verdaccio-e2e';
10
+ const packaged = resolve(here, '..', 'build', 'bin', binaryName);
11
+ const localRelease = resolve(here, '..', 'target', 'release', binaryName);
12
+ const binary = existsSync(packaged) ? packaged : localRelease;
13
+
14
+ if (!existsSync(binary)) {
15
+ console.error(
16
+ 'verdaccio-e2e binary not found. Run "pnpm --filter @verdaccio/e2e-cli build" first.'
17
+ );
18
+ process.exit(1);
19
+ }
20
+
21
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' });
22
+
23
+ if (result.error) {
24
+ console.error(result.error);
25
+ process.exit(1);
26
+ }
27
+
28
+ process.exit(result.status ?? 1);
Binary file
@@ -1,166 +1,11 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
3
- const require_bun = require("./adapters/bun.cjs");
4
- const require_deno = require("./adapters/deno.cjs");
5
- const require_npm = require("./adapters/npm.cjs");
6
- const require_pnpm = require("./adapters/pnpm.cjs");
7
- const require_yarn_classic = require("./adapters/yarn-classic.cjs");
8
- const require_yarn_modern = require("./adapters/yarn-modern.cjs");
9
- require("./adapters/index.cjs");
10
- const require_runner = require("./runner.cjs");
11
- const require_index$1 = require("./scenarios/index.cjs");
12
- const require_index$2 = require("./tests/index.cjs");
13
- const require_registry_client = require("./utils/registry-client.cjs");
14
- let debug = require("debug");
15
- debug = require_runtime.__toESM(debug, 1);
16
- //#region src/index.ts
17
- (0, debug.default)("verdaccio:e2e-cli");
18
- function parsePmSpec(filter) {
19
- const eqIdx = filter.indexOf("=");
20
- if (eqIdx !== -1) return {
21
- name: filter.slice(0, eqIdx).toLowerCase(),
22
- binPath: filter.slice(eqIdx + 1)
23
- };
24
- const atIdx = filter.indexOf("@");
25
- if (atIdx !== -1) return {
26
- name: filter.slice(0, atIdx).toLowerCase(),
27
- version: filter.slice(atIdx + 1)
28
- };
29
- return { name: filter.toLowerCase() };
30
- }
31
- function parseAdapters(pmFilters) {
32
- if (!pmFilters || pmFilters.length === 0) return [require_npm.createNpmAdapter()];
33
- const adapters = [];
34
- for (const filter of pmFilters) {
35
- const { name, version, binPath } = parsePmSpec(filter);
36
- if (name === "npm") adapters.push(require_npm.createNpmAdapter(binPath, version));
37
- 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));
39
- else if (name === "yarn-modern" || name === "yarn") adapters.push(require_yarn_modern.createYarnModernAdapter(binPath, version));
40
- else if (name === "bun") adapters.push(require_bun.createBunAdapter(binPath, version));
41
- 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`);
43
- }
44
- return adapters;
45
- }
46
- function parseArgs(argv) {
47
- const options = {
48
- registry: "",
49
- pm: [],
50
- test: [],
51
- concurrency: 1,
52
- timeout: 5e4,
53
- verbose: false
54
- };
55
- for (let i = 2; i < argv.length; i++) {
56
- const arg = argv[i];
57
- if (arg === "--registry" || arg === "-r") options.registry = argv[++i];
58
- else if (arg === "--pm") options.pm.push(argv[++i]);
59
- else if (arg === "--test" || arg === "-t") options.test.push(argv[++i]);
60
- else if (arg === "--concurrency" || arg === "-c") options.concurrency = parseInt(argv[++i], 10);
61
- else if (arg === "--timeout") options.timeout = parseInt(argv[++i], 10);
62
- else if (arg === "--token") options.token = argv[++i];
63
- else if (arg === "--verbose" || arg === "-v") options.verbose = true;
64
- else if (arg === "--help" || arg === "-h") {
65
- printHelp();
66
- process.exit(0);
67
- } else if (arg.startsWith("--registry=")) options.registry = arg.split("=")[1];
68
- else if (arg.startsWith("--pm=")) options.pm.push(arg.split("=")[1]);
69
- else if (arg.startsWith("--test=")) options.test.push(arg.split("=")[1]);
70
- else if (arg.startsWith("--token=")) options.token = arg.split("=")[1];
71
- else if (arg.startsWith("--timeout=")) options.timeout = parseInt(arg.split("=")[1], 10);
72
- else {
73
- console.error(`Unknown argument: ${arg}`);
74
- printHelp();
75
- process.exit(1);
76
- }
77
- }
78
- return options;
79
- }
80
- function printHelp() {
81
- console.log(`
82
- @verdaccio/e2e-cli - Run Verdaccio e2e tests against any running registry
83
-
84
- Usage:
85
- verdaccio-e2e --registry <url> [options]
86
-
87
- Required:
88
- -r, --registry <url> Verdaccio registry URL (e.g. http://localhost:4873)
89
-
90
- Options:
91
- --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
- --pm yarn-modern@4
95
- --pm yarn-modern@3
96
- --pm yarn-classic
97
- --pm bun
98
- --pm npm --pm pnpm (uses system version)
99
- Auto-installs the requested yarn version if needed
100
- Default: npm
101
-
102
- -t, --test <name> Filter tests by name (can be repeated)
103
- Available: publish, install, ci, audit, info, deprecate,
104
- dist-tags, ping, search, unpublish
105
- Scenarios: scenario:install-multiple-deps,
106
- scenario:minimum-release-age (pnpm 11.1+)
107
- Default: all supported by the PM
108
-
109
- --token <token> Auth token (skips user creation)
110
- --timeout <ms> Per-test timeout (default: 50000)
111
- -v, --verbose Enable debug output
112
- -h, --help Show this help
113
- `);
114
- }
115
- async function main(argv = process.argv) {
116
- const options = parseArgs(argv);
117
- if (!options.registry) {
118
- console.error("Error: --registry is required\n");
119
- printHelp();
120
- process.exit(1);
121
- }
122
- const { createTempFolder } = await Promise.resolve().then(() => require("./utils/project.cjs"));
123
- const runDir = await createTempFolder("e2e-run");
124
- process.chdir(runDir);
125
- if (options.verbose) {
126
- const { setVerbose } = await Promise.resolve().then(() => require("./utils/process.cjs"));
127
- setVerbose(true);
128
- }
129
- console.log(`Checking registry at ${options.registry}...`);
130
- if (!await require_registry_client.pingRegistry(options.registry)) {
131
- console.error(`Error: Registry at ${options.registry} is not reachable`);
132
- process.exit(1);
133
- }
134
- console.log(`Registry is alive.`);
135
- let token = options.token;
136
- if (!token) {
137
- console.log("Creating test user...");
138
- const auth = await require_registry_client.createUser(options.registry);
139
- token = auth.token;
140
- console.log(`User "${auth.user}" created.`);
141
- }
142
- const adapters = parseAdapters(options.pm);
143
- console.log(`Adapters: ${adapters.map((a) => a.name).join(", ")}`);
144
- const tests = options.test && options.test.length > 0 ? require_index$2.allTests.filter((t) => options.test.includes(t.name)) : require_index$2.allTests;
145
- console.log(`Tests: ${tests.map((t) => t.name).join(", ")}`);
146
- const { exitCode } = await require_runner.runAll(adapters, tests, options.registry, token, {
147
- timeout: options.timeout,
148
- concurrency: options.concurrency,
149
- testFilter: options.test
150
- });
151
- process.exit(exitCode);
152
- }
153
- //#endregion
154
- exports.allScenarios = require_index$1.allScenarios;
155
- exports.allTests = require_index$2.allTests;
156
- exports.createBunAdapter = require_bun.createBunAdapter;
157
- exports.createDenoAdapter = require_deno.createDenoAdapter;
158
- exports.createNpmAdapter = require_npm.createNpmAdapter;
159
- exports.createPnpmAdapter = require_pnpm.createPnpmAdapter;
160
- exports.createYarnClassicAdapter = require_yarn_classic.createYarnClassicAdapter;
161
- exports.createYarnModernAdapter = require_yarn_modern.createYarnModernAdapter;
162
- exports.main = main;
163
- exports.runAll = require_runner.runAll;
164
- exports.runSuite = require_runner.runSuite;
165
-
166
- //# sourceMappingURL=index.cjs.map
1
+ function unavailable() { throw new Error('@verdaccio/e2e-cli programmatic API is no longer available in the Rust build. Use the verdaccio-e2e binary.'); }
2
+ exports.allTests = [];
3
+ exports.allScenarios = [];
4
+ exports.runAll = unavailable;
5
+ exports.runSuite = unavailable;
6
+ exports.createNpmAdapter = unavailable;
7
+ exports.createPnpmAdapter = unavailable;
8
+ exports.createYarnClassicAdapter = unavailable;
9
+ exports.createYarnModernAdapter = unavailable;
10
+ exports.createBunAdapter = unavailable;
11
+ exports.createDenoAdapter = unavailable;
@@ -1,153 +1,10 @@
1
- import { createBunAdapter } from "./adapters/bun.js";
2
- import { createDenoAdapter } from "./adapters/deno.js";
3
- import { createNpmAdapter } from "./adapters/npm.js";
4
- import { createPnpmAdapter } from "./adapters/pnpm.js";
5
- import { createYarnClassicAdapter } from "./adapters/yarn-classic.js";
6
- import { createYarnModernAdapter } from "./adapters/yarn-modern.js";
7
- import "./adapters/index.js";
8
- import { runAll, runSuite } from "./runner.js";
9
- import { allScenarios } from "./scenarios/index.js";
10
- import { allTests } from "./tests/index.js";
11
- import { createUser, pingRegistry } from "./utils/registry-client.js";
12
- import buildDebug from "debug";
13
- //#region src/index.ts
14
- buildDebug("verdaccio:e2e-cli");
15
- function parsePmSpec(filter) {
16
- const eqIdx = filter.indexOf("=");
17
- if (eqIdx !== -1) return {
18
- name: filter.slice(0, eqIdx).toLowerCase(),
19
- binPath: filter.slice(eqIdx + 1)
20
- };
21
- const atIdx = filter.indexOf("@");
22
- if (atIdx !== -1) return {
23
- name: filter.slice(0, atIdx).toLowerCase(),
24
- version: filter.slice(atIdx + 1)
25
- };
26
- return { name: filter.toLowerCase() };
27
- }
28
- function parseAdapters(pmFilters) {
29
- if (!pmFilters || pmFilters.length === 0) return [createNpmAdapter()];
30
- const adapters = [];
31
- for (const filter of pmFilters) {
32
- const { name, version, binPath } = parsePmSpec(filter);
33
- if (name === "npm") adapters.push(createNpmAdapter(binPath, version));
34
- else if (name === "pnpm") adapters.push(createPnpmAdapter(binPath, version));
35
- else if (name === "yarn-classic" || name === "yarn1") adapters.push(createYarnClassicAdapter(binPath, version));
36
- else if (name === "yarn-modern" || name === "yarn") adapters.push(createYarnModernAdapter(binPath, version));
37
- else if (name === "bun") adapters.push(createBunAdapter(binPath, version));
38
- else if (name === "deno") adapters.push(createDenoAdapter(binPath, version));
39
- else throw new Error(`Unknown package manager: "${name}". Supported: npm, pnpm, yarn-classic, yarn-modern, bun, deno`);
40
- }
41
- return adapters;
42
- }
43
- function parseArgs(argv) {
44
- const options = {
45
- registry: "",
46
- pm: [],
47
- test: [],
48
- concurrency: 1,
49
- timeout: 5e4,
50
- verbose: false
51
- };
52
- for (let i = 2; i < argv.length; i++) {
53
- const arg = argv[i];
54
- if (arg === "--registry" || arg === "-r") options.registry = argv[++i];
55
- else if (arg === "--pm") options.pm.push(argv[++i]);
56
- else if (arg === "--test" || arg === "-t") options.test.push(argv[++i]);
57
- else if (arg === "--concurrency" || arg === "-c") options.concurrency = parseInt(argv[++i], 10);
58
- else if (arg === "--timeout") options.timeout = parseInt(argv[++i], 10);
59
- else if (arg === "--token") options.token = argv[++i];
60
- else if (arg === "--verbose" || arg === "-v") options.verbose = true;
61
- else if (arg === "--help" || arg === "-h") {
62
- printHelp();
63
- process.exit(0);
64
- } else if (arg.startsWith("--registry=")) options.registry = arg.split("=")[1];
65
- else if (arg.startsWith("--pm=")) options.pm.push(arg.split("=")[1]);
66
- else if (arg.startsWith("--test=")) options.test.push(arg.split("=")[1]);
67
- else if (arg.startsWith("--token=")) options.token = arg.split("=")[1];
68
- else if (arg.startsWith("--timeout=")) options.timeout = parseInt(arg.split("=")[1], 10);
69
- else {
70
- console.error(`Unknown argument: ${arg}`);
71
- printHelp();
72
- process.exit(1);
73
- }
74
- }
75
- return options;
76
- }
77
- function printHelp() {
78
- console.log(`
79
- @verdaccio/e2e-cli - Run Verdaccio e2e tests against any running registry
80
-
81
- Usage:
82
- verdaccio-e2e --registry <url> [options]
83
-
84
- Required:
85
- -r, --registry <url> Verdaccio registry URL (e.g. http://localhost:4873)
86
-
87
- Options:
88
- --pm <name[@version]> Package manager to test (can be repeated)
89
- Supported: npm, pnpm, yarn-classic, yarn-modern (or yarn), bun, deno
90
- Examples: --pm npm@10 --pm pnpm@9
91
- --pm yarn-modern@4
92
- --pm yarn-modern@3
93
- --pm yarn-classic
94
- --pm bun
95
- --pm npm --pm pnpm (uses system version)
96
- Auto-installs the requested yarn version if needed
97
- Default: npm
98
-
99
- -t, --test <name> Filter tests by name (can be repeated)
100
- Available: publish, install, ci, audit, info, deprecate,
101
- dist-tags, ping, search, unpublish
102
- Scenarios: scenario:install-multiple-deps,
103
- scenario:minimum-release-age (pnpm 11.1+)
104
- Default: all supported by the PM
105
-
106
- --token <token> Auth token (skips user creation)
107
- --timeout <ms> Per-test timeout (default: 50000)
108
- -v, --verbose Enable debug output
109
- -h, --help Show this help
110
- `);
111
- }
112
- async function main(argv = process.argv) {
113
- const options = parseArgs(argv);
114
- if (!options.registry) {
115
- console.error("Error: --registry is required\n");
116
- printHelp();
117
- process.exit(1);
118
- }
119
- const { createTempFolder } = await import("./utils/project.js");
120
- const runDir = await createTempFolder("e2e-run");
121
- process.chdir(runDir);
122
- if (options.verbose) {
123
- const { setVerbose } = await import("./utils/process.js");
124
- setVerbose(true);
125
- }
126
- console.log(`Checking registry at ${options.registry}...`);
127
- if (!await pingRegistry(options.registry)) {
128
- console.error(`Error: Registry at ${options.registry} is not reachable`);
129
- process.exit(1);
130
- }
131
- console.log(`Registry is alive.`);
132
- let token = options.token;
133
- if (!token) {
134
- console.log("Creating test user...");
135
- const auth = await createUser(options.registry);
136
- token = auth.token;
137
- console.log(`User "${auth.user}" created.`);
138
- }
139
- const adapters = parseAdapters(options.pm);
140
- console.log(`Adapters: ${adapters.map((a) => a.name).join(", ")}`);
141
- const tests = options.test && options.test.length > 0 ? allTests.filter((t) => options.test.includes(t.name)) : allTests;
142
- console.log(`Tests: ${tests.map((t) => t.name).join(", ")}`);
143
- const { exitCode } = await runAll(adapters, tests, options.registry, token, {
144
- timeout: options.timeout,
145
- concurrency: options.concurrency,
146
- testFilter: options.test
147
- });
148
- process.exit(exitCode);
149
- }
150
- //#endregion
151
- export { allScenarios, allTests, createBunAdapter, createDenoAdapter, createNpmAdapter, createPnpmAdapter, createYarnClassicAdapter, createYarnModernAdapter, main, runAll, runSuite };
152
-
153
- //# sourceMappingURL=index.js.map
1
+ export const allTests = [];
2
+ export const allScenarios = [];
3
+ export function runAll() { throw new Error('@verdaccio/e2e-cli programmatic API is no longer available in the Rust build. Use the verdaccio-e2e binary.'); }
4
+ export function runSuite() { throw new Error('@verdaccio/e2e-cli programmatic API is no longer available in the Rust build. Use the verdaccio-e2e binary.'); }
5
+ export function createNpmAdapter() { throw new Error('@verdaccio/e2e-cli adapters are implemented in Rust. Use the verdaccio-e2e binary.'); }
6
+ export const createPnpmAdapter = createNpmAdapter;
7
+ export const createYarnClassicAdapter = createNpmAdapter;
8
+ export const createYarnModernAdapter = createNpmAdapter;
9
+ export const createBunAdapter = createNpmAdapter;
10
+ export const createDenoAdapter = createNpmAdapter;
package/build/index.d.ts CHANGED
@@ -1,6 +1,15 @@
1
- export declare function main(argv?: string[]): Promise<void>;
2
- export { allTests } from './tests';
3
- export { allScenarios } from './scenarios';
4
- export { createBunAdapter, createDenoAdapter, createNpmAdapter, createPnpmAdapter, createYarnClassicAdapter, createYarnModernAdapter, } from './adapters';
5
- export { runAll, runSuite } from './runner';
6
- export type { PackageManagerAdapter, TestDefinition, TestContext, CliOptions } from './types';
1
+ export type ExecOutput = { stdout: string; stderr: string };
2
+ export type PackageManagerAdapter = unknown;
3
+ export type TestDefinition = unknown;
4
+ export type TestContext = unknown;
5
+ export type CliOptions = unknown;
6
+ export const allTests: TestDefinition[];
7
+ export const allScenarios: TestDefinition[];
8
+ export function runAll(...args: unknown[]): never;
9
+ export function runSuite(...args: unknown[]): never;
10
+ export function createNpmAdapter(...args: unknown[]): never;
11
+ export function createPnpmAdapter(...args: unknown[]): never;
12
+ export function createYarnClassicAdapter(...args: unknown[]): never;
13
+ export function createYarnModernAdapter(...args: unknown[]): never;
14
+ export function createBunAdapter(...args: unknown[]): never;
15
+ export function createDenoAdapter(...args: unknown[]): never;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/e2e-cli",
3
- "version": "2.10.1",
3
+ "version": "3.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "CLI tool to run Verdaccio e2e tests against any running registry",
@@ -11,7 +11,11 @@
11
11
  },
12
12
  "files": [
13
13
  "build",
14
- "bin"
14
+ "bin",
15
+ "Cargo.lock",
16
+ "Cargo.toml",
17
+ "scripts",
18
+ "src"
15
19
  ],
16
20
  "bin": {
17
21
  "verdaccio-e2e": "./bin/e2e-cli.js"
@@ -26,20 +30,14 @@
26
30
  "types": "./build/index.d.ts"
27
31
  }
28
32
  },
29
- "dependencies": {
30
- "@verdaccio/registry-cli": "^1.1.0",
31
- "debug": "4.4.0",
32
- "get-port": "5.1.1",
33
- "js-yaml": "4.1.1"
34
- },
35
- "devDependencies": {
36
- "@types/debug": "4.1.12",
37
- "@types/js-yaml": "4.0.9",
38
- "@types/node": "24.12.4",
39
- "vite": "8.0.11"
40
- },
33
+ "dependencies": {},
34
+ "devDependencies": {},
41
35
  "scripts": {
42
- "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.build.json",
43
- "clean": "rimraf build"
36
+ "build": "cargo build --release && node scripts/build-js-package.mjs",
37
+ "postinstall": "cargo build --release && node scripts/build-js-package.mjs",
38
+ "clean": "rimraf build target",
39
+ "fmt:check": "cargo fmt -- --check",
40
+ "clippy": "cargo clippy --all-targets -- -D warnings",
41
+ "docs": "cargo doc --no-deps"
44
42
  }
45
43
  }
@@ -0,0 +1,25 @@
1
+ import { chmodSync, copyFileSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
6
+ const binaryName = process.platform === 'win32' ? 'verdaccio-e2e.exe' : 'verdaccio-e2e';
7
+ const binarySource = resolve(root, 'target', 'release', binaryName);
8
+ const binaryDest = resolve(root, 'build', 'bin', binaryName);
9
+
10
+ rmSync(resolve(root, 'build'), { recursive: true, force: true });
11
+ mkdirSync(dirname(binaryDest), { recursive: true });
12
+ copyFileSync(binarySource, binaryDest);
13
+ if (process.platform !== 'win32') {
14
+ chmodSync(binaryDest, 0o755);
15
+ }
16
+
17
+ const esm = `export const allTests = [];\nexport const allScenarios = [];\nexport function runAll() { throw new Error('@verdaccio/e2e-cli programmatic API is no longer available in the Rust build. Use the verdaccio-e2e binary.'); }\nexport function runSuite() { throw new Error('@verdaccio/e2e-cli programmatic API is no longer available in the Rust build. Use the verdaccio-e2e binary.'); }\nexport function createNpmAdapter() { throw new Error('@verdaccio/e2e-cli adapters are implemented in Rust. Use the verdaccio-e2e binary.'); }\nexport const createPnpmAdapter = createNpmAdapter;\nexport const createYarnClassicAdapter = createNpmAdapter;\nexport const createYarnModernAdapter = createNpmAdapter;\nexport const createBunAdapter = createNpmAdapter;\nexport const createDenoAdapter = createNpmAdapter;\n`;
18
+ const cjs = `function unavailable() { throw new Error('@verdaccio/e2e-cli programmatic API is no longer available in the Rust build. Use the verdaccio-e2e binary.'); }\nexports.allTests = [];\nexports.allScenarios = [];\nexports.runAll = unavailable;\nexports.runSuite = unavailable;\nexports.createNpmAdapter = unavailable;\nexports.createPnpmAdapter = unavailable;\nexports.createYarnClassicAdapter = unavailable;\nexports.createYarnModernAdapter = unavailable;\nexports.createBunAdapter = unavailable;\nexports.createDenoAdapter = unavailable;\n`;
19
+ const dts = `export type ExecOutput = { stdout: string; stderr: string };\nexport type PackageManagerAdapter = unknown;\nexport type TestDefinition = unknown;\nexport type TestContext = unknown;\nexport type CliOptions = unknown;\nexport const allTests: TestDefinition[];\nexport const allScenarios: TestDefinition[];\nexport function runAll(...args: unknown[]): never;\nexport function runSuite(...args: unknown[]): never;\nexport function createNpmAdapter(...args: unknown[]): never;\nexport function createPnpmAdapter(...args: unknown[]): never;\nexport function createYarnClassicAdapter(...args: unknown[]): never;\nexport function createYarnModernAdapter(...args: unknown[]): never;\nexport function createBunAdapter(...args: unknown[]): never;\nexport function createDenoAdapter(...args: unknown[]): never;\n`;
20
+
21
+ mkdirSync(resolve(root, 'build', 'esm'), { recursive: true });
22
+ mkdirSync(resolve(root, 'build', 'cjs'), { recursive: true });
23
+ writeFileSync(resolve(root, 'build', 'esm', 'index.js'), esm);
24
+ writeFileSync(resolve(root, 'build', 'cjs', 'index.cjs'), cjs);
25
+ writeFileSync(resolve(root, 'build', 'index.d.ts'), dts);
@@ -0,0 +1,51 @@
1
+ use super::prelude::*;
2
+
3
+ pub(crate) fn test_audit(ctx: &mut TestContext<'_>) -> Result<()> {
4
+ if !matches!(ctx.adapter.kind, AdapterType::Npm | AdapterType::Bun) {
5
+ return Ok(());
6
+ }
7
+ for pkg_name in [
8
+ format!("verdaccio-audit-{}", ctx.run_id),
9
+ format!("@verdaccio/audit-{}", ctx.run_id),
10
+ ] {
11
+ let mut deps = BTreeMap::new();
12
+ deps.insert("jquery".into(), "3.6.1".into());
13
+ let temp = prepare_project(ctx, &pkg_name, "1.0.0", deps, BTreeMap::new())?;
14
+ let mut install = vec!["install".into()];
15
+ install.extend(registry_arg(&ctx.adapter, &ctx.registry_url));
16
+ exec_adapter(ctx, Some(&temp), install)?;
17
+ let probe = Client::new()
18
+ .post(format!(
19
+ "{}/-/npm/v1/security/audits/quick",
20
+ ctx.registry_url
21
+ ))
22
+ .header("Content-Type", "application/json")
23
+ .body("{}")
24
+ .send();
25
+ match probe {
26
+ Ok(resp) if resp.status().as_u16() == 404 => return Ok(()),
27
+ Err(_) => return Ok(()),
28
+ _ => {}
29
+ }
30
+ let mut args = vec!["audit".into(), "--json".into()];
31
+ args.extend(registry_arg(&ctx.adapter, &ctx.registry_url));
32
+ let resp = exec_adapter(ctx, Some(&temp), args)?;
33
+ if ctx.adapter.kind == AdapterType::Bun {
34
+ assert_true(
35
+ !resp.stdout.is_empty() || !resp.stderr.is_empty(),
36
+ "Expected audit output",
37
+ )?;
38
+ } else {
39
+ let parsed: Value = serde_json::from_str(&resp.stdout)?;
40
+ assert_true(
41
+ parsed.get("auditReportVersion").is_some(),
42
+ "Expected auditReportVersion",
43
+ )?;
44
+ assert_true(
45
+ parsed.get("vulnerabilities").is_some(),
46
+ "Expected vulnerabilities",
47
+ )?;
48
+ }
49
+ }
50
+ Ok(())
51
+ }
@@ -0,0 +1,32 @@
1
+ use super::prelude::*;
2
+
3
+ pub(crate) fn test_ci(ctx: &mut TestContext<'_>) -> Result<()> {
4
+ if ctx.adapter.kind == AdapterType::Deno {
5
+ return Ok(());
6
+ }
7
+ let mut deps = BTreeMap::new();
8
+ deps.insert("is-odd".into(), "1.0.0".into());
9
+ let temp = prepare_project(
10
+ ctx,
11
+ &format!("ci-test-{}", ctx.run_id),
12
+ "1.0.0",
13
+ deps,
14
+ BTreeMap::new(),
15
+ )?;
16
+ let mut install = vec!["install".into()];
17
+ install.extend(registry_arg(&ctx.adapter, &ctx.registry_url));
18
+ exec_adapter(ctx, Some(&temp), install)?;
19
+ let _ = fs::remove_dir_all(temp.join("node_modules"));
20
+ let _ = fs::remove_dir_all(temp.join(".pnpm-store"));
21
+ let mut args = match ctx.adapter.kind {
22
+ AdapterType::Npm => vec!["ci".into()],
23
+ AdapterType::Pnpm | AdapterType::YarnClassic | AdapterType::Bun => {
24
+ vec!["install".into(), "--frozen-lockfile".into()]
25
+ }
26
+ AdapterType::YarnModern => vec!["install".into(), "--immutable".into()],
27
+ AdapterType::Deno => vec!["ci".into()],
28
+ };
29
+ args.extend(registry_arg(&ctx.adapter, &ctx.registry_url));
30
+ exec_adapter(ctx, Some(&temp), args)?;
31
+ Ok(())
32
+ }
@@ -0,0 +1,64 @@
1
+ use super::prelude::*;
2
+
3
+ pub(crate) fn test_deprecate(ctx: &mut TestContext<'_>) -> Result<()> {
4
+ sub_test(ctx, "deprecate single version", |ctx| {
5
+ let pkg = format!("@verdaccio/dep1-{}", ctx.run_id);
6
+ let temp = prepare_deprecate_project(ctx, &pkg, "1.0.0")?;
7
+ publish_pkg(ctx, &temp)?;
8
+ deprecate_pkg(ctx, &temp, &format!("{pkg}@1.0.0"), "some message")?;
9
+ let info = info_pkg(ctx, &temp, &pkg)?;
10
+ assert_eq_json(info.get("name"), pkg.as_str(), "Package name mismatch")?;
11
+ assert_eq_json(
12
+ info.get("deprecated"),
13
+ "some message",
14
+ "Package should be deprecated",
15
+ )?;
16
+ Ok(())
17
+ })?;
18
+ sub_test(ctx, "un-deprecate", |ctx| {
19
+ let pkg = format!("@verdaccio/dep2-{}", ctx.run_id);
20
+ let temp = prepare_deprecate_project(ctx, &pkg, "1.0.0")?;
21
+ publish_pkg(ctx, &temp)?;
22
+ deprecate_pkg(ctx, &temp, &format!("{pkg}@1.0.0"), "some message")?;
23
+ let info = info_pkg(ctx, &temp, &pkg)?;
24
+ assert_eq_json(
25
+ info.get("deprecated"),
26
+ "some message",
27
+ "Package should be deprecated",
28
+ )?;
29
+ deprecate_pkg(ctx, &temp, &format!("{pkg}@1.0.0"), "")?;
30
+ let info = info_pkg(ctx, &temp, &pkg)?;
31
+ assert_true(
32
+ info.get("deprecated").is_none(),
33
+ "Package should be un-deprecated",
34
+ )?;
35
+ Ok(())
36
+ })?;
37
+ sub_test(ctx, "deprecate multiple versions", |ctx| {
38
+ let pkg = format!("@verdaccio/dep3-{}", ctx.run_id);
39
+ let temp = prepare_deprecate_project(ctx, &pkg, "1.0.0")?;
40
+ publish_pkg(ctx, &temp)?;
41
+ for _ in 0..3 {
42
+ bump_version(ctx, &temp, "minor")?;
43
+ publish_pkg(ctx, &temp)?;
44
+ }
45
+ deprecate_pkg(ctx, &temp, &pkg, "some message")?;
46
+ for version in ["1.0.0", "1.1.0", "1.2.0", "1.3.0"] {
47
+ let info = info_pkg(ctx, &temp, &format!("{pkg}@{version}"))?;
48
+ assert_eq_json(
49
+ info.get("deprecated"),
50
+ "some message",
51
+ "Version should be deprecated",
52
+ )?;
53
+ }
54
+ bump_version(ctx, &temp, "minor")?;
55
+ publish_pkg(ctx, &temp)?;
56
+ let info = info_pkg(ctx, &temp, &format!("{pkg}@1.4.0"))?;
57
+ assert_true(
58
+ info.get("deprecated").is_none(),
59
+ "New version should not be deprecated",
60
+ )?;
61
+ Ok(())
62
+ })?;
63
+ Ok(())
64
+ }