verdaccio
Version:
A lightweight private npm proxy registry
94 lines (93 loc) • 3.86 kB
JavaScript
import { isLegacyStoragePlugin, wrapLegacyStoragePlugin } from "./legacy-storage-adapter.mjs";
import { head, isNil } from "lodash-es";
import { PLUGIN_CATEGORY, PLUGIN_PREFIX, errorUtils } from "@verdaccio/core";
import createDebug from "debug";
import assert from "node:assert";
import { asyncLoadPlugin } from "@verdaccio/loaders";
import LocalDatabaseModule from "@verdaccio/local-storage";
import { Storage as Storage$1 } from "@verdaccio/store";
//#region src/lib/storage.ts
var debug = createDebug("verdaccio:storage");
var LocalDatabase = LocalDatabaseModule.default || LocalDatabaseModule;
var storageSanityCheck = (plugin) => typeof plugin?.getPackageStorage !== "undefined";
/**
* Drop-in replacement for `@verdaccio/store`'s internal `LocalStorage` that
* loads the configured storage plugin exactly like upstream, but wraps a
* legacy callback-based plugin in a promisifying adapter so it satisfies the
* promise contract the rest of `@verdaccio/store` relies on.
*
* `@verdaccio/store` only ever calls `init()`, `getSecret()` and
* `getStoragePlugin()` on this object, so that is the entire surface we mirror.
*/
var CompatLocalStorage = class {
storagePlugin = null;
config;
logger;
constructor(config, logger) {
this.config = config;
this.logger = logger.child({ sub: "fs" });
}
async init() {
if (this.storagePlugin === null) {
const loaded = await this.loadStorage();
this.storagePlugin = isLegacyStoragePlugin(loaded) ? wrapLegacyStoragePlugin(loaded, this.logger) : loaded;
debug("storage plugin init");
await this.storagePlugin.init();
debug("storage plugin initialized");
} else this.logger.warn("storage plugin has been already initialized");
}
getStoragePlugin() {
if (this.storagePlugin === null) throw errorUtils.getInternalError("storage plugin is not initialized");
return this.storagePlugin;
}
async getSecret(config) {
const secretKey = await this.storagePlugin.getSecret();
return this.storagePlugin.setSecret(config.checkSecretKey(secretKey));
}
async loadStorage() {
const Storage = await this.loadStorePlugin();
if (isNil(Storage)) {
assert(this.config.storage, "CONFIG: storage path not defined");
debug("no custom storage found, loading default storage @verdaccio/local-storage");
const localStorage = new LocalDatabase(this.config, this.logger);
this.logger.info({
name: "@verdaccio/local-storage",
pluginCategory: PLUGIN_CATEGORY.STORAGE
}, "plugin @{name} successfully loaded (@{pluginCategory})");
return localStorage;
}
return Storage;
}
async loadStorePlugin() {
const plugins = await asyncLoadPlugin(this.config.store, {
config: this.config,
logger: this.logger
}, storageSanityCheck, true, this.config.server?.pluginPrefix ?? PLUGIN_PREFIX, PLUGIN_CATEGORY.STORAGE);
if (plugins.length > 1) this.logger.warn("more than one storage plugins has been detected, multiple storage are not supported, one will be selected automatically");
return head(plugins);
}
};
/**
* `@verdaccio/store` Storage, with one change: it loads the storage plugin
* through {@link CompatLocalStorage} so legacy callback plugins keep working.
*
* The base `init()` only creates its internal `LocalStorage` when
* `this.localStorage` is still null; by pre-populating it we reuse the entire
* rest of the upstream Storage implementation (including filter loading via
* `super.init`) unchanged.
*/
var Storage = class extends Storage$1 {
async init(config) {
if (this.localStorage === null) {
const localStorage = new CompatLocalStorage(this.config, this.logger);
await localStorage.init();
await localStorage.getSecret(config);
this.localStorage = localStorage;
debug("compat local storage initialized");
}
await super.init(config);
}
};
//#endregion
export { Storage, Storage as default };
//# sourceMappingURL=storage.mjs.map