Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/core/dbs/SessionsDb.ts
1028 views
1
import * as Database from 'better-sqlite3';
2
import { Database as SqliteDatabase } from 'better-sqlite3';
3
import SessionsTable from '../models/SessionsTable';
4
import DetachedJsPathCallsTable from '../models/DetachedJsPathCallsTable';
5
6
interface IDbOptions {
7
readonly?: boolean;
8
fileMustExist?: boolean;
9
}
10
11
export default class SessionsDb {
12
private static dbByBaseDir: { [dir: string]: SessionsDb } = {};
13
public readonly sessions: SessionsTable;
14
public readonly detachedJsPathCalls: DetachedJsPathCallsTable;
15
public readonly readonly: boolean;
16
private readonly baseDir: string;
17
private db: SqliteDatabase;
18
19
constructor(baseDir: string, dbOptions: IDbOptions = {}) {
20
const { readonly = false, fileMustExist = false } = dbOptions;
21
this.db = new Database(`${baseDir}/sessions.db`, { readonly, fileMustExist });
22
this.baseDir = baseDir;
23
this.readonly = readonly;
24
this.sessions = new SessionsTable(this.db);
25
this.detachedJsPathCalls = new DetachedJsPathCallsTable(this.db);
26
}
27
28
public findLatestSessionId(script: {
29
sessionName: string;
30
scriptInstanceId: string;
31
scriptEntrypoint?: string;
32
}) {
33
const { sessionName, scriptEntrypoint, scriptInstanceId } = script;
34
if (sessionName && scriptInstanceId) {
35
// find default session if current not available
36
const sessionRecord =
37
this.sessions.findByName(sessionName, scriptInstanceId) ??
38
this.sessions.findByName('default-session', scriptInstanceId);
39
return sessionRecord?.id;
40
}
41
if (scriptEntrypoint) {
42
const sessionRecords = this.sessions.findByScriptEntrypoint(scriptEntrypoint);
43
if (!sessionRecords.length) return undefined;
44
return sessionRecords[0].id;
45
}
46
}
47
48
public findRelatedSessions(session: { scriptEntrypoint: string; scriptInstanceId: string }) {
49
const otherSessions = this.sessions.findByScriptEntrypoint(session.scriptEntrypoint);
50
const relatedScriptInstances: {
51
id: string;
52
startDate: number;
53
defaultSessionId: string;
54
}[] = [];
55
const relatedSessions: { id: string; name: string }[] = [];
56
const scriptDates = new Set<string>();
57
for (const otherSession of otherSessions) {
58
const key = `${otherSession.scriptInstanceId}_${otherSession.scriptStartDate}`;
59
if (!scriptDates.has(key)) {
60
relatedScriptInstances.push({
61
id: otherSession.scriptInstanceId,
62
startDate: new Date(otherSession.scriptStartDate).getTime(),
63
defaultSessionId: otherSession.id,
64
});
65
}
66
if (otherSession.scriptInstanceId === session.scriptInstanceId) {
67
relatedSessions.unshift({ id: otherSession.id, name: otherSession.name });
68
}
69
scriptDates.add(key);
70
}
71
return {
72
relatedSessions,
73
relatedScriptInstances,
74
};
75
}
76
77
public close() {
78
if (this.db) {
79
this.db.close();
80
}
81
this.db = null;
82
delete SessionsDb.dbByBaseDir[this.baseDir];
83
}
84
85
public static shutdown() {
86
for (const [key, db] of Object.entries(SessionsDb.dbByBaseDir)) {
87
db.close();
88
delete SessionsDb.dbByBaseDir[key];
89
}
90
}
91
92
public static find(baseDir: string) {
93
if (!this.dbByBaseDir[baseDir]) {
94
this.dbByBaseDir[baseDir] = new SessionsDb(baseDir);
95
}
96
return this.dbByBaseDir[baseDir];
97
}
98
}
99
100