UNPKG

boostr

Version:
148 lines 5.91 kB
import { join, resolve } from 'path'; import fsExtra from 'fs-extra'; import { Subservice } from './sub.js'; import { BackendService } from './backend.js'; import { requireGlobalNPMPackage } from '../npm.js'; const MONGODB_MEMORY_SERVER_GLOBAL_PACKAGE_VERSION = '8.11.0'; const LOCAL_DATA_DIRECTORY_NAME = 'data'; export class DatabaseService extends Subservice { parseConfigURL() { const directory = this.getDirectory(); const config = this.getConfig(); const { protocol, hostname, port, pathname } = this._parseConfigURL(); if (config.platform === 'local') { if (protocol !== 'mongodb:') { this.throwError(`The 'url' property in the configuration should start with 'mongodb://' (directory: '${directory}')`); } if (hostname !== 'localhost') { this.throwError(`The host of the 'url' property in the configuration should be 'localhost' (directory: '${directory}')`); } if (!port) { this.throwError(`The 'url' property in the configuration should specify a port (directory: '${directory}')`); } if (pathname.length < 2) { this.throwError(`The 'url' property in the configuration should specify a database name (directory: '${directory}')`); } } else { this.throwError('Non-local database URL cannot be parsed for now'); } return { protocol, hostname, port, pathname }; } async start() { await super.start(); const directory = this.getDirectory(); const config = this.getConfig(); const serviceName = this.getName(); if (config.platform !== 'local') { return; } const { port, pathname } = this.parseConfigURL(); const databaseName = pathname.slice(1); const dataDirectory = join(directory, LOCAL_DATA_DIRECTORY_NAME); fsExtra.ensureDirSync(dataDirectory); const { MongoMemoryServer } = await requireGlobalNPMPackage('mongodb-memory-server-global', MONGODB_MEMORY_SERVER_GLOBAL_PACKAGE_VERSION, { serviceName }); this._localServer = (await MongoMemoryServer.create({ instance: { port, dbName: databaseName, dbPath: dataDirectory, storageEngine: 'wiredTiger' } })); let connectionString = this._localServer.getUri(); connectionString = connectionString.replace('127.0.0.1', 'localhost'); if (connectionString.endsWith('?')) { connectionString = connectionString.slice(0, -1); } this.logMessage(`MongoDB server started at ${connectionString}`); } async stop() { if (this._localServer !== undefined) { await this._localServer.stop(); this.logMessage(`MongoDB server stopped`); } } async migrate() { const directory = this.getDirectory(); const { url } = this.getConfig(); if (!url) { this.throwError(`A 'url' property is required in the configuration to migrate a database (directory: '${directory}')`); } await this.start(); for (const service of this.getDependents()) { if (service instanceof BackendService) { await service.migrateDatabase(url); } } await this.stop(); } async import(inputFile) { inputFile = resolve(process.cwd(), inputFile); const directory = this.getDirectory(); const { url } = this.getConfig(); if (!url) { this.throwError(`A 'url' property is required in the configuration to import a database (directory: '${directory}')`); } await this.start(); for (const service of this.getDependents()) { if (service instanceof BackendService) { await service.importDatabase(url, inputFile); } } await this.stop(); } async export(outputFile) { outputFile = resolve(process.cwd(), outputFile); const directory = this.getDirectory(); const { url } = this.getConfig(); if (!url) { this.throwError(`A 'url' property is required in the configuration to export a database (directory: '${directory}')`); } await this.start(); for (const service of this.getDependents()) { if (service instanceof BackendService) { await service.exportDatabase(url, outputFile); } } await this.stop(); } } DatabaseService.type = 'database'; DatabaseService.description = 'A database service providing some storage capability to your app.'; DatabaseService.examples = [ 'boostr {{serviceName}} start', 'boostr {{serviceName}} migrate', 'boostr {{serviceName}} migrate --production' ]; // === Commands === DatabaseService.commands = { ...Subservice.commands, migrate: { ...Subservice.commands.migrate, description: 'Migrates your database.', examples: ['boostr {{serviceName}} migrate'], async handler() { await this.migrate(); } }, import: { ...Subservice.commands.import, description: 'Imports the specified JSON file to your database.', examples: ['boostr {{serviceName}} import inputFile'], arguments: ['inputFile'], async handler([inputFile]) { await this.import(inputFile); } }, export: { ...Subservice.commands.export, description: 'Exports the your database to a JSON file.', examples: ['boostr {{serviceName}} export outputFile'], arguments: ['outputFile'], async handler([outputFile]) { await this.export(outputFile); } } }; //# sourceMappingURL=database.js.map