mirror of
https://github.com/morten-olsen/mini-loader.git
synced 2026-02-08 01:36:26 +01:00
qa: add e2e tests
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import 'source-map-support/register.js';
|
||||
import '../dist/esm/index.js';
|
||||
import '../dist/esm/bin.js';
|
||||
|
||||
@@ -41,9 +41,11 @@
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"knex": "^3.1.0",
|
||||
"nanoid": "^5.0.4",
|
||||
"reflect-metadata": "^0.2.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"sqlite3": "^5.1.7",
|
||||
"superjson": "^2.2.1",
|
||||
"typedi": "^0.10.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"homepage": "https://github.com/morten-olsen/mini-loader",
|
||||
|
||||
@@ -4,17 +4,21 @@ import { existsSync } from 'fs';
|
||||
import { mkdir, readFile, writeFile } from 'fs/promises';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { Config } from '../config/config.js';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
|
||||
type AuthOptions = {
|
||||
config: Config;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class Auth {
|
||||
#options: AuthOptions;
|
||||
#data: Promise<{ secret: string }>;
|
||||
|
||||
constructor(options: AuthOptions) {
|
||||
this.#options = options;
|
||||
constructor(container: ContainerInstance) {
|
||||
this.#options = {
|
||||
config: container.get(Config),
|
||||
};
|
||||
this.#data = this.#setup();
|
||||
}
|
||||
|
||||
|
||||
14
packages/server/src/bin.ts
Normal file
14
packages/server/src/bin.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { ContainerInstance } from 'typedi';
|
||||
import { createServerCli } from './index.js';
|
||||
|
||||
const program = createServerCli(new ContainerInstance('server'));
|
||||
|
||||
program.setOptionValue('output', (data: unknown) => {
|
||||
console.log('got data', data);
|
||||
});
|
||||
|
||||
await program.parseAsync(process.argv);
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
@@ -1,10 +1,22 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Service } from 'typedi';
|
||||
import envPaths from 'env-paths';
|
||||
import { join } from 'path';
|
||||
|
||||
type Config = {
|
||||
database: Omit<Knex.Config, 'migrations'>;
|
||||
files: {
|
||||
data: string;
|
||||
cache: string;
|
||||
const paths = envPaths('mini-loader-server');
|
||||
|
||||
@Service()
|
||||
class Config {
|
||||
database: Omit<Knex.Config, 'migrations'> = {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: join(paths.data, 'db.sqlite'),
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
};
|
||||
files = {
|
||||
data: paths.data,
|
||||
cache: paths.cache,
|
||||
};
|
||||
auth?: {
|
||||
oidc?: {
|
||||
@@ -15,6 +27,6 @@ type Config = {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type { Config };
|
||||
export { Config };
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import knex, { Knex } from 'knex';
|
||||
import { Service, ContainerInstance } from 'typedi';
|
||||
|
||||
import { Config } from '../config/config.js';
|
||||
import { source } from './migrations/migrations.source.js';
|
||||
import { mkdir } from 'fs/promises';
|
||||
import { dirname } from 'path';
|
||||
@@ -8,13 +10,15 @@ const tableNames = {
|
||||
loads: 'loads',
|
||||
};
|
||||
|
||||
@Service()
|
||||
class Database {
|
||||
#instance?: Promise<Knex>;
|
||||
#config: Knex.Config;
|
||||
|
||||
constructor(config: Knex.Config) {
|
||||
constructor(container: ContainerInstance) {
|
||||
const config = container.get(Config);
|
||||
this.#config = {
|
||||
...config,
|
||||
...config.database,
|
||||
migrations: {
|
||||
migrationSource: source,
|
||||
},
|
||||
|
||||
9
packages/server/src/id/id.ts
Normal file
9
packages/server/src/id/id.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
import { Service } from 'typedi';
|
||||
|
||||
@Service()
|
||||
class IdGenerator {
|
||||
public generate = () => nanoid();
|
||||
}
|
||||
|
||||
export { IdGenerator };
|
||||
@@ -1,40 +1,42 @@
|
||||
import { program, Command } from 'commander';
|
||||
import 'reflect-metadata';
|
||||
import { Command } from 'commander';
|
||||
import { Runtime } from './runtime/runtime.js';
|
||||
import { createServer } from './server/server.js';
|
||||
import { ContainerInstance } from 'typedi';
|
||||
|
||||
const start = new Command('start');
|
||||
start.action(async () => {
|
||||
const port = 4500;
|
||||
const runtime = await Runtime.create();
|
||||
await runtime.scheduler.start();
|
||||
const server = await createServer(runtime);
|
||||
await server.listen({
|
||||
port,
|
||||
host: '0.0.0.0',
|
||||
const createServerCli = (container: ContainerInstance) => {
|
||||
const program = new Command();
|
||||
|
||||
const start = new Command('start');
|
||||
start.action(async () => {
|
||||
const port = 4500;
|
||||
const runtime = container.get(Runtime);
|
||||
await runtime.scheduler.start();
|
||||
const server = await createServer(container);
|
||||
await server.listen({
|
||||
port,
|
||||
host: '0.0.0.0',
|
||||
});
|
||||
|
||||
console.log(`Server listening on port ${port}`);
|
||||
});
|
||||
|
||||
console.log(`Server listening on port ${port}`);
|
||||
});
|
||||
|
||||
const createToken = new Command('create-token');
|
||||
createToken.action(async () => {
|
||||
const runtime = await Runtime.create();
|
||||
const token = await runtime.auth.createToken({
|
||||
policy: {
|
||||
'*:*': ['*'],
|
||||
},
|
||||
const createToken = new Command('create-token');
|
||||
createToken.action(async () => {
|
||||
const runtime = container.get(Runtime);
|
||||
const token = await runtime.auth.createToken({
|
||||
policy: {
|
||||
'*:*': ['*'],
|
||||
},
|
||||
});
|
||||
console.log(token);
|
||||
});
|
||||
console.log(token);
|
||||
});
|
||||
|
||||
program.addCommand(start);
|
||||
program.addCommand(createToken);
|
||||
program.addCommand(start);
|
||||
program.addCommand(createToken);
|
||||
return program;
|
||||
};
|
||||
|
||||
await program.parseAsync(process.argv);
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
export type { Runtime } from './runtime/runtime.js';
|
||||
export { createServerCli, createServer, Runtime };
|
||||
export { Config } from './config/config.js';
|
||||
export type { RootRouter } from './router/router.js';
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Database } from '../../database/database.js';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { AddArtifactOptions, FindArtifactsOptions } from './artifacts.schemas.js';
|
||||
import { createHash } from 'crypto';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { IdGenerator } from '../../id/id.js';
|
||||
|
||||
type ArtifactRepoEvents = {};
|
||||
|
||||
type ArtifactRepoOptions = {
|
||||
database: Database;
|
||||
idGenerator: IdGenerator;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class ArtifactRepo extends EventEmitter<ArtifactRepoEvents> {
|
||||
#options: ArtifactRepoOptions;
|
||||
|
||||
constructor(options: ArtifactRepoOptions) {
|
||||
constructor(container: ContainerInstance) {
|
||||
super();
|
||||
this.#options = options;
|
||||
this.#options = {
|
||||
database: container.get(Database),
|
||||
idGenerator: container.get(IdGenerator),
|
||||
};
|
||||
}
|
||||
|
||||
public get = async (id: string) => {
|
||||
@@ -26,9 +32,9 @@ class ArtifactRepo extends EventEmitter<ArtifactRepoEvents> {
|
||||
};
|
||||
|
||||
public add = async (options: AddArtifactOptions) => {
|
||||
const { database } = this.#options;
|
||||
const { database, idGenerator } = this.#options;
|
||||
const db = await database.instance;
|
||||
const id = nanoid();
|
||||
const id = idGenerator.generate();
|
||||
|
||||
await db('artifacts').insert({
|
||||
id,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Database } from '../../database/database.js';
|
||||
import { FindLoadsOptions, SetLoadOptions } from './loads.schemas.js';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { createHash } from 'crypto';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import { resolve } from 'path';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { IdGenerator } from '../../id/id.js';
|
||||
|
||||
type LoadRepoEvents = {
|
||||
created: (id: string) => void;
|
||||
@@ -16,14 +17,20 @@ type LoadRepoEvents = {
|
||||
type LoadRepoOptions = {
|
||||
database: Database;
|
||||
config: Config;
|
||||
idGenerator: IdGenerator;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class LoadRepo extends EventEmitter<LoadRepoEvents> {
|
||||
#options: LoadRepoOptions;
|
||||
|
||||
constructor(options: LoadRepoOptions) {
|
||||
constructor(container: ContainerInstance) {
|
||||
super();
|
||||
this.#options = options;
|
||||
this.#options = {
|
||||
database: container.get(Database),
|
||||
config: container.get(Config),
|
||||
idGenerator: container.get(IdGenerator),
|
||||
};
|
||||
}
|
||||
|
||||
public getById = async (id: string) => {
|
||||
@@ -58,9 +65,9 @@ class LoadRepo extends EventEmitter<LoadRepoEvents> {
|
||||
};
|
||||
|
||||
public set = async (options: SetLoadOptions) => {
|
||||
const { database } = this.#options;
|
||||
const { database, idGenerator } = this.#options;
|
||||
const db = await database.instance;
|
||||
const id = options.id || nanoid();
|
||||
const id = options.id || idGenerator.generate();
|
||||
const script = createHash('sha256').update(options.script).digest('hex');
|
||||
const scriptDir = resolve(this.#options.config.files.data, 'scripts');
|
||||
await mkdir(scriptDir, { recursive: true });
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Database } from '../../database/database.js';
|
||||
import { AddLogOptions, FindLogsOptions } from './logs.schemas.js';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { createHash } from 'crypto';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { IdGenerator } from '../../id/id.js';
|
||||
|
||||
type LogRepoEvents = {};
|
||||
|
||||
type LogRepoOptions = {
|
||||
database: Database;
|
||||
idGenerator: IdGenerator;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class LogRepo extends EventEmitter<LogRepoEvents> {
|
||||
#options: LogRepoOptions;
|
||||
|
||||
constructor(options: LogRepoOptions) {
|
||||
constructor(container: ContainerInstance) {
|
||||
super();
|
||||
this.#options = options;
|
||||
this.#options = {
|
||||
database: container.get(Database),
|
||||
idGenerator: container.get(IdGenerator),
|
||||
};
|
||||
}
|
||||
|
||||
public add = async (options: AddLogOptions) => {
|
||||
const { database } = this.#options;
|
||||
const { database, idGenerator } = this.#options;
|
||||
const db = await database.instance;
|
||||
const id = nanoid();
|
||||
const id = idGenerator.generate();
|
||||
|
||||
await db('logs').insert({
|
||||
id,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Config } from '../config/config.js';
|
||||
import { Database } from '../database/database.js';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { ArtifactRepo } from './artifacts/artifacts.js';
|
||||
import { LoadRepo } from './loads/loads.js';
|
||||
import { LogRepo } from './logs/logs.js';
|
||||
@@ -7,64 +6,36 @@ import { RunRepo } from './runs/runs.js';
|
||||
import { ScheduleRepo } from './schedules/schedules.js';
|
||||
import { SecretRepo } from './secrets/secrets.js';
|
||||
|
||||
type ReposOptions = {
|
||||
database: Database;
|
||||
config: Config;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class Repos {
|
||||
#loads: LoadRepo;
|
||||
#runs: RunRepo;
|
||||
#logs: LogRepo;
|
||||
#artifacts: ArtifactRepo;
|
||||
#secrets: SecretRepo;
|
||||
#schedule: ScheduleRepo;
|
||||
#container: ContainerInstance;
|
||||
|
||||
constructor({ database, config }: ReposOptions) {
|
||||
this.#loads = new LoadRepo({
|
||||
database,
|
||||
config,
|
||||
});
|
||||
this.#runs = new RunRepo({
|
||||
database,
|
||||
loads: this.#loads,
|
||||
});
|
||||
this.#logs = new LogRepo({
|
||||
database,
|
||||
});
|
||||
this.#artifacts = new ArtifactRepo({
|
||||
database,
|
||||
});
|
||||
this.#secrets = new SecretRepo({
|
||||
database,
|
||||
});
|
||||
this.#schedule = new ScheduleRepo({
|
||||
database,
|
||||
});
|
||||
constructor(container: ContainerInstance) {
|
||||
this.#container = container;
|
||||
}
|
||||
|
||||
public get loads() {
|
||||
return this.#loads;
|
||||
return this.#container.get(LoadRepo);
|
||||
}
|
||||
|
||||
public get runs() {
|
||||
return this.#runs;
|
||||
return this.#container.get(RunRepo);
|
||||
}
|
||||
|
||||
public get logs() {
|
||||
return this.#logs;
|
||||
return this.#container.get(LogRepo);
|
||||
}
|
||||
|
||||
public get artifacts() {
|
||||
return this.#artifacts;
|
||||
return this.#container.get(ArtifactRepo);
|
||||
}
|
||||
|
||||
public get secrets() {
|
||||
return this.#secrets;
|
||||
return this.#container.get(SecretRepo);
|
||||
}
|
||||
|
||||
public get schedules() {
|
||||
return this.#schedule;
|
||||
return this.#container.get(ScheduleRepo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Database } from '../../database/database.js';
|
||||
import { CreateRunOptions, FindRunsOptions, UpdateRunOptions } from './runs.schemas.js';
|
||||
import { LoadRepo } from '../loads/loads.js';
|
||||
import { createHash } from 'crypto';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { IdGenerator } from '../../id/id.js';
|
||||
|
||||
type RunRepoEvents = {
|
||||
created: (args: { id: string; loadId: string }) => void;
|
||||
@@ -15,16 +16,21 @@ type RunRepoEvents = {
|
||||
type RunRepoOptions = {
|
||||
database: Database;
|
||||
loads: LoadRepo;
|
||||
idGenerator: IdGenerator;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class RunRepo extends EventEmitter<RunRepoEvents> {
|
||||
#options: RunRepoOptions;
|
||||
#isReady: Promise<void>;
|
||||
#isSetup?: Promise<void>;
|
||||
|
||||
constructor(options: RunRepoOptions) {
|
||||
constructor(container: ContainerInstance) {
|
||||
super();
|
||||
this.#options = options;
|
||||
this.#isReady = this.#setup();
|
||||
this.#options = {
|
||||
database: container.get(Database),
|
||||
loads: container.get(LoadRepo),
|
||||
idGenerator: container.get(IdGenerator),
|
||||
};
|
||||
}
|
||||
|
||||
#setup = async () => {
|
||||
@@ -33,6 +39,13 @@ class RunRepo extends EventEmitter<RunRepoEvents> {
|
||||
await db('runs').update({ status: 'failed', error: 'server was shut down' }).where({ status: 'running' });
|
||||
};
|
||||
|
||||
get #isReady() {
|
||||
if (!this.#isSetup) {
|
||||
this.#isSetup = this.#setup();
|
||||
}
|
||||
return this.#isSetup;
|
||||
}
|
||||
|
||||
public getById = async (id: string) => {
|
||||
await this.#isReady;
|
||||
const { database } = this.#options;
|
||||
@@ -150,8 +163,8 @@ class RunRepo extends EventEmitter<RunRepoEvents> {
|
||||
|
||||
public create = async (options: CreateRunOptions) => {
|
||||
await this.#isReady;
|
||||
const { database, loads } = this.#options;
|
||||
const id = nanoid();
|
||||
const { database, loads, idGenerator } = this.#options;
|
||||
const id = idGenerator.generate();
|
||||
const db = await database.instance;
|
||||
|
||||
const script = await loads.getScript(options.loadId);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Database } from '../../database/database.js';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { AddScheduleOptions, FindSchedulesOptions } from './schedules.schemas.js';
|
||||
import { createHash } from 'crypto';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { IdGenerator } from '../../id/id.js';
|
||||
|
||||
type ScheduleRepoEvents = {
|
||||
added: (id: string) => void;
|
||||
@@ -11,14 +12,19 @@ type ScheduleRepoEvents = {
|
||||
|
||||
type ScheduleRepoOptions = {
|
||||
database: Database;
|
||||
idGenerator: IdGenerator;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class ScheduleRepo extends EventEmitter<ScheduleRepoEvents> {
|
||||
#options: ScheduleRepoOptions;
|
||||
|
||||
constructor(options: ScheduleRepoOptions) {
|
||||
constructor(container: ContainerInstance) {
|
||||
super();
|
||||
this.#options = options;
|
||||
this.#options = {
|
||||
database: container.get(Database),
|
||||
idGenerator: container.get(IdGenerator),
|
||||
};
|
||||
}
|
||||
|
||||
public get = async (id: string) => {
|
||||
@@ -29,9 +35,9 @@ class ScheduleRepo extends EventEmitter<ScheduleRepoEvents> {
|
||||
};
|
||||
|
||||
public add = async (options: AddScheduleOptions) => {
|
||||
const { database } = this.#options;
|
||||
const { database, idGenerator } = this.#options;
|
||||
const db = await database.instance;
|
||||
const id = nanoid();
|
||||
const id = idGenerator.generate();
|
||||
|
||||
await db('schedules').insert({
|
||||
id,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Database } from '../../database/database.js';
|
||||
import { FindSecretOptions, SetSecretOptions } from './secrets.schemas.js';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
|
||||
type LogRepoEvents = {};
|
||||
|
||||
@@ -8,12 +9,15 @@ type LogRepoOptions = {
|
||||
database: Database;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class SecretRepo extends EventEmitter<LogRepoEvents> {
|
||||
#options: LogRepoOptions;
|
||||
|
||||
constructor(options: LogRepoOptions) {
|
||||
constructor(container: ContainerInstance) {
|
||||
super();
|
||||
this.#options = options;
|
||||
this.#options = {
|
||||
database: container.get(Database),
|
||||
};
|
||||
}
|
||||
|
||||
public set = async (options: SetSecretOptions) => {
|
||||
|
||||
@@ -2,13 +2,15 @@ import { initTRPC } from '@trpc/server';
|
||||
import { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';
|
||||
import superjson from 'superjson';
|
||||
import { Runtime } from '../runtime/runtime.js';
|
||||
import { ContainerInstance } from 'typedi';
|
||||
|
||||
type ContextOptions = {
|
||||
runtime: Runtime;
|
||||
container: ContainerInstance;
|
||||
};
|
||||
|
||||
const createContext = async ({ runtime }: ContextOptions) => {
|
||||
const createContext = async ({ container }: ContextOptions) => {
|
||||
return async ({ req }: CreateFastifyContextOptions) => {
|
||||
const runtime = container.get(Runtime);
|
||||
const { authorization } = req.headers;
|
||||
const { auth } = runtime;
|
||||
if (!authorization) {
|
||||
@@ -18,6 +20,7 @@ const createContext = async ({ runtime }: ContextOptions) => {
|
||||
await auth.validateToken(token);
|
||||
return {
|
||||
runtime,
|
||||
container,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { Config } from '../config/config.js';
|
||||
import { Repos } from '../repos/repos.js';
|
||||
import { RunnerInstance } from './runner.instance.js';
|
||||
@@ -7,13 +8,17 @@ type RunnerOptions = {
|
||||
config: Config;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class Runner {
|
||||
#options: RunnerOptions;
|
||||
#instances: Map<string, RunnerInstance> = new Map();
|
||||
|
||||
constructor(options: RunnerOptions) {
|
||||
this.#options = options;
|
||||
const { repos } = options;
|
||||
constructor(container: ContainerInstance) {
|
||||
this.#options = {
|
||||
repos: container.get(Repos),
|
||||
config: container.get(Config),
|
||||
};
|
||||
const { repos } = this.#options;
|
||||
repos.runs.on('created', this.#start);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
import { resolve } from 'path';
|
||||
import envPaths from 'env-paths';
|
||||
import { Database } from '../database/database.js';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { Repos } from '../repos/repos.js';
|
||||
import { Runner } from '../runner/runner.js';
|
||||
import { Config } from '../config/config.js';
|
||||
import { Auth } from '../auth/auth.js';
|
||||
import { Scheduler } from '../scheduler/scheduler.js';
|
||||
|
||||
const paths = envPaths('mini-loader-server');
|
||||
|
||||
@Service()
|
||||
class Runtime {
|
||||
#repos: Repos;
|
||||
#runner: Runner;
|
||||
#auth: Auth;
|
||||
#scheduler: Scheduler;
|
||||
|
||||
constructor(options: Config) {
|
||||
const database = new Database(options.database);
|
||||
this.#repos = new Repos({ database, config: options });
|
||||
this.#runner = new Runner({ repos: this.#repos, config: options });
|
||||
this.#auth = new Auth({ config: options });
|
||||
this.#scheduler = new Scheduler({ runs: this.#repos.runs, schedules: this.#repos.schedules });
|
||||
constructor(container: ContainerInstance) {
|
||||
this.#repos = container.get(Repos);
|
||||
this.#runner = container.get(Runner);
|
||||
this.#auth = container.get(Auth);
|
||||
this.#scheduler = container.get(Scheduler);
|
||||
}
|
||||
|
||||
public get repos() {
|
||||
@@ -38,24 +33,6 @@ class Runtime {
|
||||
public get scheduler() {
|
||||
return this.#scheduler;
|
||||
}
|
||||
|
||||
public static create = async () => {
|
||||
const runtime = new Runtime({
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: resolve(paths.data, 'database.sqlite'),
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
},
|
||||
files: {
|
||||
data: process.env.DATA_DIR || resolve(paths.data, 'data', 'files'),
|
||||
cache: process.env.CACHE_DIR || resolve(paths.cache, 'data', 'cache'),
|
||||
},
|
||||
});
|
||||
|
||||
return runtime;
|
||||
};
|
||||
}
|
||||
|
||||
export { Runtime };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CronJob } from 'cron';
|
||||
import { ScheduleRepo } from '../repos/schedules/schedules.js';
|
||||
import { RunRepo } from '../repos/runs/runs.js';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
|
||||
type SchedulerOptions = {
|
||||
runs: RunRepo;
|
||||
@@ -13,12 +14,16 @@ type RunningSchedule = {
|
||||
stop: () => Promise<void>;
|
||||
};
|
||||
|
||||
@Service()
|
||||
class Scheduler {
|
||||
#running: RunningSchedule[] = [];
|
||||
#options: SchedulerOptions;
|
||||
|
||||
constructor(options: SchedulerOptions) {
|
||||
this.#options = options;
|
||||
constructor(container: ContainerInstance) {
|
||||
this.#options = {
|
||||
runs: container.get(RunRepo),
|
||||
schedules: container.get(ScheduleRepo),
|
||||
};
|
||||
const { schedules } = this.#options;
|
||||
schedules.on('added', this.#add);
|
||||
schedules.on('removed', this.#remove);
|
||||
|
||||
@@ -2,17 +2,12 @@ import { fastifyTRPCPlugin, FastifyTRPCPluginOptions } from '@trpc/server/adapte
|
||||
import fastify from 'fastify';
|
||||
import { RootRouter, rootRouter } from '../router/router.js';
|
||||
import { createContext } from '../router/router.utils.js';
|
||||
import { Runtime } from '../runtime/runtime.js';
|
||||
import { gateway } from '../gateway/gateway.js';
|
||||
import { createRequire } from 'module';
|
||||
import { readFile } from 'fs/promises';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const createServer = async (runtime: Runtime) => {
|
||||
const pkgLocation = require.resolve('#pkg');
|
||||
const pkg = JSON.parse(await readFile(pkgLocation, 'utf-8'));
|
||||
import { ContainerInstance } from 'typedi';
|
||||
import { Runtime } from '../runtime/runtime.js';
|
||||
|
||||
const createServer = async (container: ContainerInstance) => {
|
||||
const runtime = container.get(Runtime);
|
||||
const server = fastify({
|
||||
maxParamLength: 10000,
|
||||
bodyLimit: 30 * 1024 * 1024,
|
||||
@@ -31,14 +26,14 @@ const createServer = async (runtime: Runtime) => {
|
||||
authorized = true;
|
||||
}
|
||||
} catch (error) {}
|
||||
return { authorized, status: 'ok', version: pkg.version };
|
||||
return { authorized, status: 'ok' };
|
||||
});
|
||||
|
||||
server.register(fastifyTRPCPlugin, {
|
||||
prefix: '/trpc',
|
||||
trpcOptions: {
|
||||
router: rootRouter,
|
||||
createContext: await createContext({ runtime }),
|
||||
createContext: await createContext({ container }),
|
||||
onError({ error }) {
|
||||
console.error(error);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user