@mieweb/wikigdrive
Version:
Google Drive to MarkDown synchronization
141 lines (114 loc) • 3.51 kB
text/typescript
import process from 'node:process';
import type {QueueObject} from 'async';
import casual from 'casual';
import winston from 'winston';
import {FileContentService} from './utils/FileContentService.ts';
import {QueueTask} from './containers/google_folder/QueueTask.ts';
import {FileId} from './model/model.ts';
export interface ContainerConfig {
name?: string;
[key: string]: string;
}
export interface ContainerConfigArr {
[key: string]: string[];
}
type EventCallback = (driveId: FileId, payload) => void;
export class Container {
protected engine: ContainerEngine;
protected filesService: FileContentService;
constructor(public readonly params: ContainerConfig, public readonly paramsArr: ContainerConfigArr = {}) {
if (!this.params.name) {
this.params.name = casual.array_of_words(2).join('_');
}
}
async mount(fileService: FileContentService) {
this.filesService = fileService;
}
async init(engine: ContainerEngine): Promise<void> {
this.engine = engine;
}
async run(command) {
switch (command) {
case 'scan':
break;
}
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async destroy(): Promise<void> {
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async flushData() {
}
getQueue(): QueueObject<QueueTask> {
return null;
}
}
export class ContainerError extends Error {
constructor(msg) {
super(msg);
}
}
export class ContainerEngine {
constructor(public readonly logger: winston.Logger, public readonly rootFileService: FileContentService) {
process.on('SIGINT', async () => {
console.log('SIGINT');
await this.flushData();
process.exit();
});
}
private readonly containers: { [name: string]: Container } = {};
private listeners: {
[eventName: string]: Set<EventCallback>;
} = {};
async registerContainer(container: Container): Promise<Container> {
if (this.containers[container.params.name]) {
throw new ContainerError(`Container already exists: ${container.params.name}`);
}
try {
await container.init(this);
this.containers[container.params.name] = container;
} catch (err) {
this.logger.error(`Error starting container ${container.params.name} ${err.stack ? err.stack : err.message}`, err);
}
return container;
}
async unregisterContainer(name: string): Promise<void> {
const container = this.containers[name];
if (!container) {
throw new ContainerError(`No such container: ${name}`);
}
await container.destroy();
delete this.containers[container.params.name];
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async run() {
}
getContainer(name: string) {
if (!this.containers[name]) {
throw new Error(`Unknown container: ${name}`);
}
return this.containers[name];
}
hasContainer(name: string) {
return !!this.containers[name];
}
async flushData() {
for (const container of Object.values(this.containers)) {
await container.flushData();
}
}
emit(driveId: FileId, eventName: string, payload) {
if (!this.listeners[eventName]) {
return;
}
for (const listener of this.listeners[eventName]) {
listener(driveId, payload);
}
}
subscribe(eventName: string, callback: EventCallback) {
if (!this.listeners[eventName]) {
this.listeners[eventName] = new Set();
}
this.listeners[eventName].add(callback);
}
}