@storecraft/database-mongodb 1.0.20 → 1.2.5

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/README.md CHANGED
@@ -45,16 +45,15 @@ const app = new App()
45
45
  }
46
46
  )
47
47
  )
48
+ .init();
48
49
 
49
- await app.init();
50
- await migrateToLatest(app.db, false);
51
- // create if not exists
52
- await app.vectorstore.createVectorIndex(false, false);
50
+ await migrateToLatest(app.__show_me_everything.db, false);
51
+ await app.__show_me_everything.vector_store.createVectorIndex();
53
52
 
54
- const server = http.createServer(app.handler).listen(
53
+ http.createServer(app.handler).listen(
55
54
  8000,
56
55
  () => {
57
- console.log(`Server is running on http://localhost:8000`);
56
+ app.print_banner('http://localhost:8000');
58
57
  }
59
58
  );
60
59
 
@@ -91,7 +90,8 @@ So, you can instantiate with empty config
91
90
 
92
91
  ## Testing Locally (I recommend to use `Atlas`)
93
92
 
94
- 1. First start a `mongo-db` server
93
+ 1. Start a `mongo-db` server with `docker`
94
+
95
95
  First, make sure you have `docker` installed,
96
96
  Then, run
97
97
 
package/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * @import { Config } from './types.public.js'
3
- * @import { MongoClientOptions } from 'mongodb'
4
3
  * @import { db_driver } from '@storecraft/core/database'
5
- * @import { BaseType } from '@storecraft/core/api'
6
4
  * @import { ENV } from '@storecraft/core'
7
5
  */
8
6
  import { App } from '@storecraft/core';
@@ -21,49 +19,37 @@ import { impl as storefronts } from './src/con.storefronts.js';
21
19
  import { impl as tags } from './src/con.tags.js';
22
20
  import { impl as templates } from './src/con.templates.js';
23
21
  import { impl as search } from './src/con.search.js';
22
+ import { impl as chats } from './src/con.chats.js';
24
23
  export { migrateToLatest } from './migrate.js';
25
24
  export { MongoVectorStore } from './vector-store/index.js';
26
25
 
27
-
28
26
  /**
29
27
  * @implements {db_driver}
30
28
  */
31
29
  export class MongoDB {
32
30
 
33
31
  /** @satisfies {ENV<Config>} */
34
- static EnvConfig = /** @type{const} */ ({
32
+ static EnvConfig = /** @type {const} */ ({
35
33
  db_name: 'MONGODB_NAME',
36
34
  url: 'MONGODB_URL',
37
35
  });
38
36
 
39
- /**
40
- *
41
- * @type {boolean}
42
- */
37
+ /** @type {boolean} */
43
38
  #is_ready;
44
39
 
45
- /**
46
- *
47
- * @type {App<any, any, any>}
48
- */
40
+ /** @type {App<any, any, any>} */
49
41
  #app;
50
42
 
51
- /**
52
- *
53
- * @type {MongoClient}
54
- */
43
+ /** @type {MongoClient} */
55
44
  #mongo_client;
56
45
 
57
- /**
58
- *
59
- * @type {Config}
60
- */
46
+ /** @type {Config} */
61
47
  #config;
62
48
 
63
49
  /**
64
- *
65
50
  * @param {Config} [config] config, if undefined,
66
- * env variables `MONGODB_URL` will be used for uri upon init later
51
+ * env variables `MONGODB_URL` will be used for
52
+ * uri upon init later
67
53
  */
68
54
  constructor(config) {
69
55
  this.#is_ready = false;
@@ -81,18 +67,20 @@ export class MongoDB {
81
67
  };
82
68
  }
83
69
 
84
- /**
85
- * @type {db_driver["init"]}
86
- */
70
+ /** @type {db_driver["init"]} */
87
71
  init(app) {
88
72
  if(this.isReady)
89
73
  return this;
74
+
90
75
  const c = this.#config;
91
- c.db_name ??= app.platform.env[MongoDB.EnvConfig.db_name];
92
- c.url ??= app.platform.env[MongoDB.EnvConfig.url] ?? 'main';
76
+
77
+ c.db_name ??= app.env[MongoDB.EnvConfig.db_name];
78
+ c.url ??= app.env[MongoDB.EnvConfig.url] ?? 'main';
93
79
 
94
80
  if(!this.config.db_name || !this.config.url) {
95
- throw new Error('MongoVectorStore::client() - missing url or db_name');
81
+ throw new Error(
82
+ 'MongoVectorStore::client() - missing url or db_name'
83
+ );
96
84
  }
97
85
 
98
86
  this.#app = app;
@@ -111,6 +99,7 @@ export class MongoDB {
111
99
  shipping_methods: shipping(this),
112
100
  templates: templates(this),
113
101
  search: search(this),
102
+ chats: chats(this),
114
103
  }
115
104
 
116
105
  this.#is_ready = true;
@@ -120,6 +109,7 @@ export class MongoDB {
120
109
 
121
110
  async disconnect() {
122
111
  await this.mongo_client.close(true);
112
+
123
113
  return true;
124
114
  }
125
115
 
@@ -131,7 +121,6 @@ export class MongoDB {
131
121
  }
132
122
 
133
123
  /**
134
- *
135
124
  * @description database name
136
125
  */
137
126
  get name () {
@@ -139,7 +128,6 @@ export class MongoDB {
139
128
  }
140
129
 
141
130
  /**
142
- *
143
131
  * @description Get the `storecraft` app
144
132
  */
145
133
  get app() {
@@ -147,12 +135,13 @@ export class MongoDB {
147
135
  }
148
136
 
149
137
  /**
150
- *
151
138
  * @description Get the native `mongodb` client
152
139
  */
153
140
  get mongo_client() {
154
141
  if(!this.config.db_name || !this.config.url) {
155
- throw new Error('MongoVectorStore::client() - missing url or db_name');
142
+ throw new Error(
143
+ 'MongoVectorStore::client() - missing url or db_name'
144
+ );
156
145
  }
157
146
 
158
147
  this.#mongo_client = this.#mongo_client ?? new MongoClient(
@@ -167,7 +156,6 @@ export class MongoDB {
167
156
  }
168
157
 
169
158
  /**
170
- *
171
159
  * @description Get the config object
172
160
  */
173
161
  get config() {
@@ -175,13 +163,8 @@ export class MongoDB {
175
163
  }
176
164
 
177
165
  /**
178
- *
179
- * @template {BaseType} T
180
- *
181
- *
166
+ * @template T
182
167
  * @param {string} name
183
- *
184
- *
185
168
  * @returns {Collection<T>}
186
169
  */
187
170
  collection(name) {
package/migrate.js CHANGED
@@ -7,7 +7,6 @@ const __filename = fileURLToPath(import.meta.url);
7
7
  const __dirname = path.dirname(__filename);
8
8
 
9
9
  /**
10
- *
11
10
  * @param {MongoDB} driver
12
11
  * @param {boolean} [destroy_db_upon_completion=true]
13
12
  */
@@ -0,0 +1,57 @@
1
+ import { Db, MongoClient } from 'mongodb';
2
+
3
+ const collections = [
4
+ 'chats'
5
+ ];
6
+
7
+ /**
8
+ * @param {Db} db
9
+ * @param {MongoClient} client
10
+ */
11
+ export async function up(db, client) {
12
+
13
+ const session = client.startSession();
14
+ try {
15
+ await session.withTransaction(async ($session) => {
16
+ for (const collection_name of collections) {
17
+
18
+ await db.createCollection(collection_name, {session: $session})
19
+ await db.collection(collection_name).dropIndexes({ session: $session });
20
+
21
+ await db.collection(collection_name).createIndexes(
22
+ [
23
+ {
24
+ key: { handle: 1 }, name: 'handle+',
25
+ background: false, unique: true, sparse: true
26
+ },
27
+ {
28
+ key: { updated_at: 1, _id: 1 }, name: '(updated_at+, _id+)',
29
+ background: false, sparse: true
30
+ },
31
+ {
32
+ key: { updated_at: -1, _id: -1 }, name: '(updated_at-, _id-)',
33
+ background: false, sparse: true
34
+ },
35
+ {
36
+ key: { search: 1 }, name: '(search+)',
37
+ background: false, sparse: true
38
+ },
39
+ ], {
40
+ session: $session
41
+ }
42
+ )
43
+ }
44
+
45
+ });
46
+ } finally {
47
+ await session.endSession();
48
+ }
49
+ }
50
+
51
+ /**
52
+ *
53
+ * @param {Db} db
54
+ * @param {MongoClient} client
55
+ */
56
+ export async function down(db, client) {
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storecraft/database-mongodb",
3
- "version": "1.0.20",
3
+ "version": "1.2.5",
4
4
  "description": "Storecraft database driver for mongodb on node / bun / deno platform",
5
5
  "license": "MIT",
6
6
  "author": "Tomer Shalev (https://github.com/store-craft)",
@@ -36,7 +36,6 @@
36
36
  "database-mongodb:docker-compose-up": "docker compose -f ./tests/docker-compose.yml up -d ",
37
37
  "database-mongodb:test": "node ./tests/runner.test.js",
38
38
  "test": "npm run database-mongodb:test",
39
- "prepublishOnly": "npm version patch --force",
40
39
  "sc-publish": "npm publish"
41
40
  },
42
41
  "dependencies": {
@@ -1,22 +1,18 @@
1
1
  /**
2
2
  * @import { db_auth_users as db_col } from '@storecraft/core/database'
3
- * @import { AuthUserType } from '@storecraft/core/api'
4
3
  */
5
-
6
4
  import { MongoDB } from '../index.js'
7
5
  import { Collection } from 'mongodb'
8
6
  import {
9
7
  handle_or_id,
10
- objid_or_else_filter, sanitize_one, to_objid_safe
8
+ objid_or_else_filter, sanitize_one
11
9
  } from './utils.funcs.js'
12
10
  import {
13
- count_regular, get_regular, list_regular, upsert_regular
11
+ count_regular, list_regular, upsert_regular
14
12
  } from './con.shared.js'
15
13
 
16
14
  /**
17
15
  * @param {MongoDB} d
18
- *
19
- *
20
16
  * @returns {Collection<db_col["$type_get"]>}
21
17
  */
22
18
  const col = (d) => d.collection('auth_users');
@@ -29,8 +25,6 @@ const upsert = (driver) => upsert_regular(driver, col(driver));
29
25
 
30
26
  /**
31
27
  * @param {MongoDB} driver
32
- *
33
- *
34
28
  * @returns {db_col["getByEmail"]}
35
29
  */
36
30
  const get = (driver) => {
@@ -46,8 +40,6 @@ const get = (driver) => {
46
40
 
47
41
  /**
48
42
  * @param {MongoDB} driver
49
- *
50
- *
51
43
  * @returns {db_col["getByEmail"]}
52
44
  */
53
45
  const getByEmail = (driver) => {
@@ -99,8 +91,6 @@ const remove = (driver) => {
99
91
 
100
92
  /**
101
93
  * @param {MongoDB} driver
102
- *
103
- *
104
94
  * @returns {db_col["removeByEmail"]}
105
95
  */
106
96
  const removeByEmail = (driver) => {
@@ -125,10 +115,8 @@ const count = (driver) => count_regular(driver, col(driver));
125
115
 
126
116
  /**
127
117
  * @param {MongoDB} driver
128
- *
129
- *
130
118
  * @return {db_col & { _col: ReturnType<col>}}
131
- * */
119
+ */
132
120
  export const impl = (driver) => {
133
121
 
134
122
  return {
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @import { db_chats as db_col } from '@storecraft/core/database'
3
+ * @import { WithRelations } from './utils.types.js'
4
+ */
5
+ import { Collection } from 'mongodb'
6
+ import { MongoDB } from '../index.js'
7
+ import { count_regular, get_regular, list_regular } from './con.shared.js'
8
+ import { handle_or_id, to_objid } from './utils.funcs.js';
9
+ import {
10
+ add_search_terms_relation_on, delete_me,
11
+ save_me,
12
+ } from './utils.relations.js';
13
+
14
+ /**
15
+ * @param {MongoDB} d
16
+ * @returns {Collection<WithRelations<db_col["$type_get"]>>}
17
+ */
18
+ const col = (d) => d.collection('chats');
19
+
20
+ /**
21
+ * @param {MongoDB} driver
22
+ * @returns {db_col["upsert"]}
23
+ */
24
+ const upsert = (driver) => {
25
+ return async (data, search_terms=[]) => {
26
+ data = {...data};
27
+ const objid = to_objid(data.id);
28
+ const session = driver.mongo_client.startSession();
29
+
30
+ try {
31
+ await session.withTransaction(
32
+ async () => {
33
+
34
+ // SEARCH
35
+ add_search_terms_relation_on(data, search_terms);
36
+
37
+ // SAVE ME
38
+ await save_me(driver, 'chats', objid, data, session);
39
+
40
+ }
41
+ );
42
+ } catch(e) {
43
+ console.log(e);
44
+ return false;
45
+ } finally {
46
+ await session.endSession();
47
+ }
48
+
49
+ return true;
50
+ }
51
+
52
+ }
53
+ /**
54
+ * @param {MongoDB} driver
55
+ */
56
+ const get = (driver) => get_regular(driver, col(driver));
57
+
58
+ /**
59
+ * @param {MongoDB} driver
60
+ * @returns {db_col["remove"]}
61
+ */
62
+ const remove = (driver) => {
63
+ return async (id_or_handle) => {
64
+ const item = await col(driver).findOne(handle_or_id(id_or_handle));
65
+
66
+ if(!item) return;
67
+
68
+ const objid = to_objid(item.id)
69
+ const session = driver.mongo_client.startSession();
70
+
71
+ try {
72
+ await session.withTransaction(
73
+ async () => {
74
+
75
+ // DELETE ME
76
+ await delete_me(
77
+ driver, 'chats', objid, session
78
+ );
79
+
80
+ }
81
+ );
82
+ } catch(e) {
83
+ console.log(e);
84
+ return false;
85
+ } finally {
86
+ await session.endSession();
87
+ }
88
+
89
+ return true;
90
+ }
91
+
92
+ }
93
+
94
+
95
+ /**
96
+ * @param {MongoDB} driver
97
+ */
98
+ const list = (driver) => list_regular(driver, col(driver));
99
+
100
+ /**
101
+ * @param {MongoDB} driver
102
+ */
103
+ const count = (driver) => count_regular(driver, col(driver));
104
+
105
+ /**
106
+ * @param {MongoDB} driver
107
+ * @return {db_col & { _col: ReturnType<col>}}
108
+ */
109
+ export const impl = (driver) => {
110
+
111
+ return {
112
+ _col: col(driver),
113
+ get: get(driver),
114
+ upsert: upsert(driver),
115
+ remove: remove(driver),
116
+ list: list(driver),
117
+ count: count(driver),
118
+ }
119
+ }
@@ -4,7 +4,6 @@
4
4
  * @import { WithRelations } from './utils.types.js'
5
5
  * @import { Filter } from 'mongodb'
6
6
  */
7
-
8
7
  import { Collection } from 'mongodb'
9
8
  import { MongoDB } from '../index.js'
10
9
  import { count_regular, expand, get_regular, list_regular } from './con.shared.js'
@@ -18,7 +17,6 @@ import {
18
17
  update_entry_on_all_connection_of_relation
19
18
  } from './utils.relations.js'
20
19
 
21
-
22
20
  const transactionOptions = {
23
21
  readPreference: 'primary',
24
22
  readConcern: { level: 'local' },
@@ -94,8 +92,6 @@ const get = (driver) => get_regular(driver, col(driver));
94
92
 
95
93
  /**
96
94
  * @param {MongoDB} driver
97
- *
98
- *
99
95
  * @returns {db_col["remove"]}
100
96
  */
101
97
  const remove = (driver) => {
@@ -221,10 +217,7 @@ const count_collection_products = (driver) => {
221
217
  filter: filter_query, sort, reverse_sign
222
218
  } = query_to_mongo(query);
223
219
 
224
- /**
225
- * @type {Filter<WithRelations<ProductType | VariantType>>
226
- * }
227
- */
220
+ /** @type {Filter<WithRelations<ProductType | VariantType>>} */
228
221
  const filter = {
229
222
  $and: [
230
223
  { '_relations.search': `col:${handle_or_id}` },
@@ -277,10 +270,8 @@ const list_used_products_tags = (driver) => {
277
270
 
278
271
  /**
279
272
  * @param {MongoDB} driver
280
- *
281
- *
282
273
  * @return {db_col & { _col: ReturnType<col>}}
283
- * */
274
+ */
284
275
  export const impl = (driver) => {
285
276
 
286
277
  return {
@@ -4,17 +4,17 @@
4
4
  * @import { WithRelations } from './utils.types.js'
5
5
  * @import { Filter } from 'mongodb'
6
6
  */
7
-
8
7
  import { Collection, ObjectId } from 'mongodb'
9
8
  import { MongoDB } from '../index.js'
10
- import { count_regular, get_regular, list_regular,
11
- upsert_regular } from './con.shared.js'
9
+ import {
10
+ count_regular, get_regular, list_regular,
11
+ upsert_regular
12
+ } from './con.shared.js'
12
13
  import { handle_or_id, isDef, sanitize_array, to_objid } from './utils.funcs.js'
13
14
  import { query_to_mongo } from './utils.query.js';
14
15
 
15
16
  /**
16
17
  * @param {MongoDB} d
17
- *
18
18
  * @returns {Collection<db_col["$type_get"]>}
19
19
  */
20
20
  const col = (d) => d.collection('customers');
@@ -31,8 +31,6 @@ const get = (driver) => get_regular(driver, col(driver));
31
31
 
32
32
  /**
33
33
  * @param {MongoDB} driver
34
- *
35
- *
36
34
  * @returns {db_col["getByEmail"]}
37
35
  */
38
36
  const getByEmail = (driver) => {
@@ -44,10 +42,7 @@ const getByEmail = (driver) => {
44
42
  }
45
43
 
46
44
  /**
47
- *
48
45
  * @param {string} email_or_id
49
- *
50
- *
51
46
  * @returns { {_id:ObjectId} | {email: string}}
52
47
  */
53
48
  export const email_or_id = (email_or_id) => {
@@ -109,8 +104,6 @@ const count = (driver) => count_regular(driver, col(driver));
109
104
 
110
105
  /**
111
106
  * @param {MongoDB} driver
112
- *
113
- *
114
107
  * @returns {db_col["list_customer_orders"]}
115
108
  */
116
109
  const list_customer_orders = (driver) => {
@@ -177,10 +170,8 @@ const count_customer_orders = (driver) => {
177
170
 
178
171
  /**
179
172
  * @param {MongoDB} driver
180
- *
181
- *
182
173
  * @return {db_col & { _col: ReturnType<col>}}
183
- * */
174
+ */
184
175
  export const impl = (driver) => {
185
176
 
186
177
  return {
@@ -4,7 +4,6 @@
4
4
  * @import { WithRelations } from './utils.types.js'
5
5
  * @import { Filter } from 'mongodb'
6
6
  */
7
-
8
7
  import { Collection } from 'mongodb'
9
8
  import { MongoDB } from '../index.js'
10
9
  import {
@@ -13,7 +12,7 @@ import {
13
12
  import {
14
13
  handle_or_id, isDef, sanitize_array, to_objid
15
14
  } from './utils.funcs.js'
16
- import { discount_to_mongo_conjunctions } from './con.discounts.utils.js'
15
+ import { discount_to_mongo_conjunctions, is_order_discount } from './con.discounts.utils.js'
17
16
  import { query_to_mongo } from './utils.query.js'
18
17
  import { report_document_media } from './con.images.js'
19
18
  import { enums } from '@storecraft/core/api'
@@ -30,8 +29,6 @@ import {
30
29
 
31
30
  /**
32
31
  * @param {MongoDB} d
33
- *
34
- *
35
32
  * @returns {Collection<db_col["$type_get"]>}
36
33
  */
37
34
  const col = (d) => d.collection('discounts');
@@ -39,8 +36,6 @@ const col = (d) => d.collection('discounts');
39
36
 
40
37
  /**
41
38
  * @param {MongoDB} driver
42
- *
43
- *
44
39
  * @returns {db_col["upsert"]}
45
40
  */
46
41
  const upsert = (driver) => {
@@ -82,7 +77,11 @@ const upsert = (driver) => {
82
77
  );
83
78
 
84
79
  // now filter and update for products
85
- if(data.active && data.application.id===enums.DiscountApplicationEnum.Auto.id) {
80
+ if(
81
+ data.active &&
82
+ data.application.id===enums.DiscountApplicationEnum.Auto.id &&
83
+ !is_order_discount(data)
84
+ ) {
86
85
  const conjunctions = discount_to_mongo_conjunctions(data);
87
86
  await driver.resources.products._col.updateMany(
88
87
  conjunctions.length ? { $and: conjunctions } : {},
@@ -143,8 +142,6 @@ const get = (driver) => get_regular(driver, col(driver));
143
142
 
144
143
  /**
145
144
  * @param {MongoDB} driver
146
- *
147
- *
148
145
  * @returns {db_col["remove"]}
149
146
  */
150
147
  const remove = (driver) => {
@@ -327,8 +324,6 @@ const count_discount_products = (driver) => {
327
324
 
328
325
  /**
329
326
  * @param {MongoDB} driver
330
- *
331
- *
332
327
  * @return {db_col & { _col: ReturnType<col>}}
333
328
  */
334
329
  export const impl = (driver) => {
@@ -5,12 +5,11 @@
5
5
  * Filter_p_in_products, Filter_p_not_in_products
6
6
  * } from '@storecraft/core/api'
7
7
  */
8
-
9
8
  import { enums } from "@storecraft/core/api";
10
9
  import { to_objid_safe } from "./utils.funcs.js";
11
10
 
12
11
  /** @param {DiscountType} d */
13
- const is_order_discount = d => {
12
+ export const is_order_discount = d => {
14
13
  return (
15
14
  (d.info.details.type===enums.DiscountMetaEnum.order.type) ||
16
15
  // @ts-ignore
@@ -19,7 +18,7 @@ const is_order_discount = d => {
19
18
  }
20
19
 
21
20
  /** @param {DiscountType} d */
22
- const is_automatic_discount = d => {
21
+ export const is_automatic_discount = d => {
23
22
  return (d.application.id===enums.DiscountApplicationEnum.Auto.id);
24
23
  }
25
24