@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.
@@ -2,15 +2,19 @@
2
2
  * @import { db_discounts as db_col } from '@storecraft/core/database'
3
3
  */
4
4
  import { enums } from '@storecraft/core/api'
5
+ import {
6
+ helper_compute_product_extra_search_keywords_because_of_discount_side_effect_for_db,
7
+ helper_compute_product_extra_tags_because_of_discount_side_effect_for_db
8
+ } from '@storecraft/core/database'
5
9
  import { SQL } from '../index.js'
6
10
  import { discount_to_conjunctions } from './con.discounts.utils.js'
7
- import { delete_entity_values_by_value_or_reporter,
11
+ import {
12
+ delete_entity_values_by_value_or_reporter_and_context,
8
13
  delete_me, delete_media_of, delete_search_of,
9
14
  delete_tags_of, insert_media_of, insert_search_of,
10
- insert_tags_of, select_entity_ids_by_value_or_reporter, regular_upsert_me, where_id_or_handle_table,
11
- with_media, with_tags,
12
- count_regular,
13
- with_search} from './con.shared.js'
15
+ insert_tags_of, regular_upsert_me, where_id_or_handle_table,
16
+ with_media, with_tags, count_regular, with_search,
17
+ } from './con.shared.js'
14
18
  import { sanitize, sanitize_array } from './utils.funcs.js'
15
19
  import { query_to_eb, query_to_sort } from './utils.query.js'
16
20
  import { report_document_media } from './con.images.js'
