tunnel/source/server/db.ts

100 lines
2.2 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
export type AccessMode = 'private' | 'public';
export interface TunnelConfig
{
id: string;
name: string;
description: string;
purpose: string;
ownerId: string;
access: AccessMode;
allowedUserIds: string[];
localPort: number;
createdAt: string;
}
const DB_PATH = path.join( __dirname, '..', '..', '..', 'build', 'data', 'db', 'tunnels.json' );
function ensureDir(): void
{
fs.mkdirSync( path.dirname( DB_PATH ), { recursive: true } );
}
function readAll(): TunnelConfig[]
{
try
{
return JSON.parse( fs.readFileSync( DB_PATH, 'utf-8' ) );
}
catch
{
return [];
}
}
function writeAll( tunnels: TunnelConfig[] ): void
{
ensureDir();
fs.writeFileSync( DB_PATH, JSON.stringify( tunnels, null, 2 ) );
}
export function createTunnel( data: Omit<TunnelConfig, 'id' | 'createdAt'> ): TunnelConfig
{
const tunnel: TunnelConfig = {
...data,
id: crypto.randomUUID(),
createdAt: new Date().toISOString(),
};
const all = readAll();
all.push( tunnel );
writeAll( all );
return tunnel;
}
export function getTunnel( id: string ): TunnelConfig | undefined
{
return readAll().find( t => t.id === id );
}
export function getTunnelsByOwner( ownerId: string ): TunnelConfig[]
{
return readAll().filter( t => t.ownerId === ownerId );
}
export function getAvailableTunnels( userId: string, purpose?: string ): TunnelConfig[]
{
let tunnels = readAll().filter( t =>
t.ownerId === userId ||
t.access === 'public' ||
t.allowedUserIds.includes( userId )
);
if ( purpose ) tunnels = tunnels.filter( t => t.purpose === purpose );
return tunnels;
}
export function updateTunnel(
id: string,
patch: Partial<Pick<TunnelConfig, 'name' | 'description' | 'access' | 'allowedUserIds' | 'purpose'>>
): TunnelConfig | undefined
{
const all = readAll();
const idx = all.findIndex( t => t.id === id );
if ( idx === -1 ) return undefined;
all[ idx ] = { ...all[ idx ], ...patch };
writeAll( all );
return all[ idx ];
}
export function deleteTunnel( id: string ): boolean
{
const all = readAll();
const filtered = all.filter( t => t.id !== id );
if ( filtered.length === all.length ) return false;
writeAll( filtered );
return true;
}