@pikku/kysely-sqlite 0.12.4 → 0.12.6

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 (37) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/src/create-sqlite-kysely.js +1 -1
  3. package/dist/src/index.d.ts +2 -0
  4. package/dist/src/index.js +1 -0
  5. package/dist/src/libsql-web-dialect.d.ts +33 -0
  6. package/dist/src/libsql-web-dialect.js +175 -0
  7. package/dist/tsconfig.tsbuildinfo +1 -0
  8. package/package.json +9 -6
  9. package/src/create-sqlite-kysely.ts +12 -0
  10. package/{dist/index.d.ts → src/index.ts} +16 -12
  11. package/src/libsql-web-dialect.ts +250 -0
  12. package/src/sqlite-kysely-agent-run-service.ts +3 -0
  13. package/src/sqlite-kysely-ai-storage-service.ts +3 -0
  14. package/src/sqlite-kysely-channel-store.ts +3 -0
  15. package/src/sqlite-kysely-deployment-service.ts +3 -0
  16. package/src/sqlite-kysely-eventhub-store.ts +3 -0
  17. package/src/sqlite-kysely-secret-service.ts +3 -0
  18. package/src/sqlite-kysely-workflow-run-service.ts +3 -0
  19. package/src/sqlite-kysely-workflow-service.ts +3 -0
  20. package/tsconfig.json +12 -0
  21. package/dist/index.js +0 -19
  22. package/dist/sqlite-kysely-agent-run-service.d.ts +0 -3
  23. package/dist/sqlite-kysely-agent-run-service.js +0 -27
  24. package/dist/sqlite-kysely-ai-storage-service.d.ts +0 -3
  25. package/dist/sqlite-kysely-ai-storage-service.js +0 -27
  26. package/dist/sqlite-kysely-channel-store.d.ts +0 -3
  27. package/dist/sqlite-kysely-channel-store.js +0 -27
  28. package/dist/sqlite-kysely-deployment-service.d.ts +0 -3
  29. package/dist/sqlite-kysely-deployment-service.js +0 -27
  30. package/dist/sqlite-kysely-eventhub-store.d.ts +0 -3
  31. package/dist/sqlite-kysely-eventhub-store.js +0 -27
  32. package/dist/sqlite-kysely-secret-service.d.ts +0 -3
  33. package/dist/sqlite-kysely-secret-service.js +0 -27
  34. package/dist/sqlite-kysely-workflow-run-service.d.ts +0 -3
  35. package/dist/sqlite-kysely-workflow-run-service.js +0 -27
  36. package/dist/sqlite-kysely-workflow-service.d.ts +0 -3
  37. package/dist/sqlite-kysely-workflow-service.js +0 -27
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @pikku/kysely-sqlite
2
2
 
3
+ ## 0.12.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 34f254e: Bump the `kysely` dependency range to `^0.29.0` so it dedupes onto a single
8
+ copy alongside Better Auth (which bundles kysely 0.29.x), avoiding two
9
+ incompatible `Kysely` classes (the `#private` brand mismatch) when both pikku's
10
+ adapters and Better Auth share a database connection.
11
+
12
+ kysely 0.29 is ESM-only, which the unmaintained `kysely-plugin-serialize`
13
+ (no `exports` map, CommonJS build) cannot import. Its `SerializePlugin` is now
14
+ maintained directly in `@pikku/kysely` and re-exported, and the external
15
+ dependency is dropped from `@pikku/kysely`, `@pikku/kysely-sqlite`, and
16
+ `@pikku/cloudflare`.
17
+
18
+ - Updated dependencies [6565b97]
19
+ - Updated dependencies [34f254e]
20
+ - @pikku/kysely@0.12.16
21
+
22
+ ## 0.12.5
23
+
24
+ ### Patch Changes
25
+
26
+ - 9060165: New `@pikku/kysely-node-sqlite` provides a Kysely dialect and migrator for Node's built-in `node:sqlite`. `@pikku/kysely-sqlite` adds a `LibsqlWebDialect` for running Kysely against Cloudflare Workers and Turso databases over HTTP.
27
+ - Updated dependencies [9060165]
28
+ - Updated dependencies [9060165]
29
+ - Updated dependencies [9060165]
30
+ - @pikku/core@0.12.21
31
+
3
32
  ## 0.12.4
4
33
 
