@sixb/sqlite 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/action-run-storage.d.ts +29 -0
- package/dist/action-run-storage.d.ts.map +1 -0
- package/dist/agents/agent-storage.d.ts +25 -0
- package/dist/agents/agent-storage.d.ts.map +1 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/messages.d.ts +14 -0
- package/dist/agents/messages.d.ts.map +1 -0
- package/dist/agents/rows.d.ts +77 -0
- package/dist/agents/rows.d.ts.map +1 -0
- package/dist/agents/runs.d.ts +26 -0
- package/dist/agents/runs.d.ts.map +1 -0
- package/dist/agents/threads.d.ts +14 -0
- package/dist/agents/threads.d.ts.map +1 -0
- package/dist/auth-storage/access-tokens.d.ts +33 -0
- package/dist/auth-storage/access-tokens.d.ts.map +1 -0
- package/dist/auth-storage/auth-storage.d.ts +46 -0
- package/dist/auth-storage/auth-storage.d.ts.map +1 -0
- package/dist/auth-storage/group-memberships.d.ts +21 -0
- package/dist/auth-storage/group-memberships.d.ts.map +1 -0
- package/dist/auth-storage/identities.d.ts +17 -0
- package/dist/auth-storage/identities.d.ts.map +1 -0
- package/dist/auth-storage/index.d.ts +3 -0
- package/dist/auth-storage/index.d.ts.map +1 -0
- package/dist/auth-storage/invitations.d.ts +28 -0
- package/dist/auth-storage/invitations.d.ts.map +1 -0
- package/dist/auth-storage/magic-links.d.ts +28 -0
- package/dist/auth-storage/magic-links.d.ts.map +1 -0
- package/dist/auth-storage/oidc-attempts.d.ts +18 -0
- package/dist/auth-storage/oidc-attempts.d.ts.map +1 -0
- package/dist/auth-storage/rows.d.ts +134 -0
- package/dist/auth-storage/rows.d.ts.map +1 -0
- package/dist/auth-storage/service-account-group-memberships.d.ts +17 -0
- package/dist/auth-storage/service-account-group-memberships.d.ts.map +1 -0
- package/dist/auth-storage/service-accounts.d.ts +14 -0
- package/dist/auth-storage/service-accounts.d.ts.map +1 -0
- package/dist/auth-storage/sessions.d.ts +55 -0
- package/dist/auth-storage/sessions.d.ts.map +1 -0
- package/dist/auth-storage/shared.d.ts +131 -0
- package/dist/auth-storage/shared.d.ts.map +1 -0
- package/dist/auth-storage/users.d.ts +19 -0
- package/dist/auth-storage/users.d.ts.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10204 -0
- package/dist/index.js.map +54 -0
- package/dist/latest-run-query.d.ts +22 -0
- package/dist/latest-run-query.d.ts.map +1 -0
- package/dist/migrations.d.ts +18 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/object-query-compiler.d.ts +44 -0
- package/dist/object-query-compiler.d.ts.map +1 -0
- package/dist/object-storage.d.ts +93 -0
- package/dist/object-storage.d.ts.map +1 -0
- package/dist/ontology-storage/commits.d.ts +14 -0
- package/dist/ontology-storage/commits.d.ts.map +1 -0
- package/dist/ontology-storage/index.d.ts +22 -0
- package/dist/ontology-storage/index.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-session.d.ts +49 -0
- package/dist/ontology-storage/materialization-session.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-state.d.ts +63 -0
- package/dist/ontology-storage/materialization-state.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-writer.d.ts +15 -0
- package/dist/ontology-storage/materialization-writer.d.ts.map +1 -0
- package/dist/ontology-storage/materializations.d.ts +32 -0
- package/dist/ontology-storage/materializations.d.ts.map +1 -0
- package/dist/ontology-storage/outbox.d.ts +14 -0
- package/dist/ontology-storage/outbox.d.ts.map +1 -0
- package/dist/ontology-storage/shared.d.ts +91 -0
- package/dist/ontology-storage/shared.d.ts.map +1 -0
- package/dist/ontology-storage/sources.d.ts +26 -0
- package/dist/ontology-storage/sources.d.ts.map +1 -0
- package/dist/pipeline-run-storage.d.ts +26 -0
- package/dist/pipeline-run-storage.d.ts.map +1 -0
- package/dist/projection-run-storage.d.ts +32 -0
- package/dist/projection-run-storage.d.ts.map +1 -0
- package/dist/rules-storage.d.ts +33 -0
- package/dist/rules-storage.d.ts.map +1 -0
- package/dist/run-list-query.d.ts +27 -0
- package/dist/run-list-query.d.ts.map +1 -0
- package/dist/storage-errors.d.ts +2 -0
- package/dist/storage-errors.d.ts.map +1 -0
- package/dist/sync-run-storage.d.ts +23 -0
- package/dist/sync-run-storage.d.ts.map +1 -0
- package/dist/timeseries-storage.d.ts +41 -0
- package/dist/timeseries-storage.d.ts.map +1 -0
- package/dist/transactions.d.ts +15 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/tsconfig.json +5 -0
- package/dist/validation.d.ts +5 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/webhook-delivery-storage.d.ts +27 -0
- package/dist/webhook-delivery-storage.d.ts.map +1 -0
- package/dist/webhook-run-storage.d.ts +22 -0
- package/dist/webhook-run-storage.d.ts.map +1 -0
- package/dist/workflow-intervention-storage.d.ts +26 -0
- package/dist/workflow-intervention-storage.d.ts.map +1 -0
- package/dist/workflow-run-storage.d.ts +63 -0
- package/dist/workflow-run-storage.d.ts.map +1 -0
- package/package.json +58 -0
- package/src/action-run-storage.ts +761 -0
- package/src/agents/agent-storage.ts +46 -0
- package/src/agents/index.ts +5 -0
- package/src/agents/messages.ts +162 -0
- package/src/agents/rows.ts +205 -0
- package/src/agents/runs.ts +389 -0
- package/src/agents/threads.ts +133 -0
- package/src/auth-storage/access-tokens.ts +289 -0
- package/src/auth-storage/auth-storage.ts +784 -0
- package/src/auth-storage/group-memberships.ts +52 -0
- package/src/auth-storage/identities.ts +98 -0
- package/src/auth-storage/index.ts +2 -0
- package/src/auth-storage/invitations.ts +258 -0
- package/src/auth-storage/magic-links.ts +149 -0
- package/src/auth-storage/oidc-attempts.ts +109 -0
- package/src/auth-storage/rows.ts +338 -0
- package/src/auth-storage/service-account-group-memberships.ts +161 -0
- package/src/auth-storage/service-accounts.ts +168 -0
- package/src/auth-storage/sessions.ts +230 -0
- package/src/auth-storage/shared.ts +707 -0
- package/src/auth-storage/users.ts +226 -0
- package/src/index.ts +292 -0
- package/src/latest-run-query.ts +49 -0
- package/src/migrations/001-initial-schema.sql +1068 -0
- package/src/migrations.ts +245 -0
- package/src/object-query-compiler.ts +1198 -0
- package/src/object-storage.ts +605 -0
- package/src/ontology-storage/commits.ts +127 -0
- package/src/ontology-storage/index.ts +35 -0
- package/src/ontology-storage/materialization-session.ts +393 -0
- package/src/ontology-storage/materialization-state.ts +901 -0
- package/src/ontology-storage/materialization-writer.ts +394 -0
- package/src/ontology-storage/materializations.ts +838 -0
- package/src/ontology-storage/outbox.ts +237 -0
- package/src/ontology-storage/shared.ts +269 -0
- package/src/ontology-storage/sources.ts +653 -0
- package/src/pipeline-run-storage.ts +506 -0
- package/src/projection-run-storage.ts +592 -0
- package/src/rules-storage.ts +375 -0
- package/src/run-list-query.ts +98 -0
- package/src/sql.d.ts +4 -0
- package/src/storage-errors.ts +3 -0
- package/src/sync-run-storage.ts +299 -0
- package/src/timeseries-storage.ts +212 -0
- package/src/transactions.ts +96 -0
- package/src/validation.ts +30 -0
- package/src/webhook-delivery-storage.ts +272 -0
- package/src/webhook-run-storage.ts +240 -0
- package/src/workflow-intervention-storage.ts +398 -0
- package/src/workflow-run-storage.ts +1148 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import type { Principal } from "@sixb/core"
|
|
2
|
+
import type {
|
|
3
|
+
AccessTokenRecord,
|
|
4
|
+
GroupMembershipRecord,
|
|
5
|
+
GroupMembershipSource,
|
|
6
|
+
InvitationRecord,
|
|
7
|
+
InvitationStatus,
|
|
8
|
+
MagicLinkRecord,
|
|
9
|
+
OidcAuthorizationAttemptRecord,
|
|
10
|
+
ServiceAccountGroupMembershipRecord,
|
|
11
|
+
ServiceAccountRecord,
|
|
12
|
+
ServiceAccountStatus,
|
|
13
|
+
SessionRecord,
|
|
14
|
+
UserIdentityRecord,
|
|
15
|
+
UserRecord,
|
|
16
|
+
UserStatus,
|
|
17
|
+
} from "@sixb/core/storage"
|
|
18
|
+
|
|
19
|
+
export interface SqliteAuthUserRow {
|
|
20
|
+
readonly project_id: string
|
|
21
|
+
readonly id: string
|
|
22
|
+
readonly email: string
|
|
23
|
+
readonly display_name: string | null
|
|
24
|
+
readonly avatar_url: string | null
|
|
25
|
+
readonly status: UserStatus
|
|
26
|
+
readonly created_at: string
|
|
27
|
+
readonly updated_at: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface SqliteAuthUserIdentityRow {
|
|
31
|
+
readonly project_id: string
|
|
32
|
+
readonly strategy_id: string
|
|
33
|
+
readonly subject: string
|
|
34
|
+
readonly user_id: string
|
|
35
|
+
readonly claims: string | null
|
|
36
|
+
readonly created_at: string
|
|
37
|
+
readonly updated_at: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SqliteAuthServiceAccountRow {
|
|
41
|
+
readonly project_id: string
|
|
42
|
+
readonly id: string
|
|
43
|
+
readonly name: string
|
|
44
|
+
readonly description: string | null
|
|
45
|
+
readonly status: ServiceAccountStatus
|
|
46
|
+
readonly created_by_principal_type: Principal["type"] | null
|
|
47
|
+
readonly created_by_principal_id: string | null
|
|
48
|
+
readonly created_by_session_id: string | null
|
|
49
|
+
readonly created_at: string
|
|
50
|
+
readonly updated_at: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface SqliteAuthServiceAccountGroupMembershipRow {
|
|
54
|
+
readonly project_id: string
|
|
55
|
+
readonly service_account_id: string
|
|
56
|
+
readonly group_id: string
|
|
57
|
+
readonly source: GroupMembershipSource
|
|
58
|
+
readonly created_at: string
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SqliteAuthSessionRow {
|
|
62
|
+
readonly project_id: string
|
|
63
|
+
readonly id: string
|
|
64
|
+
readonly user_id: string
|
|
65
|
+
readonly strategy_id: string
|
|
66
|
+
readonly audience: SessionRecord["audience"]
|
|
67
|
+
readonly token_hash: string
|
|
68
|
+
readonly created_at: string
|
|
69
|
+
readonly expires_at: string
|
|
70
|
+
readonly absolute_expires_at: string | null
|
|
71
|
+
readonly revoked_at: string | null
|
|
72
|
+
readonly last_seen_at: string | null
|
|
73
|
+
readonly user_agent: string | null
|
|
74
|
+
readonly ip_address: string | null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface SqliteAuthAccessTokenRow {
|
|
78
|
+
readonly project_id: string
|
|
79
|
+
readonly id: string
|
|
80
|
+
readonly name: string
|
|
81
|
+
readonly kind: AccessTokenRecord["kind"]
|
|
82
|
+
readonly subject_type: AccessTokenRecord["subjectType"]
|
|
83
|
+
readonly subject_id: string
|
|
84
|
+
readonly token_hash: string
|
|
85
|
+
readonly group_ids: string | null
|
|
86
|
+
readonly created_by_principal_type: Principal["type"] | null
|
|
87
|
+
readonly created_by_principal_id: string | null
|
|
88
|
+
readonly created_by_session_id: string | null
|
|
89
|
+
readonly created_at: string
|
|
90
|
+
readonly expires_at: string
|
|
91
|
+
readonly revoked_at: string | null
|
|
92
|
+
readonly last_used_at: string | null
|
|
93
|
+
readonly last_used_user_agent: string | null
|
|
94
|
+
readonly last_used_ip_address: string | null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface SqliteAuthInvitationRow {
|
|
98
|
+
readonly project_id: string
|
|
99
|
+
readonly id: string
|
|
100
|
+
readonly email: string
|
|
101
|
+
readonly status: InvitationStatus
|
|
102
|
+
readonly created_by_principal_type: Principal["type"] | null
|
|
103
|
+
readonly created_by_principal_id: string | null
|
|
104
|
+
readonly created_by_session_id: string | null
|
|
105
|
+
readonly created_at: string
|
|
106
|
+
readonly updated_at: string
|
|
107
|
+
readonly expires_at: string
|
|
108
|
+
readonly accepted_at: string | null
|
|
109
|
+
readonly revoked_at: string | null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface SqliteAuthGroupMembershipRow {
|
|
113
|
+
readonly project_id: string
|
|
114
|
+
readonly user_id: string
|
|
115
|
+
readonly group_id: string
|
|
116
|
+
readonly source: GroupMembershipSource
|
|
117
|
+
readonly created_at: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface SqliteAuthMagicLinkRow {
|
|
121
|
+
readonly project_id: string
|
|
122
|
+
readonly id: string
|
|
123
|
+
readonly strategy_id: string
|
|
124
|
+
readonly audience: MagicLinkRecord["audience"]
|
|
125
|
+
readonly email: string
|
|
126
|
+
readonly token_hash: string
|
|
127
|
+
readonly return_to: string | null
|
|
128
|
+
readonly created_at: string
|
|
129
|
+
readonly expires_at: string
|
|
130
|
+
readonly consumed_at: string | null
|
|
131
|
+
readonly revoked_at: string | null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface SqliteAuthOidcAttemptRow {
|
|
135
|
+
readonly project_id: string
|
|
136
|
+
readonly id: string
|
|
137
|
+
readonly strategy_id: string
|
|
138
|
+
readonly audience: OidcAuthorizationAttemptRecord["audience"]
|
|
139
|
+
readonly state_hash: string
|
|
140
|
+
readonly nonce_hash: string
|
|
141
|
+
readonly code_verifier: string
|
|
142
|
+
readonly return_to: string | null
|
|
143
|
+
readonly created_at: string
|
|
144
|
+
readonly expires_at: string
|
|
145
|
+
readonly consumed_at: string | null
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function rowToUserRecord(row: SqliteAuthUserRow): UserRecord {
|
|
149
|
+
return {
|
|
150
|
+
id: row.id,
|
|
151
|
+
projectId: row.project_id,
|
|
152
|
+
email: row.email,
|
|
153
|
+
displayName: row.display_name ?? undefined,
|
|
154
|
+
avatarUrl: row.avatar_url ?? undefined,
|
|
155
|
+
status: row.status,
|
|
156
|
+
createdAt: new Date(row.created_at),
|
|
157
|
+
updatedAt: new Date(row.updated_at),
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function rowToIdentityRecord(row: SqliteAuthUserIdentityRow): UserIdentityRecord {
|
|
162
|
+
return {
|
|
163
|
+
projectId: row.project_id,
|
|
164
|
+
strategyId: row.strategy_id,
|
|
165
|
+
subject: row.subject,
|
|
166
|
+
userId: row.user_id,
|
|
167
|
+
claims: parseOptionalRecord(row.claims),
|
|
168
|
+
createdAt: new Date(row.created_at),
|
|
169
|
+
updatedAt: new Date(row.updated_at),
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function rowToServiceAccountRecord(row: SqliteAuthServiceAccountRow): ServiceAccountRecord {
|
|
174
|
+
return {
|
|
175
|
+
id: row.id,
|
|
176
|
+
projectId: row.project_id,
|
|
177
|
+
name: row.name,
|
|
178
|
+
description: row.description ?? undefined,
|
|
179
|
+
status: row.status,
|
|
180
|
+
createdByPrincipal:
|
|
181
|
+
row.created_by_principal_type && row.created_by_principal_id
|
|
182
|
+
? {
|
|
183
|
+
type: row.created_by_principal_type,
|
|
184
|
+
id: row.created_by_principal_id,
|
|
185
|
+
}
|
|
186
|
+
: undefined,
|
|
187
|
+
createdBySessionId: row.created_by_session_id ?? undefined,
|
|
188
|
+
createdAt: new Date(row.created_at),
|
|
189
|
+
updatedAt: new Date(row.updated_at),
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function rowToServiceAccountGroupMembershipRecord(
|
|
194
|
+
row: SqliteAuthServiceAccountGroupMembershipRow
|
|
195
|
+
): ServiceAccountGroupMembershipRecord {
|
|
196
|
+
return {
|
|
197
|
+
projectId: row.project_id,
|
|
198
|
+
serviceAccountId: row.service_account_id,
|
|
199
|
+
groupId: row.group_id,
|
|
200
|
+
source: row.source,
|
|
201
|
+
createdAt: new Date(row.created_at),
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function rowToSessionRecord(row: SqliteAuthSessionRow): SessionRecord {
|
|
206
|
+
return {
|
|
207
|
+
id: row.id,
|
|
208
|
+
projectId: row.project_id,
|
|
209
|
+
userId: row.user_id,
|
|
210
|
+
strategyId: row.strategy_id,
|
|
211
|
+
audience: row.audience,
|
|
212
|
+
tokenHash: row.token_hash,
|
|
213
|
+
createdAt: new Date(row.created_at),
|
|
214
|
+
expiresAt: new Date(row.expires_at),
|
|
215
|
+
absoluteExpiresAt: row.absolute_expires_at ? new Date(row.absolute_expires_at) : undefined,
|
|
216
|
+
revokedAt: row.revoked_at ? new Date(row.revoked_at) : undefined,
|
|
217
|
+
lastSeenAt: row.last_seen_at ? new Date(row.last_seen_at) : undefined,
|
|
218
|
+
userAgent: row.user_agent ?? undefined,
|
|
219
|
+
ipAddress: row.ip_address ?? undefined,
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function rowToAccessTokenRecord(row: SqliteAuthAccessTokenRow): AccessTokenRecord {
|
|
224
|
+
return {
|
|
225
|
+
id: row.id,
|
|
226
|
+
projectId: row.project_id,
|
|
227
|
+
name: row.name,
|
|
228
|
+
kind: row.kind,
|
|
229
|
+
subjectType: row.subject_type,
|
|
230
|
+
subjectId: row.subject_id,
|
|
231
|
+
tokenHash: row.token_hash,
|
|
232
|
+
groupIds: parseOptionalStringArray(row.group_ids),
|
|
233
|
+
createdByPrincipal:
|
|
234
|
+
row.created_by_principal_type && row.created_by_principal_id
|
|
235
|
+
? {
|
|
236
|
+
type: row.created_by_principal_type,
|
|
237
|
+
id: row.created_by_principal_id,
|
|
238
|
+
}
|
|
239
|
+
: undefined,
|
|
240
|
+
createdBySessionId: row.created_by_session_id ?? undefined,
|
|
241
|
+
createdAt: new Date(row.created_at),
|
|
242
|
+
expiresAt: new Date(row.expires_at),
|
|
243
|
+
revokedAt: row.revoked_at ? new Date(row.revoked_at) : undefined,
|
|
244
|
+
lastUsedAt: row.last_used_at ? new Date(row.last_used_at) : undefined,
|
|
245
|
+
lastUsedUserAgent: row.last_used_user_agent ?? undefined,
|
|
246
|
+
lastUsedIpAddress: row.last_used_ip_address ?? undefined,
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function rowToInvitationRecord(
|
|
251
|
+
row: SqliteAuthInvitationRow,
|
|
252
|
+
groupIds: readonly string[]
|
|
253
|
+
): InvitationRecord {
|
|
254
|
+
return {
|
|
255
|
+
id: row.id,
|
|
256
|
+
projectId: row.project_id,
|
|
257
|
+
email: row.email,
|
|
258
|
+
groupIds,
|
|
259
|
+
status: row.status,
|
|
260
|
+
createdByPrincipal:
|
|
261
|
+
row.created_by_principal_type && row.created_by_principal_id
|
|
262
|
+
? {
|
|
263
|
+
type: row.created_by_principal_type,
|
|
264
|
+
id: row.created_by_principal_id,
|
|
265
|
+
}
|
|
266
|
+
: undefined,
|
|
267
|
+
createdBySessionId: row.created_by_session_id ?? undefined,
|
|
268
|
+
createdAt: new Date(row.created_at),
|
|
269
|
+
updatedAt: new Date(row.updated_at),
|
|
270
|
+
expiresAt: new Date(row.expires_at),
|
|
271
|
+
acceptedAt: row.accepted_at ? new Date(row.accepted_at) : undefined,
|
|
272
|
+
revokedAt: row.revoked_at ? new Date(row.revoked_at) : undefined,
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function rowToGroupMembershipRecord(
|
|
277
|
+
row: SqliteAuthGroupMembershipRow
|
|
278
|
+
): GroupMembershipRecord {
|
|
279
|
+
return {
|
|
280
|
+
projectId: row.project_id,
|
|
281
|
+
userId: row.user_id,
|
|
282
|
+
groupId: row.group_id,
|
|
283
|
+
source: row.source,
|
|
284
|
+
createdAt: new Date(row.created_at),
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function rowToMagicLinkRecord(row: SqliteAuthMagicLinkRow): MagicLinkRecord {
|
|
289
|
+
return {
|
|
290
|
+
id: row.id,
|
|
291
|
+
projectId: row.project_id,
|
|
292
|
+
strategyId: row.strategy_id,
|
|
293
|
+
audience: row.audience,
|
|
294
|
+
email: row.email,
|
|
295
|
+
tokenHash: row.token_hash,
|
|
296
|
+
returnTo: row.return_to ?? undefined,
|
|
297
|
+
createdAt: new Date(row.created_at),
|
|
298
|
+
expiresAt: new Date(row.expires_at),
|
|
299
|
+
consumedAt: row.consumed_at ? new Date(row.consumed_at) : undefined,
|
|
300
|
+
revokedAt: row.revoked_at ? new Date(row.revoked_at) : undefined,
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function rowToOidcAuthorizationAttemptRecord(
|
|
305
|
+
row: SqliteAuthOidcAttemptRow
|
|
306
|
+
): OidcAuthorizationAttemptRecord {
|
|
307
|
+
return {
|
|
308
|
+
id: row.id,
|
|
309
|
+
projectId: row.project_id,
|
|
310
|
+
strategyId: row.strategy_id,
|
|
311
|
+
audience: row.audience,
|
|
312
|
+
stateHash: row.state_hash,
|
|
313
|
+
nonceHash: row.nonce_hash,
|
|
314
|
+
codeVerifier: row.code_verifier,
|
|
315
|
+
returnTo: row.return_to ?? undefined,
|
|
316
|
+
createdAt: new Date(row.created_at),
|
|
317
|
+
expiresAt: new Date(row.expires_at),
|
|
318
|
+
consumedAt: row.consumed_at ? new Date(row.consumed_at) : undefined,
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function serializeOptionalRecord(
|
|
323
|
+
value: Readonly<Record<string, unknown>> | undefined
|
|
324
|
+
): string | null {
|
|
325
|
+
return value ? JSON.stringify(value) : null
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function serializeOptionalStringArray(value: readonly string[] | undefined): string | null {
|
|
329
|
+
return value === undefined ? null : JSON.stringify(value)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function parseOptionalRecord(value: string | null): Readonly<Record<string, unknown>> | undefined {
|
|
333
|
+
return value ? (JSON.parse(value) as Readonly<Record<string, unknown>>) : undefined
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function parseOptionalStringArray(value: string | null): readonly string[] | undefined {
|
|
337
|
+
return value === null ? undefined : (JSON.parse(value) as readonly string[])
|
|
338
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite"
|
|
2
|
+
import type {
|
|
3
|
+
AuthServiceAccountGroupMembershipStore,
|
|
4
|
+
ReconcileAuthServiceAccountGroupMembershipsInput,
|
|
5
|
+
ServiceAccountGroupMembershipRecord,
|
|
6
|
+
UpsertAuthServiceAccountGroupMembershipInput,
|
|
7
|
+
} from "@sixb/core/storage"
|
|
8
|
+
import { AuthStorageError } from "@sixb/core/storage"
|
|
9
|
+
import type {
|
|
10
|
+
SqliteAuthServiceAccountGroupMembershipRow,
|
|
11
|
+
SqliteAuthServiceAccountRow,
|
|
12
|
+
} from "./rows"
|
|
13
|
+
import { rowToServiceAccountGroupMembershipRecord } from "./rows"
|
|
14
|
+
import { assertNonEmpty, dateOrNow, normalizeGroupIds, toIso } from "./shared"
|
|
15
|
+
|
|
16
|
+
export class SqliteAuthServiceAccountGroupMembershipStore
|
|
17
|
+
implements AuthServiceAccountGroupMembershipStore
|
|
18
|
+
{
|
|
19
|
+
constructor(private readonly db: Database) {}
|
|
20
|
+
|
|
21
|
+
async upsert(
|
|
22
|
+
input: UpsertAuthServiceAccountGroupMembershipInput
|
|
23
|
+
): Promise<ServiceAccountGroupMembershipRecord> {
|
|
24
|
+
const projectId = assertNonEmpty(input.projectId, "Project id")
|
|
25
|
+
const serviceAccountId = assertNonEmpty(input.serviceAccountId, "Service account id")
|
|
26
|
+
const groupId = assertNonEmpty(input.groupId, "Group id")
|
|
27
|
+
const serviceAccount = this.db
|
|
28
|
+
.query("SELECT * FROM auth_service_accounts WHERE project_id = ? AND id = ?")
|
|
29
|
+
.get(projectId, serviceAccountId) as SqliteAuthServiceAccountRow | null
|
|
30
|
+
if (!serviceAccount) {
|
|
31
|
+
throw new AuthStorageError(
|
|
32
|
+
"missing_service_account",
|
|
33
|
+
`[Sixb] Service account '${serviceAccountId}' not found for project '${projectId}'.`
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.db
|
|
38
|
+
.query(
|
|
39
|
+
`
|
|
40
|
+
INSERT OR IGNORE INTO auth_service_account_group_memberships (
|
|
41
|
+
project_id,
|
|
42
|
+
service_account_id,
|
|
43
|
+
group_id,
|
|
44
|
+
source,
|
|
45
|
+
created_at
|
|
46
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
47
|
+
`
|
|
48
|
+
)
|
|
49
|
+
.run(projectId, serviceAccountId, groupId, input.source, toIso(dateOrNow(input.createdAt)))
|
|
50
|
+
|
|
51
|
+
const row = this.db
|
|
52
|
+
.query(
|
|
53
|
+
`
|
|
54
|
+
SELECT *
|
|
55
|
+
FROM auth_service_account_group_memberships
|
|
56
|
+
WHERE project_id = ?
|
|
57
|
+
AND service_account_id = ?
|
|
58
|
+
AND group_id = ?
|
|
59
|
+
`
|
|
60
|
+
)
|
|
61
|
+
.get(projectId, serviceAccountId, groupId) as SqliteAuthServiceAccountGroupMembershipRow
|
|
62
|
+
return rowToServiceAccountGroupMembershipRecord(row)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async reconcileForServiceAccount(
|
|
66
|
+
input: ReconcileAuthServiceAccountGroupMembershipsInput
|
|
67
|
+
): Promise<readonly ServiceAccountGroupMembershipRecord[]> {
|
|
68
|
+
const projectId = assertNonEmpty(input.projectId, "Project id")
|
|
69
|
+
const serviceAccountId = assertNonEmpty(input.serviceAccountId, "Service account id")
|
|
70
|
+
const serviceAccount = this.db
|
|
71
|
+
.query("SELECT * FROM auth_service_accounts WHERE project_id = ? AND id = ?")
|
|
72
|
+
.get(projectId, serviceAccountId) as SqliteAuthServiceAccountRow | null
|
|
73
|
+
if (!serviceAccount) {
|
|
74
|
+
throw new AuthStorageError(
|
|
75
|
+
"missing_service_account",
|
|
76
|
+
`[Sixb] Service account '${serviceAccountId}' not found for project '${projectId}'.`
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const groupIds = normalizeGroupIds(input.groupIds)
|
|
81
|
+
const desired = new Set(groupIds)
|
|
82
|
+
const existing = await this.listForServiceAccount({ projectId, serviceAccountId })
|
|
83
|
+
for (const membership of existing) {
|
|
84
|
+
if (membership.source === input.source && !desired.has(membership.groupId)) {
|
|
85
|
+
this.db
|
|
86
|
+
.query(
|
|
87
|
+
`
|
|
88
|
+
DELETE FROM auth_service_account_group_memberships
|
|
89
|
+
WHERE project_id = ?
|
|
90
|
+
AND service_account_id = ?
|
|
91
|
+
AND group_id = ?
|
|
92
|
+
AND source = ?
|
|
93
|
+
`
|
|
94
|
+
)
|
|
95
|
+
.run(projectId, serviceAccountId, membership.groupId, input.source)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const updatedAt = toIso(dateOrNow(input.updatedAt))
|
|
100
|
+
for (const groupId of groupIds) {
|
|
101
|
+
this.db
|
|
102
|
+
.query(
|
|
103
|
+
`
|
|
104
|
+
INSERT INTO auth_service_account_group_memberships (
|
|
105
|
+
project_id,
|
|
106
|
+
service_account_id,
|
|
107
|
+
group_id,
|
|
108
|
+
source,
|
|
109
|
+
created_at
|
|
110
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
111
|
+
ON CONFLICT(project_id, service_account_id, group_id) DO UPDATE
|
|
112
|
+
SET source = excluded.source
|
|
113
|
+
`
|
|
114
|
+
)
|
|
115
|
+
.run(projectId, serviceAccountId, groupId, input.source, updatedAt)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return this.listForServiceAccount({ projectId, serviceAccountId })
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async listForServiceAccount(params: {
|
|
122
|
+
readonly projectId: string
|
|
123
|
+
readonly serviceAccountId: string
|
|
124
|
+
}): Promise<readonly ServiceAccountGroupMembershipRecord[]> {
|
|
125
|
+
const rows = this.db
|
|
126
|
+
.query(
|
|
127
|
+
`
|
|
128
|
+
SELECT *
|
|
129
|
+
FROM auth_service_account_group_memberships
|
|
130
|
+
WHERE project_id = ?
|
|
131
|
+
AND service_account_id = ?
|
|
132
|
+
ORDER BY group_id ASC
|
|
133
|
+
`
|
|
134
|
+
)
|
|
135
|
+
.all(
|
|
136
|
+
params.projectId,
|
|
137
|
+
params.serviceAccountId
|
|
138
|
+
) as SqliteAuthServiceAccountGroupMembershipRow[]
|
|
139
|
+
|
|
140
|
+
return rows.map(rowToServiceAccountGroupMembershipRecord)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async listForGroup(params: {
|
|
144
|
+
readonly projectId: string
|
|
145
|
+
readonly groupId: string
|
|
146
|
+
}): Promise<readonly ServiceAccountGroupMembershipRecord[]> {
|
|
147
|
+
const rows = this.db
|
|
148
|
+
.query(
|
|
149
|
+
`
|
|
150
|
+
SELECT *
|
|
151
|
+
FROM auth_service_account_group_memberships
|
|
152
|
+
WHERE project_id = ?
|
|
153
|
+
AND group_id = ?
|
|
154
|
+
ORDER BY service_account_id ASC
|
|
155
|
+
`
|
|
156
|
+
)
|
|
157
|
+
.all(params.projectId, params.groupId) as SqliteAuthServiceAccountGroupMembershipRow[]
|
|
158
|
+
|
|
159
|
+
return rows.map(rowToServiceAccountGroupMembershipRecord)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite"
|
|
2
|
+
import type {
|
|
3
|
+
AuthServiceAccountStore,
|
|
4
|
+
CreateAuthServiceAccountInput,
|
|
5
|
+
ListAuthServiceAccountsInput,
|
|
6
|
+
ListAuthServiceAccountsResult,
|
|
7
|
+
ServiceAccountRecord,
|
|
8
|
+
UpdateAuthServiceAccountInput,
|
|
9
|
+
} from "@sixb/core/storage"
|
|
10
|
+
import { AuthStorageError } from "@sixb/core/storage"
|
|
11
|
+
import type { SqliteAuthServiceAccountRow } from "./rows"
|
|
12
|
+
import { rowToServiceAccountRecord } from "./rows"
|
|
13
|
+
import {
|
|
14
|
+
appendPagination,
|
|
15
|
+
assertNonEmpty,
|
|
16
|
+
dateOrNow,
|
|
17
|
+
hasEmptyFilter,
|
|
18
|
+
mapUniqueConstraintError,
|
|
19
|
+
type SqliteValue,
|
|
20
|
+
toIso,
|
|
21
|
+
} from "./shared"
|
|
22
|
+
|
|
23
|
+
export class SqliteAuthServiceAccountStore implements AuthServiceAccountStore {
|
|
24
|
+
constructor(private readonly db: Database) {}
|
|
25
|
+
|
|
26
|
+
async create(input: CreateAuthServiceAccountInput): Promise<ServiceAccountRecord> {
|
|
27
|
+
const id = assertNonEmpty(input.id, "Service account id")
|
|
28
|
+
const projectId = assertNonEmpty(input.projectId, "Project id")
|
|
29
|
+
const name = assertNonEmpty(input.name, "Service account name")
|
|
30
|
+
const createdAt = dateOrNow(input.createdAt)
|
|
31
|
+
const updatedAt = input.updatedAt ? new Date(input.updatedAt) : createdAt
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
this.db
|
|
35
|
+
.query(
|
|
36
|
+
`
|
|
37
|
+
INSERT INTO auth_service_accounts (
|
|
38
|
+
project_id,
|
|
39
|
+
id,
|
|
40
|
+
name,
|
|
41
|
+
description,
|
|
42
|
+
status,
|
|
43
|
+
created_by_principal_type,
|
|
44
|
+
created_by_principal_id,
|
|
45
|
+
created_by_session_id,
|
|
46
|
+
created_at,
|
|
47
|
+
updated_at
|
|
48
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
49
|
+
`
|
|
50
|
+
)
|
|
51
|
+
.run(
|
|
52
|
+
projectId,
|
|
53
|
+
id,
|
|
54
|
+
name,
|
|
55
|
+
input.description ?? null,
|
|
56
|
+
input.status ?? "active",
|
|
57
|
+
input.createdByPrincipal?.type ?? null,
|
|
58
|
+
input.createdByPrincipal?.id ?? null,
|
|
59
|
+
input.createdBySessionId ?? null,
|
|
60
|
+
toIso(createdAt),
|
|
61
|
+
toIso(updatedAt)
|
|
62
|
+
)
|
|
63
|
+
} catch (error) {
|
|
64
|
+
mapUniqueConstraintError(
|
|
65
|
+
error,
|
|
66
|
+
"duplicate_service_account",
|
|
67
|
+
`[Sixb] Service account '${id}' already exists for project '${projectId}'.`
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
id,
|
|
73
|
+
projectId,
|
|
74
|
+
name,
|
|
75
|
+
description: input.description,
|
|
76
|
+
status: input.status ?? "active",
|
|
77
|
+
createdByPrincipal: input.createdByPrincipal,
|
|
78
|
+
createdBySessionId: input.createdBySessionId,
|
|
79
|
+
createdAt,
|
|
80
|
+
updatedAt,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async getById(params: {
|
|
85
|
+
readonly projectId: string
|
|
86
|
+
readonly id: string
|
|
87
|
+
}): Promise<ServiceAccountRecord | null> {
|
|
88
|
+
const row = this.db
|
|
89
|
+
.query("SELECT * FROM auth_service_accounts WHERE project_id = ? AND id = ?")
|
|
90
|
+
.get(params.projectId, params.id) as SqliteAuthServiceAccountRow | null
|
|
91
|
+
return row ? rowToServiceAccountRecord(row) : null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async update(input: UpdateAuthServiceAccountInput): Promise<ServiceAccountRecord> {
|
|
95
|
+
const existing = await this.getById(input)
|
|
96
|
+
if (!existing) {
|
|
97
|
+
throw new AuthStorageError(
|
|
98
|
+
"missing_service_account",
|
|
99
|
+
`[Sixb] Service account '${input.id}' not found for project '${input.projectId}'.`
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const updatedAt = dateOrNow(input.updatedAt)
|
|
104
|
+
const name =
|
|
105
|
+
input.name === undefined ? existing.name : assertNonEmpty(input.name, "Service account name")
|
|
106
|
+
const description = input.description === undefined ? existing.description : input.description
|
|
107
|
+
const status = input.status ?? existing.status
|
|
108
|
+
this.db
|
|
109
|
+
.query(
|
|
110
|
+
`
|
|
111
|
+
UPDATE auth_service_accounts
|
|
112
|
+
SET name = ?,
|
|
113
|
+
description = ?,
|
|
114
|
+
status = ?,
|
|
115
|
+
updated_at = ?
|
|
116
|
+
WHERE project_id = ?
|
|
117
|
+
AND id = ?
|
|
118
|
+
`
|
|
119
|
+
)
|
|
120
|
+
.run(name, description ?? null, status, toIso(updatedAt), input.projectId, input.id)
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
...existing,
|
|
124
|
+
name,
|
|
125
|
+
description,
|
|
126
|
+
status,
|
|
127
|
+
updatedAt,
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async list(input: ListAuthServiceAccountsInput): Promise<ListAuthServiceAccountsResult> {
|
|
132
|
+
if (hasEmptyFilter(input.statuses)) {
|
|
133
|
+
return { serviceAccounts: [], hasMore: false, total: 0 }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const whereClauses = ["project_id = ?"]
|
|
137
|
+
const args: SqliteValue[] = [input.projectId]
|
|
138
|
+
if (input.statuses) {
|
|
139
|
+
whereClauses.push(`status IN (${input.statuses.map(() => "?").join(", ")})`)
|
|
140
|
+
args.push(...input.statuses)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const where = `WHERE ${whereClauses.join(" AND ")}`
|
|
144
|
+
const order = input.order === "desc" ? "DESC" : "ASC"
|
|
145
|
+
const totalRow = this.db
|
|
146
|
+
.query(`SELECT COUNT(*) AS count FROM auth_service_accounts ${where}`)
|
|
147
|
+
.get(...args) as { readonly count: number }
|
|
148
|
+
const queryArgs = [...args]
|
|
149
|
+
const query = appendPagination(
|
|
150
|
+
`
|
|
151
|
+
SELECT *
|
|
152
|
+
FROM auth_service_accounts
|
|
153
|
+
${where}
|
|
154
|
+
ORDER BY created_at ${order}, id ${order}
|
|
155
|
+
`,
|
|
156
|
+
queryArgs,
|
|
157
|
+
input
|
|
158
|
+
)
|
|
159
|
+
const rows = this.db.query(query).all(...queryArgs) as SqliteAuthServiceAccountRow[]
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
serviceAccounts: rows.map(rowToServiceAccountRecord),
|
|
163
|
+
hasMore:
|
|
164
|
+
input.limit === undefined ? false : (input.offset ?? 0) + input.limit < totalRow.count,
|
|
165
|
+
total: totalRow.count,
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|