@storecraft/database-sql-base 1.0.12 → 1.0.14
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 +20 -19
- package/migrations.mysql/00003_alter_auth_users.js +1 -0
- package/migrations.postgres/00003_alter_auth_users.js +1 -0
- package/migrations.shared/00003_alter_auth_users.js +37 -0
- package/migrations.sqlite/00003_alter_auth_users.js +1 -0
- package/package.json +1 -1
- package/src/con.auth_users.js +21 -20
- package/src/con.collections.js +123 -22
- package/src/con.customers.js +51 -16
- package/src/con.discounts.js +193 -58
- package/src/con.discounts.utils.js +13 -12
- package/src/con.helpers.json.js +34 -30
- package/src/con.helpers.json.mysql.js +39 -19
- package/src/con.helpers.json.postgres.js +14 -8
- package/src/con.helpers.json.sqlite.js +35 -15
- package/src/con.notifications.js +10 -6
- package/src/con.orders.js +4 -3
- package/src/con.posts.js +6 -6
- package/src/con.products.js +82 -33
- package/src/con.search.js +1 -7
- package/src/con.shared.experiment.js +1 -0
- package/src/con.shared.js +110 -63
- package/src/con.shipping.js +6 -6
- package/src/con.storefronts.js +170 -90
- package/src/con.tags.js +9 -5
- package/src/con.templates.js +3 -1
- package/src/utils.funcs.js +6 -2
- package/src/utils.query.js +24 -20
- package/src/utils.types.d.ts +25 -0
- package/tests/Untitled-1.sqlite3-query +19 -0
- package/tests/sandbox.js +210 -0
- package/types.sql.tables.d.ts +76 -22
- package/src/con.helpers.json.mssql.js +0 -233
- package/tests/sandbox.test.js +0 -73
package/index.js
CHANGED
@@ -40,35 +40,35 @@ const assert = (b, msg) => {
|
|
40
40
|
export class SQL {
|
41
41
|
|
42
42
|
/** @type {boolean} */
|
43
|
-
#
|
43
|
+
#is_ready;
|
44
44
|
|
45
45
|
/** @type {App<any, any, any>} */
|
46
|
-
#
|
46
|
+
#app;
|
47
47
|
|
48
48
|
/** @type {ConfigType} */
|
49
|
-
#
|
49
|
+
#config;
|
50
50
|
|
51
51
|
/** @type {Kysely<Database>} */
|
52
|
-
#
|
52
|
+
#client;
|
53
53
|
|
54
54
|
/** @type {db_driver["resources"]} */
|
55
|
-
#
|
55
|
+
#resources;
|
56
56
|
|
57
57
|
/**
|
58
58
|
*
|
59
59
|
* @param {ConfigType} [config] config
|
60
60
|
*/
|
61
61
|
constructor(config) {
|
62
|
-
this.#
|
63
|
-
this.#
|
62
|
+
this.#is_ready = false;
|
63
|
+
this.#config = config;
|
64
64
|
|
65
65
|
assert(
|
66
|
-
this.#
|
66
|
+
this.#config.dialect,
|
67
67
|
'No Dialect found !'
|
68
68
|
);
|
69
69
|
|
70
70
|
assert(
|
71
|
-
this.#
|
71
|
+
this.#config.dialect_type,
|
72
72
|
'No Dialect Type specified !'
|
73
73
|
);
|
74
74
|
}
|
@@ -87,9 +87,9 @@ export class SQL {
|
|
87
87
|
if(this.isReady)
|
88
88
|
return this;
|
89
89
|
|
90
|
-
this.#
|
90
|
+
this.#app = app;
|
91
91
|
|
92
|
-
this.#
|
92
|
+
this.#resources = {
|
93
93
|
auth_users: auth_users(this),
|
94
94
|
collections: collections(this),
|
95
95
|
customers: customers(this),
|
@@ -106,7 +106,7 @@ export class SQL {
|
|
106
106
|
search: search(this),
|
107
107
|
}
|
108
108
|
|
109
|
-
this.#
|
109
|
+
this.#is_ready = true;
|
110
110
|
|
111
111
|
return this;
|
112
112
|
}
|
@@ -118,9 +118,10 @@ export class SQL {
|
|
118
118
|
|
119
119
|
/**
|
120
120
|
* `database` resources
|
121
|
+
* @type {db_driver["resources"]}
|
121
122
|
*/
|
122
123
|
get resources () {
|
123
|
-
return this.#
|
124
|
+
return this.#resources;
|
124
125
|
}
|
125
126
|
|
126
127
|
get name() {
|
@@ -128,11 +129,11 @@ export class SQL {
|
|
128
129
|
}
|
129
130
|
|
130
131
|
get app() {
|
131
|
-
return this.#
|
132
|
+
return this.#app;
|
132
133
|
}
|
133
134
|
|
134
135
|
get client() {
|
135
|
-
this.#
|
136
|
+
this.#client = this.#client ?? new Kysely(
|
136
137
|
{
|
137
138
|
dialect: this.config.dialect,
|
138
139
|
plugins: [
|
@@ -142,19 +143,19 @@ export class SQL {
|
|
142
143
|
}
|
143
144
|
);
|
144
145
|
|
145
|
-
return this.#
|
146
|
+
return this.#client;
|
146
147
|
}
|
147
148
|
|
148
149
|
get config() {
|
149
|
-
return this.#
|
150
|
+
return this.#config;
|
150
151
|
}
|
151
152
|
|
152
153
|
get isReady() {
|
153
|
-
return this.#
|
154
|
+
return this.#is_ready;
|
154
155
|
}
|
155
156
|
|
156
157
|
get dialectType() {
|
157
|
-
return this.#
|
158
|
+
return this.#config.dialect_type;
|
158
159
|
}
|
159
160
|
|
160
161
|
get isSqlite() {
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../migrations.shared/00003_alter_auth_users.js'
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../migrations.shared/00003_alter_auth_users.js'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/**
|
2
|
+
* @import { Database } from '../types.sql.tables.js'
|
3
|
+
*/
|
4
|
+
import { Kysely } from 'kysely'
|
5
|
+
|
6
|
+
/**
|
7
|
+
*
|
8
|
+
* @param {Kysely<Database>} db
|
9
|
+
*/
|
10
|
+
export async function up(db) {
|
11
|
+
|
12
|
+
await db.schema
|
13
|
+
.alterTable('auth_users')
|
14
|
+
.addColumn('firstname', 'text')
|
15
|
+
.execute();
|
16
|
+
|
17
|
+
await db.schema
|
18
|
+
.alterTable('auth_users')
|
19
|
+
.addColumn('lastname', 'text')
|
20
|
+
.execute();
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
*
|
25
|
+
* @param {Kysely<Database>} db
|
26
|
+
*/
|
27
|
+
export async function down(db) {
|
28
|
+
await db.schema
|
29
|
+
.alterTable('auth_users')
|
30
|
+
.dropColumn('firstname')
|
31
|
+
.execute();
|
32
|
+
|
33
|
+
await db.schema
|
34
|
+
.alterTable('auth_users')
|
35
|
+
.dropColumn('lastname')
|
36
|
+
.execute();
|
37
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../migrations.shared/00003_alter_auth_users.js'
|
package/package.json
CHANGED
package/src/con.auth_users.js
CHANGED
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
regular_upsert_me, where_id_or_handle_table, with_media, with_tags
|
9
9
|
} from './con.shared.js'
|
10
10
|
import { query_to_eb, query_to_sort } from './utils.query.js';
|
11
|
+
import { remove as remove_customer_and_auth_user } from './con.customers.js';
|
11
12
|
|
12
13
|
|
13
14
|
export const table_name = 'auth_users';
|
@@ -31,17 +32,19 @@ const upsert = (driver) => {
|
|
31
32
|
confirmed_mail: item.confirmed_mail ? 1 : 0,
|
32
33
|
email: item.email,
|
33
34
|
handle: item.email,
|
34
|
-
password: item.password,
|
35
|
+
password: item.password ?? null,
|
35
36
|
created_at: item.created_at,
|
36
37
|
updated_at: item.updated_at,
|
37
38
|
id: item.id,
|
39
|
+
attributes: JSON.stringify(item.attributes),
|
40
|
+
description: item.description,
|
41
|
+
active: item.active ? 1 : 0,
|
38
42
|
roles: JSON.stringify(item.roles),
|
39
43
|
firstname: item.firstname,
|
40
44
|
lastname: item.lastname
|
41
45
|
});
|
42
46
|
}
|
43
47
|
);
|
44
|
-
return t.numInsertedOrUpdatedRows>0;
|
45
48
|
} catch(e) {
|
46
49
|
console.log(e);
|
47
50
|
return false;
|
@@ -74,7 +77,8 @@ const getByEmail = (driver) => {
|
|
74
77
|
return async (email) => {
|
75
78
|
return driver.client
|
76
79
|
.selectFrom('auth_users')
|
77
|
-
.selectAll()
|
80
|
+
.selectAll()
|
81
|
+
.where('email', '=', email)
|
78
82
|
.executeTakeFirst()
|
79
83
|
.then(sanitize);
|
80
84
|
}
|
@@ -85,21 +89,18 @@ const getByEmail = (driver) => {
|
|
85
89
|
* @returns {db_col["remove"]}
|
86
90
|
*/
|
87
91
|
const remove = (driver) => {
|
88
|
-
return async (
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
return false;
|
101
|
-
}
|
102
|
-
return true;
|
92
|
+
return async (handle_or_id) => {
|
93
|
+
// delete related auth user
|
94
|
+
// customers and auth_users have the same object-id and handle
|
95
|
+
let customer_handle_or_id = handle_or_id;
|
96
|
+
if(handle_or_id.startsWith('au_')) {
|
97
|
+
// found an id
|
98
|
+
const object_id = handle_or_id.split('_').at(-1);
|
99
|
+
customer_handle_or_id = 'cus_' + object_id;
|
100
|
+
}
|
101
|
+
return remove_customer_and_auth_user(driver)(
|
102
|
+
customer_handle_or_id
|
103
|
+
);
|
103
104
|
}
|
104
105
|
}
|
105
106
|
/**
|
@@ -148,8 +149,8 @@ const list = (driver) => {
|
|
148
149
|
|
149
150
|
/**
|
150
151
|
* @param {SQL} driver
|
151
|
-
* @return {db_col}
|
152
|
-
|
152
|
+
* @return {db_col}
|
153
|
+
*/
|
153
154
|
export const impl = (driver) => {
|
154
155
|
|
155
156
|
return {
|
package/src/con.collections.js
CHANGED
@@ -3,18 +3,18 @@
|
|
3
3
|
*/
|
4
4
|
import { SQL } from '../index.js'
|
5
5
|
import { report_document_media } from './con.images.js'
|
6
|
-
import {
|
6
|
+
import {
|
7
|
+
delete_entity_values_by_value_or_reporter_and_context, delete_me,
|
7
8
|
delete_media_of, delete_search_of, delete_tags_of,
|
8
9
|
insert_media_of, insert_search_of, insert_tags_of,
|
9
|
-
select_entity_ids_by_value_or_reporter,
|
10
10
|
regular_upsert_me, where_id_or_handle_table,
|
11
11
|
with_media, with_tags,
|
12
12
|
count_regular,
|
13
|
-
with_search
|
13
|
+
with_search
|
14
|
+
} from './con.shared.js'
|
14
15
|
import { sanitize, sanitize_array } from './utils.funcs.js'
|
15
16
|
import { query_to_eb, query_to_sort } from './utils.query.js'
|
16
17
|
|
17
|
-
|
18
18
|
export const table_name = 'collections'
|
19
19
|
|
20
20
|
/**
|
@@ -88,16 +88,16 @@ const remove = (driver) => {
|
|
88
88
|
async (trx) => {
|
89
89
|
|
90
90
|
// entities
|
91
|
-
await delete_tags_of(trx, id_or_handle);
|
92
|
-
await delete_search_of(trx, id_or_handle);
|
93
|
-
await delete_media_of(trx, id_or_handle);
|
91
|
+
await delete_tags_of(trx, id_or_handle, id_or_handle, table_name);
|
92
|
+
await delete_search_of(trx, id_or_handle, id_or_handle, table_name);
|
93
|
+
await delete_media_of(trx, id_or_handle, id_or_handle, table_name);
|
94
94
|
// PRODUCTS -> COLLECTIONS
|
95
|
-
await
|
95
|
+
await delete_entity_values_by_value_or_reporter_and_context('products_to_collections')(
|
96
96
|
trx, id_or_handle, id_or_handle
|
97
97
|
);
|
98
98
|
// STOREFRONT => COLLECTIONS
|
99
|
-
await
|
100
|
-
trx, id_or_handle, id_or_handle
|
99
|
+
await delete_entity_values_by_value_or_reporter_and_context('storefronts_to_other')(
|
100
|
+
trx, id_or_handle, id_or_handle, table_name
|
101
101
|
);
|
102
102
|
|
103
103
|
// delete me
|
@@ -120,7 +120,8 @@ const remove = (driver) => {
|
|
120
120
|
const list = (driver) => {
|
121
121
|
return async (query) => {
|
122
122
|
|
123
|
-
const items = await driver.client
|
123
|
+
const items = await driver.client
|
124
|
+
.selectFrom(table_name)
|
124
125
|
.selectAll()
|
125
126
|
.select(eb => [
|
126
127
|
with_tags(eb, eb.ref('collections.id'), driver.dialectType),
|
@@ -151,19 +152,27 @@ const list_collection_products = (driver) => {
|
|
151
152
|
|
152
153
|
const items = await driver.client
|
153
154
|
.selectFrom('products')
|
154
|
-
.
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
155
|
+
.innerJoin(
|
156
|
+
'products_to_collections',
|
157
|
+
'products_to_collections.entity_id',
|
158
|
+
'products.id'
|
159
|
+
)
|
160
|
+
.selectAll('products')
|
161
|
+
.select(
|
162
|
+
eb => [
|
163
|
+
with_media(eb, eb.ref('products.id'), driver.dialectType),
|
164
|
+
with_tags(eb, eb.ref('products.id'), driver.dialectType),
|
165
|
+
]
|
166
|
+
)
|
159
167
|
.where(
|
160
168
|
(eb) => eb.and(
|
161
169
|
[
|
162
170
|
query_to_eb(eb, query, 'products'),
|
163
|
-
eb(
|
164
|
-
|
165
|
-
eb, '
|
166
|
-
|
171
|
+
eb.or(
|
172
|
+
[
|
173
|
+
eb('products_to_collections.reporter', '=', handle_or_id),
|
174
|
+
eb('products_to_collections.value', '=', handle_or_id)
|
175
|
+
]
|
167
176
|
)
|
168
177
|
].filter(Boolean)
|
169
178
|
)
|
@@ -172,12 +181,104 @@ const list_collection_products = (driver) => {
|
|
172
181
|
.limit(query.limitToLast ?? query.limit ?? 10)
|
173
182
|
.execute();
|
174
183
|
|
184
|
+
// .compile();
|
185
|
+
// console.log(items[0])
|
186
|
+
|
175
187
|
if(query.limitToLast) items.reverse();
|
176
188
|
|
177
189
|
return sanitize_array(items);
|
178
190
|
}
|
179
191
|
}
|
180
192
|
|
193
|
+
/**
|
194
|
+
* @param {SQL} driver
|
195
|
+
* @returns {db_col["count_collection_products"]}
|
196
|
+
*/
|
197
|
+
const count_collection_products = (driver) => {
|
198
|
+
return async (handle_or_id, query={}) => {
|
199
|
+
|
200
|
+
const result = await driver.client
|
201
|
+
.selectFrom('products')
|
202
|
+
// .select('products.id')
|
203
|
+
.select(
|
204
|
+
(eb) => eb.fn.countAll().as('count')
|
205
|
+
)
|
206
|
+
.innerJoin(
|
207
|
+
'products_to_collections',
|
208
|
+
'products_to_collections.entity_id',
|
209
|
+
'products.id'
|
210
|
+
)
|
211
|
+
.where(
|
212
|
+
(eb) => eb.and(
|
213
|
+
[
|
214
|
+
query_to_eb(eb, query, 'products'),
|
215
|
+
eb.or(
|
216
|
+
[
|
217
|
+
eb('products_to_collections.reporter', '=', handle_or_id),
|
218
|
+
eb('products_to_collections.value', '=', handle_or_id)
|
219
|
+
]
|
220
|
+
)
|
221
|
+
].filter(Boolean)
|
222
|
+
)
|
223
|
+
)
|
224
|
+
.executeTakeFirst();
|
225
|
+
|
226
|
+
// console.log({result})
|
227
|
+
|
228
|
+
return Number(result.count);
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
// SELECT
|
234
|
+
// entity_to_tags_projections.value as tag
|
235
|
+
// FROM products
|
236
|
+
// INNER JOIN
|
237
|
+
// products_to_collections ON products.id = products_to_collections.entity_id
|
238
|
+
// INNER JOIN
|
239
|
+
// entity_to_tags_projections ON products.id = entity_to_tags_projections.entity_id
|
240
|
+
// WHERE products_to_collections.reporter = 'playstation-4-games'
|
241
|
+
// GROUP BY tag
|
242
|
+
|
243
|
+
/**
|
244
|
+
* @param {SQL} driver
|
245
|
+
* @returns {db_col["list_used_products_tags"]}
|
246
|
+
*/
|
247
|
+
const list_used_products_tags = (driver) => {
|
248
|
+
return async (handle_or_id) => {
|
249
|
+
|
250
|
+
const items = await driver.client
|
251
|
+
.selectFrom('products')
|
252
|
+
.innerJoin(
|
253
|
+
'products_to_collections',
|
254
|
+
'products_to_collections.entity_id',
|
255
|
+
'products.id'
|
256
|
+
)
|
257
|
+
.innerJoin(
|
258
|
+
'entity_to_tags_projections',
|
259
|
+
'entity_to_tags_projections.entity_id',
|
260
|
+
'products.id'
|
261
|
+
)
|
262
|
+
.select('entity_to_tags_projections.value as tag')
|
263
|
+
.where(
|
264
|
+
(eb) => eb.or(
|
265
|
+
[
|
266
|
+
eb('products_to_collections.reporter', '=', handle_or_id),
|
267
|
+
eb('products_to_collections.value', '=', handle_or_id)
|
268
|
+
]
|
269
|
+
)
|
270
|
+
)
|
271
|
+
.groupBy('tag')
|
272
|
+
.execute();
|
273
|
+
|
274
|
+
// .compile();
|
275
|
+
// console.log(items[0])
|
276
|
+
|
277
|
+
return items.map(e => e.tag);
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
|
181
282
|
/**
|
182
283
|
* @param {SQL} driver
|
183
284
|
*
|
@@ -187,13 +288,13 @@ const list_collection_products = (driver) => {
|
|
187
288
|
export const impl = (driver) => {
|
188
289
|
|
189
290
|
return {
|
190
|
-
|
191
291
|
get: get(driver),
|
192
292
|
upsert: upsert(driver),
|
193
293
|
remove: remove(driver),
|
194
294
|
list: list(driver),
|
195
295
|
list_collection_products: list_collection_products(driver),
|
296
|
+
count_collection_products: count_collection_products(driver),
|
297
|
+
list_used_products_tags: list_used_products_tags(driver),
|
196
298
|
count: count_regular(driver, table_name),
|
197
|
-
|
198
299
|
}
|
199
300
|
}
|
package/src/con.customers.js
CHANGED
@@ -87,26 +87,31 @@ const getByEmail = (driver) => {
|
|
87
87
|
* @param {SQL} driver
|
88
88
|
* @returns {db_col["remove"]}
|
89
89
|
*/
|
90
|
-
const remove = (driver) => {
|
91
|
-
return async (
|
90
|
+
export const remove = (driver) => {
|
91
|
+
return async (handle_or_id) => {
|
92
92
|
try {
|
93
93
|
await driver.client.transaction().execute(
|
94
94
|
async (trx) => {
|
95
95
|
|
96
|
-
const valid_auth_id = `au_${id.split('_').at(-1)}`
|
97
96
|
// entities
|
98
|
-
await
|
99
|
-
await
|
100
|
-
await
|
101
|
-
|
102
|
-
// delete related auth user
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
await delete_tags_of(trx, handle_or_id, handle_or_id, table_name);
|
98
|
+
await delete_search_of(trx, handle_or_id, handle_or_id, table_name);
|
99
|
+
await delete_media_of(trx, handle_or_id, handle_or_id, table_name);
|
100
|
+
|
101
|
+
{ // delete related auth user
|
102
|
+
// customers and auth_users have the same object-id and handle
|
103
|
+
let auth_user_handle_or_id = handle_or_id;
|
104
|
+
if(handle_or_id.startsWith('cus_')) {
|
105
|
+
// found an id
|
106
|
+
const object_id = handle_or_id.split('_').at(-1);
|
107
|
+
auth_user_handle_or_id = 'au_' + object_id;
|
108
|
+
}
|
109
|
+
|
110
|
+
await delete_me(trx, 'auth_users', auth_user_handle_or_id);
|
111
|
+
}
|
107
112
|
|
108
|
-
// delete
|
109
|
-
await delete_me(trx, table_name,
|
113
|
+
// delete customer
|
114
|
+
await delete_me(trx, table_name, handle_or_id);
|
110
115
|
}
|
111
116
|
);
|
112
117
|
} catch(e) {
|
@@ -150,8 +155,6 @@ const list = (driver) => {
|
|
150
155
|
|
151
156
|
/**
|
152
157
|
* @param {SQL} driver
|
153
|
-
*
|
154
|
-
*
|
155
158
|
* @returns {db_col["list_customer_orders"]}
|
156
159
|
*/
|
157
160
|
const list_customer_orders = (driver) => {
|
@@ -187,6 +190,37 @@ const list_customer_orders = (driver) => {
|
|
187
190
|
}
|
188
191
|
}
|
189
192
|
|
193
|
+
/**
|
194
|
+
* @param {SQL} driver
|
195
|
+
* @returns {db_col["count_customer_orders"]}
|
196
|
+
*/
|
197
|
+
const count_customer_orders = (driver) => {
|
198
|
+
return async (id, query) => {
|
199
|
+
|
200
|
+
const result = await driver.client
|
201
|
+
.selectFrom('orders')
|
202
|
+
.select(
|
203
|
+
(eb) => eb.fn.countAll().as('count')
|
204
|
+
)
|
205
|
+
.where(
|
206
|
+
(eb) => eb.and(
|
207
|
+
[
|
208
|
+
query_to_eb(eb, query, table_name),
|
209
|
+
eb.or(
|
210
|
+
[
|
211
|
+
eb('_customer_id', '=', id),
|
212
|
+
eb('_customer_email', '=', id),
|
213
|
+
]
|
214
|
+
)
|
215
|
+
].filter(Boolean)
|
216
|
+
)
|
217
|
+
)
|
218
|
+
.executeTakeFirst();
|
219
|
+
|
220
|
+
return Number(result.count);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
190
224
|
/**
|
191
225
|
* @param {SQL} driver
|
192
226
|
* @return {db_col}}
|
@@ -200,6 +234,7 @@ export const impl = (driver) => {
|
|
200
234
|
remove: remove(driver),
|
201
235
|
list: list(driver),
|
202
236
|
list_customer_orders: list_customer_orders(driver),
|
237
|
+
count_customer_orders: count_customer_orders(driver),
|
203
238
|
count: count_regular(driver, table_name),
|
204
239
|
}
|
205
240
|
}
|