-
Notifications
You must be signed in to change notification settings - Fork 313
Expand file tree
/
Copy pathconfig.mts
More file actions
136 lines (121 loc) · 4.09 KB
/
config.mts
File metadata and controls
136 lines (121 loc) · 4.09 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { eq, and, inArray } from 'drizzle-orm';
import { type SecretWithAssociatedSessions, randomid } from '@srcbook/shared';
import { configs, type Config, secrets, type Secret, secretsToSession } from './db/schema.mjs';
import { db } from './db/index.mjs';
import { HOME_DIR } from './constants.mjs';
async function init() {
const existingConfig = await db.select().from(configs).limit(1);
if (existingConfig.length === 0) {
const defaultConfig = {
baseDir: HOME_DIR,
defaultLanguage: 'typescript',
autoInstallDependencies: true,
installId: randomid(),
aiConfig: { provider: 'openai', model: 'gpt-4o' } as const,
aiProvider: 'openai',
aiModel: 'gpt-4o',
};
console.log();
console.log('Initializing application with the following configuration:\n');
console.log(JSON.stringify(defaultConfig, null, 2));
console.log();
await db.insert(configs).values(defaultConfig).returning();
}
}
// Block rest of module until we have initialized config.
await init();
export async function getConfig(): Promise<Config> {
const results = await db.select().from(configs);
if (results.length !== 1) {
console.warn('Expected exactly one config record, found:', results.length);
}
if (results.length === 0) {
throw new Error('No config found');
}
// explicitly known that a config exists here
return results[0] as Config;
}
export async function updateConfig(attrs: Partial<Config>) {
return db.update(configs).set(attrs).returning();
}
export async function getSecrets(): Promise<Array<SecretWithAssociatedSessions>> {
const secretsResult = await db.select().from(secrets);
const secretsToSessionResult = await db
.select()
.from(secretsToSession)
.where(
inArray(
secretsToSession.secret_id,
secretsResult.map((secret) => secret.id),
),
);
return secretsResult.map((secret) => ({
name: secret.name,
value: secret.value,
associatedWithSessionIds: secretsToSessionResult
.filter((secretToSession) => secretToSession.secret_id === secret.id)
.map((secretToSession) => secretToSession.session_id),
}));
}
export async function getSecretsAssociatedWithSession(
sessionId: string,
): Promise<Record<string, string>> {
const secretsResults = await getSecrets();
return Object.fromEntries(
secretsResults
.filter((secret) => secret.associatedWithSessionIds.includes(sessionId))
.map((secret) => [secret.name, secret.value]),
);
}
export async function addSecret(name: string, value: string): Promise<Secret> {
const result = await db
.insert(secrets)
.values({ name, value })
.onConflictDoUpdate({ target: secrets.name, set: { value } })
.returning();
if (result.length === 0) {
throw new Error('No secret returned');
}
// explicitly known that a config exists here
return result[0] as Secret;
}
export async function removeSecret(name: string) {
await db.delete(secrets).where(eq(secrets.name, name)).returning();
}
export async function associateSecretWithSession(secretName: string, sessionId: string) {
const result = await db
.select({ id: secrets.id })
.from(secrets)
.where(eq(secrets.name, secretName))
.limit(1);
if (result.length < 1) {
throw new Error(
`Cannot associate '${secretName}' with ${sessionId}: cannot find secret with that name!`,
);
}
const secretId = result[0]!.id;
await db
.insert(secretsToSession)
.values({ secret_id: secretId, session_id: sessionId })
.onConflictDoNothing()
.returning();
}
export async function disassociateSecretWithSession(secretName: string, sessionId: string) {
const result = await db
.select({ id: secrets.id })
.from(secrets)
.where(eq(secrets.name, secretName))
.limit(1);
if (result.length < 1) {
throw new Error(
`Cannot associate '${secretName}' with ${sessionId}: cannot find secret with that name!`,
);
}
const secretId = result[0]!.id;
await db
.delete(secretsToSession)
.where(
and(eq(secretsToSession.secret_id, secretId), eq(secretsToSession.session_id, sessionId)),
)
.returning();
}