@verdaccio/plugin-verifier 1.0.0-next-9.1

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 (72) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +255 -0
  4. package/bin/verdaccio-plugin-verifier +6 -0
  5. package/build/_virtual/_rolldown/runtime.cjs +23 -0
  6. package/build/cli.cjs +15 -0
  7. package/build/cli.cjs.map +1 -0
  8. package/build/cli.d.ts +2 -0
  9. package/build/cli.d.ts.map +1 -0
  10. package/build/cli.js +14 -0
  11. package/build/cli.js.map +1 -0
  12. package/build/commands/verify.cjs +76 -0
  13. package/build/commands/verify.cjs.map +1 -0
  14. package/build/commands/verify.d.ts +11 -0
  15. package/build/commands/verify.d.ts.map +1 -0
  16. package/build/commands/verify.js +74 -0
  17. package/build/commands/verify.js.map +1 -0
  18. package/build/diagnostics.cjs +209 -0
  19. package/build/diagnostics.cjs.map +1 -0
  20. package/build/diagnostics.d.ts +13 -0
  21. package/build/diagnostics.d.ts.map +1 -0
  22. package/build/diagnostics.js +207 -0
  23. package/build/diagnostics.js.map +1 -0
  24. package/build/index.cjs +11 -0
  25. package/build/index.d.ts +5 -0
  26. package/build/index.d.ts.map +1 -0
  27. package/build/index.js +4 -0
  28. package/build/sanity-checks.cjs +27 -0
  29. package/build/sanity-checks.cjs.map +1 -0
  30. package/build/sanity-checks.d.ts +11 -0
  31. package/build/sanity-checks.d.ts.map +1 -0
  32. package/build/sanity-checks.js +22 -0
  33. package/build/sanity-checks.js.map +1 -0
  34. package/build/types.d.ts +80 -0
  35. package/build/types.d.ts.map +1 -0
  36. package/build/verify-plugin.cjs +87 -0
  37. package/build/verify-plugin.cjs.map +1 -0
  38. package/build/verify-plugin.d.ts +19 -0
  39. package/build/verify-plugin.d.ts.map +1 -0
  40. package/build/verify-plugin.js +85 -0
  41. package/build/verify-plugin.js.map +1 -0
  42. package/package.json +63 -0
  43. package/src/cli.ts +14 -0
  44. package/src/commands/verify.ts +100 -0
  45. package/src/diagnostics.ts +274 -0
  46. package/src/index.ts +10 -0
  47. package/src/sanity-checks.ts +27 -0
  48. package/src/types.ts +83 -0
  49. package/src/verify-plugin.ts +115 -0
  50. package/tests/diagnostics.spec.ts +323 -0
  51. package/tests/fixtures/entry-point-bad-json/package.json +1 -0
  52. package/tests/fixtures/entry-point-exports-default/package.json +7 -0
  53. package/tests/fixtures/entry-point-exports-import-default/package.json +9 -0
  54. package/tests/fixtures/entry-point-exports-import-string/package.json +7 -0
  55. package/tests/fixtures/entry-point-exports-string/package.json +5 -0
  56. package/tests/fixtures/entry-point-main/package.json +3 -0
  57. package/tests/fixtures/entry-point-module/package.json +3 -0
  58. package/tests/fixtures/package.json +3 -0
  59. package/tests/fixtures/verdaccio-invalid-plugin/index.js +2 -0
  60. package/tests/fixtures/verdaccio-null-plugin/index.js +4 -0
  61. package/tests/fixtures/verdaccio-throwing-plugin/index.js +4 -0
  62. package/tests/fixtures/verdaccio-valid-auth-es6-plugin/index.js +14 -0
  63. package/tests/fixtures/verdaccio-valid-auth-plugin/index.js +20 -0
  64. package/tests/fixtures/verdaccio-valid-filter-plugin/index.js +12 -0
  65. package/tests/fixtures/verdaccio-valid-middleware-plugin/index.js +10 -0
  66. package/tests/fixtures/verdaccio-valid-storage-plugin/index.js +30 -0
  67. package/tests/fixtures/verdaccio-wrong-category-plugin/index.js +11 -0
  68. package/tests/verify-plugin.spec.ts +218 -0
  69. package/tsconfig.build.json +4 -0
  70. package/tsconfig.json +24 -0
  71. package/vite.config.mjs +69 -0
  72. package/vitest.config.mjs +11 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # @verdaccio/plugin-verifier
