Path: blob/master/src/packages/sync-client/lib/index.ts
1503 views
/*1This is specifically meant for connecting to one project.23Example use:45~/cocalc/src/packages/sync-client$ PROJECT_PORT=33177 DEBUG='cocalc:sync*' node6...78> c = new (require('.').default)(); s = c.sync_client.sync_db({project_id:'97ce5a7c-25c1-4059-8670-c7de96a0db92',path:'b.tasks',primary_keys:["task_id"], string_cols:['desc']})910> s.set({task_id:'cf163fb4-b198-4664-b32b-82ce4ec71701',desc:"fubar"})11> await s.save()12> s.to_str()13'{"desc":"fubar","last_edited":1684420716277,"position":0,"task_id":"cf163fb4-b198-4664-b32b-82ce4ec71701"}'14> s.set({task_id:'cf163fb4-b198-4664-b32b-82ce4ec71701',desc:"figure it out"})15undefined16> await s.save()17undefined18> s.to_str()19'{"desc":"figure it out","last_edited":1684420716277,"position":0,"task_id":"cf163fb4-b198-4664-b32b-82ce4ec71701"}'20*/2122import { EventEmitter } from "events";23import type { AppClient } from "@cocalc/sync/client/types";24import { SyncClient } from "@cocalc/sync/client/sync-client";25import ProjectClient from "./project-client";26import debug from "debug";27import { bind_methods, isValidUUID, uuid } from "@cocalc/util/misc";28import { project } from "@cocalc/api-client";29import { reuseInFlight } from "@cocalc/util/reuse-in-flight";3031export type Role = "project" | "browser" | "compute_server";3233interface Options {34project_id: string;35client_id?: string;36role: Role;37}3839export default class Client extends EventEmitter implements AppClient {40project_client: ProjectClient;41sync_client: SyncClient;42synctable_project: Function;43project_id: string;44_client_id: string;45private role: Role;4647constructor({ project_id, client_id = uuid(), role }: Options) {48super();49this._client_id = client_id;50this.project_id = project_id;51this.role = role;5253if (!isValidUUID(project_id)) {54throw Error("project_id must be a valid uuid");55}5657this.project_client = bind_methods(new ProjectClient());58this.sync_client = bind_methods(new SyncClient(this));59}6061client_id = () => {62return this._client_id;63};6465// [ ] TODO: is this something we should worry about? Probably yes.66is_deleted = (_filename: string, _project_id: string) => {67return false;68};6970set_deleted = async (_filename: string, _project_id?: string) => {71// TODO -- implement in fs aware clients72};7374mark_file = async (_opts: any) => {75// [ ] TODO: should we?76};7778is_project = () => {79return this.role == "project";80};8182is_browser = () => {83return this.role == "browser";84};8586is_compute_server = () => {87return this.role == "compute_server";88};8990dbg = (str: string) => {91return debug(`cocalc:sync:client.${str}`);92};9394query = (opts) => {95this.dbg("query")(opts);96if (typeof opts?.query != "object") {97throw Error("opts.query must be specified");98}99let project_id = this.project_id;100for (const table in opts.query) {101if (opts.query[table].project_id) {102project_id = opts.query[table].project_id;103break;104}105if (opts.query[table][0]?.project_id) {106project_id = opts.query[table][0]?.project_id;107break;108}109}110if (!project_id) {111throw Error(112"query involving an explicit project_id or clients with project_id set are supported",113);114}115(async () => {116try {117const api = await this.project_client.api(project_id);118const result = await api.query(opts);119opts.cb?.(undefined, result);120} catch (err) {121opts.cb?.(`${err}`);122}123})();124};125126query_cancel = () => {127console.log("query_cancel");128};129130server_time = () => {131return new Date();132};133134is_connected = () => {135return true;136};137138is_signed_in = () => {139return true;140};141142private _touchProject = reuseInFlight(async (project_id: string) => {143const dbg = this.dbg("sync-client:_touchProject");144dbg(project_id);145try {146await project.touch({ project_id });147} catch (err) {148dbg("error ", err);149}150});151152touch_project = (project_id: string, _compute_server_id?: number) => {153this._touchProject(project_id);154};155}156157158