assai 1.1.1 → 2.1.0
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 +23 -22
- package/dist/src/factories/create_mongo_collection.d.mts +60 -18
- package/dist/src/types.d.ts +1 -1
- 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.d.mts +3 -1
- package/dist/src/usecases/mongo/operation/find_one.d.mts +4 -1
- 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/operation/insert_many.d.mts +3 -1
- package/dist/src/usecases/mongo/operation/insert_one.d.mts +3 -1
- package/dist/src/usecases/mongo/operation/update_many.d.mts +3 -1
- package/dist/src/usecases/mongo/operation/update_one.d.mts +4 -1
- package/dist/src/usecases/mongo/transformers/id/rename_find_options.d.mts +3 -4
- package/dist/src/usecases/mongo/transformers/input_transformer.d.mts +10 -0
- package/dist/src/usecases/mongo/transformers/output_transformer.d.mts +10 -0
- package/dist/src/usecases/mongo/transformers/timestamps.d.mts +6 -0
- package/jsconfig.json +16 -19
- package/package.json +5 -4
- package/src/factories/create_mongo_collection.mjs +75 -68
- package/src/types.ts +1 -15
- package/src/usecases/mongo/operation/aggregate.mjs +26 -0
- package/src/usecases/mongo/operation/bulk_write.mjs +54 -0
- package/src/usecases/mongo/operation/find.mjs +7 -6
- package/src/usecases/mongo/operation/find_one.mjs +9 -2
- 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 +5 -0
- package/src/usecases/mongo/operation/insert_many.mjs +7 -4
- package/src/usecases/mongo/operation/insert_one.mjs +10 -4
- package/src/usecases/mongo/operation/update_many.mjs +22 -1
- package/src/usecases/mongo/operation/update_one.mjs +23 -1
- package/src/usecases/mongo/transformers/input_transformer.mjs +33 -0
- package/src/usecases/mongo/transformers/output_transformer.mjs +19 -0
- package/src/usecases/mongo/transformers/timestamps.mjs +28 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Collection } from 'mongodb'
|
|
2
2
|
import {
|
|
3
|
+
aggregate, bulkWrite,
|
|
3
4
|
count, deleteMany, deleteOne,
|
|
4
5
|
deleteOneOrThrow,
|
|
5
|
-
find, findOne,
|
|
6
|
+
find, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate,
|
|
6
7
|
getClient,
|
|
7
8
|
insertMany, insertOne, updateMany, updateOne
|
|
8
9
|
} from '../usecases/mongo/index.mjs'
|
|
@@ -13,8 +14,7 @@ import {
|
|
|
13
14
|
* This method will read the string DATABASE_URL to create a connection. If you have it in another
|
|
14
15
|
* location, you will need to pass it at `connectionString` property inside the options parameter.
|
|
15
16
|
*
|
|
16
|
-
* The connection is cached by default. Use `collectionGetter`
|
|
17
|
-
* customize this behavior.
|
|
17
|
+
* The connection is cached by default. Use `collectionGetter` to customize this behavior.
|
|
18
18
|
* @template {import('../types.js').MongoDocument} T
|
|
19
19
|
* @param {string} name
|
|
20
20
|
* @param {IcreateCollectionOptions<T>} [options]
|
|
@@ -23,12 +23,12 @@ export function createMongoCollection(name, options = {}) {
|
|
|
23
23
|
|
|
24
24
|
/** @type {Collection<T> | null} */
|
|
25
25
|
let _collection = null
|
|
26
|
-
const
|
|
26
|
+
const collectionOptions = options
|
|
27
27
|
|
|
28
28
|
async function getCollection() {
|
|
29
29
|
const {
|
|
30
30
|
connectionString, dbName, options: createOptions,
|
|
31
|
-
|
|
31
|
+
collectionGetter,
|
|
32
32
|
} = options
|
|
33
33
|
|
|
34
34
|
// Connection getter from options
|
|
@@ -37,12 +37,6 @@ export function createMongoCollection(name, options = {}) {
|
|
|
37
37
|
// Checking cache
|
|
38
38
|
if (_collection) return _collection
|
|
39
39
|
|
|
40
|
-
// Cache function from options
|
|
41
|
-
if (cachableCollectionGetter != null) {
|
|
42
|
-
_collection = await cachableCollectionGetter()
|
|
43
|
-
return _collection
|
|
44
|
-
}
|
|
45
|
-
|
|
46
40
|
// Default connection getter
|
|
47
41
|
const client = await getClient({ connectionString })
|
|
48
42
|
let db = client.db(dbName, createOptions)
|
|
@@ -51,31 +45,6 @@ export function createMongoCollection(name, options = {}) {
|
|
|
51
45
|
return _collection
|
|
52
46
|
}
|
|
53
47
|
|
|
54
|
-
/**
|
|
55
|
-
*
|
|
56
|
-
* @param {import('../types.js').Optional<T, 'id'>} doc
|
|
57
|
-
*/
|
|
58
|
-
function validate(doc) {
|
|
59
|
-
if (validator == null) {
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
if (typeof validator == 'function') {
|
|
63
|
-
return validator(doc)
|
|
64
|
-
} else {
|
|
65
|
-
for (const [field, fieldValidator] of Object.entries(validator)) {
|
|
66
|
-
if (!fieldValidator) {
|
|
67
|
-
continue
|
|
68
|
-
}
|
|
69
|
-
const value = fieldValidator(doc[field])
|
|
70
|
-
if (value) {
|
|
71
|
-
// @ts-ignore
|
|
72
|
-
doc[field] = value
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return doc
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
48
|
return {
|
|
80
49
|
/**
|
|
81
50
|
* Returns the native driver.
|
|
@@ -91,7 +60,9 @@ export function createMongoCollection(name, options = {}) {
|
|
|
91
60
|
* @param {import('../types.js').FindOptions<T, K>} options
|
|
92
61
|
* @returns {Promise<T[]>}
|
|
93
62
|
*/
|
|
94
|
-
find: async (query, options = {}) =>
|
|
63
|
+
find: async (query, options = {}) => {
|
|
64
|
+
return await find({ query, options, getCollection, collectionOptions })
|
|
65
|
+
},
|
|
95
66
|
/**
|
|
96
67
|
* @template {import('../types.js').Projection<T> | undefined} K
|
|
97
68
|
* @param {import('mongodb').Filter<T>} query
|
|
@@ -99,20 +70,17 @@ export function createMongoCollection(name, options = {}) {
|
|
|
99
70
|
* @returns {Promise<T | null>}
|
|
100
71
|
*/
|
|
101
72
|
findOne: async (query, options = {}) => {
|
|
102
|
-
return await findOne({ query, options, getCollection })
|
|
73
|
+
return await findOne({ query, options, collectionOptions, getCollection })
|
|
103
74
|
},
|
|
104
75
|
/**
|
|
105
76
|
* @param {import('../types.js').Optional<T, 'id'>} doc
|
|
106
77
|
* @returns {Promise<T>}
|
|
107
78
|
*/
|
|
108
79
|
insertOne: async (doc) => {
|
|
109
|
-
const result = validate(doc)
|
|
110
|
-
if (result) {
|
|
111
|
-
doc = result
|
|
112
|
-
}
|
|
113
80
|
return await insertOne({
|
|
114
81
|
doc,
|
|
115
82
|
getCollection,
|
|
83
|
+
collectionOptions,
|
|
116
84
|
})
|
|
117
85
|
},
|
|
118
86
|
/**
|
|
@@ -120,7 +88,7 @@ export function createMongoCollection(name, options = {}) {
|
|
|
120
88
|
* @param {import('../types.js').Optional<T, 'id'>[]} docs
|
|
121
89
|
* @returns {Promise<T[]>}
|
|
122
90
|
*/
|
|
123
|
-
insertMany: async (docs) => await insertMany({ docs, getCollection }),
|
|
91
|
+
insertMany: async (docs) => await insertMany({ docs, collectionOptions, getCollection }),
|
|
124
92
|
/**
|
|
125
93
|
* @param {import('mongodb').Filter<T>} query
|
|
126
94
|
* @returns {Promise<boolean>}
|
|
@@ -144,7 +112,7 @@ export function createMongoCollection(name, options = {}) {
|
|
|
144
112
|
* @param {import('mongodb').UpdateOptions} [options]
|
|
145
113
|
*/
|
|
146
114
|
updateOne: async (query, update, options) => await updateOne({
|
|
147
|
-
query, update, options, getCollection,
|
|
115
|
+
query, update, options, collectionOptions, getCollection,
|
|
148
116
|
}),
|
|
149
117
|
/**
|
|
150
118
|
* @param {import('mongodb').Filter<T>} query
|
|
@@ -152,8 +120,56 @@ export function createMongoCollection(name, options = {}) {
|
|
|
152
120
|
* @param {import('mongodb').UpdateOptions} [options]
|
|
153
121
|
*/
|
|
154
122
|
updateMany: async (query, update, options) => await updateMany({
|
|
155
|
-
query, update, options, getCollection,
|
|
156
|
-
})
|
|
123
|
+
query, update, options, collectionOptions, getCollection,
|
|
124
|
+
}),
|
|
125
|
+
/**
|
|
126
|
+
* @param {import('mongodb').Document[]} pipeline
|
|
127
|
+
* @param {import('mongodb').AggregateOptions} [options]
|
|
128
|
+
* @returns {Promise<T[]>}
|
|
129
|
+
*/
|
|
130
|
+
aggregate: async (pipeline, options) => await aggregate({
|
|
131
|
+
pipeline, options, getCollection, collectionOptions,
|
|
132
|
+
}),
|
|
133
|
+
/**
|
|
134
|
+
* @param {import('mongodb').AnyBulkWriteOperation<T>[]} operations
|
|
135
|
+
* @param {import('mongodb').BulkWriteOptions} [options]
|
|
136
|
+
*/
|
|
137
|
+
bulkWrite: async (operations, options) => await bulkWrite({
|
|
138
|
+
operations, options, getCollection, collectionOptions,
|
|
139
|
+
}),
|
|
140
|
+
/**
|
|
141
|
+
* Atomically finds a document, applies the update, and returns the document.
|
|
142
|
+
* By default returns the document as it was **before** the update.
|
|
143
|
+
* Pass `{ returnDocument: 'after' }` in options to get the updated version.
|
|
144
|
+
* @param {import('mongodb').Filter<T>} query
|
|
145
|
+
* @param {import('mongodb').UpdateFilter<T>} update
|
|
146
|
+
* @param {import('mongodb').FindOneAndUpdateOptions} [options]
|
|
147
|
+
* @returns {Promise<T | null>}
|
|
148
|
+
*/
|
|
149
|
+
findOneAndUpdate: async (query, update, options) => await findOneAndUpdate({
|
|
150
|
+
query, update, options, getCollection, collectionOptions,
|
|
151
|
+
}),
|
|
152
|
+
/**
|
|
153
|
+
* Atomically finds a document, deletes it, and returns the deleted document.
|
|
154
|
+
* @param {import('mongodb').Filter<T>} query
|
|
155
|
+
* @param {import('mongodb').FindOneAndDeleteOptions} [options]
|
|
156
|
+
* @returns {Promise<T | null>}
|
|
157
|
+
*/
|
|
158
|
+
findOneAndDelete: async (query, options) => await findOneAndDelete({
|
|
159
|
+
query, options, getCollection, collectionOptions,
|
|
160
|
+
}),
|
|
161
|
+
/**
|
|
162
|
+
* Atomically finds a document, replaces it with `replacement`, and returns a document.
|
|
163
|
+
* By default returns the document as it was **before** the replacement.
|
|
164
|
+
* Pass `{ returnDocument: 'after' }` in options to get the new version.
|
|
165
|
+
* @param {import('mongodb').Filter<T>} query
|
|
166
|
+
* @param {import('mongodb').WithoutId<T>} replacement
|
|
167
|
+
* @param {import('mongodb').FindOneAndReplaceOptions} [options]
|
|
168
|
+
* @returns {Promise<T | null>}
|
|
169
|
+
*/
|
|
170
|
+
findOneAndReplace: async (query, replacement, options) => await findOneAndReplace({
|
|
171
|
+
query, replacement, options, getCollection, collectionOptions,
|
|
172
|
+
}),
|
|
157
173
|
}
|
|
158
174
|
}
|
|
159
175
|
|
|
@@ -178,14 +194,6 @@ export function createMongoCollection(name, options = {}) {
|
|
|
178
194
|
* collectionGetter: async () => await getMyCollection()
|
|
179
195
|
* ```
|
|
180
196
|
*
|
|
181
|
-
* @property {IcollectionGetter<T>} [options.cachableCollectionGetter]
|
|
182
|
-
* Same as `collectionGetter`. But the object is cached.
|
|
183
|
-
*
|
|
184
|
-
* Example:
|
|
185
|
-
* ```js
|
|
186
|
-
* cachableCollectionGetter: async () => await getMyCollection()
|
|
187
|
-
* ```
|
|
188
|
-
*
|
|
189
197
|
* @property {string} [options.connectionString]
|
|
190
198
|
* A custom connection string. If none is given, `process.env.DATABASE_URL` will be used.
|
|
191
199
|
*
|
|
@@ -193,23 +201,22 @@ export function createMongoCollection(name, options = {}) {
|
|
|
193
201
|
*
|
|
194
202
|
* @property {import('mongodb').DbOptions} [options] The options used when initializing the client.
|
|
195
203
|
*
|
|
196
|
-
* @property {
|
|
204
|
+
* @property {ItimestampConfiguration} [timestamps] Configured how the package manages 'createdAt'
|
|
205
|
+
* and 'updatedAt'.
|
|
197
206
|
*/
|
|
198
207
|
|
|
199
208
|
/**
|
|
200
|
-
* @
|
|
201
|
-
* @
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* If null is returned, the input parameter will be used normaly in inserts.
|
|
209
|
+
* @typedef {object} ItimestampConfiguration
|
|
210
|
+
* @property {'fromId' | 'generate' | 'none'} createdAt
|
|
211
|
+
* Changes how the 'createdAt' field is managed:
|
|
212
|
+
* - 'fromId': the field is generated when you use `find` or `findOne` and is calculated using _id.
|
|
213
|
+
* But it does not exist in the database.
|
|
214
|
+
* - 'generate': the field is generated when you use `insertOne` or `insertMany`. The value exist in
|
|
215
|
+
* the database.
|
|
216
|
+
* - 'none': no value is generated at any time.
|
|
217
|
+
* @property {'generate' | 'none'} updatedAt
|
|
218
|
+
* - 'generate': the value is generated when you use `insertOne` or `insertMany` and is updated on
|
|
219
|
+
* `updateOne` and `updateMany`.
|
|
213
220
|
*/
|
|
214
221
|
|
|
215
222
|
/**
|
package/src/types.ts
CHANGED
|
@@ -27,20 +27,6 @@ type GivenProjectionReturnType<T extends MongoDocument, P extends NonNullProject
|
|
|
27
27
|
export type ProjectionReturnType<T extends MongoDocument, P extends Projection<T>> =
|
|
28
28
|
P extends NonNullProjection<T> ? GivenProjectionReturnType<T, P> : T
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
// P extends Partial<Record<keyof T, 0>>
|
|
32
|
-
// ? {
|
|
33
|
-
// [K in keyof T as P[K] extends 0 ? never : K]: T[K]
|
|
34
|
-
// }
|
|
35
|
-
// : (P extends Partial<Record<keyof T, 0 | 1>> ? {
|
|
36
|
-
// [K in keyof T as P[K] extends 1 ? K : (
|
|
37
|
-
// K extends 'id' ? (
|
|
38
|
-
// P[K] extends 0 ? never : K
|
|
39
|
-
// ) :
|
|
40
|
-
// never
|
|
41
|
-
// )]: T[K]
|
|
42
|
-
// } : T)
|
|
43
|
-
|
|
44
|
-
export type FindOptions<T extends MongoDocument, K extends Projection<T>> = Omit<FO<T>, 'projection'> & {
|
|
30
|
+
export type FindOptions<T extends MongoDocument, K extends Projection<T>> = Omit<FO, 'projection'> & {
|
|
45
31
|
projection?: K
|
|
46
32
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Collection } from 'mongodb'
|
|
2
|
+
import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
3
|
+
import { outputTransformer } from '../transformers/output_transformer.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template {import('../../../types.js').MongoDocument} T
|
|
7
|
+
* @param {object} parameter
|
|
8
|
+
* @param {() => Promise<Collection<T>>} parameter.getCollection
|
|
9
|
+
* @param {import('mongodb').Document[]} parameter.pipeline
|
|
10
|
+
* @param {import('mongodb').AggregateOptions} [parameter.options]
|
|
11
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [parameter.collectionOptions]
|
|
12
|
+
* @returns {Promise<T[]>}
|
|
13
|
+
*/
|
|
14
|
+
export async function aggregate({ getCollection, pipeline, options, collectionOptions }) {
|
|
15
|
+
for (const stage of pipeline) {
|
|
16
|
+
if (stage.$match != null) {
|
|
17
|
+
stage.$match = renameToMongoId(stage.$match)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
pipeline = stringsIntoId(pipeline)
|
|
21
|
+
|
|
22
|
+
const col = await getCollection()
|
|
23
|
+
const docs = await col.aggregate(pipeline, options).toArray()
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
return docs.map((doc) => outputTransformer({ document: doc, collectionOptions }))
|
|
26
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Collection } from 'mongodb'
|
|
2
|
+
import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
3
|
+
import { inputTransformer } from '../transformers/input_transformer.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template {import('../../../types.js').MongoDocument} T
|
|
7
|
+
* @param {object} parameter
|
|
8
|
+
* @param {() => Promise<Collection<T>>} parameter.getCollection
|
|
9
|
+
* @param {import('mongodb').AnyBulkWriteOperation<T>[]} parameter.operations
|
|
10
|
+
* @param {import('mongodb').BulkWriteOptions} [parameter.options]
|
|
11
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [parameter.collectionOptions]
|
|
12
|
+
*/
|
|
13
|
+
export async function bulkWrite({ getCollection, operations, options, collectionOptions }) {
|
|
14
|
+
for (const op of operations) {
|
|
15
|
+
/** @type {any} */
|
|
16
|
+
const o = op
|
|
17
|
+
if (o.insertOne != null) {
|
|
18
|
+
o.insertOne.document = inputTransformer({
|
|
19
|
+
document: o.insertOne.document,
|
|
20
|
+
collectionOptions,
|
|
21
|
+
})
|
|
22
|
+
} else if (o.updateOne != null) {
|
|
23
|
+
o.updateOne.filter = renameToMongoId(o.updateOne.filter)
|
|
24
|
+
stringsIntoId(o.updateOne.filter)
|
|
25
|
+
stringsIntoId(o.updateOne.update)
|
|
26
|
+
} else if (o.updateMany != null) {
|
|
27
|
+
o.updateMany.filter = renameToMongoId(o.updateMany.filter)
|
|
28
|
+
stringsIntoId(o.updateMany.filter)
|
|
29
|
+
stringsIntoId(o.updateMany.update)
|
|
30
|
+
} else if (o.deleteOne != null) {
|
|
31
|
+
o.deleteOne.filter = renameToMongoId(o.deleteOne.filter)
|
|
32
|
+
stringsIntoId(o.deleteOne.filter)
|
|
33
|
+
} else if (o.deleteMany != null) {
|
|
34
|
+
o.deleteMany.filter = renameToMongoId(o.deleteMany.filter)
|
|
35
|
+
stringsIntoId(o.deleteMany.filter)
|
|
36
|
+
} else if (o.replaceOne != null) {
|
|
37
|
+
o.replaceOne.filter = renameToMongoId(o.replaceOne.filter)
|
|
38
|
+
stringsIntoId(o.replaceOne.filter)
|
|
39
|
+
stringsIntoId(o.replaceOne.replacement)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const col = await getCollection()
|
|
44
|
+
const result = await col.bulkWrite(operations, options)
|
|
45
|
+
|
|
46
|
+
if (result.insertedIds) {
|
|
47
|
+
for (const key of Object.keys(result.insertedIds)) {
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
result.insertedIds[key] = result.insertedIds[key].toHexString()
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return result
|
|
54
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Collection } from 'mongodb'
|
|
2
2
|
import {
|
|
3
|
-
idsIntoString,
|
|
4
3
|
renameFindOptions,
|
|
5
|
-
renameToDevId,
|
|
6
4
|
renameToMongoId,
|
|
7
5
|
stringsIntoId
|
|
8
6
|
} from '../transformers/index.mjs'
|
|
7
|
+
import { outputTransformer } from '../transformers/output_transformer.mjs'
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* @template {import('../../../types.js').MongoDocument} T
|
|
@@ -14,9 +13,10 @@ import {
|
|
|
14
13
|
* @param {() => Promise<Collection<T>>} parameter.getCollection
|
|
15
14
|
* @param {import('mongodb').Filter<T>} parameter.query
|
|
16
15
|
* @param {import('../../../types.js').FindOptions<T, K>} [parameter.options]
|
|
16
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [parameter.collectionOptions]
|
|
17
17
|
* @returns {Promise<T[]>}
|
|
18
18
|
*/
|
|
19
|
-
export async function find({ getCollection, query, options }) {
|
|
19
|
+
export async function find({ getCollection, query, options, collectionOptions }) {
|
|
20
20
|
query = renameToMongoId(query)
|
|
21
21
|
options = renameFindOptions(options)
|
|
22
22
|
|
|
@@ -26,9 +26,10 @@ export async function find({ getCollection, query, options }) {
|
|
|
26
26
|
|
|
27
27
|
const docs = await col.find(query, options).toArray()
|
|
28
28
|
const fixedDocs = docs.map((doc) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
return outputTransformer({
|
|
30
|
+
document: doc,
|
|
31
|
+
collectionOptions,
|
|
32
|
+
})
|
|
32
33
|
})
|
|
33
34
|
return fixedDocs
|
|
34
35
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Collection } from 'mongodb'
|
|
2
|
+
import { outputTransformer } from '../transformers/output_transformer.mjs'
|
|
2
3
|
import { find } from './find.mjs'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -8,8 +9,10 @@ import { find } from './find.mjs'
|
|
|
8
9
|
* @param {import('mongodb').Filter<T>} param.query
|
|
9
10
|
* @param {import('../../../types.js').FindOptions<T, K>} [param.options]
|
|
10
11
|
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
12
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} param.collectionOptions
|
|
13
|
+
* @returns {Promise<T | null>}
|
|
11
14
|
*/
|
|
12
|
-
export async function findOne({ query, options, getCollection }) {
|
|
15
|
+
export async function findOne({ query, options, collectionOptions, getCollection }) {
|
|
13
16
|
const docs = await find({
|
|
14
17
|
query,
|
|
15
18
|
options: {
|
|
@@ -22,5 +25,9 @@ export async function findOne({ query, options, getCollection }) {
|
|
|
22
25
|
if (doc == null) {
|
|
23
26
|
return null
|
|
24
27
|
}
|
|
25
|
-
|
|
28
|
+
|
|
29
|
+
return outputTransformer({
|
|
30
|
+
document: doc,
|
|
31
|
+
collectionOptions,
|
|
32
|
+
})
|
|
26
33
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Collection } from 'mongodb'
|
|
2
|
+
import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
3
|
+
import { outputTransformer } from '../transformers/output_transformer.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template {import('../../../types.js').MongoDocument} T
|
|
7
|
+
* @param {object} param
|
|
8
|
+
* @param {import('mongodb').Filter<T>} param.query
|
|
9
|
+
* @param {import('mongodb').FindOneAndDeleteOptions} [param.options]
|
|
10
|
+
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
11
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [param.collectionOptions]
|
|
12
|
+
* @returns {Promise<T | null>}
|
|
13
|
+
*/
|
|
14
|
+
export async function findOneAndDelete({ query, options, collectionOptions, getCollection }) {
|
|
15
|
+
query = renameToMongoId(query)
|
|
16
|
+
stringsIntoId(query)
|
|
17
|
+
const col = await getCollection()
|
|
18
|
+
|
|
19
|
+
const doc = await col.findOneAndDelete(query, options ?? {})
|
|
20
|
+
if (doc == null) return null
|
|
21
|
+
|
|
22
|
+
return outputTransformer({ document: doc, collectionOptions })
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Collection } from 'mongodb'
|
|
2
|
+
import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
3
|
+
import { outputTransformer } from '../transformers/output_transformer.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template {import('../../../types.js').MongoDocument} T
|
|
7
|
+
* @param {object} param
|
|
8
|
+
* @param {import('mongodb').Filter<T>} param.query
|
|
9
|
+
* @param {import('mongodb').WithoutId<T>} param.replacement
|
|
10
|
+
* @param {import('mongodb').FindOneAndReplaceOptions} [param.options]
|
|
11
|
+
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
12
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [param.collectionOptions]
|
|
13
|
+
* @returns {Promise<T | null>}
|
|
14
|
+
*/
|
|
15
|
+
export async function findOneAndReplace({ query, replacement, options, collectionOptions, getCollection }) {
|
|
16
|
+
query = renameToMongoId(query)
|
|
17
|
+
stringsIntoId(query)
|
|
18
|
+
const col = await getCollection()
|
|
19
|
+
|
|
20
|
+
const doc = await col.findOneAndReplace(query, replacement, options ?? {})
|
|
21
|
+
if (doc == null) return null
|
|
22
|
+
|
|
23
|
+
return outputTransformer({ document: doc, collectionOptions })
|
|
24
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Collection } from 'mongodb'
|
|
2
|
+
import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
3
|
+
import { outputTransformer } from '../transformers/output_transformer.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template {import('../../../types.js').MongoDocument} T
|
|
7
|
+
* @param {object} param
|
|
8
|
+
* @param {import('mongodb').Filter<T>} param.query
|
|
9
|
+
* @param {import('mongodb').UpdateFilter<T>} param.update
|
|
10
|
+
* @param {import('mongodb').FindOneAndUpdateOptions} [param.options]
|
|
11
|
+
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
12
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [param.collectionOptions]
|
|
13
|
+
* @returns {Promise<T | null>}
|
|
14
|
+
*/
|
|
15
|
+
export async function findOneAndUpdate({ query, update, options, collectionOptions, getCollection }) {
|
|
16
|
+
query = renameToMongoId(query)
|
|
17
|
+
stringsIntoId(query)
|
|
18
|
+
stringsIntoId(update)
|
|
19
|
+
const col = await getCollection()
|
|
20
|
+
|
|
21
|
+
const { timestamps } = collectionOptions ?? {}
|
|
22
|
+
const { updatedAt } = timestamps ?? { updatedAt: 'generate' }
|
|
23
|
+
|
|
24
|
+
const { $set } = update
|
|
25
|
+
const hasUpdatedAt = $set != null && $set.updatedAt != null
|
|
26
|
+
if (!hasUpdatedAt && updatedAt === 'generate') {
|
|
27
|
+
if ($set != null) {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
$set.updatedAt = new Date()
|
|
30
|
+
} else {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
update.$set = { updatedAt: new Date() }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const doc = await col.findOneAndUpdate(query, update, options ?? {})
|
|
37
|
+
if (doc == null) return null
|
|
38
|
+
|
|
39
|
+
return outputTransformer({ document: doc, collectionOptions })
|
|
40
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
export * from './additional/index.mjs'
|
|
2
|
+
export * from './aggregate.mjs'
|
|
3
|
+
export * from './bulk_write.mjs'
|
|
2
4
|
export * from './count.mjs'
|
|
3
5
|
export * from './delete_many.mjs'
|
|
4
6
|
export * from './delete_one.mjs'
|
|
5
7
|
export * from './find.mjs'
|
|
6
8
|
export * from './find_one.mjs'
|
|
9
|
+
export * from './find_one_and_delete.mjs'
|
|
10
|
+
export * from './find_one_and_replace.mjs'
|
|
11
|
+
export * from './find_one_and_update.mjs'
|
|
7
12
|
export * from './insert_many.mjs'
|
|
8
13
|
export * from './insert_one.mjs'
|
|
9
14
|
export * from './update_many.mjs'
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Collection, ObjectId } from 'mongodb'
|
|
2
|
-
import {
|
|
2
|
+
import { inputTransformer } from '../transformers/input_transformer.mjs'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @template {import('../../../types.js').MongoDocument} T
|
|
6
6
|
* @param {object} param
|
|
7
7
|
* @param {import('../../../types.js').Optional<T, 'id'>[]} param.docs
|
|
8
8
|
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
9
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} param.collectionOptions
|
|
9
10
|
* @returns {Promise<T[]>}
|
|
10
11
|
*/
|
|
11
|
-
export async function insertMany({ docs, getCollection }) {
|
|
12
|
+
export async function insertMany({ docs, collectionOptions, getCollection }) {
|
|
12
13
|
if (docs.length == 0) return []
|
|
13
14
|
|
|
14
15
|
// We need to clone the array to prevent the function from changing the original input object.
|
|
@@ -16,8 +17,10 @@ export async function insertMany({ docs, getCollection }) {
|
|
|
16
17
|
docs = [...docs]
|
|
17
18
|
|
|
18
19
|
for (let i = 0; i < docs.length; i++) {
|
|
19
|
-
docs[i] =
|
|
20
|
-
|
|
20
|
+
docs[i] = inputTransformer({
|
|
21
|
+
document: docs[i],
|
|
22
|
+
collectionOptions: collectionOptions
|
|
23
|
+
})
|
|
21
24
|
}
|
|
22
25
|
const col = await getCollection()
|
|
23
26
|
const result = await col.insertMany(
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { Collection, ObjectId } from 'mongodb'
|
|
2
|
-
import {
|
|
2
|
+
import { inputTransformer } from '../transformers/input_transformer.mjs'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @template {import('../../../types.js').MongoDocument} T
|
|
6
6
|
* @param {object} param
|
|
7
7
|
* @param {import('../../../types.js').Optional<T, 'id'>} param.doc
|
|
8
8
|
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
9
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [param.collectionOptions]
|
|
9
10
|
* @returns {Promise<T>}
|
|
10
11
|
*/
|
|
11
|
-
export async function insertOne({ doc, getCollection }) {
|
|
12
|
-
doc =
|
|
13
|
-
|
|
12
|
+
export async function insertOne({ doc, collectionOptions, getCollection }) {
|
|
13
|
+
doc = inputTransformer({
|
|
14
|
+
document: doc,
|
|
15
|
+
collectionOptions
|
|
16
|
+
})
|
|
17
|
+
|
|
14
18
|
const col = await getCollection()
|
|
15
19
|
const result = await col.insertOne(
|
|
16
20
|
// @ts-ignore
|
|
@@ -22,6 +26,8 @@ export async function insertOne({ doc, getCollection }) {
|
|
|
22
26
|
id = id.toHexString()
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
delete doc._id
|
|
30
|
+
|
|
25
31
|
// @ts-ignore
|
|
26
32
|
return { id, ...doc }
|
|
27
33
|
}
|
|
@@ -8,11 +8,32 @@ import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
|
8
8
|
* @param {import('mongodb').UpdateFilter<T>} param.update
|
|
9
9
|
* @param {import('mongodb').UpdateOptions} [param.options]
|
|
10
10
|
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
11
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [param.collectionOptions]
|
|
11
12
|
*/
|
|
12
|
-
export async function updateMany({ query, update, options, getCollection }) {
|
|
13
|
+
export async function updateMany({ query, update, options, collectionOptions, getCollection }) {
|
|
13
14
|
query = renameToMongoId(query)
|
|
14
15
|
stringsIntoId(query)
|
|
15
16
|
stringsIntoId(update)
|
|
17
|
+
|
|
18
|
+
const { timestamps } = collectionOptions ?? {}
|
|
19
|
+
const { updatedAt } = timestamps ?? {
|
|
20
|
+
updatedAt: 'generate'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { $set } = update
|
|
24
|
+
const hasUpdatedAt = $set != null && $set.updatedAt != null
|
|
25
|
+
if (!hasUpdatedAt && updatedAt === 'generate') {
|
|
26
|
+
if ($set != null) {
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
$set.updatedAt = new Date()
|
|
29
|
+
} else {
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
update.$set = {
|
|
32
|
+
updatedAt: new Date()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
16
37
|
const col = await getCollection()
|
|
17
38
|
const r = await col.updateMany(query, update, options)
|
|
18
39
|
return r
|
|
@@ -8,12 +8,34 @@ import { renameToMongoId, stringsIntoId } from '../transformers/index.mjs'
|
|
|
8
8
|
* @param {import('mongodb').UpdateFilter<T>} param.update
|
|
9
9
|
* @param {import('mongodb').UpdateOptions} [param.options]
|
|
10
10
|
* @param {() => Promise<Collection<T>>} param.getCollection
|
|
11
|
+
* @param {import('../../../factories/create_mongo_collection.mjs').IcreateCollectionOptions<T>} [param.collectionOptions]
|
|
12
|
+
* @returns {Promise<boolean>}
|
|
11
13
|
*/
|
|
12
|
-
export async function updateOne({ query, update, options, getCollection }) {
|
|
14
|
+
export async function updateOne({ query, update, options, collectionOptions, getCollection }) {
|
|
13
15
|
query = renameToMongoId(query)
|
|
14
16
|
stringsIntoId(query)
|
|
15
17
|
stringsIntoId(update)
|
|
16
18
|
const col = await getCollection()
|
|
19
|
+
|
|
20
|
+
const { timestamps } = collectionOptions ?? {}
|
|
21
|
+
const { updatedAt } = timestamps ?? {
|
|
22
|
+
updatedAt: 'generate'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { $set } = update
|
|
26
|
+
const hasUpdatedAt = $set != null && $set.updatedAt != null
|
|
27
|
+
if (!hasUpdatedAt && updatedAt === 'generate') {
|
|
28
|
+
if ($set != null) {
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
$set.updatedAt = new Date()
|
|
31
|
+
} else {
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
update.$set = {
|
|
34
|
+
updatedAt: new Date()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
17
39
|
const r = await col.updateOne(query, update, options)
|
|
18
40
|
return r.matchedCount > 0
|
|
19
41
|
}
|