@rsksmart/rif-storage
Version:
Library integrating distributed storage projects
158 lines (152 loc) • 6.68 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Manager = void 0;
const definitions_1 = require("./definitions");
const index_1 = __importDefault(require("./index"));
const errors_1 = require("./errors");
const utils_1 = require("./utils");
/**
* Utility class that supports easy usage of multiple providers in your applications.
* It allows registration of all supported providers and then easy putting/getting data with
* the same interface as providers.
*
* It has concept of active provider which is the one to which the data are `put()`.
* When registering providers the first one will become the active one by default.
*
* For getting data it is decided based on provided address what Provider should be used. If
* provider for given address is not registered, then error is thrown.
*
* For putting data, there is concept of "active" provider, that the data are passed to.
* The first provider that you register automatically becomes the active provider. You can
* change that anytime using `makeActive()` method.
*
* @example
* ```javascript
* import { Manager, Provider } from 'rif-storage'
const storage = new Manager()
// The first added provider becomes also the active one
storage.addProvider(Provider.IPFS, { host: 'localhost', port: '5001', protocol: 'http' })
storage.addProvider(Provider.SWARM, { url: 'http://localhost:8500' })
const ipfsHash = await storage.put(Buffer.from('hello ipfs!')) // Stored to IPFS
storage.makeActive(Provider.SWARM)
const swarmHash = await storage.put(Buffer.from('hello swarm!')) // Stored to Swarm
console.log(storage.get(ipfsHash).toString()) // Retrieves data from IPFS and prints 'hello ipfs!'
console.log(storage.get(swarmHash).toString()) // Retrieves data from Swarm and prints 'hello swarm!'
```
*/
class Manager {
constructor() {
this.providers = {};
this.type = definitions_1.Provider.MANAGER;
}
/**
* Returns the active provider
*/
get activeProvider() {
if (!this.active) {
return undefined;
}
return this.providers[this.active];
}
/**
* Register new provider to be used by the Manager
* @param type {@link Provider} enum value
* @param options
* @throws {TypeError} if no type is provided
* @throws {ValueError} if invalid type is provided
*/
addProvider(type, options) {
if (!type) {
throw new TypeError('type is required!');
}
if (!this.active) {
this.active = type;
}
// Type value is checked in factory
this.providers[type] = index_1.default(type, options);
}
/**
* Specify active provider
*
* @throws {ProviderError} When provider is not registered
* @param name {@link Provider} enum value
*/
makeActive(name) {
if (!this.providers[name]) {
throw new errors_1.ProviderError(`${name} is not registered provider!`);
}
this.active = name;
}
// eslint-disable-next-line require-await
getHelper(fnName, address, options) {
return __awaiter(this, void 0, void 0, function* () {
const detected = utils_1.detectAddress(address);
if (detected === definitions_1.Provider.IPFS) {
if (this.providers[definitions_1.Provider.IPFS] === undefined) {
throw new errors_1.ProviderError('You wanted to fetched IPFS address, but you haven\'t register IPFS provider!');
}
// "!" is TS syntax for forcing compiler to not complain about possible null or undefined
return this.providers[definitions_1.Provider.IPFS][fnName](address, options);
}
else if (detected === definitions_1.Provider.SWARM) {
if (this.providers[definitions_1.Provider.SWARM] === undefined) {
throw new errors_1.ProviderError('You wanted to fetched Swarm address, but you haven\'t register Swarm provider!');
}
return this.providers[definitions_1.Provider.SWARM][fnName](address, options);
}
else {
throw new errors_1.ValueError('Address does not have expected format');
}
});
}
/**
* Retrieves data from provider.
*
* It detects which provider to use based on the format of provided address. If the detected
* provider is not registered then exception is raised.
*
* @param address
* @param options
* @throws {ProviderError} when provider is not registered for given type of address
* @throws {ValueError} if given address does not have expected format
* @see Storage#get
*/
get(address, options) {
return this.getHelper('get', address, options);
}
/**
* Retrieves data from provider.
*
* It detects which provider to use based on the format of provided address. If the detected
* provider is not registered then exception is raised.
*
* @param address
* @param options
* @throws {ProviderError} when provider is not registered for given type of address
* @throws {ValueError} if given address does not have expected format
* @see Storage#get
*/
getReadable(address, options) {
return this.getHelper('getReadable', address, options);
}
put(data, options) {
if (!this.activeProvider) {
throw new errors_1.ProviderError('Before putting any data, you have to first add some provider!');
}
// @ts-ignore: TypeScript does have problems with overloading, the implementation signature is actually matching but he looks only to the function definitions.
return this.activeProvider.put(data, options);
}
}
exports.Manager = Manager;