5
34
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  import { Kysely, SqliteDialect } from 'kysely';
2
- import { SerializePlugin } from 'kysely-plugin-serialize';
2
+ import { SerializePlugin } from '@pikku/kysely';
3
3
  export function createSQLiteKysely(database) {
4
4
  return new Kysely({
5
5
  dialect: new SqliteDialect({ database }),
@@ -7,6 +7,8 @@ export { SQLiteKyselyWorkflowRunService } from './sqlite-kysely-workflow-run-ser
7
7
  export { SQLiteKyselyChannelStore } from './sqlite-kysely-channel-store.js';
8
8
  export { SQLiteKyselyEventHubStore } from './sqlite-kysely-eventhub-store.js';
9
9
  export { SQLiteKyselySecretService } from './sqlite-kysely-secret-service.js';
10
+ export { LibsqlWebDialect } from './libsql-web-dialect.js';
11
+ export type { LibsqlWebDialectConfig } from './libsql-web-dialect.js';
10
12
  export type { KyselyPikkuDB } from '@pikku/kysely';
11
13
  export type { KyselySecretServiceConfig } from '@pikku/kysely';
12
14
  export type { WorkflowRunService } from '@pikku/core/workflow';
package/dist/src/index.js CHANGED
@@ -7,3 +7,4 @@ export { SQLiteKyselyWorkflowRunService } from './sqlite-kysely-workflow-run-ser
7
7
  export { SQLiteKyselyChannelStore } from './sqlite-kysely-channel-store.js';
8
8
  export { SQLiteKyselyEventHubStore } from './sqlite-kysely-eventhub-store.js';
9
9
  export { SQLiteKyselySecretService } from './sqlite-kysely-secret-service.js';
10
+ export { LibsqlWebDialect } from './libsql-web-dialect.js';
@@ -0,0 +1,33 @@
1
+ import { type Dialect, type Driver, type Kysely, type DatabaseIntrospector, type DialectAdapter, type QueryCompiler } from 'kysely';
2
+ /**
3
+ * Kysely dialect for libsql over the *HTTP pipeline* transport (v2/pipeline).
4
+ *
5
+ * Why this file exists at all:
6
+ * - @libsql/kysely-libsql imports @libsql/client (Node), which uses node:http.
7
+ * CF Workers nodejs_compat_v2 doesn't ship node:http -> upload error 10021.
8
+ * - @libsql/client/web imports both ./http.js and ./ws.js at module top, and
9
+ * ./ws.js pulls in `ws` which does `require('node:events')` at load time.
10
+ * CF Workers also doesn't ship node:events -> upload error 10021.
11
+ * - @libsql/client/http re-uses @libsql/hrana-client's index which still
12
+ * imports ws transitively for the same reason.
13
+ *
14
+ * So we talk to the libsql/Turso HTTP pipeline directly with fetch. Single
15
+ * endpoint, single round-trip per execute. Transactions use the `baton`
16
+ * mechanism: every response returns a baton, and resending it on the next
17
+ * request keeps the same server-side stream (== same SQL connection ==
18
+ * same transaction).
19
+ *
20
+ * Pipeline reference: https://github.com/tursodatabase/libsql/blob/main/docs/HTTP_V2_SPEC.md
21
+ */
22
+ export interface LibsqlWebDialectConfig {
23
+ url: string;
24
+ authToken?: string;
25
+ }
26
+ export declare class LibsqlWebDialect implements Dialect {
27
+ private readonly config;
28
+ constructor(config: LibsqlWebDialectConfig);
29
+ createAdapter(): DialectAdapter;
30
+ createDriver(): Driver;
31
+ createQueryCompiler(): QueryCompiler;
32
+ createIntrospector(db: Kysely<unknown>): DatabaseIntrospector;
33
+ }
@@ -0,0 +1,175 @@
1
+ import { SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler, } from 'kysely';
2
+ export class LibsqlWebDialect {
3
+ config;
4
+ constructor(config) {
5
+ this.config = config;
6
+ }
7
+ createAdapter() {
8
+ return new SqliteAdapter();
9
+ }
10
+ createDriver() {
11
+ return new LibsqlWebDriver(this.config);
12
+ }
13
+ createQueryCompiler() {
14
+ return new SqliteQueryCompiler();
15
+ }
16
+ createIntrospector(db) {
17
+ return new SqliteIntrospector(db);
18
+ }
19
+ }
20
+ class LibsqlWebDriver {
21
+ endpoint;
22
+ authHeader;
23
+ constructor(config) {
24
+ // Accept libsql://, https://, http://. The pipeline is HTTP only.
25
+ // Turso embeds the JWT in the URL as ?authToken=... — honor that, but let
26
+ // an explicit config.authToken win.
27
+ const u = new URL(config.url);
28
+ const scheme = u.protocol === 'libsql:' ? 'https:' : u.protocol;
29
+ const tokenFromUrl = u.searchParams.get('authToken') ?? undefined;
30
+ this.endpoint = `${scheme}//${u.host}/v2/pipeline`;
31
+ const token = config.authToken ?? tokenFromUrl;
32
+ this.authHeader = token ? `Bearer ${token}` : undefined;
33
+ }
34
+ async init() { }
35
+ async acquireConnection() {
36
+ return new LibsqlWebConnection(this.endpoint, this.authHeader);
37
+ }
38
+ async beginTransaction(conn) {
39
+ await conn.executeRaw('BEGIN');
40
+ }
41
+ async commitTransaction(conn) {
42
+ await conn.executeRaw('COMMIT');
43
+ }
44
+ async rollbackTransaction(conn) {
45
+ await conn.executeRaw('ROLLBACK');
46
+ }
47
+ async releaseConnection(conn) {
48
+ await conn.close();
49
+ }
50
+ async destroy() { }
51
+ }
52
+ class LibsqlWebConnection {
53
+ authHeader;
54
+ baton = null;
55
+ endpoint;
56
+ constructor(initialEndpoint, authHeader) {
57
+ this.authHeader = authHeader;
58
+ this.endpoint = initialEndpoint;
59
+ }
60
+ async executeQuery(query) {
61
+ const result = await this.runStmt(query.sql, query.parameters);
62
+ return decodeResult(result);
63
+ }
64
+ async *streamQuery(query) {
65
+ yield this.executeQuery(query);
66
+ }
67
+ async executeRaw(sql) {
68
+ await this.runStmt(sql, []);
69
+ }
70
+ async close() {
71
+ if (this.baton === null)
72
+ return;
73
+ await this.send([{ type: 'close' }]);
74
+ this.baton = null;
75
+ }
76
+ async runStmt(sql, args) {
77
+ const resp = await this.send([
78
+ {
79
+ type: 'execute',
80
+ stmt: { sql, args: args.map(encodeArg) },
81
+ },
82
+ ]);
83
+ const r = resp.results[0];
84
+ if (!r)
85
+ throw new Error('libsql: empty pipeline response');
86
+ if (r.type === 'error')
87
+ throw new Error(`libsql: ${r.error.message}${r.error.code ? ` (${r.error.code})` : ''}`);
88
+ if (r.response.type !== 'execute')
89
+ throw new Error(`libsql: unexpected response type ${r.response.type}`);
90
+ return r.response.result;
91
+ }
92
+ async send(requests) {
93
+ const headers = {
94
+ 'content-type': 'application/json',
95
+ };
96
+ if (this.authHeader)
97
+ headers.authorization = this.authHeader;
98
+ const res = await fetch(this.endpoint, {
99
+ method: 'POST',
100
+ headers,
101
+ body: JSON.stringify({ baton: this.baton, requests }),
102
+ });
103
+ if (!res.ok) {
104
+ const body = await res.text().catch(() => '');
105
+ throw new Error(`libsql HTTP ${res.status}: ${body}`);
106
+ }
107
+ const json = (await res.json());
108
+ this.baton = json.baton;
109
+ if (json.base_url)
110
+ this.endpoint = `${json.base_url.replace(/\/$/, '')}/v2/pipeline`;
111
+ return json;
112
+ }
113
+ }
114
+ function encodeArg(v) {
115
+ if (v === null || v === undefined)
116
+ return { type: 'null' };
117
+ if (typeof v === 'string')
118
+ return { type: 'text', value: v };
119
+ if (typeof v === 'number')
120
+ return Number.isInteger(v)
121
+ ? { type: 'integer', value: String(v) }
122
+ : { type: 'float', value: v };
123
+ if (typeof v === 'bigint')
124
+ return { type: 'integer', value: v.toString() };
125
+ if (typeof v === 'boolean')
126
+ return { type: 'integer', value: v ? '1' : '0' };
127
+ if (v instanceof ArrayBuffer)
128
+ return { type: 'blob', base64: bytesToBase64(new Uint8Array(v)) };
129
+ if (v instanceof Uint8Array)
130
+ return { type: 'blob', base64: bytesToBase64(v) };
131
+ throw new Error(`libsql: unsupported argument type ${typeof v}`);
132
+ }
133
+ function decodeValue(v) {
134
+ switch (v.type) {
135
+ case 'null':
136
+ return null;
137
+ case 'integer': {
138
+ const n = Number(v.value);
139
+ return Number.isSafeInteger(n) ? n : BigInt(v.value);
140
+ }
141
+ case 'float':
142
+ return v.value;
143
+ case 'text':
144
+ return v.value;
145
+ case 'blob':
146
+ return base64ToBytes(v.base64);
147
+ }
148
+ }
149
+ function decodeResult(r) {
150
+ const colNames = r.cols.map((c, i) => c.name ?? `c${i}`);
151
+ const rows = r.rows.map((row) => {
152
+ const o = {};
153
+ for (let i = 0; i < colNames.length; i++)
154
+ o[colNames[i]] = decodeValue(row[i]);
155
+ return o;
156
+ });
157
+ return {
158
+ rows,
159
+ numAffectedRows: BigInt(r.affected_row_count),
160
+ insertId: r.last_insert_rowid !== null ? BigInt(r.last_insert_rowid) : undefined,
161
+ };
162
+ }
163
+ function bytesToBase64(b) {
164
+ let s = '';
165
+ for (let i = 0; i < b.length; i++)
166
+ s += String.fromCharCode(b[i]);
167
+ return btoa(s);
168
+ }
169
+ function base64ToBytes(s) {
170
+ const bin = atob(s);
171
+ const out = new Uint8Array(bin.length);
172
+ for (let i = 0; i < bin.length; i++)
173
+ out[i] = bin.charCodeAt(i);
174
+ return out;
175
+ }
@@ -0,0 +1 @@
1
+ {"root":["../src/create-sqlite-kysely.ts","../src/index.ts","../src/libsql-web-dialect.ts","../src/sqlite-kysely-agent-run-service.ts","../src/sqlite-kysely-ai-storage-service.ts","../src/sqlite-kysely-channel-store.ts","../src/sqlite-kysely-deployment-service.ts","../src/sqlite-kysely-eventhub-store.ts","../src/sqlite-kysely-secret-service.ts","../src/sqlite-kysely-workflow-run-service.ts","../src/sqlite-kysely-workflow-service.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/kysely-sqlite",
3
- "version": "0.12.4",
3
+ "version": "0.12.6",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/src/index.js",
@@ -9,15 +9,18 @@
9
9
  "scripts": {
10
10
  "tsc": "tsc",
11
11
  "ncu": "npx npm-check-updates",
12
- "build": "tsc -b"
12
+ "build": "tsc -b",
13
+ "prepublishOnly": "yarn build"
13
14
  },
14
15
  "dependencies": {
15
- "@pikku/core": "^0.12.0",
16
- "@pikku/kysely": "^0.12.0",
17
- "kysely": "^0.28.11",
18
- "kysely-plugin-serialize": "^0.8.2"
16
+ "@pikku/core": "^0.12.21",
17
+ "@pikku/kysely": "^0.12.16",
18
+ "kysely": "^0.29.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "typescript": "^5.9"
22
+ },
23
+ "exports": {
24
+ ".": "./dist/src/index.js"
22
25
  }
23
26
  }
@@ -0,0 +1,12 @@
1
+ import { Kysely, SqliteDialect, type SqliteDatabase } from 'kysely'
2
+ import { SerializePlugin } from '@pikku/kysely'
3
+ import type { KyselyPikkuDB } from '@pikku/kysely'
4
+
5
+ export function createSQLiteKysely(
6
+ database: SqliteDatabase | (() => Promise<SqliteDatabase>)
7
+ ): Kysely<KyselyPikkuDB> {
8
+ return new Kysely<KyselyPikkuDB>({
9
+ dialect: new SqliteDialect({ database }),
10
+ plugins: [new SerializePlugin()],
11
+ })
12
+ }
@@ -1,12 +1,16 @@
1
- export { SQLiteKyselyWorkflowService } from './sqlite-kysely-workflow-service.js';
2
- export { SQLiteKyselyDeploymentService } from './sqlite-kysely-deployment-service.js';
3
- export { SQLiteKyselyAIStorageService } from './sqlite-kysely-ai-storage-service.js';
4
- export { SQLiteKyselyAgentRunService } from './sqlite-kysely-agent-run-service.js';
5
- export { SQLiteKyselyWorkflowRunService } from './sqlite-kysely-workflow-run-service.js';
6
- export { SQLiteKyselyChannelStore } from './sqlite-kysely-channel-store.js';
7
- export { SQLiteKyselyEventHubStore } from './sqlite-kysely-eventhub-store.js';
8
- export { SQLiteKyselySecretService } from './sqlite-kysely-secret-service.js';
9
- export type { KyselyPikkuDB } from '@pikku/kysely';
10
- export type { KyselySecretServiceConfig } from '@pikku/kysely';
11
- export type { WorkflowRunService } from '@pikku/core/workflow';
12
- export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent';
1
+ export { createSQLiteKysely } from './create-sqlite-kysely.js'
2
+ export { SQLiteKyselyWorkflowService } from './sqlite-kysely-workflow-service.js'
3
+ export { SQLiteKyselyDeploymentService } from './sqlite-kysely-deployment-service.js'
4
+ export { SQLiteKyselyAIStorageService } from './sqlite-kysely-ai-storage-service.js'
5
+ export { SQLiteKyselyAgentRunService } from './sqlite-kysely-agent-run-service.js'
6
+ export { SQLiteKyselyWorkflowRunService } from './sqlite-kysely-workflow-run-service.js'
7
+ export { SQLiteKyselyChannelStore } from './sqlite-kysely-channel-store.js'
8
+ export { SQLiteKyselyEventHubStore } from './sqlite-kysely-eventhub-store.js'
9
+ export { SQLiteKyselySecretService } from './sqlite-kysely-secret-service.js'
10
+ export { LibsqlWebDialect } from './libsql-web-dialect.js'
11
+ export type { LibsqlWebDialectConfig } from './libsql-web-dialect.js'
12
+
13
+ export type { KyselyPikkuDB } from '@pikku/kysely'
14
+ export type { KyselySecretServiceConfig } from '@pikku/kysely'
15
+ export type { WorkflowRunService } from '@pikku/core/workflow'
16
+ export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent'
@@ -0,0 +1,250 @@
1
+ import {
2
+ SqliteAdapter,
3
+ SqliteIntrospector,
4
+ SqliteQueryCompiler,
5
+ type DatabaseConnection,
6
+ type Dialect,
7
+ type Driver,
8
+ type CompiledQuery,
9
+ type QueryResult,
10
+ type Kysely,
11
+ type DatabaseIntrospector,
12
+ type DialectAdapter,
13
+ type QueryCompiler,
14
+ } from 'kysely'
15
+
16
+ /**
17
+ * Kysely dialect for libsql over the *HTTP pipeline* transport (v2/pipeline).
18
+ *
19
+ * Why this file exists at all:
20
+ * - @libsql/kysely-libsql imports @libsql/client (Node), which uses node:http.
21
+ * CF Workers nodejs_compat_v2 doesn't ship node:http -> upload error 10021.
22
+ * - @libsql/client/web imports both ./http.js and ./ws.js at module top, and
23
+ * ./ws.js pulls in `ws` which does `require('node:events')` at load time.
24
+ * CF Workers also doesn't ship node:events -> upload error 10021.
25
+ * - @libsql/client/http re-uses @libsql/hrana-client's index which still
26
+ * imports ws transitively for the same reason.
27
+ *
28
+ * So we talk to the libsql/Turso HTTP pipeline directly with fetch. Single
29
+ * endpoint, single round-trip per execute. Transactions use the `baton`
30
+ * mechanism: every response returns a baton, and resending it on the next
31
+ * request keeps the same server-side stream (== same SQL connection ==
32
+ * same transaction).
33
+ *
34
+ * Pipeline reference: https://github.com/tursodatabase/libsql/blob/main/docs/HTTP_V2_SPEC.md
35
+ */
36
+ export interface LibsqlWebDialectConfig {
37
+ url: string
38
+ authToken?: string
39
+ }
40
+
41
+ export class LibsqlWebDialect implements Dialect {
42
+ constructor(private readonly config: LibsqlWebDialectConfig) {}
43
+ createAdapter(): DialectAdapter {
44
+ return new SqliteAdapter()
45
+ }
46
+ createDriver(): Driver {
47
+ return new LibsqlWebDriver(this.config)
48
+ }
49
+ createQueryCompiler(): QueryCompiler {
50
+ return new SqliteQueryCompiler()
51
+ }
52
+ createIntrospector(db: Kysely<unknown>): DatabaseIntrospector {
53
+ return new SqliteIntrospector(db)
54
+ }
55
+ }
56
+
57
+ type HranaValue =
58
+ | { type: 'null' }
59
+ | { type: 'integer'; value: string }
60
+ | { type: 'float'; value: number }
61
+ | { type: 'text'; value: string }
62
+ | { type: 'blob'; base64: string }
63
+
64
+ interface HranaStmtResult {
65
+ cols: Array<{ name: string | null; decltype: string | null }>
66
+ rows: HranaValue[][]
67
+ affected_row_count: number
68
+ last_insert_rowid: string | null
69
+ }
70
+
71
+ interface PipelineResponse {
72
+ baton: string | null
73
+ base_url: string | null
74
+ results: Array<
75
+ | {
76
+ type: 'ok'
77
+ response:
78
+ | { type: 'execute'; result: HranaStmtResult }
79
+ | { type: 'close' }
80
+ }
81
+ | { type: 'error'; error: { message: string; code?: string } }
82
+ >
83
+ }
84
+
85
+ class LibsqlWebDriver implements Driver {
86
+ private readonly endpoint: string
87
+ private readonly authHeader: string | undefined
88
+ constructor(config: LibsqlWebDialectConfig) {
89
+ // Accept libsql://, https://, http://. The pipeline is HTTP only.
90
+ // Turso embeds the JWT in the URL as ?authToken=... — honor that, but let
91
+ // an explicit config.authToken win.
92
+ const u = new URL(config.url)
93
+ const scheme = u.protocol === 'libsql:' ? 'https:' : u.protocol
94
+ const tokenFromUrl = u.searchParams.get('authToken') ?? undefined
95
+ this.endpoint = `${scheme}//${u.host}/v2/pipeline`
96
+ const token = config.authToken ?? tokenFromUrl
97
+ this.authHeader = token ? `Bearer ${token}` : undefined
98
+ }
99
+ async init(): Promise<void> {}
100
+ async acquireConnection(): Promise<DatabaseConnection> {
101
+ return new LibsqlWebConnection(this.endpoint, this.authHeader)
102
+ }
103
+ async beginTransaction(conn: DatabaseConnection): Promise<void> {
104
+ await (conn as LibsqlWebConnection).executeRaw('BEGIN')
105
+ }
106
+ async commitTransaction(conn: DatabaseConnection): Promise<void> {
107
+ await (conn as LibsqlWebConnection).executeRaw('COMMIT')
108
+ }
109
+ async rollbackTransaction(conn: DatabaseConnection): Promise<void> {
110
+ await (conn as LibsqlWebConnection).executeRaw('ROLLBACK')
111
+ }
112
+ async releaseConnection(conn: DatabaseConnection): Promise<void> {
113
+ await (conn as LibsqlWebConnection).close()
114
+ }
115
+ async destroy(): Promise<void> {}
116
+ }
117
+
118
+ class LibsqlWebConnection implements DatabaseConnection {
119
+ private baton: string | null = null
120
+ private endpoint: string
121
+ constructor(
122
+ initialEndpoint: string,
123
+ private readonly authHeader: string | undefined
124
+ ) {
125
+ this.endpoint = initialEndpoint
126
+ }
127
+
128
+ async executeQuery<R>(query: CompiledQuery): Promise<QueryResult<R>> {
129
+ const result = await this.runStmt(query.sql, query.parameters)
130
+ return decodeResult<R>(result)
131
+ }
132
+
133
+ async *streamQuery<R>(
134
+ query: CompiledQuery
135
+ ): AsyncIterableIterator<QueryResult<R>> {
136
+ yield this.executeQuery<R>(query)
137
+ }
138
+
139
+ async executeRaw(sql: string): Promise<void> {
140
+ await this.runStmt(sql, [])
141
+ }
142
+
143
+ async close(): Promise<void> {
144
+ if (this.baton === null) return
145
+ await this.send([{ type: 'close' }])
146
+ this.baton = null
147
+ }
148
+
149
+ private async runStmt(
150
+ sql: string,
151
+ args: readonly unknown[]
152
+ ): Promise<HranaStmtResult> {
153
+ const resp = await this.send([
154
+ {
155
+ type: 'execute',
156
+ stmt: { sql, args: args.map(encodeArg) },
157
+ },
158
+ ])
159
+ const r = resp.results[0]
160
+ if (!r) throw new Error('libsql: empty pipeline response')
161
+ if (r.type === 'error')
162
+ throw new Error(
163
+ `libsql: ${r.error.message}${r.error.code ? ` (${r.error.code})` : ''}`
164
+ )
165
+ if (r.response.type !== 'execute')
166
+ throw new Error(`libsql: unexpected response type ${r.response.type}`)
167
+ return r.response.result
168
+ }
169
+
170
+ private async send(requests: unknown[]): Promise<PipelineResponse> {
171
+ const headers: Record<string, string> = {
172
+ 'content-type': 'application/json',
173
+ }
174
+ if (this.authHeader) headers.authorization = this.authHeader
175
+ const res = await fetch(this.endpoint, {
176
+ method: 'POST',
177
+ headers,
178
+ body: JSON.stringify({ baton: this.baton, requests }),
179
+ })
180
+ if (!res.ok) {
181
+ const body = await res.text().catch(() => '')
182
+ throw new Error(`libsql HTTP ${res.status}: ${body}`)
183
+ }
184
+ const json = (await res.json()) as PipelineResponse
185
+ this.baton = json.baton
186
+ if (json.base_url)
187
+ this.endpoint = `${json.base_url.replace(/\/$/, '')}/v2/pipeline`
188
+ return json
189
+ }
190
+ }
191
+
192
+ function encodeArg(v: unknown): HranaValue {
193
+ if (v === null || v === undefined) return { type: 'null' }
194
+ if (typeof v === 'string') return { type: 'text', value: v }
195
+ if (typeof v === 'number')
196
+ return Number.isInteger(v)
197
+ ? { type: 'integer', value: String(v) }
198
+ : { type: 'float', value: v }
199
+ if (typeof v === 'bigint') return { type: 'integer', value: v.toString() }
200
+ if (typeof v === 'boolean') return { type: 'integer', value: v ? '1' : '0' }
201
+ if (v instanceof ArrayBuffer)
202
+ return { type: 'blob', base64: bytesToBase64(new Uint8Array(v)) }
203
+ if (v instanceof Uint8Array) return { type: 'blob', base64: bytesToBase64(v) }
204
+ throw new Error(`libsql: unsupported argument type ${typeof v}`)
205
+ }
206
+
207
+ function decodeValue(v: HranaValue): unknown {
208
+ switch (v.type) {
209
+ case 'null':
210
+ return null
211
+ case 'integer': {
212
+ const n = Number(v.value)
213
+ return Number.isSafeInteger(n) ? n : BigInt(v.value)
214
+ }
215
+ case 'float':
216
+ return v.value
217
+ case 'text':
218
+ return v.value
219
+ case 'blob':
220
+ return base64ToBytes(v.base64)
221
+ }
222
+ }
223
+
224
+ function decodeResult<R>(r: HranaStmtResult): QueryResult<R> {
225
+ const colNames = r.cols.map((c, i) => c.name ?? `c${i}`)
226
+ const rows = r.rows.map((row) => {
227
+ const o: Record<string, unknown> = {}
228
+ for (let i = 0; i < colNames.length; i++)
229
+ o[colNames[i]!] = decodeValue(row[i]!)
230
+ return o as R
231
+ })
232
+ return {
233
+ rows,
234
+ numAffectedRows: BigInt(r.affected_row_count),
235
+ insertId:
236
+ r.last_insert_rowid !== null ? BigInt(r.last_insert_rowid) : undefined,
237
+ }
238
+ }
239
+
240
+ function bytesToBase64(b: Uint8Array): string {
241
+ let s = ''
242
+ for (let i = 0; i < b.length; i++) s += String.fromCharCode(b[i]!)
243
+ return btoa(s)
244
+ }
245
+ function base64ToBytes(s: string): Uint8Array {
246
+ const bin = atob(s)
247
+ const out = new Uint8Array(bin.length)
248
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)
249
+ return out
250
+ }
@@ -0,0 +1,3 @@
1
+ import { KyselyAgentRunService } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyAgentRunService extends KyselyAgentRunService {}
@@ -0,0 +1,3 @@
1
+ import { KyselyAIStorageService } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyAIStorageService extends KyselyAIStorageService {}
@@ -0,0 +1,3 @@
1
+ import { KyselyChannelStore } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyChannelStore extends KyselyChannelStore {}
@@ -0,0 +1,3 @@
1
+ import { KyselyDeploymentService } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyDeploymentService extends KyselyDeploymentService {}
@@ -0,0 +1,3 @@
1
+ import { KyselyEventHubStore } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyEventHubStore extends KyselyEventHubStore {}
@@ -0,0 +1,3 @@
1
+ import { KyselySecretService } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselySecretService extends KyselySecretService {}
@@ -0,0 +1,3 @@
1
+ import { KyselyWorkflowRunService } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyWorkflowRunService extends KyselyWorkflowRunService {}
@@ -0,0 +1,3 @@
1
+ import { KyselyWorkflowService } from '@pikku/kysely'
2
+
3
+ export class SQLiteKyselyWorkflowService extends KyselyWorkflowService {}
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "module": "Node18",
6
+ "outDir": "dist",
7
+ "target": "esnext",
8
+ "declaration": true
9
+ },
10
+ "include": ["src/**/*.ts"],
11
+ "exclude": ["**/*.test.ts", "node_modules"]
12
+ }
package/dist/index.js DELETED
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SQLiteKyselySecretService = exports.SQLiteKyselyEventHubStore = exports.SQLiteKyselyChannelStore = exports.SQLiteKyselyWorkflowRunService = exports.SQLiteKyselyAgentRunService = exports.SQLiteKyselyAIStorageService = exports.SQLiteKyselyDeploymentService = exports.SQLiteKyselyWorkflowService = void 0;
4
- var sqlite_kysely_workflow_service_js_1 = require("./sqlite-kysely-workflow-service.js");
5
- Object.defineProperty(exports, "SQLiteKyselyWorkflowService", { enumerable: true, get: function () { return sqlite_kysely_workflow_service_js_1.SQLiteKyselyWorkflowService; } });
6
- var sqlite_kysely_deployment_service_js_1 = require("./sqlite-kysely-deployment-service.js");
7
- Object.defineProperty(exports, "SQLiteKyselyDeploymentService", { enumerable: true, get: function () { return sqlite_kysely_deployment_service_js_1.SQLiteKyselyDeploymentService; } });
8
- var sqlite_kysely_ai_storage_service_js_1 = require("./sqlite-kysely-ai-storage-service.js");
9
- Object.defineProperty(exports, "SQLiteKyselyAIStorageService", { enumerable: true, get: function () { return sqlite_kysely_ai_storage_service_js_1.SQLiteKyselyAIStorageService; } });
10
- var sqlite_kysely_agent_run_service_js_1 = require("./sqlite-kysely-agent-run-service.js");
11
- Object.defineProperty(exports, "SQLiteKyselyAgentRunService", { enumerable: true, get: function () { return sqlite_kysely_agent_run_service_js_1.SQLiteKyselyAgentRunService; } });
12
- var sqlite_kysely_workflow_run_service_js_1 = require("./sqlite-kysely-workflow-run-service.js");
13
- Object.defineProperty(exports, "SQLiteKyselyWorkflowRunService", { enumerable: true, get: function () { return sqlite_kysely_workflow_run_service_js_1.SQLiteKyselyWorkflowRunService; } });
14
- var sqlite_kysely_channel_store_js_1 = require("./sqlite-kysely-channel-store.js");
15
- Object.defineProperty(exports, "SQLiteKyselyChannelStore", { enumerable: true, get: function () { return sqlite_kysely_channel_store_js_1.SQLiteKyselyChannelStore; } });
16
- var sqlite_kysely_eventhub_store_js_1 = require("./sqlite-kysely-eventhub-store.js");
17
- Object.defineProperty(exports, "SQLiteKyselyEventHubStore", { enumerable: true, get: function () { return sqlite_kysely_eventhub_store_js_1.SQLiteKyselyEventHubStore; } });
18
- var sqlite_kysely_secret_service_js_1 = require("./sqlite-kysely-secret-service.js");
19
- Object.defineProperty(exports, "SQLiteKyselySecretService", { enumerable: true, get: function () { return sqlite_kysely_secret_service_js_1.SQLiteKyselySecretService; } });
@@ -1,3 +0,0 @@
1
- import { KyselyAgentRunService } from '@pikku/kysely';
2
- export declare class SQLiteKyselyAgentRunService extends KyselyAgentRunService {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyAgentRunService = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyAgentRunService = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyAgentRunService, _super);
22
- function SQLiteKyselyAgentRunService() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyAgentRunService;
26
- }(kysely_1.KyselyAgentRunService));
27
- exports.SQLiteKyselyAgentRunService = SQLiteKyselyAgentRunService;
@@ -1,3 +0,0 @@
1
- import { KyselyAIStorageService } from '@pikku/kysely';
2
- export declare class SQLiteKyselyAIStorageService extends KyselyAIStorageService {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyAIStorageService = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyAIStorageService = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyAIStorageService, _super);
22
- function SQLiteKyselyAIStorageService() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyAIStorageService;
26
- }(kysely_1.KyselyAIStorageService));
27
- exports.SQLiteKyselyAIStorageService = SQLiteKyselyAIStorageService;
@@ -1,3 +0,0 @@
1
- import { KyselyChannelStore } from '@pikku/kysely';
2
- export declare class SQLiteKyselyChannelStore extends KyselyChannelStore {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyChannelStore = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyChannelStore = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyChannelStore, _super);
22
- function SQLiteKyselyChannelStore() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyChannelStore;
26
- }(kysely_1.KyselyChannelStore));
27
- exports.SQLiteKyselyChannelStore = SQLiteKyselyChannelStore;
@@ -1,3 +0,0 @@
1
- import { KyselyDeploymentService } from '@pikku/kysely';
2
- export declare class SQLiteKyselyDeploymentService extends KyselyDeploymentService {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyDeploymentService = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyDeploymentService = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyDeploymentService, _super);
22
- function SQLiteKyselyDeploymentService() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyDeploymentService;
26
- }(kysely_1.KyselyDeploymentService));
27
- exports.SQLiteKyselyDeploymentService = SQLiteKyselyDeploymentService;
@@ -1,3 +0,0 @@
1
- import { KyselyEventHubStore } from '@pikku/kysely';
2
- export declare class SQLiteKyselyEventHubStore extends KyselyEventHubStore {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyEventHubStore = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyEventHubStore = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyEventHubStore, _super);
22
- function SQLiteKyselyEventHubStore() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyEventHubStore;
26
- }(kysely_1.KyselyEventHubStore));
27
- exports.SQLiteKyselyEventHubStore = SQLiteKyselyEventHubStore;
@@ -1,3 +0,0 @@
1
- import { KyselySecretService } from '@pikku/kysely';
2
- export declare class SQLiteKyselySecretService extends KyselySecretService {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselySecretService = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselySecretService = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselySecretService, _super);
22
- function SQLiteKyselySecretService() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselySecretService;
26
- }(kysely_1.KyselySecretService));
27
- exports.SQLiteKyselySecretService = SQLiteKyselySecretService;
@@ -1,3 +0,0 @@
1
- import { KyselyWorkflowRunService } from '@pikku/kysely';
2
- export declare class SQLiteKyselyWorkflowRunService extends KyselyWorkflowRunService {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyWorkflowRunService = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyWorkflowRunService = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyWorkflowRunService, _super);
22
- function SQLiteKyselyWorkflowRunService() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyWorkflowRunService;
26
- }(kysely_1.KyselyWorkflowRunService));
27
- exports.SQLiteKyselyWorkflowRunService = SQLiteKyselyWorkflowRunService;
@@ -1,3 +0,0 @@
1
- import { KyselyWorkflowService } from '@pikku/kysely';
2
- export declare class SQLiteKyselyWorkflowService extends KyselyWorkflowService {
3
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SQLiteKyselyWorkflowService = void 0;
19
- var kysely_1 = require("@pikku/kysely");
20
- var SQLiteKyselyWorkflowService = /** @class */ (function (_super) {
21
- __extends(SQLiteKyselyWorkflowService, _super);
22
- function SQLiteKyselyWorkflowService() {
23
- return _super !== null && _super.apply(this, arguments) || this;
24
- }
25
- return SQLiteKyselyWorkflowService;
26
- }(kysely_1.KyselyWorkflowService));
27
- exports.SQLiteKyselyWorkflowService = SQLiteKyselyWorkflowService;