@storecraft/database-sql-base 1.0.17 → 1.0.19
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/kysely.aggregate.dialect.js +11 -1
- package/migrate.js +41 -6
- package/migrations.mysql/00000_init_tables.js +2 -3
- package/migrations.mysql/00004_update_previous_templates_with_subject.js +1 -0
- package/migrations.postgres/00000_init_tables.js +2 -3
- package/migrations.postgres/00004_update_previous_templates_with_subject.js +1 -0
- package/migrations.shared/00001_seed_email_templates.js +28 -1
- package/migrations.shared/00002_seed_email_templates.js +30 -5
- package/migrations.shared/00004_update_previous_templates_with_subject.js +39 -0
- package/migrations.sqlite/00000_init_tables.js +2 -3
- package/migrations.sqlite/00004_update_previous_templates_with_subject.js +1 -0
- package/package.json +1 -1
- package/src/con.templates.js +8 -10
- package/tests/runner.sqlite-local.test.js +1 -1
- package/types.sql.tables.d.ts +1 -0
- package/tests/aggregate.js +0 -38
@@ -16,7 +16,17 @@ import {
|
|
16
16
|
*/
|
17
17
|
|
18
18
|
/**
|
19
|
-
* @description
|
19
|
+
* @description A special dialect that aggregates / records queries.
|
20
|
+
* This is useful for
|
21
|
+
* - testing / debugging
|
22
|
+
* - generating migration files for cloud based databases
|
23
|
+
* such as `libsql` / `turso` / `d1`
|
24
|
+
*
|
25
|
+
* NOTE:
|
26
|
+
* - This dialect does not support transactions
|
27
|
+
* - This is only useful for non-interactive queries, which are
|
28
|
+
* basically transactions, that do not depend on results of previous queries.
|
29
|
+
* Which is the philosophy of `storecraft` and is quite common in migrations.
|
20
30
|
*
|
21
31
|
* @implements {Dialect}
|
22
32
|
*/
|
package/migrate.js
CHANGED
@@ -46,17 +46,17 @@ export const get_migrations = async (dialect_type='SQLITE') => {
|
|
46
46
|
return migrations;
|
47
47
|
}
|
48
48
|
|
49
|
-
console.log(
|
50
|
-
|
51
|
-
)
|
49
|
+
// console.log(
|
50
|
+
// await get_migrations()
|
51
|
+
// )
|
52
52
|
|
53
53
|
|
54
54
|
/**
|
55
55
|
*
|
56
56
|
* @param {SQL} db_driver
|
57
|
-
* @param {boolean} [
|
57
|
+
* @param {boolean} [release_db_upon_completion=true]
|
58
58
|
*/
|
59
|
-
export async function migrateToLatest(db_driver,
|
59
|
+
export async function migrateToLatest(db_driver, release_db_upon_completion=true) {
|
60
60
|
if(!db_driver?.client)
|
61
61
|
throw new Error('No Kysely client found !!!');
|
62
62
|
|
@@ -104,6 +104,41 @@ export async function migrateToLatest(db_driver, destroy_db_upon_completion=true
|
|
104
104
|
process.exit(1)
|
105
105
|
}
|
106
106
|
|
107
|
-
if(
|
107
|
+
if(release_db_upon_completion)
|
108
108
|
await db.destroy();
|
109
109
|
}
|
110
|
+
|
111
|
+
|
112
|
+
/**
|
113
|
+
* @description Just for education and debugging, do not use !!!
|
114
|
+
* @param {string} stmt
|
115
|
+
* @param {any[] | Record<string, any>} params
|
116
|
+
*/
|
117
|
+
export const prepare_and_bind = (stmt='', params=[]) => {
|
118
|
+
const params_object = Array.isArray(params) ?
|
119
|
+
params.reduce((a, v, idx) => ({ ...a, [idx+1]: v}), {}) :
|
120
|
+
params;
|
121
|
+
|
122
|
+
let current = 0;
|
123
|
+
let result = ''
|
124
|
+
let index_run = 1;
|
125
|
+
for (let m of stmt.matchAll(/\?[0-9]*/g)) {
|
126
|
+
result += stmt.slice(current, m.index);
|
127
|
+
|
128
|
+
const match_string = m[0];
|
129
|
+
let index_access = match_string.length > 1 ?
|
130
|
+
Number(match_string.slice(1)) :
|
131
|
+
index_run;
|
132
|
+
|
133
|
+
result += "'" + params_object[index_access] + "'";
|
134
|
+
|
135
|
+
current = m.index + m[0].length;
|
136
|
+
index_run+=1;
|
137
|
+
}
|
138
|
+
|
139
|
+
result += stmt.slice(current);
|
140
|
+
|
141
|
+
return result;
|
142
|
+
}
|
143
|
+
|
144
|
+
|
@@ -1,8 +1,7 @@
|
|
1
|
-
import { CreateTableBuilder, Kysely } from 'kysely'
|
2
|
-
|
3
1
|
/**
|
4
|
-
* @
|
2
|
+
* @import { Database } from '../types.sql.tables.js'
|
5
3
|
*/
|
4
|
+
import { CreateTableBuilder, Kysely } from 'kysely'
|
6
5
|
|
7
6
|
/**
|
8
7
|
* @template {string} TB
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../migrations.shared/00004_update_previous_templates_with_subject.js'
|
@@ -1,8 +1,7 @@
|
|
1
|
-
import { CreateTableBuilder, Kysely } from 'kysely'
|
2
|
-
|
3
1
|
/**
|
4
|
-
* @
|
2
|
+
* @import { Database } from '../types.sql.tables.js'
|
5
3
|
*/
|
4
|
+
import { CreateTableBuilder, Kysely } from 'kysely'
|
6
5
|
|
7
6
|
/**
|
8
7
|
* @template {string} TB
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../migrations.shared/00004_update_previous_templates_with_subject.js'
|
@@ -3,7 +3,7 @@
|
|
3
3
|
*/
|
4
4
|
import { Kysely } from 'kysely'
|
5
5
|
import { upsert } from '../src/con.templates.js'
|
6
|
-
import { templates } from '@storecraft/core/assets/seed-templates.js';
|
6
|
+
import { templates } from '@storecraft/core/assets/seed-templates-v1.js';
|
7
7
|
|
8
8
|
|
9
9
|
/**
|
@@ -12,6 +12,33 @@ import { templates } from '@storecraft/core/assets/seed-templates.js';
|
|
12
12
|
*/
|
13
13
|
export async function up(db) {
|
14
14
|
|
15
|
+
//
|
16
|
+
// NOTE: seeding templates this way might be problematic. Basically,
|
17
|
+
// seeds should not be in the migration folder. But, because we have
|
18
|
+
// direct access to the database, we can seed the templates directly.
|
19
|
+
// But this may result with problems, because right now we use the
|
20
|
+
// an `api` layer to seed the templates, which always assumes that we
|
21
|
+
// have the latest schema. So, if we change the schema, we need to change
|
22
|
+
// the seed templates as well. This is not a problem for now, but it may be.
|
23
|
+
// So, we need to be careful with this. If any issue arises, please just
|
24
|
+
// use kysely directly to seed the tempaltes according to the schema at
|
25
|
+
// that time.
|
26
|
+
//
|
27
|
+
// Example:
|
28
|
+
// - later on, we add a new column to the template table.
|
29
|
+
// - The `upsert` function always assumes that the schema is up to date.
|
30
|
+
// - So, if the upsert method assigns a value like a default value to the new column,
|
31
|
+
// it will fail, because the column does not exist yet.
|
32
|
+
// - So, the solution for that, is to write our version of the upsert here.
|
33
|
+
//
|
34
|
+
// NOTE 2:
|
35
|
+
// - It is always better to seperate the seed data from the migration files.
|
36
|
+
// - seeding always assumes that the schema is up to date.
|
37
|
+
// - It is more hustle for users to run seeds, which might evolve.
|
38
|
+
// - I can afford to run seeds in migration files, because i have direct access to the database,
|
39
|
+
// as oppposed to ORM users etc.
|
40
|
+
//
|
41
|
+
//
|
15
42
|
for (const template of templates.slice(0)) {
|
16
43
|
const result = await upsert(db)(template, template.search);
|
17
44
|
if(!result)
|
@@ -1,17 +1,42 @@
|
|
1
|
+
/**
|
2
|
+
* @import { Database } from '../types.sql.tables.js'
|
3
|
+
*/
|
1
4
|
import { Kysely } from 'kysely'
|
2
5
|
import { upsert } from '../src/con.templates.js'
|
3
6
|
import { templates } from '@storecraft/core/assets/seed-templates-v2.js';
|
4
7
|
|
5
|
-
/**
|
6
|
-
* @typedef {import('../types.sql.tables.js').Database} Database
|
7
|
-
*/
|
8
|
-
|
9
8
|
/**
|
10
9
|
*
|
11
10
|
* @param {Kysely<Database>} db
|
12
11
|
*/
|
13
12
|
export async function up(db) {
|
14
|
-
|
13
|
+
//
|
14
|
+
// NOTE: seeding templates this way might be problematic. Basically,
|
15
|
+
// seeds should not be in the migration folder. But, because we have
|
16
|
+
// direct access to the database, we can seed the templates directly.
|
17
|
+
// But this may result with problems, because right now we use the
|
18
|
+
// an `api` layer to seed the templates, which always assumes that we
|
19
|
+
// have the latest schema. So, if we change the schema, we need to change
|
20
|
+
// the seed templates as well. This is not a problem for now, but it may be.
|
21
|
+
// So, we need to be careful with this. If any issue arises, please just
|
22
|
+
// use kysely directly to seed the tempaltes according to the schema at
|
23
|
+
// that time.
|
24
|
+
//
|
25
|
+
// Example:
|
26
|
+
// - later on, we add a new column to the template table.
|
27
|
+
// - The `upsert` function always assumes that the schema is up to date.
|
28
|
+
// - So, if the upsert method assigns a value like a default value to the new column,
|
29
|
+
// it will fail, because the column does not exist yet.
|
30
|
+
// - So, the solution for that, is to write our version of the upsert here.
|
31
|
+
//
|
32
|
+
// NOTE 2:
|
33
|
+
// - It is always better to seperate the seed data from the migration files.
|
34
|
+
// - seeding always assumes that the schema is up to date.
|
35
|
+
// - It is more hustle for users to run seeds, which might evolve.
|
36
|
+
// - I can afford to run seeds in migration files, because i have direct access to the database,
|
37
|
+
// as oppposed to ORM users etc.
|
38
|
+
//
|
39
|
+
//
|
15
40
|
for (const template of templates.slice(0)) {
|
16
41
|
const result = await upsert(db)(template, template.search);
|
17
42
|
if(!result)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/**
|
2
|
+
* @import { Database } from '../types.sql.tables.js'
|
3
|
+
*/
|
4
|
+
import { Kysely } from 'kysely'
|
5
|
+
import {
|
6
|
+
templates as templates_corrections
|
7
|
+
} from '@storecraft/core/assets/seed-templates-v3-update-previous-templates-with-subject.js';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* update templates with subject template
|
11
|
+
* @param {Kysely<Database>} db
|
12
|
+
*/
|
13
|
+
export async function up(db) {
|
14
|
+
await db.schema
|
15
|
+
.alterTable('templates')
|
16
|
+
.addColumn('template_subject', 'text')
|
17
|
+
.execute();
|
18
|
+
|
19
|
+
for (const template of templates_corrections) {
|
20
|
+
await db
|
21
|
+
.updateTable('templates')
|
22
|
+
.set({
|
23
|
+
template_subject: template.template_subject,
|
24
|
+
})
|
25
|
+
.where('id', '=', template.id)
|
26
|
+
.executeTakeFirst();
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
*
|
32
|
+
* @param {Kysely<Database>} db
|
33
|
+
*/
|
34
|
+
export async function down(db) {
|
35
|
+
await db.schema
|
36
|
+
.alterTable('templates')
|
37
|
+
.dropColumn('template_subject')
|
38
|
+
.execute();
|
39
|
+
}
|
@@ -1,8 +1,7 @@
|
|
1
|
-
import { CreateTableBuilder, Kysely } from 'kysely'
|
2
|
-
|
3
1
|
/**
|
4
|
-
* @
|
2
|
+
* @import { Database } from '../types.sql.tables.js'
|
5
3
|
*/
|
4
|
+
import { CreateTableBuilder, Kysely } from 'kysely'
|
6
5
|
|
7
6
|
/**
|
8
7
|
* @template {string} TB
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../migrations.shared/00004_update_previous_templates_with_subject.js'
|
package/package.json
CHANGED
package/src/con.templates.js
CHANGED
@@ -19,7 +19,7 @@ export const table_name = 'templates'
|
|
19
19
|
* @param {string} val
|
20
20
|
*/
|
21
21
|
const encode_base64_if_needed = val => {
|
22
|
-
if(val
|
22
|
+
if(val?.startsWith('base64_'))
|
23
23
|
return val;
|
24
24
|
|
25
25
|
return 'base64_' + base64.encode(val);
|
@@ -31,7 +31,7 @@ const encode_base64_if_needed = val => {
|
|
31
31
|
* @param {string} val
|
32
32
|
*/
|
33
33
|
const decode_base64_if_needed = val => {
|
34
|
-
if(!val
|
34
|
+
if(!val?.startsWith('base64_'))
|
35
35
|
return val;
|
36
36
|
|
37
37
|
return base64.decode(val.split('base64_').at(-1) ?? '');
|
@@ -39,7 +39,6 @@ const decode_base64_if_needed = val => {
|
|
39
39
|
|
40
40
|
/**
|
41
41
|
* @param {Kysely<Database>} client
|
42
|
-
*
|
43
42
|
* @returns {db_col["upsert"]}
|
44
43
|
*/
|
45
44
|
export const upsert = (client) => {
|
@@ -56,8 +55,9 @@ export const upsert = (client) => {
|
|
56
55
|
active: item.active ? 1 : 0,
|
57
56
|
title: item.title,
|
58
57
|
handle: item.handle,
|
59
|
-
template_html: encode_base64_if_needed(item.template_html),
|
60
|
-
template_text: encode_base64_if_needed(item.template_text),
|
58
|
+
template_html: item.template_html && encode_base64_if_needed(item.template_html),
|
59
|
+
template_text: item.template_text && encode_base64_if_needed(item.template_text),
|
60
|
+
template_subject: item.template_subject && encode_base64_if_needed(item.template_subject),
|
61
61
|
reference_example_input: JSON.stringify(item.reference_example_input ?? {})
|
62
62
|
});
|
63
63
|
}
|
@@ -74,11 +74,9 @@ export const upsert = (client) => {
|
|
74
74
|
|
75
75
|
/**
|
76
76
|
* @param {SQL} driver
|
77
|
-
*
|
78
|
-
*
|
79
77
|
* @returns {db_col["get"]}
|
80
78
|
*/
|
81
|
-
const get = (driver) => {
|
79
|
+
export const get = (driver) => {
|
82
80
|
return (id_or_handle, options) => {
|
83
81
|
return driver.client
|
84
82
|
.selectFrom(table_name)
|
@@ -96,6 +94,7 @@ const get = (driver) => {
|
|
96
94
|
|
97
95
|
item.template_html = decode_base64_if_needed(item.template_html);
|
98
96
|
item.template_text = decode_base64_if_needed(item.template_text);
|
97
|
+
item.template_subject = decode_base64_if_needed(item.template_subject);
|
99
98
|
|
100
99
|
return item;
|
101
100
|
}
|
@@ -106,8 +105,6 @@ const get = (driver) => {
|
|
106
105
|
|
107
106
|
/**
|
108
107
|
* @param {SQL} driver
|
109
|
-
*
|
110
|
-
*
|
111
108
|
* @returns {db_col["remove"]}
|
112
109
|
*/
|
113
110
|
const remove = (driver) => {
|
@@ -162,6 +159,7 @@ const list = (driver) => {
|
|
162
159
|
(item) => {
|
163
160
|
item.template_html = decode_base64_if_needed(item.template_html);
|
164
161
|
item.template_text = decode_base64_if_needed(item.template_text);
|
162
|
+
item.template_subject = decode_base64_if_needed(item.template_subject);
|
165
163
|
return item;
|
166
164
|
}
|
167
165
|
)
|
@@ -10,7 +10,7 @@ import { homedir } from 'node:os';
|
|
10
10
|
import { join } from 'node:path';
|
11
11
|
|
12
12
|
export const sqlite_dialect = new SqliteDialect({
|
13
|
-
database: async () => new SQLite(
|
13
|
+
database: async () => new SQLite(':memory:'),
|
14
14
|
});
|
15
15
|
|
16
16
|
export const create_app = async () => {
|
package/types.sql.tables.d.ts
CHANGED
package/tests/aggregate.js
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
import 'dotenv/config';
|
2
|
-
import { App } from '@storecraft/core';
|
3
|
-
import { SQL } from '@storecraft/database-sql-base';
|
4
|
-
import { migrateToLatest } from '@storecraft/database-sql-base/migrate.js';
|
5
|
-
import { NodePlatform } from '@storecraft/core/platform/node';
|
6
|
-
import { api } from '@storecraft/core/test-runner'
|
7
|
-
import SQLite from 'better-sqlite3'
|
8
|
-
import { SqliteDialect } from 'kysely';
|
9
|
-
import { homedir } from 'node:os';
|
10
|
-
import { join } from 'node:path';
|
11
|
-
import { up } from '../migrations.sqlite/00000_init_tables.js'
|
12
|
-
import { AggregateDialect } from '../kysely.aggregate.dialect.js'
|
13
|
-
|
14
|
-
export const sqlite_dialect = new SqliteDialect(
|
15
|
-
{
|
16
|
-
database: async () => new SQLite(join(homedir(), 'db.sqlite')),
|
17
|
-
}
|
18
|
-
);
|
19
|
-
|
20
|
-
export const test = async () => {
|
21
|
-
const aggregate_dialect = new AggregateDialect(
|
22
|
-
{
|
23
|
-
dialect: sqlite_dialect,
|
24
|
-
}
|
25
|
-
);
|
26
|
-
|
27
|
-
const db = new SQL({
|
28
|
-
dialect: aggregate_dialect,
|
29
|
-
dialect_type: 'SQLITE'
|
30
|
-
});
|
31
|
-
|
32
|
-
await up(db.client);
|
33
|
-
|
34
|
-
const queries = aggregate_dialect.queries;
|
35
|
-
console.log({queries})
|
36
|
-
|
37
|
-
}
|
38
|
-
test();
|