@sixb/sqlite 0.1.20 → 0.1.21
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/dist/action-run-storage.d.ts +4 -0
- package/dist/action-run-storage.d.ts.map +1 -1
- package/dist/activity-storage.d.ts +20 -0
- package/dist/activity-storage.d.ts.map +1 -0
- package/dist/agents/threads.d.ts +4 -0
- package/dist/agents/threads.d.ts.map +1 -1
- package/dist/artifact-storage.d.ts +22 -0
- package/dist/artifact-storage.d.ts.map +1 -0
- package/dist/auth-storage/sessions.d.ts +2 -1
- package/dist/auth-storage/sessions.d.ts.map +1 -1
- package/dist/execution-storage.d.ts +2 -1
- package/dist/execution-storage.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +880 -14
- package/dist/index.js.map +14 -12
- package/dist/migrations.d.ts.map +1 -1
- package/dist/ontology-storage/sources.d.ts +2 -1
- package/dist/ontology-storage/sources.d.ts.map +1 -1
- package/dist/share-grant-storage.d.ts +2 -1
- package/dist/share-grant-storage.d.ts.map +1 -1
- package/dist/workflow-run-storage.d.ts +4 -0
- package/dist/workflow-run-storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/action-run-storage.ts +27 -0
- package/src/activity-storage.ts +588 -0
- package/src/agents/threads.ts +27 -0
- package/src/artifact-storage.ts +356 -0
- package/src/auth-storage/sessions.ts +27 -0
- package/src/execution-storage.ts +56 -0
- package/src/index.ts +10 -0
- package/src/migrations/062-artifacts.sql +71 -0
- package/src/migrations/063-drop-output-diagnostics.sql +19 -0
- package/src/migrations/064-activity.sql +61 -0
- package/src/migrations/065-activity-timeline.sql +19 -0
- package/src/migrations/066-activity-interactions.sql +20 -0
- package/src/migrations.ts +14 -0
- package/src/ontology-storage/sources.ts +41 -0
- package/src/share-grant-storage.ts +25 -0
- package/src/workflow-run-storage.ts +27 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
-- App activity: one source per verified session, the visits it opened, and their page views.
|
|
2
|
+
-- Foreground activity moves a visit's `last_seen_at` and stores no row, unless it opens a visit.
|
|
3
|
+
-- A session id names an `auth_sessions` row for a user and a `share_sessions` row for a share; it
|
|
4
|
+
-- is not a secret, and no foreign key holds it, so history outlives its sessions. Timestamps are
|
|
5
|
+
-- ISO-8601 UTC text and compare lexicographically.
|
|
6
|
+
CREATE TABLE activity_sources (
|
|
7
|
+
project_id TEXT NOT NULL,
|
|
8
|
+
actor_type TEXT NOT NULL CHECK (actor_type IN ('user', 'share')),
|
|
9
|
+
session_id TEXT NOT NULL CHECK (length(session_id) > 0),
|
|
10
|
+
visit_id TEXT NOT NULL,
|
|
11
|
+
last_seen_at TEXT NOT NULL,
|
|
12
|
+
sequence INTEGER NOT NULL CHECK (sequence >= 0),
|
|
13
|
+
window_start TEXT NOT NULL,
|
|
14
|
+
window_count INTEGER NOT NULL CHECK (window_count >= 0),
|
|
15
|
+
PRIMARY KEY (project_id, actor_type, session_id)
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE activity_visits (
|
|
19
|
+
project_id TEXT NOT NULL,
|
|
20
|
+
id TEXT NOT NULL,
|
|
21
|
+
actor_type TEXT NOT NULL CHECK (actor_type IN ('user', 'share')),
|
|
22
|
+
user_id TEXT,
|
|
23
|
+
grant_id TEXT,
|
|
24
|
+
session_id TEXT NOT NULL CHECK (length(session_id) > 0),
|
|
25
|
+
started_at TEXT NOT NULL,
|
|
26
|
+
last_seen_at TEXT NOT NULL CHECK (last_seen_at >= started_at),
|
|
27
|
+
page_views INTEGER NOT NULL CHECK (page_views >= 0),
|
|
28
|
+
attribution TEXT CHECK (attribution IS NULL OR json_type(attribution) = 'object'),
|
|
29
|
+
PRIMARY KEY (project_id, id),
|
|
30
|
+
CHECK (
|
|
31
|
+
(actor_type = 'user' AND user_id IS NOT NULL AND grant_id IS NULL)
|
|
32
|
+
OR (actor_type = 'share' AND user_id IS NULL AND grant_id IS NOT NULL)
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
-- A period reads the visits it overlaps. A visit lasts less than a day, so they started in
|
|
37
|
+
-- `[from - 1 day, to)`: both period indexes bound `started_at` on both sides. `last_seen_at` is
|
|
38
|
+
-- left out of every index, so the update each batch makes touches none of them. The user index
|
|
39
|
+
-- also serves deleting one user's history.
|
|
40
|
+
CREATE INDEX idx_activity_visits_started
|
|
41
|
+
ON activity_visits (project_id, started_at, id);
|
|
42
|
+
CREATE INDEX idx_activity_visits_user
|
|
43
|
+
ON activity_visits (project_id, user_id, started_at, id);
|
|
44
|
+
-- A session's visits, to join them with the session and the executions it authorized.
|
|
45
|
+
CREATE INDEX idx_activity_visits_session
|
|
46
|
+
ON activity_visits (project_id, actor_type, session_id);
|
|
47
|
+
|
|
48
|
+
CREATE TABLE activity_page_views (
|
|
49
|
+
project_id TEXT NOT NULL,
|
|
50
|
+
visit_id TEXT NOT NULL,
|
|
51
|
+
sequence INTEGER NOT NULL CHECK (sequence > 0),
|
|
52
|
+
id TEXT NOT NULL,
|
|
53
|
+
route TEXT NOT NULL,
|
|
54
|
+
received_at TEXT NOT NULL,
|
|
55
|
+
attribution TEXT CHECK (attribution IS NULL OR json_type(attribution) = 'object'),
|
|
56
|
+
PRIMARY KEY (project_id, visit_id, sequence),
|
|
57
|
+
FOREIGN KEY (project_id, visit_id) REFERENCES activity_visits (project_id, id) ON DELETE CASCADE
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
-- Finds a retried page view by the id its browser chose.
|
|
61
|
+
CREATE INDEX idx_activity_page_views_id ON activity_page_views (project_id, id);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- A visit's timeline reads what its session started: the roots it authorized in a window, then
|
|
2
|
+
-- everything they caused. A signed-in session is the credential of its roots, a shared link's
|
|
3
|
+
-- session their delegation; a child names its parent. Agent executions copy their parent's
|
|
4
|
+
-- session: the root indexes hold only executions without a parent, so they never see those, and
|
|
5
|
+
-- end with `id` so the root read's order needs no sort.
|
|
6
|
+
CREATE INDEX idx_executions_session_roots
|
|
7
|
+
ON executions (project_id, authority_session_id, created_at, id)
|
|
8
|
+
WHERE authority_session_id IS NOT NULL AND parent_execution_id IS NULL;
|
|
9
|
+
CREATE INDEX idx_executions_delegation_roots
|
|
10
|
+
ON executions (project_id, authority_delegation_session_id, created_at, id)
|
|
11
|
+
WHERE authority_delegation_session_id IS NOT NULL AND parent_execution_id IS NULL;
|
|
12
|
+
CREATE INDEX idx_executions_parent
|
|
13
|
+
ON executions (project_id, parent_execution_id)
|
|
14
|
+
WHERE parent_execution_id IS NOT NULL;
|
|
15
|
+
|
|
16
|
+
-- A user's connection history lists all their sessions, revoked and expired ones too, newest
|
|
17
|
+
-- first.
|
|
18
|
+
CREATE INDEX idx_auth_sessions_user_created
|
|
19
|
+
ON auth_sessions (project_id, user_id, created_at, id);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Interactions an app marks, such as a button: their name and route, never a value. They share
|
|
2
|
+
-- the visit's sequence with its page views, so a visit reads both in the order they happened, and
|
|
3
|
+
-- cascade with the visit, which counts them as it counts its page views.
|
|
4
|
+
ALTER TABLE activity_visits
|
|
5
|
+
ADD COLUMN interactions INTEGER NOT NULL DEFAULT 0 CHECK (interactions >= 0);
|
|
6
|
+
|
|
7
|
+
CREATE TABLE activity_interactions (
|
|
8
|
+
project_id TEXT NOT NULL,
|
|
9
|
+
visit_id TEXT NOT NULL,
|
|
10
|
+
sequence INTEGER NOT NULL CHECK (sequence > 0),
|
|
11
|
+
id TEXT NOT NULL,
|
|
12
|
+
name TEXT NOT NULL CHECK (length(name) BETWEEN 1 AND 100),
|
|
13
|
+
route TEXT NOT NULL,
|
|
14
|
+
received_at TEXT NOT NULL,
|
|
15
|
+
PRIMARY KEY (project_id, visit_id, sequence),
|
|
16
|
+
FOREIGN KEY (project_id, visit_id) REFERENCES activity_visits (project_id, id) ON DELETE CASCADE
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
-- Finds a retried interaction by the id its browser chose.
|
|
20
|
+
CREATE INDEX idx_activity_interactions_id ON activity_interactions (project_id, id);
|
package/src/migrations.ts
CHANGED
|
@@ -273,6 +273,11 @@ export const sqliteStorageMigrations = defineMigrations({
|
|
|
273
273
|
sqliteSql("059-drained-source-versions", drainedSourceVersionsSql),
|
|
274
274
|
sqliteSql("060-terminal-action-runs", terminalActionRunsSql),
|
|
275
275
|
sqliteSql("061-drop-auth-audience", dropAuthAudienceSql),
|
|
276
|
+
sqliteSql("062-artifacts", artifactsSql),
|
|
277
|
+
sqliteSql("063-drop-output-diagnostics", dropOutputDiagnosticsSql),
|
|
278
|
+
sqliteSql("064-activity", activitySql),
|
|
279
|
+
sqliteSql("065-activity-timeline", activityTimelineSql),
|
|
280
|
+
sqliteSql("066-activity-interactions", activityInteractionsSql),
|
|
276
281
|
],
|
|
277
282
|
})
|
|
278
283
|
|
|
@@ -621,3 +626,12 @@ import drainedSourceVersionsSql from "./migrations/059-drained-source-versions.s
|
|
|
621
626
|
}
|
|
622
627
|
import terminalActionRunsSql from "./migrations/060-terminal-action-runs.sql" with { type: "text" }
|
|
623
628
|
import dropAuthAudienceSql from "./migrations/061-drop-auth-audience.sql" with { type: "text" }
|
|
629
|
+
import artifactsSql from "./migrations/062-artifacts.sql" with { type: "text" }
|
|
630
|
+
import dropOutputDiagnosticsSql from "./migrations/063-drop-output-diagnostics.sql" with {
|
|
631
|
+
type: "text",
|
|
632
|
+
}
|
|
633
|
+
import activitySql from "./migrations/064-activity.sql" with { type: "text" }
|
|
634
|
+
import activityTimelineSql from "./migrations/065-activity-timeline.sql" with { type: "text" }
|
|
635
|
+
import activityInteractionsSql from "./migrations/066-activity-interactions.sql" with {
|
|
636
|
+
type: "text",
|
|
637
|
+
}
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
AbandonRunSourceMaterializationInput,
|
|
21
21
|
AbandonSourceMaterializationCandidateInput,
|
|
22
22
|
AbandonSourceMaterializationInput,
|
|
23
|
+
ActiveOntologySource,
|
|
23
24
|
AdoptedSourceMaterialization,
|
|
24
25
|
AdoptSourceMaterializationInput,
|
|
25
26
|
AssertSourceMaterializationExecutionInput,
|
|
@@ -27,6 +28,7 @@ import type {
|
|
|
27
28
|
CleanupTerminalSourceMaterializationsInput,
|
|
28
29
|
CleanupTerminalSourceMaterializationsResult,
|
|
29
30
|
GetActiveOntologySourceInput,
|
|
31
|
+
ListActiveOntologySourcesInput,
|
|
30
32
|
MarkSourceMaterializationReadyInput,
|
|
31
33
|
OntologySourceRecord,
|
|
32
34
|
OntologySourceStorage,
|
|
@@ -238,6 +240,36 @@ export class SqliteOntologySourceStorage implements OntologySourceStorage {
|
|
|
238
240
|
})
|
|
239
241
|
}
|
|
240
242
|
|
|
243
|
+
async listActive(
|
|
244
|
+
input: ListActiveOntologySourcesInput
|
|
245
|
+
): Promise<readonly ActiveOntologySource[]> {
|
|
246
|
+
return this.runRootOperation(() => {
|
|
247
|
+
assertNonblank(input.projectId, "Source project id")
|
|
248
|
+
|
|
249
|
+
// Served by the partial index on active sources.
|
|
250
|
+
const rows = this.db
|
|
251
|
+
.query(
|
|
252
|
+
`
|
|
253
|
+
SELECT source_id, dataset_id, dataset_version_id, dataset_version_created_at,
|
|
254
|
+
projection_revision
|
|
255
|
+
FROM ontology_sources
|
|
256
|
+
WHERE project_id = ? AND status = 'active'
|
|
257
|
+
`
|
|
258
|
+
)
|
|
259
|
+
.all(input.projectId) as ActiveSourceRow[]
|
|
260
|
+
|
|
261
|
+
return rows.map((row) => ({
|
|
262
|
+
source: { projectionId: row.source_id },
|
|
263
|
+
datasetVersion: {
|
|
264
|
+
datasetId: row.dataset_id,
|
|
265
|
+
versionId: row.dataset_version_id,
|
|
266
|
+
createdAt: row.dataset_version_created_at,
|
|
267
|
+
},
|
|
268
|
+
projectionRevision: row.projection_revision,
|
|
269
|
+
}))
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
241
273
|
async adopt(
|
|
242
274
|
input: AdoptSourceMaterializationInput
|
|
243
275
|
): Promise<AdoptedSourceMaterialization | null> {
|
|
@@ -626,3 +658,12 @@ export class SqliteOntologySourceStorage implements OntologySourceStorage {
|
|
|
626
658
|
return row
|
|
627
659
|
}
|
|
628
660
|
}
|
|
661
|
+
|
|
662
|
+
type ActiveSourceRow = Pick<
|
|
663
|
+
SqliteOntologySourceRow,
|
|
664
|
+
| "source_id"
|
|
665
|
+
| "dataset_id"
|
|
666
|
+
| "dataset_version_id"
|
|
667
|
+
| "dataset_version_created_at"
|
|
668
|
+
| "projection_revision"
|
|
669
|
+
>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import type {
|
|
10
10
|
CreateShareGrantInput,
|
|
11
11
|
GetShareGrantByIdInput,
|
|
12
|
+
GetShareGrantsByIdsInput,
|
|
12
13
|
ListShareGrantsInput,
|
|
13
14
|
ListShareGrantsResult,
|
|
14
15
|
RevokeShareGrantInput,
|
|
@@ -85,6 +86,30 @@ export class SqliteShareGrantStorage implements ShareGrantStorage {
|
|
|
85
86
|
return this.getRow(normalized.projectId, normalized.id)
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
async getByIds(input: GetShareGrantsByIdsInput): Promise<readonly ShareGrantRecord[]> {
|
|
90
|
+
const ids = [...new Set(input.ids)]
|
|
91
|
+
if (ids.length === 0) {
|
|
92
|
+
return []
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const rows = this.db
|
|
96
|
+
.query(
|
|
97
|
+
`
|
|
98
|
+
SELECT *
|
|
99
|
+
FROM share_grants
|
|
100
|
+
WHERE project_id = ?
|
|
101
|
+
AND id IN (SELECT value FROM json_each(?))
|
|
102
|
+
`
|
|
103
|
+
)
|
|
104
|
+
.all(input.projectId, JSON.stringify(ids)) as SqliteShareGrantRow[]
|
|
105
|
+
|
|
106
|
+
const byId = new Map(rows.map((row) => [row.id, row]))
|
|
107
|
+
return ids.flatMap((id) => {
|
|
108
|
+
const row = byId.get(id)
|
|
109
|
+
return row ? [rowToRecord(row)] : []
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
88
113
|
async list(input: ListShareGrantsInput): Promise<ListShareGrantsResult> {
|
|
89
114
|
const normalized = normalizeListShareGrantsInput(input)
|
|
90
115
|
const where = ["project_id = ?"]
|
|
@@ -358,6 +358,33 @@ export class SqliteWorkflowRunStorage implements WorkflowRunStorage {
|
|
|
358
358
|
return row ? rowToWorkflowRunRecord(row) : null
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
async getByExecutionIds(params: {
|
|
362
|
+
readonly projectId: string
|
|
363
|
+
readonly executionIds: readonly string[]
|
|
364
|
+
}): Promise<readonly WorkflowRunRecord[]> {
|
|
365
|
+
const executionIds = [...new Set(params.executionIds)]
|
|
366
|
+
if (executionIds.length === 0) {
|
|
367
|
+
return []
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const rows = this.db
|
|
371
|
+
.query(
|
|
372
|
+
`
|
|
373
|
+
SELECT *
|
|
374
|
+
FROM workflow_runs
|
|
375
|
+
WHERE project_id = ?
|
|
376
|
+
AND execution_id IN (SELECT value FROM json_each(?))
|
|
377
|
+
`
|
|
378
|
+
)
|
|
379
|
+
.all(params.projectId, JSON.stringify(executionIds)) as WorkflowRunDatabaseRow[]
|
|
380
|
+
|
|
381
|
+
const byExecution = new Map(rows.map((row) => [row.execution_id, row]))
|
|
382
|
+
return executionIds.flatMap((executionId) => {
|
|
383
|
+
const row = byExecution.get(executionId)
|
|
384
|
+
return row ? [rowToWorkflowRunRecord(row)] : []
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
|
|
361
388
|
async list(input: ListWorkflowRunsInput): Promise<ListWorkflowRunsResult> {
|
|
362
389
|
if (hasEmptyStatuses(input) || input.workflowIds?.length === 0) {
|
|
363
390
|
return {
|