2022-03-28 14:01:10 +00:00
|
|
|
import Database, { IDatabaseOptions, Model, TransactionAble } from '@nocobase/database';
|
|
|
|
import { Application } from '@nocobase/server';
|
|
|
|
import lodash from 'lodash';
|
|
|
|
import * as path from 'path';
|
|
|
|
|
2022-04-29 12:00:50 +00:00
|
|
|
export interface registerAppOptions extends TransactionAble {
|
2022-03-28 14:01:10 +00:00
|
|
|
skipInstall?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class ApplicationModel extends Model {
|
|
|
|
static getDatabaseConfig(app: Application): IDatabaseOptions {
|
|
|
|
return lodash.cloneDeep(
|
|
|
|
lodash.isPlainObject(app.options.database)
|
|
|
|
? (app.options.database as IDatabaseOptions)
|
|
|
|
: (app.options.database as Database).options,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-29 12:00:50 +00:00
|
|
|
static async handleAppStart(app: Application, options: registerAppOptions) {
|
|
|
|
await app.load();
|
|
|
|
|
|
|
|
if (!lodash.get(options, 'skipInstall', false)) {
|
|
|
|
await app.install();
|
|
|
|
}
|
|
|
|
|
|
|
|
await app.start();
|
|
|
|
}
|
|
|
|
|
2022-03-28 14:01:10 +00:00
|
|
|
async registerToMainApp(mainApp: Application, options: registerAppOptions) {
|
|
|
|
const appName = this.get('name') as string;
|
2022-04-24 12:22:50 +00:00
|
|
|
const appOptions = (this.get('options') as any) || {};
|
2022-03-28 14:01:10 +00:00
|
|
|
|
2022-04-30 15:41:01 +00:00
|
|
|
const AppModel = this.constructor as typeof ApplicationModel;
|
|
|
|
|
2022-04-24 12:22:50 +00:00
|
|
|
const app = mainApp.appManager.createApplication(appName, {
|
2022-04-30 15:41:01 +00:00
|
|
|
...AppModel.initOptions(appName, mainApp),
|
2022-04-24 12:22:50 +00:00
|
|
|
...appOptions,
|
|
|
|
});
|
2022-03-28 14:01:10 +00:00
|
|
|
|
2022-04-29 12:00:50 +00:00
|
|
|
// create database before installation if it not exists
|
2022-03-28 14:01:10 +00:00
|
|
|
app.on('beforeInstall', async function createDatabase() {
|
2022-04-30 15:41:01 +00:00
|
|
|
const { host, port, username, password, database, dialect } = AppModel.getDatabaseConfig(app);
|
2022-03-28 14:01:10 +00:00
|
|
|
|
|
|
|
if (dialect === 'mysql') {
|
|
|
|
const mysql = require('mysql2/promise');
|
|
|
|
const connection = await mysql.createConnection({ host, port, user: username, password });
|
|
|
|
await connection.query(`CREATE DATABASE IF NOT EXISTS \`${database}\`;`);
|
|
|
|
await connection.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dialect === 'postgres') {
|
|
|
|
const { Client } = require('pg');
|
|
|
|
|
|
|
|
const client = new Client({
|
|
|
|
user: username,
|
|
|
|
host,
|
|
|
|
password: password,
|
|
|
|
port,
|
|
|
|
});
|
|
|
|
|
|
|
|
await client.connect();
|
|
|
|
|
|
|
|
try {
|
|
|
|
await client.query(`CREATE DATABASE "${database}"`);
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
|
|
await client.end();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-04-30 15:41:01 +00:00
|
|
|
await AppModel.handleAppStart(app, options);
|
|
|
|
|
|
|
|
await AppModel.update(
|
|
|
|
{
|
|
|
|
status: 'running',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
transaction: options.transaction,
|
|
|
|
where: {
|
|
|
|
[AppModel.primaryKeyAttribute]: this.get(AppModel.primaryKeyAttribute),
|
|
|
|
},
|
|
|
|
hooks: false,
|
|
|
|
},
|
|
|
|
);
|
2022-03-28 14:01:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static initOptions(appName: string, mainApp: Application) {
|
2022-04-30 15:41:01 +00:00
|
|
|
const rawDatabaseOptions = this.getDatabaseConfig(mainApp);
|
2022-03-28 14:01:10 +00:00
|
|
|
|
|
|
|
if (rawDatabaseOptions.dialect === 'sqlite') {
|
|
|
|
const mainAppStorage = rawDatabaseOptions.storage;
|
|
|
|
if (mainAppStorage !== ':memory:') {
|
|
|
|
const mainStorageDir = path.dirname(mainAppStorage);
|
|
|
|
rawDatabaseOptions.storage = path.join(mainStorageDir, `${appName}.sqlite`);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
rawDatabaseOptions.database = appName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
database: rawDatabaseOptions,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|