@sixb/sqlite 0.1.7 → 0.1.8
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/execution-storage.d.ts +3 -2
- package/dist/execution-storage.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1492 -380
- package/dist/index.js.map +16 -10
- package/dist/migrations.d.ts.map +1 -1
- package/dist/objects/index.d.ts +3 -0
- package/dist/objects/index.d.ts.map +1 -0
- package/dist/{object-query-compiler.d.ts → objects/query-compiler.d.ts} +16 -1
- package/dist/objects/query-compiler.d.ts.map +1 -0
- package/dist/objects/read-scope.d.ts +17 -0
- package/dist/objects/read-scope.d.ts.map +1 -0
- package/dist/objects/reader.d.ts +51 -0
- package/dist/objects/reader.d.ts.map +1 -0
- package/dist/objects/rows.d.ts +33 -0
- package/dist/objects/rows.d.ts.map +1 -0
- package/dist/objects/selected-reader.d.ts +9 -0
- package/dist/objects/selected-reader.d.ts.map +1 -0
- package/dist/{object-storage.d.ts → objects/storage.d.ts} +12 -9
- package/dist/objects/storage.d.ts.map +1 -0
- package/dist/share-grant-storage.d.ts +20 -0
- package/dist/share-grant-storage.d.ts.map +1 -0
- package/dist/share-session-storage.d.ts +19 -0
- package/dist/share-session-storage.d.ts.map +1 -0
- package/dist/storage-errors.d.ts +1 -0
- package/dist/storage-errors.d.ts.map +1 -1
- package/dist/transactions.d.ts +8 -0
- package/dist/transactions.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/execution-storage.ts +22 -3
- package/src/index.ts +18 -3
- package/src/migrations/035-share-grants.sql +66 -0
- package/src/migrations/036-share-sessions.sql +226 -0
- package/src/migrations.ts +4 -0
- package/src/objects/index.ts +2 -0
- package/src/{object-query-compiler.ts → objects/query-compiler.ts} +104 -54
- package/src/objects/read-scope.ts +316 -0
- package/src/objects/reader.ts +526 -0
- package/src/objects/rows.ts +123 -0
- package/src/objects/selected-reader.ts +119 -0
- package/src/objects/storage.ts +296 -0
- package/src/share-grant-storage.ts +252 -0
- package/src/share-session-storage.ts +189 -0
- package/src/storage-errors.ts +4 -0
- package/src/transactions.ts +32 -0
- package/dist/object-query-compiler.d.ts.map +0 -1
- package/dist/object-storage.d.ts.map +0 -1
- package/src/object-storage.ts +0 -709
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite"
|
|
2
|
+
import {
|
|
3
|
+
normalizeGetShareSessionByIdInput,
|
|
4
|
+
normalizeRenewShareSessionIfValidInput,
|
|
5
|
+
normalizeRevokeShareSessionInput,
|
|
6
|
+
normalizeShareSessionCreate,
|
|
7
|
+
parseShareSessionRecord,
|
|
8
|
+
} from "@sixb/core/internal/share-session-storage-provider"
|
|
9
|
+
import type {
|
|
10
|
+
CreateShareSessionInput,
|
|
11
|
+
GetShareSessionByIdInput,
|
|
12
|
+
RenewShareSessionIfValidInput,
|
|
13
|
+
RevokeShareSessionInput,
|
|
14
|
+
ShareSessionRecord,
|
|
15
|
+
ShareSessionStorage,
|
|
16
|
+
} from "@sixb/core/storage"
|
|
17
|
+
import { ShareSessionStorageError } from "@sixb/core/storage"
|
|
18
|
+
import { installFreshSqliteSchema } from "./migrations"
|
|
19
|
+
import { isForeignKeyConstraintError, isUniqueConstraintError } from "./storage-errors"
|
|
20
|
+
import {
|
|
21
|
+
closeSqliteStoreConnection,
|
|
22
|
+
openSqliteStoreConnection,
|
|
23
|
+
type SqliteStoreConnection,
|
|
24
|
+
} from "./transactions"
|
|
25
|
+
|
|
26
|
+
export interface SqliteShareSessionStorageOptions {
|
|
27
|
+
readonly path?: string
|
|
28
|
+
readonly connection?: SqliteStoreConnection
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** SQLite persistence for short-lived Share access sessions. */
|
|
32
|
+
export class SqliteShareSessionStorage implements ShareSessionStorage {
|
|
33
|
+
private readonly connection: SqliteStoreConnection
|
|
34
|
+
private readonly db: Database
|
|
35
|
+
|
|
36
|
+
constructor(options: SqliteShareSessionStorageOptions = {}) {
|
|
37
|
+
this.connection = openSqliteStoreConnection(options)
|
|
38
|
+
this.db = this.connection.db
|
|
39
|
+
if (this.connection.installFreshSchema) installFreshSqliteSchema(this.db)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async create(input: CreateShareSessionInput): Promise<ShareSessionRecord> {
|
|
43
|
+
const record = normalizeShareSessionCreate(input)
|
|
44
|
+
try {
|
|
45
|
+
const row = this.db
|
|
46
|
+
.query(
|
|
47
|
+
`
|
|
48
|
+
INSERT INTO share_sessions (
|
|
49
|
+
project_id, id, grant_id, token_hash, created_at, expires_at,
|
|
50
|
+
absolute_expires_at
|
|
51
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
52
|
+
RETURNING *
|
|
53
|
+
`
|
|
54
|
+
)
|
|
55
|
+
.get(
|
|
56
|
+
record.projectId,
|
|
57
|
+
record.id,
|
|
58
|
+
record.grantId,
|
|
59
|
+
record.tokenHash,
|
|
60
|
+
record.createdAt.toISOString(),
|
|
61
|
+
record.expiresAt.toISOString(),
|
|
62
|
+
record.absoluteExpiresAt.toISOString()
|
|
63
|
+
) as SqliteShareSessionRow | null
|
|
64
|
+
if (!row) throw invalidRecord(`Share session '${record.id}' disappeared after create.`)
|
|
65
|
+
return rowToRecord(row)
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (isUniqueConstraintError(error)) {
|
|
68
|
+
throw new ShareSessionStorageError(
|
|
69
|
+
"duplicate",
|
|
70
|
+
`[SixbSqlite] Share session '${record.id}' conflicts with an existing record.`,
|
|
71
|
+
{ cause: error }
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
if (isForeignKeyConstraintError(error)) {
|
|
75
|
+
throw new ShareSessionStorageError(
|
|
76
|
+
"invalid_input",
|
|
77
|
+
`[SixbSqlite] Share grant '${record.grantId}' does not exist in project '${record.projectId}'.`,
|
|
78
|
+
{ cause: error }
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
throw error
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getById(input: GetShareSessionByIdInput): Promise<ShareSessionRecord | null> {
|
|
86
|
+
const normalized = normalizeGetShareSessionByIdInput(input)
|
|
87
|
+
return this.getRow(normalized.projectId, normalized.id)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async renewIfValid(input: RenewShareSessionIfValidInput): Promise<ShareSessionRecord | null> {
|
|
91
|
+
const normalized = normalizeRenewShareSessionIfValidInput(input)
|
|
92
|
+
const requestedExpiry = normalized.expiresAt.toISOString()
|
|
93
|
+
const now = normalized.now.toISOString()
|
|
94
|
+
const row = this.db
|
|
95
|
+
.query(
|
|
96
|
+
`
|
|
97
|
+
UPDATE share_sessions
|
|
98
|
+
SET expires_at = CASE
|
|
99
|
+
WHEN ? > absolute_expires_at THEN absolute_expires_at
|
|
100
|
+
WHEN ? > expires_at THEN ?
|
|
101
|
+
ELSE expires_at
|
|
102
|
+
END
|
|
103
|
+
WHERE project_id = ?
|
|
104
|
+
AND id = ?
|
|
105
|
+
AND grant_id = ?
|
|
106
|
+
AND token_hash = ?
|
|
107
|
+
AND revoked_at IS NULL
|
|
108
|
+
AND created_at <= ?
|
|
109
|
+
AND expires_at > ?
|
|
110
|
+
AND absolute_expires_at > ?
|
|
111
|
+
RETURNING *
|
|
112
|
+
`
|
|
113
|
+
)
|
|
114
|
+
.get(
|
|
115
|
+
requestedExpiry,
|
|
116
|
+
requestedExpiry,
|
|
117
|
+
requestedExpiry,
|
|
118
|
+
normalized.projectId,
|
|
119
|
+
normalized.id,
|
|
120
|
+
normalized.grantId,
|
|
121
|
+
normalized.tokenHash,
|
|
122
|
+
now,
|
|
123
|
+
now,
|
|
124
|
+
now
|
|
125
|
+
) as SqliteShareSessionRow | null
|
|
126
|
+
return row ? rowToRecord(row) : null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async revoke(input: RevokeShareSessionInput): Promise<ShareSessionRecord | null> {
|
|
130
|
+
const normalized = normalizeRevokeShareSessionInput(input)
|
|
131
|
+
const current = this.getRow(normalized.projectId, normalized.id)
|
|
132
|
+
if (!current || current.revokedAt) return current
|
|
133
|
+
const revocation = normalizeRevokeShareSessionInput(normalized, current.createdAt)
|
|
134
|
+
const row = this.db
|
|
135
|
+
.query(
|
|
136
|
+
`
|
|
137
|
+
UPDATE share_sessions
|
|
138
|
+
SET revoked_at = ?
|
|
139
|
+
WHERE project_id = ? AND id = ? AND revoked_at IS NULL
|
|
140
|
+
RETURNING *
|
|
141
|
+
`
|
|
142
|
+
)
|
|
143
|
+
.get(
|
|
144
|
+
revocation.revokedAt.toISOString(),
|
|
145
|
+
revocation.projectId,
|
|
146
|
+
revocation.id
|
|
147
|
+
) as SqliteShareSessionRow | null
|
|
148
|
+
return row ? rowToRecord(row) : this.getRow(revocation.projectId, revocation.id)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
close(): void {
|
|
152
|
+
closeSqliteStoreConnection(this.connection)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private getRow(projectId: string, id: string): ShareSessionRecord | null {
|
|
156
|
+
const row = this.db
|
|
157
|
+
.query("SELECT * FROM share_sessions WHERE project_id = ? AND id = ?")
|
|
158
|
+
.get(projectId, id) as SqliteShareSessionRow | null
|
|
159
|
+
return row ? rowToRecord(row) : null
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface SqliteShareSessionRow {
|
|
164
|
+
readonly project_id: unknown
|
|
165
|
+
readonly id: unknown
|
|
166
|
+
readonly grant_id: unknown
|
|
167
|
+
readonly token_hash: unknown
|
|
168
|
+
readonly created_at: unknown
|
|
169
|
+
readonly expires_at: unknown
|
|
170
|
+
readonly absolute_expires_at: unknown
|
|
171
|
+
readonly revoked_at: unknown
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function rowToRecord(row: SqliteShareSessionRow): ShareSessionRecord {
|
|
175
|
+
return parseShareSessionRecord({
|
|
176
|
+
projectId: row.project_id,
|
|
177
|
+
id: row.id,
|
|
178
|
+
grantId: row.grant_id,
|
|
179
|
+
tokenHash: row.token_hash,
|
|
180
|
+
createdAt: row.created_at,
|
|
181
|
+
expiresAt: row.expires_at,
|
|
182
|
+
absoluteExpiresAt: row.absolute_expires_at,
|
|
183
|
+
...(row.revoked_at === null ? {} : { revokedAt: row.revoked_at }),
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function invalidRecord(message: string): ShareSessionStorageError {
|
|
188
|
+
return new ShareSessionStorageError("invalid_record", `[SixbSqlite] ${message}`)
|
|
189
|
+
}
|
package/src/storage-errors.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export function isUniqueConstraintError(error: unknown): boolean {
|
|
2
2
|
return error instanceof Error && error.message.includes("UNIQUE constraint failed")
|
|
3
3
|
}
|
|
4
|
+
|
|
5
|
+
export function isForeignKeyConstraintError(error: unknown): boolean {
|
|
6
|
+
return error instanceof Error && error.message.includes("FOREIGN KEY constraint failed")
|
|
7
|
+
}
|
package/src/transactions.ts
CHANGED
|
@@ -45,6 +45,7 @@ export function closeSqliteStoreConnection(connection: SqliteStoreConnection): v
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const activeImmediateTransactions = new WeakSet<Database>()
|
|
48
|
+
const activeDeferredReadTransactions = new WeakSet<Database>()
|
|
48
49
|
|
|
49
50
|
export function runImmediateTransaction<T>(db: Database, run: () => T): T {
|
|
50
51
|
if (activeImmediateTransactions.has(db)) {
|
|
@@ -94,6 +95,37 @@ export async function runImmediateTransactionAsync<T>(
|
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Run a multi-statement read against one proven SQLite snapshot.
|
|
100
|
+
*
|
|
101
|
+
* A provider-owned immediate transaction already has a stable snapshot and may be reused. Any
|
|
102
|
+
* other pre-existing transaction is rejected because this provider cannot prove who owns it or
|
|
103
|
+
* which lifecycle will close it.
|
|
104
|
+
*/
|
|
105
|
+
export function runDeferredReadTransaction<T>(db: Database, run: () => T): T {
|
|
106
|
+
if (activeImmediateTransactions.has(db) || activeDeferredReadTransactions.has(db)) {
|
|
107
|
+
return run()
|
|
108
|
+
}
|
|
109
|
+
if (db.inTransaction) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
"[SixbSqlite] Selected object reads cannot join an unverified SQLite transaction."
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
db.run("BEGIN DEFERRED")
|
|
116
|
+
activeDeferredReadTransactions.add(db)
|
|
117
|
+
try {
|
|
118
|
+
const result = run()
|
|
119
|
+
db.run("COMMIT")
|
|
120
|
+
return result
|
|
121
|
+
} catch (error) {
|
|
122
|
+
rollbackQuietly(db)
|
|
123
|
+
throw error
|
|
124
|
+
} finally {
|
|
125
|
+
activeDeferredReadTransactions.delete(db)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
97
129
|
function rollbackQuietly(db: Database): void {
|
|
98
130
|
try {
|
|
99
131
|
db.run("ROLLBACK")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"object-query-compiler.d.ts","sourceRoot":"","sources":["../src/object-query-compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAKjB,MAAM,YAAY,CAAA;AAEnB,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;AAEnE,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,WAAW,EAAE,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,KAAK,EAAE,aAAa,CAAA;IACpB,YAAY,CAAC,EAAE,oBAAoB,CAAA;IACnC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAClD,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,CAAA;IAC7C,aAAa,CAAC,IAAI,EAAE,SAAS,wBAAwB,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAC/F;AAED,UAAU,oBAAoB;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,WAAW,EAAE,CAAA;IACnB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;CACnC;AAWD,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,WAAW,EAAE,CAAA;IACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACrC,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,KAAK,kBAAkB,GACnB;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B,GACD;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,gBAAgB,GAAG,YAAY,CAAA;IACvC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B,CAAA;AAqBL,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,mBAAmB,CAGrB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"object-storage.d.ts","sourceRoot":"","sources":["../src/object-storage.ts"],"names":[],"mappings":"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"}
|