@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.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/dist/action-run-storage.d.ts +29 -0
  4. package/dist/action-run-storage.d.ts.map +1 -0
  5. package/dist/agents/agent-storage.d.ts +25 -0
  6. package/dist/agents/agent-storage.d.ts.map +1 -0
  7. package/dist/agents/index.d.ts +6 -0
  8. package/dist/agents/index.d.ts.map +1 -0
  9. package/dist/agents/messages.d.ts +14 -0
  10. package/dist/agents/messages.d.ts.map +1 -0
  11. package/dist/agents/rows.d.ts +77 -0
  12. package/dist/agents/rows.d.ts.map +1 -0
  13. package/dist/agents/runs.d.ts +26 -0
  14. package/dist/agents/runs.d.ts.map +1 -0
  15. package/dist/agents/threads.d.ts +14 -0
  16. package/dist/agents/threads.d.ts.map +1 -0
  17. package/dist/auth-storage/access-tokens.d.ts +33 -0
  18. package/dist/auth-storage/access-tokens.d.ts.map +1 -0
  19. package/dist/auth-storage/auth-storage.d.ts +46 -0
  20. package/dist/auth-storage/auth-storage.d.ts.map +1 -0
  21. package/dist/auth-storage/group-memberships.d.ts +21 -0
  22. package/dist/auth-storage/group-memberships.d.ts.map +1 -0
  23. package/dist/auth-storage/identities.d.ts +17 -0
  24. package/dist/auth-storage/identities.d.ts.map +1 -0
  25. package/dist/auth-storage/index.d.ts +3 -0
  26. package/dist/auth-storage/index.d.ts.map +1 -0
  27. package/dist/auth-storage/invitations.d.ts +28 -0
  28. package/dist/auth-storage/invitations.d.ts.map +1 -0
  29. package/dist/auth-storage/magic-links.d.ts +28 -0
  30. package/dist/auth-storage/magic-links.d.ts.map +1 -0
  31. package/dist/auth-storage/oidc-attempts.d.ts +18 -0
  32. package/dist/auth-storage/oidc-attempts.d.ts.map +1 -0
  33. package/dist/auth-storage/rows.d.ts +134 -0
  34. package/dist/auth-storage/rows.d.ts.map +1 -0
  35. package/dist/auth-storage/service-account-group-memberships.d.ts +17 -0
  36. package/dist/auth-storage/service-account-group-memberships.d.ts.map +1 -0
  37. package/dist/auth-storage/service-accounts.d.ts +14 -0
  38. package/dist/auth-storage/service-accounts.d.ts.map +1 -0
  39. package/dist/auth-storage/sessions.d.ts +55 -0
  40. package/dist/auth-storage/sessions.d.ts.map +1 -0
  41. package/dist/auth-storage/shared.d.ts +131 -0
  42. package/dist/auth-storage/shared.d.ts.map +1 -0
  43. package/dist/auth-storage/users.d.ts +19 -0
  44. package/dist/auth-storage/users.d.ts.map +1 -0
  45. package/dist/index.d.ts +71 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +10204 -0
  48. package/dist/index.js.map +54 -0
  49. package/dist/latest-run-query.d.ts +22 -0
  50. package/dist/latest-run-query.d.ts.map +1 -0
  51. package/dist/migrations.d.ts +18 -0
  52. package/dist/migrations.d.ts.map +1 -0
  53. package/dist/object-query-compiler.d.ts +44 -0
  54. package/dist/object-query-compiler.d.ts.map +1 -0
  55. package/dist/object-storage.d.ts +93 -0
  56. package/dist/object-storage.d.ts.map +1 -0
  57. package/dist/ontology-storage/commits.d.ts +14 -0
  58. package/dist/ontology-storage/commits.d.ts.map +1 -0
  59. package/dist/ontology-storage/index.d.ts +22 -0
  60. package/dist/ontology-storage/index.d.ts.map +1 -0
  61. package/dist/ontology-storage/materialization-session.d.ts +49 -0
  62. package/dist/ontology-storage/materialization-session.d.ts.map +1 -0
  63. package/dist/ontology-storage/materialization-state.d.ts +63 -0
  64. package/dist/ontology-storage/materialization-state.d.ts.map +1 -0
  65. package/dist/ontology-storage/materialization-writer.d.ts +15 -0
  66. package/dist/ontology-storage/materialization-writer.d.ts.map +1 -0
  67. package/dist/ontology-storage/materializations.d.ts +32 -0
  68. package/dist/ontology-storage/materializations.d.ts.map +1 -0
  69. package/dist/ontology-storage/outbox.d.ts +14 -0
  70. package/dist/ontology-storage/outbox.d.ts.map +1 -0
  71. package/dist/ontology-storage/shared.d.ts +91 -0
  72. package/dist/ontology-storage/shared.d.ts.map +1 -0
  73. package/dist/ontology-storage/sources.d.ts +26 -0
  74. package/dist/ontology-storage/sources.d.ts.map +1 -0
  75. package/dist/pipeline-run-storage.d.ts +26 -0
  76. package/dist/pipeline-run-storage.d.ts.map +1 -0
  77. package/dist/projection-run-storage.d.ts +32 -0
  78. package/dist/projection-run-storage.d.ts.map +1 -0
  79. package/dist/rules-storage.d.ts +33 -0
  80. package/dist/rules-storage.d.ts.map +1 -0
  81. package/dist/run-list-query.d.ts +27 -0
  82. package/dist/run-list-query.d.ts.map +1 -0
  83. package/dist/storage-errors.d.ts +2 -0
  84. package/dist/storage-errors.d.ts.map +1 -0
  85. package/dist/sync-run-storage.d.ts +23 -0
  86. package/dist/sync-run-storage.d.ts.map +1 -0
  87. package/dist/timeseries-storage.d.ts +41 -0
  88. package/dist/timeseries-storage.d.ts.map +1 -0
  89. package/dist/transactions.d.ts +15 -0
  90. package/dist/transactions.d.ts.map +1 -0
  91. package/dist/tsconfig.json +5 -0
  92. package/dist/validation.d.ts +5 -0
  93. package/dist/validation.d.ts.map +1 -0
  94. package/dist/webhook-delivery-storage.d.ts +27 -0
  95. package/dist/webhook-delivery-storage.d.ts.map +1 -0
  96. package/dist/webhook-run-storage.d.ts +22 -0
  97. package/dist/webhook-run-storage.d.ts.map +1 -0
  98. package/dist/workflow-intervention-storage.d.ts +26 -0
  99. package/dist/workflow-intervention-storage.d.ts.map +1 -0
  100. package/dist/workflow-run-storage.d.ts +63 -0
  101. package/dist/workflow-run-storage.d.ts.map +1 -0
  102. package/package.json +58 -0
  103. package/src/action-run-storage.ts +761 -0
  104. package/src/agents/agent-storage.ts +46 -0
  105. package/src/agents/index.ts +5 -0
  106. package/src/agents/messages.ts +162 -0
  107. package/src/agents/rows.ts +205 -0
  108. package/src/agents/runs.ts +389 -0
  109. package/src/agents/threads.ts +133 -0
  110. package/src/auth-storage/access-tokens.ts +289 -0
  111. package/src/auth-storage/auth-storage.ts +784 -0
  112. package/src/auth-storage/group-memberships.ts +52 -0
  113. package/src/auth-storage/identities.ts +98 -0
  114. package/src/auth-storage/index.ts +2 -0
  115. package/src/auth-storage/invitations.ts +258 -0
  116. package/src/auth-storage/magic-links.ts +149 -0
  117. package/src/auth-storage/oidc-attempts.ts +109 -0
  118. package/src/auth-storage/rows.ts +338 -0
  119. package/src/auth-storage/service-account-group-memberships.ts +161 -0
  120. package/src/auth-storage/service-accounts.ts +168 -0
  121. package/src/auth-storage/sessions.ts +230 -0
  122. package/src/auth-storage/shared.ts +707 -0
  123. package/src/auth-storage/users.ts +226 -0
  124. package/src/index.ts +292 -0
  125. package/src/latest-run-query.ts +49 -0
  126. package/src/migrations/001-initial-schema.sql +1068 -0
  127. package/src/migrations.ts +245 -0
  128. package/src/object-query-compiler.ts +1198 -0
  129. package/src/object-storage.ts +605 -0
  130. package/src/ontology-storage/commits.ts +127 -0
  131. package/src/ontology-storage/index.ts +35 -0
  132. package/src/ontology-storage/materialization-session.ts +393 -0
  133. package/src/ontology-storage/materialization-state.ts +901 -0
  134. package/src/ontology-storage/materialization-writer.ts +394 -0
  135. package/src/ontology-storage/materializations.ts +838 -0
  136. package/src/ontology-storage/outbox.ts +237 -0
  137. package/src/ontology-storage/shared.ts +269 -0
  138. package/src/ontology-storage/sources.ts +653 -0
  139. package/src/pipeline-run-storage.ts +506 -0
  140. package/src/projection-run-storage.ts +592 -0
  141. package/src/rules-storage.ts +375 -0
  142. package/src/run-list-query.ts +98 -0
  143. package/src/sql.d.ts +4 -0
  144. package/src/storage-errors.ts +3 -0
  145. package/src/sync-run-storage.ts +299 -0
  146. package/src/timeseries-storage.ts +212 -0
  147. package/src/transactions.ts +96 -0
  148. package/src/validation.ts +30 -0
  149. package/src/webhook-delivery-storage.ts +272 -0
  150. package/src/webhook-run-storage.ts +240 -0
  151. package/src/workflow-intervention-storage.ts +398 -0
  152. package/src/workflow-run-storage.ts +1148 -0
