@budibase/backend-core 3.2.5 → 3.2.7

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