@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.
Files changed (272) hide show
  1. package/dist/index.js.map +1 -1
  2. package/dist/index.js.meta.json +1 -1
  3. package/dist/package.json +11 -4
  4. package/dist/plugins.js.meta.json +1 -1
  5. package/package.json +11 -4
  6. package/src/accounts/accounts.ts +0 -82
  7. package/src/accounts/api.ts +0 -59
  8. package/src/accounts/index.ts +0 -1
  9. package/src/auth/auth.ts +0 -210
  10. package/src/auth/index.ts +0 -1
  11. package/src/auth/tests/auth.spec.ts +0 -14
  12. package/src/blacklist/blacklist.ts +0 -54
  13. package/src/blacklist/index.ts +0 -1
  14. package/src/blacklist/tests/blacklist.spec.ts +0 -46
  15. package/src/cache/appMetadata.ts +0 -88
  16. package/src/cache/base/index.ts +0 -150
  17. package/src/cache/docWritethrough.ts +0 -105
  18. package/src/cache/generic.ts +0 -33
  19. package/src/cache/index.ts +0 -8
  20. package/src/cache/invite.ts +0 -86
  21. package/src/cache/passwordReset.ts +0 -49
  22. package/src/cache/tests/docWritethrough.spec.ts +0 -296
  23. package/src/cache/tests/user.spec.ts +0 -145
  24. package/src/cache/tests/writethrough.spec.ts +0 -139
  25. package/src/cache/user.ts +0 -154
  26. package/src/cache/writethrough.ts +0 -133
  27. package/src/configs/configs.ts +0 -263
  28. package/src/configs/index.ts +0 -1
  29. package/src/configs/tests/configs.spec.ts +0 -184
  30. package/src/constants/db.ts +0 -75
  31. package/src/constants/index.ts +0 -2
  32. package/src/constants/misc.ts +0 -36
  33. package/src/context/Context.ts +0 -14
  34. package/src/context/identity.ts +0 -58
  35. package/src/context/index.ts +0 -3
  36. package/src/context/mainContext.ts +0 -422
  37. package/src/context/tests/index.spec.ts +0 -255
  38. package/src/context/types.ts +0 -26
  39. package/src/db/Replication.ts +0 -94
  40. package/src/db/couch/DatabaseImpl.ts +0 -511
  41. package/src/db/couch/connections.ts +0 -89
  42. package/src/db/couch/index.ts +0 -4
  43. package/src/db/couch/pouchDB.ts +0 -97
  44. package/src/db/couch/pouchDump.ts +0 -0
  45. package/src/db/couch/tests/DatabaseImpl.spec.ts +0 -118
  46. package/src/db/couch/utils.ts +0 -55
  47. package/src/db/db.ts +0 -34
  48. package/src/db/errors.ts +0 -14
  49. package/src/db/index.ts +0 -12
  50. package/src/db/instrumentation.ts +0 -199
  51. package/src/db/lucene.ts +0 -721
  52. package/src/db/searchIndexes/index.ts +0 -1
  53. package/src/db/searchIndexes/searchIndexes.ts +0 -62
  54. package/src/db/tests/DatabaseImpl.spec.ts +0 -55
  55. package/src/db/tests/connections.spec.ts +0 -22
  56. package/src/db/tests/index.spec.ts +0 -32
  57. package/src/db/tests/lucene.spec.ts +0 -400
  58. package/src/db/tests/pouch.spec.js +0 -62
  59. package/src/db/tests/utils.spec.ts +0 -63
  60. package/src/db/utils.ts +0 -208
  61. package/src/db/views.ts +0 -245
  62. package/src/docIds/conversions.ts +0 -60
  63. package/src/docIds/ids.ts +0 -126
  64. package/src/docIds/index.ts +0 -2
  65. package/src/docIds/newid.ts +0 -5
  66. package/src/docIds/params.ts +0 -189
  67. package/src/docUpdates/index.ts +0 -24
  68. package/src/environment.ts +0 -293
  69. package/src/errors/errors.ts +0 -119
  70. package/src/errors/index.ts +0 -1
  71. package/src/events/analytics.ts +0 -6
  72. package/src/events/asyncEvents/index.ts +0 -2
  73. package/src/events/asyncEvents/publisher.ts +0 -12
  74. package/src/events/asyncEvents/queue.ts +0 -22
  75. package/src/events/backfill.ts +0 -183
  76. package/src/events/documentId.ts +0 -56
  77. package/src/events/events.ts +0 -47
  78. package/src/events/identification.ts +0 -311
  79. package/src/events/index.ts +0 -15
  80. package/src/events/processors/AnalyticsProcessor.ts +0 -64
  81. package/src/events/processors/AuditLogsProcessor.ts +0 -92
  82. package/src/events/processors/LoggingProcessor.ts +0 -36
  83. package/src/events/processors/Processors.ts +0 -52
  84. package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -38
  85. package/src/events/processors/index.ts +0 -19
  86. package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
  87. package/src/events/processors/posthog/index.ts +0 -3
  88. package/src/events/processors/posthog/rateLimiting.ts +0 -106
  89. package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -164
  90. package/src/events/processors/types.ts +0 -1
  91. package/src/events/publishers/account.ts +0 -41
  92. package/src/events/publishers/ai.ts +0 -21
  93. package/src/events/publishers/app.ts +0 -168
  94. package/src/events/publishers/auditLog.ts +0 -26
  95. package/src/events/publishers/auth.ts +0 -73
  96. package/src/events/publishers/automation.ts +0 -110
  97. package/src/events/publishers/backfill.ts +0 -74
  98. package/src/events/publishers/backup.ts +0 -42
  99. package/src/events/publishers/datasource.ts +0 -48
  100. package/src/events/publishers/email.ts +0 -17
  101. package/src/events/publishers/environmentVariable.ts +0 -38
  102. package/src/events/publishers/group.ts +0 -99
  103. package/src/events/publishers/index.ts +0 -25
  104. package/src/events/publishers/installation.ts +0 -38
  105. package/src/events/publishers/layout.ts +0 -26
  106. package/src/events/publishers/license.ts +0 -84
  107. package/src/events/publishers/org.ts +0 -37
  108. package/src/events/publishers/plugin.ts +0 -47
  109. package/src/events/publishers/query.ts +0 -89
  110. package/src/events/publishers/role.ts +0 -62
  111. package/src/events/publishers/rows.ts +0 -29
  112. package/src/events/publishers/screen.ts +0 -36
  113. package/src/events/publishers/serve.ts +0 -43
  114. package/src/events/publishers/table.ts +0 -70
  115. package/src/events/publishers/user.ts +0 -202
  116. package/src/events/publishers/view.ts +0 -107
  117. package/src/features/features.ts +0 -277
  118. package/src/features/index.ts +0 -2
  119. package/src/features/tests/features.spec.ts +0 -267
  120. package/src/features/tests/utils.ts +0 -64
  121. package/src/helpers.ts +0 -9
  122. package/src/index.ts +0 -59
  123. package/src/installation.ts +0 -115
  124. package/src/logging/alerts.ts +0 -26
  125. package/src/logging/correlation/correlation.ts +0 -15
  126. package/src/logging/correlation/index.ts +0 -1
  127. package/src/logging/correlation/middleware.ts +0 -18
  128. package/src/logging/index.ts +0 -4
  129. package/src/logging/pino/logger.ts +0 -239
  130. package/src/logging/pino/middleware.ts +0 -48
  131. package/src/logging/system.ts +0 -81
  132. package/src/logging/tests/system.spec.ts +0 -61
  133. package/src/middleware/adminOnly.ts +0 -9
  134. package/src/middleware/auditLog.ts +0 -6
  135. package/src/middleware/authenticated.ts +0 -247
  136. package/src/middleware/builderOnly.ts +0 -21
  137. package/src/middleware/builderOrAdmin.ts +0 -21
  138. package/src/middleware/contentSecurityPolicy.ts +0 -113
  139. package/src/middleware/csrf.ts +0 -81
  140. package/src/middleware/errorHandling.ts +0 -43
  141. package/src/middleware/index.ts +0 -24
  142. package/src/middleware/internalApi.ts +0 -23
  143. package/src/middleware/ip.ts +0 -12
  144. package/src/middleware/joi-validator.ts +0 -58
  145. package/src/middleware/matchers.ts +0 -39
  146. package/src/middleware/passport/datasource/google.ts +0 -102
  147. package/src/middleware/passport/local.ts +0 -54
  148. package/src/middleware/passport/sso/google.ts +0 -77
  149. package/src/middleware/passport/sso/oidc.ts +0 -152
  150. package/src/middleware/passport/sso/sso.ts +0 -138
  151. package/src/middleware/passport/sso/tests/google.spec.ts +0 -68
  152. package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -144
  153. package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
  154. package/src/middleware/passport/utils.ts +0 -38
  155. package/src/middleware/querystringToBody.ts +0 -28
  156. package/src/middleware/tenancy.ts +0 -36
  157. package/src/middleware/tests/builder.spec.ts +0 -181
  158. package/src/middleware/tests/contentSecurityPolicy.spec.ts +0 -75
  159. package/src/middleware/tests/matchers.spec.ts +0 -100
  160. package/src/migrations/definitions.ts +0 -40
  161. package/src/migrations/index.ts +0 -2
  162. package/src/migrations/migrations.ts +0 -186
  163. package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
  164. package/src/migrations/tests/migrations.spec.ts +0 -64
  165. package/src/objectStore/buckets/app.ts +0 -53
  166. package/src/objectStore/buckets/global.ts +0 -29
  167. package/src/objectStore/buckets/index.ts +0 -3
  168. package/src/objectStore/buckets/plugins.ts +0 -71
  169. package/src/objectStore/buckets/tests/app.spec.ts +0 -161
  170. package/src/objectStore/buckets/tests/global.spec.ts +0 -74
  171. package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
  172. package/src/objectStore/cloudfront.ts +0 -41
  173. package/src/objectStore/index.ts +0 -3
  174. package/src/objectStore/objectStore.ts +0 -585
  175. package/src/objectStore/utils.ts +0 -113
  176. package/src/platform/index.ts +0 -3
  177. package/src/platform/platformDb.ts +0 -6
  178. package/src/platform/tenants.ts +0 -101
  179. package/src/platform/tests/tenants.spec.ts +0 -26
  180. package/src/platform/users.ts +0 -129
  181. package/src/plugin/index.ts +0 -1
  182. package/src/plugin/tests/validation.spec.ts +0 -209
  183. package/src/plugin/utils.ts +0 -175
  184. package/src/queue/constants.ts +0 -8
  185. package/src/queue/inMemoryQueue.ts +0 -189
  186. package/src/queue/index.ts +0 -2
  187. package/src/queue/listeners.ts +0 -199
  188. package/src/queue/queue.ts +0 -84
  189. package/src/redis/index.ts +0 -6
  190. package/src/redis/init.ts +0 -118
  191. package/src/redis/redis.ts +0 -358
  192. package/src/redis/redlockImpl.ts +0 -155
  193. package/src/redis/tests/redis.spec.ts +0 -207
  194. package/src/redis/tests/redlockImpl.spec.ts +0 -105
  195. package/src/redis/utils.ts +0 -128
  196. package/src/security/auth.ts +0 -24
  197. package/src/security/encryption.ts +0 -185
  198. package/src/security/index.ts +0 -1
  199. package/src/security/permissions.ts +0 -166
  200. package/src/security/roles.ts +0 -655
  201. package/src/security/secrets.ts +0 -20
  202. package/src/security/sessions.ts +0 -123
  203. package/src/security/tests/auth.spec.ts +0 -45
  204. package/src/security/tests/encryption.spec.ts +0 -31
  205. package/src/security/tests/permissions.spec.ts +0 -146
  206. package/src/security/tests/secrets.spec.ts +0 -35
  207. package/src/security/tests/sessions.spec.ts +0 -12
  208. package/src/sql/designDoc.ts +0 -17
  209. package/src/sql/index.ts +0 -5
  210. package/src/sql/sql.ts +0 -1854
  211. package/src/sql/sqlTable.ts +0 -319
  212. package/src/sql/utils.ts +0 -193
  213. package/src/tenancy/db.ts +0 -6
  214. package/src/tenancy/index.ts +0 -2
  215. package/src/tenancy/tenancy.ts +0 -148
  216. package/src/tenancy/tests/tenancy.spec.ts +0 -184
  217. package/src/timers/index.ts +0 -1
  218. package/src/timers/timers.ts +0 -22
  219. package/src/users/db.ts +0 -582
  220. package/src/users/events.ts +0 -176
  221. package/src/users/index.ts +0 -4
  222. package/src/users/lookup.ts +0 -99
  223. package/src/users/test/db.spec.ts +0 -188
  224. package/src/users/test/utils.spec.ts +0 -67
  225. package/src/users/users.ts +0 -353
  226. package/src/users/utils.ts +0 -81
  227. package/src/utils/Duration.ts +0 -56
  228. package/src/utils/hashing.ts +0 -15
  229. package/src/utils/index.ts +0 -4
  230. package/src/utils/stringUtils.ts +0 -8
  231. package/src/utils/tests/Duration.spec.ts +0 -19
  232. package/src/utils/tests/utils.spec.ts +0 -204
  233. package/src/utils/utils.ts +0 -249
  234. package/tests/core/logging.ts +0 -34
  235. package/tests/core/users/users.spec.js +0 -53
  236. package/tests/core/utilities/index.ts +0 -7
  237. package/tests/core/utilities/jestUtils.ts +0 -33
  238. package/tests/core/utilities/mocks/alerts.ts +0 -4
  239. package/tests/core/utilities/mocks/date.ts +0 -3
  240. package/tests/core/utilities/mocks/events.ts +0 -132
  241. package/tests/core/utilities/mocks/index.ts +0 -9
  242. package/tests/core/utilities/mocks/licenses.ts +0 -119
  243. package/tests/core/utilities/queue.ts +0 -9
  244. package/tests/core/utilities/structures/Chance.ts +0 -20
  245. package/tests/core/utilities/structures/accounts.ts +0 -80
  246. package/tests/core/utilities/structures/apps.ts +0 -21
  247. package/tests/core/utilities/structures/common.ts +0 -7
  248. package/tests/core/utilities/structures/db.ts +0 -12
  249. package/tests/core/utilities/structures/documents/index.ts +0 -1
  250. package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
  251. package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
  252. package/tests/core/utilities/structures/generator.ts +0 -3
  253. package/tests/core/utilities/structures/index.ts +0 -15
  254. package/tests/core/utilities/structures/koa.ts +0 -16
  255. package/tests/core/utilities/structures/licenses.ts +0 -190
  256. package/tests/core/utilities/structures/plugins.ts +0 -19
  257. package/tests/core/utilities/structures/quotas.ts +0 -72
  258. package/tests/core/utilities/structures/scim.ts +0 -80
  259. package/tests/core/utilities/structures/sso.ts +0 -118
  260. package/tests/core/utilities/structures/tenants.ts +0 -5
  261. package/tests/core/utilities/structures/userGroups.ts +0 -10
  262. package/tests/core/utilities/structures/users.ts +0 -89
  263. package/tests/core/utilities/testContainerUtils.ts +0 -165
  264. package/tests/core/utilities/utils/index.ts +0 -2
  265. package/tests/core/utilities/utils/queue.ts +0 -27
  266. package/tests/core/utilities/utils/time.ts +0 -3
  267. package/tests/extra/DBTestConfiguration.ts +0 -36
  268. package/tests/extra/index.ts +0 -2
  269. package/tests/extra/testEnv.ts +0 -95
  270. package/tests/index.ts +0 -2
  271. package/tests/jestEnv.ts +0 -10
  272. package/tests/jestSetup.ts +0 -36
@@ -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
- }
@@ -1,4 +0,0 @@
1
- export * from "./connections"
2
- export * from "./DatabaseImpl"
3
- export * from "./utils"
4
- export { init, getPouch, getPouchDB, closePouchDB } from "./pouchDB"