2022-02-11 23:59:03 +08:00
|
|
|
import { ACL } from '@nocobase/acl';
|
2021-09-16 00:38:48 +08:00
|
|
|
import { registerActions } from '@nocobase/actions';
|
2023-10-23 15:41:35 +08:00
|
|
|
import { actions as authActions, AuthManager, AuthManagerOptions } from '@nocobase/auth';
|
2023-11-21 11:39:19 +08:00
|
|
|
import { Cache, CacheManager, CacheManagerOptions } from '@nocobase/cache';
|
2023-08-24 17:47:45 +08:00
|
|
|
import Database, { CollectionOptions, IDatabaseOptions } from '@nocobase/database';
|
2023-12-27 13:56:13 +08:00
|
|
|
import {
|
2023-12-29 13:11:56 +08:00
|
|
|
AppLogger,
|
2023-12-27 13:56:13 +08:00
|
|
|
AppLoggerOptions,
|
|
|
|
createAppLogger,
|
2023-12-29 13:11:56 +08:00
|
|
|
createLogger,
|
2023-12-27 13:56:13 +08:00
|
|
|
getLoggerFilePath,
|
2023-12-29 13:11:56 +08:00
|
|
|
LoggerOptions,
|
2023-12-27 13:56:13 +08:00
|
|
|
} from '@nocobase/logger';
|
2023-12-29 13:11:56 +08:00
|
|
|
import { ResourceOptions, Resourcer } from '@nocobase/resourcer';
|
2023-10-23 15:41:35 +08:00
|
|
|
import { applyMixins, AsyncEmitter, measureExecutionTime, Toposort, ToposortOptions } from '@nocobase/utils';
|
2023-12-29 13:11:56 +08:00
|
|
|
import chalk from 'chalk';
|
2022-08-08 14:42:48 +08:00
|
|
|
import { Command, CommandOptions, ParseOptions } from 'commander';
|
2023-12-29 13:11:56 +08:00
|
|
|
import { randomUUID } from 'crypto';
|
2023-08-24 17:47:45 +08:00
|
|
|
import { IncomingMessage, Server, ServerResponse } from 'http';
|
2021-11-08 19:32:59 +08:00
|
|
|
import { i18n, InitOptions } from 'i18next';
|
2022-09-23 09:22:17 +08:00
|
|
|
import Koa, { DefaultContext as KoaDefaultContext, DefaultState as KoaDefaultState } from 'koa';
|
2022-09-29 21:05:31 +08:00
|
|
|
import compose from 'koa-compose';
|
2023-08-24 17:47:45 +08:00
|
|
|
import lodash from 'lodash';
|
2023-12-29 13:11:56 +08:00
|
|
|
import { RecordableHistogram } from 'node:perf_hooks';
|
|
|
|
import packageJson from '../package.json';
|
2022-02-11 23:59:03 +08:00
|
|
|
import { createACL } from './acl';
|
2023-09-24 11:41:26 +08:00
|
|
|
import { AppCommand } from './app-command';
|
2023-08-24 17:47:45 +08:00
|
|
|
import { AppSupervisor } from './app-supervisor';
|
2023-11-21 11:39:19 +08:00
|
|
|
import { createCacheManager } from './cache';
|
2022-05-19 00:40:55 +08:00
|
|
|
import { registerCli } from './commands';
|
2023-11-21 11:39:19 +08:00
|
|
|
import { CronJobManager } from './cron/cron-job-manager';
|
2023-08-24 17:47:45 +08:00
|
|
|
import { ApplicationNotInstall } from './errors/application-not-install';
|
2023-12-12 23:02:09 +08:00
|
|
|
import {
|
|
|
|
createAppProxy,
|
|
|
|
createI18n,
|
|
|
|
createResourcer,
|
2023-12-29 13:11:56 +08:00
|
|
|
enablePerfHooks,
|
2023-12-12 23:02:09 +08:00
|
|
|
getCommandFullName,
|
|
|
|
registerMiddlewares,
|
|
|
|
} from './helper';
|
2023-08-24 17:47:45 +08:00
|
|
|
import { ApplicationVersion } from './helpers/application-version';
|
2023-07-25 17:09:34 +08:00
|
|
|
import { Locale } from './locale';
|
2022-01-30 11:11:36 +08:00
|
|
|
import { Plugin } from './plugin';
|
2022-04-24 12:38:54 +08:00
|
|
|
import { InstallOptions, PluginManager } from './plugin-manager';
|
2022-10-10 15:37:47 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
export type PluginType = string | typeof Plugin;
|
|
|
|
export type PluginConfiguration = PluginType | [PluginType, any];
|
2022-04-17 10:00:42 +08:00
|
|
|
|
2021-09-09 13:05:33 +08:00
|
|
|
export interface ResourcerOptions {
|
|
|
|
prefix?: string;
|
|
|
|
}
|
2020-11-12 11:48:27 +08:00
|
|
|
|
|
|
|
export interface ApplicationOptions {
|
2022-02-15 00:20:25 +08:00
|
|
|
database?: IDatabaseOptions | Database;
|
2023-11-20 17:14:20 +08:00
|
|
|
cacheManager?: CacheManagerOptions;
|
2021-09-09 13:05:33 +08:00
|
|
|
resourcer?: ResourcerOptions;
|
|
|
|
bodyParser?: any;
|
|
|
|
cors?: any;
|
|
|
|
dataWrapping?: boolean;
|
2021-10-18 12:49:37 +08:00
|
|
|
registerActions?: boolean;
|
2021-11-08 19:32:59 +08:00
|
|
|
i18n?: i18n | InitOptions;
|
2022-09-19 09:23:01 +08:00
|
|
|
plugins?: PluginConfiguration[];
|
2022-09-29 21:05:31 +08:00
|
|
|
acl?: boolean;
|
2022-11-12 17:12:50 +08:00
|
|
|
logger?: AppLoggerOptions;
|
2022-10-27 13:00:16 +08:00
|
|
|
pmSock?: string;
|
2023-02-14 15:30:58 +08:00
|
|
|
name?: string;
|
2023-10-23 15:41:35 +08:00
|
|
|
authManager?: AuthManagerOptions;
|
2023-12-12 23:02:09 +08:00
|
|
|
perfHooks?: boolean;
|
2020-11-12 11:48:27 +08:00
|
|
|
}
|
2020-11-11 18:16:18 +08:00
|
|
|
|
2022-09-23 09:22:17 +08:00
|
|
|
export interface DefaultState extends KoaDefaultState {
|
2021-09-16 15:57:21 +08:00
|
|
|
currentUser?: any;
|
2023-01-09 07:35:48 +08:00
|
|
|
|
2021-09-16 15:57:21 +08:00
|
|
|
[key: string]: any;
|
|
|
|
}
|
|
|
|
|
2022-09-23 09:22:17 +08:00
|
|
|
export interface DefaultContext extends KoaDefaultContext {
|
2021-09-16 15:57:21 +08:00
|
|
|
db: Database;
|
2022-10-10 15:37:47 +08:00
|
|
|
cache: Cache;
|
2021-09-16 15:57:21 +08:00
|
|
|
resourcer: Resourcer;
|
2022-09-23 09:22:17 +08:00
|
|
|
i18n: any;
|
2023-01-09 07:35:48 +08:00
|
|
|
|
2021-09-16 15:57:21 +08:00
|
|
|
[key: string]: any;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface ActionsOptions {
|
|
|
|
resourceName?: string;
|
|
|
|
resourceNames?: string[];
|
|
|
|
}
|
|
|
|
|
2022-01-30 11:11:36 +08:00
|
|
|
interface ListenOptions {
|
|
|
|
port?: number | undefined;
|
|
|
|
host?: string | undefined;
|
|
|
|
backlog?: number | undefined;
|
|
|
|
path?: string | undefined;
|
|
|
|
exclusive?: boolean | undefined;
|
|
|
|
readableAll?: boolean | undefined;
|
|
|
|
writableAll?: boolean | undefined;
|
|
|
|
/**
|
|
|
|
* @default false
|
|
|
|
*/
|
|
|
|
ipv6Only?: boolean | undefined;
|
|
|
|
signal?: AbortSignal | undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface StartOptions {
|
2022-02-07 01:14:00 +08:00
|
|
|
cliArgs?: any[];
|
2022-11-04 15:38:08 +08:00
|
|
|
dbSync?: boolean;
|
2023-08-24 17:47:45 +08:00
|
|
|
checkInstall?: boolean;
|
2023-09-25 15:26:52 +08:00
|
|
|
recover?: boolean;
|
2022-01-30 11:11:36 +08:00
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
type MaintainingStatus = 'command_begin' | 'command_end' | 'command_running' | 'command_error';
|
2022-06-17 10:25:59 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
export type MaintainingCommandStatus = {
|
|
|
|
command: {
|
|
|
|
name: string;
|
|
|
|
};
|
|
|
|
status: MaintainingStatus;
|
|
|
|
error?: Error;
|
|
|
|
};
|
2022-06-17 10:25:59 +08:00
|
|
|
|
2022-01-30 11:11:36 +08:00
|
|
|
export class Application<StateT = DefaultState, ContextT = DefaultContext> extends Koa implements AsyncEmitter {
|
2023-08-24 17:47:45 +08:00
|
|
|
public listenServer: Server;
|
|
|
|
declare middleware: any;
|
|
|
|
stopped = false;
|
|
|
|
ready = false;
|
|
|
|
declare emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>;
|
|
|
|
public rawOptions: ApplicationOptions;
|
|
|
|
public activatedCommand: {
|
|
|
|
name: string;
|
|
|
|
} = null;
|
|
|
|
public running = false;
|
2023-12-12 23:02:09 +08:00
|
|
|
public perfHistograms = new Map<string, RecordableHistogram>();
|
2023-08-24 17:47:45 +08:00
|
|
|
protected plugins = new Map<string, Plugin>();
|
|
|
|
protected _appSupervisor: AppSupervisor = AppSupervisor.getInstance();
|
|
|
|
protected _started: boolean;
|
|
|
|
private _authenticated = false;
|
|
|
|
private _maintaining = false;
|
|
|
|
private _maintainingCommandStatus: MaintainingCommandStatus;
|
|
|
|
private _maintainingStatusBeforeCommand: MaintainingCommandStatus | null;
|
2023-09-12 22:39:23 +08:00
|
|
|
private _actionCommand: Command;
|
2021-09-05 23:59:38 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
constructor(public options: ApplicationOptions) {
|
|
|
|
super();
|
2023-12-27 13:56:13 +08:00
|
|
|
this.context.reqId = randomUUID();
|
2023-08-24 17:47:45 +08:00
|
|
|
this.rawOptions = this.name == 'main' ? lodash.cloneDeep(options) : {};
|
|
|
|
this.init();
|
2021-11-08 19:32:59 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this._appSupervisor.addApp(this);
|
|
|
|
}
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _loaded: boolean;
|
2022-02-11 23:59:03 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get loaded() {
|
|
|
|
return this._loaded;
|
|
|
|
}
|
2022-03-28 22:01:10 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
private _maintainingMessage: string;
|
2023-06-07 23:46:42 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get maintainingMessage() {
|
|
|
|
return this._maintainingMessage;
|
|
|
|
}
|
2023-07-25 17:09:34 +08:00
|
|
|
|
2023-09-27 19:31:14 +08:00
|
|
|
protected _cronJobManager: CronJobManager;
|
|
|
|
|
|
|
|
get cronJobManager() {
|
|
|
|
return this._cronJobManager;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _db: Database;
|
2022-06-17 10:25:59 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get db() {
|
|
|
|
return this._db;
|
|
|
|
}
|
2020-11-12 11:48:27 +08:00
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
protected _logger: AppLogger;
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get logger() {
|
|
|
|
return this._logger;
|
|
|
|
}
|
2022-09-29 21:05:31 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _resourcer: Resourcer;
|
2023-03-06 21:19:49 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get resourcer() {
|
|
|
|
return this._resourcer;
|
2022-09-18 14:10:01 +08:00
|
|
|
}
|
|
|
|
|
2023-11-20 17:14:20 +08:00
|
|
|
protected _cacheManager: CacheManager;
|
|
|
|
|
|
|
|
get cacheManager() {
|
|
|
|
return this._cacheManager;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _cache: Cache;
|
2022-09-18 14:10:01 +08:00
|
|
|
|
2022-10-10 15:37:47 +08:00
|
|
|
get cache() {
|
|
|
|
return this._cache;
|
|
|
|
}
|
|
|
|
|
2023-12-21 20:39:11 +08:00
|
|
|
set cache(cache: Cache) {
|
|
|
|
this._cache = cache;
|
|
|
|
}
|
|
|
|
|
2023-09-19 14:39:54 +08:00
|
|
|
protected _cli: AppCommand;
|
2022-09-18 14:10:01 +08:00
|
|
|
|
|
|
|
get cli() {
|
|
|
|
return this._cli;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _i18n: i18n;
|
2022-09-18 14:10:01 +08:00
|
|
|
|
|
|
|
get i18n() {
|
|
|
|
return this._i18n;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _pm: PluginManager;
|
|
|
|
|
2022-09-18 14:10:01 +08:00
|
|
|
get pm() {
|
|
|
|
return this._pm;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _acl: ACL;
|
2021-09-09 13:05:33 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get acl() {
|
|
|
|
return this._acl;
|
2022-09-18 14:10:01 +08:00
|
|
|
}
|
2021-09-05 23:59:38 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _authManager: AuthManager;
|
|
|
|
|
2023-06-07 23:46:42 +08:00
|
|
|
get authManager() {
|
|
|
|
return this._authManager;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _locales: Locale;
|
|
|
|
|
|
|
|
get locales() {
|
|
|
|
return this._locales;
|
2022-11-12 17:12:50 +08:00
|
|
|
}
|
|
|
|
|
2023-11-21 11:39:19 +08:00
|
|
|
get localeManager() {
|
|
|
|
return this._locales;
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected _version: ApplicationVersion;
|
|
|
|
|
|
|
|
get version() {
|
|
|
|
return this._version;
|
2022-11-12 17:12:50 +08:00
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
get log() {
|
|
|
|
return this._logger;
|
2023-07-25 17:09:34 +08:00
|
|
|
}
|
|
|
|
|
2023-02-14 15:30:58 +08:00
|
|
|
get name() {
|
|
|
|
return this.options.name || 'main';
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
isMaintaining() {
|
|
|
|
return this._maintaining;
|
|
|
|
}
|
2023-06-07 23:46:42 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
getMaintaining() {
|
|
|
|
return this._maintainingCommandStatus;
|
|
|
|
}
|
2022-09-29 21:05:31 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
setMaintaining(_maintainingCommandStatus: MaintainingCommandStatus) {
|
|
|
|
this._maintainingCommandStatus = _maintainingCommandStatus;
|
2023-07-25 17:09:34 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.emit('maintaining', _maintainingCommandStatus);
|
2022-03-11 10:10:57 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
if (_maintainingCommandStatus.status == 'command_end') {
|
|
|
|
this._maintaining = false;
|
|
|
|
return;
|
2021-09-09 13:05:33 +08:00
|
|
|
}
|
2022-04-17 10:00:42 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this._maintaining = true;
|
2022-06-17 10:25:59 +08:00
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
setMaintainingMessage(message: string) {
|
|
|
|
this._maintainingMessage = message;
|
2023-03-10 19:16:00 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.emit('maintainingMessageChanged', {
|
|
|
|
message: this._maintainingMessage,
|
|
|
|
maintainingStatus: this._maintainingCommandStatus,
|
|
|
|
});
|
2022-05-19 00:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
getVersion() {
|
|
|
|
return packageJson.version;
|
2020-12-18 19:54:53 +08:00
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
plugin<O = any>(pluginClass: any, options?: O) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug(`add plugin`, { method: 'plugin', name: pluginClass.name });
|
2023-08-24 17:47:45 +08:00
|
|
|
this.pm.addPreset(pluginClass, options);
|
2022-01-30 11:11:36 +08:00
|
|
|
}
|
|
|
|
|
2022-09-29 21:05:31 +08:00
|
|
|
// @ts-ignore
|
2021-09-16 15:57:21 +08:00
|
|
|
use<NewStateT = {}, NewContextT = {}>(
|
|
|
|
middleware: Koa.Middleware<StateT & NewStateT, ContextT & NewContextT>,
|
2022-09-29 21:05:31 +08:00
|
|
|
options?: ToposortOptions,
|
2021-09-23 00:16:04 +08:00
|
|
|
) {
|
2022-09-29 21:05:31 +08:00
|
|
|
this.middleware.add(middleware, options);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
callback() {
|
|
|
|
const fn = compose(this.middleware.nodes);
|
|
|
|
|
|
|
|
if (!this.listenerCount('error')) this.on('error', this.onerror);
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
return (req: IncomingMessage, res: ServerResponse) => {
|
2022-09-29 21:05:31 +08:00
|
|
|
const ctx = this.createContext(req, res);
|
2023-03-07 22:10:51 +08:00
|
|
|
|
2022-09-29 21:05:31 +08:00
|
|
|
// @ts-ignore
|
|
|
|
return this.handleRequest(ctx, fn);
|
|
|
|
};
|
2021-09-16 15:57:21 +08:00
|
|
|
}
|
|
|
|
|
2021-12-06 21:23:34 +08:00
|
|
|
collection(options: CollectionOptions) {
|
|
|
|
return this.db.collection(options);
|
2021-09-14 11:09:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
resource(options: ResourceOptions) {
|
|
|
|
return this.resourcer.define(options);
|
|
|
|
}
|
|
|
|
|
2021-09-16 15:57:21 +08:00
|
|
|
actions(handlers: any, options?: ActionsOptions) {
|
2021-09-16 00:38:48 +08:00
|
|
|
return this.resourcer.registerActions(handlers);
|
|
|
|
}
|
|
|
|
|
2023-09-19 14:39:54 +08:00
|
|
|
command(name: string, desc?: string, opts?: CommandOptions): AppCommand {
|
2022-05-19 00:40:55 +08:00
|
|
|
return this.cli.command(name, desc, opts).allowUnknownOption();
|
2021-09-14 11:09:26 +08:00
|
|
|
}
|
|
|
|
|
2021-10-18 12:49:37 +08:00
|
|
|
findCommand(name: string): Command {
|
2023-08-24 17:47:45 +08:00
|
|
|
return (this.cli as any)._findCommand(name);
|
2021-10-18 12:49:37 +08:00
|
|
|
}
|
|
|
|
|
2022-10-27 13:00:16 +08:00
|
|
|
async load(options?: any) {
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this._loaded) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-27 13:00:16 +08:00
|
|
|
if (options?.reload) {
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('app reload');
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.info(`app.reload()`, { method: 'load' });
|
2022-10-31 22:45:39 +08:00
|
|
|
const oldDb = this._db;
|
2022-10-27 13:00:16 +08:00
|
|
|
this.init();
|
2023-09-12 22:39:23 +08:00
|
|
|
if (!oldDb.closed()) {
|
|
|
|
await oldDb.close();
|
|
|
|
}
|
2023-11-20 17:14:20 +08:00
|
|
|
if (this._cacheManager) {
|
|
|
|
await this._cacheManager.close();
|
|
|
|
}
|
2022-10-27 13:00:16 +08:00
|
|
|
}
|
2022-10-31 22:45:39 +08:00
|
|
|
|
2023-11-20 17:14:20 +08:00
|
|
|
this._cacheManager = await createCacheManager(this, this.options.cacheManager);
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('init plugins');
|
|
|
|
await this.pm.initPlugins();
|
|
|
|
|
|
|
|
this.setMaintainingMessage('start load');
|
|
|
|
|
|
|
|
this.setMaintainingMessage('emit beforeLoad');
|
2022-10-27 13:00:16 +08:00
|
|
|
await this.emitAsync('beforeLoad', this, options);
|
2023-08-24 17:47:45 +08:00
|
|
|
|
2022-10-27 13:00:16 +08:00
|
|
|
await this.pm.load(options);
|
2023-08-24 17:47:45 +08:00
|
|
|
|
|
|
|
this.setMaintainingMessage('emit afterLoad');
|
2022-10-27 13:00:16 +08:00
|
|
|
await this.emitAsync('afterLoad', this, options);
|
2023-08-24 17:47:45 +08:00
|
|
|
this._loaded = true;
|
2021-09-14 11:09:26 +08:00
|
|
|
}
|
|
|
|
|
2022-10-27 13:00:16 +08:00
|
|
|
async reload(options?: any) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug(`start reload`, { method: 'reload' });
|
2023-08-24 17:47:45 +08:00
|
|
|
|
|
|
|
this._loaded = false;
|
|
|
|
|
2023-09-27 19:31:14 +08:00
|
|
|
await this.emitAsync('beforeReload', this, options);
|
|
|
|
|
2022-10-27 13:00:16 +08:00
|
|
|
await this.load({
|
|
|
|
...options,
|
|
|
|
reload: true,
|
|
|
|
});
|
2023-03-10 19:16:00 +08:00
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('emit afterReload', { method: 'reload' });
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('emit afterReload');
|
2023-03-10 19:16:00 +08:00
|
|
|
await this.emitAsync('afterReload', this, options);
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug(`finish reload`, { method: 'reload' });
|
2022-09-18 14:10:01 +08:00
|
|
|
}
|
|
|
|
|
2023-12-29 13:11:56 +08:00
|
|
|
/**
|
|
|
|
* @deprecated Use the `pm.get()` instead.
|
|
|
|
*/
|
2023-08-24 17:47:45 +08:00
|
|
|
getPlugin<P extends Plugin>(name: string | typeof Plugin) {
|
2022-01-30 11:11:36 +08:00
|
|
|
return this.pm.get(name) as P;
|
2022-01-24 14:10:35 +08:00
|
|
|
}
|
|
|
|
|
2022-01-30 11:11:36 +08:00
|
|
|
async parse(argv = process.argv) {
|
2022-08-08 14:42:48 +08:00
|
|
|
return this.runAsCLI(argv);
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
async authenticate() {
|
|
|
|
if (this._authenticated) {
|
|
|
|
return;
|
2022-12-02 22:43:51 +08:00
|
|
|
}
|
2023-08-24 17:47:45 +08:00
|
|
|
this._authenticated = true;
|
2023-09-18 10:00:11 +08:00
|
|
|
await this.db.auth();
|
2023-11-20 08:54:40 +08:00
|
|
|
await this.db.checkVersion();
|
2023-02-23 20:14:50 +08:00
|
|
|
await this.db.prepare();
|
2023-08-24 17:47:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
async runCommand(command: string, ...args: any[]) {
|
|
|
|
return await this.runAsCLI([command, ...args], { from: 'user' });
|
|
|
|
}
|
|
|
|
|
|
|
|
createCli() {
|
2023-09-19 14:39:54 +08:00
|
|
|
const command = new AppCommand('nocobase')
|
2023-08-24 17:47:45 +08:00
|
|
|
.usage('[command] [options]')
|
|
|
|
.hook('preAction', async (_, actionCommand) => {
|
2023-09-12 22:39:23 +08:00
|
|
|
this._actionCommand = actionCommand;
|
2023-08-24 17:47:45 +08:00
|
|
|
this.activatedCommand = {
|
|
|
|
name: getCommandFullName(actionCommand),
|
|
|
|
};
|
2023-02-23 20:14:50 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintaining({
|
|
|
|
status: 'command_begin',
|
|
|
|
command: this.activatedCommand,
|
|
|
|
});
|
|
|
|
|
|
|
|
this.setMaintaining({
|
|
|
|
status: 'command_running',
|
|
|
|
command: this.activatedCommand,
|
|
|
|
});
|
|
|
|
|
|
|
|
await this.authenticate();
|
|
|
|
await this.load();
|
|
|
|
})
|
|
|
|
.hook('postAction', async (_, actionCommand) => {
|
|
|
|
if (this._maintainingStatusBeforeCommand?.error && this._started) {
|
|
|
|
await this.restart();
|
|
|
|
}
|
2022-12-17 10:35:10 +08:00
|
|
|
});
|
2023-09-01 16:11:27 +08:00
|
|
|
|
|
|
|
command.exitOverride((err) => {
|
|
|
|
throw err;
|
|
|
|
});
|
|
|
|
|
|
|
|
return command;
|
2023-08-24 17:47:45 +08:00
|
|
|
}
|
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
async runAsCLI(argv = process.argv, options?: ParseOptions & { throwError?: boolean; reqId?: string }) {
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this.activatedCommand) {
|
|
|
|
return;
|
2022-12-17 10:35:10 +08:00
|
|
|
}
|
2023-12-27 13:56:13 +08:00
|
|
|
if (options.reqId) {
|
|
|
|
this.context.reqId = options.reqId;
|
|
|
|
this._logger = this._logger.child({ reqId: this.context.reqId });
|
|
|
|
}
|
2023-08-24 17:47:45 +08:00
|
|
|
this._maintainingStatusBeforeCommand = this._maintainingCommandStatus;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const command = await this.cli.parseAsync(argv, options);
|
|
|
|
|
|
|
|
this.setMaintaining({
|
|
|
|
status: 'command_end',
|
|
|
|
command: this.activatedCommand,
|
|
|
|
});
|
|
|
|
|
|
|
|
return command;
|
|
|
|
} catch (error) {
|
2023-09-21 10:03:39 +08:00
|
|
|
console.log({ error });
|
2023-09-01 16:11:27 +08:00
|
|
|
if (!this.activatedCommand) {
|
|
|
|
this.activatedCommand = {
|
|
|
|
name: 'unknown',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintaining({
|
|
|
|
status: 'command_error',
|
|
|
|
command: this.activatedCommand,
|
|
|
|
error,
|
|
|
|
});
|
2023-09-01 16:11:27 +08:00
|
|
|
|
|
|
|
if (options?.throwError) {
|
|
|
|
throw error;
|
|
|
|
}
|
2023-08-24 17:47:45 +08:00
|
|
|
} finally {
|
2023-09-12 22:39:23 +08:00
|
|
|
const _actionCommand = this._actionCommand;
|
|
|
|
if (_actionCommand) {
|
2023-09-14 06:24:30 +08:00
|
|
|
const options = _actionCommand['options'];
|
2023-09-12 22:39:23 +08:00
|
|
|
_actionCommand['_optionValues'] = {};
|
|
|
|
_actionCommand['_optionValueSources'] = {};
|
2023-09-14 06:24:30 +08:00
|
|
|
_actionCommand['options'] = [];
|
|
|
|
for (const option of options) {
|
|
|
|
_actionCommand.addOption(option);
|
|
|
|
}
|
2023-09-12 22:39:23 +08:00
|
|
|
}
|
|
|
|
this._actionCommand = null;
|
2023-09-21 10:03:39 +08:00
|
|
|
this.activatedCommand = null;
|
2023-08-24 17:47:45 +08:00
|
|
|
}
|
2022-01-30 11:11:36 +08:00
|
|
|
}
|
|
|
|
|
2022-05-13 11:18:36 +08:00
|
|
|
async start(options: StartOptions = {}) {
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this._started) {
|
|
|
|
return;
|
2021-12-06 21:23:34 +08:00
|
|
|
}
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this._started = true;
|
|
|
|
|
|
|
|
if (options.checkInstall && !(await this.isInstalled())) {
|
|
|
|
throw new ApplicationNotInstall(
|
|
|
|
`Application ${this.name} is not installed, Please run 'yarn nocobase install' command first`,
|
|
|
|
);
|
2022-11-04 15:38:08 +08:00
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('starting app...');
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this.db.closed()) {
|
|
|
|
await this.db.reconnect();
|
|
|
|
}
|
2023-03-10 19:16:00 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('emit beforeStart');
|
|
|
|
await this.emitAsync('beforeStart', this, options);
|
2022-05-13 11:20:30 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('emit afterStart');
|
|
|
|
await this.emitAsync('afterStart', this, options);
|
2023-09-25 15:26:52 +08:00
|
|
|
await this.emitStartedEvent(options);
|
2023-09-12 22:39:23 +08:00
|
|
|
|
|
|
|
this.stopped = false;
|
|
|
|
}
|
|
|
|
|
2023-09-25 15:26:52 +08:00
|
|
|
async emitStartedEvent(options: StartOptions = {}) {
|
2023-09-01 16:11:27 +08:00
|
|
|
await this.emitAsync('__started', this, {
|
|
|
|
maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus),
|
2023-09-25 15:26:52 +08:00
|
|
|
options,
|
2023-09-01 16:11:27 +08:00
|
|
|
});
|
2023-08-24 17:47:45 +08:00
|
|
|
}
|
2022-10-27 13:00:16 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
async isStarted() {
|
|
|
|
return this._started;
|
|
|
|
}
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2023-09-25 15:26:52 +08:00
|
|
|
async tryReloadOrRestart(options: StartOptions = {}) {
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this._started) {
|
2023-09-25 15:26:52 +08:00
|
|
|
await this.restart(options);
|
2023-08-24 17:47:45 +08:00
|
|
|
} else {
|
2023-09-25 15:26:52 +08:00
|
|
|
await this.reload(options);
|
2021-12-06 21:23:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
async restart(options: StartOptions = {}) {
|
|
|
|
if (!this._started) {
|
|
|
|
return;
|
|
|
|
}
|
2023-09-12 22:39:23 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this._started = false;
|
2023-09-12 22:39:23 +08:00
|
|
|
await this.emitAsync('beforeStop');
|
2023-08-24 17:47:45 +08:00
|
|
|
await this.reload(options);
|
|
|
|
await this.start(options);
|
|
|
|
this.emit('__restarted', this, options);
|
2022-03-28 22:01:10 +08:00
|
|
|
}
|
|
|
|
|
2022-05-13 11:18:36 +08:00
|
|
|
async stop(options: any = {}) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('stop app...', { method: 'stop' });
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('stopping app...');
|
2023-10-25 08:41:38 +08:00
|
|
|
|
2023-03-06 21:19:49 +08:00
|
|
|
if (this.stopped) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.warn(`Application ${this.name} already stopped`, { method: 'stop' });
|
2023-03-06 21:19:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-02-07 01:14:00 +08:00
|
|
|
await this.emitAsync('beforeStop', this, options);
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2022-03-28 22:01:10 +08:00
|
|
|
try {
|
|
|
|
// close database connection
|
|
|
|
// silent if database already closed
|
2022-10-27 13:00:16 +08:00
|
|
|
if (!this.db.closed()) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.info(`close db`, { method: 'stop' });
|
2022-10-27 13:00:16 +08:00
|
|
|
await this.db.close();
|
|
|
|
}
|
2022-03-28 22:01:10 +08:00
|
|
|
} catch (e) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.error(e.message, { method: 'stop', err: e.stack });
|
2022-03-28 22:01:10 +08:00
|
|
|
}
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2023-12-12 23:02:09 +08:00
|
|
|
if (this._cacheManager) {
|
|
|
|
await this._cacheManager.close();
|
|
|
|
}
|
|
|
|
|
2022-02-07 01:14:00 +08:00
|
|
|
await this.emitAsync('afterStop', this, options);
|
2023-09-12 22:39:23 +08:00
|
|
|
|
2023-03-06 21:19:49 +08:00
|
|
|
this.stopped = true;
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.info(`${this.name} is stopped`, { method: 'stop' });
|
2023-08-24 17:47:45 +08:00
|
|
|
this._started = false;
|
2020-12-18 19:54:53 +08:00
|
|
|
}
|
|
|
|
|
2022-05-13 11:18:36 +08:00
|
|
|
async destroy(options: any = {}) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('start destroy app', { method: 'destory' });
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('destroying app...');
|
2022-02-07 01:14:00 +08:00
|
|
|
await this.emitAsync('beforeDestroy', this, options);
|
|
|
|
await this.stop(options);
|
2023-08-24 17:47:45 +08:00
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('emit afterDestroy', { method: 'destory' });
|
2022-02-07 01:14:00 +08:00
|
|
|
await this.emitAsync('afterDestroy', this, options);
|
2023-08-24 17:47:45 +08:00
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('finish destroy app', { method: 'destory' });
|
2022-01-30 11:11:36 +08:00
|
|
|
}
|
|
|
|
|
2022-12-05 22:19:22 +08:00
|
|
|
async isInstalled() {
|
|
|
|
return (
|
|
|
|
(await this.db.collectionExistsInDb('applicationVersion')) || (await this.db.collectionExistsInDb('collections'))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-11-12 21:32:50 +08:00
|
|
|
async install(options: InstallOptions = {}) {
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('installing app...');
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('Database dialect: ' + this.db.sequelize.getDialect(), { method: 'install' });
|
2022-11-04 00:32:25 +08:00
|
|
|
|
|
|
|
if (options?.clean || options?.sync?.force) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('truncate database', { method: 'install' });
|
2022-11-04 00:32:25 +08:00
|
|
|
await this.db.clean({ drop: true });
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('app reloading', { method: 'install' });
|
2023-08-24 17:47:45 +08:00
|
|
|
await this.reload();
|
|
|
|
} else if (await this.isInstalled()) {
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.warn('app is installed', { method: 'install' });
|
2023-08-24 17:47:45 +08:00
|
|
|
return;
|
2022-01-30 11:11:36 +08:00
|
|
|
}
|
2022-02-28 21:49:50 +08:00
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('emit beforeInstall', { method: 'install' });
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('call beforeInstall hook...');
|
2022-09-18 14:10:01 +08:00
|
|
|
await this.emitAsync('beforeInstall', this, options);
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('start install plugins', { method: 'install' });
|
2022-02-28 21:49:50 +08:00
|
|
|
await this.pm.install(options);
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('update version', { method: 'install' });
|
2022-06-17 10:25:59 +08:00
|
|
|
await this.version.update();
|
2023-12-27 13:56:13 +08:00
|
|
|
this.log.debug('emit afterInstall', { method: 'install' });
|
2023-08-24 17:47:45 +08:00
|
|
|
this.setMaintainingMessage('call afterInstall hook...');
|
2022-01-30 11:11:36 +08:00
|
|
|
await this.emitAsync('afterInstall', this, options);
|
2023-08-24 17:47:45 +08:00
|
|
|
|
|
|
|
if (this._maintainingStatusBeforeCommand?.error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._started) {
|
|
|
|
await this.restart();
|
|
|
|
}
|
2021-09-09 13:05:33 +08:00
|
|
|
}
|
2022-01-30 11:11:36 +08:00
|
|
|
|
2022-06-17 10:25:59 +08:00
|
|
|
async upgrade(options: any = {}) {
|
2022-07-10 00:41:36 +08:00
|
|
|
await this.emitAsync('beforeUpgrade', this, options);
|
2022-06-17 10:25:59 +08:00
|
|
|
const force = false;
|
2023-10-11 19:15:59 +08:00
|
|
|
|
|
|
|
await measureExecutionTime(async () => {
|
|
|
|
await this.db.migrator.up();
|
|
|
|
}, 'Migrator');
|
|
|
|
|
|
|
|
await measureExecutionTime(async () => {
|
|
|
|
await this.db.sync({
|
|
|
|
force,
|
|
|
|
alter: {
|
|
|
|
drop: force,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}, 'Sync');
|
|
|
|
|
2022-06-17 10:25:59 +08:00
|
|
|
await this.version.update();
|
2022-07-10 00:41:36 +08:00
|
|
|
await this.emitAsync('afterUpgrade', this, options);
|
2023-10-11 19:15:59 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
this.log.debug(chalk.green(`✨ NocoBase has been upgraded to v${this.getVersion()}`));
|
2023-10-11 19:15:59 +08:00
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this._started) {
|
2023-10-11 19:15:59 +08:00
|
|
|
await measureExecutionTime(async () => {
|
|
|
|
await this.restart();
|
|
|
|
}, 'Restart');
|
2023-08-24 17:47:45 +08:00
|
|
|
}
|
2022-06-17 10:25:59 +08:00
|
|
|
}
|
|
|
|
|
2023-02-14 15:30:58 +08:00
|
|
|
toJSON() {
|
|
|
|
return {
|
|
|
|
appName: this.name,
|
2023-08-24 17:47:45 +08:00
|
|
|
name: this.name,
|
2023-02-14 15:30:58 +08:00
|
|
|
};
|
|
|
|
}
|
2023-08-24 17:47:45 +08:00
|
|
|
|
|
|
|
reInitEvents() {
|
|
|
|
for (const eventName of this.eventNames()) {
|
|
|
|
for (const listener of this.listeners(eventName)) {
|
|
|
|
if (listener['_reinitializable']) {
|
|
|
|
this.removeListener(eventName, listener as any);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
createLogger(options: LoggerOptions) {
|
|
|
|
const { dirname } = options;
|
|
|
|
return createLogger({
|
|
|
|
...options,
|
|
|
|
dirname: getLoggerFilePath(this.name || 'main', dirname || ''),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
protected init() {
|
|
|
|
const options = this.options;
|
|
|
|
|
2023-12-27 13:56:13 +08:00
|
|
|
this._logger = createAppLogger({
|
|
|
|
app: this.name,
|
|
|
|
...(options.logger?.system || {}),
|
|
|
|
}).child({
|
|
|
|
reqId: this.context.reqId,
|
|
|
|
module: 'application',
|
2023-08-24 17:47:45 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
this.reInitEvents();
|
|
|
|
|
|
|
|
this.middleware = new Toposort<any>();
|
|
|
|
this.plugins = new Map<string, Plugin>();
|
|
|
|
this._acl = createACL();
|
|
|
|
|
2023-09-27 19:31:14 +08:00
|
|
|
this._cronJobManager = new CronJobManager(this);
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
if (this._db) {
|
|
|
|
// MaxListenersExceededWarning
|
|
|
|
this._db.removeAllListeners();
|
|
|
|
}
|
|
|
|
|
|
|
|
this._db = this.createDatabase(options);
|
|
|
|
|
|
|
|
this._resourcer = createResourcer(options);
|
|
|
|
this._cli = this.createCli();
|
|
|
|
this._i18n = createI18n(options);
|
|
|
|
this.context.db = this._db;
|
2023-12-27 13:56:13 +08:00
|
|
|
// this.context.logger = this._logger;
|
2023-08-24 17:47:45 +08:00
|
|
|
this.context.resourcer = this._resourcer;
|
2023-11-20 17:14:20 +08:00
|
|
|
this.context.cacheManager = this._cacheManager;
|
2023-08-24 17:47:45 +08:00
|
|
|
this.context.cache = this._cache;
|
|
|
|
|
|
|
|
const plugins = this._pm ? this._pm.options.plugins : options.plugins;
|
|
|
|
|
|
|
|
this._pm = new PluginManager({
|
|
|
|
app: this,
|
|
|
|
plugins: plugins || [],
|
|
|
|
});
|
|
|
|
|
|
|
|
this._authManager = new AuthManager({
|
|
|
|
authKey: 'X-Authenticator',
|
|
|
|
default: 'basic',
|
2023-10-23 15:41:35 +08:00
|
|
|
...(this.options.authManager || {}),
|
2023-08-24 17:47:45 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
this.resource({
|
|
|
|
name: 'auth',
|
|
|
|
actions: authActions,
|
|
|
|
});
|
|
|
|
|
|
|
|
this._resourcer.use(this._authManager.middleware(), { tag: 'auth' });
|
|
|
|
|
|
|
|
if (this.options.acl !== false) {
|
|
|
|
this._resourcer.use(this._acl.middleware(), { tag: 'acl', after: ['auth'] });
|
|
|
|
}
|
|
|
|
|
|
|
|
this._locales = new Locale(createAppProxy(this));
|
|
|
|
|
2023-12-12 23:02:09 +08:00
|
|
|
if (options.perfHooks) {
|
|
|
|
enablePerfHooks(this);
|
|
|
|
}
|
|
|
|
|
2023-08-24 17:47:45 +08:00
|
|
|
registerMiddlewares(this, options);
|
|
|
|
|
|
|
|
if (options.registerActions !== false) {
|
|
|
|
registerActions(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
registerCli(this);
|
|
|
|
|
|
|
|
this._version = new ApplicationVersion(this);
|
|
|
|
}
|
|
|
|
|
2023-10-17 22:22:45 +08:00
|
|
|
protected createDatabase(options: ApplicationOptions) {
|
2023-12-27 13:56:13 +08:00
|
|
|
const sqlLogger = this.createLogger({
|
|
|
|
filename: 'sql',
|
|
|
|
level: 'debug',
|
|
|
|
});
|
|
|
|
const logging = (msg: any) => {
|
|
|
|
if (typeof msg === 'string') {
|
|
|
|
msg = msg.replace(/[\r\n]/gm, '').replace(/\s+/g, ' ');
|
|
|
|
}
|
|
|
|
if (msg.includes('INSERT INTO')) {
|
|
|
|
msg = msg.substring(0, 2000) + '...';
|
|
|
|
}
|
|
|
|
sqlLogger.debug({ reqId: this.context.reqId, message: msg });
|
|
|
|
};
|
|
|
|
const dbOptions = options.database instanceof Database ? options.database.options : options.database;
|
2023-08-24 17:47:45 +08:00
|
|
|
const db = new Database({
|
2023-12-27 13:56:13 +08:00
|
|
|
...dbOptions,
|
|
|
|
logging: dbOptions.logging ? logging : false,
|
2023-08-24 17:47:45 +08:00
|
|
|
migrator: {
|
|
|
|
context: { app: this },
|
|
|
|
},
|
2023-12-27 13:56:13 +08:00
|
|
|
logger: this._logger.child({ module: 'database' }),
|
2023-08-24 17:47:45 +08:00
|
|
|
});
|
|
|
|
return db;
|
|
|
|
}
|
2020-11-11 18:16:18 +08:00
|
|
|
}
|
|
|
|
|
2022-01-30 11:11:36 +08:00
|
|
|
applyMixins(Application, [AsyncEmitter]);
|
|
|
|
|
2020-11-11 18:16:18 +08:00
|
|
|
export default Application;
|