@storecraft/database-mongodb 1.0.14 → 1.0.16

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,7 @@
1
+ /**
2
+ * @import { WithRelations } from './utils.types.js';
3
+ * @import { Filter } from 'mongodb';
4
+ */
1
5
  import { ObjectId } from 'mongodb';
2
6
 
3
7
  /** @param {any} v */
@@ -14,11 +18,7 @@ export const delete_keys = (...keys) => {
14
18
 
15
19
  /**
16
20
  * @template T
17
- *
18
- *
19
21
  * @param {T} o
20
- *
21
- *
22
22
  * @returns {T}
23
23
  */
24
24
  return (o) => {
@@ -30,16 +30,9 @@ export const delete_keys = (...keys) => {
30
30
 
31
31
  /**
32
32
  * Sanitize hidden properties in-place
33
- *
34
- *
35
33
  * @template {object} T
36
- *
37
- *
38
34
  * @param {T} o
39
- *
40
- *
41
35
  * @return {Omit<T, '_id' | '_relations'>}
42
- *
43
36
  */
44
37
  export const sanitize_hidden = o => {
45
38
  if(!isDef(o))
@@ -53,27 +46,26 @@ export const sanitize_hidden = o => {
53
46
  }
54
47
 
55
48
  /**
56
- *
57
- * @template T
58
- *
59
- *
49
+ * Sanitize hidden properties in-place recursively
50
+ * @template {object} T
60
51
  * @param {T} o
61
- *
62
- *
63
- * @returns {T}
52
+ * @return {Omit<T, '_id' | '_relations'>}
64
53
  */
65
- export const delete_id = o => {
66
- return delete_keys('_id')(o)
54
+ export const sanitize_recursively = o => {
55
+ for(const k of Object.keys(o)) {
56
+ if(k.startsWith('_')) {
57
+ delete o[k];
58
+ } else if(typeof o[k] === 'object') {
59
+ sanitize_recursively(o[k]);
60
+ }
61
+ }
62
+ return o;
67
63
  }
68
64
 
69
65
  /**
70
- *
71
66
  * Sanitize the mongo document before sending to client
72
- *
73
67
  * @template T
74
- *
75
- *
76
- * @param {T} o
68
+ * @param {WithRelations<T>} o
77
69
  */
78
70
  export const sanitize_one = o => {
79
71
  return sanitize_hidden(o)
@@ -81,30 +73,31 @@ export const sanitize_one = o => {
81
73
 
82
74
  /**
83
75
  * Sanitize the mongo document before sending to client
84
- *
85
76
  * @template T
86
- *
87
- *
88
- * @param {T[]} o
89
- *
77
+ * @param {WithRelations<T>[]} o
90
78
  */
91
79
  export const sanitize_array = o => {
92
80
  return o?.map(sanitize_hidden);
93
81
  }
94
82
 
95
83
  /**
96
- *
84
+ * @template T
85
+ * @param {T} o
86
+ * @returns {T}
87
+ */
88
+ export const delete_id = o => {
89
+ return delete_keys('_id')(o)
90
+ }
91
+
92
+ /**
97
93
  * @param {string} id
98
- *
99
94
  */
100
95
  export const to_objid = id => {
101
96
  return new ObjectId(id.split('_').at(-1))
102
97
  }
103
98
 
104
99
  /**
105
- *
106
100
  * @param {string} id
107
- *
108
101
  */
109
102
  export const to_objid_safe = id => {
110
103
  try {
@@ -116,27 +109,20 @@ export const to_objid_safe = id => {
116
109
  }
117
110
 
118
111
  /**
112
+ * Create a `filter` for `object-id` or `handle`
119
113
  * @template {{handle?: string}} G
120
- *
121
- *
122
114
  * @param {string} handle_or_id
123
- *
124
- *
125
- * @returns {import('mongodb').Filter<G>}
115
+ * @returns {Filter<G>}
126
116
  */
127
117
  export const handle_or_id = (handle_or_id) => {
128
- return objid_or_else_filter(handle_or_id);
118
+ return objid_or_else_filter(handle_or_id, 'handle');
129
119
  }
130
120
 
131
121
 
132
122
  /**
133
123
  * @template {{handle?: string}} G
134
- *
135
- *
136
124
  * @param {string} id_or_else
137
- *
138
- *
139
- * @returns {import('mongodb').Filter<G>}
125
+ * @returns {Filter<G>}
140
126
  */
141
127
  export const objid_or_else_filter = (id_or_else, else_key='handle') => {
142
128
  try {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @import { ID } from '@storecraft/core/database'
3
3
  * @import { BaseType } from '@storecraft/core/api'
4
- * @import { WithRelations } from './utils.relations.js'
4
+ * @import { Relation, WithRelations } from './utils.types.js'
5
5
  * @import { Filter } from 'mongodb'
6
6
  */
7
7
 
@@ -10,20 +10,6 @@ import { isDef, isUndef, to_objid } from './utils.funcs.js';
10
10
  import { MongoDB } from '../index.js';
11
11
  import { zeroed_relations } from './con.shared.js';
12
12
 
13
- /**
14
- * @template {any} T
15
- *
16
- * @typedef {Object} Relation
17
- * @property {ObjectId[]} [ids]
18
- * @property {Record<ID, T>} [entries]
19
- */
20
-
21
- /**
22
- * @template {any} T
23
- *
24
- * @typedef {T & { _relations? : Record<string, Relation<any>> }} WithRelations
25
- */
26
-
27
13
  /**
28
14
  *
29
15
  * On upsert Create a relation on a given field that represents a relation.
@@ -259,12 +245,13 @@ export const update_specific_connection_of_relation = (
259
245
  * @param {ObjectId} entry_objid the proper `ObjectId` of the entry
260
246
  * @param {ClientSession} [session] client `session` for atomicity purposes
261
247
  * @param {string[]} [search_terms_to_remove=[]] Extra `search` terms to remove
248
+ * @param {string[]} [tags_to_remove=[]] Extra `tags` terms to remove
262
249
  * from all the connections
263
250
  *
264
251
  */
265
252
  export const remove_entry_from_all_connection_of_relation = (
266
253
  driver, collection, relation_name, entry_objid, session,
267
- search_terms_to_remove=[]
254
+ search_terms_to_remove=[], tags_to_remove=[]
268
255
  ) => {
269
256
  return driver.collection(collection).updateMany(
270
257
  {
@@ -273,7 +260,8 @@ export const remove_entry_from_all_connection_of_relation = (
273
260
  {
274
261
  $pull: {
275
262
  [`_relations.${relation_name}.ids`] : entry_objid,
276
- '_relations.search': { $in : search_terms_to_remove }
263
+ '_relations.search': { $in : search_terms_to_remove },
264
+ 'tags': { $in : tags_to_remove },
277
265
  },
278
266
  $unset: {
279
267
  [`_relations.${relation_name}.entries.${entry_objid.toString()}`]: ''
@@ -0,0 +1,12 @@
1
+ import type { ID } from "@storecraft/core/database";
2
+ import type { ObjectId, WithId } from "mongodb";
3
+
4
+ export type Relation<T extends any = any> = {
5
+ ids?: ObjectId[];
6
+ entries?: Record<ID, T>;
7
+ }
8
+
9
+ export type WithRelations<T extends any = undefined> = {
10
+ _relations?: Record<string, Relation<any>>
11
+ _id?: ObjectId;
12
+ } & T;
@@ -0,0 +1,23 @@
1
+ services:
2
+ mongo1:
3
+ image: mongo:latest
4
+ container_name: test-mongodb
5
+ command: ["--replSet", "rs0", "--bind_ip_all", "--port", "27017"]
6
+ ports:
7
+ - 27017:27017
8
+ extra_hosts:
9
+ - "host.docker.internal:host-gateway"
10
+ healthcheck:
11
+ test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'host.docker.internal:27017'}]}) }" | mongosh --port 27017 --quiet
12
+ interval: 5s
13
+ timeout: 30s
14
+ start_period: 0s
15
+ start_interval: 1s
16
+ retries: 30
17
+ volumes:
18
+ - "mongo1_data:/data/db"
19
+ - "mongo1_config:/data/configdb"
20
+
21
+ volumes:
22
+ mongo1_data:
23
+ mongo1_config:
@@ -9,7 +9,9 @@ export const create_app = async () => {
9
9
  {
10
10
  auth_admins_emails: ['admin@sc.com'],
11
11
  auth_secret_access_token: 'auth_secret_access_token',
12
- auth_secret_refresh_token: 'auth_secret_refresh_token'
12
+ auth_secret_refresh_token: 'auth_secret_refresh_token',
13
+ auth_secret_confirm_email_token: 'auth_secret_confirm_email_token',
14
+ auth_secret_forgot_password_token: 'auth_secret_forgot_password_token',
13
15
  }
14
16
  )
15
17
  .withPlatform(new NodePlatform())
@@ -22,22 +24,24 @@ export const create_app = async () => {
22
24
  )
23
25
  )
24
26
 
25
- return app.init();
27
+ return app.init()
26
28
  }
27
29
 
28
30
  async function test() {
29
31
  const app = await create_app();
30
32
 
31
33
  await migrateToLatest(app.db, false);
32
-
34
+
33
35
  Object.entries(api).slice(0, -1).forEach(
34
36
  ([name, runner]) => {
35
37
  runner.create(app).run();
36
38
  }
37
39
  );
40
+
38
41
  const last_test = Object.values(api).at(-1).create(app);
39
42
  last_test.after(async ()=>{app.db.disconnect()});
40
43
  last_test.run();
41
44
  }
42
45
 
46
+ // twice
43
47
  test();
@@ -1,7 +1,10 @@
1
+ import 'dotenv/config';
1
2
  import { App } from '@storecraft/core';
2
3
  import { MongoDB } from '@storecraft/database-mongodb';
3
4
  import { migrateToLatest } from '@storecraft/database-mongodb/migrate.js';
4
5
  import { NodePlatform } from '@storecraft/core/platform/node';
6
+ import { expand } from '../src/con.shared.js';
7
+ import { sanitize_hidden, sanitize_recursively } from '../src/utils.funcs.js';
5
8
 
6
9
  export const create_app = async () => {
7
10
  const app = new App(
@@ -14,42 +17,20 @@ export const create_app = async () => {
14
17
  .withPlatform(new NodePlatform())
15
18
  .withDatabase(new MongoDB({ db_name: 'test'}))
16
19
 
17
- return app.init();
20
+ await app.init();
21
+ await migrateToLatest(app.db, false);
22
+ return app;
18
23
  }
19
24
 
20
- /**
21
- *
22
- * @template R
23
- *
24
- * @param {(()=>Promise<R>) | (() => R)} fn
25
- */
26
- const withTime = async (fn) => {
27
- const n1 = Date.now() ;
28
- const r = await fn();
29
- const delta = Date.now() - n1;
30
- console.log(delta);
31
- return r;
32
- }
33
25
 
34
26
  async function test() {
35
- const app = await withTime(create_app);
36
-
37
- await migrateToLatest(app.db, false);
38
-
27
+ const app = await create_app();
39
28
 
40
- const doit = async () => {
41
- let items = await app.db.resources.search.quicksearch(
42
- {
43
- vql: '',
44
- sortBy: ['updated_at']
45
- }
46
- );
47
- return items;
48
- }
29
+ const sf = await app.db.resources.storefronts.get_default_auto_generated_storefront()
49
30
 
50
- const items = await withTime(doit);
31
+ console.log(JSON.stringify(sf, null, 2));
51
32
 
52
- // console.log('items ', items)
33
+ await app.db.disconnect();
53
34
  }
54
35
 
55
36
  test();
@@ -53,21 +53,33 @@ export class MongoVectorStore {
53
53
  */
54
54
  constructor(config) {
55
55
  this.config = {
56
- ...config,
57
- index_name: config.index_name ?? 'vector_store',
58
- similarity: config.similarity ?? 'cosine',
59
- dimensions: config.dimensions ?? 1536,
60
- options: config.options ?? {
56
+ index_name: DEFAULT_INDEX_NAME,
57
+ similarity: 'cosine',
58
+ dimensions: 1536,
59
+ options: {
61
60
  ignoreUndefined: true,
62
61
  serverApi: {
63
62
  version: ServerApiVersion.v1,
64
63
  strict: false,
65
64
  deprecationErrors: true,
66
65
  }
67
- }
66
+ },
67
+ ...config,
68
68
  };
69
69
  }
70
70
 
71
+ get metric() {
72
+ switch(this.config.similarity) {
73
+ case 'cosine': return 'cosine';
74
+ case 'dotProduct': return 'dotproduct';
75
+ case 'euclidean': return 'euclidean';
76
+ }
77
+ };
78
+
79
+ get dimensions() {
80
+ return this.config.dimensions;
81
+ };
82
+
71
83
  get client() {
72
84
  if(!this.config.db_name || !this.config.url) {
73
85
  throw new Error('MongoVectorStore::client() - missing url or db_name');
@@ -81,8 +93,10 @@ export class MongoVectorStore {
81
93
 
82
94
  /** @type {VectorStore["onInit"]} */
83
95
  onInit = (app) => {
84
- this.config.url ??= app.platform.env[MongoVectorStore.EnvConfig.url ?? 'MONGODB_URL'];
85
- this.config.db_name ??= app.platform.env[MongoVectorStore.EnvConfig.db_name ?? 'MONGODB_DB_NAME'] ?? 'main';
96
+ this.config.url ??= app.platform.env[MongoVectorStore.EnvConfig.url]
97
+ ?? app.platform.env['MONGODB_URL'];
98
+ this.config.db_name ??= app.platform.env[MongoVectorStore.EnvConfig.db_name]
99
+ ?? app.platform.env['MONGODB_DB_NAME'] ?? 'main';
86
100
  }
87
101
 
88
102
  /** @type {VectorStore["embedder"]} */