Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/sync-client/lib/index.ts
Views: 687
/*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));59this.synctable_project = this.sync_client.synctable_project.bind(60this.sync_client,61);62}6364client_id = () => {65return this._client_id;66};6768// [ ] TODO: is this something we should worry about? Probably yes.69is_deleted = (_filename: string, _project_id: string) => {70return false;71};7273set_deleted = async (_filename: string, _project_id?: string) => {74// TODO -- implement in fs aware clients75};7677mark_file = async (_opts: any) => {78// [ ] TODO: should we?79};8081is_project = () => {82return this.role == "project";83};8485is_browser = () => {86return this.role == "browser";87};8889is_compute_server = () => {90return this.role == "compute_server";91};9293dbg = (str: string) => {94return debug(`cocalc:sync:client.${str}`);95};9697query = (opts) => {98this.dbg("query")(opts);99if (typeof opts?.query != "object") {100throw Error("opts.query must be specified");101}102let project_id = this.project_id;103for (const table in opts.query) {104if (opts.query[table].project_id) {105project_id = opts.query[table].project_id;106break;107}108if (opts.query[table][0]?.project_id) {109project_id = opts.query[table][0]?.project_id;110break;111}112}113if (!project_id) {114throw Error(115"query involving an explicit project_id or clients with project_id set are supported",116);117}118(async () => {119try {120const api = await this.project_client.api(project_id);121const result = await api.query(opts);122opts.cb?.(undefined, result);123} catch (err) {124opts.cb?.(`${err}`);125}126})();127};128129query_cancel = () => {130console.log("query_cancel");131};132133server_time = () => {134return new Date();135};136137is_connected = () => {138return true;139};140141is_signed_in = () => {142return true;143};144145private _touchProject = reuseInFlight(async (project_id: string) => {146const dbg = this.dbg("sync-client:_touchProject");147dbg(project_id);148try {149await project.touch({ project_id });150} catch (err) {151dbg("error ", err);152}153});154155touch_project = (project_id: string) => {156this._touchProject(project_id);157};158}159160161