@verdaccio/plugin-verifier 1.0.0-next-9.13 → 1.0.0-next-9.15

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @verdaccio/plugin-verifier
2
2
 
3
+ ## 1.0.0-next-9.15
4
+
5
+ ### Patch Changes
6
+
7
+ - 47f122f: chore(deps): clean-up unused and duplicates
8
+ - Updated dependencies [47f122f]
9
+ - @verdaccio/core@9.0.0-next-9.19
10
+ - @verdaccio/loaders@9.0.0-next-9.19
11
+ - @verdaccio/logger@9.0.0-next-9.19
12
+
13
+ ## 1.0.0-next-9.14
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [62ebd31]
18
+ - Updated dependencies [e8421bd]
19
+ - Updated dependencies [d9203d0]
20
+ - Updated dependencies [95c4441]
21
+ - Updated dependencies [73c78e3]
22
+ - @verdaccio/core@9.0.0-next-9.18
23
+ - @verdaccio/loaders@9.0.0-next-9.18
24
+ - @verdaccio/logger@9.0.0-next-9.18
25
+
3
26
  ## 1.0.0-next-9.13
4
27
 
5
28
  ### Patch Changes
package/build/cli.cjs CHANGED
@@ -1,4 +1,3 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  const require_verify = require("./commands/verify.cjs");
3
2
  let clipanion = require("clipanion");
4
3
  //#region src/cli.ts
package/build/cli.cjs.map CHANGED
@@ -1 +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"}
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;AACjB,CAAC;AAED,IAAI,SAAS,eAAA,aAAa;AAC1B,IAAI,QAAQ,MAAM,UAAA,IAAI,cAAc"}
package/build/cli.js.map CHANGED
@@ -1 +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"}
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;AACjB,CAAC;AAED,IAAI,SAAS,aAAa;AAC1B,IAAI,QAAQ,MAAM,IAAI,cAAc"}
@@ -1,7 +1,7 @@
1
1
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
2
  const require_verify_plugin = require("../verify-plugin.cjs");
3
3
  let debug = require("debug");
4
- debug = require_runtime.__toESM(debug);
4
+ debug = require_runtime.__toESM(debug, 1);
5
5
  let _verdaccio_core = require("@verdaccio/core");
6
6
  let clipanion = require("clipanion");
7
7
  //#region src/commands/verify.ts
@@ -1 +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"}
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,+BAA+B;AACxD,IAAM,mBAAmB,OAAO,OAAO,gBAAA,eAAe;AAEtD,IAAa,gBAAb,cAAmC,UAAA,QAAQ;CACzC,OAAc,QAAQ,CAAC,UAAA,QAAQ,OAAO;CAEtC,OAAO,QAAQ,UAAA,QAAQ,MAAM;EAC3B,aAAa;EACb,SAAS;;;;;;;;;;;;;;;EAeT,UAAU;GACR,CACE,+CACA,wFACF;GACA,CACE,6CACA,yDACF;GACA,CACE,+CACA,qFACF;EACF;CACF,CAAC;CAED,aAAqB,UAAA,OAAO,OAAO;EACjC,UAAU;EACV,MAAM;CACR,CAAC;CAED,WAAmB,UAAA,OAAO,OAAO,iBAAiB;EAChD,UAAU;EACV,aAAa,oBAAoB,iBAAiB,KAAK,IAAI;CAC7D,CAAC;CAED,gBAAwB,UAAA,OAAO,OAAO,uBAAuB,EAC3D,aAAa,kEACf,CAAC;CAED,SAAiB,UAAA,OAAO,OAAO,eAAe,EAC5C,aAAa,iCAAiC,gBAAA,cAAc,IAC9D,CAAC;CAED,MAAa,UAA2B;EACtC,QAAM,8CAA8C,KAAK,YAAY,KAAK,QAAQ;EAClF,QAAM,8BAA8B,KAAK,eAAe,KAAK,MAAM;EAEnE,IAAI,CAAC,iBAAiB,SAAS,KAAK,QAAQ,GAAG;GAC7C,KAAK,QAAQ,OAAO,MAClB,4BAA4B,KAAK,SAAS,qBAAqB,iBAAiB,KAAK,IAAI,EAAE,GAC7F;GACA,OAAO;EACT;EAEA,MAAM,SAAS,MAAM,sBAAA,aAAa;GAChC,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,eAAe,KAAK;GACpB,QAAQ,KAAK;EACf,CAAC;EAED,IAAI,OAAO,SAAS;GAClB,KAAK,QAAQ,OAAO,MAClB,WAAW,OAAO,WAAW,wCAAwC,OAAO,SAAS,KAAK,OAAO,cAAc,uBACjH;GACA,OAAO;EACT;EAEA,KAAK,QAAQ,OAAO,MAAM,+BAA+B,OAAO,MAAM,GAAG;EACzE,IAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;GACvD,KAAK,QAAQ,OAAO,MAAM,kBAAkB;GAC5C,KAAK,MAAM,QAAQ,OAAO,aAAa;IACrC,MAAM,OAAO,KAAK,OAAO,SAAS;IAClC,KAAK,QAAQ,OAAO,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,GAAG;GAC1E;EACF;EACA,OAAO;CACT;AACF"}
@@ -1 +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"}
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,+BAA+B;AACxD,IAAM,mBAAmB,OAAO,OAAO,eAAe;AAEtD,IAAa,gBAAb,cAAmC,QAAQ;CACzC,OAAc,QAAQ,CAAC,QAAQ,OAAO;CAEtC,OAAO,QAAQ,QAAQ,MAAM;EAC3B,aAAa;EACb,SAAS;;;;;;;;;;;;;;;EAeT,UAAU;GACR,CACE,+CACA,wFACF;GACA,CACE,6CACA,yDACF;GACA,CACE,+CACA,qFACF;EACF;CACF,CAAC;CAED,aAAqB,OAAO,OAAO;EACjC,UAAU;EACV,MAAM;CACR,CAAC;CAED,WAAmB,OAAO,OAAO,iBAAiB;EAChD,UAAU;EACV,aAAa,oBAAoB,iBAAiB,KAAK,IAAI;CAC7D,CAAC;CAED,gBAAwB,OAAO,OAAO,uBAAuB,EAC3D,aAAa,kEACf,CAAC;CAED,SAAiB,OAAO,OAAO,eAAe,EAC5C,aAAa,iCAAiC,cAAc,IAC9D,CAAC;CAED,MAAa,UAA2B;EACtC,MAAM,8CAA8C,KAAK,YAAY,KAAK,QAAQ;EAClF,MAAM,8BAA8B,KAAK,eAAe,KAAK,MAAM;EAEnE,IAAI,CAAC,iBAAiB,SAAS,KAAK,QAAQ,GAAG;GAC7C,KAAK,QAAQ,OAAO,MAClB,4BAA4B,KAAK,SAAS,qBAAqB,iBAAiB,KAAK,IAAI,EAAE,GAC7F;GACA,OAAO;EACT;EAEA,MAAM,SAAS,MAAM,aAAa;GAChC,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,eAAe,KAAK;GACpB,QAAQ,KAAK;EACf,CAAC;EAED,IAAI,OAAO,SAAS;GAClB,KAAK,QAAQ,OAAO,MAClB,WAAW,OAAO,WAAW,wCAAwC,OAAO,SAAS,KAAK,OAAO,cAAc,uBACjH;GACA,OAAO;EACT;EAEA,KAAK,QAAQ,OAAO,MAAM,+BAA+B,OAAO,MAAM,GAAG;EACzE,IAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;GACvD,KAAK,QAAQ,OAAO,MAAM,kBAAkB;GAC5C,KAAK,MAAM,QAAQ,OAAO,aAAa;IACrC,MAAM,OAAO,KAAK,OAAO,SAAS;IAClC,KAAK,QAAQ,OAAO,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,GAAG;GAC1E;EACF;EACA,OAAO;CACT;AACF"}
@@ -1,7 +1,7 @@
1
1
  const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
2
2
  const require_sanity_checks = require("./sanity-checks.cjs");
3
3
  let debug = require("debug");
4
- debug = require_runtime.__toESM(debug);
4
+ debug = require_runtime.__toESM(debug, 1);
5
5
  let node_path = require("node:path");
6
6
  let _verdaccio_core = require("@verdaccio/core");
