import { callback } from "awaiting" ; import { SyncTable } from "@cocalc/sync/table" ; import { is_array } from "@cocalc/util/misc" ; const open_synctables = { } ; const wait_for = { } ; export function key ( query ) { const table = Object . keys ( query ) [ 0 ] ; if ( ! table ) { throw Error ( "no table in query" ) ; } let c = query [ table ] ; if ( c == null ) { throw Error ( "invalid query format" ) ; } if ( is_array ( c ) ) { c = c [ 0 ] ; } const string_id = c . string_id ; if ( string_id == null ) { throw Error ( "open-syncstring-tables is only for queries with a specified string_id field" + "(patches, cursors, eval_inputs, eval_outputs, etc.): query=" + JSON . stringify ( query ) ) ; } return `${ table }.${ string_id }` ; } export function register_synctable ( query , synctable ) { const k = key ( query ) ; open_synctables [ k ] = synctable ; synctable . on ( "closed" , function ( ) { delete open_synctables [ k ] ; } ) ; if ( wait_for [ k ] != null ) { handle_wait_for ( k , synctable ) ; } } export async function get_synctable ( query , client ) { const k = key ( query ) ; const log = client . dbg ( `get_synctable(key=${ k })` ) ; log ( "open_synctables = " , Object . keys ( open_synctables ) ) ; log ( "key=" , k , "query=" , query ) ; const s = open_synctables [ k ] ; if ( s != null ) { log ( "done" ) ; return s ; } function f ( cb ) { log ( "f got called" ) ; add_to_wait_for ( k , cb ) ; } log ( "waiting..." ) ; const synctable = await callback ( f ) ; log ( `got the synctable! ${ JSON . stringify ( ( synctable as any ) . query ) }` ) ; return synctable ; } function add_to_wait_for ( k , cb ) { if ( wait_for [ k ] == null ) { wait_for [ k ] = [ cb ] ; } else { wait_for [ k ] . push ( cb ) ; } } function handle_wait_for ( k , synctable ) { if ( wait_for [ k ] == null ) { return ; } const v = wait_for [ k ] ; delete wait_for [ k ] ; for ( const cb of v ) { cb ( undefined , synctable ) ; } }