@storecraft/database-sql-base 1.0.21 → 1.0.23
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/migrate.js +3 -35
- package/migrations.shared/00003_alter_auth_users.js +6 -0
- package/package.json +2 -2
- package/src/con.customers.js +3 -3
- package/src/con.discounts.js +1 -1
- package/src/con.discounts.utils.js +44 -37
- package/src/con.notifications.js +4 -2
- package/src/con.products.js +28 -94
- package/src/utils.query.js +47 -17
- package/utils.js +33 -0
package/migrate.js
CHANGED
@@ -101,44 +101,12 @@ export async function migrateToLatest(db_driver, release_db_upon_completion=true
|
|
101
101
|
if (error) {
|
102
102
|
console.error('failed to migrate')
|
103
103
|
console.error(JSON.stringify(error, null, 2))
|
104
|
+
console.error(JSON.stringify(results, null, 2))
|
104
105
|
process.exit(1)
|
105
106
|
}
|
106
107
|
|
108
|
+
console.log('Resolving migrations COMPLETE.')
|
109
|
+
|
107
110
|
if(release_db_upon_completion)
|
108
111
|
await db.destroy();
|
109
112
|
}
|
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
|
-
|
@@ -9,6 +9,12 @@ import { Kysely } from 'kysely'
|
|
9
9
|
*/
|
10
10
|
export async function up(db) {
|
11
11
|
|
12
|
+
// console.log(
|
13
|
+
// db.schema.alterTable('auth_users')
|
14
|
+
// .addColumn('firstname', 'text')
|
15
|
+
// .compile()
|
16
|
+
// )
|
17
|
+
|
12
18
|
await db.schema
|
13
19
|
.alterTable('auth_users')
|
14
20
|
.addColumn('firstname', 'text')
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@storecraft/database-sql-base",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.23",
|
4
4
|
"description": "Official SQL Database driver for storecraft",
|
5
5
|
"license": "MIT",
|
6
6
|
"author": "Tomer Shalev (https://github.com/store-craft)",
|
@@ -38,7 +38,7 @@
|
|
38
38
|
},
|
39
39
|
"dependencies": {
|
40
40
|
"@storecraft/core": "^1.0.0",
|
41
|
-
"kysely": "^0.
|
41
|
+
"kysely": "^0.28.1"
|
42
42
|
},
|
43
43
|
"devDependencies": {
|
44
44
|
"@types/better-sqlite3": "^7.6.9",
|
package/src/con.customers.js
CHANGED
@@ -195,7 +195,7 @@ const list_customer_orders = (driver) => {
|
|
195
195
|
* @returns {db_col["count_customer_orders"]}
|
196
196
|
*/
|
197
197
|
const count_customer_orders = (driver) => {
|
198
|
-
return async (
|
198
|
+
return async (customer_id_or_email, query) => {
|
199
199
|
|
200
200
|
const result = await driver.client
|
201
201
|
.selectFrom('orders')
|
@@ -208,8 +208,8 @@ const count_customer_orders = (driver) => {
|
|
208
208
|
query_to_eb(eb, query, table_name),
|
209
209
|
eb.or(
|
210
210
|
[
|
211
|
-
eb('_customer_id', '=',
|
212
|
-
eb('_customer_email', '=',
|
211
|
+
eb('_customer_id', '=', customer_id_or_email),
|
212
|
+
eb('_customer_email', '=', customer_id_or_email),
|
213
213
|
]
|
214
214
|
)
|
215
215
|
].filter(Boolean)
|
package/src/con.discounts.js
CHANGED
@@ -135,7 +135,7 @@ const upsert = (driver) => {
|
|
135
135
|
application: JSON.stringify(item.application),
|
136
136
|
info: JSON.stringify(item.info),
|
137
137
|
_application_id: item.application.id,
|
138
|
-
_discount_type_id: item
|
138
|
+
_discount_type_id: item?.info?.details?.meta?.id ?? -1,
|
139
139
|
});
|
140
140
|
}
|
141
141
|
);
|
@@ -1,8 +1,8 @@
|
|
1
1
|
/**
|
2
2
|
* @import {
|
3
|
-
* DiscountType,
|
4
|
-
*
|
5
|
-
*
|
3
|
+
* DiscountType, Filter_p_in_price_range, Filter_p_not_in_collections,
|
4
|
+
* Filter_p_in_collections, Filter_p_not_in_tags, Filter_p_in_tags,
|
5
|
+
* Filter_p_in_products, Filter_p_not_in_products
|
6
6
|
* } from '@storecraft/core/api'
|
7
7
|
* @import { Database } from '../types.sql.tables.js'
|
8
8
|
* @import { ExpressionBuilder, BinaryOperator } from 'kysely'
|
@@ -11,7 +11,11 @@ import { enums } from "@storecraft/core/api";
|
|
11
11
|
|
12
12
|
/** @param {DiscountType} d */
|
13
13
|
const is_order_discount = d => {
|
14
|
-
return (
|
14
|
+
return (
|
15
|
+
(d.info.details.type===enums.DiscountMetaEnum.order.type) ||
|
16
|
+
// @ts-ignore
|
17
|
+
(d.info.details.meta?.type===enums.DiscountMetaEnum.order.type)
|
18
|
+
);
|
15
19
|
}
|
16
20
|
|
17
21
|
/** @param {DiscountType} d */
|
@@ -67,7 +71,7 @@ export const discount_to_conjunctions = (eb, d) => {
|
|
67
71
|
const filters = d.info.filters;
|
68
72
|
|
69
73
|
for(const filter of filters) {
|
70
|
-
const op = filter.meta.op;
|
74
|
+
const op = filter.op ?? filter.meta.op;
|
71
75
|
|
72
76
|
switch (op) {
|
73
77
|
case enums.FilterMetaEnum.p_all.op:
|
@@ -75,60 +79,60 @@ export const discount_to_conjunctions = (eb, d) => {
|
|
75
79
|
break;
|
76
80
|
case enums.FilterMetaEnum.p_in_products.op:
|
77
81
|
{
|
78
|
-
|
79
|
-
|
80
|
-
Array.isArray(filter?.value) ? filter.value : []
|
82
|
+
const cast_filter = /** @type {Filter_p_in_products} */ (
|
83
|
+
filter
|
81
84
|
);
|
82
|
-
|
85
|
+
const value = cast_filter?.value ?? [];
|
83
86
|
conjunctions.push(
|
84
87
|
eb(
|
85
88
|
'products.handle', 'in',
|
86
|
-
|
89
|
+
value.map(item => item.handle).filter(Boolean)
|
87
90
|
)
|
88
91
|
);
|
89
92
|
}
|
90
93
|
break;
|
91
94
|
case enums.FilterMetaEnum.p_not_in_products.op:
|
92
95
|
{
|
93
|
-
|
94
|
-
|
95
|
-
Array.isArray(filter?.value) ? filter.value : []
|
96
|
+
const cast_filter = /** @type {Filter_p_not_in_products} */ (
|
97
|
+
filter
|
96
98
|
);
|
99
|
+
const value = cast_filter?.value ?? [];
|
97
100
|
|
98
101
|
conjunctions.push(
|
99
102
|
eb(
|
100
103
|
'products.handle', 'not in',
|
101
|
-
|
104
|
+
value.map(item => item.handle).filter(Boolean)
|
102
105
|
)
|
103
106
|
);
|
104
107
|
}
|
105
108
|
break;
|
106
109
|
case enums.FilterMetaEnum.p_in_tags.op:
|
107
110
|
{
|
108
|
-
|
109
|
-
|
110
|
-
Array.isArray(filter?.value) ? filter.value : []
|
111
|
+
const cast_filter = /** @type {Filter_p_in_tags} */ (
|
112
|
+
filter
|
111
113
|
);
|
112
|
-
|
114
|
+
const value = cast_filter?.value ?? [];
|
115
|
+
|
113
116
|
conjunctions.push(
|
114
117
|
eb_in(
|
115
118
|
eb, 'entity_to_tags_projections',
|
116
|
-
|
119
|
+
value
|
117
120
|
)
|
118
121
|
);
|
119
122
|
}
|
120
123
|
break;
|
121
124
|
case enums.FilterMetaEnum.p_not_in_tags.op:
|
122
125
|
{
|
123
|
-
const
|
124
|
-
|
126
|
+
const cast_filter = /** @type {Filter_p_not_in_tags} */ (
|
127
|
+
filter
|
125
128
|
);
|
129
|
+
const value = cast_filter?.value ?? [];
|
126
130
|
|
127
131
|
conjunctions.push(
|
128
132
|
eb.not(
|
129
133
|
eb_in(
|
130
134
|
eb, 'entity_to_tags_projections',
|
131
|
-
|
135
|
+
value
|
132
136
|
)
|
133
137
|
)
|
134
138
|
);
|
@@ -136,30 +140,32 @@ export const discount_to_conjunctions = (eb, d) => {
|
|
136
140
|
break;
|
137
141
|
case enums.FilterMetaEnum.p_in_collections.op:
|
138
142
|
{
|
139
|
-
const
|
140
|
-
|
143
|
+
const cast_filter = /** @type {Filter_p_in_collections} */ (
|
144
|
+
filter
|
141
145
|
);
|
146
|
+
const value = cast_filter?.value ?? [];
|
142
147
|
|
143
148
|
// PROBLEM: we only have ids, but use handles in the filters
|
144
149
|
conjunctions.push(
|
145
150
|
eb_in(
|
146
151
|
eb, 'products_to_collections',
|
147
|
-
|
152
|
+
value.map(c => c.id)
|
148
153
|
)
|
149
154
|
);
|
150
155
|
}
|
151
156
|
break;
|
152
157
|
case enums.FilterMetaEnum.p_not_in_collections.op:
|
153
158
|
{
|
154
|
-
const
|
155
|
-
|
159
|
+
const cast_filter = /** @type {Filter_p_not_in_collections} */ (
|
160
|
+
filter
|
156
161
|
);
|
162
|
+
const value = cast_filter?.value ?? [];
|
157
163
|
|
158
164
|
conjunctions.push(
|
159
165
|
eb.not(
|
160
166
|
eb_in(
|
161
167
|
eb, 'products_to_collections',
|
162
|
-
|
168
|
+
value.map(c => c.id)
|
163
169
|
)
|
164
170
|
)
|
165
171
|
);
|
@@ -167,16 +173,17 @@ export const discount_to_conjunctions = (eb, d) => {
|
|
167
173
|
break;
|
168
174
|
case enums.FilterMetaEnum.p_in_price_range.op:
|
169
175
|
{
|
170
|
-
const
|
171
|
-
|
172
|
-
from: 0,
|
173
|
-
to: Number.POSITIVE_INFINITY,
|
174
|
-
...(filter?.value ?? {}),
|
175
|
-
}
|
176
|
+
const cast_filter = /** @type {Filter_p_in_price_range} */ (
|
177
|
+
filter
|
176
178
|
);
|
177
|
-
|
178
|
-
|
179
|
-
|
179
|
+
const value = /** @type {Filter_p_in_price_range["value"]} */({
|
180
|
+
from: 0,
|
181
|
+
to: Number.POSITIVE_INFINITY,
|
182
|
+
...(cast_filter?.value ?? {}),
|
183
|
+
});
|
184
|
+
|
185
|
+
const from = extract_abs_number(value.from);
|
186
|
+
const to = extract_abs_number(value.to);
|
180
187
|
|
181
188
|
const conj = { price: { $and: [] } };
|
182
189
|
|
package/src/con.notifications.js
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
* @import { db_notifications as db_col } from '@storecraft/core/database'
|
3
3
|
*/
|
4
4
|
import { SQL } from '../index.js'
|
5
|
-
import {
|
5
|
+
import {
|
6
|
+
count_regular, delete_me, delete_search_of,
|
6
7
|
insert_search_of, regular_upsert_me, where_id_or_handle_table,
|
7
|
-
with_search
|
8
|
+
with_search
|
9
|
+
} from './con.shared.js'
|
8
10
|
import { sanitize_array } from './utils.funcs.js'
|
9
11
|
import { query_to_eb, query_to_sort } from './utils.query.js'
|
10
12
|
|
package/src/con.products.js
CHANGED
@@ -75,6 +75,8 @@ const upsert = (driver) => {
|
|
75
75
|
d.info.filters, item
|
76
76
|
)
|
77
77
|
);
|
78
|
+
|
79
|
+
|
78
80
|
|
79
81
|
item.tags = union(
|
80
82
|
[
|
@@ -420,73 +422,6 @@ const list = (driver) => {
|
|
420
422
|
}
|
421
423
|
}
|
422
424
|
|
423
|
-
/**
|
424
|
-
* @param {SQL} driver
|
425
|
-
* @returns {db_col["list_all_product_collections"]}
|
426
|
-
*/
|
427
|
-
const list_product_collections = (driver) => {
|
428
|
-
return async (product_id_or_handle) => {
|
429
|
-
// we don't expect many collections per products,
|
430
|
-
// therefore we use the simple `get` method instead of a query
|
431
|
-
const item = await get(driver)(
|
432
|
-
product_id_or_handle, { expand: ['collections'] }
|
433
|
-
);
|
434
|
-
return item?.collections ?? []
|
435
|
-
}
|
436
|
-
}
|
437
|
-
|
438
|
-
/**
|
439
|
-
* @param {SQL} driver
|
440
|
-
* @returns {db_col["list_all_product_discounts"]}
|
441
|
-
*/
|
442
|
-
const list_product_discounts = (driver) => {
|
443
|
-
return async (product_id_or_handle) => {
|
444
|
-
// we don't expect many discounts per products,
|
445
|
-
// therefore we use the simple `get` method instead of a query
|
446
|
-
const item = await get(driver)(
|
447
|
-
product_id_or_handle, { expand: ['discounts'] }
|
448
|
-
);
|
449
|
-
return item?.discounts ?? []
|
450
|
-
}
|
451
|
-
}
|
452
|
-
|
453
|
-
/**
|
454
|
-
* @param {SQL} driver
|
455
|
-
*
|
456
|
-
* @returns {db_col["list_all_product_variants"]}
|
457
|
-
*/
|
458
|
-
const list_product_variants = (driver) => {
|
459
|
-
return async (product_id_or_handle) => {
|
460
|
-
// we don't expect many discounts per products,
|
461
|
-
// therefore we use the simple `get` method instead of a query
|
462
|
-
const item = await get(driver)(
|
463
|
-
product_id_or_handle, { expand: ['variants'] }
|
464
|
-
);
|
465
|
-
|
466
|
-
if(item && (`variants` in item))
|
467
|
-
return item.variants ?? [];
|
468
|
-
|
469
|
-
return [];
|
470
|
-
}
|
471
|
-
}
|
472
|
-
|
473
|
-
/**
|
474
|
-
* @param {SQL} driver
|
475
|
-
*
|
476
|
-
* @returns {db_col["list_all_related_products"]}
|
477
|
-
*/
|
478
|
-
const list_related_products = (driver) => {
|
479
|
-
return async (product_id_or_handle) => {
|
480
|
-
// we don't expect many discounts per products,
|
481
|
-
// therefore we use the simple `get` method instead of a query
|
482
|
-
const item = await get(driver)(
|
483
|
-
product_id_or_handle, { expand: ['related_products'] }
|
484
|
-
);
|
485
|
-
|
486
|
-
return item?.related_products ?? [];
|
487
|
-
}
|
488
|
-
}
|
489
|
-
|
490
425
|
/**
|
491
426
|
* @param {SQL} driver
|
492
427
|
* @returns {db_col["list_used_products_tags"]}
|
@@ -520,33 +455,36 @@ const list_used_products_tags = (driver) => {
|
|
520
455
|
*/
|
521
456
|
const changeStockOfBy = (driver) => {
|
522
457
|
return async (product_ids_or_handles, deltas) => {
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
458
|
+
try {
|
459
|
+
await driver.client.transaction().execute(
|
460
|
+
async (trx) => {
|
461
|
+
for(let ix=0; ix < product_ids_or_handles.length; ix++ ) {
|
462
|
+
const id = product_ids_or_handles[ix];
|
463
|
+
const delta = deltas[ix];
|
464
|
+
|
465
|
+
await trx
|
466
|
+
.updateTable('products')
|
467
|
+
.set(
|
468
|
+
eb => (
|
469
|
+
{
|
470
|
+
qty: eb('qty', '+', delta)
|
471
|
+
}
|
472
|
+
)
|
537
473
|
)
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
474
|
+
.where(
|
475
|
+
where_id_or_handle_table(id)
|
476
|
+
)
|
477
|
+
.execute()
|
478
|
+
}
|
544
479
|
}
|
545
|
-
|
546
|
-
)
|
480
|
+
);
|
481
|
+
} catch(e) {
|
482
|
+
console.log(e);
|
483
|
+
return false;
|
484
|
+
}
|
547
485
|
|
486
|
+
return true;
|
548
487
|
}
|
549
|
-
|
550
488
|
}
|
551
489
|
|
552
490
|
|
@@ -564,10 +502,6 @@ export const impl = (driver) => {
|
|
564
502
|
upsert: upsert(driver),
|
565
503
|
remove: remove(driver),
|
566
504
|
list: list(driver),
|
567
|
-
list_all_product_collections: list_product_collections(driver),
|
568
|
-
list_all_product_discounts: list_product_discounts(driver),
|
569
|
-
list_all_product_variants: list_product_variants(driver),
|
570
|
-
list_all_related_products: list_related_products(driver),
|
571
505
|
list_used_products_tags: list_used_products_tags(driver),
|
572
506
|
count: count_regular(driver, table_name),
|
573
507
|
}
|
package/src/utils.query.js
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
* @import { VQL } from '@storecraft/core/vql'
|
4
4
|
* @import { Database } from '../types.sql.tables.js'
|
5
5
|
* @import { BinaryOperator, ExpressionBuilder } from 'kysely'
|
6
|
+
* @import {DirectedOrderByStringReference, QueryableTables} from './utils.types.js'
|
6
7
|
*/
|
7
8
|
|
8
9
|
import { parse } from "@storecraft/core/vql";
|
@@ -18,7 +19,8 @@ import { parse } from "@storecraft/core/vql";
|
|
18
19
|
* @param {ExpressionBuilder<Database>} eb
|
19
20
|
* @param {Cursor} c
|
20
21
|
* @param {'>' | '>=' | '<' | '<='} relation
|
21
|
-
* @param {(x: [k: string, v: any]) => [k: string, v: any]} transformer
|
22
|
+
* @param {(x: [k: string, v: any]) => [k: string, v: any]} transformer
|
23
|
+
* Your chance to change key and value
|
22
24
|
*/
|
23
25
|
export const query_cursor_to_eb = (eb, c, relation, transformer=(x)=>x) => {
|
24
26
|
|
@@ -94,11 +96,20 @@ export const query_vql_node_to_eb = (eb, node, table_name) => {
|
|
94
96
|
[
|
95
97
|
eb.or(
|
96
98
|
[
|
97
|
-
eb(
|
98
|
-
|
99
|
+
eb(
|
100
|
+
`entity_to_search_terms.entity_id`, '=',
|
101
|
+
eb.ref(`${table_name}.id`)
|
102
|
+
),
|
103
|
+
eb(
|
104
|
+
`entity_to_search_terms.entity_handle`, '=',
|
105
|
+
eb.ref(`${table_name}.handle`)
|
106
|
+
),
|
99
107
|
]
|
100
108
|
),
|
101
|
-
eb(
|
109
|
+
eb(
|
110
|
+
`entity_to_search_terms.value`, 'like',
|
111
|
+
node.value.toLowerCase()
|
112
|
+
)
|
102
113
|
]
|
103
114
|
)
|
104
115
|
)
|
@@ -129,7 +140,9 @@ export const query_vql_node_to_eb = (eb, node, table_name) => {
|
|
129
140
|
* @param {QueryableTables} table_name
|
130
141
|
*/
|
131
142
|
export const query_vql_to_eb = (eb, root, table_name) => {
|
132
|
-
return root ?
|
143
|
+
return root ?
|
144
|
+
query_vql_node_to_eb(eb, root, table_name) :
|
145
|
+
undefined;
|
133
146
|
}
|
134
147
|
|
135
148
|
|
@@ -169,15 +182,31 @@ export const query_to_eb = (eb, q={}, table_name) => {
|
|
169
182
|
|
170
183
|
// compute index clauses
|
171
184
|
if(q.startAt) {
|
172
|
-
clauses.push(
|
185
|
+
clauses.push(
|
186
|
+
query_cursor_to_eb(
|
187
|
+
eb, q.startAt, asc ? '>=' : '<=', transformer
|
188
|
+
)
|
189
|
+
);
|
173
190
|
} else if(q.startAfter) {
|
174
|
-
clauses.push(
|
191
|
+
clauses.push(
|
192
|
+
query_cursor_to_eb(
|
193
|
+
eb, q.startAfter, asc ? '>' : '<', transformer
|
194
|
+
)
|
195
|
+
);
|
175
196
|
}
|
176
197
|
|
177
198
|
if(q.endAt) {
|
178
|
-
clauses.push(
|
199
|
+
clauses.push(
|
200
|
+
query_cursor_to_eb(
|
201
|
+
eb, q.endAt, asc ? '<=' : '>=', transformer
|
202
|
+
)
|
203
|
+
);
|
179
204
|
} else if(q.endBefore) {
|
180
|
-
clauses.push(
|
205
|
+
clauses.push(
|
206
|
+
query_cursor_to_eb(
|
207
|
+
eb, q.endBefore, asc ? '<' : '>', transformer
|
208
|
+
)
|
209
|
+
);
|
181
210
|
}
|
182
211
|
|
183
212
|
// compute VQL clauses
|
@@ -187,7 +216,10 @@ export const query_to_eb = (eb, q={}, table_name) => {
|
|
187
216
|
}
|
188
217
|
} catch(e) {}
|
189
218
|
|
190
|
-
const vql_clause = query_vql_to_eb(
|
219
|
+
const vql_clause = query_vql_to_eb(
|
220
|
+
eb, q.vqlParsed, table_name
|
221
|
+
);
|
222
|
+
|
191
223
|
vql_clause && clauses.push(vql_clause);
|
192
224
|
|
193
225
|
return eb.and(clauses);
|
@@ -198,12 +230,6 @@ const SIGN = {
|
|
198
230
|
'-1': 'desc'
|
199
231
|
}
|
200
232
|
|
201
|
-
// export type DirectedOrderByStringReference<DB, TB extends keyof DB, O> = `${StringReference<DB, TB> | (keyof O & string)} ${OrderByDirection}`;
|
202
|
-
|
203
|
-
/**
|
204
|
-
* @import {DirectedOrderByStringReference, QueryableTables} from './utils.types.js'
|
205
|
-
*/
|
206
|
-
// OE extends OrderByExpression<DB, TB, O>
|
207
233
|
/**
|
208
234
|
* Convert an API Query into mongo dialect, also sanitize.
|
209
235
|
* @template {Record<string, any>} [Type=Record<string, any>]
|
@@ -227,5 +253,9 @@ export const query_to_sort = (q={}, table) => {
|
|
227
253
|
)
|
228
254
|
// it's too complicated to map each ket to table column.
|
229
255
|
// kysely was designed to do this in place
|
230
|
-
return (
|
256
|
+
return (
|
257
|
+
/** @type {DirectedOrderByStringReference<Database, Table, Database[Table]>[]} */ (
|
258
|
+
sort
|
259
|
+
)
|
260
|
+
);
|
231
261
|
}
|
package/utils.js
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
/**
|
2
|
+
* @description Just for education and debugging, do not use !!!
|
3
|
+
* @param {string} stmt
|
4
|
+
* @param {any[] | Record<string, any>} params
|
5
|
+
*/
|
6
|
+
export const prepare_and_bind = (stmt='', params=[]) => {
|
7
|
+
const params_object = Array.isArray(params) ?
|
8
|
+
params.reduce((a, v, idx) => ({ ...a, [idx+1]: v}), {}) :
|
9
|
+
params;
|
10
|
+
|
11
|
+
let current = 0;
|
12
|
+
let result = ''
|
13
|
+
let index_run = 1;
|
14
|
+
for (let m of stmt.matchAll(/\?[0-9]*/g)) {
|
15
|
+
result += stmt.slice(current, m.index);
|
16
|
+
|
17
|
+
const match_string = m[0];
|
18
|
+
let index_access = match_string.length > 1 ?
|
19
|
+
Number(match_string.slice(1)) :
|
20
|
+
index_run;
|
21
|
+
|
22
|
+
result += "'" + params_object[index_access] + "'";
|
23
|
+
|
24
|
+
current = m.index + m[0].length;
|
25
|
+
index_run+=1;
|
26
|
+
}
|
27
|
+
|
28
|
+
result += stmt.slice(current);
|
29
|
+
|
30
|
+
return result;
|
31
|
+
}
|
32
|
+
|
33
|
+
|