1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-11-01 19:07:38 +01:00
unleash.unleash/src/lib/server-impl.ts
Fredrik Strand Oseberg 26c9d53b89
feat: Move environments to enterprise (#935)
- Adding, updating and renaming environments are meant to be
  enterprise only features, as such, this PR moves these operations out
  of this server

- We still keep sortOrder updating, toggling on/off and getting one,
  getting all, so we can still work with environments in the OSS version
  as well.

Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>

Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2021-09-13 15:57:38 +02:00

180 lines
5.4 KiB
TypeScript

import EventEmitter from 'events';
import stoppable, { StoppableServer } from 'stoppable';
import { promisify } from 'util';
import version from './util/version';
import { migrateDb } from '../migrator';
import getApp from './app';
import { createMetricsMonitor } from './metrics';
import { createStores } from './db';
import { createServices } from './services';
import { createConfig } from './create-config';
import { addEventHook } from './event-hook';
import registerGracefulShutdown from './util/graceful-shutdown';
import { createDb } from './db/db-pool';
import sessionDb from './middleware/session-db';
// Types
import { IUnleash } from './types/core';
import { IUnleashConfig, IUnleashOptions, IAuthType } from './types/option';
import { IUnleashServices } from './types/services';
import User, { IUser } from './types/user';
import { Logger, LogLevel } from './logger';
import AuthenticationRequired from './types/authentication-required';
import Controller from './routes/controller';
import { IAuthRequest } from './routes/unleash-types';
import * as permissions from './types/permissions';
import * as eventType from './types/events';
import { RoleName } from './types/model';
async function createApp(
config: IUnleashConfig,
startApp: boolean,
): Promise<IUnleash> {
// Database dependencies (stateful)
const logger = config.getLogger('server-impl.js');
const serverVersion = version;
const eventBus = new EventEmitter();
const db = createDb(config);
const stores = createStores(config, eventBus, db);
const services = createServices(stores, config);
const metricsMonitor = createMetricsMonitor();
const unleashSession = sessionDb(config, db);
const stopUnleash = async (server?: StoppableServer) => {
logger.info('Shutting down Unleash...');
if (server) {
const stopServer = promisify(server.stop);
await stopServer();
}
metricsMonitor.stopMonitoring();
stores.clientInstanceStore.destroy();
stores.clientMetricsStore.destroy();
await db.destroy();
};
if (!config.server.secret) {
const secret = await stores.settingStore.get('unleash.secret');
// eslint-disable-next-line no-param-reassign
config.server.secret = secret;
}
const app = getApp(config, stores, services, eventBus, unleashSession);
if (typeof config.eventHook === 'function') {
addEventHook(config.eventHook, stores.eventStore);
}
metricsMonitor.startMonitoring(config, stores, serverVersion, eventBus, db);
const unleash: Omit<IUnleash, 'stop'> = {
stores,
eventBus,
services,
app,
config,
version: serverVersion,
};
if (config.import.file) {
await services.stateService.importFile({
file: config.import.file,
dropBeforeImport: config.import.dropBeforeImport,
userName: 'import',
keepExisting: config.import.keepExisting,
});
}
return new Promise((resolve, reject) => {
if (startApp) {
const server = stoppable(
app.listen(config.listen, () =>
logger.info('Unleash has started.', server.address()),
),
config.server.gracefulShutdownTimeout,
);
server.keepAliveTimeout = config.server.keepAliveTimeout;
server.headersTimeout = config.server.headersTimeout;
server.on('listening', () => {
resolve({
...unleash,
server,
stop: () => stopUnleash(server),
});
});
server.on('error', reject);
} else {
resolve({ ...unleash, stop: stopUnleash });
}
});
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
async function start(opts: IUnleashOptions = {}): Promise<IUnleash> {
const config = createConfig(opts);
const logger = config.getLogger('server-impl.js');
try {
if (config.db.disableMigration) {
logger.info('DB migration: disabled');
} else {
logger.info('DB migration: start');
await migrateDb(config);
logger.info('DB migration: end');
}
} catch (err) {
logger.error('Failed to migrate db', err);
throw err;
}
const unleash = await createApp(config, true);
if (config.server.gracefulShutdownEnable) {
registerGracefulShutdown(unleash, logger);
}
return unleash;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
async function create(opts: IUnleashOptions): Promise<IUnleash> {
const config = createConfig(opts);
const logger = config.getLogger('server-impl.js');
try {
if (config.db.disableMigration) {
logger.info('DB migrations disabled');
} else {
await migrateDb(config);
}
} catch (err) {
logger.error('Failed to migrate db', err);
throw err;
}
return createApp(config, false);
}
// Module exports
export {
start,
create,
permissions,
eventType,
Controller,
AuthenticationRequired,
User,
LogLevel,
RoleName,
IAuthType,
};
export default {
start,
create,
};
export type {
Logger,
IUnleash,
IUnleashOptions,
IUnleashConfig,
IUser,
IUnleashServices,
IAuthRequest,
};