feat: add initial API

This commit is contained in:
Morten Olsen
2025-10-16 20:54:31 +02:00
parent 5cf0a3612a
commit 11828da073
17 changed files with 647 additions and 89 deletions

View File

@@ -1,6 +1,15 @@
import tcp from 'node:net';
import type { IncomingMessage } from 'node:http';
import swagger from '@fastify/swagger';
import type { ZodTypeProvider } from 'fastify-type-provider-zod';
import {
jsonSchemaTransform,
createJsonSchemaTransform,
serializerCompiler,
validatorCompiler,
} from 'fastify-type-provider-zod';
import scalar from '@scalar/fastify-api-reference';
import {
type AuthenticateHandler,
type AuthorizeForwardHandler,
@@ -19,6 +28,8 @@ import { TopicsHandler } from '#root/topics/topics.handler.ts';
import type { Services } from '#root/utils/services.ts';
import { Session } from '#root/services/sessions/sessions.session.ts';
import { SessionProvider } from '#root/services/sessions/sessions.provider.ts';
import fastifySensible from '@fastify/sensible';
import { Config } from '#root/config/config.ts';
type Aedes = ReturnType<typeof aedes.createBroker>;
@@ -52,6 +63,10 @@ class MqttServer {
});
}
public get bus() {
return this.#server;
}
#authenticate: AuthenticateHandler = async (client, username, password, callback) => {
try {
if (!username || !password) {
@@ -112,14 +127,51 @@ class MqttServer {
#setupHttpServer = async () => {
const http = fastify({});
await http.register(fastifyWebSocket);
http.get('/ws', { websocket: true }, (socket, req) => {
const stream = createWebSocketStream(socket);
this.#server.handle(stream, req as unknown as IncomingMessage);
});
await http.register(api, {
prefix: '/api',
});
const config = this.#services.get(Config);
if (config.api.enabled) {
http.decorate('services', this.#services);
http.setValidatorCompiler(validatorCompiler);
http.setSerializerCompiler(serializerCompiler);
await http.register(fastifyWebSocket);
await http.register(fastifySensible);
await http.register(swagger, {
openapi: {
info: {
title: 'Backbone',
version: '1.0.0',
},
components: {
securitySchemes: {
authProviderHeader: {
type: 'apiKey',
name: 'X-Auth-Provider',
in: 'header',
},
bearerAuth: {
type: 'http',
scheme: 'bearer',
},
},
},
security: [{ bearerAuth: [], authProviderHeader: [] }],
},
transform: jsonSchemaTransform,
});
await http.register(scalar, {
routePrefix: '/docs',
});
await http.register(api, {
prefix: '/api',
});
}
if (config.ws.enabled) {
http.get('/ws', { websocket: true }, (socket, req) => {
const stream = createWebSocketStream(socket);
this.#server.handle(stream, req as unknown as IncomingMessage);
});
}
await http.ready();
http.swagger();
return http;
};