@@ -36,14 +40,25 @@ const upsert = (driver) => {
36
40
  // PRODUCTS => DISCOUNTS
37
41
  //
38
42
  // remove all products relation to this discount
39
- await delete_entity_values_by_value_or_reporter('products_to_discounts')(
43
+ await delete_entity_values_by_value_or_reporter_and_context('products_to_discounts')(
40
44
  trx, item.id, item.handle);
45
+
46
+ const extra_search_for_products =
47
+ helper_compute_product_extra_search_keywords_because_of_discount_side_effect_for_db(item);
41
48
 
42
- await delete_entity_values_by_value_or_reporter('entity_to_search_terms')(
43
- trx, `discount:${item.id}`);
44
- await delete_entity_values_by_value_or_reporter('entity_to_search_terms')(
45
- trx, `discount:${item.handle}`);
46
-
49
+ const extra_tags_for_products =
50
+ helper_compute_product_extra_tags_because_of_discount_side_effect_for_db(item);
51
+
52
+ // maybe i should confine these to `context`=`products`
53
+ for(const extra_search of extra_search_for_products) {
54
+ await delete_entity_values_by_value_or_reporter_and_context('entity_to_search_terms')(
55
+ trx, extra_search);
56
+ }
57
+ for(const extra_tag of extra_tags_for_products) {
58
+ await delete_entity_values_by_value_or_reporter_and_context('entity_to_tags_projections')(
59
+ trx, extra_tag);
60
+ }
61
+
47
62
  if(item.active && item.application.id===enums.DiscountApplicationEnum.Auto.id) {
48
63
  // make connections
49
64
  await trx
@@ -63,37 +78,44 @@ const upsert = (driver) => {
63
78
  )
64
79
  ).execute();
65
80
 
66
- await trx
67
- .insertInto('entity_to_search_terms')
68
- .columns(['entity_handle', 'entity_id', 'value'])
69
- .expression(eb =>
70
- eb.selectFrom('products')
71
- .select(eb => [
72
- 'handle as entity_handle',
73
- 'id as entity_id',
74
- eb.val(`discount:${item.id}`).as('value'),
75
- ]
76
- )
77
- .where(
78
- eb => eb.and(discount_to_conjunctions(eb, item))
79
- )
80
- ).execute();
81
-
82
- await trx
83
- .insertInto('entity_to_search_terms')
84
- .columns(['entity_handle', 'entity_id', 'value'])
85
- .expression(eb =>
86
- eb.selectFrom('products')
87
- .select(eb => [
88
- 'handle as entity_handle',
89
- 'id as entity_id',
90
- eb.val(`discount:${item.handle}`).as('value'),
91
- ]
92
- )
93
- .where(
94
- eb => eb.and(discount_to_conjunctions(eb, item))
95
- )
96
- ).execute();
81
+ for(const extra_search of extra_search_for_products) {
82
+ await trx
83
+ .insertInto('entity_to_search_terms')
84
+ .columns(['entity_handle', 'entity_id', 'value', 'reporter', 'context'])
85
+ .expression(eb =>
86
+ eb.selectFrom('products')
87
+ .select(eb => [
88
+ 'handle as entity_handle',
89
+ 'id as entity_id',
90
+ eb.val(extra_search).as('value'),
91
+ eb.val(item.id).as('reporter'),
92
+ eb.val('products').as('context'),
93
+ ]
94
+ )
95
+ .where(
96
+ eb => eb.and(discount_to_conjunctions(eb, item))
97
+ )
98
+ ).execute();
99
+ }
100
+ for(const extra_tag of extra_tags_for_products) {
101
+ await trx
102
+ .insertInto('entity_to_tags_projections')
103
+ .columns(['entity_handle', 'entity_id', 'value', 'reporter', 'context'])
104
+ .expression(eb =>
105
+ eb.selectFrom('products')
106
+ .select(eb => [
107
+ 'handle as entity_handle',
108
+ 'id as entity_id',
109
+ eb.val(extra_tag).as('value'),
110
+ eb.val(item.id).as('reporter'),
111
+ eb.val('products').as('context'),
112
+ ]
113
+ )
114
+ .where(
115
+ eb => eb.and(discount_to_conjunctions(eb, item))
116
+ )
117
+ ).execute();
118
+ }
97
119
  }
98
120
 
99
121
  ///
@@ -158,17 +180,48 @@ const remove = (driver) => {
158
180
  async (trx) => {
159
181
 
160
182
  // entities
161
- await delete_search_of(trx, id_or_handle);
162
- await delete_media_of(trx, id_or_handle);
163
- await delete_tags_of(trx, id_or_handle);
183
+ await delete_tags_of(trx, id_or_handle, id_or_handle, table_name);
184
+ await delete_search_of(trx, id_or_handle, id_or_handle, table_name);
185
+ await delete_media_of(trx, id_or_handle, id_or_handle, table_name);
164
186
  // delete products -> discounts
165
187
  // PRODUCTS => DISCOUNTS
166
- await delete_entity_values_by_value_or_reporter('products_to_discounts')(
188
+ await delete_entity_values_by_value_or_reporter_and_context('products_to_discounts')(
167
189
  trx, id_or_handle, id_or_handle);
168
190
  // STOREFRONT => DISCOUNTS
169
- await delete_entity_values_by_value_or_reporter('storefronts_to_other')(
170
- trx, id_or_handle, id_or_handle
191
+ await delete_entity_values_by_value_or_reporter_and_context('storefronts_to_other')(
192
+ trx, id_or_handle, id_or_handle, table_name
171
193
  );
194
+ // discount might have published search terms and tags for other products,
195
+ // so let's remove
196
+ const discount_handle_and_id = await trx
197
+ .selectFrom('discounts')
198
+ .select(['handle', 'id'])
199
+ .where(
200
+ (eb) => eb.or([
201
+ eb('discounts.handle', '=', id_or_handle),
202
+ eb('discounts.id', '=', id_or_handle)
203
+ ])
204
+ )
205
+ .executeTakeFirst();
206
+
207
+ const extra_search_for_products =
208
+ helper_compute_product_extra_search_keywords_because_of_discount_side_effect_for_db(
209
+ discount_handle_and_id
210
+ );
211
+
212
+ const extra_tags_for_products =
213
+ helper_compute_product_extra_tags_because_of_discount_side_effect_for_db(
214
+ discount_handle_and_id
215
+ );
216
+
217
+ for(const extra_search of extra_search_for_products) {
218
+ await delete_entity_values_by_value_or_reporter_and_context('entity_to_search_terms')(
219
+ trx, extra_search);
220
+ }
221
+ for(const extra_tag of extra_tags_for_products) {
222
+ await delete_entity_values_by_value_or_reporter_and_context('entity_to_tags_projections')(
223
+ trx, extra_tag);
224
+ }
172
225
 
173
226
  // delete me
174
227
  await delete_me(trx, table_name, id_or_handle);
@@ -220,13 +273,14 @@ const list = (driver) => {
220
273
  const list_discount_products = (driver) => {
221
274
  return async (handle_or_id, query={}) => {
222
275
 
223
- // TODO: try to rewrite this with JOIN to products_to_discounts ON products.id=entity_id
224
- // TODO: and then filter by value==handle_or_id_of_discount
225
- // TODO: I think it will be better and more memory efficient for the database
226
- // TODO: becausee right now it loads all the eligible products ids in advance
227
276
  const items = await driver.client
228
277
  .selectFrom('products')
229
- .selectAll()
278
+ .innerJoin(
279
+ 'products_to_discounts',
280
+ 'products_to_discounts.entity_id',
281
+ 'products.id'
282
+ )
283
+ .selectAll('products')
230
284
  .select(eb => [
231
285
  with_media(eb, eb.ref('products.id'), driver.dialectType),
232
286
  with_tags(eb, eb.ref('products.id'), driver.dialectType),
@@ -235,12 +289,13 @@ const list_discount_products = (driver) => {
235
289
  (eb) => eb.and(
236
290
  [
237
291
  query_to_eb(eb, query, 'products'),
238
- eb('products.id', 'in',
239
- eb => select_entity_ids_by_value_or_reporter( // select all the product ids by discount id
240
- eb, 'products_to_discounts', handle_or_id
241
- )
292
+ eb.or(
293
+ [
294
+ eb('products_to_discounts.reporter', '=', handle_or_id),
295
+ eb('products_to_discounts.value', '=', handle_or_id)
296
+ ]
242
297
  )
243
- ].filter(Boolean)
298
+ ].filter(Boolean)
244
299
  )
245
300
  )
246
301
  .orderBy(query_to_sort(query, 'products'))
@@ -253,6 +308,84 @@ const list_discount_products = (driver) => {
253
308
  }
254
309
  }
255
310
 
311
+
312
+
313
+ /**
314
+ * @param {SQL} driver
315
+ * @returns {db_col["list_all_discount_products_tags"]}
316
+ */
317
+ const list_all_discount_products_tags = (driver) => {
318
+ return async (handle_or_id) => {
319
+
320
+ const items = await driver.client
321
+ .selectFrom('products')
322
+ .innerJoin(
323
+ 'products_to_discounts',
324
+ 'products_to_discounts.entity_id',
325
+ 'products.id'
326
+ )
327
+ .innerJoin(
328
+ 'entity_to_tags_projections',
329
+ 'entity_to_tags_projections.entity_id',
330
+ 'products.id'
331
+ )
332
+ .select('entity_to_tags_projections.value as tag')
333
+ .where(
334
+ (eb) => eb.or(
335
+ [
336
+ eb('products_to_discounts.reporter', '=', handle_or_id),
337
+ eb('products_to_discounts.value', '=', handle_or_id)
338
+ ]
339
+ )
340
+ )
341
+ .groupBy('tag')
342
+ .execute();
343
+
344
+ // .compile();
345
+ // console.log(items[0])
346
+
347
+ return items.map(e => e.tag);
348
+ }
349
+ }
350
+
351
+
352
+ /**
353
+ * @param {SQL} driver
354
+ * @returns {db_col["count_discount_products"]}
355
+ */
356
+ const count_discount_products = (driver) => {
357
+ return async (handle_or_id, query={}) => {
358
+
359
+ const result = await driver.client
360
+ .selectFrom('products')
361
+ .innerJoin(
362
+ 'products_to_discounts',
363
+ 'products_to_discounts.entity_id',
364
+ 'products.id'
365
+ )
366
+ .select(
367
+ (eb) => eb.fn.countAll().as('count')
368
+ )
369
+ .where(
370
+ (eb) => eb.and(
371
+ [
372
+ query_to_eb(eb, query, 'products'),
373
+ eb.or(
374
+ [
375
+ eb('products_to_discounts.reporter', '=', handle_or_id),
376
+ eb('products_to_discounts.value', '=', handle_or_id)
377
+ ]
378
+ )
379
+ ].filter(Boolean)
380
+ )
381
+ )
382
+ .executeTakeFirst();
383
+
384
+ return Number(result.count);
385
+ }
386
+ }
387
+
388
+
256
389
  /**
257
390
  * @param {SQL} driver
258
391
  * @return {db_col}}
@@ -265,6 +398,8 @@ export const impl = (driver) => {
265
398
  remove: remove(driver),
266
399
  list: list(driver),
267
400
  list_discount_products: list_discount_products(driver),
401
+ count_discount_products: count_discount_products(driver),
402
+ list_all_discount_products_tags: list_all_discount_products_tags(driver),
268
403
  count: count_regular(driver, table_name),
269
404
  }
270
405
  }
@@ -25,25 +25,26 @@ const extract_abs_number = v => {
25
25
  /**
26
26
  * @param {ExpressionBuilder<Database, 'products'>} eb
27
27
  * @param {keyof Pick<Database, 'entity_to_tags_projections' | 'products_to_collections'>} table
28
- * @param {BinaryOperator} op
29
28
  * @param {string[]} value
30
29
  */
31
- const eb_in = (eb, table, op, value) => {
30
+ const eb_in = (eb, table, value) => {
32
31
  return eb.exists(
33
32
  eb => eb
34
- .selectFrom(table)
35
- .select('id')
36
- .where(
37
- eb => eb.and([
33
+ .selectFrom(table)
34
+ .select('id')
35
+ .where(
36
+ eb => eb.and(
37
+ [
38
38
  eb.or(
39
39
  [
40
40
  eb(`${table}.entity_id`, '=', eb.ref('products.id')),
41
41
  eb(`${table}.entity_handle`, '=', eb.ref('products.handle')),
42
42
  ]
43
43
  ),
44
- eb(`${table}.value`, op, value)
45
- ])
44
+ eb(`${table}.value`, 'in', value)
45
+ ]
46
46
  )
47
+ )
47
48
  )
48
49
  }
49
50
 
@@ -111,7 +112,7 @@ export const discount_to_conjunctions = (eb, d) => {
111
112
 
112
113
  conjunctions.push(
113
114
  eb_in(
114
- eb, 'entity_to_tags_projections', 'in',
115
+ eb, 'entity_to_tags_projections',
115
116
  cast
116
117
  )
117
118
  );
@@ -126,7 +127,7 @@ export const discount_to_conjunctions = (eb, d) => {
126
127
  conjunctions.push(
127
128
  eb.not(
128
129
  eb_in(
129
- eb, 'entity_to_tags_projections', 'in',
130
+ eb, 'entity_to_tags_projections',
130
131
  cast
131
132
  )
132
133
  )
@@ -142,7 +143,7 @@ export const discount_to_conjunctions = (eb, d) => {
142
143
  // PROBLEM: we only have ids, but use handles in the filters
143
144
  conjunctions.push(
144
145
  eb_in(
145
- eb, 'products_to_collections', 'in',
146
+ eb, 'products_to_collections',
146
147
  cast.map(c => c.id)
147
148
  )
148
149
  );
@@ -157,7 +158,7 @@ export const discount_to_conjunctions = (eb, d) => {
157
158
  conjunctions.push(
158
159
  eb.not(
159
160
  eb_in(
160
- eb, 'products_to_collections', 'in',
161
+ eb, 'products_to_collections',
161
162
  cast.map(c => c.id)
162
163
  )
163
164
  )
@@ -1,14 +1,25 @@
1
+ /**
2
+ * @import { AliasableExpression, Expression} from 'kysely'
3
+ * @import { SelectQueryBuilderExpression } from './con.helpers.json.js'
4
+ * @import { SqlDialectType } from '../types.public.js'
5
+ * @import { RawBuilder, Simplify } from 'kysely'
6
+ */
7
+
1
8
  import {
2
9
  AliasNode, ColumnNode, ExpressionWrapper, IdentifierNode,
3
10
  ReferenceNode, SelectQueryNode, TableNode, ValueNode } from 'kysely'
4
- import { sqlite_jsonArrayFrom, sqlite_jsonObjectFrom,
5
- sqlite_stringArrayFrom } from './con.helpers.json.sqlite.js'
6
- import { pg_jsonArrayFrom, pg_jsonObjectFrom,
7
- pg_stringArrayFrom } from './con.helpers.json.postgres.js'
8
- import { mysql_jsonArrayFrom, mysql_jsonObjectFrom,
9
- mysql_stringArrayFrom } from './con.helpers.json.mysql.js'
10
- import { mssql_jsonArrayFrom, mssql_jsonObjectFrom,
11
- mssql_stringArrayFrom } from './con.helpers.json.mssql.js'
11
+ import {
12
+ sqlite_jsonArrayFrom, sqlite_jsonObjectFrom,
13
+ sqlite_stringArrayFrom
14
+ } from './con.helpers.json.sqlite.js'
15
+ import {
16
+ pg_jsonArrayFrom, pg_jsonObjectFrom,
17
+ pg_stringArrayFrom
18
+ } from './con.helpers.json.postgres.js'
19
+ import {
20
+ mysql_jsonArrayFrom, mysql_jsonObjectFrom,
21
+ mysql_stringArrayFrom
22
+ } from './con.helpers.json.mysql.js'
12
23
 
13
24
 
14
25
  /**
@@ -20,7 +31,7 @@ import { mssql_jsonArrayFrom, mssql_jsonObjectFrom,
20
31
 
21
32
  /**
22
33
  * @template O
23
- * @typedef {import('kysely').AliasableExpression<O> & _SelectQueryBuilderExpression<O>} SelectQueryBuilderExpression
34
+ * @typedef {AliasableExpression<O> & _SelectQueryBuilderExpression<O>} SelectQueryBuilderExpression
24
35
  * @property {boolean} isSelectQueryBuilder
25
36
  * @property {(): SelectQueryNode} toOperationNode
26
37
  */
@@ -30,10 +41,10 @@ import { mssql_jsonArrayFrom, mssql_jsonObjectFrom,
30
41
  *
31
42
  * @param {SelectQueryNode} node
32
43
  * @param {string} table
33
- * @returns {import('kysely').Expression<unknown>[] }
44
+ * @returns {Expression<unknown>[] }
34
45
  */
35
46
  export function getJsonObjectArgs(node, table) {
36
- /** @type {import('kysely').Expression<unknown>[] } */
47
+ /** @type {Expression<unknown>[] } */
37
48
  const args = []
38
49
 
39
50
  for (const { selection: s } of node.selections ?? []) {
@@ -58,7 +69,7 @@ export function getJsonObjectArgs(node, table) {
58
69
  /**
59
70
  *
60
71
  * @param {string} col
61
- * @returns {import('kysely').Expression<unknown> }
72
+ * @returns {Expression<unknown> }
62
73
  */
63
74
  function colName(col) {
64
75
  return new ExpressionWrapper(ValueNode.createImmediate(col))
@@ -68,7 +79,7 @@ function colName(col) {
68
79
  *
69
80
  * @param {string} table
70
81
  * @param {string} col
71
- * @returns {import('kysely').Expression<unknown> }
82
+ * @returns {Expression<unknown> }
72
83
  */
73
84
  function colRef(table, col) {
74
85
  return new ExpressionWrapper(
@@ -80,7 +91,7 @@ function colRef(table, col) {
80
91
  * @template O
81
92
  * @param {SelectQueryBuilderExpression<O>} expr
82
93
  * @param {string} table
83
- * @returns {import('kysely').Expression<unknown>}
94
+ * @returns {Expression<unknown>}
84
95
  */
85
96
  export const extract_first_selection = (expr, table) => {
86
97
  /** @type {any} */
@@ -88,7 +99,7 @@ export const extract_first_selection = (expr, table) => {
88
99
  /** @type {SelectQueryNode} */
89
100
  const s__ = s_;
90
101
  const s = s__.selections[0].selection;
91
- /** @type {import('kysely').Expression<unknown>} */
102
+ /** @type {Expression<unknown>} */
92
103
  let arg;
93
104
  if (ReferenceNode.is(s) && ColumnNode.is(s.column)) {
94
105
  // console.log('arg ', s)
@@ -126,11 +137,10 @@ export const extract_first_selection = (expr, table) => {
126
137
  * result[0].pets[0].pet_id
127
138
  * result[0].pets[0].name
128
139
  * ```
129
- *
130
140
  * @template O
131
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
132
- * @param {import('../types.public.d.ts').SqlDialectType} sql_type
133
- * @returns {import('kysely').RawBuilder<import('kysely').Simplify<O>[]>}
141
+ * @param {SelectQueryBuilderExpression<O>} expr
142
+ * @param {SqlDialectType} sql_type
143
+ * @returns {RawBuilder<Simplify<O>[]>}
134
144
  */
135
145
  export function jsonArrayFrom(expr, sql_type) {
136
146
  switch(sql_type) {
@@ -140,8 +150,6 @@ export function jsonArrayFrom(expr, sql_type) {
140
150
  return pg_jsonArrayFrom(expr);
141
151
  case 'MYSQL':
142
152
  return mysql_jsonArrayFrom(expr);
143
- // case 'MSSQL':
144
- // return mssql_jsonArrayFrom(expr);
145
153
  default:
146
154
  throw new Error(`sql_type=${sql_type} NOT SUPPORTED !`);
147
155
  }
@@ -169,8 +177,8 @@ export function jsonArrayFrom(expr, sql_type) {
169
177
  * result[0].pets = ['name1', 'name2', ....]
170
178
  * ```
171
179
  * @template O
172
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
173
- * @param {import('../types.public.d.ts').SqlDialectType} sql_type
180
+ * @param {SelectQueryBuilderExpression<O>} expr
181
+ * @param {SqlDialectType} sql_type
174
182
  */
175
183
  export function stringArrayFrom(expr, sql_type) {
176
184
  switch(sql_type) {
@@ -180,8 +188,6 @@ export function stringArrayFrom(expr, sql_type) {
180
188
  return pg_stringArrayFrom(expr);
181
189
  case 'MYSQL':
182
190
  return mysql_stringArrayFrom(expr);
183
- // case 'MSSQL':
184
- // return mssql_stringArrayFrom(expr);
185
191
  default:
186
192
  throw new Error(`sql_type=${sql_type} NOT SUPPORTED !`);
187
193
  }
@@ -211,9 +217,9 @@ export function stringArrayFrom(expr, sql_type) {
211
217
  * ```
212
218
  *
213
219
  * @template O
214
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
215
- * @param {import('../types.public.d.ts').SqlDialectType} sql_type
216
- * @returns {import('kysely').RawBuilder<import('kysely').Simplify<O> | null>}
220
+ * @param {SelectQueryBuilderExpression<O>} expr
221
+ * @param {SqlDialectType} sql_type
222
+ * @returns {RawBuilder<Simplify<O> | null>}
217
223
  */
218
224
  export function jsonObjectFrom(expr, sql_type) {
219
225
  switch(sql_type) {
@@ -223,8 +229,6 @@ export function jsonObjectFrom(expr, sql_type) {
223
229
  return pg_jsonObjectFrom(expr);
224
230
  case 'MYSQL':
225
231
  return mysql_jsonObjectFrom(expr);
226
- // case 'MSSQL':
227
- // return mssql_jsonObjectFrom(expr);
228
232
  default:
229
233
  throw new Error(`sql_type=${sql_type} NOT SUPPORTED !`);
230
234
  }
@@ -1,5 +1,13 @@
1
+ /**
2
+ * @import { AliasableExpression, Expression} from 'kysely'
3
+ * @import { SelectQueryBuilderExpression } from './con.helpers.json.js'
4
+ * @import { SqlDialectType } from '../types.public.js'
5
+ * @import { RawBuilder, Simplify } from 'kysely'
6
+ */
1
7
  import { SelectQueryNode, sql } from "kysely"
2
- import { extract_first_selection, getJsonObjectArgs } from "./con.helpers.json.js"
8
+ import {
9
+ extract_first_selection, getJsonObjectArgs
10
+ } from "./con.helpers.json.js"
3
11
 
4
12
  /**
5
13
  * A MySQL helper for aggregating a subquery into a JSON array.
@@ -48,13 +56,18 @@ import { extract_first_selection, getJsonObjectArgs } from "./con.helpers.json.j
48
56
  * ```
49
57
  *
50
58
  * @template O
51
- * @param {import("./con.helpers.json.js").SelectQueryBuilderExpression<O>} expr
52
- * @returns {import("kysely").RawBuilder<import("kysely").Simplify<O>[]>}
59
+ * @param {SelectQueryBuilderExpression<O>} expr
60
+ * @returns {RawBuilder<Simplify<O>[]>}
53
61
  */
54
62
  export function mysql_jsonArrayFrom(expr) {
55
- return sql`(select cast(coalesce(json_arrayagg(json_object(${sql.join(
56
- getMysqlJsonObjectArgs(expr.toOperationNode(), 'agg'),
57
- )})), '[]') as json) from ${expr} as agg)`
63
+ return sql`(select cast(coalesce(json_arrayagg(json_object(${
64
+ sql.join(
65
+ getMysqlJsonObjectArgs(
66
+ /** @type {SelectQueryNode} */(expr.toOperationNode()),
67
+ 'agg'
68
+ ),
69
+ )
70
+ })), '[]') as json) from ${expr} as agg)`
58
71
  }
59
72
 
60
73
  /**
@@ -105,8 +118,8 @@ export function mysql_jsonArrayFrom(expr) {
105
118
  * from "person"
106
119
  * ```
107
120
  * @template O
108
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
109
- * @returns {import('kysely').RawBuilder<string[]>}
121
+ * @param {SelectQueryBuilderExpression<O>} expr
122
+ * @returns {RawBuilder<string[]>}
110
123
  */
111
124
  export function mysql_stringArrayFrom(expr) {
112
125
  const arg = extract_first_selection(expr, 'agg');
@@ -163,13 +176,18 @@ export function mysql_stringArrayFrom(expr) {
163
176
  * ```
164
177
  *
165
178
  * @template O
166
- * @param {import("./con.helpers.json.js").SelectQueryBuilderExpression<O>} expr
167
- * @returns {import("kysely").RawBuilder<import("kysely").Simplify<O> | null>}
179
+ * @param {SelectQueryBuilderExpression<O>} expr
180
+ * @returns {RawBuilder<Simplify<O> | null>}
168
181
  */
169
182
  export function mysql_jsonObjectFrom(expr) {
170
- return sql`(select json_object(${sql.join(
171
- getMysqlJsonObjectArgs(expr.toOperationNode(), 'obj'),
172
- )}) from ${expr} as obj)`
183
+ return sql`(select json_object(${
184
+ sql.join(
185
+ getMysqlJsonObjectArgs(
186
+ /** @type {SelectQueryNode} */(expr.toOperationNode()),
187
+ 'obj'
188
+ ),
189
+ )
190
+ }) from ${expr} as obj)`
173
191
  }
174
192
 
175
193
  /**
@@ -212,21 +230,23 @@ export function mysql_jsonObjectFrom(expr) {
212
230
  * from "person"
213
231
  * ```
214
232
  *
215
- * @template {Record<string, import("kysely").Expression<unknown>>} O
233
+ * @template {Record<string, Expression<unknown>>} O
216
234
  * @param {O} obj
217
- * @returns {import("kysely").RawBuilder<import("kysely").Simplify<{[K in keyof O]: O[K] extends Expression<infer V> ? V : never}>>}
235
+ * @returns {RawBuilder<Simplify<{[K in keyof O]: O[K] extends Expression<infer V> ? V : never}>>}
218
236
  */
219
237
  export function mysql_jsonBuildObject(obj) {
220
- return sql`json_object(${sql.join(
221
- Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]),
222
- )})`
238
+ return sql`json_object(${
239
+ sql.join(
240
+ Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]),
241
+ )
242
+ })`
223
243
  }
224
244
 
225
245
  /**
226
246
  *
227
247
  * @param {SelectQueryNode} node
228
248
  * @param {string} table
229
- * @returns {import("kysely").Expression<unknown>[]}
249
+ * @returns {Expression<unknown>[]}
230
250
  */
231
251
  function getMysqlJsonObjectArgs(node, table) {
232
252
  try {