Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/client/query.ts
1503 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { is_array } from "@cocalc/util/misc";
7
import { validate_client_query } from "@cocalc/util/schema-validate";
8
import { CB } from "@cocalc/util/types/database";
9
import { ConatChangefeed } from "@cocalc/sync/table/changefeed-conat";
10
import { uuid } from "@cocalc/util/misc";
11
12
declare const $: any; // jQuery
13
14
export class QueryClient {
15
private client: any;
16
private changefeeds: { [id: string]: ConatChangefeed } = {};
17
18
constructor(client: any) {
19
this.client = client;
20
}
21
22
// This works like a normal async function when
23
// opts.cb is NOT specified. When opts.cb is specified,
24
// it works like a cb and returns nothing. For changefeeds
25
// you MUST specify opts.cb, but can always optionally do so.
26
query = async (opts: {
27
query: object;
28
options?: object[]; // if given must be an array of objects, e.g., [{limit:5}]
29
changes?: boolean;
30
timeout?: number; // ms
31
cb?: CB; // support old cb interface
32
}): Promise<any> => {
33
// Deprecation warnings:
34
for (const field of ["standby", "no_post", "ignore_response"]) {
35
if (opts[field] != null) {
36
console.trace(`WARNING: passing '${field}' to query is deprecated`);
37
}
38
}
39
if (opts.options != null && !is_array(opts.options)) {
40
// should never happen...
41
throw Error("options must be an array");
42
}
43
if (opts.changes) {
44
const { cb } = opts;
45
if (cb == null) {
46
throw Error("for changefeed, must specify opts.cb");
47
}
48
let changefeed;
49
try {
50
changefeed = new ConatChangefeed({
51
account_id: this.client.account_id,
52
query: opts.query,
53
options: opts.options,
54
});
55
// id for canceling this changefeed
56
const id = uuid();
57
const initval = await changefeed.connect();
58
const query = {
59
[Object.keys(opts.query)[0]]: initval,
60
};
61
this.changefeeds[id] = changefeed;
62
cb(undefined, { query, id });
63
changefeed.on("update", (change) => {
64
cb(undefined, change);
65
});
66
} catch (err) {
67
cb(`${err}`);
68
return;
69
}
70
} else {
71
try {
72
const err = validate_client_query(opts.query, this.client.account_id);
73
if (err) {
74
throw Error(err);
75
}
76
const query = await this.client.conat_client.hub.db.userQuery({
77
query: opts.query,
78
options: opts.options,
79
timeout: opts.timeout,
80
});
81
82
if (opts.cb == null) {
83
return { query };
84
} else {
85
opts.cb(undefined, { query });
86
}
87
} catch (err) {
88
if (opts.cb == null) {
89
throw err;
90
} else {
91
opts.cb(err);
92
}
93
}
94
}
95
};
96
97
// cancel a changefeed created above. This is ONLY used
98
// right now by the CRM code.
99
cancel = async (id: string): Promise<void> => {
100
this.changefeeds[id]?.close();
101
delete this.changefeeds[id];
102
};
103
}
104
105