@storecraft/database-mongodb 1.0.1

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.
@@ -0,0 +1,232 @@
1
+ import { Collection } from 'mongodb'
2
+ import { MongoDB } from '../index.js'
3
+ import { count_regular, expand, get_regular, list_regular } from './con.shared.js'
4
+ import { handle_or_id, isDef, sanitize_array, to_objid } from './utils.funcs.js'
5
+ import { query_to_mongo } from './utils.query.js'
6
+ import { report_document_media } from './con.images.js'
7
+ import {
8
+ add_search_terms_relation_on, delete_me,
9
+ remove_entry_from_all_connection_of_relation,
10
+ save_me,
11
+ update_entry_on_all_connection_of_relation
12
+ } from './utils.relations.js'
13
+
14
+ /**
15
+ * @typedef {import('@storecraft/core/v-database').db_collections} db_col
16
+ */
17
+
18
+
19
+ const transactionOptions = {
20
+ readPreference: 'primary',
21
+ readConcern: { level: 'local' },
22
+ writeConcern: { w: 'majority' }
23
+ };
24
+
25
+ /**
26
+ * @param {MongoDB} d
27
+ *
28
+ *
29
+ * @returns {Collection<
30
+ * import('./utils.relations.js').WithRelations<db_col["$type_get"]>
31
+ * >}
32
+ */
33
+ const col = (d) => d.collection('collections');
34
+
35
+ /**
36
+ * @param {MongoDB} driver
37
+ * @returns {db_col["upsert"]}
38
+ */
39
+ const upsert = (driver) => {
40
+ return async (data, search_terms=[]) => {
41
+ data = {...data};
42
+ const objid = to_objid(data.id)
43
+ const session = driver.mongo_client.startSession();
44
+
45
+ try {
46
+ await session.withTransaction(
47
+ async () => {
48
+ // SEARCH
49
+ add_search_terms_relation_on(data, search_terms);
50
+
51
+ ////
52
+ // PRODUCT -> COLLECTION RELATION
53
+ ////
54
+ // update collection document in products, that reference this collection
55
+ await update_entry_on_all_connection_of_relation(
56
+ driver, 'products', 'collections', objid, data, session
57
+ );
58
+
59
+ ////
60
+ // STOREFRONTS -> COLLECTIONS RELATION
61
+ ////
62
+ await update_entry_on_all_connection_of_relation(
63
+ driver, 'storefronts', 'collections', objid, data, session
64
+ );
65
+
66
+ ////
67
+ // REPORT IMAGES USAGE
68
+ ////
69
+ await report_document_media(driver)(data, session);
70
+
71
+ // SAVE ME
72
+ await save_me(
73
+ driver, 'collections', objid, data, session
74
+ );
75
+
76
+ }, transactionOptions
77
+ );
78
+
79
+ } catch(e) {
80
+ return false;
81
+ } finally {
82
+ await session.endSession();
83
+ }
84
+
85
+ return true;
86
+ }
87
+
88
+ }
89
+
90
+ /**
91
+ * @param {MongoDB} driver
92
+ */
93
+ const get = (driver) => get_regular(driver, col(driver));
94
+
95
+ /**
96
+ * @param {MongoDB} driver
97
+ *
98
+ *
99
+ * @returns {db_col["remove"]}
100
+ */
101
+ const remove = (driver) => {
102
+ return async (id_or_handle) => {
103
+
104
+ const item = await col(driver).findOne(
105
+ handle_or_id(id_or_handle)
106
+ );
107
+
108
+ if(!item) return;
109
+
110
+ const objid = to_objid(item.id);
111
+ const session = driver.mongo_client.startSession();
112
+
113
+ try {
114
+ await session.withTransaction(
115
+ async () => {
116
+
117
+ ////
118
+ // PRODUCTS --> COLLECTIONS RELATION
119
+ ////
120
+ await remove_entry_from_all_connection_of_relation(
121
+ driver, 'products', 'collections', objid, session,
122
+ [
123
+ `col:${item.id}`, `col:${item.handle}`
124
+ ]
125
+ );
126
+
127
+ ////
128
+ // STOREFRONTS --> COLLECTIONS RELATION
129
+ ////
130
+ await remove_entry_from_all_connection_of_relation(
131
+ driver, 'storefronts', 'collections', objid, session
132
+ );
133
+
134
+ // DELETE ME
135
+ await delete_me(
136
+ driver, 'collections', objid, session
137
+ );
138
+
139
+ }, transactionOptions
140
+ );
141
+ } catch(e) {
142
+ console.log(e);
143
+
144
+ return false;
145
+ } finally {
146
+ await session.endSession();
147
+ }
148
+
149
+ return true;
150
+ }
151
+
152
+ }
153
+
154
+
155
+ /**
156
+ * @param {MongoDB} driver
157
+ */
158
+ const list = (driver) => list_regular(driver, col(driver));
159
+
160
+
161
+ /**
162
+ * @param {MongoDB} driver
163
+ */
164
+ const count = (driver) => count_regular(driver, col(driver));
165
+
166
+
167
+ /**
168
+ * @param {MongoDB} driver
169
+ *
170
+ *
171
+ * @returns {db_col["list_collection_products"]}
172
+ */
173
+ const list_collection_products = (driver) => {
174
+ return async (handle_or_id, query) => {
175
+
176
+ const { filter: filter_query, sort, reverse_sign } = query_to_mongo(query);
177
+
178
+ // console.log('query', query)
179
+ // console.log('filter', JSON.stringify(filter_query, null, 2))
180
+ // console.log('sort', sort)
181
+ // console.log('expand', query?.expand)
182
+
183
+ /**
184
+ * @type {import('mongodb').Filter<
185
+ * import('./utils.relations.js').WithRelations<
186
+ * import('@storecraft/core/v-api').ProductType |
187
+ * import('@storecraft/core/v-api').VariantType
188
+ * >
189
+ * >}
190
+ */
191
+ const filter = {
192
+ $and: [
193
+ { '_relations.search': `col:${handle_or_id}` },
194
+ ]
195
+ };
196
+
197
+ // add the query filter
198
+ isDef(filter_query) && filter.$and.push(filter_query);
199
+
200
+ const items = await driver.resources.products._col.find(
201
+ filter, {
202
+ sort, limit: reverse_sign==-1 ? query.limitToLast : query.limit
203
+ }
204
+ ).toArray();
205
+
206
+ if(reverse_sign==-1) items.reverse();
207
+
208
+ // try expand relations, that were asked
209
+ expand(items, query?.expand);
210
+
211
+ return sanitize_array(items);
212
+ }
213
+ }
214
+
215
+ /**
216
+ * @param {MongoDB} driver
217
+ *
218
+ *
219
+ * @return {db_col & { _col: ReturnType<col>}}
220
+ * */
221
+ export const impl = (driver) => {
222
+
223
+ return {
224
+ _col: col(driver),
225
+ get: get(driver),
226
+ upsert: upsert(driver),
227
+ remove: remove(driver),
228
+ list: list(driver),
229
+ count: count(driver),
230
+ list_collection_products: list_collection_products(driver)
231
+ }
232
+ }
@@ -0,0 +1,172 @@
1
+ import { Collection, ObjectId } from 'mongodb'
2
+ import { MongoDB } from '../index.js'
3
+ import { count_regular, get_regular, list_regular,
4
+ upsert_regular } from './con.shared.js'
5
+ import { isDef, sanitize_array, to_objid } from './utils.funcs.js'
6
+ import { query_to_mongo } from './utils.query.js';
7
+
8
+ /**
9
+ * @typedef {import('@storecraft/core/v-database').db_customers} db_col
10
+ */
11
+
12
+ /**
13
+ * @param {MongoDB} d
14
+ *
15
+ *
16
+ * @returns {Collection<db_col["$type_get"]>}
17
+ */
18
+ const col = (d) => d.collection('customers');
19
+
20
+ /**
21
+ * @param {MongoDB} driver
22
+ */
23
+ const upsert = (driver) => upsert_regular(driver, col(driver));
24
+
25
+ /**
26
+ * @param {MongoDB} driver
27
+ */
28
+ const get = (driver) => get_regular(driver, col(driver));
29
+
30
+ /**
31
+ * @param {MongoDB} driver
32
+ *
33
+ *
34
+ * @returns {db_col["getByEmail"]}
35
+ */
36
+ const getByEmail = (driver) => {
37
+ return async (email) => {
38
+ return col(driver).findOne(
39
+ { email }
40
+ );
41
+ }
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @param {string} email_or_id
47
+ *
48
+ *
49
+ * @returns { {_id:ObjectId} | {email: string}}
50
+ */
51
+ export const email_or_id = (email_or_id) => {
52
+ let r = {};
53
+ try {
54
+ r._id = to_objid(email_or_id);
55
+ } catch (e) {
56
+ r.email = email_or_id;
57
+ }
58
+ return r;
59
+ }
60
+
61
+ /**
62
+ * @param {MongoDB} driver
63
+ *
64
+ *
65
+ * @returns {db_col["remove"]}
66
+ */
67
+ const remove = (driver) => {
68
+ return async (id) => {
69
+
70
+ const session = driver.mongo_client.startSession();
71
+ try {
72
+ await session.withTransaction(
73
+ async () => {
74
+ const res = await col(driver).findOneAndDelete(
75
+ email_or_id(id),
76
+ { session }
77
+ );
78
+
79
+ // delete the auth user
80
+ if(res?.auth_id) {
81
+ await driver.resources.auth_users._col.deleteOne(
82
+ { _id: to_objid(res.auth_id) },
83
+ { session }
84
+ );
85
+ }
86
+ }
87
+ );
88
+ } catch(e) {
89
+ console.log(e);
90
+ return false;
91
+ } finally {
92
+ await session.endSession();
93
+ }
94
+
95
+ return true;
96
+ }
97
+ }
98
+
99
+
100
+ /**
101
+ * @param {MongoDB} driver
102
+ */
103
+ const list = (driver) => list_regular(driver, col(driver));
104
+
105
+ /**
106
+ * @param {MongoDB} driver
107
+ */
108
+ const count = (driver) => count_regular(driver, col(driver));
109
+
110
+ /**
111
+ * @param {MongoDB} driver
112
+ *
113
+ *
114
+ * @returns {db_col["list_customer_orders"]}
115
+ */
116
+ const list_customer_orders = (driver) => {
117
+ return async (customer_id, query) => {
118
+
119
+ const { filter: filter_query, sort, reverse_sign } = query_to_mongo(query);
120
+
121
+ console.log('query', query)
122
+ console.log('filter', JSON.stringify(filter_query, null, 2))
123
+ console.log('sort', sort)
124
+ console.log('expand', query?.expand)
125
+
126
+ /**
127
+ * @type {import('mongodb').Filter<
128
+ * import('./utils.relations.js').WithRelations<
129
+ * import('@storecraft/core/v-api').OrderData
130
+ * >
131
+ * >}
132
+ */
133
+ const filter = {
134
+ $and: [
135
+ {'_relations.search': `customer:${customer_id}` },
136
+ ]
137
+ };
138
+
139
+ // add the query filter
140
+ isDef(filter_query) && filter.$and.push(filter_query);
141
+
142
+ const items = await driver.resources.orders._col.find(
143
+ filter, {
144
+ sort, limit: reverse_sign==-1 ? query.limitToLast : query.limit
145
+ }
146
+ ).toArray();
147
+
148
+ if(reverse_sign==-1) items.reverse();
149
+
150
+ return sanitize_array(items);
151
+ }
152
+ }
153
+
154
+ /**
155
+ * @param {MongoDB} driver
156
+ *
157
+ *
158
+ * @return {db_col & { _col: ReturnType<col>}}
159
+ * */
160
+ export const impl = (driver) => {
161
+
162
+ return {
163
+ _col: col(driver),
164
+ get: get(driver),
165
+ getByEmail: getByEmail(driver),
166
+ upsert: upsert(driver),
167
+ remove: remove(driver),
168
+ list: list(driver),
169
+ count: count(driver),
170
+ list_customer_orders: list_customer_orders(driver)
171
+ }
172
+ }
@@ -0,0 +1,261 @@
1
+ import { Collection } from 'mongodb'
2
+ import { MongoDB } from '../index.js'
3
+ import {
4
+ count_regular, expand, get_bulk, get_regular, list_regular
5
+ } from './con.shared.js'
6
+ import {
7
+ handle_or_id, isDef, sanitize_array, to_objid
8
+ } from './utils.funcs.js'
9
+ import { discount_to_mongo_conjunctions } from './con.discounts.utils.js'
10
+ import { query_to_mongo } from './utils.query.js'
11
+ import { report_document_media } from './con.images.js'
12
+ import { enums } from '@storecraft/core/v-api'
13
+ import {
14
+ add_search_terms_relation_on, delete_me,
15
+ remove_entry_from_all_connection_of_relation,
16
+ save_me,
17
+ update_entry_on_all_connection_of_relation
18
+ } from './utils.relations.js'
19
+
20
+
21
+ /**
22
+ * @typedef {import('@storecraft/core/v-database').db_discounts} db_col
23
+ */
24
+
25
+
26
+ /**
27
+ * @param {MongoDB} d
28
+ *
29
+ *
30
+ * @returns {Collection<db_col["$type_get"]>}
31
+ */
32
+ const col = (d) => d.collection('discounts');
33
+
34
+
35
+ /**
36
+ * @param {MongoDB} driver
37
+ *
38
+ *
39
+ * @returns {db_col["upsert"]}
40
+ */
41
+ const upsert = (driver) => {
42
+ return async (data, search_terms=[]) => {
43
+
44
+ data = {...data};
45
+
46
+ const objid = to_objid(data.id);
47
+ const session = driver.mongo_client.startSession();
48
+
49
+ try {
50
+ await session.withTransaction(
51
+ async () => {
52
+ // SEARCH
53
+ add_search_terms_relation_on(data, search_terms);
54
+
55
+
56
+ ////
57
+ // PRODUCT --> DISCOUNTS RELATION
58
+ ////
59
+
60
+ // first remove discount from anywhere
61
+ await remove_entry_from_all_connection_of_relation(
62
+ driver, 'products', 'discounts', objid, session,
63
+ [
64
+ `discount:${data.handle}`, `discount:${data.id}`
65
+ ]
66
+ );
67
+
68
+ // now filter and update for products
69
+ if(data.active && data.application.id===enums.DiscountApplicationEnum.Auto.id) {
70
+ const conjunctions = discount_to_mongo_conjunctions(data);
71
+ await driver.resources.products._col.updateMany(
72
+ conjunctions.length ? { $and: conjunctions } : {},
73
+ {
74
+ $set: { [`_relations.discounts.entries.${objid.toString()}`]: data },
75
+ $addToSet: {
76
+ '_relations.discounts.ids': objid,
77
+ '_relations.search': {
78
+ $each : [ `discount:${data.handle}`, `discount:${data.id}` ]
79
+ }
80
+ },
81
+
82
+ },
83
+ { session }
84
+ );
85
+ }
86
+
87
+ ////
88
+ // STOREFRONTS -> DISCOUNTS RELATION
89
+ ////
90
+ await update_entry_on_all_connection_of_relation(
91
+ driver, 'storefronts', 'discounts', objid, data, session
92
+ );
93
+
94
+ ////
95
+ // REPORT IMAGES USAGE
96
+ ////
97
+ await report_document_media(driver)(data, session);
98
+
99
+ // SAVE ME
100
+
101
+ await save_me(
102
+ driver, 'discounts', objid, data, session
103
+ );
104
+
105
+ }
106
+ );
107
+ } catch(e) {
108
+ console.log(e);
109
+ return false;
110
+ } finally {
111
+ await session.endSession();
112
+ }
113
+
114
+
115
+ return true;
116
+ }
117
+ }
118
+
119
+ /**
120
+ * @param {MongoDB} driver
121
+ */
122
+ const get = (driver) => get_regular(driver, col(driver));
123
+
124
+
125
+ /**
126
+ * @param {MongoDB} driver
127
+ *
128
+ *
129
+ * @returns {db_col["remove"]}
130
+ */
131
+ const remove = (driver) => {
132
+ return async (id_or_handle) => {
133
+
134
+ const item = await col(driver).findOne(
135
+ handle_or_id(id_or_handle)
136
+ );
137
+
138
+ if(!item) return;
139
+
140
+ const objid = to_objid(item.id)
141
+ const session = driver.mongo_client.startSession();
142
+
143
+ try {
144
+ await session.withTransaction(
145
+ async () => {
146
+ ////
147
+ // PRODUCT -> DISCOUNTS RELATION
148
+ ////
149
+ await remove_entry_from_all_connection_of_relation(
150
+ driver, 'products', 'discounts', objid, session,
151
+ [
152
+ `discount:${item.handle}`, `discount:${item.id}`
153
+ ]
154
+ );
155
+
156
+ ////
157
+ // STOREFRONTS --> DISCOUNTS RELATION
158
+ ////
159
+ await remove_entry_from_all_connection_of_relation(
160
+ driver, 'storefronts', 'discounts', objid, session
161
+ );
162
+
163
+ // DELETE ME
164
+ await delete_me(
165
+ driver, 'discounts', objid, session
166
+ );
167
+
168
+ }
169
+ );
170
+ } catch(e) {
171
+ console.log(e);
172
+
173
+ return false;
174
+ } finally {
175
+ await session.endSession();
176
+ }
177
+
178
+ return true;
179
+ }
180
+
181
+ }
182
+
183
+ /**
184
+ * @param {MongoDB} driver
185
+ */
186
+ const list = (driver) => list_regular(driver, col(driver));
187
+
188
+
189
+ /**
190
+ * @param {MongoDB} driver
191
+ */
192
+ const count = (driver) => count_regular(driver, col(driver));
193
+
194
+
195
+ /**
196
+ * @param {MongoDB} driver
197
+ *
198
+ *
199
+ * @returns {db_col["list_discount_products"]}
200
+ */
201
+ const list_discount_products = (driver) => {
202
+ return async (handle_or_id, query) => {
203
+
204
+ const { filter: filter_query, sort, reverse_sign } = query_to_mongo(query);
205
+
206
+ // console.log('query', query)
207
+ // console.log('filter', JSON.stringify(filter_query, null, 2))
208
+ // console.log('sort', sort)
209
+ // console.log('expand', query?.expand)
210
+
211
+ /**
212
+ * @type {import('mongodb').Filter<
213
+ * import('./utils.relations.js').WithRelations<
214
+ * import('@storecraft/core/v-api').ProductType |
215
+ * import('@storecraft/core/v-api').VariantType
216
+ * >
217
+ * >}
218
+ */
219
+ const filter = {
220
+ $and: [
221
+ { '_relations.search': `discount:${handle_or_id}` },
222
+ ]
223
+ };
224
+
225
+ // add the query filter
226
+ isDef(filter_query) && filter.$and.push(filter_query);
227
+
228
+ const items = await driver.resources.products._col.find(
229
+ filter, {
230
+ sort, limit: reverse_sign==-1 ? query.limitToLast : query.limit
231
+ }
232
+ ).toArray();
233
+
234
+ if(reverse_sign==-1) items.reverse();
235
+
236
+ // try expand relations, that were asked
237
+ expand(items, query?.expand);
238
+
239
+ return sanitize_array(items);
240
+ }
241
+ }
242
+
243
+ /**
244
+ * @param {MongoDB} driver
245
+ *
246
+ *
247
+ * @return {db_col & { _col: ReturnType<col>}}
248
+ */
249
+ export const impl = (driver) => {
250
+
251
+ return {
252
+ _col: col(driver),
253
+ get: get(driver),
254
+ getBulk: get_bulk(driver, col(driver)),
255
+ upsert: upsert(driver),
256
+ remove: remove(driver),
257
+ list: list(driver),
258
+ count: count(driver),
259
+ list_discount_products: list_discount_products(driver)
260
+ }
261
+ }