feat(api): complete phase 2.4 control plane
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import type Database from 'better-sqlite3';
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import { buildApp, type BuildAppOptions } from './app.js';
|
||||
import {
|
||||
ConnectionProbe,
|
||||
type ConnectionTransport,
|
||||
} from './application/connections/connection-probe.js';
|
||||
import { InstanceCredentialResolver } from './application/connections/instance-credential-resolver.js';
|
||||
import { InstanceLoginService } from './application/connections/instance-login-service.js';
|
||||
import {
|
||||
InstanceSessionStore,
|
||||
UpstreamSessionClient,
|
||||
type UpstreamSessionClientOptions,
|
||||
} from './application/connections/upstream-session-client.js';
|
||||
import { InstanceService } from './application/instances/instance-service.js';
|
||||
import { DeleteInstanceOperation } from './application/operations/delete-instance-operation.js';
|
||||
import type { SecretStore } from './infrastructure/secrets/secret-store.js';
|
||||
import { registerInstanceRoutes } from './interface/http/instance-routes.js';
|
||||
|
||||
export interface SafeControlPlaneUpstream extends ConnectionTransport {
|
||||
request: UpstreamSessionClientOptions['request'];
|
||||
}
|
||||
export interface ControlPlaneOptions {
|
||||
readonly db: Database.Database;
|
||||
readonly store: SecretStore;
|
||||
readonly upstream: SafeControlPlaneUpstream;
|
||||
readonly now?: () => Date;
|
||||
readonly app?: Omit<BuildAppOptions, 'registerRoutes'>;
|
||||
}
|
||||
export interface ControlPlaneApp extends FastifyInstance {
|
||||
retryPendingSecretCleanup(): Promise<unknown>;
|
||||
}
|
||||
export function buildControlPlaneApp(options: ControlPlaneOptions): ControlPlaneApp {
|
||||
const instances = options.now
|
||||
? new InstanceService({ db: options.db, store: options.store, now: options.now })
|
||||
: new InstanceService({ db: options.db, store: options.store });
|
||||
const connections = options.now
|
||||
? new ConnectionProbe({
|
||||
db: options.db,
|
||||
instances,
|
||||
transport: options.upstream,
|
||||
now: options.now,
|
||||
})
|
||||
: new ConnectionProbe({ db: options.db, instances, transport: options.upstream });
|
||||
const sessions = new InstanceSessionStore();
|
||||
const client = new UpstreamSessionClient({ sessions, request: options.upstream.request });
|
||||
const resolver = new InstanceCredentialResolver({ db: options.db, store: options.store });
|
||||
const login = options.now
|
||||
? new InstanceLoginService({ db: options.db, client, resolver, now: options.now })
|
||||
: new InstanceLoginService({ db: options.db, client, resolver });
|
||||
const deletion = options.now
|
||||
? new DeleteInstanceOperation({ db: options.db, instances, now: options.now })
|
||||
: new DeleteInstanceOperation({ db: options.db, instances });
|
||||
deletion.reconcileInterruptedJobs();
|
||||
const app = buildApp({
|
||||
...options.app,
|
||||
registerRoutes: (app) =>
|
||||
registerInstanceRoutes(app, { instances, connections, login, deletion }),
|
||||
});
|
||||
Object.assign(app, {
|
||||
retryPendingSecretCleanup: () => instances.retryPendingSecretCleanup(),
|
||||
});
|
||||
return app as ControlPlaneApp;
|
||||
}
|
||||
Reference in New Issue
Block a user