assai 2.0.0 → 2.1.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.
- package/README.md +148 -148
- package/dist/src/__test/mock_get_collection.d.mts +2 -0
- package/dist/src/factories/create_mongo_collection.d.mts +55 -11
- package/dist/src/usecases/mongo/operation/aggregate.d.mts +16 -0
- package/dist/src/usecases/mongo/operation/bulk_write.d.mts +15 -0
- package/dist/src/usecases/mongo/operation/find_one_and_delete.d.mts +16 -0
- package/dist/src/usecases/mongo/operation/find_one_and_replace.d.mts +18 -0
- package/dist/src/usecases/mongo/operation/find_one_and_update.d.mts +18 -0
- package/dist/src/usecases/mongo/operation/index.d.mts +5 -0
- package/dist/src/usecases/mongo/transformers/id/rename_to_mongo_id.d.mts +3 -0
- package/dist/src/usecases/mongo/transformers/object_id/ids_into_strings.d.mts +5 -0
- package/dist/src/usecases/mongo/transformers/object_id/strings_into_id.d.mts +3 -0
- package/dist/src/usecases/mongo/transformers/timestamps.d.mts +5 -0
- package/index.mjs +2 -2
- package/jsconfig.json +17 -20
- package/jsconfig.prod.json +12 -12
- package/package.json +40 -39
- package/src/__test/manage_mock_database.mjs +24 -24
- package/src/__test/manage_mock_registry.mjs +54 -54
- package/src/__test/mock_get_collection.mjs +22 -20
- package/src/data/errors/operation_fail.mjs +9 -9
- package/src/data/errors/unsupported_error.mjs +9 -9
- package/src/data/interfaces/mongo_operator.mjs +2 -2
- package/src/data/interfaces/native_collection.mjs +27 -27
- package/src/factories/create_mock_collection.mjs +173 -173
- package/src/factories/create_mongo_collection.mjs +224 -181
- package/src/factories/index.mjs +1 -1
- package/src/types.ts +31 -31
- package/src/usecases/index.mjs +1 -1
- package/src/usecases/mongo/generate_new_id.mjs +4 -4
- package/src/usecases/mongo/index.mjs +3 -3
- package/src/usecases/mongo/mongo_client.mjs +36 -36
- package/src/usecases/mongo/operation/additional/delete_one_or_throw.mjs +17 -17
- package/src/usecases/mongo/operation/additional/index.mjs +1 -1
- package/src/usecases/mongo/operation/aggregate.mjs +21 -0
- package/src/usecases/mongo/operation/bulk_write.mjs +54 -0
- package/src/usecases/mongo/operation/count.mjs +16 -16
- package/src/usecases/mongo/operation/delete_many.mjs +15 -15
- package/src/usecases/mongo/operation/delete_one.mjs +16 -16
- package/src/usecases/mongo/operation/find.mjs +34 -34
- package/src/usecases/mongo/operation/find_one.mjs +32 -32
- package/src/usecases/mongo/operation/find_one_and_delete.mjs +23 -0
- package/src/usecases/mongo/operation/find_one_and_replace.mjs +24 -0
- package/src/usecases/mongo/operation/find_one_and_update.mjs +40 -0
- package/src/usecases/mongo/operation/index.mjs +15 -10
- package/src/usecases/mongo/operation/insert_many.mjs +39 -39
- package/src/usecases/mongo/operation/insert_one.mjs +32 -32
- package/src/usecases/mongo/operation/update_many.mjs +39 -39
- package/src/usecases/mongo/operation/update_one.mjs +40 -40
- package/src/usecases/mongo/transformers/id/index.mjs +4 -4
- package/src/usecases/mongo/transformers/id/rename_find_options.mjs +12 -12
- package/src/usecases/mongo/transformers/id/rename_to_dev_id.mjs +14 -13
- package/src/usecases/mongo/transformers/id/rename_to_mongo_id.mjs +34 -13
- package/src/usecases/mongo/transformers/index.mjs +2 -2
- package/src/usecases/mongo/transformers/input_transformer.mjs +32 -32
- package/src/usecases/mongo/transformers/object_id/ids_into_strings.mjs +47 -30
- package/src/usecases/mongo/transformers/object_id/index.mjs +3 -3
- package/src/usecases/mongo/transformers/object_id/strings_into_id.mjs +90 -44
- package/src/usecases/mongo/transformers/output_transformer.mjs +18 -18
- package/src/usecases/mongo/transformers/timestamps.mjs +32 -22
|
@@ -1,174 +1,174 @@
|
|
|
1
|
-
import { ObjectId } from 'mongodb'
|
|
2
|
-
import { NotImplemented } from '../data/errors/unsupported_error.mjs'
|
|
3
|
-
|
|
4
|
-
/** @type {Record<string, any[]>} */
|
|
5
|
-
const memory = {}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @template {import('mongodb').Document} T
|
|
9
|
-
* @param {string} [name]
|
|
10
|
-
* @returns {import('../data/interfaces/native_collection.mjs').InativeCollection<T>}
|
|
11
|
-
*/
|
|
12
|
-
export function createMockCollection(name = 'mock') {
|
|
13
|
-
|
|
14
|
-
function getItems() {
|
|
15
|
-
let items = memory[name]
|
|
16
|
-
if (items == null) {
|
|
17
|
-
items = []
|
|
18
|
-
memory[name] = items
|
|
19
|
-
}
|
|
20
|
-
return items
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* @param {import('mongodb').Filter<T>} filter
|
|
26
|
-
*/
|
|
27
|
-
function getFilteredItems(filter) {
|
|
28
|
-
const keys = Object.keys(filter)
|
|
29
|
-
const dollarFilters = keys.filter(x => x.startsWith('$'))
|
|
30
|
-
if (dollarFilters.length > 0) {
|
|
31
|
-
throw new NotImplemented('root dollar sign filters not supported')
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** @type {((item: T) => boolean)[]} */
|
|
35
|
-
const fieldFilter = []
|
|
36
|
-
for (const field of keys) {
|
|
37
|
-
const value = filter[field]
|
|
38
|
-
/**
|
|
39
|
-
* @returns {import('../data/interfaces/mongo_operator.mjs').ImongoOperator[]}
|
|
40
|
-
*/
|
|
41
|
-
function getOperators() {
|
|
42
|
-
if (value == null) return ['$eq']
|
|
43
|
-
if (typeof value != 'object') return ['$eq']
|
|
44
|
-
if (Array.isArray(value)) return ['$eq']
|
|
45
|
-
if (value instanceof RegExp) {
|
|
46
|
-
throw new NotImplemented('Search using a regular expression is not supported')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Getting operators used in query
|
|
50
|
-
const fieldInnerKeys = Object.keys(value)
|
|
51
|
-
const operators = fieldInnerKeys.filter(x => x.startsWith('$'))
|
|
52
|
-
const hasOperator = operators.length > 0
|
|
53
|
-
|
|
54
|
-
// Lack of operator presumes equal operator
|
|
55
|
-
if (!hasOperator) return ['$eq']
|
|
56
|
-
|
|
57
|
-
const areAllKeysOperators = fieldInnerKeys.every(x => x.startsWith('$'))
|
|
58
|
-
if (!areAllKeysOperators) {
|
|
59
|
-
// Means the object contained operators (such as "$eq" or "$lt"),
|
|
60
|
-
// But not all keys are operators, which is not valid.
|
|
61
|
-
throw new Error(`The value on field ${field} does not look right...`)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Reading operators from object
|
|
65
|
-
/** @type {import('../data/interfaces/mongo_operator.mjs').ImongoOperator[]} */
|
|
66
|
-
const usedOperators = []
|
|
67
|
-
for (const operator of operators) {
|
|
68
|
-
switch (operator) {
|
|
69
|
-
case '$eq':
|
|
70
|
-
usedOperators.push('$eq')
|
|
71
|
-
default:
|
|
72
|
-
throw new NotImplemented(`Operator ${operator} not implemented`)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return usedOperators
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const operators = getOperators()
|
|
79
|
-
for (const operator of operators) {
|
|
80
|
-
switch (operator) {
|
|
81
|
-
case '$eq':
|
|
82
|
-
fieldFilter.push((doc) => {
|
|
83
|
-
const savedValue = doc[field]
|
|
84
|
-
return savedValue == value
|
|
85
|
-
})
|
|
86
|
-
default:
|
|
87
|
-
throw new NotImplemented(`Operator ${operator} is not supported`)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const allCollectionItems = getItems()
|
|
93
|
-
return allCollectionItems.filter(savedDoc => {
|
|
94
|
-
return fieldFilter.every(comparator => {
|
|
95
|
-
return comparator(savedDoc)
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* $set
|
|
102
|
-
* @param {*} doc
|
|
103
|
-
* @param {*} update The update object. Should not contain operator
|
|
104
|
-
*/
|
|
105
|
-
function performSetUpdate(doc, update) {
|
|
106
|
-
for (const [field, newValue] of Object.entries(update)) {
|
|
107
|
-
doc[field] = newValue
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
async insertOne(doc) {
|
|
113
|
-
const items = getItems()
|
|
114
|
-
if (doc._id == null) {
|
|
115
|
-
// @ts-ignore
|
|
116
|
-
doc._id = new ObjectId()
|
|
117
|
-
}
|
|
118
|
-
items.push(doc)
|
|
119
|
-
},
|
|
120
|
-
async deleteOne(filter) {
|
|
121
|
-
const documentsToDelete = getFilteredItems(filter)
|
|
122
|
-
const allCollectionItems = getItems()
|
|
123
|
-
|
|
124
|
-
// Deleting the documents, one document at a time
|
|
125
|
-
while (documentsToDelete.length > 0) {
|
|
126
|
-
const docToDelete = documentsToDelete[0]
|
|
127
|
-
const index = allCollectionItems.indexOf(docToDelete)
|
|
128
|
-
if (index < 0) {
|
|
129
|
-
throw new Error('Document extracted from memory was not found in memory')
|
|
130
|
-
}
|
|
131
|
-
allCollectionItems.splice(index, 1)
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
async updateOne(filter, update) {
|
|
135
|
-
// Getting document to update
|
|
136
|
-
const documentsToUpdate = getFilteredItems(filter)
|
|
137
|
-
if (documentsToUpdate.length == 0) {
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
const docToUpdate = documentsToUpdate[0]
|
|
141
|
-
|
|
142
|
-
const updateKeys = Object.keys(update)
|
|
143
|
-
const operators = updateKeys.filter(x => x.startsWith('$'))
|
|
144
|
-
|
|
145
|
-
// Checking for empty updates
|
|
146
|
-
if (updateKeys.length == 0) {
|
|
147
|
-
return
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Is a simple $set operation
|
|
151
|
-
if (operators.length == 0) {
|
|
152
|
-
performSetUpdate(docToUpdate, update)
|
|
153
|
-
return
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Validating update object
|
|
157
|
-
if (updateKeys.length != operators.length) {
|
|
158
|
-
throw new Error('This update does not look right...')
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Processing complex update
|
|
162
|
-
for (const operator of operators) {
|
|
163
|
-
const value = update[operator]
|
|
164
|
-
switch (operator) {
|
|
165
|
-
case '$set':
|
|
166
|
-
performSetUpdate(docToUpdate, value)
|
|
167
|
-
break
|
|
168
|
-
default:
|
|
169
|
-
throw new Error(`Operator ${operator} not supported`)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
1
|
+
import { ObjectId } from 'mongodb'
|
|
2
|
+
import { NotImplemented } from '../data/errors/unsupported_error.mjs'
|
|
3
|
+
|
|
4
|
+
/** @type {Record<string, any[]>} */
|
|
5
|
+
const memory = {}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @template {import('mongodb').Document} T
|
|
9
|
+
* @param {string} [name]
|
|
10
|
+
* @returns {import('../data/interfaces/native_collection.mjs').InativeCollection<T>}
|
|
11
|
+
*/
|
|
12
|
+
export function createMockCollection(name = 'mock') {
|
|
13
|
+
|
|
14
|
+
function getItems() {
|
|
15
|
+
let items = memory[name]
|
|
16
|
+
if (items == null) {
|
|
17
|
+
items = []
|
|
18
|
+
memory[name] = items
|
|
19
|
+
}
|
|
20
|
+
return items
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {import('mongodb').Filter<T>} filter
|
|
26
|
+
*/
|
|
27
|
+
function getFilteredItems(filter) {
|
|
28
|
+
const keys = Object.keys(filter)
|
|
29
|
+
const dollarFilters = keys.filter(x => x.startsWith('$'))
|
|
30
|
+
if (dollarFilters.length > 0) {
|
|
31
|
+
throw new NotImplemented('root dollar sign filters not supported')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @type {((item: T) => boolean)[]} */
|
|
35
|
+
const fieldFilter = []
|
|
36
|
+
for (const field of keys) {
|
|
37
|
+
const value = filter[field]
|
|
38
|
+
/**
|
|
39
|
+
* @returns {import('../data/interfaces/mongo_operator.mjs').ImongoOperator[]}
|
|
40
|
+
*/
|
|
41
|
+
function getOperators() {
|
|
42
|
+
if (value == null) return ['$eq']
|
|
43
|
+
if (typeof value != 'object') return ['$eq']
|
|
44
|
+
if (Array.isArray(value)) return ['$eq']
|
|
45
|
+
if (value instanceof RegExp) {
|
|
46
|
+
throw new NotImplemented('Search using a regular expression is not supported')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Getting operators used in query
|
|
50
|
+
const fieldInnerKeys = Object.keys(value)
|
|
51
|
+
const operators = fieldInnerKeys.filter(x => x.startsWith('$'))
|
|
52
|
+
const hasOperator = operators.length > 0
|
|
53
|
+
|
|
54
|
+
// Lack of operator presumes equal operator
|
|
55
|
+
if (!hasOperator) return ['$eq']
|
|
56
|
+
|
|
57
|
+
const areAllKeysOperators = fieldInnerKeys.every(x => x.startsWith('$'))
|
|
58
|
+
if (!areAllKeysOperators) {
|
|
59
|
+
// Means the object contained operators (such as "$eq" or "$lt"),
|
|
60
|
+
// But not all keys are operators, which is not valid.
|
|
61
|
+
throw new Error(`The value on field ${field} does not look right...`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Reading operators from object
|
|
65
|
+
/** @type {import('../data/interfaces/mongo_operator.mjs').ImongoOperator[]} */
|
|
66
|
+
const usedOperators = []
|
|
67
|
+
for (const operator of operators) {
|
|
68
|
+
switch (operator) {
|
|
69
|
+
case '$eq':
|
|
70
|
+
usedOperators.push('$eq')
|
|
71
|
+
default:
|
|
72
|
+
throw new NotImplemented(`Operator ${operator} not implemented`)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return usedOperators
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const operators = getOperators()
|
|
79
|
+
for (const operator of operators) {
|
|
80
|
+
switch (operator) {
|
|
81
|
+
case '$eq':
|
|
82
|
+
fieldFilter.push((doc) => {
|
|
83
|
+
const savedValue = doc[field]
|
|
84
|
+
return savedValue == value
|
|
85
|
+
})
|
|
86
|
+
default:
|
|
87
|
+
throw new NotImplemented(`Operator ${operator} is not supported`)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const allCollectionItems = getItems()
|
|
93
|
+
return allCollectionItems.filter(savedDoc => {
|
|
94
|
+
return fieldFilter.every(comparator => {
|
|
95
|
+
return comparator(savedDoc)
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* $set
|
|
102
|
+
* @param {*} doc
|
|
103
|
+
* @param {*} update The update object. Should not contain operator
|
|
104
|
+
*/
|
|
105
|
+
function performSetUpdate(doc, update) {
|
|
106
|
+
for (const [field, newValue] of Object.entries(update)) {
|
|
107
|
+
doc[field] = newValue
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
async insertOne(doc) {
|
|
113
|
+
const items = getItems()
|
|
114
|
+
if (doc._id == null) {
|
|
115
|
+
// @ts-ignore
|
|
116
|
+
doc._id = new ObjectId()
|
|
117
|
+
}
|
|
118
|
+
items.push(doc)
|
|
119
|
+
},
|
|
120
|
+
async deleteOne(filter) {
|
|
121
|
+
const documentsToDelete = getFilteredItems(filter)
|
|
122
|
+
const allCollectionItems = getItems()
|
|
123
|
+
|
|
124
|
+
// Deleting the documents, one document at a time
|
|
125
|
+
while (documentsToDelete.length > 0) {
|
|
126
|
+
const docToDelete = documentsToDelete[0]
|
|
127
|
+
const index = allCollectionItems.indexOf(docToDelete)
|
|
128
|
+
if (index < 0) {
|
|
129
|
+
throw new Error('Document extracted from memory was not found in memory')
|
|
130
|
+
}
|
|
131
|
+
allCollectionItems.splice(index, 1)
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
async updateOne(filter, update) {
|
|
135
|
+
// Getting document to update
|
|
136
|
+
const documentsToUpdate = getFilteredItems(filter)
|
|
137
|
+
if (documentsToUpdate.length == 0) {
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
const docToUpdate = documentsToUpdate[0]
|
|
141
|
+
|
|
142
|
+
const updateKeys = Object.keys(update)
|
|
143
|
+
const operators = updateKeys.filter(x => x.startsWith('$'))
|
|
144
|
+
|
|
145
|
+
// Checking for empty updates
|
|
146
|
+
if (updateKeys.length == 0) {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Is a simple $set operation
|
|
151
|
+
if (operators.length == 0) {
|
|
152
|
+
performSetUpdate(docToUpdate, update)
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Validating update object
|
|
157
|
+
if (updateKeys.length != operators.length) {
|
|
158
|
+
throw new Error('This update does not look right...')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Processing complex update
|
|
162
|
+
for (const operator of operators) {
|
|
163
|
+
const value = update[operator]
|
|
164
|
+
switch (operator) {
|
|
165
|
+
case '$set':
|
|
166
|
+
performSetUpdate(docToUpdate, value)
|
|
167
|
+
break
|
|
168
|
+
default:
|
|
169
|
+
throw new Error(`Operator ${operator} not supported`)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
174
|
}
|