CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/sync/table/synctable-no-database.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
/*
7
Make a SyncTable which does not use a changefeed or the central
8
database at all.
9
10
The initial read waits on the client calling a function to provide
11
the initial data, and all changes are also injected by explicitly
12
calling a function. An event is emitted when a new change is made
13
that has to get saved.
14
15
This is used to implement the browser side of project specific
16
SyncTables. It's also obviously useful for unit testing.
17
*/
18
19
import { EventEmitter } from "events";
20
import { SyncTable, Client } from "./synctable";
21
import { bind_methods, keys } from "@cocalc/util/misc";
22
23
export function synctable_no_database(
24
query,
25
options,
26
client: Client,
27
throttle_changes: undefined | number = undefined,
28
initial_get_query: any[] = [],
29
project_id?: string,
30
): SyncTable {
31
if (options == null) {
32
options = [];
33
}
34
const client2 = new ClientNoDatabase(client, initial_get_query);
35
return new SyncTable(
36
query,
37
options,
38
client2,
39
throttle_changes,
40
true,
41
true,
42
project_id,
43
);
44
}
45
46
class ClientNoDatabase extends EventEmitter {
47
private client: Client;
48
private initial_get_query: any[];
49
private connected: boolean = true;
50
51
constructor(client, initial_get_query) {
52
super();
53
54
this.initial_get_query = initial_get_query;
55
bind_methods(this, ["query", "dbg", "query_cancel"]);
56
this.client = client;
57
}
58
59
public set_connected(connected: boolean): void {
60
const event = connected && this.connected != connected;
61
this.connected = connected;
62
if (event) {
63
this.emit("signed_in");
64
this.emit("connected");
65
}
66
}
67
68
public is_project(): boolean {
69
return this.client.is_project();
70
}
71
72
public is_browser(): boolean {
73
return this.client.is_browser();
74
}
75
76
public is_compute_server(): boolean {
77
return this.client.is_compute_server();
78
}
79
80
public async touch_project(project_id: string): Promise<void> {
81
await this.client.touch_project(project_id);
82
}
83
84
public is_connected(): boolean {
85
return this.connected;
86
}
87
88
public is_signed_in(): boolean {
89
return this.connected;
90
}
91
92
public server_time(): Date {
93
return this.client.server_time();
94
}
95
96
public dbg(s: string): Function {
97
return this.client.dbg(s);
98
}
99
100
public query(opts): void {
101
if (opts.options && opts.options.length === 1 && opts.options[0].set) {
102
if (this.connected) {
103
// set query -- totally ignore.
104
opts.cb();
105
} else {
106
opts.cb("disconnected");
107
}
108
} else {
109
// get query -- returns predetermined result (default: empty)
110
const table = keys(opts.query)[0];
111
opts.cb(undefined, { query: { [table]: this.initial_get_query } });
112
}
113
}
114
115
public query_cancel(_): void {}
116
117
public alert_message(opts): void {
118
if (this.client.alert_message != null) {
119
this.client.alert_message(opts);
120
}
121
}
122
123
is_deleted = (_path: string, _project_id: string) => {
124
// not implemented yet in general
125
return undefined;
126
};
127
}
128
129