@verdaccio/loaders 6.0.0-6-next.15 → 6.0.0-6-next.17

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,75 @@
1
1
  # @verdaccio/loaders
2
2
 
3
+ ## 6.0.0-6-next.17
4
+
5
+ ### Major Changes
6
+
7
+ - 9fc2e796: feat(plugins): improve plugin loader
8
+
9
+ ### Changes
10
+
11
+ - Add scope plugin support to 6.x https://github.com/verdaccio/verdaccio/pull/3227
12
+ - Avoid config collisions https://github.com/verdaccio/verdaccio/issues/928
13
+ - https://github.com/verdaccio/verdaccio/issues/1394
14
+ - `config.plugins` plugin path validations
15
+ - Updated algorithm for plugin loader.
16
+ - improved documentation (included dev)
17
+
18
+ ## Features
19
+
20
+ - Add scope plugin support to 6.x https://github.com/verdaccio/verdaccio/pull/3227
21
+ - Custom prefix:
22
+
23
+ ```
24
+ // config.yaml
25
+ server:
26
+ pluginPrefix: mycompany
27
+ middleware:
28
+ audit:
29
+ foo: 1
30
+ ```
31
+
32
+ This configuration will look up for `mycompany-audit` instead `Verdaccio-audit`.
33
+
34
+ ## Breaking Changes
35
+
36
+ ### sinopia plugins
37
+
38
+ - `sinopia` fallback support is removed, but can be restored using `pluginPrefix`
39
+
40
+ ### plugin filter
41
+
42
+ - method rename `filter_metadata`->`filterMetadata`
43
+
44
+ ### Plugin constructor does not merge configs anymore https://github.com/verdaccio/verdaccio/issues/928
45
+
46
+ The plugin receives as first argument `config`, which represents the config of the plugin. Example:
47
+
48
+ ```
49
+ // config.yaml
50
+ auth:
51
+ plugin:
52
+ foo: 1
53
+ bar: 2
54
+
55
+ export class Plugin<T> {
56
+ public constructor(config: T, options: PluginOptions) {
57
+ console.log(config);
58
+ // {foo:1, bar: 2}
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Patch Changes
64
+
65
+ - @verdaccio/logger@6.0.0-6-next.16
66
+
67
+ ## 6.0.0-6-next.16
68
+
69
+ ### Patch Changes
70
+
71
+ - @verdaccio/logger@6.0.0-6-next.15
72
+
3
73
  ## 6.0.0-6-next.15
4
74
 
5
75
  ### Patch Changes
package/build/index.d.ts CHANGED
@@ -1 +1 @@
1
- export * from './plugin-loader';
1
+ export { asyncLoadPlugin } from './plugin-async-loader';
package/build/index.js CHANGED
@@ -3,17 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
-
7
- var _pluginLoader = require("./plugin-loader");
8
-
9
- Object.keys(_pluginLoader).forEach(function (key) {
10
- if (key === "default" || key === "__esModule") return;
11
- if (key in exports && exports[key] === _pluginLoader[key]) return;
12
- Object.defineProperty(exports, key, {
13
- enumerable: true,
14
- get: function () {
15
- return _pluginLoader[key];
16
- }
17
- });
6
+ Object.defineProperty(exports, "asyncLoadPlugin", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _pluginAsyncLoader.asyncLoadPlugin;
10
+ }
18
11
  });
12
+
13
+ var _pluginAsyncLoader = require("./plugin-async-loader");
19
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export * from './plugin-loader';\n"],"mappings":";;;;;;AAAA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export { asyncLoadPlugin } from './plugin-async-loader';\n"],"mappings":";;;;;;;;;;;;AAAA"}
@@ -0,0 +1,29 @@
1
+ import { Config, IPlugin, Logger } from '@verdaccio/types';
2
+ export declare type Params = {
3
+ config: Config;
4
+ logger: Logger;
5
+ };
6
+ /**
7
+ * The plugin loader find recursively plugins, if one plugin fails is ignored and report the error to the logger.
8
+ *
9
+ * The loader follows the order:
10
+ * - If the at the `config.yaml` file the `plugins: ./plugins` is defined
11
+ * - If is absolute will use the provided path
12
+ * - If is relative, will use the base path of the config file. eg: /root/config.yaml the plugins folder should be
13
+ * hosted at /root/plugins
14
+ * - The next step is find at the node_modules or global based on the `require` native algorithm.
15
+ * - If the package is scoped eg: @scope/foo, try to load the package `@scope/foo`
16
+ * - If the package is not scoped, will use the default prefix: verdaccio-foo.
17
+ * - If a custom prefix is provided, the verdaccio- is replaced by the config.server.pluginPrefix.
18
+ *
19
+ * The `sanityCheck` is the validation for the required methods to load the plugin, if the validation fails the plugin won't be loaded.
20
+ * The `params` is an object that contains the global configuration and the logger.
21
+ *
22
+ * @param {*} pluginConfigs the custom plugin section
23
+ * @param {*} params a set of params to initialize the plugin
24
+ * @param {*} sanityCheck callback that check the shape that should fulfill the plugin
25
+ * @param {*} prefix by default is verdaccio but can be override with config.server.pluginPrefix
26
+ * @return {Array} list of plugins
27
+ */
28
+ export declare function asyncLoadPlugin<T extends IPlugin<T>>(pluginConfigs: any, params: Params, sanityCheck: any, prefix?: string): Promise<any>;
29
+ export declare function executePlugin(plugin: any, pluginConfig: any, params: Params): any;
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.asyncLoadPlugin = asyncLoadPlugin;
7
+ exports.executePlugin = executePlugin;
8
+
9
+ var _debug = _interopRequireDefault(require("debug"));
10
+
11
+ var _promises = require("fs/promises");
12
+
13
+ var _path = require("path");
14
+
15
+ var _logger = require("@verdaccio/logger");
16
+
17
+ var _utils = require("./utils");
18
+
19
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
+
21
+ const debug = (0, _debug.default)('verdaccio:plugin:loader:async');
22
+
23
+ async function isDirectory(pathFolder) {
24
+ const stat = await (0, _promises.lstat)(pathFolder);
25
+ return stat.isDirectory();
26
+ }
27
+
28
+ /**
29
+ * The plugin loader find recursively plugins, if one plugin fails is ignored and report the error to the logger.
30
+ *
31
+ * The loader follows the order:
32
+ * - If the at the `config.yaml` file the `plugins: ./plugins` is defined
33
+ * - If is absolute will use the provided path
34
+ * - If is relative, will use the base path of the config file. eg: /root/config.yaml the plugins folder should be
35
+ * hosted at /root/plugins
36
+ * - The next step is find at the node_modules or global based on the `require` native algorithm.
37
+ * - If the package is scoped eg: @scope/foo, try to load the package `@scope/foo`
38
+ * - If the package is not scoped, will use the default prefix: verdaccio-foo.
39
+ * - If a custom prefix is provided, the verdaccio- is replaced by the config.server.pluginPrefix.
40
+ *
41
+ * The `sanityCheck` is the validation for the required methods to load the plugin, if the validation fails the plugin won't be loaded.
42
+ * The `params` is an object that contains the global configuration and the logger.
43
+ *
44
+ * @param {*} pluginConfigs the custom plugin section
45
+ * @param {*} params a set of params to initialize the plugin
46
+ * @param {*} sanityCheck callback that check the shape that should fulfill the plugin
47
+ * @param {*} prefix by default is verdaccio but can be override with config.server.pluginPrefix
48
+ * @return {Array} list of plugins
49
+ */
50
+ async function asyncLoadPlugin(pluginConfigs = {}, params, sanityCheck, prefix = 'verdaccio') {
51
+ const pluginsIds = Object.keys(pluginConfigs);
52
+ const {
53
+ config
54
+ } = params;
55
+ let plugins = [];
56
+
57
+ for (let pluginId of pluginsIds) {
58
+ debug('plugin %s', pluginId);
59
+
60
+ if (typeof config.plugins === 'string') {
61
+ let pluginsPath = config.plugins;
62
+ debug('plugin path %s', pluginsPath);
63
+
64
+ if (!(0, _path.isAbsolute)(pluginsPath)) {
65
+ if (typeof config.config_path === 'string' && !config.configPath) {
66
+ _logger.logger.error('configPath is missing and the legacy config.config_path is not available for loading plugins');
67
+ }
68
+
69
+ if (!config.configPath) {
70
+ _logger.logger.error('config path property is required for loading plugins');
71
+
72
+ continue;
73
+ }
74
+
75
+ pluginsPath = (0, _path.resolve)((0, _path.join)((0, _path.dirname)(config.configPath), pluginsPath));
76
+ }
77
+
78
+ _logger.logger.debug({
79
+ path: pluginsPath
80
+ }, 'plugins folder defined, loading plugins from @{path} '); // throws if is nto a directory
81
+
82
+
83
+ try {
84
+ await isDirectory(pluginsPath);
85
+ const pluginDir = pluginsPath;
86
+ const externalFilePlugin = (0, _path.resolve)(pluginDir, `${prefix}-${pluginId}`);
87
+ let plugin = (0, _utils.tryLoad)(externalFilePlugin);
88
+
89
+ if (plugin && (0, _utils.isValid)(plugin)) {
90
+ plugin = executePlugin(plugin, pluginConfigs[pluginId], params);
91
+
92
+ if (!sanityCheck(plugin)) {
93
+ _logger.logger.error({
94
+ content: externalFilePlugin
95
+ }, "@{content} doesn't look like a valid plugin");
96
+
97
+ continue;
98
+ }
99
+
100
+ plugins.push(plugin);
101
+ continue;
102
+ }
103
+ } catch (err) {
104
+ _logger.logger.warn({
105
+ err: err.message,
106
+ pluginsPath,
107
+ pluginId
108
+ }, '@{err} on loading plugins at @{pluginsPath} for @{pluginId}');
109
+ }
110
+ }
111
+
112
+ if (typeof pluginId === 'string') {
113
+ const isScoped = pluginId.startsWith('@') && pluginId.includes('/');
114
+ debug('is scoped plugin %s', isScoped);
115
+ const pluginName = isScoped ? pluginId : `${prefix}-${pluginId}`;
116
+ debug('plugin pkg name %s', pluginName);
117
+ let plugin = (0, _utils.tryLoad)(pluginName);
118
+
119
+ if (plugin && (0, _utils.isValid)(plugin)) {
120
+ plugin = executePlugin(plugin, pluginConfigs[pluginId], params);
121
+
122
+ if (!sanityCheck(plugin)) {
123
+ _logger.logger.error({
124
+ content: pluginName
125
+ }, "@{content} doesn't look like a valid plugin");
126
+
127
+ continue;
128
+ }
129
+
130
+ plugins.push(plugin);
131
+ continue;
132
+ } else {
133
+ _logger.logger.error({
134
+ pluginName
135
+ }, 'package not found, try to install @{pluginName} with a package manager');
136
+
137
+ continue;
138
+ }
139
+ }
140
+ }
141
+
142
+ debug('plugin found %s', plugins.length);
143
+ return plugins;
144
+ }
145
+
146
+ function executePlugin(plugin, pluginConfig, params) {
147
+ if ((0, _utils.isES6)(plugin)) {
148
+ debug('plugin is ES6'); // eslint-disable-next-line new-cap
149
+
150
+ return new plugin.default(pluginConfig, params);
151
+ } else {
152
+ debug('plugin is commonJS');
153
+ return plugin(pluginConfig, params);
154
+ }
155
+ }
156
+ //# sourceMappingURL=plugin-async-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-async-loader.js","names":["debug","buildDebug","isDirectory","pathFolder","stat","lstat","asyncLoadPlugin","pluginConfigs","params","sanityCheck","prefix","pluginsIds","Object","keys","config","plugins","pluginId","pluginsPath","isAbsolute","config_path","configPath","logger","error","resolve","join","dirname","path","pluginDir","externalFilePlugin","plugin","tryLoad","isValid","executePlugin","content","push","err","warn","message","isScoped","startsWith","includes","pluginName","length","pluginConfig","isES6","default"],"sources":["../src/plugin-async-loader.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { lstat } from 'fs/promises';\nimport { dirname, isAbsolute, join, resolve } from 'path';\n\nimport { logger } from '@verdaccio/logger';\nimport { Config, IPlugin, Logger } from '@verdaccio/types';\n\nimport { isES6, isValid, tryLoad } from './utils';\n\nconst debug = buildDebug('verdaccio:plugin:loader:async');\n\nasync function isDirectory(pathFolder) {\n const stat = await lstat(pathFolder);\n return stat.isDirectory();\n}\n\nexport type Params = { config: Config; logger: Logger };\n\n/**\n * The plugin loader find recursively plugins, if one plugin fails is ignored and report the error to the logger.\n *\n * The loader follows the order:\n * - If the at the `config.yaml` file the `plugins: ./plugins` is defined\n * - If is absolute will use the provided path\n * - If is relative, will use the base path of the config file. eg: /root/config.yaml the plugins folder should be\n * hosted at /root/plugins\n * - The next step is find at the node_modules or global based on the `require` native algorithm.\n * - If the package is scoped eg: @scope/foo, try to load the package `@scope/foo`\n * - If the package is not scoped, will use the default prefix: verdaccio-foo.\n * - If a custom prefix is provided, the verdaccio- is replaced by the config.server.pluginPrefix.\n *\n * The `sanityCheck` is the validation for the required methods to load the plugin, if the validation fails the plugin won't be loaded.\n * The `params` is an object that contains the global configuration and the logger.\n *\n * @param {*} pluginConfigs the custom plugin section\n * @param {*} params a set of params to initialize the plugin\n * @param {*} sanityCheck callback that check the shape that should fulfill the plugin\n * @param {*} prefix by default is verdaccio but can be override with config.server.pluginPrefix\n * @return {Array} list of plugins\n */\nexport async function asyncLoadPlugin<T extends IPlugin<T>>(\n pluginConfigs: any = {},\n params: Params,\n sanityCheck: any,\n prefix: string = 'verdaccio'\n): Promise<any> {\n const pluginsIds = Object.keys(pluginConfigs);\n const { config } = params;\n let plugins: any[] = [];\n for (let pluginId of pluginsIds) {\n debug('plugin %s', pluginId);\n if (typeof config.plugins === 'string') {\n let pluginsPath = config.plugins;\n debug('plugin path %s', pluginsPath);\n if (!isAbsolute(pluginsPath)) {\n if (typeof config.config_path === 'string' && !config.configPath) {\n logger.error(\n 'configPath is missing and the legacy config.config_path is not available for loading plugins'\n );\n }\n\n if (!config.configPath) {\n logger.error('config path property is required for loading plugins');\n continue;\n }\n pluginsPath = resolve(join(dirname(config.configPath), pluginsPath));\n }\n\n logger.debug({ path: pluginsPath }, 'plugins folder defined, loading plugins from @{path} ');\n // throws if is nto a directory\n try {\n await isDirectory(pluginsPath);\n const pluginDir = pluginsPath;\n const externalFilePlugin = resolve(pluginDir, `${prefix}-${pluginId}`);\n let plugin = tryLoad(externalFilePlugin);\n if (plugin && isValid(plugin)) {\n plugin = executePlugin(plugin, pluginConfigs[pluginId], params);\n if (!sanityCheck(plugin)) {\n logger.error(\n { content: externalFilePlugin },\n \"@{content} doesn't look like a valid plugin\"\n );\n continue;\n }\n plugins.push(plugin);\n continue;\n }\n } catch (err: any) {\n logger.warn(\n { err: err.message, pluginsPath, pluginId },\n '@{err} on loading plugins at @{pluginsPath} for @{pluginId}'\n );\n }\n }\n\n if (typeof pluginId === 'string') {\n const isScoped: boolean = pluginId.startsWith('@') && pluginId.includes('/');\n debug('is scoped plugin %s', isScoped);\n const pluginName = isScoped ? pluginId : `${prefix}-${pluginId}`;\n debug('plugin pkg name %s', pluginName);\n let plugin = tryLoad(pluginName);\n if (plugin && isValid(plugin)) {\n plugin = executePlugin(plugin, pluginConfigs[pluginId], params);\n if (!sanityCheck(plugin)) {\n logger.error({ content: pluginName }, \"@{content} doesn't look like a valid plugin\");\n continue;\n }\n plugins.push(plugin);\n continue;\n } else {\n logger.error(\n { pluginName },\n 'package not found, try to install @{pluginName} with a package manager'\n );\n continue;\n }\n }\n }\n debug('plugin found %s', plugins.length);\n return plugins;\n}\n\nexport function executePlugin(plugin, pluginConfig, params: Params) {\n if (isES6(plugin)) {\n debug('plugin is ES6');\n // eslint-disable-next-line new-cap\n return new plugin.default(pluginConfig, params);\n } else {\n debug('plugin is commonJS');\n return plugin(pluginConfig, params);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Config } from '@verdaccio/types';
2
+ export declare function mergeConfig(appConfig: any, pluginConfig: any): Config;
3
+ export declare function isValid(plugin: any): boolean;
4
+ export declare function isES6(plugin: any): boolean;
5
+ /**
6
+ * Requires a module.
7
+ * @param {*} path the module's path
8
+ * @return {Object}
9
+ */
10
+ export declare function tryLoad(path: string): any;
package/build/utils.js ADDED
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isES6 = isES6;
7
+ exports.isValid = isValid;
8
+ exports.mergeConfig = mergeConfig;
9
+ exports.tryLoad = tryLoad;
10
+
11
+ var _debug = _interopRequireDefault(require("debug"));
12
+
13
+ var _lodash = _interopRequireDefault(require("lodash"));
14
+
15
+ var _logger = require("@verdaccio/logger");
16
+
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
+
19
+ const debug = (0, _debug.default)('verdaccio:plugin:loader:utils');
20
+ const MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';
21
+
22
+ function mergeConfig(appConfig, pluginConfig) {
23
+ return _lodash.default.merge(appConfig, pluginConfig);
24
+ }
25
+
26
+ function isValid(plugin) {
27
+ return _lodash.default.isFunction(plugin) || _lodash.default.isFunction(plugin.default);
28
+ }
29
+
30
+ function isES6(plugin) {
31
+ return Object.keys(plugin).includes('default');
32
+ }
33
+ /**
34
+ * Requires a module.
35
+ * @param {*} path the module's path
36
+ * @return {Object}
37
+ */
38
+
39
+
40
+ function tryLoad(path) {
41
+ try {
42
+ debug('loading plugin %s', path);
43
+ return require(path);
44
+ } catch (err) {
45
+ if (err.code === MODULE_NOT_FOUND) {
46
+ debug('plugin %s not found', path);
47
+ return null;
48
+ }
49
+
50
+ _logger.logger.error({
51
+ err: err.msg
52
+ }, 'error loading plugin @{err}');
53
+
54
+ throw err;
55
+ }
56
+ }
57
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","names":["debug","buildDebug","MODULE_NOT_FOUND","mergeConfig","appConfig","pluginConfig","_","merge","isValid","plugin","isFunction","default","isES6","Object","keys","includes","tryLoad","path","require","err","code","logger","error","msg"],"sources":["../src/utils.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\n\nimport { logger } from '@verdaccio/logger';\nimport { Config } from '@verdaccio/types';\n\nconst debug = buildDebug('verdaccio:plugin:loader:utils');\n\nconst MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';\n\nexport function mergeConfig(appConfig, pluginConfig): Config {\n return _.merge(appConfig, pluginConfig);\n}\n\nexport function isValid(plugin): boolean {\n return _.isFunction(plugin) || _.isFunction(plugin.default);\n}\n\nexport function isES6(plugin): boolean {\n return Object.keys(plugin).includes('default');\n}\n\n/**\n * Requires a module.\n * @param {*} path the module's path\n * @return {Object}\n */\nexport function tryLoad(path: string): any {\n try {\n debug('loading plugin %s', path);\n return require(path);\n } catch (err: any) {\n if (err.code === MODULE_NOT_FOUND) {\n debug('plugin %s not found', path);\n return null;\n }\n logger.error({ err: err.msg }, 'error loading plugin @{err}');\n throw err;\n }\n}\n"],"mappings":";;;;;;;;;;AAAA;;AACA;;AAEA;;;;AAGA,MAAMA,KAAK,GAAG,IAAAC,cAAA,EAAW,+BAAX,CAAd;AAEA,MAAMC,gBAAgB,GAAG,kBAAzB;;AAEO,SAASC,WAAT,CAAqBC,SAArB,EAAgCC,YAAhC,EAAsD;EAC3D,OAAOC,eAAA,CAAEC,KAAF,CAAQH,SAAR,EAAmBC,YAAnB,CAAP;AACD;;AAEM,SAASG,OAAT,CAAiBC,MAAjB,EAAkC;EACvC,OAAOH,eAAA,CAAEI,UAAF,CAAaD,MAAb,KAAwBH,eAAA,CAAEI,UAAF,CAAaD,MAAM,CAACE,OAApB,CAA/B;AACD;;AAEM,SAASC,KAAT,CAAeH,MAAf,EAAgC;EACrC,OAAOI,MAAM,CAACC,IAAP,CAAYL,MAAZ,EAAoBM,QAApB,CAA6B,SAA7B,CAAP;AACD;AAED;AACA;AACA;AACA;AACA;;;AACO,SAASC,OAAT,CAAiBC,IAAjB,EAAoC;EACzC,IAAI;IACFjB,KAAK,CAAC,mBAAD,EAAsBiB,IAAtB,CAAL;IACA,OAAOC,OAAO,CAACD,IAAD,CAAd;EACD,CAHD,CAGE,OAAOE,GAAP,EAAiB;IACjB,IAAIA,GAAG,CAACC,IAAJ,KAAalB,gBAAjB,EAAmC;MACjCF,KAAK,CAAC,qBAAD,EAAwBiB,IAAxB,CAAL;MACA,OAAO,IAAP;IACD;;IACDI,cAAA,CAAOC,KAAP,CAAa;MAAEH,GAAG,EAAEA,GAAG,CAACI;IAAX,CAAb,EAA+B,6BAA/B;;IACA,MAAMJ,GAAN;EACD;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/loaders",
3
- "version": "6.0.0-6-next.15",
3
+ "version": "6.0.0-6-next.17",
4
4
  "description": "loaders logic",
5
5
  "main": "./build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -13,14 +13,17 @@
13
13
  "url": "https://github.com/verdaccio/verdaccio"
14
14
  },
15
15
  "dependencies": {
16
- "@verdaccio/logger": "6.0.0-6-next.14",
16
+ "@verdaccio/logger": "6.0.0-6-next.16",
17
17
  "debug": "4.3.4",
18
18
  "lodash": "4.17.21"
19
19
  },
20
20
  "devDependencies": {
21
- "@verdaccio/core": "6.0.0-6-next.8",
22
- "@verdaccio/config": "6.0.0-6-next.17",
23
- "@verdaccio/types": "11.0.0-6-next.16"
21
+ "@verdaccio/core": "6.0.0-6-next.48",
22
+ "@verdaccio/config": "6.0.0-6-next.48",
23
+ "@verdaccio/types": "11.0.0-6-next.17",
24
+ "@verdaccio-scope/verdaccio-auth-foo": "0.0.2",
25
+ "verdaccio-auth-memory": "11.0.0-6-next.13",
26
+ "customprefix-auth": "1.0.0-6-next.0"
24
27
  },
25
28
  "homepage": "https://verdaccio.org",
26
29
  "keywords": [
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export * from './plugin-loader';
1
+ export { asyncLoadPlugin } from './plugin-async-loader';
@@ -0,0 +1,132 @@
1
+ import buildDebug from 'debug';
2
+ import { lstat } from 'fs/promises';
3
+ import { dirname, isAbsolute, join, resolve } from 'path';
4
+
5
+ import { logger } from '@verdaccio/logger';
6
+ import { Config, IPlugin, Logger } from '@verdaccio/types';
7
+
8
+ import { isES6, isValid, tryLoad } from './utils';
9
+
10
+ const debug = buildDebug('verdaccio:plugin:loader:async');
11
+
12
+ async function isDirectory(pathFolder) {
13
+ const stat = await lstat(pathFolder);
14
+ return stat.isDirectory();
15
+ }
16
+
17
+ export type Params = { config: Config; logger: Logger };
18
+
19
+ /**
20
+ * The plugin loader find recursively plugins, if one plugin fails is ignored and report the error to the logger.
21
+ *
22
+ * The loader follows the order:
23
+ * - If the at the `config.yaml` file the `plugins: ./plugins` is defined
24
+ * - If is absolute will use the provided path
25
+ * - If is relative, will use the base path of the config file. eg: /root/config.yaml the plugins folder should be
26
+ * hosted at /root/plugins
27
+ * - The next step is find at the node_modules or global based on the `require` native algorithm.
28
+ * - If the package is scoped eg: @scope/foo, try to load the package `@scope/foo`
29
+ * - If the package is not scoped, will use the default prefix: verdaccio-foo.
30
+ * - If a custom prefix is provided, the verdaccio- is replaced by the config.server.pluginPrefix.
31
+ *
32
+ * The `sanityCheck` is the validation for the required methods to load the plugin, if the validation fails the plugin won't be loaded.
33
+ * The `params` is an object that contains the global configuration and the logger.
34
+ *
35
+ * @param {*} pluginConfigs the custom plugin section
36
+ * @param {*} params a set of params to initialize the plugin
37
+ * @param {*} sanityCheck callback that check the shape that should fulfill the plugin
38
+ * @param {*} prefix by default is verdaccio but can be override with config.server.pluginPrefix
39
+ * @return {Array} list of plugins
40
+ */
41
+ export async function asyncLoadPlugin<T extends IPlugin<T>>(
42
+ pluginConfigs: any = {},
43
+ params: Params,
44
+ sanityCheck: any,
45
+ prefix: string = 'verdaccio'
46
+ ): Promise<any> {
47
+ const pluginsIds = Object.keys(pluginConfigs);
48
+ const { config } = params;
49
+ let plugins: any[] = [];
50
+ for (let pluginId of pluginsIds) {
51
+ debug('plugin %s', pluginId);
52
+ if (typeof config.plugins === 'string') {
53
+ let pluginsPath = config.plugins;
54
+ debug('plugin path %s', pluginsPath);
55
+ if (!isAbsolute(pluginsPath)) {
56
+ if (typeof config.config_path === 'string' && !config.configPath) {
57
+ logger.error(
58
+ 'configPath is missing and the legacy config.config_path is not available for loading plugins'
59
+ );
60
+ }
61
+
62
+ if (!config.configPath) {
63
+ logger.error('config path property is required for loading plugins');
64
+ continue;
65
+ }
66
+ pluginsPath = resolve(join(dirname(config.configPath), pluginsPath));
67
+ }
68
+
69
+ logger.debug({ path: pluginsPath }, 'plugins folder defined, loading plugins from @{path} ');
70
+ // throws if is nto a directory
71
+ try {
72
+ await isDirectory(pluginsPath);
73
+ const pluginDir = pluginsPath;
74
+ const externalFilePlugin = resolve(pluginDir, `${prefix}-${pluginId}`);
75
+ let plugin = tryLoad(externalFilePlugin);
76
+ if (plugin && isValid(plugin)) {
77
+ plugin = executePlugin(plugin, pluginConfigs[pluginId], params);
78
+ if (!sanityCheck(plugin)) {
79
+ logger.error(
80
+ { content: externalFilePlugin },
81
+ "@{content} doesn't look like a valid plugin"
82
+ );
83
+ continue;
84
+ }
85
+ plugins.push(plugin);
86
+ continue;
87
+ }
88
+ } catch (err: any) {
89
+ logger.warn(
90
+ { err: err.message, pluginsPath, pluginId },
91
+ '@{err} on loading plugins at @{pluginsPath} for @{pluginId}'
92
+ );
93
+ }
94
+ }
95
+
96
+ if (typeof pluginId === 'string') {
97
+ const isScoped: boolean = pluginId.startsWith('@') && pluginId.includes('/');
98
+ debug('is scoped plugin %s', isScoped);
99
+ const pluginName = isScoped ? pluginId : `${prefix}-${pluginId}`;
100
+ debug('plugin pkg name %s', pluginName);
101
+ let plugin = tryLoad(pluginName);
102
+ if (plugin && isValid(plugin)) {
103
+ plugin = executePlugin(plugin, pluginConfigs[pluginId], params);
104
+ if (!sanityCheck(plugin)) {
105
+ logger.error({ content: pluginName }, "@{content} doesn't look like a valid plugin");
106
+ continue;
107
+ }
108
+ plugins.push(plugin);
109
+ continue;
110
+ } else {
111
+ logger.error(
112
+ { pluginName },
113
+ 'package not found, try to install @{pluginName} with a package manager'
114
+ );
115
+ continue;
116
+ }
117
+ }
118
+ }
119
+ debug('plugin found %s', plugins.length);
120
+ return plugins;
121
+ }
122
+
123
+ export function executePlugin(plugin, pluginConfig, params: Params) {
124
+ if (isES6(plugin)) {
125
+ debug('plugin is ES6');
126
+ // eslint-disable-next-line new-cap
127
+ return new plugin.default(pluginConfig, params);
128
+ } else {
129
+ debug('plugin is commonJS');
130
+ return plugin(pluginConfig, params);
131
+ }
132
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,40 @@
1
+ import buildDebug from 'debug';
2
+ import _ from 'lodash';
3
+
4
+ import { logger } from '@verdaccio/logger';
5
+ import { Config } from '@verdaccio/types';
6
+
7
+ const debug = buildDebug('verdaccio:plugin:loader:utils');
8
+
9
+ const MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';
10
+
11
+ export function mergeConfig(appConfig, pluginConfig): Config {
12
+ return _.merge(appConfig, pluginConfig);
13
+ }
14
+
15
+ export function isValid(plugin): boolean {
16
+ return _.isFunction(plugin) || _.isFunction(plugin.default);
17
+ }
18
+
19
+ export function isES6(plugin): boolean {
20
+ return Object.keys(plugin).includes('default');
21
+ }
22
+
23
+ /**
24
+ * Requires a module.
25
+ * @param {*} path the module's path
26
+ * @return {Object}
27
+ */
28
+ export function tryLoad(path: string): any {
29
+ try {
30
+ debug('loading plugin %s', path);
31
+ return require(path);
32
+ } catch (err: any) {
33
+ if (err.code === MODULE_NOT_FOUND) {
34
+ debug('plugin %s not found', path);
35
+ return null;
36
+ }
37
+ logger.error({ err: err.msg }, 'error loading plugin @{err}');
38
+ throw err;
39
+ }
40
+ }
@@ -0,0 +1,3 @@
1
+ auth:
2
+ '@verdaccio-scope/verdaccio-auth-foo':
3
+ enabled: true
@@ -0,0 +1,3 @@
1
+ auth:
2
+ auth-memory:
3
+ enabled: true
@@ -0,0 +1,3 @@
1
+ auth:
2
+ not-found:
3
+ enabled: true
@@ -0,0 +1,4 @@
1
+ auth:
2
+ something:
3
+ enabled: true
4
+ plugins: /roo/does-not-exist
@@ -0,0 +1,4 @@
1
+ plugins: '../test-plugin-storage'
2
+ auth:
3
+ plugin:
4
+ enabled: true
@@ -0,0 +1,3 @@
1
+ auth:
2
+ '@verdaccio-scope/verdaccio-auth-foo':
3
+ enabled: true
@@ -0,0 +1,3 @@
1
+ auth:
2
+ plugin:
3
+ enabled: true
@@ -0,0 +1,7 @@
1
+ function ValidScopedVerdaccioPlugin() {
2
+ return {
3
+ authenticate: function () {},
4
+ };
5
+ }
6
+
7
+ module.exports = ValidVerdaccioPlugin;
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@verdaccio-scoped/verdaccio-plugin",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "",
10
+ "license": "ISC"
11
+ }
@@ -0,0 +1,168 @@
1
+ import path from 'path';
2
+
3
+ import { Config, parseConfigFile } from '@verdaccio/config';
4
+ import { logger, setup } from '@verdaccio/logger';
5
+
6
+ import { asyncLoadPlugin } from '../src/plugin-async-loader';
7
+
8
+ function getConfig(file: string) {
9
+ const conPath = path.join(__dirname, './partials/config', file);
10
+ return new Config(parseConfigFile(conPath));
11
+ }
12
+
13
+ const authSanitize = function (plugin) {
14
+ return plugin.authenticate || plugin.allow_access || plugin.allow_publish;
15
+ };
16
+
17
+ const pluginsPartialsFolder = path.join(__dirname, './partials/test-plugin-storage');
18
+
19
+ setup();
20
+
21
+ describe('plugin loader', () => {
22
+ describe('file plugins', () => {
23
+ describe('absolute path', () => {
24
+ test('testing auth valid plugin loader', async () => {
25
+ const config = getConfig('valid-plugin.yaml');
26
+ config.plugins = pluginsPartialsFolder;
27
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, authSanitize);
28
+
29
+ expect(plugins).toHaveLength(1);
30
+ });
31
+
32
+ test('should handle does not exist plugin folder', async () => {
33
+ const config = getConfig('plugins-folder-fake.yaml');
34
+ const plugins = await asyncLoadPlugin(
35
+ config.auth,
36
+ { logger: logger, config: config },
37
+ authSanitize
38
+ );
39
+
40
+ expect(plugins).toHaveLength(0);
41
+ });
42
+
43
+ test('testing load auth npm package invalid method check', async () => {
44
+ const config = getConfig('valid-plugin.yaml');
45
+ config.plugins = pluginsPartialsFolder;
46
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, (p) => p.anyMethod);
47
+
48
+ expect(plugins).toHaveLength(0);
49
+ });
50
+
51
+ test('should fails if plugins folder is not a directory', async () => {
52
+ const config = getConfig('plugins-folder-fake.yaml');
53
+ // force file instead a folder.
54
+ config.plugins = path.join(__dirname, 'just-a-file.js');
55
+ const plugins = await asyncLoadPlugin(
56
+ config.auth,
57
+ { logger: logger, config: config },
58
+ authSanitize
59
+ );
60
+
61
+ expect(plugins).toHaveLength(0);
62
+ });
63
+ });
64
+ describe('relative path', () => {
65
+ test('should resolve plugin based on relative path', async () => {
66
+ const config = getConfig('relative-plugins.yaml');
67
+ // force file instead a folder.
68
+ const plugins = await asyncLoadPlugin(
69
+ config.auth,
70
+ { logger: logger, config: config },
71
+ authSanitize
72
+ );
73
+
74
+ expect(plugins).toHaveLength(1);
75
+ });
76
+
77
+ test('should fails if config path is missing', async () => {
78
+ const config = getConfig('relative-plugins.yaml');
79
+ // @ts-expect-error
80
+ config.configPath = undefined;
81
+ // @ts-expect-error
82
+ config.config_path = undefined;
83
+ // force file instead a folder.
84
+ const plugins = await asyncLoadPlugin(
85
+ config.auth,
86
+ { logger: logger, config: config },
87
+ authSanitize
88
+ );
89
+
90
+ expect(plugins).toHaveLength(0);
91
+ });
92
+
93
+ // config.config_path is not considered for loading plugins due legacy support
94
+ test('should fails if config path is missing (only config_path)', async () => {
95
+ const config = getConfig('relative-plugins.yaml');
96
+ // @ts-expect-error
97
+ config.configPath = undefined;
98
+ // force file instead a folder.
99
+ const plugins = await asyncLoadPlugin(
100
+ config.auth,
101
+ { logger: logger, config: config },
102
+ authSanitize
103
+ );
104
+
105
+ expect(plugins).toHaveLength(0);
106
+ });
107
+ });
108
+ });
109
+
110
+ describe('npm plugins', () => {
111
+ test('testing load auth npm package', async () => {
112
+ const config = getConfig('npm-plugin-auth.yaml');
113
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, authSanitize);
114
+
115
+ expect(plugins).toHaveLength(1);
116
+ });
117
+
118
+ test('should handle not found installed package', async () => {
119
+ const config = getConfig('npm-plugin-not-found.yaml');
120
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, (p) => p.anyMethod);
121
+
122
+ expect(plugins).toHaveLength(0);
123
+ });
124
+
125
+ test('testing load auth npm package invalid method check', async () => {
126
+ const config = getConfig('npm-plugin-auth.yaml');
127
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, (p) => p.anyMethod);
128
+
129
+ expect(plugins).toHaveLength(0);
130
+ });
131
+
132
+ test('testing load auth npm package custom prefix', async () => {
133
+ const config = getConfig('custom-prefix-auth.yaml');
134
+ const plugins = await asyncLoadPlugin(
135
+ config.auth,
136
+ { config, logger },
137
+ authSanitize,
138
+ 'customprefix'
139
+ );
140
+
141
+ expect(plugins).toHaveLength(1);
142
+ });
143
+
144
+ test('testing load auth scope npm package', async () => {
145
+ const config = getConfig('scope-auth.yaml');
146
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, authSanitize);
147
+ expect(plugins).toHaveLength(1);
148
+ });
149
+ });
150
+
151
+ describe('fallback plugins', () => {
152
+ test('should fallback to npm package if does not find on plugins folder', async () => {
153
+ const config = getConfig('npm-plugin-auth.yaml');
154
+ config.plugins = pluginsPartialsFolder;
155
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, authSanitize);
156
+
157
+ expect(plugins).toHaveLength(1);
158
+ });
159
+
160
+ test('should fallback to npm package if plugins folder does not exist', async () => {
161
+ const config = getConfig('npm-plugin-auth.yaml');
162
+ config.plugins = '/does-not-exist';
163
+ const plugins = await asyncLoadPlugin(config.auth, { config, logger }, authSanitize);
164
+
165
+ expect(plugins).toHaveLength(1);
166
+ });
167
+ });
168
+ });
@@ -1,16 +0,0 @@
1
- import { Config, IPlugin } from '@verdaccio/types';
2
- export declare const MODULE_NOT_FOUND = "MODULE_NOT_FOUND";
3
- /**
4
- * Load a plugin following the rules
5
- * - First try to load from the internal directory plugins (which will disappear soon or later).
6
- * - A second attempt from the external plugin directory
7
- * - A third attempt from node_modules, in case to have multiple match as for instance
8
- * verdaccio-ldap
9
- * and sinopia-ldap. All verdaccio prefix will have preferences.
10
- * @param {*} config a reference of the configuration settings
11
- * @param {*} pluginConfigs
12
- * @param {*} params a set of params to initialize the plugin
13
- * @param {*} sanityCheck callback that check the shape that should fulfill the plugin
14
- * @return {Array} list of plugins
15
- */
16
- export declare function loadPlugin<T extends IPlugin<T>>(config: Config, pluginConfigs: any, params: any, sanityCheck: any, prefix?: string): any[];
@@ -1,159 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.MODULE_NOT_FOUND = void 0;
7
- exports.loadPlugin = loadPlugin;
8
-
9
- var _debug = _interopRequireDefault(require("debug"));
10
-
11
- var _lodash = _interopRequireDefault(require("lodash"));
12
-
13
- var _path = _interopRequireDefault(require("path"));
14
-
15
- var _logger = require("@verdaccio/logger");
16
-
17
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
-
19
- const debug = (0, _debug.default)('verdaccio:plugin:loader');
20
- const MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';
21
- /**
22
- * Requires a module.
23
- * @param {*} path the module's path
24
- * @return {Object}
25
- */
26
-
27
- exports.MODULE_NOT_FOUND = MODULE_NOT_FOUND;
28
-
29
- function tryLoad(path) {
30
- try {
31
- return require(path);
32
- } catch (err) {
33
- if (err.code === MODULE_NOT_FOUND) {
34
- return null;
35
- }
36
-
37
- throw err;
38
- }
39
- }
40
-
41
- function mergeConfig(appConfig, pluginConfig) {
42
- return _lodash.default.merge(appConfig, pluginConfig);
43
- }
44
-
45
- function isValid(plugin) {
46
- return _lodash.default.isFunction(plugin) || _lodash.default.isFunction(plugin.default);
47
- }
48
-
49
- function isES6(plugin) {
50
- return Object.keys(plugin).includes('default');
51
- } // export type PluginGeneric<R, T extends IPlugin<R> = ;
52
-
53
- /**
54
- * Load a plugin following the rules
55
- * - First try to load from the internal directory plugins (which will disappear soon or later).
56
- * - A second attempt from the external plugin directory
57
- * - A third attempt from node_modules, in case to have multiple match as for instance
58
- * verdaccio-ldap
59
- * and sinopia-ldap. All verdaccio prefix will have preferences.
60
- * @param {*} config a reference of the configuration settings
61
- * @param {*} pluginConfigs
62
- * @param {*} params a set of params to initialize the plugin
63
- * @param {*} sanityCheck callback that check the shape that should fulfill the plugin
64
- * @return {Array} list of plugins
65
- */
66
-
67
-
68
- function loadPlugin(config, pluginConfigs = {}, params, sanityCheck, prefix = 'verdaccio') {
69
- return Object.keys(pluginConfigs).map(pluginId => {
70
- let plugin;
71
-
72
- const localPlugin = _path.default.resolve(__dirname + '/../plugins', pluginId); // try local plugins first
73
-
74
-
75
- plugin = tryLoad(localPlugin); // try the external plugin directory
76
-
77
- if (plugin === null && config.plugins) {
78
- const pluginDir = config.plugins;
79
-
80
- const externalFilePlugin = _path.default.resolve(pluginDir, pluginId);
81
-
82
- plugin = tryLoad(externalFilePlugin); // npm package
83
-
84
- if (plugin === null && pluginId.match(/^[^\.\/]/)) {
85
- plugin = tryLoad(_path.default.resolve(pluginDir, `${prefix}-${pluginId}`)); // compatibility for old sinopia plugins
86
-
87
- if (!plugin) {
88
- plugin = tryLoad(_path.default.resolve(pluginDir, `sinopia-${pluginId}`));
89
- }
90
- }
91
- } // npm package
92
-
93
-
94
- if (plugin === null && pluginId.match(/^[^\.\/]/)) {
95
- plugin = tryLoad(`${prefix}-${pluginId}`); // compatibility for old sinopia plugins
96
-
97
- if (!plugin) {
98
- plugin = tryLoad(`sinopia-${pluginId}`);
99
- }
100
- }
101
-
102
- if (plugin === null) {
103
- plugin = tryLoad(pluginId);
104
- } // relative to config path
105
-
106
-
107
- debug('config path: %s', config.configPath);
108
-
109
- if (plugin === null && pluginId.match(/^\.\.?($|\/)/) && config.configPath) {
110
- plugin = tryLoad(_path.default.resolve(_path.default.dirname(config.configPath), pluginId));
111
- }
112
-
113
- if (plugin === null) {
114
- _logger.logger.error({
115
- content: pluginId,
116
- prefix
117
- }, 'plugin not found. try npm install @{prefix}-@{content}');
118
-
119
- throw Error(`
120
- ${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
121
- }
122
-
123
- if (!isValid(plugin)) {
124
- _logger.logger.error({
125
- content: pluginId
126
- }, '@{prefix}-@{content} plugin does not have the right code structure');
127
-
128
- throw Error(`"${pluginId}" plugin does not have the right code structure`);
129
- }
130
- /* eslint new-cap:off */
131
-
132
-
133
- try {
134
- plugin = isES6(plugin) ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params) : new plugin(pluginConfigs[pluginId], params);
135
- } catch (error) {
136
- plugin = null;
137
-
138
- _logger.logger.error({
139
- error,
140
- pluginId
141
- }, 'error loading a plugin @{pluginId}: @{error}');
142
- }
143
- /* eslint new-cap:off */
144
-
145
-
146
- if (plugin === null || !sanityCheck(plugin)) {
147
- _logger.logger.error({
148
- content: pluginId,
149
- prefix
150
- }, "@{prefix}-@{content} doesn't look like a valid plugin");
151
-
152
- throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`);
153
- }
154
-
155
- debug('Plugin successfully loaded: %o-%o', pluginId, prefix);
156
- return plugin;
157
- });
158
- }
159
- //# sourceMappingURL=plugin-loader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-loader.js","names":["debug","buildDebug","MODULE_NOT_FOUND","tryLoad","path","require","err","code","mergeConfig","appConfig","pluginConfig","_","merge","isValid","plugin","isFunction","default","isES6","Object","keys","includes","loadPlugin","config","pluginConfigs","params","sanityCheck","prefix","map","pluginId","localPlugin","Path","resolve","__dirname","plugins","pluginDir","externalFilePlugin","match","configPath","dirname","logger","error","content","Error"],"sources":["../src/plugin-loader.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport Path from 'path';\n\nimport { logger } from '@verdaccio/logger';\nimport { Config, IPlugin } from '@verdaccio/types';\n\nconst debug = buildDebug('verdaccio:plugin:loader');\n\nexport const MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';\n\n/**\n * Requires a module.\n * @param {*} path the module's path\n * @return {Object}\n */\nfunction tryLoad(path: string): any {\n try {\n return require(path);\n } catch (err: any) {\n if (err.code === MODULE_NOT_FOUND) {\n return null;\n }\n throw err;\n }\n}\n\nfunction mergeConfig(appConfig, pluginConfig): Config {\n return _.merge(appConfig, pluginConfig);\n}\n\nfunction isValid(plugin): boolean {\n return _.isFunction(plugin) || _.isFunction(plugin.default);\n}\n\nfunction isES6(plugin): boolean {\n return Object.keys(plugin).includes('default');\n}\n\n// export type PluginGeneric<R, T extends IPlugin<R> = ;\n\n/**\n * Load a plugin following the rules\n * - First try to load from the internal directory plugins (which will disappear soon or later).\n * - A second attempt from the external plugin directory\n * - A third attempt from node_modules, in case to have multiple match as for instance\n * verdaccio-ldap\n * and sinopia-ldap. All verdaccio prefix will have preferences.\n * @param {*} config a reference of the configuration settings\n * @param {*} pluginConfigs\n * @param {*} params a set of params to initialize the plugin\n * @param {*} sanityCheck callback that check the shape that should fulfill the plugin\n * @return {Array} list of plugins\n */\nexport function loadPlugin<T extends IPlugin<T>>(\n config: Config,\n pluginConfigs: any = {},\n params: any,\n sanityCheck: any,\n prefix: string = 'verdaccio'\n): any[] {\n return Object.keys(pluginConfigs).map((pluginId: string): IPlugin<T> => {\n let plugin;\n\n const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);\n // try local plugins first\n plugin = tryLoad(localPlugin);\n\n // try the external plugin directory\n if (plugin === null && config.plugins) {\n const pluginDir = config.plugins;\n const externalFilePlugin = Path.resolve(pluginDir, pluginId);\n plugin = tryLoad(externalFilePlugin);\n\n // npm package\n if (plugin === null && pluginId.match(/^[^\\.\\/]/)) {\n plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));\n // compatibility for old sinopia plugins\n if (!plugin) {\n plugin = tryLoad(Path.resolve(pluginDir, `sinopia-${pluginId}`));\n }\n }\n }\n\n // npm package\n if (plugin === null && pluginId.match(/^[^\\.\\/]/)) {\n plugin = tryLoad(`${prefix}-${pluginId}`);\n // compatibility for old sinopia plugins\n if (!plugin) {\n plugin = tryLoad(`sinopia-${pluginId}`);\n }\n }\n\n if (plugin === null) {\n plugin = tryLoad(pluginId);\n }\n\n // relative to config path\n debug('config path: %s', config.configPath);\n if (plugin === null && pluginId.match(/^\\.\\.?($|\\/)/) && config.configPath) {\n plugin = tryLoad(Path.resolve(Path.dirname(config.configPath), pluginId));\n }\n\n if (plugin === null) {\n logger.error(\n { content: pluginId, prefix },\n 'plugin not found. try npm install @{prefix}-@{content}'\n );\n throw Error(`\n ${prefix}-${pluginId} plugin not found. try \"npm install ${prefix}-${pluginId}\"`);\n }\n\n if (!isValid(plugin)) {\n logger.error(\n { content: pluginId },\n '@{prefix}-@{content} plugin does not have the right code structure'\n );\n throw Error(`\"${pluginId}\" plugin does not have the right code structure`);\n }\n\n /* eslint new-cap:off */\n try {\n plugin = isES6(plugin)\n ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params)\n : new plugin(pluginConfigs[pluginId], params);\n } catch (error: any) {\n plugin = null;\n logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');\n }\n /* eslint new-cap:off */\n\n if (plugin === null || !sanityCheck(plugin)) {\n logger.error(\n { content: pluginId, prefix },\n \"@{prefix}-@{content} doesn't look like a valid plugin\"\n );\n throw Error(`sanity check has failed, \"${pluginId}\" is not a valid plugin`);\n }\n\n debug('Plugin successfully loaded: %o-%o', pluginId, prefix);\n return plugin;\n });\n}\n"],"mappings":"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"}
@@ -1,143 +0,0 @@
1
- import buildDebug from 'debug';
2
- import _ from 'lodash';
3
- import Path from 'path';
4
-
5
- import { logger } from '@verdaccio/logger';
6
- import { Config, IPlugin } from '@verdaccio/types';
7
-
8
- const debug = buildDebug('verdaccio:plugin:loader');
9
-
10
- export const MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';
11
-
12
- /**
13
- * Requires a module.
14
- * @param {*} path the module's path
15
- * @return {Object}
16
- */
17
- function tryLoad(path: string): any {
18
- try {
19
- return require(path);
20
- } catch (err: any) {
21
- if (err.code === MODULE_NOT_FOUND) {
22
- return null;
23
- }
24
- throw err;
25
- }
26
- }
27
-
28
- function mergeConfig(appConfig, pluginConfig): Config {
29
- return _.merge(appConfig, pluginConfig);
30
- }
31
-
32
- function isValid(plugin): boolean {
33
- return _.isFunction(plugin) || _.isFunction(plugin.default);
34
- }
35
-
36
- function isES6(plugin): boolean {
37
- return Object.keys(plugin).includes('default');
38
- }
39
-
40
- // export type PluginGeneric<R, T extends IPlugin<R> = ;
41
-
42
- /**
43
- * Load a plugin following the rules
44
- * - First try to load from the internal directory plugins (which will disappear soon or later).
45
- * - A second attempt from the external plugin directory
46
- * - A third attempt from node_modules, in case to have multiple match as for instance
47
- * verdaccio-ldap
48
- * and sinopia-ldap. All verdaccio prefix will have preferences.
49
- * @param {*} config a reference of the configuration settings
50
- * @param {*} pluginConfigs
51
- * @param {*} params a set of params to initialize the plugin
52
- * @param {*} sanityCheck callback that check the shape that should fulfill the plugin
53
- * @return {Array} list of plugins
54
- */
55
- export function loadPlugin<T extends IPlugin<T>>(
56
- config: Config,
57
- pluginConfigs: any = {},
58
- params: any,
59
- sanityCheck: any,
60
- prefix: string = 'verdaccio'
61
- ): any[] {
62
- return Object.keys(pluginConfigs).map((pluginId: string): IPlugin<T> => {
63
- let plugin;
64
-
65
- const localPlugin = Path.resolve(__dirname + '/../plugins', pluginId);
66
- // try local plugins first
67
- plugin = tryLoad(localPlugin);
68
-
69
- // try the external plugin directory
70
- if (plugin === null && config.plugins) {
71
- const pluginDir = config.plugins;
72
- const externalFilePlugin = Path.resolve(pluginDir, pluginId);
73
- plugin = tryLoad(externalFilePlugin);
74
-
75
- // npm package
76
- if (plugin === null && pluginId.match(/^[^\.\/]/)) {
77
- plugin = tryLoad(Path.resolve(pluginDir, `${prefix}-${pluginId}`));
78
- // compatibility for old sinopia plugins
79
- if (!plugin) {
80
- plugin = tryLoad(Path.resolve(pluginDir, `sinopia-${pluginId}`));
81
- }
82
- }
83
- }
84
-
85
- // npm package
86
- if (plugin === null && pluginId.match(/^[^\.\/]/)) {
87
- plugin = tryLoad(`${prefix}-${pluginId}`);
88
- // compatibility for old sinopia plugins
89
- if (!plugin) {
90
- plugin = tryLoad(`sinopia-${pluginId}`);
91
- }
92
- }
93
-
94
- if (plugin === null) {
95
- plugin = tryLoad(pluginId);
96
- }
97
-
98
- // relative to config path
99
- debug('config path: %s', config.configPath);
100
- if (plugin === null && pluginId.match(/^\.\.?($|\/)/) && config.configPath) {
101
- plugin = tryLoad(Path.resolve(Path.dirname(config.configPath), pluginId));
102
- }
103
-
104
- if (plugin === null) {
105
- logger.error(
106
- { content: pluginId, prefix },
107
- 'plugin not found. try npm install @{prefix}-@{content}'
108
- );
109
- throw Error(`
110
- ${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
111
- }
112
-
113
- if (!isValid(plugin)) {
114
- logger.error(
115
- { content: pluginId },
116
- '@{prefix}-@{content} plugin does not have the right code structure'
117
- );
118
- throw Error(`"${pluginId}" plugin does not have the right code structure`);
119
- }
120
-
121
- /* eslint new-cap:off */
122
- try {
123
- plugin = isES6(plugin)
124
- ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params)
125
- : new plugin(pluginConfigs[pluginId], params);
126
- } catch (error: any) {
127
- plugin = null;
128
- logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');
129
- }
130
- /* eslint new-cap:off */
131
-
132
- if (plugin === null || !sanityCheck(plugin)) {
133
- logger.error(
134
- { content: pluginId, prefix },
135
- "@{prefix}-@{content} doesn't look like a valid plugin"
136
- );
137
- throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`);
138
- }
139
-
140
- debug('Plugin successfully loaded: %o-%o', pluginId, prefix);
141
- return plugin;
142
- });
143
- }
@@ -1,88 +0,0 @@
1
- import path from 'path';
2
-
3
- import { setup } from '@verdaccio/logger';
4
-
5
- import { loadPlugin } from '../src/plugin-loader';
6
-
7
- setup([]);
8
-
9
- describe('plugin loader', () => {
10
- const relativePath = path.join(__dirname, './partials/test-plugin-storage');
11
- const buildConf = (name) => {
12
- return {
13
- config_path: path.join(__dirname, './'),
14
- max_users: 0,
15
- auth: {
16
- [`${relativePath}/${name}`]: {},
17
- },
18
- };
19
- };
20
-
21
- describe('auth plugins', () => {
22
- test('testing auth valid plugin loader', () => {
23
- const _config = buildConf('verdaccio-plugin');
24
- // @ts-ignore
25
- const plugins = loadPlugin(_config, _config.auth, {}, function (plugin) {
26
- return plugin.authenticate || plugin.allow_access || plugin.allow_publish;
27
- });
28
-
29
- expect(plugins).toHaveLength(1);
30
- });
31
-
32
- test('testing storage valid plugin loader', () => {
33
- const _config = buildConf('verdaccio-es6-plugin');
34
- // @ts-ignore
35
- const plugins = loadPlugin(_config, _config.auth, {}, function (p) {
36
- return p.getPackageStorage;
37
- });
38
-
39
- expect(plugins).toHaveLength(1);
40
- });
41
-
42
- test('testing auth plugin invalid plugin', () => {
43
- const _config = buildConf('invalid-plugin');
44
- try {
45
- // @ts-ignore
46
- loadPlugin(_config, _config.auth, {}, function (p) {
47
- return p.authenticate || p.allow_access || p.allow_publish;
48
- });
49
- } catch (e: any) {
50
- expect(e.message).toEqual(
51
- `"${relativePath}/invalid-plugin" plugin does not have the right code structure`
52
- );
53
- }
54
- });
55
-
56
- test('testing auth plugin invalid plugin sanityCheck', () => {
57
- const _config = buildConf('invalid-plugin-sanity');
58
- try {
59
- // @ts-ignore
60
- loadPlugin(_config, _config.auth, {}, function (plugin) {
61
- return plugin.authenticate || plugin.allow_access || plugin.allow_publish;
62
- });
63
- } catch (err: any) {
64
- expect(err.message).toEqual(
65
- `sanity check has failed, "${relativePath}/invalid-plugin-sanity" is not a valid plugin`
66
- );
67
- }
68
- });
69
-
70
- test('testing auth plugin no plugins', () => {
71
- const _config = buildConf('invalid-package');
72
- try {
73
- // @ts-ignore
74
- loadPlugin(_config, _config.auth, {}, function (plugin) {
75
- return plugin.authenticate || plugin.allow_access || plugin.allow_publish;
76
- });
77
- } catch (e: any) {
78
- expect(e.message).toMatch('plugin not found');
79
- expect(e.message.replace(/\\/g, '/')).toMatch(
80
- '/partials/test-plugin-storage/invalid-package'
81
- );
82
- }
83
- });
84
-
85
- test.todo('test middleware plugins');
86
- test.todo('test storage plugins');
87
- });
88
- });