@toa.io/storages.mongodb 1.0.0-alpha.273 → 1.0.0-alpha.277
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/CHANGELOG.md +16 -0
- package/package.json +9 -8
- package/src/client.js +6 -10
- package/src/deployment.js +3 -8
- package/src/factory.js +3 -7
- package/src/index.js +2 -7
- package/src/outbox.js +2 -6
- package/src/record.js +2 -7
- package/src/storage.js +8 -12
- package/src/translate/criteria.js +2 -6
- package/src/translate/options.js +2 -6
- package/src/translate/rename.js +1 -5
- package/src/translate.js +4 -5
- package/test/query/criteria.fixtures.js +2 -7
- package/test/query/criteria.test.js +5 -4
- package/test/record.test.js +6 -8
- package/test/storage.test.js +13 -13
- package/test/translate.test.js +7 -6
- package/types/connection.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.0.0-alpha.277](https://github.com/toa-io/toa/compare/v1.0.0-alpha.276...v1.0.0-alpha.277) (2026-09-03)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @toa.io/storages.mongodb
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [1.0.0-alpha.274](https://github.com/toa-io/toa/compare/v1.0.0-alpha.273...v1.0.0-alpha.274) (2026-09-02)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @toa.io/storages.mongodb
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
# [1.0.0-alpha.273](https://github.com/toa-io/toa/compare/v1.0.0-alpha.272...v1.0.0-alpha.273) (2026-09-02)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @toa.io/storages.mongodb
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/storages.mongodb",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.277",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Toa MongoDB Storage Connector",
|
|
5
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
7
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -19,13 +20,13 @@
|
|
|
19
20
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@toa.io/conveyor": "1.0.0-alpha.
|
|
23
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
24
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
25
|
-
"@toa.io/pointer": "1.0.0-alpha.
|
|
26
|
-
"mongodb": "7.
|
|
27
|
-
"openspan": "1.0.0-alpha.
|
|
23
|
+
"@toa.io/conveyor": "1.0.0-alpha.277",
|
|
24
|
+
"@toa.io/core": "1.0.0-alpha.277",
|
|
25
|
+
"@toa.io/generic": "1.0.0-alpha.277",
|
|
26
|
+
"@toa.io/pointer": "1.0.0-alpha.277",
|
|
27
|
+
"mongodb": "7.6.0",
|
|
28
|
+
"openspan": "1.0.0-alpha.277",
|
|
28
29
|
"saslprep": "1.0.3"
|
|
29
30
|
},
|
|
30
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "0c0071418c2c56a44e621ba5ced5cdd23dff1738"
|
|
31
32
|
}
|
package/src/client.js
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @typedef {import('mongodb').MongoClient} MongoClient
|
|
5
3
|
* @typedef {{ count: number, client: MongoClient }} Instance
|
|
6
4
|
* @typedef {import('@toa.io/core').Locator} Locator
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
import { console } from 'openspan'
|
|
8
|
+
import { Connector } from '@toa.io/core'
|
|
9
|
+
import { resolve } from '@toa.io/pointer'
|
|
10
|
+
import { ID } from './deployment.js'
|
|
11
|
+
import { MongoClient } from 'mongodb'
|
|
14
12
|
|
|
15
13
|
/**
|
|
16
14
|
* @type {Record<string, Promise<Instance>>}
|
|
17
15
|
*/
|
|
18
16
|
const INSTANCES = {}
|
|
19
17
|
|
|
20
|
-
class Client extends Connector {
|
|
18
|
+
export class Client extends Connector {
|
|
21
19
|
name
|
|
22
20
|
|
|
23
21
|
/**
|
|
@@ -234,5 +232,3 @@ const OPTIONS = {
|
|
|
234
232
|
|
|
235
233
|
const ALREADY_EXISTS = 48
|
|
236
234
|
const OUTBOX = '_outbox'
|
|
237
|
-
|
|
238
|
-
exports.Client = Client
|
package/src/deployment.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { createVariables } from '@toa.io/pointer'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const deployment = (instances, annotation) => {
|
|
3
|
+
export const deployment = (instances, annotation) => {
|
|
6
4
|
const requests = instances.map((instance) => createRequest(instance))
|
|
7
5
|
const variables = createVariables(ID, annotation, requests)
|
|
8
6
|
|
|
@@ -16,7 +14,4 @@ function createRequest (instance) {
|
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
const ID = 'mongodb'
|
|
20
|
-
|
|
21
|
-
exports.ID = ID
|
|
22
|
-
exports.deployment = deployment
|
|
17
|
+
export const ID = 'mongodb'
|
package/src/factory.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { Client } from './client.js'
|
|
2
|
+
import { Storage } from './storage.js'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const { Storage } = require('./storage')
|
|
5
|
-
|
|
6
|
-
class Factory {
|
|
4
|
+
export class Factory {
|
|
7
5
|
storage (locator, entity, options = {}) {
|
|
8
6
|
const client = new Client(locator, options.outbox === true)
|
|
9
7
|
|
|
10
8
|
return new Storage(client, entity)
|
|
11
9
|
}
|
|
12
10
|
}
|
|
13
|
-
|
|
14
|
-
exports.Factory = Factory
|
package/src/index.js
CHANGED
package/src/outbox.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { console } = require('openspan')
|
|
1
|
+
import { console } from 'openspan'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* The outbox rows of one component. Its lifecycle is the Client's, so it is not a Connector.
|
|
@@ -8,7 +6,7 @@ const { console } = require('openspan')
|
|
|
8
6
|
* Core owns what a row means — its id, its lane and when it becomes due. This only writes
|
|
9
7
|
* them, reads back what is due, and marks what has been published.
|
|
10
8
|
*/
|
|
11
|
-
class Outbox {
|
|
9
|
+
export class Outbox {
|
|
12
10
|
/** @type {import('mongodb').Collection} */
|
|
13
11
|
#collection
|
|
14
12
|
|
|
@@ -125,5 +123,3 @@ function retention () {
|
|
|
125
123
|
|
|
126
124
|
/** seconds a published row is kept as a change log before the TTL monitor reaps it */
|
|
127
125
|
const RETENTION = 86400
|
|
128
|
-
|
|
129
|
-
exports.Outbox = Outbox
|
package/src/record.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function to (entity) {
|
|
1
|
+
export function to (entity) {
|
|
4
2
|
const { id, ...rest } = entity
|
|
5
3
|
|
|
6
4
|
return /** @type {toa.mongodb.Record} */ { _id: id, ...rest }
|
|
7
5
|
}
|
|
8
6
|
|
|
9
|
-
function from (record) {
|
|
7
|
+
export function from (record) {
|
|
10
8
|
if (record === undefined || record === null)
|
|
11
9
|
return null
|
|
12
10
|
|
|
@@ -14,6 +12,3 @@ function from (record) {
|
|
|
14
12
|
|
|
15
13
|
return { id: _id, ...rest }
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
exports.to = to
|
|
19
|
-
exports.from = from
|
package/src/storage.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Storage extends Connector {
|
|
1
|
+
import { Connector, exceptions } from '@toa.io/core'
|
|
2
|
+
import { console } from 'openspan'
|
|
3
|
+
import { translate } from './translate.js'
|
|
4
|
+
import { to, from } from './record.js'
|
|
5
|
+
import { Outbox } from './outbox.js'
|
|
6
|
+
import { ReturnDocument } from 'mongodb'
|
|
7
|
+
|
|
8
|
+
export class Storage extends Connector {
|
|
11
9
|
#client
|
|
12
10
|
|
|
13
11
|
/** @type {import('mongodb').Collection} */
|
|
@@ -500,5 +498,3 @@ async function retriable (error, attempt) {
|
|
|
500
498
|
}
|
|
501
499
|
|
|
502
500
|
const LAST_ATTEMPT = 9
|
|
503
|
-
|
|
504
|
-
exports.Storage = Storage
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { rename } = require('./rename')
|
|
1
|
+
import { rename } from './rename.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* @param {toa.core.storages.ast.Node} node
|
|
7
5
|
* @returns {import('mongodb').Filter}
|
|
8
6
|
*/
|
|
9
|
-
const criteria = (node) => {
|
|
7
|
+
export const criteria = (node) => {
|
|
10
8
|
if (TYPES[node.type] === undefined) throw new Error(`AST parse error: unknown node type '${node.type}'`)
|
|
11
9
|
|
|
12
10
|
return TYPES[node.type](node)
|
|
@@ -52,5 +50,3 @@ TYPES.COMPARISON = (expression) => {
|
|
|
52
50
|
|
|
53
51
|
TYPES.SELECTOR = (expression) => rename(expression.selector)
|
|
54
52
|
TYPES.VALUE = (expression) => expression.value
|
|
55
|
-
|
|
56
|
-
exports.criteria = criteria
|
package/src/translate/options.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { rename } from './rename.js'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const options = (options) => {
|
|
3
|
+
export const options = (options) => {
|
|
6
4
|
const result = {}
|
|
7
5
|
|
|
8
6
|
if (options.omit) { result.skip = options.omit }
|
|
@@ -29,5 +27,3 @@ const DIRECTIONS = {
|
|
|
29
27
|
asc: 1,
|
|
30
28
|
desc: -1
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
exports.options = options
|
package/src/translate/rename.js
CHANGED
package/src/translate.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import * as _criteria from './translate/criteria.js'
|
|
2
|
+
import * as _options from './translate/options.js'
|
|
2
3
|
|
|
3
|
-
const parse = { ...
|
|
4
|
+
const parse = { ..._criteria, ..._options }
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {toa.core.storages.Query} query
|
|
7
8
|
* @returns {{criteria: Object, options: Object}}
|
|
8
9
|
*/
|
|
9
|
-
const translate = (query) => {
|
|
10
|
+
export const translate = (query) => {
|
|
10
11
|
const result = {
|
|
11
12
|
criteria: query?.criteria === undefined ? {} : parse.criteria(query.criteria),
|
|
12
13
|
options: query?.options === undefined ? {} : parse.options(query.options),
|
|
@@ -27,5 +28,3 @@ const translate = (query) => {
|
|
|
27
28
|
|
|
28
29
|
return result
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
exports.translate = translate
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ast = {
|
|
1
|
+
export const ast = {
|
|
4
2
|
left: {
|
|
5
3
|
type: 'SELECTOR',
|
|
6
4
|
selector: 'id'
|
|
@@ -13,9 +11,6 @@ const ast = {
|
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
const criteria = {
|
|
14
|
+
export const criteria = {
|
|
17
15
|
_id: { $eq: 100500 }
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
exports.ast = ast
|
|
21
|
-
exports.criteria = criteria
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import * as fixtures from './criteria.fixtures.js'
|
|
5
|
+
import { criteria } from '../../src/translate/criteria.js'
|
|
5
6
|
|
|
6
7
|
it('should translate', () => {
|
|
7
8
|
const result = criteria(fixtures.ast)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
assert.deepStrictEqual(result, fixtures.criteria)
|
|
10
11
|
})
|
package/test/record.test.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
to,
|
|
5
|
-
from
|
|
6
|
-
} = require('../src/record')
|
|
4
|
+
import { to, from } from '../src/record.js'
|
|
7
5
|
|
|
8
6
|
describe('to', () => {
|
|
9
7
|
it('should rename id to _id', () => {
|
|
@@ -14,7 +12,7 @@ describe('to', () => {
|
|
|
14
12
|
}
|
|
15
13
|
const record = to(entity)
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
assert.partialDeepStrictEqual(record, { _id: '1' })
|
|
18
16
|
})
|
|
19
17
|
|
|
20
18
|
it('should not modify argument', () => {
|
|
@@ -26,7 +24,7 @@ describe('to', () => {
|
|
|
26
24
|
|
|
27
25
|
to(entity)
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
assert.deepStrictEqual(entity, {
|
|
30
28
|
id: '1',
|
|
31
29
|
_version: 0
|
|
32
30
|
})
|
|
@@ -42,7 +40,7 @@ describe('from', () => {
|
|
|
42
40
|
}
|
|
43
41
|
const entity = from(record)
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
assert.deepStrictEqual(entity, {
|
|
46
44
|
id: '1',
|
|
47
45
|
_version: 0
|
|
48
46
|
})
|
package/test/storage.test.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
import { Storage } from '../src/storage.js'
|
|
4
6
|
|
|
5
7
|
let collection
|
|
6
8
|
let storage
|
|
@@ -8,8 +10,8 @@ let storage
|
|
|
8
10
|
beforeEach(async () => {
|
|
9
11
|
collection = {
|
|
10
12
|
collectionName: 'test',
|
|
11
|
-
findOne:
|
|
12
|
-
find:
|
|
13
|
+
findOne: mock.fn(async () => null),
|
|
14
|
+
find: mock.fn(() => ({ stream: () => null }))
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
const client = {
|
|
@@ -26,14 +28,13 @@ describe('get', () => {
|
|
|
26
28
|
it('should filter deleted', async () => {
|
|
27
29
|
await storage.get({})
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
assert.ok(collection.findOne.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], { _deleted: null }) && isDeepStrictEqual(call.arguments[1], {})))
|
|
30
32
|
})
|
|
31
33
|
|
|
32
34
|
it('should filter deleted with sort', async () => {
|
|
33
35
|
await storage.get({ options: { sort: [['_created', 'desc']] } })
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
.toHaveBeenCalledWith({ _deleted: null }, { sort: [['_created', -1]] })
|
|
37
|
+
assert.ok(collection.findOne.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], { _deleted: null }) && isDeepStrictEqual(call.arguments[1], { sort: [['_created', -1]] })))
|
|
37
38
|
})
|
|
38
39
|
|
|
39
40
|
it('should not filter deleted if queried by id', async () => {
|
|
@@ -41,13 +42,13 @@ describe('get', () => {
|
|
|
41
42
|
|
|
42
43
|
await storage.get({ id })
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
assert.ok(collection.findOne.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], { _id: id }) && isDeepStrictEqual(call.arguments[1], {})))
|
|
45
46
|
})
|
|
46
47
|
|
|
47
48
|
it('should not filter deleted if requested', async () => {
|
|
48
49
|
await storage.get({ options: { deleted: true } })
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
assert.ok(collection.findOne.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], {}) && isDeepStrictEqual(call.arguments[1], {})))
|
|
51
52
|
})
|
|
52
53
|
})
|
|
53
54
|
|
|
@@ -55,19 +56,18 @@ describe('stream', () => {
|
|
|
55
56
|
it('should filter deleted', async () => {
|
|
56
57
|
await storage.stream()
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
assert.ok(collection.find.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], { _deleted: null }) && isDeepStrictEqual(call.arguments[1], {})))
|
|
59
60
|
})
|
|
60
61
|
|
|
61
62
|
it('should filter deleted with sort', async () => {
|
|
62
63
|
await storage.stream({ options: { sort: [['_created', 'desc']] } })
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
.toHaveBeenCalledWith({ _deleted: null }, { sort: [['_created', -1]] })
|
|
65
|
+
assert.ok(collection.find.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], { _deleted: null }) && isDeepStrictEqual(call.arguments[1], { sort: [['_created', -1]] })))
|
|
66
66
|
})
|
|
67
67
|
|
|
68
68
|
it('should not filter deleted if requested', async () => {
|
|
69
69
|
await storage.stream({ options: { deleted: true } })
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
assert.ok(collection.find.mock.calls.some((call) => call.arguments.length === 2 && isDeepStrictEqual(call.arguments[0], {}) && isDeepStrictEqual(call.arguments[1], {})))
|
|
72
72
|
})
|
|
73
73
|
})
|
package/test/translate.test.js
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import { translate } from '../src/translate.js'
|
|
4
5
|
|
|
5
6
|
describe('options', () => {
|
|
6
7
|
it('should translate omit', () => {
|
|
7
8
|
const options = { omit: 10 }
|
|
8
9
|
const query = translate({ options })
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
assert.deepStrictEqual(query.options.skip, options.omit)
|
|
11
12
|
})
|
|
12
13
|
|
|
13
14
|
it('should translate limit', () => {
|
|
14
15
|
const options = { limit: 10 }
|
|
15
16
|
const query = translate({ options })
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
assert.deepStrictEqual(query.options.limit, options.limit)
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
it('should translate sort', () => {
|
|
21
22
|
const options = { sort: [['a', 'asc'], ['b', 'desc'], ['id', 'asc']] }
|
|
22
23
|
const query = translate({ options })
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
assert.deepStrictEqual(query.options.sort, [['a', 1], ['b', -1], ['_id', 1]])
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
it('should translate projection', () => {
|
|
28
29
|
const options = { projection: ['a', 'b', 'c', 'id'] }
|
|
29
30
|
const query = translate({ options })
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
assert.deepStrictEqual(query.options.projection, { a: 1, b: 1, c: 1, _id: 1 })
|
|
32
33
|
})
|
|
33
34
|
})
|