@primate/mongodb 0.1.3 → 0.3.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/lib/private/ColumnTypes.d.ts +21 -0
- package/lib/private/ColumnTypes.js +2 -0
- package/lib/private/Database.d.ts +45 -0
- package/lib/private/Database.js +147 -0
- package/lib/private/typemap.d.ts +5 -0
- package/lib/private/typemap.js +86 -0
- package/lib/public/index.d.ts +4 -0
- package/lib/public/index.js +3 -0
- package/package.json +25 -14
- package/src/default.js +0 -10
- package/src/private/Facade.js +0 -89
- package/src/private/connect.js +0 -8
- package/src/private/defaults.js +0 -4
- package/src/private/serve.js +0 -62
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type TypedArray from "@rcompat/type/TypedArray";
|
|
2
|
+
import type { Binary, Decimal128, ObjectId } from "mongodb";
|
|
3
|
+
type Param = bigint | Binary | boolean | Date | Decimal128 | number | ObjectId | string | TypedArray;
|
|
4
|
+
type Validate<T extends {
|
|
5
|
+
[K in keyof T]: Param;
|
|
6
|
+
}> = T;
|
|
7
|
+
type ColumnTypes = Validate<{
|
|
8
|
+
BINARY: Binary;
|
|
9
|
+
BOOLEAN: boolean;
|
|
10
|
+
DATE: Date;
|
|
11
|
+
DECIMAL: Decimal128;
|
|
12
|
+
DOUBLE: number;
|
|
13
|
+
INT: number;
|
|
14
|
+
LONG: bigint;
|
|
15
|
+
PRIMARY: ObjectId;
|
|
16
|
+
STRING: string;
|
|
17
|
+
TIME: string;
|
|
18
|
+
UUID: string;
|
|
19
|
+
}>;
|
|
20
|
+
export type { ColumnTypes as default };
|
|
21
|
+
//# sourceMappingURL=ColumnTypes.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import Database from "@primate/core/Database";
|
|
2
|
+
import type As from "@primate/core/database/As";
|
|
3
|
+
import type DataDict from "@primate/core/database/DataDict";
|
|
4
|
+
import type TypeMap from "@primate/core/database/TypeMap";
|
|
5
|
+
import type Dict from "@rcompat/type/Dict";
|
|
6
|
+
declare const schema: import("pema").ObjectType<{
|
|
7
|
+
database: import("pema/string").StringType;
|
|
8
|
+
host: import("pema").DefaultType<import("pema/string").StringType, "localhost">;
|
|
9
|
+
password: import("pema").OptionalType<import("pema/string").StringType>;
|
|
10
|
+
port: import("pema").DefaultType<import("pema/uint").UintType<"u32">, 27017>;
|
|
11
|
+
username: import("pema").OptionalType<import("pema/string").StringType>;
|
|
12
|
+
}>;
|
|
13
|
+
export default class MongoDBDatabase extends Database {
|
|
14
|
+
#private;
|
|
15
|
+
static config: typeof schema.input;
|
|
16
|
+
constructor(config?: typeof schema.input);
|
|
17
|
+
get typemap(): TypeMap<Dict>;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
get schema(): {
|
|
20
|
+
create: () => undefined;
|
|
21
|
+
delete: (name: string) => Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
create<O extends Dict>(as: As, args: {
|
|
24
|
+
record: DataDict;
|
|
25
|
+
}): Promise<O>;
|
|
26
|
+
read(as: As, args: {
|
|
27
|
+
count: true;
|
|
28
|
+
criteria: DataDict;
|
|
29
|
+
}): Promise<number>;
|
|
30
|
+
read(as: As, args: {
|
|
31
|
+
criteria: DataDict;
|
|
32
|
+
fields?: string[];
|
|
33
|
+
limit?: number;
|
|
34
|
+
sort?: Dict<"asc" | "desc">;
|
|
35
|
+
}): Promise<Dict[]>;
|
|
36
|
+
update(as: As, args: {
|
|
37
|
+
changes: DataDict;
|
|
38
|
+
criteria: DataDict;
|
|
39
|
+
}): Promise<number>;
|
|
40
|
+
delete(as: As, args: {
|
|
41
|
+
criteria: DataDict;
|
|
42
|
+
}): Promise<number>;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=Database.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import typemap from "#typemap";
|
|
2
|
+
import Database from "@primate/core/Database";
|
|
3
|
+
import assert from "@rcompat/assert";
|
|
4
|
+
import maybe from "@rcompat/assert/maybe";
|
|
5
|
+
import empty from "@rcompat/record/empty";
|
|
6
|
+
import entries from "@rcompat/record/entries";
|
|
7
|
+
import toQueryString from "@rcompat/record/toQueryString";
|
|
8
|
+
import { MongoClient } from "mongodb";
|
|
9
|
+
import pema from "pema";
|
|
10
|
+
import string from "pema/string";
|
|
11
|
+
import uint from "pema/uint";
|
|
12
|
+
const schema = pema({
|
|
13
|
+
database: string,
|
|
14
|
+
host: string.default("localhost"),
|
|
15
|
+
password: string.optional(),
|
|
16
|
+
port: uint.port().default(27017),
|
|
17
|
+
username: string.optional(),
|
|
18
|
+
});
|
|
19
|
+
function make_limit(limit) {
|
|
20
|
+
maybe(limit).usize();
|
|
21
|
+
if (limit === undefined) {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
return limit;
|
|
25
|
+
}
|
|
26
|
+
;
|
|
27
|
+
const null_to_set_unset = (changes) => {
|
|
28
|
+
const entry_changes = entries(changes);
|
|
29
|
+
const $set = entry_changes.filter(([, value]) => value !== null).get();
|
|
30
|
+
const $unset = entry_changes.filter(([, value]) => value === null).get();
|
|
31
|
+
return { $set, $unset };
|
|
32
|
+
};
|
|
33
|
+
const url_params = { directConnection: "true", replicaSet: "rs0" };
|
|
34
|
+
export default class MongoDBDatabase extends Database {
|
|
35
|
+
static config;
|
|
36
|
+
#factory;
|
|
37
|
+
#name;
|
|
38
|
+
#client;
|
|
39
|
+
constructor(config) {
|
|
40
|
+
super();
|
|
41
|
+
const { database, host, port } = schema.parse(config);
|
|
42
|
+
const url = `mongodb://${host}:${port}?${toQueryString(url_params)}`;
|
|
43
|
+
const client = new MongoClient(url);
|
|
44
|
+
this.#name = database;
|
|
45
|
+
this.#factory = async () => {
|
|
46
|
+
await client.connect();
|
|
47
|
+
return client;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async #get(collection) {
|
|
51
|
+
if (this.#client === undefined) {
|
|
52
|
+
this.#client = await this.#factory();
|
|
53
|
+
}
|
|
54
|
+
return this.#client.db(this.#name).collection(collection);
|
|
55
|
+
}
|
|
56
|
+
get typemap() {
|
|
57
|
+
return typemap;
|
|
58
|
+
}
|
|
59
|
+
async close() {
|
|
60
|
+
await this.#client.close();
|
|
61
|
+
}
|
|
62
|
+
async #drop(name) {
|
|
63
|
+
await (await this.#get(name)).drop();
|
|
64
|
+
}
|
|
65
|
+
get schema() {
|
|
66
|
+
return {
|
|
67
|
+
// noop
|
|
68
|
+
create: () => undefined,
|
|
69
|
+
delete: this.#drop.bind(this),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async #bind(object, types) {
|
|
73
|
+
const prepared = Object.fromEntries(Object.entries(object)
|
|
74
|
+
.map(([key, value]) => {
|
|
75
|
+
if (value === null)
|
|
76
|
+
return [key, null];
|
|
77
|
+
if (typeof value === "object" && "$like" in value) {
|
|
78
|
+
const pattern = String(value.$like);
|
|
79
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
80
|
+
const $regex = `^${escaped.replace(/%/g, ".*").replace(/_/g, ".")}$`;
|
|
81
|
+
return [key, { $regex }];
|
|
82
|
+
}
|
|
83
|
+
return [key, value];
|
|
84
|
+
}));
|
|
85
|
+
const { id, ...rest } = await this.bind(types, prepared);
|
|
86
|
+
return id === undefined
|
|
87
|
+
? rest
|
|
88
|
+
: { _id: id, ...rest };
|
|
89
|
+
}
|
|
90
|
+
#unbind(object, types) {
|
|
91
|
+
const { _id: id, ...rest } = object;
|
|
92
|
+
return this.unbind(types, id === undefined ? rest : { id, ...rest });
|
|
93
|
+
}
|
|
94
|
+
async create(as, args) {
|
|
95
|
+
const binds = await this.#bind(args.record, as.types);
|
|
96
|
+
const { insertedId } = await (await this.#get(as.name)).insertOne(binds);
|
|
97
|
+
return this.#unbind({ ...args.record, _id: insertedId }, as.types);
|
|
98
|
+
}
|
|
99
|
+
async read(as, args) {
|
|
100
|
+
this.toSelect(as.types, args.fields);
|
|
101
|
+
this.toSort(as.types, args.sort);
|
|
102
|
+
const binds = await this.#bind(args.criteria, as.types);
|
|
103
|
+
if (args.count === true) {
|
|
104
|
+
return (await this.#get(as.name)).countDocuments(binds);
|
|
105
|
+
}
|
|
106
|
+
const fields = args.fields ?? [];
|
|
107
|
+
const mapped = fields.map(f => f === "id" ? "_id" : f);
|
|
108
|
+
const sort = args.sort === undefined || empty(args.sort)
|
|
109
|
+
? {}
|
|
110
|
+
: { sort: args.sort };
|
|
111
|
+
const select = mapped.length === 0
|
|
112
|
+
? {}
|
|
113
|
+
: {
|
|
114
|
+
projection: (() => {
|
|
115
|
+
const out = {};
|
|
116
|
+
if (!mapped.includes("_id")) {
|
|
117
|
+
out._id = 0;
|
|
118
|
+
}
|
|
119
|
+
for (const field of mapped) {
|
|
120
|
+
out[field] = 1;
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
})(),
|
|
124
|
+
};
|
|
125
|
+
const options = { ...select, ...sort, useBigInt64: true };
|
|
126
|
+
const records = await (await this.#get(as.name))
|
|
127
|
+
.find(binds, options)
|
|
128
|
+
.limit(make_limit(args.limit))
|
|
129
|
+
.toArray();
|
|
130
|
+
return records.map(record => this.#unbind(record, as.types));
|
|
131
|
+
}
|
|
132
|
+
async update(as, args) {
|
|
133
|
+
assert(Object.keys(args.criteria).length > 0, "update: no criteria");
|
|
134
|
+
const criteria_binds = await this.#bind(args.criteria, as.types);
|
|
135
|
+
const changes_binds = await this.#bind(args.changes, as.types);
|
|
136
|
+
const collection = await this.#get(as.name);
|
|
137
|
+
return (await collection
|
|
138
|
+
.updateMany(criteria_binds, null_to_set_unset(changes_binds)))
|
|
139
|
+
.modifiedCount;
|
|
140
|
+
}
|
|
141
|
+
async delete(as, args) {
|
|
142
|
+
assert(Object.keys(args.criteria).length > 0, "delete: no criteria");
|
|
143
|
+
const binds = await this.#bind(args.criteria, as.types);
|
|
144
|
+
return (await ((await this.#get(as.name)).deleteMany(binds))).deletedCount;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=Database.js.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Binary, Decimal128, ObjectId } from "mongodb";
|
|
2
|
+
function identity(column) {
|
|
3
|
+
return {
|
|
4
|
+
bind: value => value,
|
|
5
|
+
column,
|
|
6
|
+
unbind: value => value,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function decimal() {
|
|
10
|
+
return {
|
|
11
|
+
bind(value) {
|
|
12
|
+
return new Decimal128(value.toString());
|
|
13
|
+
},
|
|
14
|
+
column: "DECIMAL",
|
|
15
|
+
unbind(value) {
|
|
16
|
+
return BigInt(value.toString());
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const typemap = {
|
|
21
|
+
blob: {
|
|
22
|
+
async bind(value) {
|
|
23
|
+
const arrayBuffer = await value.arrayBuffer();
|
|
24
|
+
return new Binary(new Uint8Array(arrayBuffer));
|
|
25
|
+
},
|
|
26
|
+
column: "BINARY",
|
|
27
|
+
unbind(value) {
|
|
28
|
+
return new Blob([value.toBits()], { type: "application/octet-stream" });
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
boolean: identity("BOOLEAN"),
|
|
32
|
+
datetime: identity("DATE"),
|
|
33
|
+
f32: identity("DOUBLE"),
|
|
34
|
+
f64: identity("DOUBLE"),
|
|
35
|
+
i128: {
|
|
36
|
+
bind(value) {
|
|
37
|
+
return String(value);
|
|
38
|
+
},
|
|
39
|
+
column: "STRING",
|
|
40
|
+
unbind(value) {
|
|
41
|
+
return BigInt(value);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
i16: identity("INT"),
|
|
45
|
+
i32: identity("INT"),
|
|
46
|
+
i64: identity("LONG"),
|
|
47
|
+
i8: identity("INT"),
|
|
48
|
+
primary: {
|
|
49
|
+
bind(value) {
|
|
50
|
+
if (typeof value === "string") {
|
|
51
|
+
return new ObjectId(value);
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`\`${value}\` is not a valid primary key value`);
|
|
54
|
+
},
|
|
55
|
+
column: "PRIMARY",
|
|
56
|
+
unbind(value) {
|
|
57
|
+
return String(value);
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
string: identity("STRING"),
|
|
61
|
+
time: identity("TIME"),
|
|
62
|
+
u128: {
|
|
63
|
+
bind(value) {
|
|
64
|
+
return String(value);
|
|
65
|
+
},
|
|
66
|
+
column: "STRING",
|
|
67
|
+
unbind(value) {
|
|
68
|
+
return BigInt(value);
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
u16: identity("INT"),
|
|
72
|
+
u32: identity("INT"),
|
|
73
|
+
u64: decimal(),
|
|
74
|
+
u8: identity("INT"),
|
|
75
|
+
url: {
|
|
76
|
+
bind(value) {
|
|
77
|
+
return value.toString();
|
|
78
|
+
},
|
|
79
|
+
column: "STRING",
|
|
80
|
+
unbind(value) {
|
|
81
|
+
return new URL(value);
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
export default typemap;
|
|
86
|
+
//# sourceMappingURL=typemap.js.map
|
package/package.json
CHANGED
|
@@ -1,34 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primate/mongodb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Primate MongoDB database",
|
|
5
|
-
"homepage": "https://
|
|
6
|
-
"bugs": "https://github.com/
|
|
5
|
+
"homepage": "https://primate.run/docs/database/mongodb",
|
|
6
|
+
"bugs": "https://github.com/primate-run/primate/issues",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"files": [
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"/lib/**/*.js",
|
|
10
|
+
"/lib/**/*.d.ts",
|
|
11
|
+
"!/**/*.spec.*"
|
|
11
12
|
],
|
|
12
13
|
"repository": {
|
|
13
14
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/
|
|
15
|
+
"url": "https://github.com/primate-run/primate",
|
|
15
16
|
"directory": "packages/mongodb"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@rcompat/
|
|
19
|
-
"@rcompat/
|
|
20
|
-
"mongodb": "^6.
|
|
21
|
-
"
|
|
22
|
-
"@primate/
|
|
19
|
+
"@rcompat/assert": "^0.3.1",
|
|
20
|
+
"@rcompat/record": "^0.9.1",
|
|
21
|
+
"mongodb": "^6.17.0",
|
|
22
|
+
"pema": "",
|
|
23
|
+
"@primate/core": "^0.3.0"
|
|
23
24
|
},
|
|
24
25
|
"type": "module",
|
|
25
26
|
"imports": {
|
|
26
27
|
"#*": {
|
|
27
|
-
"
|
|
28
|
-
"default": "./
|
|
28
|
+
"apekit": "./src/private/*.ts",
|
|
29
|
+
"default": "./lib/private/*.js"
|
|
29
30
|
}
|
|
30
31
|
},
|
|
31
32
|
"exports": {
|
|
32
|
-
".":
|
|
33
|
+
".": {
|
|
34
|
+
"apekit": "./src/public/index.ts",
|
|
35
|
+
"default": "./lib/public/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "npm run clean && tsc",
|
|
40
|
+
"clean": "rm -rf ./lib",
|
|
41
|
+
"lint": "eslint .",
|
|
42
|
+
"test": "npm run build && npx proby",
|
|
43
|
+
"start:db": "sudo mongod --dbpath /var/lib/mongodb"
|
|
33
44
|
}
|
|
34
45
|
}
|
package/src/default.js
DELETED
package/src/private/Facade.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import maybe from "@rcompat/invariant/maybe";
|
|
2
|
-
import empty from "@rcompat/object/empty";
|
|
3
|
-
import filter from "@rcompat/object/filter";
|
|
4
|
-
import valmap from "@rcompat/object/valmap";
|
|
5
|
-
|
|
6
|
-
const toid = ({ _id, ...rest }) => ({ id: _id, ...rest });
|
|
7
|
-
const to_id = ({ id, ...rest }) => id === undefined
|
|
8
|
-
? rest
|
|
9
|
-
: { _id: id, ...rest };
|
|
10
|
-
const cid = criteria => criteria.id === undefined ? criteria : to_id(criteria);
|
|
11
|
-
const null_to_set_unset = delta => {
|
|
12
|
-
const $set = filter(delta, ([, value]) => value !== null);
|
|
13
|
-
const $unset = filter(delta, ([, value]) => value === null);
|
|
14
|
-
return { $set, $unset };
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const make_sort = ({ sort = {} } = {}) => {
|
|
18
|
-
maybe(sort).object();
|
|
19
|
-
|
|
20
|
-
return valmap(sort, value => value === "asc" ? 1 : -1);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export default class Facade {
|
|
24
|
-
schema = {
|
|
25
|
-
create: async _ => {
|
|
26
|
-
// noop
|
|
27
|
-
},
|
|
28
|
-
delete: async name => {
|
|
29
|
-
await this.#by(name).drop();
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
constructor(connection, session) {
|
|
34
|
-
this.connection = connection;
|
|
35
|
-
this.session = session;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
#by(name) {
|
|
39
|
-
return this.connection.collection(name);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get #options() {
|
|
43
|
-
return { session: this.session };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async find(name, criteria = {}, projection = [], options = {}) {
|
|
47
|
-
const sort = make_sort(options);
|
|
48
|
-
const $options = {
|
|
49
|
-
...this.#options,
|
|
50
|
-
...projection.length === 0
|
|
51
|
-
? {}
|
|
52
|
-
: {
|
|
53
|
-
projection: {
|
|
54
|
-
// erase _id unless explicit in projection
|
|
55
|
-
_id: 0,
|
|
56
|
-
...Object.fromEntries(projection.map(field => [field, 1])),
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
...empty(sort) ? {} : { sort },
|
|
60
|
-
};
|
|
61
|
-
return (await this.#by(name).find(cid(criteria), $options).toArray())
|
|
62
|
-
.map(document => toid(document));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async count(name, criteria = {}) {
|
|
66
|
-
return this.#by(name).countDocuments(criteria, this.#options);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async get(name, primary, value) {
|
|
70
|
-
const result = await this.#by(name).findOne({ _id: value }, this.#options);
|
|
71
|
-
return result === null ? undefined : toid(result);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async insert(name, primary, document) {
|
|
75
|
-
await this.#by(name).insertOne(document, this.#options);
|
|
76
|
-
return toid(document);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async update(name, criteria = {}, delta = {}) {
|
|
80
|
-
return (await this.#by(name)
|
|
81
|
-
.updateMany(cid(criteria), null_to_set_unset(delta), this.#options))
|
|
82
|
-
.modifiedCount;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async delete(name, criteria = {}) {
|
|
86
|
-
return (await this.#by(name).deleteMany(cid(criteria), this.#options))
|
|
87
|
-
.deletedCount;
|
|
88
|
-
}
|
|
89
|
-
}
|
package/src/private/connect.js
DELETED
package/src/private/defaults.js
DELETED
package/src/private/serve.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import Facade from "#Facade";
|
|
2
|
-
import connect from "#connect";
|
|
3
|
-
import ident from "@primate/store/core/ident";
|
|
4
|
-
import wrap from "@primate/store/core/wrap";
|
|
5
|
-
import { Decimal128, ObjectId } from "mongodb";
|
|
6
|
-
|
|
7
|
-
export default ({ host, port, database } = {}) => async _ => {
|
|
8
|
-
const client = await connect({ host, port });
|
|
9
|
-
|
|
10
|
-
const types = {
|
|
11
|
-
primary: {
|
|
12
|
-
validate(value) {
|
|
13
|
-
/* TODO: check that has valid objectid form */
|
|
14
|
-
if (typeof value === "string") {
|
|
15
|
-
return value;
|
|
16
|
-
}
|
|
17
|
-
throw new Error(`\`${value}\` is not a valid primary key value`);
|
|
18
|
-
},
|
|
19
|
-
in(value) {
|
|
20
|
-
return new ObjectId(value);
|
|
21
|
-
},
|
|
22
|
-
out(value) {
|
|
23
|
-
return value.toString();
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
object: ident,
|
|
27
|
-
number: ident,
|
|
28
|
-
bigint: {
|
|
29
|
-
in(value) {
|
|
30
|
-
return new Decimal128(value.toString());
|
|
31
|
-
},
|
|
32
|
-
out(value) {
|
|
33
|
-
return BigInt(value.toString());
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
boolean: ident,
|
|
37
|
-
date: ident,
|
|
38
|
-
string: ident,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
name: "@primate/mongodb",
|
|
43
|
-
types,
|
|
44
|
-
async transact(stores) {
|
|
45
|
-
return async (others, next) => {
|
|
46
|
-
const session = client.startSession();
|
|
47
|
-
const facade = new Facade(client.db(database), session);
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
return await session.withTransaction(async () => {
|
|
51
|
-
const response = await next([...others, ...stores.map(([_, store]) =>
|
|
52
|
-
[_, wrap(store, facade, types)]),
|
|
53
|
-
]);
|
|
54
|
-
return response;
|
|
55
|
-
});
|
|
56
|
-
} finally {
|
|
57
|
-
session.endSession();
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
};
|