2
+
3
+ ## 1.0.0-next-9.1
4
+
5
+ ### Minor Changes
6
+
7
+ - a9d7b4a: feat: add @verdaccio/plugin-verifier tool package
8
+
9
+ - feat(plugin-verifier): new package to verify that a Verdaccio plugin can be loaded, instantiated, and passes sanity checks — uses `asyncLoadPlugin` from `@verdaccio/loaders` (the same loader Verdaccio runs at startup)
10
+ - feat(plugin-verifier): CLI built with clipanion (`verdaccio-plugin-verifier <plugin> --category <category>`)
11
+ - feat(plugin-verifier): programmatic API for use in plugin test suites
12
+ - feat(plugin-verifier): step-by-step diagnostics on failure (resolve, export, instantiate, sanity-check) with actionable error messages
13
+ - feat(core): add shared sanity check functions (`authSanityCheck`, `storageSanityCheck`, `middlewareSanityCheck`, `filterSanityCheck`) to `pluginUtils` in `@verdaccio/core`
14
+ - feat(loaders): add ESM plugin support — `tryLoadAsync` falls back from `require()` to dynamic `import()` when loading ESM plugins
15
+ - refactor(auth,store,server): replace inline sanity check callbacks with shared functions from `@verdaccio/core`
16
+ - fix(core): replace removed `pseudoRandomBytes` with `randomBytes` for Node.js 24 compatibility
17
+ - fix(core): fix `process-warning` ESM interop — use default import instead of named imports for CJS compatibility
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [4eda7ac]
22
+ - Updated dependencies [8f9bcc8]
23
+ - Updated dependencies [a9d7b4a]
24
+ - Updated dependencies [1d5462f]
25
+ - Updated dependencies [fd09d4f]
26
+ - @verdaccio/logger@9.0.0-next-9.5
27
+ - @verdaccio/core@9.0.0-next-9.5
28
+ - @verdaccio/loaders@9.0.0-next-9.5
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Verdaccio contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,255 @@
1
+ # @verdaccio/plugin-verifier
2
+
3
+ A testing tool that verifies whether a Verdaccio plugin can be properly loaded, instantiated, and passes the required sanity checks for its category.
4
+
5
+ It uses `asyncLoadPlugin` from `@verdaccio/loaders` internally — the **same loader Verdaccio uses at startup** — so the verification is identical to what happens in production.
6
+
7
+ Available as both a **CLI** and a **programmatic API**.
8
+
9
+ This is a **pure ESM** package.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install --save-dev @verdaccio/plugin-verifier
15
+ ```
16
+
17
+ ## How It Works
18
+
19
+ When a plugin is verified, it runs through the same pipeline Verdaccio executes at boot time:
20
+
21
+ 1. **Module resolution** — can the plugin be found via `require()`?
22
+ 2. **Export validation** — does it export a function (CommonJS) or a class with a `default` export (ES6)?
23
+ 3. **Instantiation** — can the plugin be constructed with a config and plugin options?
24
+ 4. **Sanity check** — does the instance implement the required methods for its category?
25
+
26
+ ### Required Methods by Category
27
+
28
+ | Category | Required methods (at least one) |
29
+ | ---------------- | ----------------------------------------------- |
30
+ | `authentication` | `authenticate`, `allow_access`, `allow_publish` |
31
+ | `storage` | `getPackageStorage` |
32
+ | `middleware` | `register_middlewares` |
33
+ | `filter` | `filter_metadata` |
34
+
35
+ ## CLI
36
+
37
+ The CLI is built with [clipanion](https://mael.dev/clipanion/) (the same framework used by `@verdaccio/cli`).
38
+
39
+ ### Usage
40
+
41
+ ```bash
42
+ verdaccio-plugin-verifier <plugin> --category <category> [options]
43
+ ```
44
+
45
+ ### Options
46
+
47
+ | Option | Description |
48
+ | ---------------------- | ----------------------------------------------------------------------------------- |
49
+ | `--category, -c` | **(required)** Plugin category: `authentication`, `storage`, `middleware`, `filter` |
50
+ | `--plugins-folder, -d` | Absolute path to the plugins directory (maps to `config.plugins`) |
51
+ | `--prefix, -p` | Plugin name prefix (default: `verdaccio`) |
52
+
53
+ ### Examples
54
+
55
+ Verify an auth plugin from a local plugins folder:
56
+
57
+ ```bash
58
+ verdaccio-plugin-verifier my-auth --category authentication --plugins-folder /path/to/plugins
59
+ ```
60
+
61
+ Verify a storage plugin installed via npm:
62
+
63
+ ```bash
64
+ verdaccio-plugin-verifier my-storage --category storage
65
+ ```
66
+
67
+ Verify a scoped plugin:
68
+
69
+ ```bash
70
+ verdaccio-plugin-verifier @myorg/my-plugin --category middleware
71
+ ```
72
+
73
+ Use a custom plugin prefix:
74
+
75
+ ```bash
76
+ verdaccio-plugin-verifier auth --category authentication --prefix mycompany
77
+ # resolves to "mycompany-auth"
78
+ ```
79
+
80
+ ### Exit Codes
81
+
82
+ | Code | Meaning |
83
+ | ---- | --------------------------------------------------------- |
84
+ | `0` | Plugin loaded and passed all checks |
85
+ | `1` | Plugin failed to load, instantiate, or pass sanity checks |
86
+
87
+ ### CI Integration
88
+
89
+ Add a verification step to your plugin's CI pipeline:
90
+
91
+ ```yaml
92
+ # GitHub Actions example
93
+ - name: Verify plugin
94
+ run: npx verdaccio-plugin-verifier my-auth --category authentication --plugins-folder ./build
95
+ ```
96
+
97
+ ## Programmatic API
98
+
99
+ ### Verify a file-based plugin
100
+
101
+ Use `pluginsFolder` to point to the directory containing your plugin. The plugin folder must be prefixed with `verdaccio-` (or your custom prefix), matching the convention Verdaccio uses to resolve plugins from a folder.
102
+
103
+ ```
104
+ plugins/
105
+ verdaccio-my-auth/
106
+ index.js
107
+ package.json
108
+ ```
109
+
110
+ ```typescript
111
+ import { PLUGIN_CATEGORY } from '@verdaccio/core';
112
+ import { verifyPlugin } from '@verdaccio/plugin-verifier';
113
+
114
+ const result = await verifyPlugin({
115
+ pluginPath: 'my-auth',
116
+ category: PLUGIN_CATEGORY.AUTHENTICATION,
117
+ pluginsFolder: '/absolute/path/to/plugins',
118
+ });
119
+
120
+ if (result.success) {
121
+ console.log(`Plugin loaded successfully (${result.pluginsLoaded} instance(s))`);
122
+ } else {
123
+ console.error('Plugin verification failed:', result.error);
124
+ }
125
+ ```
126
+
127
+ ### Verify an npm-installed plugin
128
+
129
+ When `pluginsFolder` is omitted, the loader resolves the plugin from `node_modules` using Node's `require` algorithm, exactly as Verdaccio does in production.
130
+
131
+ ```typescript
132
+ // Unscoped: looks for `verdaccio-my-auth` in node_modules
133
+ const result = await verifyPlugin({
134
+ pluginPath: 'my-auth',
135
+ category: PLUGIN_CATEGORY.AUTHENTICATION,
136
+ });
137
+
138
+ // Scoped: looks for `@myorg/my-auth` as-is
139
+ const result = await verifyPlugin({
140
+ pluginPath: '@myorg/my-auth',
141
+ category: PLUGIN_CATEGORY.AUTHENTICATION,
142
+ });
143
+ ```
144
+
145
+ ### Use in tests (vitest / jest)
146
+
147
+ This is the primary use case — add a test in your plugin repository to ensure it can be loaded by Verdaccio:
148
+
149
+ ```typescript
150
+ import { describe, expect, it } from 'vitest';
151
+
152
+ import { PLUGIN_CATEGORY } from '@verdaccio/core';
153
+ import { verifyPlugin } from '@verdaccio/plugin-verifier';
154
+
155
+ describe('my verdaccio plugin', () => {
156
+ it('should be loadable by verdaccio', async () => {
157
+ const result = await verifyPlugin({
158
+ pluginPath: 'my-auth',
159
+ category: PLUGIN_CATEGORY.AUTHENTICATION,
160
+ pluginsFolder: '/path/to/build/output',
161
+ });
162
+
163
+ expect(result.success).toBe(true);
164
+ expect(result.pluginsLoaded).toBe(1);
165
+ });
166
+ });
167
+ ```
168
+
169
+ ### Pass plugin configuration
170
+
171
+ If your plugin requires configuration to instantiate, pass it via `pluginConfig`:
172
+
173
+ ```typescript
174
+ const result = await verifyPlugin({
175
+ pluginPath: 'my-storage',
176
+ category: PLUGIN_CATEGORY.STORAGE,
177
+ pluginsFolder: '/path/to/plugins',
178
+ pluginConfig: {
179
+ dataDir: '/tmp/verdaccio-storage',
180
+ maxSize: 1024,
181
+ },
182
+ });
183
+ ```
184
+
185
+ ### Custom sanity check
186
+
187
+ Override the default sanity check to verify additional methods specific to your plugin:
188
+
189
+ ```typescript
190
+ const result = await verifyPlugin({
191
+ pluginPath: 'my-auth',
192
+ category: PLUGIN_CATEGORY.AUTHENTICATION,
193
+ pluginsFolder: '/path/to/plugins',
194
+ sanityCheck: (plugin) => {
195
+ return typeof plugin.authenticate === 'function' && typeof plugin.changePassword === 'function';
196
+ },
197
+ });
198
+ ```
199
+
200
+ ### Custom plugin prefix
201
+
202
+ If your Verdaccio instance uses a custom plugin prefix (via `server.pluginPrefix` in `config.yaml`), pass it to the verifier:
203
+
204
+ ```typescript
205
+ const result = await verifyPlugin({
206
+ pluginPath: 'auth',
207
+ category: PLUGIN_CATEGORY.AUTHENTICATION,
208
+ pluginsFolder: '/path/to/plugins',
209
+ prefix: 'mycompany', // looks for "mycompany-auth" instead of "verdaccio-auth"
210
+ });
211
+ ```
212
+
213
+ ## API Reference
214
+
215
+ ### `verifyPlugin(options: VerifyPluginOptions): Promise<VerifyResult>`
216
+
217
+ #### `VerifyPluginOptions`
218
+
219
+ | Property | Type | Default | Description |
220
+ | --------------- | -------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
221
+ | `pluginPath` | `string` | **(required)** | Plugin identifier as it would appear in `config.yaml` (e.g. `my-auth`, `@scope/my-plugin`) |
222
+ | `category` | `PluginCategory` | **(required)** | Plugin category: `authentication`, `storage`, `middleware`, or `filter` |
223
+ | `pluginConfig` | `Record<string, unknown>` | `{}` | Configuration passed to the plugin constructor |
224
+ | `sanityCheck` | `(plugin: any) => boolean` | _(per category)_ | Custom validation function; overrides the built-in check |
225
+ | `prefix` | `string` | `'verdaccio'` | Plugin name prefix (maps to `server.pluginPrefix`) |
226
+ | `pluginsFolder` | `string` | `undefined` | Absolute path to plugins directory (maps to `config.plugins`); when omitted, resolves from `node_modules` |
227
+
228
+ #### `VerifyResult`
229
+
230
+ | Property | Type | Description |
231
+ | --------------- | ---------------- | ----------------------------------------------- |
232
+ | `success` | `boolean` | Whether the plugin loaded and passed all checks |
233
+ | `pluginName` | `string` | The plugin identifier used |
234
+ | `category` | `PluginCategory` | The category verified against |
235
+ | `pluginsLoaded` | `number` | Number of plugin instances successfully loaded |
236
+ | `error` | `string?` | Error message if verification failed |
237
+
238
+ ### Sanity Check Helpers
239
+
240
+ Individual sanity check functions are also exported for direct use:
241
+
242
+ ```typescript
243
+ import {
244
+ authSanityCheck,
245
+ filterSanityCheck,
246
+ getSanityCheck,
247
+ // returns the right check for a given category
248
+ middlewareSanityCheck,
249
+ storageSanityCheck,
250
+ } from '@verdaccio/plugin-verifier';
251
+ ```
252
+
253
+ ## License
254
+
255
+ MIT
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createRequire } from 'node:module';
4
+
5
+ const require = createRequire(import.meta.url);
6
+ require('../build/cli.cjs');
@@ -0,0 +1,23 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ exports.__toESM = __toESM;
package/build/cli.cjs ADDED
@@ -0,0 +1,15 @@
1
+ require("./_virtual/_rolldown/runtime.cjs");
2
+ const require_verify = require("./commands/verify.cjs");
3
+ let clipanion = require("clipanion");
4
+ //#region src/cli.ts
5
+ var [node, app, ...args] = process.argv;
6
+ var cli = new clipanion.Cli({
7
+ binaryLabel: "verdaccio-plugin-verifier",
8
+ binaryName: `${node} ${app}`,
9
+ binaryVersion: "1.0.0-next-9.0"
10
+ });
11
+ cli.register(require_verify.VerifyCommand);
12
+ cli.runExit(args, clipanion.Cli.defaultContext);
13
+ //#endregion
14
+
15
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.cjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { Cli } from 'clipanion';\n\nimport { VerifyCommand } from './commands/verify';\n\nconst [node, app, ...args] = process.argv;\n\nconst cli = new Cli({\n binaryLabel: 'verdaccio-plugin-verifier',\n binaryName: `${node} ${app}`,\n binaryVersion: '1.0.0-next-9.0',\n});\n\ncli.register(VerifyCommand);\ncli.runExit(args, Cli.defaultContext);\n"],"mappings":";;;;AAIA,IAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,QAAQ;AAErC,IAAM,MAAM,IAAI,UAAA,IAAI;CAClB,aAAa;CACb,YAAY,GAAG,KAAK,GAAG;CACvB,eAAe;CAChB,CAAC;AAEF,IAAI,SAAS,eAAA,cAAc;AAC3B,IAAI,QAAQ,MAAM,UAAA,IAAI,eAAe"}
package/build/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/build/cli.js ADDED
@@ -0,0 +1,14 @@
1
+ import { VerifyCommand } from "./commands/verify.js";
2
+ import { Cli } from "clipanion";
3
+ //#region src/cli.ts
4
+ var [node, app, ...args] = process.argv;
5
+ var cli = new Cli({
6
+ binaryLabel: "verdaccio-plugin-verifier",
7
+ binaryName: `${node} ${app}`,
8
+ binaryVersion: "1.0.0-next-9.0"
9
+ });
10
+ cli.register(VerifyCommand);
11
+ cli.runExit(args, Cli.defaultContext);
12
+ //#endregion
13
+
14
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { Cli } from 'clipanion';\n\nimport { VerifyCommand } from './commands/verify';\n\nconst [node, app, ...args] = process.argv;\n\nconst cli = new Cli({\n binaryLabel: 'verdaccio-plugin-verifier',\n binaryName: `${node} ${app}`,\n binaryVersion: '1.0.0-next-9.0',\n});\n\ncli.register(VerifyCommand);\ncli.runExit(args, Cli.defaultContext);\n"],"mappings":";;;AAIA,IAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,QAAQ;AAErC,IAAM,MAAM,IAAI,IAAI;CAClB,aAAa;CACb,YAAY,GAAG,KAAK,GAAG;CACvB,eAAe;CAChB,CAAC;AAEF,IAAI,SAAS,cAAc;AAC3B,IAAI,QAAQ,MAAM,IAAI,eAAe"}
@@ -0,0 +1,76 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_verify_plugin = require("../verify-plugin.cjs");
3
+ let debug = require("debug");
4
+ debug = require_runtime.__toESM(debug);
5
+ let _verdaccio_core = require("@verdaccio/core");
6
+ let clipanion = require("clipanion");
7
+ //#region src/commands/verify.ts
8
+ var debug$1 = (0, debug.default)("verdaccio:plugin:verifier:cli");
9
+ var VALID_CATEGORIES = Object.values(_verdaccio_core.PLUGIN_CATEGORY);
10
+ var VerifyCommand = class extends clipanion.Command {
11
+ static paths = [clipanion.Command.Default];
12
+ static usage = clipanion.Command.Usage({
13
+ description: "Verify that a Verdaccio plugin can be loaded and passes sanity checks",
14
+ details: `
15
+ This command uses the same plugin loader that Verdaccio runs at startup
16
+ (\`asyncLoadPlugin\` from \`@verdaccio/loaders\`) to verify that a plugin
17
+ can be resolved, instantiated, and passes the required sanity checks
18
+ for its category.
19
+
20
+ The plugin is identified by its short name (as it appears in \`config.yaml\`),
21
+ and the loader applies the prefix automatically. For example, \`my-auth\`
22
+ resolves to \`verdaccio-my-auth\` in the plugins folder or \`node_modules\`.
23
+
24
+ Scoped packages (e.g. \`@myorg/my-plugin\`) are used as-is without a prefix.
25
+
26
+ Enable debug output with the DEBUG environment variable:
27
+ DEBUG=verdaccio:plugin:verifier* verdaccio-plugin-verifier my-auth --category authentication
28
+ `,
29
+ examples: [
30
+ ["Verify an auth plugin from a plugins folder", "verdaccio-plugin-verifier my-auth --category authentication --plugins-folder ./plugins"],
31
+ ["Verify a storage plugin installed via npm", "verdaccio-plugin-verifier my-storage --category storage"],
32
+ ["Verify a scoped plugin with a custom prefix", "verdaccio-plugin-verifier @myorg/my-plugin --category middleware --prefix mycompany"]
33
+ ]
34
+ });
35
+ pluginPath = clipanion.Option.String({
36
+ required: true,
37
+ name: "plugin"
38
+ });
39
+ category = clipanion.Option.String("--category,-c", {
40
+ required: true,
41
+ description: `Plugin category: ${VALID_CATEGORIES.join(", ")}`
42
+ });
43
+ pluginsFolder = clipanion.Option.String("--plugins-folder,-d", { description: "Absolute path to the plugins directory (maps to config.plugins)" });
44
+ prefix = clipanion.Option.String("--prefix,-p", { description: `Plugin name prefix (default: "${_verdaccio_core.PLUGIN_PREFIX}")` });
45
+ async execute() {
46
+ debug$1("command invoked with plugin=%o category=%o", this.pluginPath, this.category);
47
+ debug$1("pluginsFolder=%o prefix=%o", this.pluginsFolder, this.prefix);
48
+ if (!VALID_CATEGORIES.includes(this.category)) {
49
+ this.context.stderr.write(`Error: Invalid category "${this.category}". Must be one of: ${VALID_CATEGORIES.join(", ")}\n`);
50
+ return 1;
51
+ }
52
+ const result = await require_verify_plugin.verifyPlugin({
53
+ pluginPath: this.pluginPath,
54
+ category: this.category,
55
+ pluginsFolder: this.pluginsFolder,
56
+ prefix: this.prefix
57
+ });
58
+ if (result.success) {
59
+ this.context.stdout.write(`Plugin "${result.pluginName}" verified successfully for category "${result.category}" (${result.pluginsLoaded} instance(s) loaded)\n`);
60
+ return 0;
61
+ }
62
+ this.context.stderr.write(`Plugin verification failed: ${result.error}\n`);
63
+ if (result.diagnostics && result.diagnostics.length > 0) {
64
+ this.context.stderr.write("\nDiagnostics:\n");
65
+ for (const step of result.diagnostics) {
66
+ const icon = step.pass ? "PASS" : "FAIL";
67
+ this.context.stderr.write(` [${icon}] ${step.phase}: ${step.message}\n`);
68
+ }
69
+ }
70
+ return 1;
71
+ }
72
+ };
73
+ //#endregion
74
+ exports.VerifyCommand = VerifyCommand;
75
+
76
+ //# sourceMappingURL=verify.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.cjs","names":[],"sources":["../../src/commands/verify.ts"],"sourcesContent":["import { Command, Option } from 'clipanion';\nimport buildDebug from 'debug';\n\nimport { PLUGIN_CATEGORY, PLUGIN_PREFIX } from '@verdaccio/core';\n\nimport { verifyPlugin } from '../verify-plugin';\n\nconst debug = buildDebug('verdaccio:plugin:verifier:cli');\nconst VALID_CATEGORIES = Object.values(PLUGIN_CATEGORY);\n\nexport class VerifyCommand extends Command {\n public static paths = [Command.Default];\n\n static usage = Command.Usage({\n description: 'Verify that a Verdaccio plugin can be loaded and passes sanity checks',\n details: `\n This command uses the same plugin loader that Verdaccio runs at startup\n (\\`asyncLoadPlugin\\` from \\`@verdaccio/loaders\\`) to verify that a plugin\n can be resolved, instantiated, and passes the required sanity checks\n for its category.\n\n The plugin is identified by its short name (as it appears in \\`config.yaml\\`),\n and the loader applies the prefix automatically. For example, \\`my-auth\\`\n resolves to \\`verdaccio-my-auth\\` in the plugins folder or \\`node_modules\\`.\n\n Scoped packages (e.g. \\`@myorg/my-plugin\\`) are used as-is without a prefix.\n\n Enable debug output with the DEBUG environment variable:\n DEBUG=verdaccio:plugin:verifier* verdaccio-plugin-verifier my-auth --category authentication\n `,\n examples: [\n [\n 'Verify an auth plugin from a plugins folder',\n 'verdaccio-plugin-verifier my-auth --category authentication --plugins-folder ./plugins',\n ],\n [\n 'Verify a storage plugin installed via npm',\n 'verdaccio-plugin-verifier my-storage --category storage',\n ],\n [\n 'Verify a scoped plugin with a custom prefix',\n 'verdaccio-plugin-verifier @myorg/my-plugin --category middleware --prefix mycompany',\n ],\n ],\n });\n\n private pluginPath = Option.String({\n required: true,\n name: 'plugin',\n });\n\n private category = Option.String('--category,-c', {\n required: true,\n description: `Plugin category: ${VALID_CATEGORIES.join(', ')}`,\n });\n\n private pluginsFolder = Option.String('--plugins-folder,-d', {\n description: 'Absolute path to the plugins directory (maps to config.plugins)',\n });\n\n private prefix = Option.String('--prefix,-p', {\n description: `Plugin name prefix (default: \"${PLUGIN_PREFIX}\")`,\n });\n\n public async execute(): Promise<number> {\n debug('command invoked with plugin=%o category=%o', this.pluginPath, this.category);\n debug('pluginsFolder=%o prefix=%o', this.pluginsFolder, this.prefix);\n\n if (!VALID_CATEGORIES.includes(this.category)) {\n this.context.stderr.write(\n `Error: Invalid category \"${this.category}\". Must be one of: ${VALID_CATEGORIES.join(', ')}\\n`\n );\n return 1;\n }\n\n const result = await verifyPlugin({\n pluginPath: this.pluginPath,\n category: this.category,\n pluginsFolder: this.pluginsFolder,\n prefix: this.prefix,\n });\n\n if (result.success) {\n this.context.stdout.write(\n `Plugin \"${result.pluginName}\" verified successfully for category \"${result.category}\" (${result.pluginsLoaded} instance(s) loaded)\\n`\n );\n return 0;\n }\n\n this.context.stderr.write(`Plugin verification failed: ${result.error}\\n`);\n if (result.diagnostics && result.diagnostics.length > 0) {\n this.context.stderr.write('\\nDiagnostics:\\n');\n for (const step of result.diagnostics) {\n const icon = step.pass ? 'PASS' : 'FAIL';\n this.context.stderr.write(` [${icon}] ${step.phase}: ${step.message}\\n`);\n }\n }\n return 1;\n }\n}\n"],"mappings":";;;;;;;AAOA,IAAM,WAAA,GAAA,MAAA,SAAmB,gCAAgC;AACzD,IAAM,mBAAmB,OAAO,OAAO,gBAAA,gBAAgB;AAEvD,IAAa,gBAAb,cAAmC,UAAA,QAAQ;CACzC,OAAc,QAAQ,CAAC,UAAA,QAAQ,QAAQ;CAEvC,OAAO,QAAQ,UAAA,QAAQ,MAAM;EAC3B,aAAa;EACb,SAAS;;;;;;;;;;;;;;;EAeT,UAAU;GACR,CACE,+CACA,yFACD;GACD,CACE,6CACA,0DACD;GACD,CACE,+CACA,sFACD;GACF;EACF,CAAC;CAEF,aAAqB,UAAA,OAAO,OAAO;EACjC,UAAU;EACV,MAAM;EACP,CAAC;CAEF,WAAmB,UAAA,OAAO,OAAO,iBAAiB;EAChD,UAAU;EACV,aAAa,oBAAoB,iBAAiB,KAAK,KAAK;EAC7D,CAAC;CAEF,gBAAwB,UAAA,OAAO,OAAO,uBAAuB,EAC3D,aAAa,mEACd,CAAC;CAEF,SAAiB,UAAA,OAAO,OAAO,eAAe,EAC5C,aAAa,iCAAiC,gBAAA,cAAc,KAC7D,CAAC;CAEF,MAAa,UAA2B;AACtC,UAAM,8CAA8C,KAAK,YAAY,KAAK,SAAS;AACnF,UAAM,8BAA8B,KAAK,eAAe,KAAK,OAAO;AAEpE,MAAI,CAAC,iBAAiB,SAAS,KAAK,SAAS,EAAE;AAC7C,QAAK,QAAQ,OAAO,MAClB,4BAA4B,KAAK,SAAS,qBAAqB,iBAAiB,KAAK,KAAK,CAAC,IAC5F;AACD,UAAO;;EAGT,MAAM,SAAS,MAAM,sBAAA,aAAa;GAChC,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,eAAe,KAAK;GACpB,QAAQ,KAAK;GACd,CAAC;AAEF,MAAI,OAAO,SAAS;AAClB,QAAK,QAAQ,OAAO,MAClB,WAAW,OAAO,WAAW,wCAAwC,OAAO,SAAS,KAAK,OAAO,cAAc,wBAChH;AACD,UAAO;;AAGT,OAAK,QAAQ,OAAO,MAAM,+BAA+B,OAAO,MAAM,IAAI;AAC1E,MAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;AACvD,QAAK,QAAQ,OAAO,MAAM,mBAAmB;AAC7C,QAAK,MAAM,QAAQ,OAAO,aAAa;IACrC,MAAM,OAAO,KAAK,OAAO,SAAS;AAClC,SAAK,QAAQ,OAAO,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI;;;AAG7E,SAAO"}
@@ -0,0 +1,11 @@
1
+ import { Command } from 'clipanion';
2
+ export declare class VerifyCommand extends Command {
3
+ static paths: never[][];
4
+ static usage: import('clipanion').Usage;
5
+ private pluginPath;
6
+ private category;
7
+ private pluginsFolder;
8
+ private prefix;
9
+ execute(): Promise<number>;
10
+ }
11
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAU5C,qBAAa,aAAc,SAAQ,OAAO;IACxC,OAAc,KAAK,YAAqB;IAExC,MAAM,CAAC,KAAK,4BA+BT;IAEH,OAAO,CAAC,UAAU,CAGf;IAEH,OAAO,CAAC,QAAQ,CAGb;IAEH,OAAO,CAAC,aAAa,CAElB;IAEH,OAAO,CAAC,MAAM,CAEX;IAEU,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAmCxC"}
@@ -0,0 +1,74 @@
1
+ import { verifyPlugin } from "../verify-plugin.js";
2
+ import buildDebug from "debug";
3
+ import { PLUGIN_CATEGORY, PLUGIN_PREFIX } from "@verdaccio/core";
4
+ import { Command, Option } from "clipanion";
5
+ //#region src/commands/verify.ts
6
+ var debug = buildDebug("verdaccio:plugin:verifier:cli");
7
+ var VALID_CATEGORIES = Object.values(PLUGIN_CATEGORY);
8
+ var VerifyCommand = class extends Command {
9
+ static paths = [Command.Default];
10
+ static usage = Command.Usage({
11
+ description: "Verify that a Verdaccio plugin can be loaded and passes sanity checks",
12
+ details: `
13
+ This command uses the same plugin loader that Verdaccio runs at startup
14
+ (\`asyncLoadPlugin\` from \`@verdaccio/loaders\`) to verify that a plugin
15
+ can be resolved, instantiated, and passes the required sanity checks
16
+ for its category.
17
+
18
+ The plugin is identified by its short name (as it appears in \`config.yaml\`),
19
+ and the loader applies the prefix automatically. For example, \`my-auth\`
20
+ resolves to \`verdaccio-my-auth\` in the plugins folder or \`node_modules\`.
21
+
22
+ Scoped packages (e.g. \`@myorg/my-plugin\`) are used as-is without a prefix.
23
+
24
+ Enable debug output with the DEBUG environment variable:
25
+ DEBUG=verdaccio:plugin:verifier* verdaccio-plugin-verifier my-auth --category authentication
26
+ `,
27
+ examples: [
28
+ ["Verify an auth plugin from a plugins folder", "verdaccio-plugin-verifier my-auth --category authentication --plugins-folder ./plugins"],
29
+ ["Verify a storage plugin installed via npm", "verdaccio-plugin-verifier my-storage --category storage"],
30
+ ["Verify a scoped plugin with a custom prefix", "verdaccio-plugin-verifier @myorg/my-plugin --category middleware --prefix mycompany"]
31
+ ]
32
+ });
33
+ pluginPath = Option.String({
34
+ required: true,
35
+ name: "plugin"
36
+ });
37
+ category = Option.String("--category,-c", {
38
+ required: true,
39
+ description: `Plugin category: ${VALID_CATEGORIES.join(", ")}`
40
+ });
41
+ pluginsFolder = Option.String("--plugins-folder,-d", { description: "Absolute path to the plugins directory (maps to config.plugins)" });
42
+ prefix = Option.String("--prefix,-p", { description: `Plugin name prefix (default: "${PLUGIN_PREFIX}")` });
43
+ async execute() {
44
+ debug("command invoked with plugin=%o category=%o", this.pluginPath, this.category);
45
+ debug("pluginsFolder=%o prefix=%o", this.pluginsFolder, this.prefix);
46
+ if (!VALID_CATEGORIES.includes(this.category)) {
47
+ this.context.stderr.write(`Error: Invalid category "${this.category}". Must be one of: ${VALID_CATEGORIES.join(", ")}\n`);
48
+ return 1;
49
+ }
50
+ const result = await verifyPlugin({
51
+ pluginPath: this.pluginPath,
52
+ category: this.category,
53
+ pluginsFolder: this.pluginsFolder,
54
+ prefix: this.prefix
55
+ });
56
+ if (result.success) {
57
+ this.context.stdout.write(`Plugin "${result.pluginName}" verified successfully for category "${result.category}" (${result.pluginsLoaded} instance(s) loaded)\n`);
58
+ return 0;
59
+ }
60
+ this.context.stderr.write(`Plugin verification failed: ${result.error}\n`);
61
+ if (result.diagnostics && result.diagnostics.length > 0) {
62
+ this.context.stderr.write("\nDiagnostics:\n");
63
+ for (const step of result.diagnostics) {
64
+ const icon = step.pass ? "PASS" : "FAIL";
65
+ this.context.stderr.write(` [${icon}] ${step.phase}: ${step.message}\n`);
66
+ }
67
+ }
68
+ return 1;
69
+ }
70
+ };
71
+ //#endregion
72
+ export { VerifyCommand };
73
+
74
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","names":[],"sources":["../../src/commands/verify.ts"],"sourcesContent":["import { Command, Option } from 'clipanion';\nimport buildDebug from 'debug';\n\nimport { PLUGIN_CATEGORY, PLUGIN_PREFIX } from '@verdaccio/core';\n\nimport { verifyPlugin } from '../verify-plugin';\n\nconst debug = buildDebug('verdaccio:plugin:verifier:cli');\nconst VALID_CATEGORIES = Object.values(PLUGIN_CATEGORY);\n\nexport class VerifyCommand extends Command {\n public static paths = [Command.Default];\n\n static usage = Command.Usage({\n description: 'Verify that a Verdaccio plugin can be loaded and passes sanity checks',\n details: `\n This command uses the same plugin loader that Verdaccio runs at startup\n (\\`asyncLoadPlugin\\` from \\`@verdaccio/loaders\\`) to verify that a plugin\n can be resolved, instantiated, and passes the required sanity checks\n for its category.\n\n The plugin is identified by its short name (as it appears in \\`config.yaml\\`),\n and the loader applies the prefix automatically. For example, \\`my-auth\\`\n resolves to \\`verdaccio-my-auth\\` in the plugins folder or \\`node_modules\\`.\n\n Scoped packages (e.g. \\`@myorg/my-plugin\\`) are used as-is without a prefix.\n\n Enable debug output with the DEBUG environment variable:\n DEBUG=verdaccio:plugin:verifier* verdaccio-plugin-verifier my-auth --category authentication\n `,\n examples: [\n [\n 'Verify an auth plugin from a plugins folder',\n 'verdaccio-plugin-verifier my-auth --category authentication --plugins-folder ./plugins',\n ],\n [\n 'Verify a storage plugin installed via npm',\n 'verdaccio-plugin-verifier my-storage --category storage',\n ],\n [\n 'Verify a scoped plugin with a custom prefix',\n 'verdaccio-plugin-verifier @myorg/my-plugin --category middleware --prefix mycompany',\n ],\n ],\n });\n\n private pluginPath = Option.String({\n required: true,\n name: 'plugin',\n });\n\n private category = Option.String('--category,-c', {\n required: true,\n description: `Plugin category: ${VALID_CATEGORIES.join(', ')}`,\n });\n\n private pluginsFolder = Option.String('--plugins-folder,-d', {\n description: 'Absolute path to the plugins directory (maps to config.plugins)',\n });\n\n private prefix = Option.String('--prefix,-p', {\n description: `Plugin name prefix (default: \"${PLUGIN_PREFIX}\")`,\n });\n\n public async execute(): Promise<number> {\n debug('command invoked with plugin=%o category=%o', this.pluginPath, this.category);\n debug('pluginsFolder=%o prefix=%o', this.pluginsFolder, this.prefix);\n\n if (!VALID_CATEGORIES.includes(this.category)) {\n this.context.stderr.write(\n `Error: Invalid category \"${this.category}\". Must be one of: ${VALID_CATEGORIES.join(', ')}\\n`\n );\n return 1;\n }\n\n const result = await verifyPlugin({\n pluginPath: this.pluginPath,\n category: this.category,\n pluginsFolder: this.pluginsFolder,\n prefix: this.prefix,\n });\n\n if (result.success) {\n this.context.stdout.write(\n `Plugin \"${result.pluginName}\" verified successfully for category \"${result.category}\" (${result.pluginsLoaded} instance(s) loaded)\\n`\n );\n return 0;\n }\n\n this.context.stderr.write(`Plugin verification failed: ${result.error}\\n`);\n if (result.diagnostics && result.diagnostics.length > 0) {\n this.context.stderr.write('\\nDiagnostics:\\n');\n for (const step of result.diagnostics) {\n const icon = step.pass ? 'PASS' : 'FAIL';\n this.context.stderr.write(` [${icon}] ${step.phase}: ${step.message}\\n`);\n }\n }\n return 1;\n }\n}\n"],"mappings":";;;;;AAOA,IAAM,QAAQ,WAAW,gCAAgC;AACzD,IAAM,mBAAmB,OAAO,OAAO,gBAAgB;AAEvD,IAAa,gBAAb,cAAmC,QAAQ;CACzC,OAAc,QAAQ,CAAC,QAAQ,QAAQ;CAEvC,OAAO,QAAQ,QAAQ,MAAM;EAC3B,aAAa;EACb,SAAS;;;;;;;;;;;;;;;EAeT,UAAU;GACR,CACE,+CACA,yFACD;GACD,CACE,6CACA,0DACD;GACD,CACE,+CACA,sFACD;GACF;EACF,CAAC;CAEF,aAAqB,OAAO,OAAO;EACjC,UAAU;EACV,MAAM;EACP,CAAC;CAEF,WAAmB,OAAO,OAAO,iBAAiB;EAChD,UAAU;EACV,aAAa,oBAAoB,iBAAiB,KAAK,KAAK;EAC7D,CAAC;CAEF,gBAAwB,OAAO,OAAO,uBAAuB,EAC3D,aAAa,mEACd,CAAC;CAEF,SAAiB,OAAO,OAAO,eAAe,EAC5C,aAAa,iCAAiC,cAAc,KAC7D,CAAC;CAEF,MAAa,UAA2B;AACtC,QAAM,8CAA8C,KAAK,YAAY,KAAK,SAAS;AACnF,QAAM,8BAA8B,KAAK,eAAe,KAAK,OAAO;AAEpE,MAAI,CAAC,iBAAiB,SAAS,KAAK,SAAS,EAAE;AAC7C,QAAK,QAAQ,OAAO,MAClB,4BAA4B,KAAK,SAAS,qBAAqB,iBAAiB,KAAK,KAAK,CAAC,IAC5F;AACD,UAAO;;EAGT,MAAM,SAAS,MAAM,aAAa;GAChC,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,eAAe,KAAK;GACpB,QAAQ,KAAK;GACd,CAAC;AAEF,MAAI,OAAO,SAAS;AAClB,QAAK,QAAQ,OAAO,MAClB,WAAW,OAAO,WAAW,wCAAwC,OAAO,SAAS,KAAK,OAAO,cAAc,wBAChH;AACD,UAAO;;AAGT,OAAK,QAAQ,OAAO,MAAM,+BAA+B,OAAO,MAAM,IAAI;AAC1E,MAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;AACvD,QAAK,QAAQ,OAAO,MAAM,mBAAmB;AAC7C,QAAK,MAAM,QAAQ,OAAO,aAAa;IACrC,MAAM,OAAO,KAAK,OAAO,SAAS;AAClC,SAAK,QAAQ,OAAO,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI;;;AAG7E,SAAO"}