forked from CassiopeiaCode/q2api
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathdb.ts
More file actions
122 lines (101 loc) · 4.02 KB
/
db.ts
File metadata and controls
122 lines (101 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { Account, AccountCreate, AccountUpdate } from "./types.ts";
const kv = await Deno.openKv();
export async function getAccount(id: string): Promise<Account | null> {
const res = await kv.get<Account>(["accounts", id]);
return res.value;
}
export async function listAccounts(onlyEnabled: boolean = false): Promise<Account[]> {
const iter = kv.list<Account>({ prefix: ["accounts"] });
const accounts: Account[] = [];
for await (const res of iter) {
if (onlyEnabled) {
if (res.value.enabled) accounts.push(res.value);
} else {
accounts.push(res.value);
}
}
// Sort by created_at desc
return accounts.sort((a, b) => b.created_at.localeCompare(a.created_at));
}
function getTimestamp(): string {
return new Date().toISOString().slice(0, 19); // YYYY-MM-DDTHH:MM:SS in UTC
}
export async function createAccount(data: AccountCreate & { id?: string }): Promise<Account> {
const id = data.id || crypto.randomUUID();
const now = getTimestamp();
const account: Account = {
id,
label: data.label,
clientId: data.clientId,
clientSecret: data.clientSecret,
refreshToken: data.refreshToken,
accessToken: data.accessToken,
other: data.other ? JSON.stringify(data.other) : undefined,
last_refresh_time: undefined,
last_refresh_status: "never",
created_at: now,
updated_at: now,
enabled: data.enabled !== false, // Default true
error_count: 0,
success_count: 0
};
await kv.set(["accounts", id], account);
return account;
}
export async function updateAccount(id: string, data: AccountUpdate): Promise<Account | null> {
const current = await getAccount(id);
if (!current) return null;
const now = getTimestamp();
const updated: Account = { ...current, updated_at: now };
if (data.label !== undefined) updated.label = data.label;
if (data.clientId !== undefined) updated.clientId = data.clientId;
if (data.clientSecret !== undefined) updated.clientSecret = data.clientSecret;
if (data.refreshToken !== undefined) updated.refreshToken = data.refreshToken;
if (data.accessToken !== undefined) updated.accessToken = data.accessToken;
if (data.other !== undefined) updated.other = JSON.stringify(data.other);
if (data.enabled !== undefined) updated.enabled = data.enabled;
await kv.set(["accounts", id], updated);
return updated;
}
export async function deleteAccount(id: string): Promise<boolean> {
const current = await getAccount(id);
if (!current) return false;
await kv.delete(["accounts", id]);
return true;
}
export async function updateAccountTokens(id: string, accessToken: string, refreshToken: string | undefined, status: string): Promise<void> {
const current = await getAccount(id);
if (!current) return;
const now = getTimestamp();
current.accessToken = accessToken;
if (refreshToken) current.refreshToken = refreshToken;
current.last_refresh_time = now;
current.last_refresh_status = status;
current.updated_at = now;
await kv.set(["accounts", id], current);
}
export async function updateAccountStats(id: string, success: boolean, maxErrorCount: number = 100): Promise<void> {
const current = await getAccount(id);
if (!current) return;
const now = getTimestamp();
current.updated_at = now;
if (success) {
current.success_count += 1;
current.error_count = 0;
} else {
current.error_count += 1;
if (current.error_count >= maxErrorCount) {
current.enabled = false;
}
}
await kv.set(["accounts", id], current);
}
export async function updateAccountRefreshStatus(id: string, status: string): Promise<void> {
const current = await getAccount(id);
if (!current) return;
const now = getTimestamp();
current.last_refresh_time = now;
current.last_refresh_status = status;
current.updated_at = now;
await kv.set(["accounts", id], current);
}