@storecraft/database-turso 1.0.15 → 1.0.17
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/index.js +1 -1
- package/kysely.turso.dialect.js +7 -4
- package/migrate.js +119 -1
- package/migrate_old.js +5 -0
- package/package.json +1 -1
- package/tests/runner.test.js +3 -1
- package/tests/sandbox.js +3 -1
- package/kysely.turso.utils.js +0 -33
package/index.js
CHANGED
package/kysely.turso.dialect.js
CHANGED
@@ -26,8 +26,12 @@ export class LibsqlDialect {
|
|
26
26
|
return this.#config;
|
27
27
|
}
|
28
28
|
|
29
|
-
createAdapter() {
|
30
|
-
|
29
|
+
createAdapter() {
|
30
|
+
return new kysely.SqliteAdapter();
|
31
|
+
}
|
32
|
+
createQueryCompiler() {
|
33
|
+
return new kysely.SqliteQueryCompiler();
|
34
|
+
}
|
31
35
|
createDriver() {
|
32
36
|
|
33
37
|
if (this.#config?.url===undefined) {
|
@@ -173,9 +177,7 @@ export class LibsqlConnection {
|
|
173
177
|
}
|
174
178
|
|
175
179
|
/**
|
176
|
-
*
|
177
180
|
* @param {kysely.CompiledQuery} compiledQuery
|
178
|
-
*
|
179
181
|
* @returns {Promise<QueryResult>}
|
180
182
|
*/
|
181
183
|
async executeQuery(compiledQuery) {
|
@@ -193,6 +195,7 @@ export class LibsqlConnection {
|
|
193
195
|
}
|
194
196
|
|
195
197
|
async beginTransaction() {
|
198
|
+
// console.log('beginTransaction')
|
196
199
|
if(this.config.prefers_batch_over_transactions) {
|
197
200
|
this.isBatch = true;
|
198
201
|
this.batch = [];
|
package/migrate.js
CHANGED
@@ -1,5 +1,123 @@
|
|
1
|
-
|
1
|
+
import { SQL } from "@storecraft/database-sql-base";
|
2
|
+
import { AggregateDialect } from "@storecraft/database-sql-base/kysely.aggregate.dialect.js";
|
3
|
+
import { get_migrations, prepare_and_bind } from "@storecraft/database-sql-base/migrate.js";
|
4
|
+
import { Kysely, Migrator } from "kysely";
|
5
|
+
import fs from 'node:fs';
|
6
|
+
import path from 'node:path';
|
7
|
+
import { fileURLToPath } from "node:url";
|
2
8
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
10
|
+
const __dirname = path.dirname(__filename);
|
3
11
|
|
12
|
+
/**
|
13
|
+
*
|
14
|
+
* @param {SQL} db_driver
|
15
|
+
* @param {boolean} [destroy_db_upon_completion=true]
|
16
|
+
*/
|
17
|
+
export async function migrateToLatest(
|
18
|
+
db_driver, destroy_db_upon_completion=true
|
19
|
+
) {
|
20
|
+
const db = db_driver?.client;
|
4
21
|
|
22
|
+
if(!db)
|
23
|
+
throw new Error('No Kysely client found !!!');
|
5
24
|
|
25
|
+
console.log(
|
26
|
+
'Resolving migrations. This may take 2 minutes ...'
|
27
|
+
);
|
28
|
+
|
29
|
+
const migrations = await get_migrations(db_driver.dialectType);
|
30
|
+
|
31
|
+
if(!migrations)
|
32
|
+
throw new Error('No migrations found !!!');
|
33
|
+
|
34
|
+
const sorted = Object
|
35
|
+
.entries(migrations)
|
36
|
+
.sort((a, b) => a[0].localeCompare(b[0]));
|
37
|
+
|
38
|
+
/** @type {Record<string, import("kysely").Migration>} */
|
39
|
+
const rewritten_migrations = {};
|
40
|
+
|
41
|
+
for (const [name, migration] of sorted) {
|
42
|
+
// console.log(`Executing virtual migration "${name}" ...`);
|
43
|
+
const up_agg_dialect = new AggregateDialect(
|
44
|
+
{ dialect: db_driver.config.dialect, }
|
45
|
+
);
|
46
|
+
const up_agg_kysely = new Kysely(
|
47
|
+
{ dialect: up_agg_dialect }
|
48
|
+
);
|
49
|
+
const down_agg_dialect = new AggregateDialect(
|
50
|
+
{ dialect: db_driver.config.dialect, }
|
51
|
+
);
|
52
|
+
const down_agg_kysely = new Kysely(
|
53
|
+
{ dialect: down_agg_dialect }
|
54
|
+
);
|
55
|
+
|
56
|
+
await migration.up(up_agg_kysely);
|
57
|
+
await migration.down(down_agg_kysely);
|
58
|
+
|
59
|
+
// now get the queries
|
60
|
+
const queries_up = up_agg_dialect.queries;
|
61
|
+
const queries_down = down_agg_dialect.queries;
|
62
|
+
|
63
|
+
// turso dialect supports transactions and also batch
|
64
|
+
// we take adavantage of this
|
65
|
+
rewritten_migrations[name] = {
|
66
|
+
up: async (db) => {
|
67
|
+
await db.transaction().execute(
|
68
|
+
async (trx) => {
|
69
|
+
for (const query of queries_up) {
|
70
|
+
await trx.executeQuery(query)
|
71
|
+
}
|
72
|
+
}
|
73
|
+
);
|
74
|
+
},
|
75
|
+
down: async (db) => {
|
76
|
+
await db.transaction().execute(
|
77
|
+
async (trx) => {
|
78
|
+
for (const query of queries_down) {
|
79
|
+
await trx.executeQuery(query)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
const migrator = new Migrator(
|
88
|
+
{
|
89
|
+
db,
|
90
|
+
provider: {
|
91
|
+
getMigrations: async () => {
|
92
|
+
return rewritten_migrations;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
);
|
97
|
+
|
98
|
+
const { error, results } = await migrator.migrateToLatest();
|
99
|
+
|
100
|
+
results?.forEach(
|
101
|
+
(it) => {
|
102
|
+
if (it.status === 'Success') {
|
103
|
+
console.log(
|
104
|
+
`migration "${it.migrationName}" was executed successfully`
|
105
|
+
);
|
106
|
+
} else if (it.status === 'Error') {
|
107
|
+
console.error(
|
108
|
+
`failed to execute migration "${it.migrationName}"`
|
109
|
+
);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
);
|
113
|
+
|
114
|
+
if (error) {
|
115
|
+
console.error('failed to migrate')
|
116
|
+
console.error(JSON.stringify(error, null, 2))
|
117
|
+
process.exit(1)
|
118
|
+
}
|
119
|
+
|
120
|
+
if(destroy_db_upon_completion)
|
121
|
+
await db.destroy();
|
122
|
+
}
|
123
|
+
|
package/migrate_old.js
ADDED
package/package.json
CHANGED
package/tests/runner.test.js
CHANGED
@@ -11,7 +11,9 @@ export const create_app = async () => {
|
|
11
11
|
{
|
12
12
|
auth_admins_emails: ['admin@sc.com'],
|
13
13
|
auth_secret_access_token: 'auth_secret_access_token',
|
14
|
-
auth_secret_refresh_token: 'auth_secret_refresh_token'
|
14
|
+
auth_secret_refresh_token: 'auth_secret_refresh_token',
|
15
|
+
auth_secret_confirm_email_token: 'auth_secret_confirm_email_token',
|
16
|
+
auth_secret_forgot_password_token: 'auth_secret_forgot_password_token',
|
15
17
|
}
|
16
18
|
)
|
17
19
|
.withPlatform(new NodePlatform())
|
package/tests/sandbox.js
CHANGED
@@ -9,7 +9,9 @@ export const test = async () => {
|
|
9
9
|
{
|
10
10
|
auth_admins_emails: ['admin@sc.com'],
|
11
11
|
auth_secret_access_token: 'auth_secret_access_token',
|
12
|
-
auth_secret_refresh_token: 'auth_secret_refresh_token'
|
12
|
+
auth_secret_refresh_token: 'auth_secret_refresh_token',
|
13
|
+
auth_secret_confirm_email_token: 'auth_secret_confirm_email_token',
|
14
|
+
auth_secret_forgot_password_token: 'auth_secret_forgot_password_token',
|
13
15
|
}
|
14
16
|
)
|
15
17
|
.withPlatform(new NodePlatform())
|
package/kysely.turso.utils.js
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
|
2
|
-
/**
|
3
|
-
*
|
4
|
-
* @param {string} stmt
|
5
|
-
* @param {any[] | Record<string, any>} params
|
6
|
-
*/
|
7
|
-
export const prepare_and_bind = (stmt='', params=[]) => {
|
8
|
-
const params_object = Array.isArray(params) ?
|
9
|
-
params.reduce((a, v, idx) => ({ ...a, [idx+1]: v}), {}) :
|
10
|
-
params;
|
11
|
-
|
12
|
-
let current = 0;
|
13
|
-
let result = ''
|
14
|
-
let index_run = 1;
|
15
|
-
for (let m of stmt.matchAll(/\?[0-9]*/g)) {
|
16
|
-
result += stmt.slice(current, m.index);
|
17
|
-
|
18
|
-
const match_string = m[0];
|
19
|
-
let index_access = match_string.length > 1 ?
|
20
|
-
Number(match_string.slice(1)) :
|
21
|
-
index_run;
|
22
|
-
|
23
|
-
result += "'" + params_object[index_access] + "'";
|
24
|
-
|
25
|
-
current = m.index + m[0].length;
|
26
|
-
index_run+=1;
|
27
|
-
}
|
28
|
-
|
29
|
-
result += stmt.slice(current);
|
30
|
-
|
31
|
-
return result;
|
32
|
-
}
|
33
|
-
|