@budibase/backend-core 3.2.4 → 3.2.6
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/dist/index.js.map +1 -1
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +11 -4
- package/dist/plugins.js.meta.json +1 -1
- package/package.json +11 -4
- package/src/accounts/accounts.ts +0 -82
- package/src/accounts/api.ts +0 -59
- package/src/accounts/index.ts +0 -1
- package/src/auth/auth.ts +0 -210
- package/src/auth/index.ts +0 -1
- package/src/auth/tests/auth.spec.ts +0 -14
- package/src/blacklist/blacklist.ts +0 -54
- package/src/blacklist/index.ts +0 -1
- package/src/blacklist/tests/blacklist.spec.ts +0 -46
- package/src/cache/appMetadata.ts +0 -88
- package/src/cache/base/index.ts +0 -150
- package/src/cache/docWritethrough.ts +0 -105
- package/src/cache/generic.ts +0 -33
- package/src/cache/index.ts +0 -8
- package/src/cache/invite.ts +0 -86
- package/src/cache/passwordReset.ts +0 -49
- package/src/cache/tests/docWritethrough.spec.ts +0 -296
- package/src/cache/tests/user.spec.ts +0 -145
- package/src/cache/tests/writethrough.spec.ts +0 -139
- package/src/cache/user.ts +0 -154
- package/src/cache/writethrough.ts +0 -133
- package/src/configs/configs.ts +0 -263
- package/src/configs/index.ts +0 -1
- package/src/configs/tests/configs.spec.ts +0 -184
- package/src/constants/db.ts +0 -75
- package/src/constants/index.ts +0 -2
- package/src/constants/misc.ts +0 -36
- package/src/context/Context.ts +0 -14
- package/src/context/identity.ts +0 -58
- package/src/context/index.ts +0 -3
- package/src/context/mainContext.ts +0 -422
- package/src/context/tests/index.spec.ts +0 -255
- package/src/context/types.ts +0 -26
- package/src/db/Replication.ts +0 -94
- package/src/db/couch/DatabaseImpl.ts +0 -511
- package/src/db/couch/connections.ts +0 -89
- package/src/db/couch/index.ts +0 -4
- package/src/db/couch/pouchDB.ts +0 -97
- package/src/db/couch/pouchDump.ts +0 -0
- package/src/db/couch/tests/DatabaseImpl.spec.ts +0 -118
- package/src/db/couch/utils.ts +0 -55
- package/src/db/db.ts +0 -34
- package/src/db/errors.ts +0 -14
- package/src/db/index.ts +0 -12
- package/src/db/instrumentation.ts +0 -199
- package/src/db/lucene.ts +0 -721
- package/src/db/searchIndexes/index.ts +0 -1
- package/src/db/searchIndexes/searchIndexes.ts +0 -62
- package/src/db/tests/DatabaseImpl.spec.ts +0 -55
- package/src/db/tests/connections.spec.ts +0 -22
- package/src/db/tests/index.spec.ts +0 -32
- package/src/db/tests/lucene.spec.ts +0 -400
- package/src/db/tests/pouch.spec.js +0 -62
- package/src/db/tests/utils.spec.ts +0 -63
- package/src/db/utils.ts +0 -208
- package/src/db/views.ts +0 -245
- package/src/docIds/conversions.ts +0 -60
- package/src/docIds/ids.ts +0 -126
- package/src/docIds/index.ts +0 -2
- package/src/docIds/newid.ts +0 -5
- package/src/docIds/params.ts +0 -189
- package/src/docUpdates/index.ts +0 -24
- package/src/environment.ts +0 -293
- package/src/errors/errors.ts +0 -119
- package/src/errors/index.ts +0 -1
- package/src/events/analytics.ts +0 -6
- package/src/events/asyncEvents/index.ts +0 -2
- package/src/events/asyncEvents/publisher.ts +0 -12
- package/src/events/asyncEvents/queue.ts +0 -22
- package/src/events/backfill.ts +0 -183
- package/src/events/documentId.ts +0 -56
- package/src/events/events.ts +0 -47
- package/src/events/identification.ts +0 -311
- package/src/events/index.ts +0 -15
- package/src/events/processors/AnalyticsProcessor.ts +0 -64
- package/src/events/processors/AuditLogsProcessor.ts +0 -92
- package/src/events/processors/LoggingProcessor.ts +0 -36
- package/src/events/processors/Processors.ts +0 -52
- package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -38
- package/src/events/processors/index.ts +0 -19
- package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
- package/src/events/processors/posthog/index.ts +0 -3
- package/src/events/processors/posthog/rateLimiting.ts +0 -106
- package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -164
- package/src/events/processors/types.ts +0 -1
- package/src/events/publishers/account.ts +0 -41
- package/src/events/publishers/ai.ts +0 -21
- package/src/events/publishers/app.ts +0 -168
- package/src/events/publishers/auditLog.ts +0 -26
- package/src/events/publishers/auth.ts +0 -73
- package/src/events/publishers/automation.ts +0 -110
- package/src/events/publishers/backfill.ts +0 -74
- package/src/events/publishers/backup.ts +0 -42
- package/src/events/publishers/datasource.ts +0 -48
- package/src/events/publishers/email.ts +0 -17
- package/src/events/publishers/environmentVariable.ts +0 -38
- package/src/events/publishers/group.ts +0 -99
- package/src/events/publishers/index.ts +0 -25
- package/src/events/publishers/installation.ts +0 -38
- package/src/events/publishers/layout.ts +0 -26
- package/src/events/publishers/license.ts +0 -84
- package/src/events/publishers/org.ts +0 -37
- package/src/events/publishers/plugin.ts +0 -47
- package/src/events/publishers/query.ts +0 -89
- package/src/events/publishers/role.ts +0 -62
- package/src/events/publishers/rows.ts +0 -29
- package/src/events/publishers/screen.ts +0 -36
- package/src/events/publishers/serve.ts +0 -43
- package/src/events/publishers/table.ts +0 -70
- package/src/events/publishers/user.ts +0 -202
- package/src/events/publishers/view.ts +0 -107
- package/src/features/features.ts +0 -277
- package/src/features/index.ts +0 -2
- package/src/features/tests/features.spec.ts +0 -267
- package/src/features/tests/utils.ts +0 -64
- package/src/helpers.ts +0 -9
- package/src/index.ts +0 -59
- package/src/installation.ts +0 -115
- package/src/logging/alerts.ts +0 -26
- package/src/logging/correlation/correlation.ts +0 -15
- package/src/logging/correlation/index.ts +0 -1
- package/src/logging/correlation/middleware.ts +0 -18
- package/src/logging/index.ts +0 -4
- package/src/logging/pino/logger.ts +0 -239
- package/src/logging/pino/middleware.ts +0 -48
- package/src/logging/system.ts +0 -81
- package/src/logging/tests/system.spec.ts +0 -61
- package/src/middleware/adminOnly.ts +0 -9
- package/src/middleware/auditLog.ts +0 -6
- package/src/middleware/authenticated.ts +0 -247
- package/src/middleware/builderOnly.ts +0 -21
- package/src/middleware/builderOrAdmin.ts +0 -21
- package/src/middleware/contentSecurityPolicy.ts +0 -113
- package/src/middleware/csrf.ts +0 -81
- package/src/middleware/errorHandling.ts +0 -43
- package/src/middleware/index.ts +0 -24
- package/src/middleware/internalApi.ts +0 -23
- package/src/middleware/ip.ts +0 -12
- package/src/middleware/joi-validator.ts +0 -58
- package/src/middleware/matchers.ts +0 -39
- package/src/middleware/passport/datasource/google.ts +0 -102
- package/src/middleware/passport/local.ts +0 -54
- package/src/middleware/passport/sso/google.ts +0 -77
- package/src/middleware/passport/sso/oidc.ts +0 -152
- package/src/middleware/passport/sso/sso.ts +0 -138
- package/src/middleware/passport/sso/tests/google.spec.ts +0 -68
- package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -144
- package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
- package/src/middleware/passport/utils.ts +0 -38
- package/src/middleware/querystringToBody.ts +0 -28
- package/src/middleware/tenancy.ts +0 -36
- package/src/middleware/tests/builder.spec.ts +0 -181
- package/src/middleware/tests/contentSecurityPolicy.spec.ts +0 -75
- package/src/middleware/tests/matchers.spec.ts +0 -100
- package/src/migrations/definitions.ts +0 -40
- package/src/migrations/index.ts +0 -2
- package/src/migrations/migrations.ts +0 -186
- package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
- package/src/migrations/tests/migrations.spec.ts +0 -64
- package/src/objectStore/buckets/app.ts +0 -53
- package/src/objectStore/buckets/global.ts +0 -29
- package/src/objectStore/buckets/index.ts +0 -3
- package/src/objectStore/buckets/plugins.ts +0 -71
- package/src/objectStore/buckets/tests/app.spec.ts +0 -161
- package/src/objectStore/buckets/tests/global.spec.ts +0 -74
- package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
- package/src/objectStore/cloudfront.ts +0 -41
- package/src/objectStore/index.ts +0 -3
- package/src/objectStore/objectStore.ts +0 -585
- package/src/objectStore/utils.ts +0 -113
- package/src/platform/index.ts +0 -3
- package/src/platform/platformDb.ts +0 -6
- package/src/platform/tenants.ts +0 -101
- package/src/platform/tests/tenants.spec.ts +0 -26
- package/src/platform/users.ts +0 -129
- package/src/plugin/index.ts +0 -1
- package/src/plugin/tests/validation.spec.ts +0 -209
- package/src/plugin/utils.ts +0 -175
- package/src/queue/constants.ts +0 -8
- package/src/queue/inMemoryQueue.ts +0 -189
- package/src/queue/index.ts +0 -2
- package/src/queue/listeners.ts +0 -199
- package/src/queue/queue.ts +0 -84
- package/src/redis/index.ts +0 -6
- package/src/redis/init.ts +0 -118
- package/src/redis/redis.ts +0 -358
- package/src/redis/redlockImpl.ts +0 -155
- package/src/redis/tests/redis.spec.ts +0 -207
- package/src/redis/tests/redlockImpl.spec.ts +0 -105
- package/src/redis/utils.ts +0 -128
- package/src/security/auth.ts +0 -24
- package/src/security/encryption.ts +0 -185
- package/src/security/index.ts +0 -1
- package/src/security/permissions.ts +0 -166
- package/src/security/roles.ts +0 -655
- package/src/security/secrets.ts +0 -20
- package/src/security/sessions.ts +0 -123
- package/src/security/tests/auth.spec.ts +0 -45
- package/src/security/tests/encryption.spec.ts +0 -31
- package/src/security/tests/permissions.spec.ts +0 -146
- package/src/security/tests/secrets.spec.ts +0 -35
- package/src/security/tests/sessions.spec.ts +0 -12
- package/src/sql/designDoc.ts +0 -17
- package/src/sql/index.ts +0 -5
- package/src/sql/sql.ts +0 -1854
- package/src/sql/sqlTable.ts +0 -319
- package/src/sql/utils.ts +0 -193
- package/src/tenancy/db.ts +0 -6
- package/src/tenancy/index.ts +0 -2
- package/src/tenancy/tenancy.ts +0 -148
- package/src/tenancy/tests/tenancy.spec.ts +0 -184
- package/src/timers/index.ts +0 -1
- package/src/timers/timers.ts +0 -22
- package/src/users/db.ts +0 -582
- package/src/users/events.ts +0 -176
- package/src/users/index.ts +0 -4
- package/src/users/lookup.ts +0 -99
- package/src/users/test/db.spec.ts +0 -188
- package/src/users/test/utils.spec.ts +0 -67
- package/src/users/users.ts +0 -353
- package/src/users/utils.ts +0 -81
- package/src/utils/Duration.ts +0 -56
- package/src/utils/hashing.ts +0 -15
- package/src/utils/index.ts +0 -4
- package/src/utils/stringUtils.ts +0 -8
- package/src/utils/tests/Duration.spec.ts +0 -19
- package/src/utils/tests/utils.spec.ts +0 -204
- package/src/utils/utils.ts +0 -249
- package/tests/core/logging.ts +0 -34
- package/tests/core/users/users.spec.js +0 -53
- package/tests/core/utilities/index.ts +0 -7
- package/tests/core/utilities/jestUtils.ts +0 -33
- package/tests/core/utilities/mocks/alerts.ts +0 -4
- package/tests/core/utilities/mocks/date.ts +0 -3
- package/tests/core/utilities/mocks/events.ts +0 -132
- package/tests/core/utilities/mocks/index.ts +0 -9
- package/tests/core/utilities/mocks/licenses.ts +0 -119
- package/tests/core/utilities/queue.ts +0 -9
- package/tests/core/utilities/structures/Chance.ts +0 -20
- package/tests/core/utilities/structures/accounts.ts +0 -80
- package/tests/core/utilities/structures/apps.ts +0 -21
- package/tests/core/utilities/structures/common.ts +0 -7
- package/tests/core/utilities/structures/db.ts +0 -12
- package/tests/core/utilities/structures/documents/index.ts +0 -1
- package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
- package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
- package/tests/core/utilities/structures/generator.ts +0 -3
- package/tests/core/utilities/structures/index.ts +0 -15
- package/tests/core/utilities/structures/koa.ts +0 -16
- package/tests/core/utilities/structures/licenses.ts +0 -190
- package/tests/core/utilities/structures/plugins.ts +0 -19
- package/tests/core/utilities/structures/quotas.ts +0 -72
- package/tests/core/utilities/structures/scim.ts +0 -80
- package/tests/core/utilities/structures/sso.ts +0 -118
- package/tests/core/utilities/structures/tenants.ts +0 -5
- package/tests/core/utilities/structures/userGroups.ts +0 -10
- package/tests/core/utilities/structures/users.ts +0 -89
- package/tests/core/utilities/testContainerUtils.ts +0 -165
- package/tests/core/utilities/utils/index.ts +0 -2
- package/tests/core/utilities/utils/queue.ts +0 -27
- package/tests/core/utilities/utils/time.ts +0 -3
- package/tests/extra/DBTestConfiguration.ts +0 -36
- package/tests/extra/index.ts +0 -2
- package/tests/extra/testEnv.ts +0 -95
- package/tests/index.ts +0 -2
- package/tests/jestEnv.ts +0 -10
- package/tests/jestSetup.ts +0 -36
package/src/db/Replication.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import PouchDB from "pouchdb"
|
|
2
|
-
import { getPouchDB, closePouchDB } from "./couch"
|
|
3
|
-
import { DocumentType } from "@budibase/types"
|
|
4
|
-
|
|
5
|
-
enum ReplicationDirection {
|
|
6
|
-
TO_PRODUCTION = "toProduction",
|
|
7
|
-
TO_DEV = "toDev",
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
class Replication {
|
|
11
|
-
source: PouchDB.Database
|
|
12
|
-
target: PouchDB.Database
|
|
13
|
-
direction: ReplicationDirection | undefined
|
|
14
|
-
|
|
15
|
-
constructor({ source, target }: { source: string; target: string }) {
|
|
16
|
-
this.source = getPouchDB(source)
|
|
17
|
-
this.target = getPouchDB(target)
|
|
18
|
-
if (
|
|
19
|
-
source.startsWith(DocumentType.APP_DEV) &&
|
|
20
|
-
target.startsWith(DocumentType.APP)
|
|
21
|
-
) {
|
|
22
|
-
this.direction = ReplicationDirection.TO_PRODUCTION
|
|
23
|
-
} else if (
|
|
24
|
-
source.startsWith(DocumentType.APP) &&
|
|
25
|
-
target.startsWith(DocumentType.APP_DEV)
|
|
26
|
-
) {
|
|
27
|
-
this.direction = ReplicationDirection.TO_DEV
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async close() {
|
|
32
|
-
await Promise.all([closePouchDB(this.source), closePouchDB(this.target)])
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
replicate(opts: PouchDB.Replication.ReplicateOptions = {}) {
|
|
36
|
-
return new Promise<PouchDB.Replication.ReplicationResult<{}>>(resolve => {
|
|
37
|
-
this.source.replicate
|
|
38
|
-
.to(this.target, opts)
|
|
39
|
-
.on("denied", function (err) {
|
|
40
|
-
// a document failed to replicate (e.g. due to permissions)
|
|
41
|
-
throw new Error(`Denied: Document failed to replicate ${err}`)
|
|
42
|
-
})
|
|
43
|
-
.on("complete", function (info) {
|
|
44
|
-
return resolve(info)
|
|
45
|
-
})
|
|
46
|
-
.on("error", function (err) {
|
|
47
|
-
throw err
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
appReplicateOpts(
|
|
53
|
-
opts: PouchDB.Replication.ReplicateOptions = {}
|
|
54
|
-
): PouchDB.Replication.ReplicateOptions {
|
|
55
|
-
if (typeof opts.filter === "string") {
|
|
56
|
-
return opts
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const filter = opts.filter
|
|
60
|
-
const direction = this.direction
|
|
61
|
-
const toDev = direction === ReplicationDirection.TO_DEV
|
|
62
|
-
delete opts.filter
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
...opts,
|
|
66
|
-
filter: (doc: any, params: any) => {
|
|
67
|
-
// don't sync design documents
|
|
68
|
-
if (toDev && doc._id?.startsWith("_design")) {
|
|
69
|
-
return false
|
|
70
|
-
}
|
|
71
|
-
if (doc._id?.startsWith(DocumentType.AUTOMATION_LOG)) {
|
|
72
|
-
return false
|
|
73
|
-
}
|
|
74
|
-
if (doc._id === DocumentType.APP_METADATA) {
|
|
75
|
-
return false
|
|
76
|
-
}
|
|
77
|
-
return filter ? filter(doc, params) : true
|
|
78
|
-
},
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Rollback the target DB back to the state of the source DB
|
|
84
|
-
*/
|
|
85
|
-
async rollback() {
|
|
86
|
-
await this.target.destroy()
|
|
87
|
-
// Recreate the DB again
|
|
88
|
-
this.target = getPouchDB(this.target.name)
|
|
89
|
-
// take the opportunity to remove deleted tombstones
|
|
90
|
-
await this.replicate()
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export default Replication
|
|
@@ -1,511 +0,0 @@
|
|
|
1
|
-
import Nano from "@budibase/nano"
|
|
2
|
-
import {
|
|
3
|
-
AllDocsResponse,
|
|
4
|
-
AnyDocument,
|
|
5
|
-
Database,
|
|
6
|
-
DatabaseCreateIndexOpts,
|
|
7
|
-
DatabaseDeleteIndexOpts,
|
|
8
|
-
DatabaseOpts,
|
|
9
|
-
DatabasePutOpts,
|
|
10
|
-
DatabaseQueryOpts,
|
|
11
|
-
DBError,
|
|
12
|
-
Document,
|
|
13
|
-
isDocument,
|
|
14
|
-
RowResponse,
|
|
15
|
-
RowValue,
|
|
16
|
-
SqlClient,
|
|
17
|
-
SQLiteDefinition,
|
|
18
|
-
SqlQueryBinding,
|
|
19
|
-
} from "@budibase/types"
|
|
20
|
-
import { getCouchInfo } from "./connections"
|
|
21
|
-
import { directCouchUrlCall } from "./utils"
|
|
22
|
-
import { getPouchDB } from "./pouchDB"
|
|
23
|
-
import { ReadStream, WriteStream } from "fs"
|
|
24
|
-
import { newid } from "../../docIds/newid"
|
|
25
|
-
import { SQLITE_DESIGN_DOC_ID } from "../../constants"
|
|
26
|
-
import { DDInstrumentedDatabase } from "../instrumentation"
|
|
27
|
-
import { checkSlashesInUrl } from "../../helpers"
|
|
28
|
-
import { sqlLog } from "../../sql/utils"
|
|
29
|
-
|
|
30
|
-
const DATABASE_NOT_FOUND = "Database does not exist."
|
|
31
|
-
|
|
32
|
-
function buildNano(couchInfo: { url: string; cookie: string }) {
|
|
33
|
-
return Nano({
|
|
34
|
-
url: couchInfo.url,
|
|
35
|
-
requestDefaults: {
|
|
36
|
-
headers: {
|
|
37
|
-
Authorization: couchInfo.cookie,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
parseUrl: false,
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
type DBCall<T> = () => Promise<T>
|
|
45
|
-
type DBCallback<T> = (
|
|
46
|
-
db: Nano.DocumentScope<any>
|
|
47
|
-
) => Promise<DBCall<T>> | DBCall<T>
|
|
48
|
-
|
|
49
|
-
class CouchDBError extends Error implements DBError {
|
|
50
|
-
status: number
|
|
51
|
-
statusCode: number
|
|
52
|
-
reason: string
|
|
53
|
-
name: string
|
|
54
|
-
errid: string
|
|
55
|
-
error: string
|
|
56
|
-
description: string
|
|
57
|
-
|
|
58
|
-
constructor(
|
|
59
|
-
message: string,
|
|
60
|
-
info: {
|
|
61
|
-
status?: number
|
|
62
|
-
statusCode?: number
|
|
63
|
-
name: string
|
|
64
|
-
errid?: string
|
|
65
|
-
description?: string
|
|
66
|
-
reason?: string
|
|
67
|
-
error?: string
|
|
68
|
-
}
|
|
69
|
-
) {
|
|
70
|
-
super(message)
|
|
71
|
-
const statusCode = info.status || info.statusCode || 500
|
|
72
|
-
this.status = statusCode
|
|
73
|
-
this.statusCode = statusCode
|
|
74
|
-
this.reason = info.reason || "Unknown"
|
|
75
|
-
this.name = info.name
|
|
76
|
-
this.errid = info.errid || "Unknown"
|
|
77
|
-
this.description = info.description || "Unknown"
|
|
78
|
-
this.error = info.error || "Not found"
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function DatabaseWithConnection(
|
|
83
|
-
dbName: string,
|
|
84
|
-
connection: string,
|
|
85
|
-
opts?: DatabaseOpts
|
|
86
|
-
) {
|
|
87
|
-
if (!dbName || !connection) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
"Unable to create database without database name or connection"
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
const db = new DatabaseImpl(dbName, opts, connection)
|
|
93
|
-
return new DDInstrumentedDatabase(db)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export class DatabaseImpl implements Database {
|
|
97
|
-
public readonly name: string
|
|
98
|
-
private static nano: Nano.ServerScope
|
|
99
|
-
private readonly instanceNano?: Nano.ServerScope
|
|
100
|
-
private readonly pouchOpts: DatabaseOpts
|
|
101
|
-
|
|
102
|
-
private readonly couchInfo = getCouchInfo()
|
|
103
|
-
|
|
104
|
-
constructor(dbName: string, opts?: DatabaseOpts, connection?: string) {
|
|
105
|
-
this.name = dbName
|
|
106
|
-
this.pouchOpts = opts || {}
|
|
107
|
-
if (connection) {
|
|
108
|
-
this.couchInfo = getCouchInfo(connection)
|
|
109
|
-
this.instanceNano = buildNano(this.couchInfo)
|
|
110
|
-
}
|
|
111
|
-
if (!DatabaseImpl.nano) {
|
|
112
|
-
DatabaseImpl.init()
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
static init() {
|
|
117
|
-
const couchInfo = getCouchInfo()
|
|
118
|
-
DatabaseImpl.nano = buildNano(couchInfo)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
exists(docId?: string) {
|
|
122
|
-
if (docId === undefined) {
|
|
123
|
-
return this.dbExists()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return this.docExists(docId)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private async dbExists() {
|
|
130
|
-
const response = await directCouchUrlCall({
|
|
131
|
-
url: `${this.couchInfo.url}/${this.name}`,
|
|
132
|
-
method: "HEAD",
|
|
133
|
-
cookie: this.couchInfo.cookie,
|
|
134
|
-
})
|
|
135
|
-
return response.status === 200
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
private async docExists(id: string): Promise<boolean> {
|
|
139
|
-
try {
|
|
140
|
-
await this.performCall(db => () => db.head(id))
|
|
141
|
-
return true
|
|
142
|
-
} catch {
|
|
143
|
-
return false
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private nano() {
|
|
148
|
-
return this.instanceNano || DatabaseImpl.nano
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private getDb() {
|
|
152
|
-
return this.nano().db.use(this.name)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private async checkAndCreateDb() {
|
|
156
|
-
let shouldCreate = !this.pouchOpts?.skip_setup
|
|
157
|
-
// check exists in a lightweight fashion
|
|
158
|
-
let exists = await this.exists()
|
|
159
|
-
if (!shouldCreate && !exists) {
|
|
160
|
-
throw new Error("DB does not exist")
|
|
161
|
-
}
|
|
162
|
-
if (!exists) {
|
|
163
|
-
try {
|
|
164
|
-
await this.nano().db.create(this.name)
|
|
165
|
-
} catch (err: any) {
|
|
166
|
-
// Handling race conditions
|
|
167
|
-
if (err.statusCode !== 412) {
|
|
168
|
-
throw new CouchDBError(err.message, err)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return this.getDb()
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// this function fetches the DB and handles if DB creation is needed
|
|
176
|
-
private async performCallWithDBCreation<T>(
|
|
177
|
-
call: DBCallback<T>
|
|
178
|
-
): Promise<any> {
|
|
179
|
-
const db = this.getDb()
|
|
180
|
-
const fnc = await call(db)
|
|
181
|
-
try {
|
|
182
|
-
return await fnc()
|
|
183
|
-
} catch (err: any) {
|
|
184
|
-
if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) {
|
|
185
|
-
await this.checkAndCreateDb()
|
|
186
|
-
return await this.performCallWithDBCreation(call)
|
|
187
|
-
}
|
|
188
|
-
// stripping the error down the props which are safe/useful, drop everything else
|
|
189
|
-
throw new CouchDBError(`CouchDB error: ${err.message}`, err)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private async performCall<T>(call: DBCallback<T>): Promise<any> {
|
|
194
|
-
const db = this.getDb()
|
|
195
|
-
const fnc = await call(db)
|
|
196
|
-
try {
|
|
197
|
-
return await fnc()
|
|
198
|
-
} catch (err: any) {
|
|
199
|
-
// stripping the error down the props which are safe/useful, drop everything else
|
|
200
|
-
throw new CouchDBError(`CouchDB error: ${err.message}`, err)
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async get<T extends Document>(id?: string): Promise<T> {
|
|
205
|
-
return this.performCall(db => {
|
|
206
|
-
if (!id) {
|
|
207
|
-
throw new Error("Unable to get doc without a valid _id.")
|
|
208
|
-
}
|
|
209
|
-
return () => db.get(id)
|
|
210
|
-
})
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
async tryGet<T extends Document>(id?: string): Promise<T | undefined> {
|
|
214
|
-
try {
|
|
215
|
-
return await this.get<T>(id)
|
|
216
|
-
} catch (err: any) {
|
|
217
|
-
if (err.statusCode === 404) {
|
|
218
|
-
return undefined
|
|
219
|
-
}
|
|
220
|
-
throw err
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
async getMultiple<T extends Document>(
|
|
225
|
-
ids: string[],
|
|
226
|
-
opts?: { allowMissing?: boolean; excludeDocs?: boolean }
|
|
227
|
-
): Promise<T[]> {
|
|
228
|
-
// get unique
|
|
229
|
-
ids = [...new Set(ids)]
|
|
230
|
-
const includeDocs = !opts?.excludeDocs
|
|
231
|
-
const response = await this.allDocs<T>({
|
|
232
|
-
keys: ids,
|
|
233
|
-
include_docs: includeDocs,
|
|
234
|
-
})
|
|
235
|
-
const rowUnavailable = (row: RowResponse<T>) => {
|
|
236
|
-
// row is deleted - key lookup can return this
|
|
237
|
-
if (
|
|
238
|
-
(includeDocs && row.doc == null) ||
|
|
239
|
-
(row.value && "deleted" in row.value && row.value.deleted)
|
|
240
|
-
) {
|
|
241
|
-
return true
|
|
242
|
-
}
|
|
243
|
-
return row.error === "not_found"
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const rows = response.rows.filter(row => !rowUnavailable(row))
|
|
247
|
-
const someMissing = rows.length !== response.rows.length
|
|
248
|
-
// some were filtered out - means some missing
|
|
249
|
-
if (!opts?.allowMissing && someMissing) {
|
|
250
|
-
const missing = response.rows.filter(row => rowUnavailable(row))
|
|
251
|
-
const missingIds = missing.map(row => row.key).join(", ")
|
|
252
|
-
throw new Error(`Unable to get documents: ${missingIds}`)
|
|
253
|
-
}
|
|
254
|
-
return rows.map(row => (includeDocs ? row.doc! : row.value))
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async remove(idOrDoc: string | Document, rev?: string) {
|
|
258
|
-
// not a read call - but don't create a DB to delete a document
|
|
259
|
-
return this.performCall(db => {
|
|
260
|
-
let _id: string
|
|
261
|
-
let _rev: string
|
|
262
|
-
|
|
263
|
-
if (isDocument(idOrDoc)) {
|
|
264
|
-
_id = idOrDoc._id!
|
|
265
|
-
_rev = idOrDoc._rev!
|
|
266
|
-
} else {
|
|
267
|
-
_id = idOrDoc
|
|
268
|
-
_rev = rev!
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (!_id || !_rev) {
|
|
272
|
-
throw new Error("Unable to remove doc without a valid _id and _rev.")
|
|
273
|
-
}
|
|
274
|
-
return () => db.destroy(_id, _rev)
|
|
275
|
-
})
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
async bulkRemove(documents: Document[], opts?: { silenceErrors?: boolean }) {
|
|
279
|
-
const response: Nano.DocumentBulkResponse[] = await this.performCall(db => {
|
|
280
|
-
return () =>
|
|
281
|
-
db.bulk({
|
|
282
|
-
docs: documents.map(doc => ({
|
|
283
|
-
...doc,
|
|
284
|
-
_deleted: true,
|
|
285
|
-
})),
|
|
286
|
-
})
|
|
287
|
-
})
|
|
288
|
-
if (opts?.silenceErrors) {
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
let errorFound = false
|
|
292
|
-
let errorMessage: string = "Unable to bulk remove documents: "
|
|
293
|
-
for (let res of response) {
|
|
294
|
-
if (res.error) {
|
|
295
|
-
errorFound = true
|
|
296
|
-
errorMessage += res.error
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (errorFound) {
|
|
300
|
-
throw new CouchDBError(errorMessage, {
|
|
301
|
-
name: this.name,
|
|
302
|
-
status: 400,
|
|
303
|
-
})
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
async post(document: AnyDocument, opts?: DatabasePutOpts) {
|
|
308
|
-
if (!document._id) {
|
|
309
|
-
document._id = newid()
|
|
310
|
-
}
|
|
311
|
-
return this.put(document, opts)
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
async put(document: AnyDocument, opts?: DatabasePutOpts) {
|
|
315
|
-
if (!document._id) {
|
|
316
|
-
throw new Error("Cannot store document without _id field.")
|
|
317
|
-
}
|
|
318
|
-
return this.performCallWithDBCreation(async db => {
|
|
319
|
-
if (!document.createdAt) {
|
|
320
|
-
document.createdAt = new Date().toISOString()
|
|
321
|
-
}
|
|
322
|
-
document.updatedAt = new Date().toISOString()
|
|
323
|
-
if (opts?.force && document._id) {
|
|
324
|
-
try {
|
|
325
|
-
const existing = await this.get(document._id)
|
|
326
|
-
if (existing) {
|
|
327
|
-
document._rev = existing._rev
|
|
328
|
-
}
|
|
329
|
-
} catch (err: any) {
|
|
330
|
-
if (err.status !== 404) {
|
|
331
|
-
throw err
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return () => db.insert(document)
|
|
336
|
-
})
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
async bulkDocs(documents: AnyDocument[]) {
|
|
340
|
-
const now = new Date().toISOString()
|
|
341
|
-
return this.performCallWithDBCreation(db => {
|
|
342
|
-
return () =>
|
|
343
|
-
db.bulk({
|
|
344
|
-
docs: documents.map(d => ({ createdAt: now, ...d, updatedAt: now })),
|
|
345
|
-
})
|
|
346
|
-
})
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
async allDocs<T extends Document | RowValue>(
|
|
350
|
-
params: DatabaseQueryOpts
|
|
351
|
-
): Promise<AllDocsResponse<T>> {
|
|
352
|
-
return this.performCall(db => {
|
|
353
|
-
return async () => {
|
|
354
|
-
try {
|
|
355
|
-
return (await db.list(params)) as AllDocsResponse<T>
|
|
356
|
-
} catch (err: any) {
|
|
357
|
-
if (err.reason === DATABASE_NOT_FOUND) {
|
|
358
|
-
return {
|
|
359
|
-
offset: 0,
|
|
360
|
-
total_rows: 0,
|
|
361
|
-
rows: [],
|
|
362
|
-
}
|
|
363
|
-
} else {
|
|
364
|
-
throw err
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
})
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
async _sqlQuery<T>(
|
|
372
|
-
url: string,
|
|
373
|
-
method: "POST" | "GET",
|
|
374
|
-
body?: Record<string, any>
|
|
375
|
-
): Promise<T> {
|
|
376
|
-
url = checkSlashesInUrl(`${this.couchInfo.sqlUrl}/${url}`)
|
|
377
|
-
const args: { url: string; method: string; cookie: string; body?: any } = {
|
|
378
|
-
url,
|
|
379
|
-
method,
|
|
380
|
-
cookie: this.couchInfo.cookie,
|
|
381
|
-
}
|
|
382
|
-
if (body) {
|
|
383
|
-
args.body = body
|
|
384
|
-
}
|
|
385
|
-
return this.performCall(() => {
|
|
386
|
-
return async () => {
|
|
387
|
-
const response = await directCouchUrlCall(args)
|
|
388
|
-
const text = await response.text()
|
|
389
|
-
if (response.status > 300) {
|
|
390
|
-
let json
|
|
391
|
-
try {
|
|
392
|
-
json = JSON.parse(text)
|
|
393
|
-
} catch (err) {
|
|
394
|
-
console.error(`SQS error: ${text}`)
|
|
395
|
-
throw new CouchDBError(
|
|
396
|
-
"error while running SQS query, please try again later",
|
|
397
|
-
{ name: "sqs_error", status: response.status }
|
|
398
|
-
)
|
|
399
|
-
}
|
|
400
|
-
throw json
|
|
401
|
-
}
|
|
402
|
-
return JSON.parse(text) as T
|
|
403
|
-
}
|
|
404
|
-
})
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
async sql<T extends Document>(
|
|
408
|
-
sql: string,
|
|
409
|
-
parameters?: SqlQueryBinding
|
|
410
|
-
): Promise<T[]> {
|
|
411
|
-
const dbName = this.name
|
|
412
|
-
const url = `/${dbName}/${SQLITE_DESIGN_DOC_ID}`
|
|
413
|
-
sqlLog(SqlClient.SQL_LITE, sql, parameters)
|
|
414
|
-
return await this._sqlQuery<T[]>(url, "POST", {
|
|
415
|
-
query: sql,
|
|
416
|
-
args: parameters,
|
|
417
|
-
})
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// checks design document is accurate (cleans up tables)
|
|
421
|
-
// this will check the design document and remove anything from
|
|
422
|
-
// disk which is not supposed to be there
|
|
423
|
-
async sqlDiskCleanup(): Promise<void> {
|
|
424
|
-
const dbName = this.name
|
|
425
|
-
const url = `/${dbName}/_cleanup`
|
|
426
|
-
try {
|
|
427
|
-
await this._sqlQuery<void>(url, "POST")
|
|
428
|
-
} catch (err: any) {
|
|
429
|
-
// hack for now - SQS throws a 500 when there is nothing to clean-up
|
|
430
|
-
if (err.status !== 500) {
|
|
431
|
-
throw err
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// removes a document from sqlite
|
|
437
|
-
async sqlPurgeDocument(docIds: string[] | string): Promise<void> {
|
|
438
|
-
if (!Array.isArray(docIds)) {
|
|
439
|
-
docIds = [docIds]
|
|
440
|
-
}
|
|
441
|
-
const dbName = this.name
|
|
442
|
-
const url = `/${dbName}/_purge`
|
|
443
|
-
return await this._sqlQuery<void>(url, "POST", { docs: docIds })
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
async query<T extends Document>(
|
|
447
|
-
viewName: string,
|
|
448
|
-
params: DatabaseQueryOpts
|
|
449
|
-
): Promise<AllDocsResponse<T>> {
|
|
450
|
-
return this.performCall(db => {
|
|
451
|
-
const [database, view] = viewName.split("/")
|
|
452
|
-
return () => db.view(database, view, params)
|
|
453
|
-
})
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
async destroy() {
|
|
457
|
-
if (await this.exists(SQLITE_DESIGN_DOC_ID)) {
|
|
458
|
-
// delete the design document, then run the cleanup operation
|
|
459
|
-
const definition = await this.get<SQLiteDefinition>(SQLITE_DESIGN_DOC_ID)
|
|
460
|
-
// remove all tables - save the definition then trigger a cleanup
|
|
461
|
-
definition.sql.tables = {}
|
|
462
|
-
await this.put(definition)
|
|
463
|
-
await this.sqlDiskCleanup()
|
|
464
|
-
}
|
|
465
|
-
try {
|
|
466
|
-
return await this.nano().db.destroy(this.name)
|
|
467
|
-
} catch (err: any) {
|
|
468
|
-
// didn't exist, don't worry
|
|
469
|
-
if (err.statusCode === 404) {
|
|
470
|
-
return
|
|
471
|
-
} else {
|
|
472
|
-
throw new CouchDBError(err.message, err)
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
async compact() {
|
|
478
|
-
return this.performCall(db => {
|
|
479
|
-
return () => db.compact()
|
|
480
|
-
})
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// All below functions are in-frequently called, just utilise PouchDB
|
|
484
|
-
// for them as it implements them better than we can
|
|
485
|
-
async dump(stream: WriteStream, opts?: { filter?: any }) {
|
|
486
|
-
const pouch = getPouchDB(this.name)
|
|
487
|
-
// @ts-ignore
|
|
488
|
-
return pouch.dump(stream, opts)
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
async load(stream: ReadStream) {
|
|
492
|
-
const pouch = getPouchDB(this.name)
|
|
493
|
-
// @ts-ignore
|
|
494
|
-
return pouch.load(stream)
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
async createIndex(opts: DatabaseCreateIndexOpts) {
|
|
498
|
-
const pouch = getPouchDB(this.name)
|
|
499
|
-
return pouch.createIndex(opts)
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
async deleteIndex(opts: DatabaseDeleteIndexOpts) {
|
|
503
|
-
const pouch = getPouchDB(this.name)
|
|
504
|
-
return pouch.deleteIndex(opts)
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
async getIndexes() {
|
|
508
|
-
const pouch = getPouchDB(this.name)
|
|
509
|
-
return pouch.getIndexes()
|
|
510
|
-
}
|
|
511
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import env from "../../environment"
|
|
2
|
-
|
|
3
|
-
export const getCouchInfo = (connection?: string) => {
|
|
4
|
-
// clean out any auth credentials
|
|
5
|
-
const urlInfo = getUrlInfo(connection)
|
|
6
|
-
let username
|
|
7
|
-
let password
|
|
8
|
-
if (urlInfo.auth?.username) {
|
|
9
|
-
// set from url
|
|
10
|
-
username = urlInfo.auth.username
|
|
11
|
-
} else if (env.COUCH_DB_USERNAME) {
|
|
12
|
-
// set from env
|
|
13
|
-
username = env.COUCH_DB_USERNAME
|
|
14
|
-
} else if (!env.isTest()) {
|
|
15
|
-
throw new Error("CouchDB username not set")
|
|
16
|
-
}
|
|
17
|
-
if (urlInfo.auth?.password) {
|
|
18
|
-
// set from url
|
|
19
|
-
password = urlInfo.auth.password
|
|
20
|
-
} else if (env.COUCH_DB_PASSWORD) {
|
|
21
|
-
// set from env
|
|
22
|
-
password = env.COUCH_DB_PASSWORD
|
|
23
|
-
} else if (!env.isTest()) {
|
|
24
|
-
throw new Error("CouchDB password not set")
|
|
25
|
-
}
|
|
26
|
-
const authCookie = Buffer.from(`${username}:${password}`).toString("base64")
|
|
27
|
-
let sqlUrl = env.COUCH_DB_SQL_URL
|
|
28
|
-
// default for dev
|
|
29
|
-
if (env.isDev() && !sqlUrl) {
|
|
30
|
-
sqlUrl = "http://localhost:4006"
|
|
31
|
-
} else if (!sqlUrl && urlInfo.url) {
|
|
32
|
-
const parsed = new URL(urlInfo.url)
|
|
33
|
-
// attempt to connect on default port
|
|
34
|
-
sqlUrl = urlInfo.url.replace(parsed.port, "4984")
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
url: urlInfo.url!,
|
|
38
|
-
// clean out any auth credentials
|
|
39
|
-
sqlUrl: getUrlInfo(sqlUrl).url,
|
|
40
|
-
auth: {
|
|
41
|
-
username: username,
|
|
42
|
-
password: password,
|
|
43
|
-
},
|
|
44
|
-
cookie: `Basic ${authCookie}`,
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export const getUrlInfo = (url = env.COUCH_DB_URL) => {
|
|
49
|
-
let cleanUrl, username, password, host
|
|
50
|
-
if (url) {
|
|
51
|
-
// Ensure the URL starts with a protocol
|
|
52
|
-
const protoRegex = /^https?:\/\//i
|
|
53
|
-
if (!protoRegex.test(url)) {
|
|
54
|
-
url = `http://${url}`
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Split into protocol and remainder
|
|
58
|
-
const split = url.split("://")
|
|
59
|
-
const protocol = split[0]
|
|
60
|
-
const rest = split.slice(1).join("://")
|
|
61
|
-
|
|
62
|
-
// Extract auth if specified
|
|
63
|
-
if (url.includes("@")) {
|
|
64
|
-
// Split into host and remainder
|
|
65
|
-
let parts = rest.split("@")
|
|
66
|
-
host = parts[parts.length - 1]
|
|
67
|
-
let auth = parts.slice(0, -1).join("@")
|
|
68
|
-
|
|
69
|
-
// Split auth into username and password
|
|
70
|
-
if (auth.includes(":")) {
|
|
71
|
-
const authParts = auth.split(":")
|
|
72
|
-
username = authParts[0]
|
|
73
|
-
password = authParts.slice(1).join(":")
|
|
74
|
-
} else {
|
|
75
|
-
username = auth
|
|
76
|
-
}
|
|
77
|
-
} else {
|
|
78
|
-
host = rest
|
|
79
|
-
}
|
|
80
|
-
cleanUrl = `${protocol}://${host}`
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
url: cleanUrl,
|
|
84
|
-
auth: {
|
|
85
|
-
username,
|
|
86
|
-
password,
|
|
87
|
-
},
|
|
88
|
-
}
|
|
89
|
-
}
|
package/src/db/couch/index.ts
DELETED