Skip to content

Commit b690642

Browse files
committed
Dynamically import libraries
1 parent 877e5fb commit b690642

File tree

4 files changed

+231
-14
lines changed

4 files changed

+231
-14
lines changed

src/lib/adapters/sqlite/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ interface RunResult {
22
changes: number;
33
lastInsertRowid: number | bigint;
44
}
5-
interface Statement<BindParameters extends unknown[]> {
5+
export interface Statement<BindParameters extends unknown[]> {
66
database: Database;
77
source: string;
88
reader: boolean;

src/lib/adapters/sqljs.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// File: /src/lib/database/SqlJsDatabaseAdapter.ts
22
import crypto, { type UUID } from "crypto";
3-
import { type Database } from "sql.js";
43
import { DatabaseAdapter } from "../database";
54
import {
65
Account,
@@ -11,6 +10,7 @@ import {
1110
type Relationship,
1211
} from "../types";
1312
import { sqliteTables } from "./sqlite/sqliteTables";
13+
import { Database } from "./sqljs/types";
1414

1515
export class SqlJsDatabaseAdapter extends DatabaseAdapter {
1616
db: Database;

src/lib/adapters/sqljs/types.ts

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
type SqlValue = number | string | Uint8Array | null;
2+
type ParamsObject = Record<string, SqlValue>;
3+
type ParamsCallback = (obj: ParamsObject) => void;
4+
type BindParams = SqlValue[] | ParamsObject | null;
5+
interface QueryExecResult {
6+
columns: string[];
7+
values: SqlValue[][];
8+
}
9+
10+
declare class StatementIterator
11+
implements Iterator<Statement>, Iterable<Statement>
12+
{
13+
[Symbol.iterator](): Iterator<Statement>;
14+
getRemainingSQL(): string;
15+
next(): StatementIteratorResult;
16+
}
17+
interface StatementIteratorResult {
18+
/** `true` if there are no more available statements */
19+
done: boolean;
20+
/** the next available Statement (as returned by `Database.prepare`) */
21+
value: Statement;
22+
}
23+
declare class Statement {
24+
/**
25+
* Bind values to the parameters, after having reseted the statement. If
26+
* values is null, do nothing and return true.
27+
*
28+
* SQL statements can have parameters, named '?', '?NNN', ':VVV',
29+
* '@VVV', '$VVV', where NNN is a number and VVV a string. This function
30+
* binds these parameters to the given values.
31+
*
32+
* Warning: ':', '@', and '$' are included in the parameters names
33+
*
34+
* ### Value types
35+
*
36+
* |Javascript type|SQLite type|
37+
* |-|-|
38+
* |number|REAL, INTEGER|
39+
* |boolean|INTEGER|
40+
* |string|TEXT|
41+
* |Array, Uint8Array|BLOB|
42+
* |null|NULL|
43+
* @see [https://sql.js.org/documentation/Statement.html#["bind"]](https://sql.js.org/documentation/Statement.html#%5B%22bind%22%5D)
44+
*
45+
* @param values The values to bind
46+
*/
47+
bind(values?: BindParams): boolean;
48+
49+
/**
50+
* Free the memory used by the statement
51+
* @see [https://sql.js.org/documentation/Statement.html#["free"]](https://sql.js.org/documentation/Statement.html#%5B%22free%22%5D)
52+
*/
53+
free(): boolean;
54+
55+
/**
56+
* Free the memory allocated during parameter binding
57+
* @see [https://sql.js.org/documentation/Statement.html#["freemem"]](https://sql.js.org/documentation/Statement.html#%5B%22freemem%22%5D)
58+
*/
59+
freemem(): void;
60+
61+
/**
62+
* Get one row of results of a statement. If the first parameter is not
63+
* provided, step must have been called before.
64+
* @see [https://sql.js.org/documentation/Statement.html#["get"]](https://sql.js.org/documentation/Statement.html#%5B%22get%22%5D)
65+
*
66+
* @param params If set, the values will be bound to the statement
67+
* before it is executed
68+
*/
69+
get(params?: BindParams): SqlValue[];
70+
71+
/**
72+
* Get one row of result as a javascript object, associating column
73+
* names with their value in the current row
74+
* @see [https://sql.js.org/documentation/Statement.html#["getAsObject"]](https://sql.js.org/documentation/Statement.html#%5B%22getAsObject%22%5D)
75+
*
76+
* @param params If set, the values will be bound to the statement, and
77+
* it will be executed
78+
*/
79+
getAsObject(params?: BindParams): ParamsObject;
80+
81+
/**
82+
* Get the list of column names of a row of result of a statement.
83+
* @see [https://sql.js.org/documentation/Statement.html#["getColumnNames"]](https://sql.js.org/documentation/Statement.html#%5B%22getColumnNames%22%5D)
84+
*/
85+
getColumnNames(): string[];
86+
87+
/**
88+
* Get the SQLite's normalized version of the SQL string used in
89+
* preparing this statement. The meaning of "normalized" is not
90+
* well-defined: see
91+
* [the SQLite documentation](https://sqlite.org/c3ref/expanded_sql.html).
92+
* @see [https://sql.js.org/documentation/Statement.html#["getNormalizedSQL"]](https://sql.js.org/documentation/Statement.html#%5B%22getNormalizedSQL%22%5D)
93+
*/
94+
getNormalizedSQL(): string;
95+
96+
/**
97+
* Get the SQL string used in preparing this statement.
98+
* @see [https://sql.js.org/documentation/Statement.html#["getSQL"]](https://sql.js.org/documentation/Statement.html#%5B%22getSQL%22%5D)
99+
*/
100+
getSQL(): string;
101+
102+
/**
103+
* Reset a statement, so that it's parameters can be bound to new
104+
* values. It also clears all previous bindings, freeing the memory used
105+
* by bound parameters.
106+
* @see [https://sql.js.org/documentation/Statement.html#["reset"]](https://sql.js.org/documentation/Statement.html#%5B%22reset%22%5D)
107+
*/
108+
reset(): void;
109+
110+
/**
111+
* Shorthand for bind + step + reset Bind the values, execute the
112+
* statement, ignoring the rows it returns, and resets it
113+
* @param values Value to bind to the statement
114+
*/
115+
run(values?: BindParams): void;
116+
117+
/**
118+
* Execute the statement, fetching the the next line of result, that can
119+
* be retrieved with `Statement.get`.
120+
* @see [https://sql.js.org/documentation/Statement.html#["step"]](https://sql.js.org/documentation/Statement.html#%5B%22step%22%5D)
121+
*/
122+
step(): boolean;
123+
}
124+
export declare class Database {
125+
constructor(data?: ArrayLike<number> | Buffer | null);
126+
127+
close(): void;
128+
129+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
130+
create_function(name: string, func: (...args: any[]) => any): Database;
131+
132+
each(
133+
sql: string,
134+
params: BindParams,
135+
callback: ParamsCallback,
136+
done: () => void
137+
): Database;
138+
each(sql: string, callback: ParamsCallback, done: () => void): Database;
139+
140+
/**
141+
* Execute an SQL query, and returns the result.
142+
*
143+
* This is a wrapper against `Database.prepare`, `Statement.bind`, `Statement.step`, `Statement.get`, and `Statement.free`.
144+
*
145+
* The result is an array of result elements. There are as many result elements as the number of statements in your sql string (statements are separated by a semicolon)
146+
* @see [https://sql.js.org/documentation/Database.html#["exec"]](https://sql.js.org/documentation/Database.html#%5B%22exec%22%5D)
147+
*
148+
* @param sql a string containing some SQL text to execute
149+
* @param params When the SQL statement contains placeholders, you can
150+
* pass them in here. They will be bound to the statement before it is
151+
* executed. If you use the params argument as an array, you **cannot**
152+
* provide an sql string that contains several statements (separated by
153+
* `;`). This limitation does not apply to params as an object.
154+
*/
155+
exec(sql: string, params?: BindParams): QueryExecResult[];
156+
157+
/**
158+
* Exports the contents of the database to a binary array
159+
* @see [https://sql.js.org/documentation/Database.html#["export"]](https://sql.js.org/documentation/Database.html#%5B%22export%22%5D)
160+
*/
161+
export(): Uint8Array;
162+
163+
/**
164+
* Returns the number of changed rows (modified, inserted or deleted) by
165+
* the latest completed `INSERT`, `UPDATE` or `DELETE` statement on the
166+
* database. Executing any other type of SQL statement does not modify
167+
* the value returned by this function.
168+
* @see [https://sql.js.org/documentation/Database.html#["getRowsModified"]](https://sql.js.org/documentation/Database.html#%5B%22getRowsModified%22%5D)
169+
*/
170+
getRowsModified(): number;
171+
172+
/**
173+
* Analyze a result code, return null if no error occured, and throw an
174+
* error with a descriptive message otherwise
175+
* @see [https://sql.js.org/documentation/Database.html#["handleError"]](https://sql.js.org/documentation/Database.html#%5B%22handleError%22%5D)
176+
*/
177+
handleError(): null | never;
178+
179+
/**
180+
* Iterate over multiple SQL statements in a SQL string. This function
181+
* returns an iterator over Statement objects. You can use a `for..of`
182+
* loop to execute the returned statements one by one.
183+
* @see [https://sql.js.org/documentation/Database.html#["iterateStatements"]](https://sql.js.org/documentation/Database.html#%5B%22iterateStatements%22%5D)
184+
*
185+
* @param sql a string of SQL that can contain multiple statements
186+
*/
187+
iterateStatements(sql: string): StatementIterator;
188+
189+
/**
190+
* Prepare an SQL statement
191+
* @see [https://sql.js.org/documentation/Database.html#["prepare"]](https://sql.js.org/documentation/Database.html#%5B%22prepare%22%5D)
192+
*
193+
* @param sql a string of SQL, that can contain placeholders (`?`, `:VVV`, `:AAA`, `@AAA`)
194+
* @param params values to bind to placeholders
195+
*/
196+
prepare(sql: string, params?: BindParams): Statement;
197+
198+
/**
199+
* Execute an SQL query, ignoring the rows it returns.
200+
* @see [https://sql.js.org/documentation/Database.html#["run"]](https://sql.js.org/documentation/Database.html#%5B%22run%22%5D)
201+
*
202+
* @param sql a string containing some SQL text to execute
203+
* @param params When the SQL statement contains placeholders, you can
204+
* pass them in here. They will be bound to the statement before it is
205+
* executed. If you use the params argument as an array, you **cannot**
206+
* provide an sql string that contains several statements (separated by
207+
* `;`). This limitation does not apply to params as an object.
208+
*/
209+
run(sql: string, params?: BindParams): Database;
210+
}

src/test/createRuntime.ts

+19-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { Session, createClient } from "@supabase/supabase-js";
2-
import Database from "better-sqlite3";
31
import { SqliteDatabaseAdapter } from "../lib/adapters/sqlite";
42
import { SupabaseDatabaseAdapter } from "../lib/adapters/supabase";
53
import { zeroUuid } from "../lib/constants";
@@ -15,7 +13,6 @@ import {
1513
import { User } from "./types";
1614
import { load } from "../lib/adapters/sqlite/sqlite_vss";
1715
import { SqlJsDatabaseAdapter } from "../lib/adapters/sqljs";
18-
import initSqlJs from "sql.js";
1916

2017
export async function createRuntime({
2118
env,
@@ -32,11 +29,17 @@ export async function createRuntime({
3229
}) {
3330
let adapter: DatabaseAdapter;
3431
let user: User;
35-
let session: Session;
32+
let session: {
33+
user: User;
34+
};
3635

3736
switch (env?.TEST_DATABASE_CLIENT as string) {
3837
case "sqlite":
3938
{
39+
const module = await import("better-sqlite3");
40+
41+
const Database = module.default;
42+
4043
// SQLite adapter
4144
adapter = new SqliteDatabaseAdapter(new Database(":memory:"));
4245

@@ -48,14 +51,16 @@ export async function createRuntime({
4851
4952
} as User;
5053
session = {
51-
access_token: "test-access-token",
52-
refresh_token: "test-refresh-token",
5354
user: user,
54-
} as Session;
55+
};
5556
}
5657
break;
5758
case "sqljs":
5859
{
60+
const module = await import("sql.js");
61+
62+
const initSqlJs = module.default;
63+
5964
// SQLite adapter
6065
const SQL = await initSqlJs({});
6166
const db = new SQL.Database();
@@ -70,15 +75,17 @@ export async function createRuntime({
7075
7176
} as User;
7277
session = {
73-
access_token: "test-access-token",
74-
refresh_token: "test-refresh-token",
7578
user: user,
76-
} as Session;
79+
};
7780
}
7881
break;
7982
case "supabase":
8083
default:
8184
{
85+
const module = await import("@supabase/supabase-js");
86+
87+
const { createClient } = module;
88+
8289
const supabase = createClient(
8390
env?.SUPABASE_URL ?? SUPABASE_URL,
8491
env?.SUPABASE_SERVICE_API_KEY ?? SUPABASE_ANON_KEY,
@@ -90,7 +97,7 @@ export async function createRuntime({
9097
});
9198

9299
user = data.user as User;
93-
session = data.session as Session;
100+
session = data.session as unknown as { user: User };
94101

95102
if (!session) {
96103
const response = await supabase.auth.signUp({
@@ -111,7 +118,7 @@ export async function createRuntime({
111118
}
112119

113120
user = response.data.user as User;
114-
session = response.data.session as Session;
121+
session = response.data.session as unknown as { user: User };
115122
}
116123

117124
adapter = new SupabaseDatabaseAdapter(

0 commit comments

Comments
 (0)