@@ -0,0 +1,398 @@
1
+ import type { Database } from "bun:sqlite"
2
+ import type { WorkflowIOSnapshot } from "@sixb/core/internal/workflows"
3
+ import type {
4
+ CancelWorkflowInterventionInput,
5
+ CreateWorkflowInterventionInput,
6
+ ExpireWorkflowInterventionInput,
7
+ ListWorkflowInterventionsInput,
8
+ ListWorkflowInterventionsResult,
9
+ SubmitWorkflowInterventionInput,
10
+ WorkflowInterventionActor,
11
+ WorkflowInterventionRecord,
12
+ WorkflowInterventionStorage,
13
+ } from "@sixb/core/storage"
14
+ import { WorkflowInterventionError } from "@sixb/core/storage"
15
+ import { installFreshSqliteSchema } from "./migrations"
16
+ import { isUniqueConstraintError } from "./storage-errors"
17
+ import {
18
+ closeSqliteStoreConnection,
19
+ openSqliteStoreConnection,
20
+ type SqliteStoreConnection,
21
+ } from "./transactions"
22
+
23
+ export interface SqliteWorkflowInterventionStorageOptions {
24
+ /** Path to SQLite database file. Defaults to ':memory:' for in-memory database. */
25
+ path?: string
26
+ /** Internal shared connection used by bundled SqliteStorage. */
27
+ connection?: SqliteStoreConnection
28
+ }
29
+
30
+ export class SqliteWorkflowInterventionStorage implements WorkflowInterventionStorage {
31
+ private readonly connection: SqliteStoreConnection
32
+ private readonly db: Database
33
+
34
+ constructor(options: SqliteWorkflowInterventionStorageOptions = {}) {
35
+ this.connection = openSqliteStoreConnection(options)
36
+ this.db = this.connection.db
37
+
38
+ if (this.connection.installFreshSchema) {
39
+ installFreshSqliteSchema(this.db)
40
+ }
41
+ }
42
+
43
+ async create(input: CreateWorkflowInterventionInput): Promise<WorkflowInterventionRecord> {
44
+ assertNonNegativeInteger(input.nodeIndex, "nodeIndex")
45
+
46
+ try {
47
+ this.db
48
+ .query(
49
+ `
50
+ INSERT INTO workflow_interventions (
51
+ project_id,
52
+ id,
53
+ workflow_id,
54
+ workflow_run_id,
55
+ node_run_id,
56
+ node_index,
57
+ node_id,
58
+ node_key,
59
+ intervention_id,
60
+ input,
61
+ default_response,
62
+ status,
63
+ requested_at,
64
+ expires_at
65
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
66
+ `
67
+ )
68
+ .run(
69
+ input.projectId,
70
+ input.id,
71
+ input.workflowId,
72
+ input.workflowRunId,
73
+ input.nodeRunId,
74
+ input.nodeIndex,
75
+ input.nodeId,
76
+ input.nodeKey,
77
+ input.interventionId,
78
+ serializeRecord(input.input),
79
+ serializeRecord(input.defaultResponse),
80
+ "pending",
81
+ (input.requestedAt ?? new Date()).toISOString(),
82
+ input.expiresAt?.toISOString() ?? null
83
+ )
84
+ } catch (error) {
85
+ if (isUniqueConstraintError(error)) {
86
+ throw new WorkflowInterventionError(
87
+ `[SixbSqlite] Workflow intervention '${input.id}' already exists for project '${input.projectId}'.`
88
+ )
89
+ }
90
+
91
+ throw error
92
+ }
93
+
94
+ return this.requireIntervention(input.projectId, input.id)
95
+ }
96
+
97
+ async submit(input: SubmitWorkflowInterventionInput): Promise<WorkflowInterventionRecord> {
98
+ return this.db.transaction(() => {
99
+ const existing = this.requirePendingIntervention(input.projectId, input.id)
100
+
101
+ this.db
102
+ .query(
103
+ `
104
+ UPDATE workflow_interventions
105
+ SET
106
+ status = ?,
107
+ submitted_at = ?,
108
+ submitted_by = ?,
109
+ response = ?
110
+ WHERE project_id = ? AND id = ?
111
+ `
112
+ )
113
+ .run(
114
+ "submitted",
115
+ (input.submittedAt ?? new Date()).toISOString(),
116
+ serializeActor(input.submittedBy),
117
+ serializeRecord(input.response),
118
+ existing.project_id,
119
+ existing.id
120
+ )
121
+
122
+ return this.requireIntervention(input.projectId, input.id)
123
+ })()
124
+ }
125
+
126
+ async cancel(input: CancelWorkflowInterventionInput): Promise<WorkflowInterventionRecord> {
127
+ return this.db.transaction(() => {
128
+ const existing = this.requirePendingIntervention(input.projectId, input.id)
129
+
130
+ this.db
131
+ .query(
132
+ `
133
+ UPDATE workflow_interventions
134
+ SET
135
+ status = ?,
136
+ cancelled_at = ?,
137
+ cancelled_by = ?
138
+ WHERE project_id = ? AND id = ?
139
+ `
140
+ )
141
+ .run(
142
+ "cancelled",
143
+ (input.cancelledAt ?? new Date()).toISOString(),
144
+ serializeActor(input.cancelledBy),
145
+ existing.project_id,
146
+ existing.id
147
+ )
148
+
149
+ return this.requireIntervention(input.projectId, input.id)
150
+ })()
151
+ }
152
+
153
+ async expire(input: ExpireWorkflowInterventionInput): Promise<WorkflowInterventionRecord> {
154
+ return this.db.transaction(() => {
155
+ const existing = this.requirePendingIntervention(input.projectId, input.id)
156
+
157
+ this.db
158
+ .query(
159
+ `
160
+ UPDATE workflow_interventions
161
+ SET
162
+ status = ?,
163
+ expired_at = ?
164
+ WHERE project_id = ? AND id = ?
165
+ `
166
+ )
167
+ .run(
168
+ "expired",
169
+ (input.expiredAt ?? new Date()).toISOString(),
170
+ existing.project_id,
171
+ existing.id
172
+ )
173
+
174
+ return this.requireIntervention(input.projectId, input.id)
175
+ })()
176
+ }
177
+
178
+ async getById(params: {
179
+ projectId: string
180
+ id: string
181
+ }): Promise<WorkflowInterventionRecord | null> {
182
+ const row = this.db
183
+ .query("SELECT * FROM workflow_interventions WHERE project_id = ? AND id = ?")
184
+ .get(params.projectId, params.id) as WorkflowInterventionDatabaseRow | null
185
+
186
+ return row ? rowToWorkflowInterventionRecord(row) : null
187
+ }
188
+
189
+ async list(input: ListWorkflowInterventionsInput): Promise<ListWorkflowInterventionsResult> {
190
+ if ((input.statuses && input.statuses.length === 0) || input.workflowIds?.length === 0) {
191
+ return {
192
+ interventions: [],
193
+ hasMore: false,
194
+ total: 0,
195
+ }
196
+ }
197
+
198
+ const whereClauses = ["project_id = ?"]
199
+ const args: SqliteValue[] = [input.projectId]
200
+
201
+ if (input.statuses) {
202
+ whereClauses.push(`status IN (${input.statuses.map(() => "?").join(", ")})`)
203
+ args.push(...input.statuses)
204
+ }
205
+
206
+ if (input.workflowId) {
207
+ whereClauses.push("workflow_id = ?")
208
+ args.push(input.workflowId)
209
+ }
210
+
211
+ if (input.workflowIds) {
212
+ whereClauses.push(`workflow_id IN (${input.workflowIds.map(() => "?").join(", ")})`)
213
+ args.push(...input.workflowIds)
214
+ }
215
+
216
+ if (input.workflowRunId) {
217
+ whereClauses.push("workflow_run_id = ?")
218
+ args.push(input.workflowRunId)
219
+ }
220
+
221
+ if (input.nodeRunId) {
222
+ whereClauses.push("node_run_id = ?")
223
+ args.push(input.nodeRunId)
224
+ }
225
+
226
+ if (input.nodeId) {
227
+ whereClauses.push("node_id = ?")
228
+ args.push(input.nodeId)
229
+ }
230
+
231
+ if (input.nodeKey) {
232
+ whereClauses.push("node_key = ?")
233
+ args.push(input.nodeKey)
234
+ }
235
+
236
+ if (input.interventionId) {
237
+ whereClauses.push("intervention_id = ?")
238
+ args.push(input.interventionId)
239
+ }
240
+
241
+ if (input.requestedAfter) {
242
+ whereClauses.push("requested_at >= ?")
243
+ args.push(input.requestedAfter.toISOString())
244
+ }
245
+
246
+ if (input.requestedBefore) {
247
+ whereClauses.push("requested_at <= ?")
248
+ args.push(input.requestedBefore.toISOString())
249
+ }
250
+
251
+ const where = `WHERE ${whereClauses.join(" AND ")}`
252
+ const order = input.order === "asc" ? "ASC" : "DESC"
253
+ const offset = input.offset ?? 0
254
+ const totalRow = this.db
255
+ .query(`SELECT COUNT(*) AS count FROM workflow_interventions ${where}`)
256
+ .get(...args) as { count: number }
257
+
258
+ let query = `
259
+ SELECT * FROM workflow_interventions
260
+ ${where}
261
+ ORDER BY requested_at ${order}, id ${order}
262
+ `
263
+ const queryArgs = [...args]
264
+
265
+ if (input.limit !== undefined) {
266
+ query += " LIMIT ? OFFSET ?"
267
+ queryArgs.push(input.limit, offset)
268
+ } else if (offset > 0) {
269
+ query += " LIMIT -1 OFFSET ?"
270
+ queryArgs.push(offset)
271
+ }
272
+
273
+ const rows = this.db.query(query).all(...queryArgs) as WorkflowInterventionDatabaseRow[]
274
+
275
+ return {
276
+ interventions: rows.map(rowToWorkflowInterventionRecord),
277
+ hasMore: offset + rows.length < totalRow.count,
278
+ total: totalRow.count,
279
+ }
280
+ }
281
+
282
+ close(): void {
283
+ closeSqliteStoreConnection(this.connection)
284
+ }
285
+
286
+ private requirePendingIntervention(
287
+ projectId: string,
288
+ id: string
289
+ ): WorkflowInterventionDatabaseRow {
290
+ const row = this.db
291
+ .query("SELECT * FROM workflow_interventions WHERE project_id = ? AND id = ?")
292
+ .get(projectId, id) as WorkflowInterventionDatabaseRow | null
293
+
294
+ if (!row) {
295
+ throw new WorkflowInterventionError(
296
+ `[SixbSqlite] Workflow intervention '${id}' not found for project '${projectId}'.`
297
+ )
298
+ }
299
+
300
+ if (row.status !== "pending") {
301
+ throw new WorkflowInterventionError(
302
+ `[SixbSqlite] Workflow intervention '${id}' for project '${projectId}' is not pending.`
303
+ )
304
+ }
305
+
306
+ return row
307
+ }
308
+
309
+ private requireIntervention(projectId: string, id: string): WorkflowInterventionRecord {
310
+ const row = this.db
311
+ .query("SELECT * FROM workflow_interventions WHERE project_id = ? AND id = ?")
312
+ .get(projectId, id) as WorkflowInterventionDatabaseRow | null
313
+
314
+ if (!row) {
315
+ throw new WorkflowInterventionError(
316
+ `[SixbSqlite] Failed to load workflow intervention '${id}' for project '${projectId}'.`
317
+ )
318
+ }
319
+
320
+ return rowToWorkflowInterventionRecord(row)
321
+ }
322
+ }
323
+
324
+ type SqliteValue = string | number | null
325
+
326
+ function serializeRecord(value: WorkflowIOSnapshot): string {
327
+ return JSON.stringify(value)
328
+ }
329
+
330
+ function parseRecord(value: string): WorkflowIOSnapshot {
331
+ return JSON.parse(value) as WorkflowIOSnapshot
332
+ }
333
+
334
+ function serializeActor(actor: WorkflowInterventionActor | undefined): string | null {
335
+ return actor ? JSON.stringify(actor) : null
336
+ }
337
+
338
+ function parseActor(value: string | null): WorkflowInterventionActor | undefined {
339
+ return value ? (JSON.parse(value) as WorkflowInterventionActor) : undefined
340
+ }
341
+
342
+ function rowToWorkflowInterventionRecord(
343
+ row: WorkflowInterventionDatabaseRow
344
+ ): WorkflowInterventionRecord {
345
+ return {
346
+ id: row.id,
347
+ projectId: row.project_id,
348
+ workflowId: row.workflow_id,
349
+ workflowRunId: row.workflow_run_id,
350
+ nodeRunId: row.node_run_id,
351
+ nodeIndex: row.node_index,
352
+ nodeId: row.node_id,
353
+ nodeKey: row.node_key,
354
+ interventionId: row.intervention_id,
355
+ input: parseRecord(row.input),
356
+ defaultResponse: parseRecord(row.default_response),
357
+ status: row.status,
358
+ requestedAt: new Date(row.requested_at),
359
+ expiresAt: row.expires_at ? new Date(row.expires_at) : undefined,
360
+ submittedAt: row.submitted_at ? new Date(row.submitted_at) : undefined,
361
+ submittedBy: parseActor(row.submitted_by),
362
+ response: row.response ? parseRecord(row.response) : undefined,
363
+ cancelledAt: row.cancelled_at ? new Date(row.cancelled_at) : undefined,
364
+ cancelledBy: parseActor(row.cancelled_by),
365
+ expiredAt: row.expired_at ? new Date(row.expired_at) : undefined,
366
+ }
367
+ }
368
+
369
+ function assertNonNegativeInteger(value: number, fieldName: string): void {
370
+ if (!Number.isInteger(value) || value < 0) {
371
+ throw new WorkflowInterventionError(
372
+ `[SixbSqlite] Workflow intervention ${fieldName} must be a non-negative integer.`
373
+ )
374
+ }
375
+ }
376
+
377
+ interface WorkflowInterventionDatabaseRow {
378
+ project_id: string
379
+ id: string
380
+ workflow_id: string
381
+ workflow_run_id: string
382
+ node_run_id: string
383
+ node_index: number
384
+ node_id: string
385
+ node_key: string
386
+ intervention_id: string
387
+ input: string
388
+ default_response: string
389
+ status: WorkflowInterventionRecord["status"]
390
+ requested_at: string
391
+ expires_at: string | null
392
+ submitted_at: string | null
393
+ submitted_by: string | null
394
+ response: string | null
395
+ cancelled_at: string | null
396
+ cancelled_by: string | null
397
+ expired_at: string | null
398
+ }