@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.
@@ -1,3 +1,9 @@
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 { sql} from 'kysely'
2
8
  import { extract_first_selection } from './con.helpers.json.js';
3
9
 
@@ -50,8 +56,8 @@ import { extract_first_selection } from './con.helpers.json.js';
50
56
  * from "person"
51
57
  * ```
52
58
  * @template O
53
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
54
- * @returns {import('kysely').RawBuilder<string[]>}
59
+ * @param {SelectQueryBuilderExpression<O>} expr
60
+ * @returns {RawBuilder<string[]>}
55
61
  */
56
62
  export function pg_stringArrayFrom(expr) {
57
63
  const arg = extract_first_selection(expr, 'agg');
@@ -107,8 +113,8 @@ export function pg_stringArrayFrom(expr) {
107
113
  * from "person"
108
114
  * ```
109
115
  * @template O
110
- * @param {import('kysely').Expression<O>} expr
111
- * @returns {import('kysely').RawBuilder<import('kysely').Simplify<O>[]>}
116
+ * @param {Expression<O>} expr
117
+ * @returns {RawBuilder<Simplify<O>[]>}
112
118
  */
113
119
  export function pg_jsonArrayFrom(expr) {
114
120
  return sql`(select coalesce(json_agg(agg), '[]') from ${expr} as agg)`
@@ -165,8 +171,8 @@ export function pg_jsonArrayFrom(expr) {
165
171
  * from "person"
166
172
  * ```
167
173
  * @template O
168
- * @param {import('kysely').Expression<O>} expr
169
- * @returns {import('kysely').RawBuilder<import('kysely').Simplify<O> | null>}
174
+ * @param {Expression<O>} expr
175
+ * @returns {RawBuilder<Simplify<O> | null>}
170
176
  */
171
177
  export function pg_jsonObjectFrom(expr) {
172
178
  return sql`(select to_json(obj) from ${expr} as obj)`
@@ -211,9 +217,9 @@ export function pg_jsonObjectFrom(expr) {
211
217
  * ) as "name"
212
218
  * from "person"
213
219
  * ```
214
- * @template {Record<string, import('kysely').Expression<unknown>>} O
220
+ * @template {Record<string, Expression<unknown>>} O
215
221
  * @param {O} obj
216
- * @returns { import('kysely').RawBuilder<import('kysely').Simplify<{[K in keyof O]: O[K] extends Expression<infer V> ? V : never}>>}
222
+ * @returns {RawBuilder<Simplify<{[K in keyof O]: O[K] extends Expression<infer V> ? V : never}>>}
217
223
  >}
218
224
  */
219
225
  export function pg_jsonBuildObject(obj) {
@@ -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 SQLite helper for aggregating a subquery into a JSON array.
@@ -54,14 +62,19 @@ import { extract_first_selection, getJsonObjectArgs } from './con.helpers.json.j
54
62
  * from "person"
55
63
  * ```
56
64
  * @template O
57
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
58
- * @returns {import('kysely').RawBuilder<import('kysely').Simplify<O>[]>}
65
+ * @param {SelectQueryBuilderExpression<O>} expr
66
+ * @returns {RawBuilder<Simplify<O>[]>}
59
67
  */
60
68
  export function sqlite_jsonArrayFrom(expr) {
61
69
 
62
- return sql`(select coalesce(json_group_array(json_object(${sql.join(
63
- getSqliteJsonObjectArgs(expr.toOperationNode(), 'agg')
64
- )})), '[]') from ${expr} as agg)`
70
+ return sql`(select coalesce(json_group_array(json_object(${
71
+ sql.join(
72
+ getSqliteJsonObjectArgs(
73
+ /** @type {SelectQueryNode} */(expr.toOperationNode()),
74
+ 'agg'
75
+ )
76
+ )
77
+ })), '[]') from ${expr} as agg)`
65
78
  }
66
79
 
67
80
 
@@ -113,12 +126,14 @@ export function sqlite_jsonArrayFrom(expr) {
113
126
  * from "person"
114
127
  * ```
115
128
  * @template O
116
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
117
- * @returns {import('kysely').RawBuilder<string[]>}
129
+ * @param {SelectQueryBuilderExpression<O>} expr
130
+ * @returns {RawBuilder<string[]>}
118
131
  */
119
132
  export function sqlite_stringArrayFrom(expr) {
120
133
  const arg = extract_first_selection(expr, 'agg');
121
- return sql`(select coalesce(json_group_array(${sql.join([arg])}), '[]') from ${expr} as agg)`
134
+ return sql`(select coalesce(json_group_array(${
135
+ sql.join([arg])
136
+ }), '[]') from ${expr} as agg)`
122
137
  }
123
138
 
124
139
  /**
@@ -177,13 +192,18 @@ export function sqlite_stringArrayFrom(expr) {
177
192
  * ```
178
193
  *
179
194
  * @template O
180
- * @param {import('./con.helpers.json.js').SelectQueryBuilderExpression<O>} expr
181
- * @returns {import('kysely').RawBuilder<import('kysely').Simplify<O> | null>}
195
+ * @param {SelectQueryBuilderExpression<O>} expr
196
+ * @returns {RawBuilder<Simplify<O> | null>}
182
197
  */
183
198
  export function sqlite_jsonObjectFrom(expr) {
184
- return sql`(select json_object(${sql.join(
185
- getSqliteJsonObjectArgs(expr.toOperationNode(), 'obj'),
186
- )}) from ${expr} as obj)`
199
+ return sql`(select json_object(${
200
+ sql.join(
201
+ getSqliteJsonObjectArgs(
202
+ /** @type {SelectQueryNode} */(expr.toOperationNode()),
203
+ 'obj'
204
+ ),
205
+ )
206
+ }) from ${expr} as obj)`
187
207
  }
188
208
 
189
209
  /**
@@ -250,7 +270,7 @@ export function sqlite_jsonObjectFrom(expr) {
250
270
  *
251
271
  * @param {SelectQueryNode} node
252
272
  * @param {string} table
253
- * @returns {import('kysely').Expression<unknown>[]}
273
+ * @returns {Expression<unknown>[]}
254
274
  */
255
275
  function getSqliteJsonObjectArgs(node, table) {
256
276
  try {
@@ -21,9 +21,10 @@ const upsert = (driver) => {
21
21
  const t = await c.transaction().execute(
22
22
  async (trx) => {
23
23
  await insert_search_of(
24
- trx, [...item.search, ...search_terms],
24
+ trx,
25
+ [...item.search, ...search_terms],
25
26
  item.id, item.id, table_name
26
- );
27
+ );
27
28
  await regular_upsert_me(trx, table_name, {
28
29
  handle: null,
29
30
  created_at: item.created_at,
@@ -51,10 +52,13 @@ const upsertBulk = (driver) => {
51
52
  return async (items, search_terms) => {
52
53
  const results = [];
53
54
  // for (const it of items)
54
- for(let ix = 0; ix < items.length; ix++)
55
- results.push(await upsert(driver)(
56
- items[ix], search_terms?.[ix])
57
- );
55
+ for(let ix = 0; ix < items.length; ix++) {
56
+ results.push(
57
+ await upsert(driver)(
58
+ items[ix], search_terms?.[ix]
59
+ )
60
+ );
61
+ }
58
62
 
59
63
  return results.every(b => b);
60
64
  }
package/src/con.orders.js CHANGED
@@ -30,6 +30,7 @@ const upsert = (driver) => {
30
30
  await insert_tags_of(trx, item.tags, item.id, item.id, table_name);
31
31
  await report_document_media(driver)(item, trx);
32
32
  await regular_upsert_me(trx, table_name, {
33
+ active: 1,
33
34
  attributes: JSON.stringify(item.attributes),
34
35
  description: item.description,
35
36
  created_at: item.created_at,
@@ -104,9 +105,9 @@ const remove = (driver) => {
104
105
  async (trx) => {
105
106
 
106
107
  // entities
107
- await delete_search_of(trx, id_or_handle);
108
- await delete_media_of(trx, id_or_handle);
109
- await delete_tags_of(trx, id_or_handle);
108
+ await delete_tags_of(trx, id_or_handle, id_or_handle, table_name);
109
+ await delete_search_of(trx, id_or_handle, id_or_handle, table_name);
110
+ await delete_media_of(trx, id_or_handle, id_or_handle, table_name);
110
111
  // delete me
111
112
  await delete_me(trx, table_name, id_or_handle);
112
113
  }
package/src/con.posts.js CHANGED
@@ -5,7 +5,7 @@
5
5
  import { SQL } from '../index.js'
6
6
  import { stringArrayFrom } from './con.helpers.json.js'
7
7
  import { report_document_media } from './con.images.js'
8
- import { count_regular, delete_entity_values_by_value_or_reporter,
8
+ import { count_regular, delete_entity_values_by_value_or_reporter_and_context,
9
9
  delete_me, delete_media_of, delete_search_of, delete_tags_of,
10
10
  insert_media_of, insert_search_of, insert_tags_of,
11
11
  regular_upsert_me, where_id_or_handle_table,
@@ -85,12 +85,12 @@ const remove = (driver) => {
85
85
  async (trx) => {
86
86
 
87
87
  // entities
88
- await delete_search_of(trx, id_or_handle);
89
- await delete_media_of(trx, id_or_handle);
90
- await delete_tags_of(trx, id_or_handle);
88
+ await delete_tags_of(trx, id_or_handle, id_or_handle, table_name);
89
+ await delete_search_of(trx, id_or_handle, id_or_handle, table_name);
90
+ await delete_media_of(trx, id_or_handle, id_or_handle, table_name);
91
91
  // STOREFRONT => POSTS
92
- await delete_entity_values_by_value_or_reporter('storefronts_to_other')(
93
- trx, id_or_handle, id_or_handle
92
+ await delete_entity_values_by_value_or_reporter_and_context('storefronts_to_other')(
93
+ trx, id_or_handle, id_or_handle, table_name
94
94
  );
95
95
  // delete me
96
96
  await delete_me(trx, table_name, id_or_handle);
@@ -1,18 +1,20 @@
1
1
  /**
2
2
  * @import { ProductType, VariantType } from '@storecraft/core/api'
3
- * @import { db_products as db_col } from '@storecraft/core/database'
3
+ * @import { db_products as db_col, RegularGetOptions } from '@storecraft/core/database'
4
4
  * @import { Database } from '../types.sql.tables.js'
5
5
  */
6
6
 
7
7
  import { enums } from '@storecraft/core/api'
8
8
  import { SQL } from '../index.js'
9
- import { delete_entity_values_of_by_entity_id_or_handle, delete_me, delete_media_of,
9
+ import {
10
+ delete_entity_values_of_by_entity_id_or_handle_and_context,
11
+ delete_me, delete_media_of,
10
12
  delete_search_of, delete_tags_of,
11
13
  insert_entity_values_of, insert_media_of, insert_search_of,
12
14
  insert_tags_of, regular_upsert_me,
13
15
  where_id_or_handle_table, products_with_collections,
14
16
  with_tags, with_media,
15
- delete_entity_values_by_value_or_reporter,
17
+ delete_entity_values_by_value_or_reporter_and_context,
16
18
  products_with_discounts,
17
19
  products_with_variants,
18
20
  count_regular,
@@ -23,6 +25,10 @@ import { query_to_eb, query_to_sort } from './utils.query.js'
23
25
  import { Transaction } from 'kysely'
24
26
  import { report_document_media } from './con.images.js'
25
27
  import { union } from '@storecraft/core/api/utils.func.js'
28
+ import {
29
+ helper_compute_product_extra_tags_because_of_discount_side_effect_for_db,
30
+ helper_compute_product_extra_search_keywords_because_of_discount_side_effect_for_db
31
+ } from '@storecraft/core/database'
26
32
 
27
33
 
28
34
  export const table_name = 'products'
@@ -65,14 +71,28 @@ const upsert = (driver) => {
65
71
  ).execute();
66
72
 
67
73
  const eligible_discounts = discounts.filter(
68
- d => driver.app.api.pricing.test_product_filters_against_product(d.info.filters, item)
74
+ d => driver.app.api.pricing.test_product_filters_against_product(
75
+ d.info.filters, item
76
+ )
77
+ );
78
+
79
+ item.tags = union(
80
+ [
81
+ // remove old discount tags
82
+ item.tags?.filter(t => !t.startsWith('discount_')),
83
+ // add new discount tags
84
+ eligible_discounts.map(
85
+ helper_compute_product_extra_tags_because_of_discount_side_effect_for_db
86
+ ),
87
+ ]
69
88
  );
70
89
 
71
90
  search_terms = union(
72
91
  [
73
92
  search_terms,
74
- eligible_discounts.map(d => `discount:${d.handle}`),
75
- eligible_discounts.map(d => `discount:${d.id}`),
93
+ eligible_discounts.map(
94
+ helper_compute_product_extra_search_keywords_because_of_discount_side_effect_for_db
95
+ ),
76
96
  ]
77
97
  );
78
98
 
@@ -109,7 +129,7 @@ const upsert = (driver) => {
109
129
  // PRODUCTS => VARIANTS
110
130
  if(item && ('variant_hint' in item) && is_variant(item)) {
111
131
  // remove previous
112
- await delete_entity_values_by_value_or_reporter('products_to_variants')(
132
+ await delete_entity_values_by_value_or_reporter_and_context('products_to_variants')(
113
133
  trx, item.id, item.handle
114
134
  );
115
135
  // add
@@ -123,8 +143,8 @@ const upsert = (driver) => {
123
143
  // Explicit PRODUCTS => COLLECTIONS
124
144
  //
125
145
  // remove this product's old collections connections
126
- await delete_entity_values_of_by_entity_id_or_handle('products_to_collections')(
127
- trx, item.id, item.handle
146
+ await delete_entity_values_of_by_entity_id_or_handle_and_context('products_to_collections')(
147
+ trx, item.id
128
148
  );
129
149
  if(item.collections) {
130
150
  // add this product's new collections connections
@@ -138,8 +158,8 @@ const upsert = (driver) => {
138
158
  // Explicit PRODUCTS => Related Products
139
159
  //
140
160
  // remove this product's old collections connections
141
- await delete_entity_values_of_by_entity_id_or_handle('products_to_related_products')(
142
- trx, item.id, item.handle
161
+ await delete_entity_values_of_by_entity_id_or_handle_and_context('products_to_related_products')(
162
+ trx, item.id
143
163
  );
144
164
  if(item.related_products) {
145
165
  // add this product's new `related_products` connections
@@ -152,8 +172,8 @@ const upsert = (driver) => {
152
172
 
153
173
  // PRODUCTS => DISCOUNTS
154
174
  // remove this product's older connections to discounts
155
- await delete_entity_values_of_by_entity_id_or_handle('products_to_discounts')(
156
- trx, item.id, item.handle,
175
+ await delete_entity_values_of_by_entity_id_or_handle_and_context('products_to_discounts')(
176
+ trx, item.id
157
177
  );
158
178
  if(eligible_discounts) {
159
179
  // insert new connections to discounts
@@ -186,7 +206,8 @@ const get = (driver) => {
186
206
  const expand = options?.expand ?? ['*'];
187
207
  const expand_collections = expand.includes('*') || expand.includes('collections');
188
208
  const expand_discounts = expand.includes('*') || expand.includes('discounts');
189
- const expand_variants = expand.includes('*') || expand.includes('variants');
209
+ const expand_variants = expand.includes('*') ||
210
+ (/** @type {RegularGetOptions<ProductType>["expand"]} */(expand)).includes('variants');
190
211
  const expand_related_products = expand.includes('*') || expand.includes('related_products');
191
212
  const dtype = driver.config.dialect_type;
192
213
 
@@ -224,7 +245,8 @@ const getBulk = (driver) => {
224
245
  const expand = options?.expand ?? ['*'];
225
246
  const expand_collections = expand.includes('*') || expand.includes('collections');
226
247
  const expand_discounts = expand.includes('*') || expand.includes('discounts');
227
- const expand_variants = expand.includes('*') || expand.includes('variants');
248
+ const expand_variants = expand.includes('*') ||
249
+ (/** @type {RegularGetOptions<ProductType>["expand"]} */(expand)).includes('variants');
228
250
  const expand_related_products = expand.includes('*') || expand.includes('related_products');
229
251
  const dtype = driver.config.dialect_type;
230
252
 
@@ -275,19 +297,20 @@ const remove_internal = (driver) => {
275
297
  await delete_search_of(trx, product.id);
276
298
  await delete_media_of(trx, product.id);
277
299
  // PRODUCTS => COLLECTIONS
278
- await delete_entity_values_of_by_entity_id_or_handle('products_to_collections')(
279
- trx, product.id, product.handle
300
+ await delete_entity_values_of_by_entity_id_or_handle_and_context('products_to_collections')(
301
+ trx, product.id
280
302
  );
281
303
  // PRODUCTS => DISCOUNTS
282
- await delete_entity_values_of_by_entity_id_or_handle('products_to_discounts')(
283
- trx, product.id, product.handle
304
+ await delete_entity_values_of_by_entity_id_or_handle_and_context('products_to_discounts')(
305
+ trx, product.id
284
306
  );
285
307
  // STOREFRONT => PRODUCT
286
- await delete_entity_values_by_value_or_reporter('storefronts_to_other')(
287
- trx, product.id, product.handle
308
+ // TODO: this is problematic
309
+ await delete_entity_values_by_value_or_reporter_and_context('storefronts_to_other')(
310
+ trx, product.id, product.handle, table_name
288
311
  );
289
312
  // PRODUCTS => RELATED PRODUCT
290
- await delete_entity_values_by_value_or_reporter('products_to_related_products')(
313
+ await delete_entity_values_by_value_or_reporter_and_context('products_to_related_products')(
291
314
  trx, product.id, product.handle
292
315
  );
293
316
  // PRODUCT => VARIANTS
@@ -295,7 +318,7 @@ const remove_internal = (driver) => {
295
318
  {
296
319
  if(is_variant(product)) {
297
320
  // delete my reported connections
298
- await delete_entity_values_by_value_or_reporter('products_to_variants')(
321
+ await delete_entity_values_by_value_or_reporter_and_context('products_to_variants')(
299
322
  trx, product.id, product.handle
300
323
  );
301
324
  } else if(product && 'variants' in product) { // parent
@@ -303,8 +326,8 @@ const remove_internal = (driver) => {
303
326
  (product.variants ?? []).map(v => remove_internal(driver)(v, trx))
304
327
  );
305
328
  // if I am a parent product, delete my relations to all previous variants
306
- await delete_entity_values_of_by_entity_id_or_handle('products_to_variants')(
307
- trx, product.id, product.handle
329
+ await delete_entity_values_of_by_entity_id_or_handle_and_context('products_to_variants')(
330
+ trx, product.id
308
331
  );
309
332
  }
310
333
  }
@@ -399,7 +422,7 @@ const list = (driver) => {
399
422
 
400
423
  /**
401
424
  * @param {SQL} driver
402
- * @returns {db_col["list_product_collections"]}
425
+ * @returns {db_col["list_all_product_collections"]}
403
426
  */
404
427
  const list_product_collections = (driver) => {
405
428
  return async (product_id_or_handle) => {
@@ -414,7 +437,7 @@ const list_product_collections = (driver) => {
414
437
 
415
438
  /**
416
439
  * @param {SQL} driver
417
- * @returns {db_col["list_product_discounts"]}
440
+ * @returns {db_col["list_all_product_discounts"]}
418
441
  */
419
442
  const list_product_discounts = (driver) => {
420
443
  return async (product_id_or_handle) => {
@@ -430,7 +453,7 @@ const list_product_discounts = (driver) => {
430
453
  /**
431
454
  * @param {SQL} driver
432
455
  *
433
- * @returns {db_col["list_product_variants"]}
456
+ * @returns {db_col["list_all_product_variants"]}
434
457
  */
435
458
  const list_product_variants = (driver) => {
436
459
  return async (product_id_or_handle) => {
@@ -450,7 +473,7 @@ const list_product_variants = (driver) => {
450
473
  /**
451
474
  * @param {SQL} driver
452
475
  *
453
- * @returns {db_col["list_related_products"]}
476
+ * @returns {db_col["list_all_related_products"]}
454
477
  */
455
478
  const list_related_products = (driver) => {
456
479
  return async (product_id_or_handle) => {
@@ -464,6 +487,31 @@ const list_related_products = (driver) => {
464
487
  }
465
488
  }
466
489
 
490
+ /**
491
+ * @param {SQL} driver
492
+ * @returns {db_col["list_used_products_tags"]}
493
+ */
494
+ const list_used_products_tags = (driver) => {
495
+ return async () => {
496
+
497
+ const items = await driver.client
498
+ .selectFrom('products')
499
+ .innerJoin(
500
+ 'entity_to_tags_projections',
501
+ 'entity_to_tags_projections.entity_id',
502
+ 'products.id'
503
+ )
504
+ .select('entity_to_tags_projections.value as tag')
505
+ .groupBy('tag')
506
+ .execute();
507
+
508
+ // .compile();
509
+ // console.log(items[0])
510
+
511
+ return items.map(e => e.tag);
512
+ }
513
+ }
514
+
467
515
 
468
516
  /**
469
517
  * @param {SQL} driver
@@ -516,10 +564,11 @@ export const impl = (driver) => {
516
564
  upsert: upsert(driver),
517
565
  remove: remove(driver),
518
566
  list: list(driver),
519
- list_product_collections: list_product_collections(driver),
520
- list_product_discounts: list_product_discounts(driver),
521
- list_product_variants: list_product_variants(driver),
522
- list_related_products: list_related_products(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
+ list_used_products_tags: list_used_products_tags(driver),
523
572
  count: count_regular(driver, table_name),
524
573
  }
525
574
  }
package/src/con.search.js CHANGED
@@ -61,9 +61,7 @@ const resource_to_props = {
61
61
  }
62
62
 
63
63
  /**
64
- *
65
64
  * @param {string} id
66
- *
67
65
  * @returns {keyof db_driver["resources"]}
68
66
  */
69
67
  export const id_to_resource = id => {
@@ -80,8 +78,6 @@ export const id_to_resource = id => {
80
78
 
81
79
  /**
82
80
  * @param {SQL} driver
83
- *
84
- *
85
81
  * @returns {db_col["quicksearch"]}
86
82
  */
87
83
  export const quicksearch = (driver) => {
@@ -138,10 +134,8 @@ export const quicksearch = (driver) => {
138
134
 
139
135
  /**
140
136
  * @param {SQL} driver
141
- *
142
- *
143
137
  * @return {db_col}
144
- * */
138
+ */
145
139
  export const impl = (driver) => {
146
140
 
147
141
  return {
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import { ExpressionWrapper, Kysely } from 'kysely'
2
3
  import { jsonArrayFrom, stringArrayFrom } from './con.helpers.json.js'
3
4
  import { SQL } from '../index.js';