import { isInstance , tagConstructor } from "@adpt/utils" ; import { CustomError } from "ts-custom-error" ; import { URL } from "url" ; import { HistoryStore } from "./history" ; export const $serverLock = Symbol . for ( "$serverLock" ) ; export interface ServerLock { [ $serverLock ] : true ; } export interface AdaptServer { init ( ) : Promise < void > ; destroy ( ) : Promise < void > ; set ( dataPath , val , options ? ) : Promise < void > ; get ( dataPath , options ? ) : Promise < any > ; delete ( dataPath , options ? ) : Promise < void > ; lock ( ) : Promise < ServerLock > ; unlock ( lock ) : Promise < void > ; historyStore ( dataPath , init ) : Promise < HistoryStore > ; } export interface OptionsWithLock { lock ? : ServerLock ; } export interface SetOptions extends OptionsWithLock { mustCreate ? : boolean ; } export interface GetOptions extends OptionsWithLock { } export interface DeleteOptions extends OptionsWithLock { } export interface ServerOptions { } export interface AdaptServerType { urlMatch : RegExp ; new ( url , options ) : AdaptServer ; } let serverTypes = [ ] ; export function mockServerTypes_ ( sTypes ? ) { const oldTypes = serverTypes ; if ( sTypes != null ) serverTypes = sTypes ; return oldTypes ; } export function register ( serverType ) { serverTypes . push ( serverType ) ; } export async function adaptServer ( url , options ) { let parsed ; try { parsed = new URL ( url ) ; } catch ( err ) { if ( err instanceof TypeError ) { throw new Error ( `Invalid Adapt server url '${ url }'` ) ; } throw err ; } for ( const sType of serverTypes ) { if ( sType . urlMatch . test ( url ) ) { const server = new sType ( parsed , options ) ; await server . init ( ) ; return server ; } } throw new Error ( `Adapt server url '${ url }' is not a supported url type.` ) ; } export async function withLock < T > ( server , f ) { const lock = await server . lock ( ) ; try { return await f ( lock ) ; } finally { await server . unlock ( lock ) ; } } export class ServerPathExists extends CustomError { public constructor ( public path ) { super ( `Server: path '${ path }' already exists` ) ; } } tagConstructor ( ServerPathExists , "adapt" ) ; export function isServerPathExists ( val ) { return isInstance ( val , ServerPathExists , "adapt" ) ; }