@mieweb/wikigdrive
Version:
Google Drive to MarkDown synchronization
195 lines (156 loc) • 6.25 kB
text/typescript
import process from 'node:process';
import {EventEmitter} from 'node:events';
import minimist from 'minimist';
import winston from 'winston';
import dotenv from 'dotenv';
import {addTelemetry} from '../telemetry.ts';
import type {CliParams} from '../model/CliParams.ts';
import {createLogger} from '../utils/logger/logger.ts';
import {ContainerEngine} from '../ContainerEngine.ts';
import {GoogleApiContainer} from '../containers/google_api/GoogleApiContainer.ts';
import {FileContentService} from '../utils/FileContentService.ts';
import type {AuthConfig} from '../model/AccountJson.ts';
import {loadRunningInstance} from '../containers/server/loadRunningInstance.ts';
import {FolderRegistryContainer} from '../containers/folder_registry/FolderRegistryContainer.ts';
import {JobManagerContainer} from '../containers/job/JobManagerContainer.ts';
import {WatchChangesContainer} from '../containers/changes/WatchChangesContainer.ts';
import {ServerContainer} from '../containers/server/ServerContainer.ts';
import {getAuthConfig} from './getAuthConfig.ts';
import {usage} from './usage.ts';
const __filename = import.meta.filename;
const __dirname = import.meta.dirname;
process.env.GIT_SHA = process.env.GIT_SHA || 'dev';
export class MainService {
private readonly eventBus: EventEmitter;
private readonly logger: winston.Logger;
private containerEngine: ContainerEngine;
private mainFileService: FileContentService;
private authConfig: AuthConfig;
constructor(private params: CliParams) {
this.eventBus = new EventEmitter();
this.eventBus.setMaxListeners(0);
if (params.debug.indexOf('main') > -1) {
this.attachDebug();
}
this.logger = createLogger(this.params.workdir, this.eventBus);
}
attachDebug() {
const eventNames = {};
this.eventBus.on('newListener', (event) => {
if (eventNames[event]) return;
eventNames[event] = event;
this.eventBus.on(event, () => {
this.logger.debug('OnEvent', event);
});
});
}
async init() {
this.mainFileService = new FileContentService(this.params.workdir || '/data');
await this.mainFileService.mkdir('/');
this.authConfig = await getAuthConfig(this.params, this.mainFileService);
if (this.params.share_email) {
this.authConfig.share_email = this.params.share_email;
}
this.containerEngine = new ContainerEngine(this.logger, this.mainFileService);
this.eventBus.on('panic:invalid_grant', () => {
// if (configService) {
// await configService.saveGoogleAuth(null);
// await configService.flushData();
// }
process.exit(1);
});
this.eventBus.on('panic', (error) => {
throw error;
/*
this.logger.error(error.stack ? error.stack : error.message);
console.error(error.message);
process.exit(1);
*/
});
}
async cmdServer() {
const instance = await loadRunningInstance();
if (instance) {
this.logger.error('WikiGDrive server already running, PID: ' + instance.pid);
process.exit(1);
}
if (!this.params.disable_google_watch) {
const changesContainer = new WatchChangesContainer({ name: 'watch_changes', share_email: this.params.share_email });
await changesContainer.mount(await this.mainFileService);
await this.containerEngine.registerContainer(changesContainer);
await changesContainer.run();
}
const port = parseInt(this.params.args[1]) || 3000;
const serverContainer = new ServerContainer({ name: 'server', share_email: this.params.share_email }, port);
await serverContainer.mount(await this.mainFileService);
await this.containerEngine.registerContainer(serverContainer);
await serverContainer.run();
const containerEnginePromise = this.containerEngine.run();
containerEnginePromise.then(() => {
});
await new Promise(resolve => {
this.eventBus.on('end', resolve);
});
}
async start() {
const apiContainer = new GoogleApiContainer({ name: 'google_api' }, this.authConfig);
await apiContainer.mount(await this.mainFileService);
await this.containerEngine.registerContainer(apiContainer);
await apiContainer.run();
const folderRegistryContainer = new FolderRegistryContainer({ name: 'folder_registry' });
await folderRegistryContainer.mount(await this.mainFileService);
await this.containerEngine.registerContainer(folderRegistryContainer);
await folderRegistryContainer.run();
const jobManagerContainer = new JobManagerContainer({ name: 'job_manager' });
await jobManagerContainer.mount(await this.mainFileService);
await this.containerEngine.registerContainer(jobManagerContainer);
await jobManagerContainer.run();
await this.cmdServer();
await this.containerEngine.flushData();
}
}
async function main() {
const argv = minimist(process.argv.slice(2));
if (argv._.length < 1 || argv.h || argv.help) {
await usage(__filename);
process.exit(0);
}
// PWD is null on Windows, so we can set it here
process.env.PWD = process.cwd();
const params: CliParams = {
args: argv._.slice(1),
// drive: argv['drive'],
workdir: argv['workdir'] || process.env.VOLUME_DATA || '/data',
client_id: argv['client_id'] || process.env.CLIENT_ID,
client_secret: argv['client_secret'] || process.env.CLIENT_SECRET,
// link_mode: argv['link_mode'] || 'mdURLs',
debug: (argv['debug'] || '').split(',').map(str => str.toLocaleString().trim()),
service_account: argv['service_account'] || null,
share_email: argv['share_email'] || process.env.SHARE_EMAIL || null,
server_port: +argv['server_port'],
disable_google_watch: !!argv['disable_google_watch']
};
const mainService = new MainService(params);
try {
await mainService.init();
} catch (err) {
await usage(__filename);
console.error(err);
process.exit(1);
}
return await mainService.start();
}
dotenv.config();
await addTelemetry(process.env.ZIPKIN_SERVICE || 'wikigdrive', __dirname);
try {
await main();
process.exit(0);
} catch (err) {
if (err.isUsageError) {
console.error(err.message);
await usage(__filename);
} else {
console.error(err);
}
process.exit(1);
}