@teamplay/backend 0.3.18 → 0.3.20
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/db/mongo.js +89 -19
- package/index.js +1 -1
- package/package.json +7 -7
- package/redis/getRedis.js +49 -0
- package/redis/index.js +12 -50
package/db/mongo.js
CHANGED
|
@@ -2,27 +2,32 @@ import fs from 'fs'
|
|
|
2
2
|
import { MongoClient } from 'mongodb'
|
|
3
3
|
import ShareDbMongo from 'sharedb-mongo'
|
|
4
4
|
|
|
5
|
-
export const { db, mongo, mongoClient, createMongoIndex } = getMongoDb({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
export const { db, mongo, mongoClient, createMongoIndex } = getMongoDb(process.env.MONGO_URL, {
|
|
6
|
+
// ssl key, cert and ca can be provided as paths or base64 or directly as strings
|
|
7
|
+
|
|
8
|
+
// ssl as string
|
|
9
|
+
key: process.env.MONGO_SSL_KEY,
|
|
10
|
+
cert: process.env.MONGO_SSL_CERT,
|
|
11
|
+
ca: process.env.MONGO_SSL_CA,
|
|
12
|
+
|
|
13
|
+
// ssl as path to the file
|
|
14
|
+
keyPath: process.env.MONGO_SSL_KEY_PATH,
|
|
15
|
+
certPath: process.env.MONGO_SSL_CERT_PATH,
|
|
16
|
+
caPath: process.env.MONGO_SSL_CA_PATH,
|
|
17
|
+
|
|
18
|
+
// ssl as base64
|
|
19
|
+
keyBase64: process.env.MONGO_SSL_KEY_BASE64,
|
|
20
|
+
certBase64: process.env.MONGO_SSL_CERT_BASE64,
|
|
21
|
+
caBase64: process.env.MONGO_SSL_CA_BASE64,
|
|
22
|
+
|
|
23
|
+
...(process.env.MONGO_OPTIONS ? JSON.parse(process.env.MONGO_OPTIONS) : undefined)
|
|
11
24
|
})
|
|
12
25
|
|
|
13
|
-
function getMongoDb (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
options.sslKey = fs.readFileSync(key)
|
|
19
|
-
options.sslCert = fs.readFileSync(cert)
|
|
20
|
-
options.sslCA = fs.readFileSync(ca)
|
|
21
|
-
} else if (sslKeyPath) {
|
|
22
|
-
options.sslKey = fs.readFileSync(sslKeyPath)
|
|
23
|
-
options.sslCert = fs.readFileSync(sslCertPath)
|
|
24
|
-
options.sslCA = fs.readFileSync(sslCaPath)
|
|
25
|
-
}
|
|
26
|
+
function getMongoDb (url, options = {}) {
|
|
27
|
+
options = { ...options }
|
|
28
|
+
options = processSslOptions(options)
|
|
29
|
+
|
|
30
|
+
options.useUnifiedTopology ??= true
|
|
26
31
|
|
|
27
32
|
const mongoClient = new MongoClient(url, options)
|
|
28
33
|
const mongo = mongoClient.db()
|
|
@@ -38,3 +43,68 @@ function getMongoDb ({ url, optsString, sslKeyPath, sslCertPath, sslCaPath }) {
|
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
45
|
}
|
|
46
|
+
|
|
47
|
+
function processSslOptions (options = {}) {
|
|
48
|
+
options = { ...options }
|
|
49
|
+
let initialized = false
|
|
50
|
+
if (options.key || options.cert || options.ca) {
|
|
51
|
+
if (!(options.key && options.cert && options.ca)) {
|
|
52
|
+
throw Error('[teamplay/mongo] SSL: All 3 strings must be provided: key, cert, ca')
|
|
53
|
+
}
|
|
54
|
+
if (!(typeof options.key === 'string' && typeof options.cert === 'string' && typeof options.ca === 'string')) {
|
|
55
|
+
throw Error('[teamplay/mongo] SSL: All 3 strings must be provided as strings')
|
|
56
|
+
}
|
|
57
|
+
options = {
|
|
58
|
+
...options,
|
|
59
|
+
key: Buffer.from(options.key),
|
|
60
|
+
cert: Buffer.from(options.cert),
|
|
61
|
+
ca: Buffer.from(options.ca)
|
|
62
|
+
}
|
|
63
|
+
initialized = true
|
|
64
|
+
}
|
|
65
|
+
if (options.keyPath || options.certPath || options.caPath) {
|
|
66
|
+
if (initialized) {
|
|
67
|
+
throw Error('[teamplay/mongo] SSL: Cannot mix paths and strings or base64')
|
|
68
|
+
}
|
|
69
|
+
if (!(options.keyPath && options.certPath && options.caPath)) {
|
|
70
|
+
throw Error('[teamplay/mongo] SSL: All 3 paths to files must be provided: keyPath, certPath, caPath')
|
|
71
|
+
}
|
|
72
|
+
options = {
|
|
73
|
+
...options,
|
|
74
|
+
key: fs.readFileSync(options.keyPath),
|
|
75
|
+
cert: fs.readFileSync(options.certPath),
|
|
76
|
+
ca: fs.readFileSync(options.caPath)
|
|
77
|
+
}
|
|
78
|
+
initialized = true
|
|
79
|
+
}
|
|
80
|
+
if (options.keyBase64 || options.certBase64 || options.caBase64) {
|
|
81
|
+
if (initialized) {
|
|
82
|
+
throw Error('[teamplay/mongo] SSL: Cannot mix base64 and strings or paths')
|
|
83
|
+
}
|
|
84
|
+
if (!(options.keyBase64 && options.certBase64 && options.caBase64)) {
|
|
85
|
+
throw Error('[teamplay/mongo] SSL: All 3 base64 strings must be provided: keyBase64, certBase64, caBase64')
|
|
86
|
+
}
|
|
87
|
+
options = {
|
|
88
|
+
...options,
|
|
89
|
+
key: Buffer.from(options.keyBase64, 'base64'),
|
|
90
|
+
cert: Buffer.from(options.certBase64, 'base64'),
|
|
91
|
+
ca: Buffer.from(options.caBase64, 'base64')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// enable tls mode if certificates are provided (unless explicitly disabled)
|
|
95
|
+
if (options.key && options.cert && options.ca) {
|
|
96
|
+
options.tls ??= true
|
|
97
|
+
}
|
|
98
|
+
// cleanup options object from the processed keys
|
|
99
|
+
delete options.keyPath
|
|
100
|
+
delete options.certPath
|
|
101
|
+
delete options.caPath
|
|
102
|
+
delete options.keyBase64
|
|
103
|
+
delete options.certBase64
|
|
104
|
+
delete options.caBase64
|
|
105
|
+
// delete the undefined values if they were not provided
|
|
106
|
+
if (!options.key) delete options.key
|
|
107
|
+
if (!options.cert) delete options.cert
|
|
108
|
+
if (!options.ca) delete options.ca
|
|
109
|
+
return options
|
|
110
|
+
}
|
package/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import initValidateSchema from './features/validateSchema.js'
|
|
|
7
7
|
import initServerAggregate from './features/serverAggregate.js'
|
|
8
8
|
import initAccessControl from './features/accessControl.js'
|
|
9
9
|
|
|
10
|
-
export { redis, redlock, Redlock } from './redis/index.js'
|
|
10
|
+
export { redis, redlock, Redlock, getRedis, Redis } from './redis/index.js'
|
|
11
11
|
export { db, mongo, mongoClient, createMongoIndex, sqlite } from './db/index.js'
|
|
12
12
|
|
|
13
13
|
const usersConnectionCounter = {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamplay/backend",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.20",
|
|
4
4
|
"description": "Create new ShareDB backend instance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@startupjs/sharedb-mingo-memory": "^4.0.0-1",
|
|
16
|
-
"@teamplay/schema": "^0.3.
|
|
17
|
-
"@teamplay/server-aggregate": "^0.3.
|
|
18
|
-
"@teamplay/sharedb-access": "^0.3.
|
|
19
|
-
"@teamplay/sharedb-schema": "^0.3.
|
|
20
|
-
"@teamplay/utils": "^0.3.
|
|
16
|
+
"@teamplay/schema": "^0.3.20",
|
|
17
|
+
"@teamplay/server-aggregate": "^0.3.20",
|
|
18
|
+
"@teamplay/sharedb-access": "^0.3.20",
|
|
19
|
+
"@teamplay/sharedb-schema": "^0.3.20",
|
|
20
|
+
"@teamplay/utils": "^0.3.20",
|
|
21
21
|
"@types/ioredis-mock": "^8.2.5",
|
|
22
22
|
"ioredis": "^5.3.2",
|
|
23
23
|
"ioredis-mock": "^8.9.0",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"sharedb-redis-pubsub": "^2.0.1",
|
|
30
30
|
"sqlite3": "^5.1.6"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "689f247ff9f21f711737b6625d947c10b9562e3a"
|
|
33
33
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { readFileSync } from 'fs'
|
|
2
|
+
import Redis from 'ioredis'
|
|
3
|
+
import RedisMock from 'ioredis-mock'
|
|
4
|
+
|
|
5
|
+
export { Redis, RedisMock }
|
|
6
|
+
|
|
7
|
+
export function getRedis ({ enableRedis = true, redisOpts, redisUrl, keyPrefix }) {
|
|
8
|
+
if (enableRedis) {
|
|
9
|
+
if (typeof redisOpts === 'string') {
|
|
10
|
+
redisOpts = JSON.parse(redisOpts)
|
|
11
|
+
let tls = {}
|
|
12
|
+
|
|
13
|
+
if (redisOpts.key) {
|
|
14
|
+
tls = {
|
|
15
|
+
key: readFileSync(redisOpts.key),
|
|
16
|
+
cert: readFileSync(redisOpts.cert),
|
|
17
|
+
ca: readFileSync(redisOpts.ca)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const options = {
|
|
22
|
+
sentinels: redisOpts.sentinels,
|
|
23
|
+
sslPort: redisOpts.ssl_port || '6380',
|
|
24
|
+
tls,
|
|
25
|
+
name: 'mymaster',
|
|
26
|
+
db: redisOpts.db || 0,
|
|
27
|
+
password: redisOpts.password
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_maybeAddKeyPrefixToOptions(options, keyPrefix)
|
|
31
|
+
|
|
32
|
+
return new Redis(options)
|
|
33
|
+
} else if (redisUrl) {
|
|
34
|
+
const options = {}
|
|
35
|
+
_maybeAddKeyPrefixToOptions(options, keyPrefix)
|
|
36
|
+
|
|
37
|
+
return new Redis(redisUrl, options)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const options = {}
|
|
42
|
+
_maybeAddKeyPrefixToOptions(options, keyPrefix)
|
|
43
|
+
|
|
44
|
+
return new RedisMock(options)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function _maybeAddKeyPrefixToOptions (options, keyPrefix) {
|
|
48
|
+
if (keyPrefix) options.keyPrefix = keyPrefix
|
|
49
|
+
}
|
package/redis/index.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import { readFileSync } from 'fs'
|
|
2
|
-
import Redis from 'ioredis'
|
|
3
|
-
import RedisMock from 'ioredis-mock'
|
|
4
1
|
import Redlock from 'redlock'
|
|
5
2
|
import redisPubSub from 'sharedb-redis-pubsub'
|
|
3
|
+
import { getRedis, Redis, RedisMock } from './getRedis.js'
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
disableRedis: process.env.NO_REDIS,
|
|
5
|
+
const enableRedis = !process.env.NO_REDIS
|
|
6
|
+
|
|
7
|
+
const getRedisOptions = {
|
|
8
|
+
enableRedis,
|
|
12
9
|
redisOpts: process.env.REDIS_OPTS,
|
|
13
10
|
redisUrl: process.env.REDIS_URL,
|
|
14
11
|
keyPrefix: generatePrefix({
|
|
15
12
|
mongoUrl: process.env.MONGO_URL,
|
|
16
13
|
baseUrl: process.env.BASE_URL
|
|
17
14
|
})
|
|
18
|
-
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const RedisClient = enableRedis ? Redis : RedisMock
|
|
18
|
+
export { RedisClient as Redis }
|
|
19
|
+
export { getRedis }
|
|
20
|
+
export const redis = getRedis(getRedisOptions)
|
|
21
|
+
export const redisObserver = getRedis(getRedisOptions)
|
|
19
22
|
|
|
20
23
|
export const pubsub = redisPubSub({
|
|
21
24
|
client: redis,
|
|
@@ -26,47 +29,6 @@ export const redlock = getRedlock(redis)
|
|
|
26
29
|
|
|
27
30
|
export { Redlock }
|
|
28
31
|
|
|
29
|
-
function getUniversalRedis ({ disableRedis, redisOpts, redisUrl, keyPrefix }) {
|
|
30
|
-
if (!disableRedis) {
|
|
31
|
-
if (typeof redisOpts === 'string') {
|
|
32
|
-
redisOpts = JSON.parse(redisOpts)
|
|
33
|
-
let tls = {}
|
|
34
|
-
|
|
35
|
-
if (redisOpts.key) {
|
|
36
|
-
tls = {
|
|
37
|
-
key: readFileSync(redisOpts.key),
|
|
38
|
-
cert: readFileSync(redisOpts.cert),
|
|
39
|
-
ca: readFileSync(redisOpts.ca)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const options = {
|
|
44
|
-
sentinels: redisOpts.sentinels,
|
|
45
|
-
sslPort: redisOpts.ssl_port || '6380',
|
|
46
|
-
tls,
|
|
47
|
-
name: 'mymaster',
|
|
48
|
-
db: redisOpts.db || 0,
|
|
49
|
-
password: redisOpts.password,
|
|
50
|
-
keyPrefix
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
redis: new Redis(options),
|
|
55
|
-
redisObserver: new Redis(options)
|
|
56
|
-
}
|
|
57
|
-
} else if (redisUrl) {
|
|
58
|
-
return {
|
|
59
|
-
redis: new Redis(redisUrl, { keyPrefix }),
|
|
60
|
-
redisObserver: new Redis(redisUrl, { keyPrefix })
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
redis: new RedisMock({ keyPrefix }),
|
|
66
|
-
redisObserver: new RedisMock({ keyPrefix })
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
32
|
function getRedlock (redis) {
|
|
71
33
|
return new Redlock([redis], {
|
|
72
34
|
driftFactor: 0.01,
|