7
7
  let node_fs = require("node:fs");
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.cjs","names":[],"sources":["../src/diagnostics.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\n\nimport { getSanityCheck } from './sanity-checks';\nimport type { DiagnosticStep, VerifyPluginOptions } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier:diagnostics');\n\n// createRequire needs an absolute path; works in both ESM and CJS contexts\nconst requireModule = createRequire(\n typeof __filename !== 'undefined' ? __filename : import.meta.url\n);\n\nfunction isValidExport(plugin: any): boolean {\n return typeof plugin === 'function' || typeof plugin?.default === 'function';\n}\n\nfunction isES6(plugin: any): boolean {\n return plugin && typeof plugin === 'object' && 'default' in plugin;\n}\n\n/**\n * Resolve the ESM entry point for a directory-based plugin.\n * import() doesn't support directory imports, so we resolve via package.json.\n */\nexport function resolveEntryPoint(dirPath: string): string {\n const pkgPath = join(dirPath, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n if (pkg.exports) {\n const dotExport = pkg.exports['.'];\n if (typeof dotExport === 'string') {\n return join(dirPath, dotExport);\n }\n if (dotExport?.import?.default) {\n return join(dirPath, dotExport.import.default);\n }\n if (dotExport?.import && typeof dotExport.import === 'string') {\n return join(dirPath, dotExport.import);\n }\n if (dotExport?.default) {\n return join(dirPath, dotExport.default);\n }\n }\n if (pkg.module) {\n return join(dirPath, pkg.module);\n }\n if (pkg.main) {\n return join(dirPath, pkg.main);\n }\n } catch {\n // fall through\n }\n }\n return join(dirPath, 'index.js');\n}\n\n/**\n * Try to load a module, falling back from require() to import() for ESM.\n * Handles CJS require(), ESM require() shim errors (bundlers), and\n * ERR_REQUIRE_ESM — always falls through to dynamic import() on any\n * require() failure.\n */\nasync function tryResolve(modulePath: string): Promise<{ module: any; error?: string }> {\n // Try require() first (fast path for CJS modules)\n try {\n return { module: requireModule(modulePath) };\n } catch (requireErr: any) {\n debug('require() failed for %o: %s — trying dynamic import', modulePath, requireErr.message);\n }\n\n // Fallback to dynamic import() for ESM modules\n try {\n let importPath = modulePath;\n if (existsSync(modulePath) && existsSync(join(modulePath, 'package.json'))) {\n importPath = resolveEntryPoint(modulePath);\n debug('resolved ESM entry point: %o', importPath);\n }\n const importUrl = importPath.startsWith('/') ? pathToFileURL(importPath).href : importPath;\n const mod = await import(importUrl);\n return { module: mod };\n } catch (importErr: any) {\n return { module: null, error: importErr.message };\n }\n}\n\n/**\n * Runs step-by-step diagnostics to identify exactly which phase of\n * plugin loading fails. This replicates the same resolution logic\n * as `asyncLoadPlugin` but tests each step independently.\n */\nexport async function runDiagnostics(options: VerifyPluginOptions): Promise<DiagnosticStep[]> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n } = options;\n\n const steps: DiagnosticStep[] = [];\n const isScoped = pluginPath.startsWith('@') && pluginPath.includes('/');\n const pluginName = isScoped ? pluginPath : `${prefix}-${pluginPath}`;\n\n debug('running diagnostics for %o (resolved name: %o)', pluginPath, pluginName);\n\n // --- Phase 1: Resolve ---\n let pluginModule: any = null;\n let resolvedFrom = '';\n\n // Try plugins folder first\n if (pluginsFolder) {\n const absFolder = resolve(pluginsFolder);\n const pluginDir = join(absFolder, pluginName);\n debug('checking plugins folder: %o', pluginDir);\n\n if (!existsSync(absFolder)) {\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugins folder does not exist: ${absFolder}`,\n });\n return steps;\n }\n\n if (!existsSync(pluginDir)) {\n debug('plugin directory not found: %o', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugin directory not found: ${pluginDir} — expected a folder named \"${pluginName}\" inside \"${absFolder}\"`,\n });\n return steps;\n }\n\n const result = await tryResolve(pluginDir);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginDir;\n debug('resolved from plugins folder: %o', pluginDir);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Plugin found at ${pluginDir} but has a missing dependency: ${missingDep}`\n : `Plugin found at ${pluginDir} but failed to load: ${result.error}`,\n });\n return steps;\n }\n }\n\n // Try node_modules if not found in plugins folder\n if (!pluginModule) {\n const result = await tryResolve(pluginName);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginName;\n debug('resolved from node_modules: %o', pluginName);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginName);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Package \"${pluginName}\" found but has a missing dependency: ${missingDep}`\n : `Package \"${pluginName}\" not found in node_modules — try: npm install ${pluginName}`,\n });\n return steps;\n }\n }\n\n steps.push({\n phase: 'resolve',\n pass: true,\n message: `Module resolved from ${resolvedFrom}`,\n });\n\n // --- Phase 2: Export validation ---\n if (!isValidExport(pluginModule)) {\n const exportKeys = pluginModule ? Object.keys(pluginModule).join(', ') : 'none';\n steps.push({\n phase: 'export',\n pass: false,\n message: `Module does not export a function or class (default export). Exported keys: [${exportKeys}]`,\n });\n return steps;\n }\n\n const moduleType = isES6(pluginModule) ? 'ES6 (default export)' : 'CommonJS (factory function)';\n steps.push({\n phase: 'export',\n pass: true,\n message: `Valid ${moduleType} plugin export detected`,\n });\n\n // --- Phase 3: Instantiation ---\n let instance: any;\n try {\n if (isES6(pluginModule)) {\n instance = new pluginModule.default(pluginConfig, { config: pluginConfig, logger: console });\n } else {\n instance = pluginModule(pluginConfig, { config: pluginConfig, logger: console });\n }\n } catch (err: any) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin threw during instantiation: ${err.message}`,\n });\n return steps;\n }\n\n if (!instance || (typeof instance !== 'object' && typeof instance !== 'function')) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin constructor/factory returned ${instance === null ? 'null' : typeof instance} instead of an object`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'instantiate',\n pass: true,\n message: 'Plugin instantiated successfully',\n });\n\n // --- Phase 4: Sanity check ---\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n const passed = sanityCheck(instance);\n\n if (!passed) {\n const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance) ?? {})\n .filter((m) => m !== 'constructor')\n .concat(Object.keys(instance));\n const unique = [...new Set(methods)];\n\n steps.push({\n phase: 'sanity-check',\n pass: false,\n message: `Plugin does not implement the required methods for category \"${category}\". Available methods: [${unique.join(', ')}]`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'sanity-check',\n pass: true,\n message: `Plugin passes sanity check for category \"${category}\"`,\n });\n\n return steps;\n}\n\n/**\n * When a MODULE_NOT_FOUND error is about a transitive dependency\n * (not the plugin itself), extract the missing module name.\n */\nfunction parseMissingDependency(message: string, pluginPath: string): string | null {\n const match = message.match(/Cannot find module '([^']+)'/);\n if (match && match[1] && !match[1].includes(pluginPath)) {\n return match[1];\n }\n return null;\n}\n"],"mappings":";;;;;;;;;;AAWA,IAAM,WAAA,GAAA,MAAA,SAAmB,wCAAwC;AAGjE,IAAM,iBAAA,GAAA,YAAA,eACJ,OAAO,eAAe,cAAc,aAAA,EAAA,CAAyB,IAC9D;AAED,SAAS,cAAc,QAAsB;AAC3C,QAAO,OAAO,WAAW,cAAc,OAAO,QAAQ,YAAY;;AAGpE,SAAS,MAAM,QAAsB;AACnC,QAAO,UAAU,OAAO,WAAW,YAAY,aAAa;;;;;;AAO9D,SAAgB,kBAAkB,SAAyB;CACzD,MAAM,WAAA,GAAA,UAAA,MAAe,SAAS,eAAe;AAC7C,MAAA,GAAA,QAAA,YAAe,QAAQ,CACrB,KAAI;EACF,MAAM,MAAM,KAAK,OAAA,GAAA,QAAA,cAAmB,SAAS,QAAQ,CAAC;AACtD,MAAI,IAAI,SAAS;GACf,MAAM,YAAY,IAAI,QAAQ;AAC9B,OAAI,OAAO,cAAc,SACvB,SAAA,GAAA,UAAA,MAAY,SAAS,UAAU;AAEjC,OAAI,WAAW,QAAQ,QACrB,SAAA,GAAA,UAAA,MAAY,SAAS,UAAU,OAAO,QAAQ;AAEhD,OAAI,WAAW,UAAU,OAAO,UAAU,WAAW,SACnD,SAAA,GAAA,UAAA,MAAY,SAAS,UAAU,OAAO;AAExC,OAAI,WAAW,QACb,SAAA,GAAA,UAAA,MAAY,SAAS,UAAU,QAAQ;;AAG3C,MAAI,IAAI,OACN,SAAA,GAAA,UAAA,MAAY,SAAS,IAAI,OAAO;AAElC,MAAI,IAAI,KACN,SAAA,GAAA,UAAA,MAAY,SAAS,IAAI,KAAK;SAE1B;AAIV,SAAA,GAAA,UAAA,MAAY,SAAS,WAAW;;;;;;;;AASlC,eAAe,WAAW,YAA8D;AAEtF,KAAI;AACF,SAAO,EAAE,QAAQ,cAAc,WAAW,EAAE;UACrC,YAAiB;AACxB,UAAM,uDAAuD,YAAY,WAAW,QAAQ;;AAI9F,KAAI;EACF,IAAI,aAAa;AACjB,OAAA,GAAA,QAAA,YAAe,WAAW,KAAA,GAAA,QAAA,aAAA,GAAA,UAAA,MAAoB,YAAY,eAAe,CAAC,EAAE;AAC1E,gBAAa,kBAAkB,WAAW;AAC1C,WAAM,gCAAgC,WAAW;;AAInD,SAAO,EAAE,QADG,OADM,WAAW,WAAW,IAAI,GAAA,QAAA,GAAA,SAAA,eAAiB,WAAW,CAAC,QAAA,OAAO,cAE1D;UACf,WAAgB;AACvB,SAAO;GAAE,QAAQ;GAAM,OAAO,UAAU;GAAS;;;;;;;;AASrD,eAAsB,eAAe,SAAyD;CAC5F,MAAM,EACJ,YACA,UACA,eAAe,EAAE,EACjB,aAAa,mBACb,SAAS,gBAAA,eACT,kBACE;CAEJ,MAAM,QAA0B,EAAE;CAElC,MAAM,aADW,WAAW,WAAW,IAAI,IAAI,WAAW,SAAS,IAAI,GACzC,aAAa,GAAG,OAAO,GAAG;AAExD,SAAM,kDAAkD,YAAY,WAAW;CAG/E,IAAI,eAAoB;CACxB,IAAI,eAAe;AAGnB,KAAI,eAAe;EACjB,MAAM,aAAA,GAAA,UAAA,SAAoB,cAAc;EACxC,MAAM,aAAA,GAAA,UAAA,MAAiB,WAAW,WAAW;AAC7C,UAAM,+BAA+B,UAAU;AAE/C,MAAI,EAAA,GAAA,QAAA,YAAY,UAAU,EAAE;AAC1B,SAAM,KAAK;IACT,OAAO;IACP,MAAM;IACN,SAAS,kCAAkC;IAC5C,CAAC;AACF,UAAO;;AAGT,MAAI,EAAA,GAAA,QAAA,YAAY,UAAU,EAAE;AAC1B,WAAM,kCAAkC,UAAU;AAClD,SAAM,KAAK;IACT,OAAO;IACP,MAAM;IACN,SAAS,+BAA+B,UAAU,8BAA8B,WAAW,YAAY,UAAU;IAClH,CAAC;AACF,UAAO;;EAGT,MAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,MAAI,OAAO,QAAQ;AACjB,kBAAe,OAAO;AACtB,kBAAe;AACf,WAAM,oCAAoC,UAAU;SAC/C;GACL,MAAM,aAAa,uBAAuB,OAAO,SAAS,IAAI,UAAU;AACxE,SAAM,KAAK;IACT,OAAO;IACP,MAAM;IACN,SAAS,aACL,mBAAmB,UAAU,iCAAiC,eAC9D,mBAAmB,UAAU,uBAAuB,OAAO;IAChE,CAAC;AACF,UAAO;;;AAKX,KAAI,CAAC,cAAc;EACjB,MAAM,SAAS,MAAM,WAAW,WAAW;AAC3C,MAAI,OAAO,QAAQ;AACjB,kBAAe,OAAO;AACtB,kBAAe;AACf,WAAM,kCAAkC,WAAW;SAC9C;GACL,MAAM,aAAa,uBAAuB,OAAO,SAAS,IAAI,WAAW;AACzE,SAAM,KAAK;IACT,OAAO;IACP,MAAM;IACN,SAAS,aACL,YAAY,WAAW,wCAAwC,eAC/D,YAAY,WAAW,iDAAiD;IAC7E,CAAC;AACF,UAAO;;;AAIX,OAAM,KAAK;EACT,OAAO;EACP,MAAM;EACN,SAAS,wBAAwB;EAClC,CAAC;AAGF,KAAI,CAAC,cAAc,aAAa,EAAE;EAChC,MAAM,aAAa,eAAe,OAAO,KAAK,aAAa,CAAC,KAAK,KAAK,GAAG;AACzE,QAAM,KAAK;GACT,OAAO;GACP,MAAM;GACN,SAAS,gFAAgF,WAAW;GACrG,CAAC;AACF,SAAO;;CAGT,MAAM,aAAa,MAAM,aAAa,GAAG,yBAAyB;AAClE,OAAM,KAAK;EACT,OAAO;EACP,MAAM;EACN,SAAS,SAAS,WAAW;EAC9B,CAAC;CAGF,IAAI;AACJ,KAAI;AACF,MAAI,MAAM,aAAa,CACrB,YAAW,IAAI,aAAa,QAAQ,cAAc;GAAE,QAAQ;GAAc,QAAQ;GAAS,CAAC;MAE5F,YAAW,aAAa,cAAc;GAAE,QAAQ;GAAc,QAAQ;GAAS,CAAC;UAE3E,KAAU;AACjB,QAAM,KAAK;GACT,OAAO;GACP,MAAM;GACN,SAAS,sCAAsC,IAAI;GACpD,CAAC;AACF,SAAO;;AAGT,KAAI,CAAC,YAAa,OAAO,aAAa,YAAY,OAAO,aAAa,YAAa;AACjF,QAAM,KAAK;GACT,OAAO;GACP,MAAM;GACN,SAAS,uCAAuC,aAAa,OAAO,SAAS,OAAO,SAAS;GAC9F,CAAC;AACF,SAAO;;AAGT,OAAM,KAAK;EACT,OAAO;EACP,MAAM;EACN,SAAS;EACV,CAAC;AAMF,KAAI,EAHgB,qBAAqB,sBAAA,eAAe,SAAS,EACtC,SAAS,EAEvB;EACX,MAAM,UAAU,OAAO,oBAAoB,OAAO,eAAe,SAAS,IAAI,EAAE,CAAC,CAC9E,QAAQ,MAAM,MAAM,cAAc,CAClC,OAAO,OAAO,KAAK,SAAS,CAAC;EAChC,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AAEpC,QAAM,KAAK;GACT,OAAO;GACP,MAAM;GACN,SAAS,gEAAgE,SAAS,yBAAyB,OAAO,KAAK,KAAK,CAAC;GAC9H,CAAC;AACF,SAAO;;AAGT,OAAM,KAAK;EACT,OAAO;EACP,MAAM;EACN,SAAS,4CAA4C,SAAS;EAC/D,CAAC;AAEF,QAAO;;;;;;AAOT,SAAS,uBAAuB,SAAiB,YAAmC;CAClF,MAAM,QAAQ,QAAQ,MAAM,+BAA+B;AAC3D,KAAI,SAAS,MAAM,MAAM,CAAC,MAAM,GAAG,SAAS,WAAW,CACrD,QAAO,MAAM;AAEf,QAAO"}
1
+ {"version":3,"file":"diagnostics.cjs","names":[],"sources":["../src/diagnostics.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\n\nimport { getSanityCheck } from './sanity-checks';\nimport type { DiagnosticStep, VerifyPluginOptions } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier:diagnostics');\n\n// createRequire needs an absolute path; works in both ESM and CJS contexts\nconst requireModule = createRequire(\n typeof __filename !== 'undefined' ? __filename : import.meta.url\n);\n\nfunction isValidExport(plugin: any): boolean {\n return typeof plugin === 'function' || typeof plugin?.default === 'function';\n}\n\nfunction isES6(plugin: any): boolean {\n return plugin && typeof plugin === 'object' && 'default' in plugin;\n}\n\n/**\n * Resolve the ESM entry point for a directory-based plugin.\n * import() doesn't support directory imports, so we resolve via package.json.\n */\nexport function resolveEntryPoint(dirPath: string): string {\n const pkgPath = join(dirPath, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n if (pkg.exports) {\n const dotExport = pkg.exports['.'];\n if (typeof dotExport === 'string') {\n return join(dirPath, dotExport);\n }\n if (dotExport?.import?.default) {\n return join(dirPath, dotExport.import.default);\n }\n if (dotExport?.import && typeof dotExport.import === 'string') {\n return join(dirPath, dotExport.import);\n }\n if (dotExport?.default) {\n return join(dirPath, dotExport.default);\n }\n }\n if (pkg.module) {\n return join(dirPath, pkg.module);\n }\n if (pkg.main) {\n return join(dirPath, pkg.main);\n }\n } catch {\n // fall through\n }\n }\n return join(dirPath, 'index.js');\n}\n\n/**\n * Try to load a module, falling back from require() to import() for ESM.\n * Handles CJS require(), ESM require() shim errors (bundlers), and\n * ERR_REQUIRE_ESM — always falls through to dynamic import() on any\n * require() failure.\n */\nasync function tryResolve(modulePath: string): Promise<{ module: any; error?: string }> {\n // Try require() first (fast path for CJS modules)\n try {\n return { module: requireModule(modulePath) };\n } catch (requireErr: any) {\n debug('require() failed for %o: %s — trying dynamic import', modulePath, requireErr.message);\n }\n\n // Fallback to dynamic import() for ESM modules\n try {\n let importPath = modulePath;\n if (existsSync(modulePath) && existsSync(join(modulePath, 'package.json'))) {\n importPath = resolveEntryPoint(modulePath);\n debug('resolved ESM entry point: %o', importPath);\n }\n const importUrl = importPath.startsWith('/') ? pathToFileURL(importPath).href : importPath;\n const mod = await import(importUrl);\n return { module: mod };\n } catch (importErr: any) {\n return { module: null, error: importErr.message };\n }\n}\n\n/**\n * Runs step-by-step diagnostics to identify exactly which phase of\n * plugin loading fails. This replicates the same resolution logic\n * as `asyncLoadPlugin` but tests each step independently.\n */\nexport async function runDiagnostics(options: VerifyPluginOptions): Promise<DiagnosticStep[]> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n } = options;\n\n const steps: DiagnosticStep[] = [];\n const isScoped = pluginPath.startsWith('@') && pluginPath.includes('/');\n const pluginName = isScoped ? pluginPath : `${prefix}-${pluginPath}`;\n\n debug('running diagnostics for %o (resolved name: %o)', pluginPath, pluginName);\n\n // --- Phase 1: Resolve ---\n let pluginModule: any = null;\n let resolvedFrom = '';\n\n // Try plugins folder first\n if (pluginsFolder) {\n const absFolder = resolve(pluginsFolder);\n const pluginDir = join(absFolder, pluginName);\n debug('checking plugins folder: %o', pluginDir);\n\n if (!existsSync(absFolder)) {\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugins folder does not exist: ${absFolder}`,\n });\n return steps;\n }\n\n if (!existsSync(pluginDir)) {\n debug('plugin directory not found: %o', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugin directory not found: ${pluginDir} — expected a folder named \"${pluginName}\" inside \"${absFolder}\"`,\n });\n return steps;\n }\n\n const result = await tryResolve(pluginDir);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginDir;\n debug('resolved from plugins folder: %o', pluginDir);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Plugin found at ${pluginDir} but has a missing dependency: ${missingDep}`\n : `Plugin found at ${pluginDir} but failed to load: ${result.error}`,\n });\n return steps;\n }\n }\n\n // Try node_modules if not found in plugins folder\n if (!pluginModule) {\n const result = await tryResolve(pluginName);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginName;\n debug('resolved from node_modules: %o', pluginName);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginName);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Package \"${pluginName}\" found but has a missing dependency: ${missingDep}`\n : `Package \"${pluginName}\" not found in node_modules — try: npm install ${pluginName}`,\n });\n return steps;\n }\n }\n\n steps.push({\n phase: 'resolve',\n pass: true,\n message: `Module resolved from ${resolvedFrom}`,\n });\n\n // --- Phase 2: Export validation ---\n if (!isValidExport(pluginModule)) {\n const exportKeys = pluginModule ? Object.keys(pluginModule).join(', ') : 'none';\n steps.push({\n phase: 'export',\n pass: false,\n message: `Module does not export a function or class (default export). Exported keys: [${exportKeys}]`,\n });\n return steps;\n }\n\n const moduleType = isES6(pluginModule) ? 'ES6 (default export)' : 'CommonJS (factory function)';\n steps.push({\n phase: 'export',\n pass: true,\n message: `Valid ${moduleType} plugin export detected`,\n });\n\n // --- Phase 3: Instantiation ---\n let instance: any;\n try {\n if (isES6(pluginModule)) {\n instance = new pluginModule.default(pluginConfig, { config: pluginConfig, logger: console });\n } else {\n instance = pluginModule(pluginConfig, { config: pluginConfig, logger: console });\n }\n } catch (err: any) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin threw during instantiation: ${err.message}`,\n });\n return steps;\n }\n\n if (!instance || (typeof instance !== 'object' && typeof instance !== 'function')) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin constructor/factory returned ${instance === null ? 'null' : typeof instance} instead of an object`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'instantiate',\n pass: true,\n message: 'Plugin instantiated successfully',\n });\n\n // --- Phase 4: Sanity check ---\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n const passed = sanityCheck(instance);\n\n if (!passed) {\n const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance) ?? {})\n .filter((m) => m !== 'constructor')\n .concat(Object.keys(instance));\n const unique = [...new Set(methods)];\n\n steps.push({\n phase: 'sanity-check',\n pass: false,\n message: `Plugin does not implement the required methods for category \"${category}\". Available methods: [${unique.join(', ')}]`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'sanity-check',\n pass: true,\n message: `Plugin passes sanity check for category \"${category}\"`,\n });\n\n return steps;\n}\n\n/**\n * When a MODULE_NOT_FOUND error is about a transitive dependency\n * (not the plugin itself), extract the missing module name.\n */\nfunction parseMissingDependency(message: string, pluginPath: string): string | null {\n const match = message.match(/Cannot find module '([^']+)'/);\n if (match && match[1] && !match[1].includes(pluginPath)) {\n return match[1];\n }\n return null;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.js","names":[],"sources":["../src/diagnostics.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\n\nimport { getSanityCheck } from './sanity-checks';\nimport type { DiagnosticStep, VerifyPluginOptions } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier:diagnostics');\n\n// createRequire needs an absolute path; works in both ESM and CJS contexts\nconst requireModule = createRequire(\n typeof __filename !== 'undefined' ? __filename : import.meta.url\n);\n\nfunction isValidExport(plugin: any): boolean {\n return typeof plugin === 'function' || typeof plugin?.default === 'function';\n}\n\nfunction isES6(plugin: any): boolean {\n return plugin && typeof plugin === 'object' && 'default' in plugin;\n}\n\n/**\n * Resolve the ESM entry point for a directory-based plugin.\n * import() doesn't support directory imports, so we resolve via package.json.\n */\nexport function resolveEntryPoint(dirPath: string): string {\n const pkgPath = join(dirPath, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n if (pkg.exports) {\n const dotExport = pkg.exports['.'];\n if (typeof dotExport === 'string') {\n return join(dirPath, dotExport);\n }\n if (dotExport?.import?.default) {\n return join(dirPath, dotExport.import.default);\n }\n if (dotExport?.import && typeof dotExport.import === 'string') {\n return join(dirPath, dotExport.import);\n }\n if (dotExport?.default) {\n return join(dirPath, dotExport.default);\n }\n }\n if (pkg.module) {\n return join(dirPath, pkg.module);\n }\n if (pkg.main) {\n return join(dirPath, pkg.main);\n }\n } catch {\n // fall through\n }\n }\n return join(dirPath, 'index.js');\n}\n\n/**\n * Try to load a module, falling back from require() to import() for ESM.\n * Handles CJS require(), ESM require() shim errors (bundlers), and\n * ERR_REQUIRE_ESM — always falls through to dynamic import() on any\n * require() failure.\n */\nasync function tryResolve(modulePath: string): Promise<{ module: any; error?: string }> {\n // Try require() first (fast path for CJS modules)\n try {\n return { module: requireModule(modulePath) };\n } catch (requireErr: any) {\n debug('require() failed for %o: %s — trying dynamic import', modulePath, requireErr.message);\n }\n\n // Fallback to dynamic import() for ESM modules\n try {\n let importPath = modulePath;\n if (existsSync(modulePath) && existsSync(join(modulePath, 'package.json'))) {\n importPath = resolveEntryPoint(modulePath);\n debug('resolved ESM entry point: %o', importPath);\n }\n const importUrl = importPath.startsWith('/') ? pathToFileURL(importPath).href : importPath;\n const mod = await import(importUrl);\n return { module: mod };\n } catch (importErr: any) {\n return { module: null, error: importErr.message };\n }\n}\n\n/**\n * Runs step-by-step diagnostics to identify exactly which phase of\n * plugin loading fails. This replicates the same resolution logic\n * as `asyncLoadPlugin` but tests each step independently.\n */\nexport async function runDiagnostics(options: VerifyPluginOptions): Promise<DiagnosticStep[]> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n } = options;\n\n const steps: DiagnosticStep[] = [];\n const isScoped = pluginPath.startsWith('@') && pluginPath.includes('/');\n const pluginName = isScoped ? pluginPath : `${prefix}-${pluginPath}`;\n\n debug('running diagnostics for %o (resolved name: %o)', pluginPath, pluginName);\n\n // --- Phase 1: Resolve ---\n let pluginModule: any = null;\n let resolvedFrom = '';\n\n // Try plugins folder first\n if (pluginsFolder) {\n const absFolder = resolve(pluginsFolder);\n const pluginDir = join(absFolder, pluginName);\n debug('checking plugins folder: %o', pluginDir);\n\n if (!existsSync(absFolder)) {\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugins folder does not exist: ${absFolder}`,\n });\n return steps;\n }\n\n if (!existsSync(pluginDir)) {\n debug('plugin directory not found: %o', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugin directory not found: ${pluginDir} — expected a folder named \"${pluginName}\" inside \"${absFolder}\"`,\n });\n return steps;\n }\n\n const result = await tryResolve(pluginDir);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginDir;\n debug('resolved from plugins folder: %o', pluginDir);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Plugin found at ${pluginDir} but has a missing dependency: ${missingDep}`\n : `Plugin found at ${pluginDir} but failed to load: ${result.error}`,\n });\n return steps;\n }\n }\n\n // Try node_modules if not found in plugins folder\n if (!pluginModule) {\n const result = await tryResolve(pluginName);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginName;\n debug('resolved from node_modules: %o', pluginName);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginName);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Package \"${pluginName}\" found but has a missing dependency: ${missingDep}`\n : `Package \"${pluginName}\" not found in node_modules — try: npm install ${pluginName}`,\n });\n return steps;\n }\n }\n\n steps.push({\n phase: 'resolve',\n pass: true,\n message: `Module resolved from ${resolvedFrom}`,\n });\n\n // --- Phase 2: Export validation ---\n if (!isValidExport(pluginModule)) {\n const exportKeys = pluginModule ? Object.keys(pluginModule).join(', ') : 'none';\n steps.push({\n phase: 'export',\n pass: false,\n message: `Module does not export a function or class (default export). Exported keys: [${exportKeys}]`,\n });\n return steps;\n }\n\n const moduleType = isES6(pluginModule) ? 'ES6 (default export)' : 'CommonJS (factory function)';\n steps.push({\n phase: 'export',\n pass: true,\n message: `Valid ${moduleType} plugin export detected`,\n });\n\n // --- Phase 3: Instantiation ---\n let instance: any;\n try {\n if (isES6(pluginModule)) {\n instance = new pluginModule.default(pluginConfig, { config: pluginConfig, logger: console });\n } else {\n instance = pluginModule(pluginConfig, { config: pluginConfig, logger: console });\n }\n } catch (err: any) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin threw during instantiation: ${err.message}`,\n });\n return steps;\n }\n\n if (!instance || (typeof instance !== 'object' && typeof instance !== 'function')) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin constructor/factory returned ${instance === null ? 'null' : typeof instance} instead of an object`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'instantiate',\n pass: true,\n message: 'Plugin instantiated successfully',\n });\n\n // --- Phase 4: Sanity check ---\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n const passed = sanityCheck(instance);\n\n if (!passed) {\n const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance) ?? {})\n .filter((m) => m !== 'constructor')\n .concat(Object.keys(instance));\n const unique = [...new Set(methods)];\n\n steps.push({\n phase: 'sanity-check',\n pass: false,\n message: `Plugin does not implement the required methods for category \"${category}\". Available methods: [${unique.join(', ')}]`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'sanity-check',\n pass: true,\n message: `Plugin passes sanity check for category \"${category}\"`,\n });\n\n return steps;\n}\n\n/**\n * When a MODULE_NOT_FOUND error is about a transitive dependency\n * (not the plugin itself), extract the missing module name.\n */\nfunction parseMissingDependency(message: string, pluginPath: string): string | null {\n const match = message.match(/Cannot find module '([^']+)'/);\n if (match && match[1] && !match[1].includes(pluginPath)) {\n return match[1];\n }\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"diagnostics.js","names":[],"sources":["../src/diagnostics.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\n\nimport { getSanityCheck } from './sanity-checks';\nimport type { DiagnosticStep, VerifyPluginOptions } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier:diagnostics');\n\n// createRequire needs an absolute path; works in both ESM and CJS contexts\nconst requireModule = createRequire(\n typeof __filename !== 'undefined' ? __filename : import.meta.url\n);\n\nfunction isValidExport(plugin: any): boolean {\n return typeof plugin === 'function' || typeof plugin?.default === 'function';\n}\n\nfunction isES6(plugin: any): boolean {\n return plugin && typeof plugin === 'object' && 'default' in plugin;\n}\n\n/**\n * Resolve the ESM entry point for a directory-based plugin.\n * import() doesn't support directory imports, so we resolve via package.json.\n */\nexport function resolveEntryPoint(dirPath: string): string {\n const pkgPath = join(dirPath, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n if (pkg.exports) {\n const dotExport = pkg.exports['.'];\n if (typeof dotExport === 'string') {\n return join(dirPath, dotExport);\n }\n if (dotExport?.import?.default) {\n return join(dirPath, dotExport.import.default);\n }\n if (dotExport?.import && typeof dotExport.import === 'string') {\n return join(dirPath, dotExport.import);\n }\n if (dotExport?.default) {\n return join(dirPath, dotExport.default);\n }\n }\n if (pkg.module) {\n return join(dirPath, pkg.module);\n }\n if (pkg.main) {\n return join(dirPath, pkg.main);\n }\n } catch {\n // fall through\n }\n }\n return join(dirPath, 'index.js');\n}\n\n/**\n * Try to load a module, falling back from require() to import() for ESM.\n * Handles CJS require(), ESM require() shim errors (bundlers), and\n * ERR_REQUIRE_ESM — always falls through to dynamic import() on any\n * require() failure.\n */\nasync function tryResolve(modulePath: string): Promise<{ module: any; error?: string }> {\n // Try require() first (fast path for CJS modules)\n try {\n return { module: requireModule(modulePath) };\n } catch (requireErr: any) {\n debug('require() failed for %o: %s — trying dynamic import', modulePath, requireErr.message);\n }\n\n // Fallback to dynamic import() for ESM modules\n try {\n let importPath = modulePath;\n if (existsSync(modulePath) && existsSync(join(modulePath, 'package.json'))) {\n importPath = resolveEntryPoint(modulePath);\n debug('resolved ESM entry point: %o', importPath);\n }\n const importUrl = importPath.startsWith('/') ? pathToFileURL(importPath).href : importPath;\n const mod = await import(importUrl);\n return { module: mod };\n } catch (importErr: any) {\n return { module: null, error: importErr.message };\n }\n}\n\n/**\n * Runs step-by-step diagnostics to identify exactly which phase of\n * plugin loading fails. This replicates the same resolution logic\n * as `asyncLoadPlugin` but tests each step independently.\n */\nexport async function runDiagnostics(options: VerifyPluginOptions): Promise<DiagnosticStep[]> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n } = options;\n\n const steps: DiagnosticStep[] = [];\n const isScoped = pluginPath.startsWith('@') && pluginPath.includes('/');\n const pluginName = isScoped ? pluginPath : `${prefix}-${pluginPath}`;\n\n debug('running diagnostics for %o (resolved name: %o)', pluginPath, pluginName);\n\n // --- Phase 1: Resolve ---\n let pluginModule: any = null;\n let resolvedFrom = '';\n\n // Try plugins folder first\n if (pluginsFolder) {\n const absFolder = resolve(pluginsFolder);\n const pluginDir = join(absFolder, pluginName);\n debug('checking plugins folder: %o', pluginDir);\n\n if (!existsSync(absFolder)) {\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugins folder does not exist: ${absFolder}`,\n });\n return steps;\n }\n\n if (!existsSync(pluginDir)) {\n debug('plugin directory not found: %o', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: `Plugin directory not found: ${pluginDir} — expected a folder named \"${pluginName}\" inside \"${absFolder}\"`,\n });\n return steps;\n }\n\n const result = await tryResolve(pluginDir);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginDir;\n debug('resolved from plugins folder: %o', pluginDir);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginDir);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Plugin found at ${pluginDir} but has a missing dependency: ${missingDep}`\n : `Plugin found at ${pluginDir} but failed to load: ${result.error}`,\n });\n return steps;\n }\n }\n\n // Try node_modules if not found in plugins folder\n if (!pluginModule) {\n const result = await tryResolve(pluginName);\n if (result.module) {\n pluginModule = result.module;\n resolvedFrom = pluginName;\n debug('resolved from node_modules: %o', pluginName);\n } else {\n const missingDep = parseMissingDependency(result.error ?? '', pluginName);\n steps.push({\n phase: 'resolve',\n pass: false,\n message: missingDep\n ? `Package \"${pluginName}\" found but has a missing dependency: ${missingDep}`\n : `Package \"${pluginName}\" not found in node_modules — try: npm install ${pluginName}`,\n });\n return steps;\n }\n }\n\n steps.push({\n phase: 'resolve',\n pass: true,\n message: `Module resolved from ${resolvedFrom}`,\n });\n\n // --- Phase 2: Export validation ---\n if (!isValidExport(pluginModule)) {\n const exportKeys = pluginModule ? Object.keys(pluginModule).join(', ') : 'none';\n steps.push({\n phase: 'export',\n pass: false,\n message: `Module does not export a function or class (default export). Exported keys: [${exportKeys}]`,\n });\n return steps;\n }\n\n const moduleType = isES6(pluginModule) ? 'ES6 (default export)' : 'CommonJS (factory function)';\n steps.push({\n phase: 'export',\n pass: true,\n message: `Valid ${moduleType} plugin export detected`,\n });\n\n // --- Phase 3: Instantiation ---\n let instance: any;\n try {\n if (isES6(pluginModule)) {\n instance = new pluginModule.default(pluginConfig, { config: pluginConfig, logger: console });\n } else {\n instance = pluginModule(pluginConfig, { config: pluginConfig, logger: console });\n }\n } catch (err: any) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin threw during instantiation: ${err.message}`,\n });\n return steps;\n }\n\n if (!instance || (typeof instance !== 'object' && typeof instance !== 'function')) {\n steps.push({\n phase: 'instantiate',\n pass: false,\n message: `Plugin constructor/factory returned ${instance === null ? 'null' : typeof instance} instead of an object`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'instantiate',\n pass: true,\n message: 'Plugin instantiated successfully',\n });\n\n // --- Phase 4: Sanity check ---\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n const passed = sanityCheck(instance);\n\n if (!passed) {\n const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance) ?? {})\n .filter((m) => m !== 'constructor')\n .concat(Object.keys(instance));\n const unique = [...new Set(methods)];\n\n steps.push({\n phase: 'sanity-check',\n pass: false,\n message: `Plugin does not implement the required methods for category \"${category}\". Available methods: [${unique.join(', ')}]`,\n });\n return steps;\n }\n\n steps.push({\n phase: 'sanity-check',\n pass: true,\n message: `Plugin passes sanity check for category \"${category}\"`,\n });\n\n return steps;\n}\n\n/**\n * When a MODULE_NOT_FOUND error is about a transitive dependency\n * (not the plugin itself), extract the missing module name.\n */\nfunction parseMissingDependency(message: string, pluginPath: string): string | null {\n const match = message.match(/Cannot find module '([^']+)'/);\n if (match && match[1] && !match[1].includes(pluginPath)) {\n return match[1];\n }\n return null;\n}\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  let _verdaccio_core = require("@verdaccio/core");
3
2
  //#region src/sanity-checks.ts
4
3
  var authSanityCheck = _verdaccio_core.pluginUtils.authSanityCheck;
@@ -1 +1 @@
1
- {"version":3,"file":"sanity-checks.cjs","names":[],"sources":["../src/sanity-checks.ts"],"sourcesContent":["import { PLUGIN_CATEGORY, pluginUtils } from '@verdaccio/core';\n\nimport type { PluginCategory } from './types';\n\n// Re-export sanity checks from @verdaccio/core for convenience.\nexport const authSanityCheck = pluginUtils.authSanityCheck;\nexport const storageSanityCheck = pluginUtils.storageSanityCheck;\nexport const middlewareSanityCheck = pluginUtils.middlewareSanityCheck;\nexport const filterSanityCheck = pluginUtils.filterSanityCheck;\n\n/**\n * Returns the appropriate sanity check function for the given plugin category.\n */\nexport function getSanityCheck(category: PluginCategory): (plugin: any) => boolean {\n switch (category) {\n case PLUGIN_CATEGORY.AUTHENTICATION:\n return authSanityCheck;\n case PLUGIN_CATEGORY.STORAGE:\n return storageSanityCheck;\n case PLUGIN_CATEGORY.MIDDLEWARE:\n return middlewareSanityCheck;\n case PLUGIN_CATEGORY.FILTER:\n return filterSanityCheck;\n default:\n return () => true;\n }\n}\n"],"mappings":";;;AAKA,IAAa,kBAAkB,gBAAA,YAAY;AAC3C,IAAa,qBAAqB,gBAAA,YAAY;AAC9C,IAAa,wBAAwB,gBAAA,YAAY;AACjD,IAAa,oBAAoB,gBAAA,YAAY;;;;AAK7C,SAAgB,eAAe,UAAoD;AACjF,SAAQ,UAAR;EACE,KAAK,gBAAA,gBAAgB,eACnB,QAAO;EACT,KAAK,gBAAA,gBAAgB,QACnB,QAAO;EACT,KAAK,gBAAA,gBAAgB,WACnB,QAAO;EACT,KAAK,gBAAA,gBAAgB,OACnB,QAAO;EACT,QACE,cAAa"}
1
+ {"version":3,"file":"sanity-checks.cjs","names":[],"sources":["../src/sanity-checks.ts"],"sourcesContent":["import { PLUGIN_CATEGORY, pluginUtils } from '@verdaccio/core';\n\nimport type { PluginCategory } from './types';\n\n// Re-export sanity checks from @verdaccio/core for convenience.\nexport const authSanityCheck = pluginUtils.authSanityCheck;\nexport const storageSanityCheck = pluginUtils.storageSanityCheck;\nexport const middlewareSanityCheck = pluginUtils.middlewareSanityCheck;\nexport const filterSanityCheck = pluginUtils.filterSanityCheck;\n\n/**\n * Returns the appropriate sanity check function for the given plugin category.\n */\nexport function getSanityCheck(category: PluginCategory): (plugin: any) => boolean {\n switch (category) {\n case PLUGIN_CATEGORY.AUTHENTICATION:\n return authSanityCheck;\n case PLUGIN_CATEGORY.STORAGE:\n return storageSanityCheck;\n case PLUGIN_CATEGORY.MIDDLEWARE:\n return middlewareSanityCheck;\n case PLUGIN_CATEGORY.FILTER:\n return filterSanityCheck;\n default:\n return () => true;\n }\n}\n"],"mappings":";;AAKA,IAAa,kBAAkB,gBAAA,YAAY;AAC3C,IAAa,qBAAqB,gBAAA,YAAY;AAC9C,IAAa,wBAAwB,gBAAA,YAAY;AACjD,IAAa,oBAAoB,gBAAA,YAAY;;;;AAK7C,SAAgB,eAAe,UAAoD;CACjF,QAAQ,UAAR;EACE,KAAK,gBAAA,gBAAgB,gBACnB,OAAO;EACT,KAAK,gBAAA,gBAAgB,SACnB,OAAO;EACT,KAAK,gBAAA,gBAAgB,YACnB,OAAO;EACT,KAAK,gBAAA,gBAAgB,QACnB,OAAO;EACT,SACE,aAAa;CACjB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"sanity-checks.js","names":[],"sources":["../src/sanity-checks.ts"],"sourcesContent":["import { PLUGIN_CATEGORY, pluginUtils } from '@verdaccio/core';\n\nimport type { PluginCategory } from './types';\n\n// Re-export sanity checks from @verdaccio/core for convenience.\nexport const authSanityCheck = pluginUtils.authSanityCheck;\nexport const storageSanityCheck = pluginUtils.storageSanityCheck;\nexport const middlewareSanityCheck = pluginUtils.middlewareSanityCheck;\nexport const filterSanityCheck = pluginUtils.filterSanityCheck;\n\n/**\n * Returns the appropriate sanity check function for the given plugin category.\n */\nexport function getSanityCheck(category: PluginCategory): (plugin: any) => boolean {\n switch (category) {\n case PLUGIN_CATEGORY.AUTHENTICATION:\n return authSanityCheck;\n case PLUGIN_CATEGORY.STORAGE:\n return storageSanityCheck;\n case PLUGIN_CATEGORY.MIDDLEWARE:\n return middlewareSanityCheck;\n case PLUGIN_CATEGORY.FILTER:\n return filterSanityCheck;\n default:\n return () => true;\n }\n}\n"],"mappings":";;AAKA,IAAa,kBAAkB,YAAY;AAC3C,IAAa,qBAAqB,YAAY;AAC9C,IAAa,wBAAwB,YAAY;AACjD,IAAa,oBAAoB,YAAY;;;;AAK7C,SAAgB,eAAe,UAAoD;AACjF,SAAQ,UAAR;EACE,KAAK,gBAAgB,eACnB,QAAO;EACT,KAAK,gBAAgB,QACnB,QAAO;EACT,KAAK,gBAAgB,WACnB,QAAO;EACT,KAAK,gBAAgB,OACnB,QAAO;EACT,QACE,cAAa"}
1
+ {"version":3,"file":"sanity-checks.js","names":[],"sources":["../src/sanity-checks.ts"],"sourcesContent":["import { PLUGIN_CATEGORY, pluginUtils } from '@verdaccio/core';\n\nimport type { PluginCategory } from './types';\n\n// Re-export sanity checks from @verdaccio/core for convenience.\nexport const authSanityCheck = pluginUtils.authSanityCheck;\nexport const storageSanityCheck = pluginUtils.storageSanityCheck;\nexport const middlewareSanityCheck = pluginUtils.middlewareSanityCheck;\nexport const filterSanityCheck = pluginUtils.filterSanityCheck;\n\n/**\n * Returns the appropriate sanity check function for the given plugin category.\n */\nexport function getSanityCheck(category: PluginCategory): (plugin: any) => boolean {\n switch (category) {\n case PLUGIN_CATEGORY.AUTHENTICATION:\n return authSanityCheck;\n case PLUGIN_CATEGORY.STORAGE:\n return storageSanityCheck;\n case PLUGIN_CATEGORY.MIDDLEWARE:\n return middlewareSanityCheck;\n case PLUGIN_CATEGORY.FILTER:\n return filterSanityCheck;\n default:\n return () => true;\n }\n}\n"],"mappings":";;AAKA,IAAa,kBAAkB,YAAY;AAC3C,IAAa,qBAAqB,YAAY;AAC9C,IAAa,wBAAwB,YAAY;AACjD,IAAa,oBAAoB,YAAY;;;;AAK7C,SAAgB,eAAe,UAAoD;CACjF,QAAQ,UAAR;EACE,KAAK,gBAAgB,gBACnB,OAAO;EACT,KAAK,gBAAgB,SACnB,OAAO;EACT,KAAK,gBAAgB,YACnB,OAAO;EACT,KAAK,gBAAgB,QACnB,OAAO;EACT,SACE,aAAa;CACjB;AACF"}
@@ -2,7 +2,7 @@ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
2
2
  const require_sanity_checks = require("./sanity-checks.cjs");
3
3
  const require_diagnostics = require("./diagnostics.cjs");
4
4
  let debug = require("debug");
5
- debug = require_runtime.__toESM(debug);
5
+ debug = require_runtime.__toESM(debug, 1);
6
6
  let node_path = require("node:path");
7
7
  let _verdaccio_core = require("@verdaccio/core");
8
8
  let _verdaccio_loaders = require("@verdaccio/loaders");
@@ -1 +1 @@
1
- {"version":3,"file":"verify-plugin.cjs","names":[],"sources":["../src/verify-plugin.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { resolve } from 'node:path';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\nimport { asyncLoadPlugin } from '@verdaccio/loaders';\nimport { logger, setup } from '@verdaccio/logger';\n\nimport { runDiagnostics } from './diagnostics';\nimport { getSanityCheck } from './sanity-checks';\nimport type { VerifyPluginOptions, VerifyResult } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier');\n\n/**\n * Verifies that a plugin can be loaded by Verdaccio.\n *\n * Uses `asyncLoadPlugin` from `@verdaccio/loaders` — the same loader\n * Verdaccio uses at startup — so the verification is identical to what\n * happens in production.\n *\n * Steps verified:\n * 1. Module resolution — can the plugin be found/required?\n * 2. Export validation — does it export a function or a class (default export)?\n * 3. Instantiation — can the plugin be instantiated with a config and options?\n * 4. Sanity check — does the instance implement the required methods for its category?\n *\n * When loading fails, detailed diagnostics are included in the result\n * to pinpoint exactly which step failed and why.\n */\nexport async function verifyPlugin(options: VerifyPluginOptions): Promise<VerifyResult> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n configPath,\n } = options;\n\n debug('verifying plugin %o for category %o', pluginPath, category);\n debug('prefix: %o, pluginsFolder: %o', prefix, pluginsFolder);\n\n await setup({});\n\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n debug('using %s sanity check', customSanityCheck ? 'custom' : 'default');\n\n const config: any = {\n ...pluginConfig,\n };\n\n if (pluginsFolder) {\n config.plugins = resolve(pluginsFolder);\n debug('resolved plugins folder: %o', config.plugins);\n }\n\n if (configPath) {\n config.configPath = configPath;\n debug('config path: %o', config.configPath);\n }\n\n const pluginConfigs = { [pluginPath]: pluginConfig };\n debug('plugin config: %o', pluginConfigs);\n\n try {\n const plugins = await asyncLoadPlugin(\n pluginConfigs,\n { config, logger },\n sanityCheck,\n false,\n prefix,\n category\n );\n\n debug('plugins loaded: %o', plugins.length);\n\n if (plugins.length > 0) {\n debug('verification succeeded for %o', pluginPath);\n return {\n success: true,\n pluginName: pluginPath,\n category,\n pluginsLoaded: plugins.length,\n };\n }\n\n debug('verification failed, running diagnostics for %o', pluginPath);\n const diagnostics = await runDiagnostics(options);\n const failedStep = diagnostics.find((d) => !d.pass);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error:\n failedStep?.message ??\n `Plugin \"${pluginPath}\" could not be loaded for category \"${category}\"`,\n diagnostics,\n };\n } catch (err: any) {\n debug('verification error for %o: %o', pluginPath, err.message);\n const diagnostics = await runDiagnostics(options);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error: err.message,\n diagnostics,\n };\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,IAAM,WAAA,GAAA,MAAA,SAAmB,4BAA4B;;;;;;;;;;;;;;;;;AAkBrD,eAAsB,aAAa,SAAqD;CACtF,MAAM,EACJ,YACA,UACA,eAAe,EAAE,EACjB,aAAa,mBACb,SAAS,gBAAA,eACT,eACA,eACE;AAEJ,SAAM,uCAAuC,YAAY,SAAS;AAClE,SAAM,iCAAiC,QAAQ,cAAc;AAE7D,QAAA,GAAA,kBAAA,OAAY,EAAE,CAAC;CAEf,MAAM,cAAc,qBAAqB,sBAAA,eAAe,SAAS;AACjE,SAAM,yBAAyB,oBAAoB,WAAW,UAAU;CAExE,MAAM,SAAc,EAClB,GAAG,cACJ;AAED,KAAI,eAAe;AACjB,SAAO,WAAA,GAAA,UAAA,SAAkB,cAAc;AACvC,UAAM,+BAA+B,OAAO,QAAQ;;AAGtD,KAAI,YAAY;AACd,SAAO,aAAa;AACpB,UAAM,mBAAmB,OAAO,WAAW;;CAG7C,MAAM,gBAAgB,GAAG,aAAa,cAAc;AACpD,SAAM,qBAAqB,cAAc;AAEzC,KAAI;EACF,MAAM,UAAU,OAAA,GAAA,mBAAA,iBACd,eACA;GAAE;GAAQ,QAAA,kBAAA;GAAQ,EAClB,aACA,OACA,QACA,SACD;AAED,UAAM,sBAAsB,QAAQ,OAAO;AAE3C,MAAI,QAAQ,SAAS,GAAG;AACtB,WAAM,iCAAiC,WAAW;AAClD,UAAO;IACL,SAAS;IACT,YAAY;IACZ;IACA,eAAe,QAAQ;IACxB;;AAGH,UAAM,mDAAmD,WAAW;EACpE,MAAM,cAAc,MAAM,oBAAA,eAAe,QAAQ;AAGjD,SAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAPiB,YAAY,MAAM,MAAM,CAAC,EAAE,KAAK,EAQnC,WACZ,WAAW,WAAW,sCAAsC,SAAS;GACvE;GACD;UACM,KAAU;AACjB,UAAM,iCAAiC,YAAY,IAAI,QAAQ;EAC/D,MAAM,cAAc,MAAM,oBAAA,eAAe,QAAQ;AAEjD,SAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAAO,IAAI;GACX;GACD"}
1
+ {"version":3,"file":"verify-plugin.cjs","names":[],"sources":["../src/verify-plugin.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { resolve } from 'node:path';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\nimport { asyncLoadPlugin } from '@verdaccio/loaders';\nimport { logger, setup } from '@verdaccio/logger';\n\nimport { runDiagnostics } from './diagnostics';\nimport { getSanityCheck } from './sanity-checks';\nimport type { VerifyPluginOptions, VerifyResult } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier');\n\n/**\n * Verifies that a plugin can be loaded by Verdaccio.\n *\n * Uses `asyncLoadPlugin` from `@verdaccio/loaders` — the same loader\n * Verdaccio uses at startup — so the verification is identical to what\n * happens in production.\n *\n * Steps verified:\n * 1. Module resolution — can the plugin be found/required?\n * 2. Export validation — does it export a function or a class (default export)?\n * 3. Instantiation — can the plugin be instantiated with a config and options?\n * 4. Sanity check — does the instance implement the required methods for its category?\n *\n * When loading fails, detailed diagnostics are included in the result\n * to pinpoint exactly which step failed and why.\n */\nexport async function verifyPlugin(options: VerifyPluginOptions): Promise<VerifyResult> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n configPath,\n } = options;\n\n debug('verifying plugin %o for category %o', pluginPath, category);\n debug('prefix: %o, pluginsFolder: %o', prefix, pluginsFolder);\n\n await setup({});\n\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n debug('using %s sanity check', customSanityCheck ? 'custom' : 'default');\n\n const config: any = {\n ...pluginConfig,\n };\n\n if (pluginsFolder) {\n config.plugins = resolve(pluginsFolder);\n debug('resolved plugins folder: %o', config.plugins);\n }\n\n if (configPath) {\n config.configPath = configPath;\n debug('config path: %o', config.configPath);\n }\n\n const pluginConfigs = { [pluginPath]: pluginConfig };\n debug('plugin config: %o', pluginConfigs);\n\n try {\n const plugins = await asyncLoadPlugin(\n pluginConfigs,\n { config, logger },\n sanityCheck,\n false,\n prefix,\n category\n );\n\n debug('plugins loaded: %o', plugins.length);\n\n if (plugins.length > 0) {\n debug('verification succeeded for %o', pluginPath);\n return {\n success: true,\n pluginName: pluginPath,\n category,\n pluginsLoaded: plugins.length,\n };\n }\n\n debug('verification failed, running diagnostics for %o', pluginPath);\n const diagnostics = await runDiagnostics(options);\n const failedStep = diagnostics.find((d) => !d.pass);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error:\n failedStep?.message ??\n `Plugin \"${pluginPath}\" could not be loaded for category \"${category}\"`,\n diagnostics,\n };\n } catch (err: any) {\n debug('verification error for %o: %o', pluginPath, err.message);\n const diagnostics = await runDiagnostics(options);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error: err.message,\n diagnostics,\n };\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,IAAM,WAAA,GAAA,MAAA,SAAmB,2BAA2B;;;;;;;;;;;;;;;;;AAkBpD,eAAsB,aAAa,SAAqD;CACtF,MAAM,EACJ,YACA,UACA,eAAe,CAAC,GAChB,aAAa,mBACb,SAAS,gBAAA,eACT,eACA,eACE;CAEJ,QAAM,uCAAuC,YAAY,QAAQ;CACjE,QAAM,iCAAiC,QAAQ,aAAa;CAE5D,OAAA,GAAA,kBAAA,OAAY,CAAC,CAAC;CAEd,MAAM,cAAc,qBAAqB,sBAAA,eAAe,QAAQ;CAChE,QAAM,yBAAyB,oBAAoB,WAAW,SAAS;CAEvE,MAAM,SAAc,EAClB,GAAG,aACL;CAEA,IAAI,eAAe;EACjB,OAAO,WAAA,GAAA,UAAA,SAAkB,aAAa;EACtC,QAAM,+BAA+B,OAAO,OAAO;CACrD;CAEA,IAAI,YAAY;EACd,OAAO,aAAa;EACpB,QAAM,mBAAmB,OAAO,UAAU;CAC5C;CAEA,MAAM,gBAAgB,GAAG,aAAa,aAAa;CACnD,QAAM,qBAAqB,aAAa;CAExC,IAAI;EACF,MAAM,UAAU,OAAA,GAAA,mBAAA,iBACd,eACA;GAAE;GAAQ,QAAA,kBAAA;EAAO,GACjB,aACA,OACA,QACA,QACF;EAEA,QAAM,sBAAsB,QAAQ,MAAM;EAE1C,IAAI,QAAQ,SAAS,GAAG;GACtB,QAAM,iCAAiC,UAAU;GACjD,OAAO;IACL,SAAS;IACT,YAAY;IACZ;IACA,eAAe,QAAQ;GACzB;EACF;EAEA,QAAM,mDAAmD,UAAU;EACnE,MAAM,cAAc,MAAM,oBAAA,eAAe,OAAO;EAGhD,OAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAPiB,YAAY,MAAM,MAAM,CAAC,EAAE,IAQ1C,GAAY,WACZ,WAAW,WAAW,sCAAsC,SAAS;GACvE;EACF;CACF,SAAS,KAAU;EACjB,QAAM,iCAAiC,YAAY,IAAI,OAAO;EAC9D,MAAM,cAAc,MAAM,oBAAA,eAAe,OAAO;EAEhD,OAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAAO,IAAI;GACX;EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify-plugin.js","names":[],"sources":["../src/verify-plugin.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { resolve } from 'node:path';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\nimport { asyncLoadPlugin } from '@verdaccio/loaders';\nimport { logger, setup } from '@verdaccio/logger';\n\nimport { runDiagnostics } from './diagnostics';\nimport { getSanityCheck } from './sanity-checks';\nimport type { VerifyPluginOptions, VerifyResult } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier');\n\n/**\n * Verifies that a plugin can be loaded by Verdaccio.\n *\n * Uses `asyncLoadPlugin` from `@verdaccio/loaders` — the same loader\n * Verdaccio uses at startup — so the verification is identical to what\n * happens in production.\n *\n * Steps verified:\n * 1. Module resolution — can the plugin be found/required?\n * 2. Export validation — does it export a function or a class (default export)?\n * 3. Instantiation — can the plugin be instantiated with a config and options?\n * 4. Sanity check — does the instance implement the required methods for its category?\n *\n * When loading fails, detailed diagnostics are included in the result\n * to pinpoint exactly which step failed and why.\n */\nexport async function verifyPlugin(options: VerifyPluginOptions): Promise<VerifyResult> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n configPath,\n } = options;\n\n debug('verifying plugin %o for category %o', pluginPath, category);\n debug('prefix: %o, pluginsFolder: %o', prefix, pluginsFolder);\n\n await setup({});\n\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n debug('using %s sanity check', customSanityCheck ? 'custom' : 'default');\n\n const config: any = {\n ...pluginConfig,\n };\n\n if (pluginsFolder) {\n config.plugins = resolve(pluginsFolder);\n debug('resolved plugins folder: %o', config.plugins);\n }\n\n if (configPath) {\n config.configPath = configPath;\n debug('config path: %o', config.configPath);\n }\n\n const pluginConfigs = { [pluginPath]: pluginConfig };\n debug('plugin config: %o', pluginConfigs);\n\n try {\n const plugins = await asyncLoadPlugin(\n pluginConfigs,\n { config, logger },\n sanityCheck,\n false,\n prefix,\n category\n );\n\n debug('plugins loaded: %o', plugins.length);\n\n if (plugins.length > 0) {\n debug('verification succeeded for %o', pluginPath);\n return {\n success: true,\n pluginName: pluginPath,\n category,\n pluginsLoaded: plugins.length,\n };\n }\n\n debug('verification failed, running diagnostics for %o', pluginPath);\n const diagnostics = await runDiagnostics(options);\n const failedStep = diagnostics.find((d) => !d.pass);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error:\n failedStep?.message ??\n `Plugin \"${pluginPath}\" could not be loaded for category \"${category}\"`,\n diagnostics,\n };\n } catch (err: any) {\n debug('verification error for %o: %o', pluginPath, err.message);\n const diagnostics = await runDiagnostics(options);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error: err.message,\n diagnostics,\n };\n }\n}\n"],"mappings":";;;;;;;;AAWA,IAAM,QAAQ,WAAW,4BAA4B;;;;;;;;;;;;;;;;;AAkBrD,eAAsB,aAAa,SAAqD;CACtF,MAAM,EACJ,YACA,UACA,eAAe,EAAE,EACjB,aAAa,mBACb,SAAS,eACT,eACA,eACE;AAEJ,OAAM,uCAAuC,YAAY,SAAS;AAClE,OAAM,iCAAiC,QAAQ,cAAc;AAE7D,OAAM,MAAM,EAAE,CAAC;CAEf,MAAM,cAAc,qBAAqB,eAAe,SAAS;AACjE,OAAM,yBAAyB,oBAAoB,WAAW,UAAU;CAExE,MAAM,SAAc,EAClB,GAAG,cACJ;AAED,KAAI,eAAe;AACjB,SAAO,UAAU,QAAQ,cAAc;AACvC,QAAM,+BAA+B,OAAO,QAAQ;;AAGtD,KAAI,YAAY;AACd,SAAO,aAAa;AACpB,QAAM,mBAAmB,OAAO,WAAW;;CAG7C,MAAM,gBAAgB,GAAG,aAAa,cAAc;AACpD,OAAM,qBAAqB,cAAc;AAEzC,KAAI;EACF,MAAM,UAAU,MAAM,gBACpB,eACA;GAAE;GAAQ;GAAQ,EAClB,aACA,OACA,QACA,SACD;AAED,QAAM,sBAAsB,QAAQ,OAAO;AAE3C,MAAI,QAAQ,SAAS,GAAG;AACtB,SAAM,iCAAiC,WAAW;AAClD,UAAO;IACL,SAAS;IACT,YAAY;IACZ;IACA,eAAe,QAAQ;IACxB;;AAGH,QAAM,mDAAmD,WAAW;EACpE,MAAM,cAAc,MAAM,eAAe,QAAQ;AAGjD,SAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAPiB,YAAY,MAAM,MAAM,CAAC,EAAE,KAAK,EAQnC,WACZ,WAAW,WAAW,sCAAsC,SAAS;GACvE;GACD;UACM,KAAU;AACjB,QAAM,iCAAiC,YAAY,IAAI,QAAQ;EAC/D,MAAM,cAAc,MAAM,eAAe,QAAQ;AAEjD,SAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAAO,IAAI;GACX;GACD"}
1
+ {"version":3,"file":"verify-plugin.js","names":[],"sources":["../src/verify-plugin.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { resolve } from 'node:path';\n\nimport { PLUGIN_PREFIX } from '@verdaccio/core';\nimport { asyncLoadPlugin } from '@verdaccio/loaders';\nimport { logger, setup } from '@verdaccio/logger';\n\nimport { runDiagnostics } from './diagnostics';\nimport { getSanityCheck } from './sanity-checks';\nimport type { VerifyPluginOptions, VerifyResult } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:verifier');\n\n/**\n * Verifies that a plugin can be loaded by Verdaccio.\n *\n * Uses `asyncLoadPlugin` from `@verdaccio/loaders` — the same loader\n * Verdaccio uses at startup — so the verification is identical to what\n * happens in production.\n *\n * Steps verified:\n * 1. Module resolution — can the plugin be found/required?\n * 2. Export validation — does it export a function or a class (default export)?\n * 3. Instantiation — can the plugin be instantiated with a config and options?\n * 4. Sanity check — does the instance implement the required methods for its category?\n *\n * When loading fails, detailed diagnostics are included in the result\n * to pinpoint exactly which step failed and why.\n */\nexport async function verifyPlugin(options: VerifyPluginOptions): Promise<VerifyResult> {\n const {\n pluginPath,\n category,\n pluginConfig = {},\n sanityCheck: customSanityCheck,\n prefix = PLUGIN_PREFIX,\n pluginsFolder,\n configPath,\n } = options;\n\n debug('verifying plugin %o for category %o', pluginPath, category);\n debug('prefix: %o, pluginsFolder: %o', prefix, pluginsFolder);\n\n await setup({});\n\n const sanityCheck = customSanityCheck ?? getSanityCheck(category);\n debug('using %s sanity check', customSanityCheck ? 'custom' : 'default');\n\n const config: any = {\n ...pluginConfig,\n };\n\n if (pluginsFolder) {\n config.plugins = resolve(pluginsFolder);\n debug('resolved plugins folder: %o', config.plugins);\n }\n\n if (configPath) {\n config.configPath = configPath;\n debug('config path: %o', config.configPath);\n }\n\n const pluginConfigs = { [pluginPath]: pluginConfig };\n debug('plugin config: %o', pluginConfigs);\n\n try {\n const plugins = await asyncLoadPlugin(\n pluginConfigs,\n { config, logger },\n sanityCheck,\n false,\n prefix,\n category\n );\n\n debug('plugins loaded: %o', plugins.length);\n\n if (plugins.length > 0) {\n debug('verification succeeded for %o', pluginPath);\n return {\n success: true,\n pluginName: pluginPath,\n category,\n pluginsLoaded: plugins.length,\n };\n }\n\n debug('verification failed, running diagnostics for %o', pluginPath);\n const diagnostics = await runDiagnostics(options);\n const failedStep = diagnostics.find((d) => !d.pass);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error:\n failedStep?.message ??\n `Plugin \"${pluginPath}\" could not be loaded for category \"${category}\"`,\n diagnostics,\n };\n } catch (err: any) {\n debug('verification error for %o: %o', pluginPath, err.message);\n const diagnostics = await runDiagnostics(options);\n\n return {\n success: false,\n pluginName: pluginPath,\n category,\n pluginsLoaded: 0,\n error: err.message,\n diagnostics,\n };\n }\n}\n"],"mappings":";;;;;;;;AAWA,IAAM,QAAQ,WAAW,2BAA2B;;;;;;;;;;;;;;;;;AAkBpD,eAAsB,aAAa,SAAqD;CACtF,MAAM,EACJ,YACA,UACA,eAAe,CAAC,GAChB,aAAa,mBACb,SAAS,eACT,eACA,eACE;CAEJ,MAAM,uCAAuC,YAAY,QAAQ;CACjE,MAAM,iCAAiC,QAAQ,aAAa;CAE5D,MAAM,MAAM,CAAC,CAAC;CAEd,MAAM,cAAc,qBAAqB,eAAe,QAAQ;CAChE,MAAM,yBAAyB,oBAAoB,WAAW,SAAS;CAEvE,MAAM,SAAc,EAClB,GAAG,aACL;CAEA,IAAI,eAAe;EACjB,OAAO,UAAU,QAAQ,aAAa;EACtC,MAAM,+BAA+B,OAAO,OAAO;CACrD;CAEA,IAAI,YAAY;EACd,OAAO,aAAa;EACpB,MAAM,mBAAmB,OAAO,UAAU;CAC5C;CAEA,MAAM,gBAAgB,GAAG,aAAa,aAAa;CACnD,MAAM,qBAAqB,aAAa;CAExC,IAAI;EACF,MAAM,UAAU,MAAM,gBACpB,eACA;GAAE;GAAQ;EAAO,GACjB,aACA,OACA,QACA,QACF;EAEA,MAAM,sBAAsB,QAAQ,MAAM;EAE1C,IAAI,QAAQ,SAAS,GAAG;GACtB,MAAM,iCAAiC,UAAU;GACjD,OAAO;IACL,SAAS;IACT,YAAY;IACZ;IACA,eAAe,QAAQ;GACzB;EACF;EAEA,MAAM,mDAAmD,UAAU;EACnE,MAAM,cAAc,MAAM,eAAe,OAAO;EAGhD,OAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAPiB,YAAY,MAAM,MAAM,CAAC,EAAE,IAQ1C,GAAY,WACZ,WAAW,WAAW,sCAAsC,SAAS;GACvE;EACF;CACF,SAAS,KAAU;EACjB,MAAM,iCAAiC,YAAY,IAAI,OAAO;EAC9D,MAAM,cAAc,MAAM,eAAe,OAAO;EAEhD,OAAO;GACL,SAAS;GACT,YAAY;GACZ;GACA,eAAe;GACf,OAAO,IAAI;GACX;EACF;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/plugin-verifier",
3
- "version": "1.0.0-next-9.13",
3
+ "version": "1.0.0-next-9.15",
4
4
  "description": "Tool to verify that a Verdaccio plugin can be loaded and passes sanity checks",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",
@@ -33,16 +33,17 @@
33
33
  "node": ">=24"
34
34
  },
35
35
  "dependencies": {
36
- "@verdaccio/core": "9.0.0-next-9.17",
37
- "@verdaccio/loaders": "9.0.0-next-9.17",
38
- "@verdaccio/logger": "9.0.0-next-9.17",
36
+ "@verdaccio/core": "9.0.0-next-9.19",
37
+ "@verdaccio/loaders": "9.0.0-next-9.19",
38
+ "@verdaccio/logger": "9.0.0-next-9.19",
39
39
  "clipanion": "4.0.0-rc.4",
40
40
  "debug": "4.4.3"
41
41
  },
42
42
  "devDependencies": {
43
- "@verdaccio/config": "9.0.0-next-9.17",
44
- "@verdaccio/types": "14.0.0-next-9.8",
45
- "vitest": "4.1.0"
43
+ "rimraf": "6.1.3",
44
+ "vite": "8.0.14",
45
+ "vite-plugin-dts": "5.0.1",
46
+ "vitest": "4.1.7"
46
47
  },
47
48
  "funding": {
48
49
  "type": "opencollective",