@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
package/src/db/lucene.ts DELETED
@@ -1,721 +0,0 @@
1
- import fetch from "node-fetch"
2
- import { getCouchInfo } from "./couch"
3
- import {
4
- SearchFilters,
5
- Row,
6
- EmptyFilterOption,
7
- SearchResponse,
8
- SearchParams,
9
- WithRequired,
10
- } from "@budibase/types"
11
- import { dataFilters } from "@budibase/shared-core"
12
-
13
- export const removeKeyNumbering = dataFilters.removeKeyNumbering
14
-
15
- function isEmpty(value: any) {
16
- return value == null || value === ""
17
- }
18
-
19
- /**
20
- * Class to build lucene query URLs.
21
- * Optionally takes a base lucene query object.
22
- */
23
- export class QueryBuilder<T> {
24
- #dbName: string
25
- #index: string
26
- #query: SearchFilters
27
- #limit: number
28
- #sort?: string
29
- #bookmark?: string | number
30
- #sortOrder: string
31
- #sortType: string
32
- #includeDocs: boolean
33
- #version?: string
34
- #indexBuilder?: () => Promise<any>
35
- #noEscaping = false
36
- #skip?: number
37
-
38
- static readonly maxLimit = 200
39
-
40
- constructor(dbName: string, index: string, base?: SearchFilters) {
41
- this.#dbName = dbName
42
- this.#index = index
43
- this.#query = {
44
- allOr: false,
45
- onEmptyFilter: EmptyFilterOption.RETURN_ALL,
46
- string: {},
47
- fuzzy: {},
48
- range: {},
49
- equal: {},
50
- notEqual: {},
51
- empty: {},
52
- notEmpty: {},
53
- oneOf: {},
54
- contains: {},
55
- notContains: {},
56
- containsAny: {},
57
- ...base,
58
- }
59
- this.#limit = 50
60
- this.#sortOrder = "ascending"
61
- this.#sortType = "string"
62
- this.#includeDocs = true
63
- }
64
-
65
- disableEscaping() {
66
- this.#noEscaping = true
67
- return this
68
- }
69
-
70
- setIndexBuilder(builderFn: () => Promise<any>) {
71
- this.#indexBuilder = builderFn
72
- return this
73
- }
74
-
75
- setVersion(version?: string) {
76
- if (version != null) {
77
- this.#version = version
78
- }
79
- return this
80
- }
81
-
82
- setTable(tableId: string) {
83
- this.#query.equal!.tableId = tableId
84
- return this
85
- }
86
-
87
- setLimit(limit?: number) {
88
- if (limit != null) {
89
- this.#limit = limit
90
- }
91
- return this
92
- }
93
-
94
- setSort(sort?: string) {
95
- if (sort != null) {
96
- this.#sort = sort
97
- }
98
- return this
99
- }
100
-
101
- setSortOrder(sortOrder?: string) {
102
- if (sortOrder != null) {
103
- this.#sortOrder = sortOrder
104
- }
105
- return this
106
- }
107
-
108
- setSortType(sortType?: string) {
109
- if (sortType != null) {
110
- this.#sortType = sortType
111
- }
112
- return this
113
- }
114
-
115
- setBookmark(bookmark?: string | number) {
116
- if (bookmark != null) {
117
- this.#bookmark = bookmark
118
- }
119
- return this
120
- }
121
-
122
- setSkip(skip: number | undefined) {
123
- this.#skip = skip
124
- return this
125
- }
126
-
127
- excludeDocs() {
128
- this.#includeDocs = false
129
- return this
130
- }
131
-
132
- includeDocs() {
133
- this.#includeDocs = true
134
- return this
135
- }
136
-
137
- addString(key: string, partial: string) {
138
- this.#query.string![key] = partial
139
- return this
140
- }
141
-
142
- addFuzzy(key: string, fuzzy: string) {
143
- this.#query.fuzzy![key] = fuzzy
144
- return this
145
- }
146
-
147
- addRange(key: string, low: string | number, high: string | number) {
148
- this.#query.range![key] = {
149
- low,
150
- high,
151
- }
152
- return this
153
- }
154
-
155
- addEqual(key: string, value: any) {
156
- this.#query.equal![key] = value
157
- return this
158
- }
159
-
160
- addNotEqual(key: string, value: any) {
161
- this.#query.notEqual![key] = value
162
- return this
163
- }
164
-
165
- addEmpty(key: string, value: any) {
166
- this.#query.empty![key] = value
167
- return this
168
- }
169
-
170
- addNotEmpty(key: string, value: any) {
171
- this.#query.notEmpty![key] = value
172
- return this
173
- }
174
-
175
- addOneOf(key: string, value: any) {
176
- this.#query.oneOf![key] = value
177
- return this
178
- }
179
-
180
- addContains(key: string, value: any) {
181
- this.#query.contains![key] = value
182
- return this
183
- }
184
-
185
- addNotContains(key: string, value: any) {
186
- this.#query.notContains![key] = value
187
- return this
188
- }
189
-
190
- addContainsAny(key: string, value: any) {
191
- this.#query.containsAny![key] = value
192
- return this
193
- }
194
-
195
- setAllOr() {
196
- this.#query.allOr = true
197
- }
198
-
199
- setOnEmptyFilter(value: EmptyFilterOption) {
200
- this.#query.onEmptyFilter = value
201
- }
202
-
203
- handleSpaces(input: string) {
204
- if (this.#noEscaping) {
205
- return input
206
- } else {
207
- return input.replace(/ /g, "_")
208
- }
209
- }
210
-
211
- preprocess(
212
- value: any,
213
- {
214
- escape,
215
- lowercase,
216
- wrap,
217
- type,
218
- }: {
219
- escape?: boolean
220
- lowercase?: boolean
221
- wrap?: boolean
222
- type?: string
223
- } = {}
224
- ): string | any {
225
- const hasVersion = !!this.#version
226
- // Determine if type needs wrapped
227
- const originalType = typeof value
228
- // Convert to lowercase
229
- if (value && lowercase) {
230
- value = value.toLowerCase ? value.toLowerCase() : value
231
- }
232
- // Escape characters
233
- if (!this.#noEscaping && escape && originalType === "string") {
234
- value = `${value}`.replace(/[ /#+\-&|!(){}\]^"~*?:\\]/g, "\\$&")
235
- }
236
-
237
- // Wrap in quotes
238
- if (originalType === "string" && !isNaN(value) && !type) {
239
- value = `"${value}"`
240
- } else if (hasVersion && wrap) {
241
- value = originalType === "number" ? value : `"${value}"`
242
- }
243
- return value
244
- }
245
-
246
- isMultiCondition() {
247
- let count = 0
248
- for (let filters of Object.values(this.#query)) {
249
- // not contains is one massive filter in allOr mode
250
- if (typeof filters === "object") {
251
- count += Object.keys(filters).length
252
- }
253
- }
254
- return count > 1
255
- }
256
-
257
- compressFilters(filters: Record<string, string[]>) {
258
- const compressed: typeof filters = {}
259
- for (let key of Object.keys(filters)) {
260
- const finalKey = removeKeyNumbering(key)
261
- if (compressed[finalKey]) {
262
- compressed[finalKey] = compressed[finalKey].concat(filters[key])
263
- } else {
264
- compressed[finalKey] = filters[key]
265
- }
266
- }
267
- // add prefixes back
268
- const final: typeof filters = {}
269
- let count = 1
270
- for (let [key, value] of Object.entries(compressed)) {
271
- final[`${count++}:${key}`] = value
272
- }
273
- return final
274
- }
275
-
276
- buildSearchQuery() {
277
- const builder = this
278
- let allOr = this.#query && this.#query.allOr
279
- let query = allOr ? "" : "*:*"
280
- let allFiltersEmpty = true
281
- const allPreProcessingOpts = { escape: true, lowercase: true, wrap: true }
282
- let tableId: string = ""
283
- if (this.#query.equal!.tableId) {
284
- tableId = this.#query.equal!.tableId
285
- delete this.#query.equal!.tableId
286
- }
287
-
288
- const equal = (key: string, value: any) => {
289
- if (isEmpty(value)) {
290
- return null
291
- }
292
- return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
293
- }
294
-
295
- const contains = (key: string, value: any, mode = "AND") => {
296
- if (isEmpty(value)) {
297
- return null
298
- }
299
- if (!Array.isArray(value)) {
300
- return `${key}:${value}`
301
- }
302
- let statement = `${builder.preprocess(value[0], { escape: true })}`
303
- for (let i = 1; i < value.length; i++) {
304
- statement += ` ${mode} ${builder.preprocess(value[i], {
305
- escape: true,
306
- })}`
307
- }
308
- return `${key}:(${statement})`
309
- }
310
-
311
- const fuzzy = (key: string, value: any) => {
312
- if (isEmpty(value)) {
313
- return null
314
- }
315
- value = builder.preprocess(value, {
316
- escape: true,
317
- lowercase: true,
318
- type: "fuzzy",
319
- })
320
- return `${key}:/.*${value}.*/`
321
- }
322
-
323
- const notContains = (key: string, value: any) => {
324
- const allPrefix = allOr ? "*:* AND " : ""
325
- const mode = allOr ? "AND" : undefined
326
- return allPrefix + "NOT " + contains(key, value, mode)
327
- }
328
-
329
- const containsAny = (key: string, value: any) => {
330
- return contains(key, value, "OR")
331
- }
332
-
333
- const oneOf = (key: string, value: any) => {
334
- if (isEmpty(value)) {
335
- return `*:*`
336
- }
337
- if (!Array.isArray(value)) {
338
- if (typeof value === "string") {
339
- value = value.split(",")
340
- } else {
341
- return ""
342
- }
343
- }
344
- let orStatement = `${builder.preprocess(value[0], allPreProcessingOpts)}`
345
- for (let i = 1; i < value.length; i++) {
346
- orStatement += ` OR ${builder.preprocess(
347
- value[i],
348
- allPreProcessingOpts
349
- )}`
350
- }
351
- return `${key}:(${orStatement})`
352
- }
353
-
354
- function build(
355
- structure: any,
356
- queryFn: (key: string, value: any) => string | null,
357
- opts?: { returnBuilt?: boolean; mode?: string }
358
- ) {
359
- let built = ""
360
- for (let [key, value] of Object.entries(structure)) {
361
- // check for new format - remove numbering if needed
362
- key = removeKeyNumbering(key)
363
- key = builder.preprocess(builder.handleSpaces(key), {
364
- escape: true,
365
- })
366
- let expression = queryFn(key, value)
367
- if (expression == null) {
368
- continue
369
- }
370
- if (built.length > 0 || query.length > 0) {
371
- const mode = opts?.mode ? opts.mode : allOr ? "OR" : "AND"
372
- built += ` ${mode} `
373
- }
374
- built += expression
375
- if (
376
- (typeof value !== "string" && value != null) ||
377
- (typeof value === "string" && value !== tableId && value !== "")
378
- ) {
379
- allFiltersEmpty = false
380
- }
381
- }
382
- if (opts?.returnBuilt) {
383
- return built
384
- } else {
385
- query += built
386
- }
387
- }
388
-
389
- // Construct the actual lucene search query string from JSON structure
390
- if (this.#query.string) {
391
- build(this.#query.string, (key: string, value: any) => {
392
- if (isEmpty(value)) {
393
- return null
394
- }
395
- value = builder.preprocess(value, {
396
- escape: true,
397
- lowercase: true,
398
- type: "string",
399
- })
400
- return `${key}:${value}*`
401
- })
402
- }
403
- if (this.#query.range) {
404
- build(this.#query.range, (key: string, value: any) => {
405
- if (isEmpty(value)) {
406
- return null
407
- }
408
- if (value.low == null || value.low === "") {
409
- return null
410
- }
411
- if (value.high == null || value.high === "") {
412
- return null
413
- }
414
- const low = builder.preprocess(value.low, allPreProcessingOpts)
415
- const high = builder.preprocess(value.high, allPreProcessingOpts)
416
- return `${key}:[${low} TO ${high}]`
417
- })
418
- }
419
- if (this.#query.fuzzy) {
420
- build(this.#query.fuzzy, fuzzy)
421
- }
422
- if (this.#query.equal) {
423
- build(this.#query.equal, equal)
424
- }
425
- if (this.#query.notEqual) {
426
- build(this.#query.notEqual, (key: string, value: any) => {
427
- if (isEmpty(value)) {
428
- return null
429
- }
430
- if (typeof value === "boolean") {
431
- return `(*:* AND !${key}:${value})`
432
- }
433
- return `!${key}:${builder.preprocess(value, allPreProcessingOpts)}`
434
- })
435
- }
436
- if (this.#query.empty) {
437
- build(this.#query.empty, (key: string) => {
438
- // Because the structure of an empty filter looks like this:
439
- // { empty: { someKey: null } }
440
- //
441
- // The check inside of `build` does not set `allFiltersEmpty`, which results
442
- // in weird behaviour when the empty filter is the only filter. We get around
443
- // this by setting `allFiltersEmpty` to false here.
444
- allFiltersEmpty = false
445
- return `(*:* -${key}:["" TO *])`
446
- })
447
- }
448
- if (this.#query.notEmpty) {
449
- build(this.#query.notEmpty, (key: string) => {
450
- // Because the structure of a notEmpty filter looks like this:
451
- // { notEmpty: { someKey: null } }
452
- //
453
- // The check inside of `build` does not set `allFiltersEmpty`, which results
454
- // in weird behaviour when the empty filter is the only filter. We get around
455
- // this by setting `allFiltersEmpty` to false here.
456
- allFiltersEmpty = false
457
- return `${key}:["" TO *]`
458
- })
459
- }
460
- if (this.#query.oneOf) {
461
- build(this.#query.oneOf, oneOf)
462
- }
463
- if (this.#query.contains) {
464
- build(this.#query.contains, contains)
465
- }
466
- if (this.#query.notContains) {
467
- build(this.compressFilters(this.#query.notContains), notContains)
468
- }
469
- if (this.#query.containsAny) {
470
- build(this.#query.containsAny, containsAny)
471
- }
472
- // make sure table ID is always added as an AND
473
- if (tableId) {
474
- query = this.isMultiCondition() ? `(${query})` : query
475
- allOr = false
476
- build({ tableId }, equal)
477
- }
478
- if (allFiltersEmpty) {
479
- if (this.#query.onEmptyFilter === EmptyFilterOption.RETURN_NONE) {
480
- return ""
481
- } else if (this.#query?.allOr) {
482
- return query.replace("()", "(*:*)")
483
- }
484
- }
485
- return query
486
- }
487
-
488
- buildSearchBody() {
489
- let body: any = {
490
- q: this.buildSearchQuery(),
491
- limit: Math.min(this.#limit, QueryBuilder.maxLimit),
492
- include_docs: this.#includeDocs,
493
- }
494
- if (this.#bookmark) {
495
- body.bookmark = this.#bookmark
496
- }
497
- if (this.#sort) {
498
- const order = this.#sortOrder === "descending" ? "-" : ""
499
- const type = `<${this.#sortType}>`
500
- body.sort = `${order}${this.handleSpaces(this.#sort)}${type}`
501
- }
502
- return body
503
- }
504
-
505
- async run() {
506
- if (this.#skip) {
507
- await this.#skipItems(this.#skip)
508
- }
509
- return await this.#execute()
510
- }
511
-
512
- /**
513
- * Lucene queries do not support pagination and use bookmarks instead.
514
- * For the given builder, walk through pages using bookmarks until the desired
515
- * page has been met.
516
- */
517
- async #skipItems(skip: number) {
518
- // Lucene does not support pagination.
519
- // Handle pagination by finding the right bookmark
520
- const prevIncludeDocs = this.#includeDocs
521
- const prevLimit = this.#limit
522
-
523
- this.excludeDocs()
524
- let skipRemaining = skip
525
- let iterationFetched = 0
526
- do {
527
- const toSkip = Math.min(QueryBuilder.maxLimit, skipRemaining)
528
- this.setLimit(toSkip)
529
- const { bookmark, rows } = await this.#execute()
530
- this.setBookmark(bookmark)
531
- iterationFetched = rows.length
532
- skipRemaining -= rows.length
533
- } while (skipRemaining > 0 && iterationFetched > 0)
534
-
535
- this.#includeDocs = prevIncludeDocs
536
- this.#limit = prevLimit
537
- }
538
-
539
- async #execute() {
540
- const { url, cookie } = getCouchInfo()
541
- const fullPath = `${url}/${this.#dbName}/_design/database/_search/${
542
- this.#index
543
- }`
544
- const body = this.buildSearchBody()
545
- try {
546
- return await runQuery<T>(fullPath, body, cookie)
547
- } catch (err: any) {
548
- if (err.status === 404 && this.#indexBuilder) {
549
- await this.#indexBuilder()
550
- return await runQuery<T>(fullPath, body, cookie)
551
- } else {
552
- throw err
553
- }
554
- }
555
- }
556
- }
557
-
558
- /**
559
- * Executes a lucene search query.
560
- * @param url The query URL
561
- * @param body The request body defining search criteria
562
- * @param cookie The auth cookie for CouchDB
563
- * @returns {Promise<{rows: []}>}
564
- */
565
- async function runQuery<T>(
566
- url: string,
567
- body: any,
568
- cookie: string
569
- ): Promise<WithRequired<SearchResponse<T>, "totalRows">> {
570
- const response = await fetch(url, {
571
- body: JSON.stringify(body),
572
- method: "POST",
573
- headers: {
574
- Authorization: cookie,
575
- },
576
- })
577
-
578
- if (response.status === 404) {
579
- throw response
580
- }
581
- const json = await response.json()
582
-
583
- let output: WithRequired<SearchResponse<T>, "totalRows"> = {
584
- rows: [],
585
- totalRows: 0,
586
- }
587
- if (json.rows != null && json.rows.length > 0) {
588
- output.rows = json.rows.map((row: any) => row.doc)
589
- }
590
- if (json.bookmark) {
591
- output.bookmark = json.bookmark
592
- }
593
- if (json.total_rows) {
594
- output.totalRows = json.total_rows
595
- }
596
- return output
597
- }
598
-
599
- /**
600
- * Gets round the fixed limit of 200 results from a query by fetching as many
601
- * pages as required and concatenating the results. This recursively operates
602
- * until enough results have been found.
603
- * @param dbName Which database to run a lucene query on
604
- * @param index Which search index to utilise
605
- * @param query The JSON query structure
606
- * @param params The search params including:
607
- * tableId {string} The table ID to search
608
- * sort {string} The sort column
609
- * sortOrder {string} The sort order ("ascending" or "descending")
610
- * sortType {string} Whether to treat sortable values as strings or
611
- * numbers. ("string" or "number")
612
- * limit {number} The number of results to fetch
613
- * bookmark {string|null} Current bookmark in the recursive search
614
- * rows {array|null} Current results in the recursive search
615
- */
616
- async function recursiveSearch<T>(
617
- dbName: string,
618
- index: string,
619
- query: any,
620
- params: SearchParams
621
- ): Promise<any> {
622
- const bookmark = params.bookmark
623
- const rows = params.rows || []
624
- if (params.limit && rows.length >= params.limit) {
625
- return rows
626
- }
627
- let pageSize = QueryBuilder.maxLimit
628
- if (params.limit && rows.length > params.limit - QueryBuilder.maxLimit) {
629
- pageSize = params.limit - rows.length
630
- }
631
- const queryBuilder = new QueryBuilder<T>(dbName, index, query)
632
- queryBuilder
633
- .setVersion(params.version)
634
- .setBookmark(bookmark)
635
- .setLimit(pageSize)
636
- .setSort(params.sort)
637
- .setSortOrder(params.sortOrder)
638
- .setSortType(params.sortType)
639
-
640
- if (params.tableId) {
641
- queryBuilder.setTable(params.tableId)
642
- }
643
-
644
- const page = await queryBuilder.run()
645
- if (!page.rows.length) {
646
- return rows
647
- }
648
- if (page.rows.length < QueryBuilder.maxLimit) {
649
- return [...rows, ...page.rows]
650
- }
651
- const newParams: SearchParams = {
652
- ...params,
653
- bookmark: page.bookmark,
654
- rows: [...rows, ...page.rows] as Row[],
655
- }
656
- return await recursiveSearch(dbName, index, query, newParams)
657
- }
658
-
659
- export async function paginatedSearch<T>(
660
- dbName: string,
661
- index: string,
662
- query: SearchFilters,
663
- params: SearchParams
664
- ): Promise<SearchResponse<T>> {
665
- let limit = params.limit
666
- if (limit == null || isNaN(limit) || limit < 0) {
667
- limit = 50
668
- }
669
- limit = Math.min(limit, QueryBuilder.maxLimit)
670
- const search = new QueryBuilder<T>(dbName, index, query)
671
- if (params.version) {
672
- search.setVersion(params.version)
673
- }
674
- if (params.tableId) {
675
- search.setTable(params.tableId)
676
- }
677
- if (params.sort) {
678
- search
679
- .setSort(params.sort)
680
- .setSortOrder(params.sortOrder)
681
- .setSortType(params.sortType)
682
- }
683
- if (params.indexer) {
684
- search.setIndexBuilder(params.indexer)
685
- }
686
- if (params.disableEscaping) {
687
- search.disableEscaping()
688
- }
689
- const searchResults = await search
690
- .setBookmark(params.bookmark)
691
- .setLimit(limit)
692
- .run()
693
-
694
- // Try fetching 1 row in the next page to see if another page of results
695
- // exists or not
696
- search.setBookmark(searchResults.bookmark).setLimit(1)
697
- if (params.tableId) {
698
- search.setTable(params.tableId)
699
- }
700
- const nextResults = await search.run()
701
-
702
- return {
703
- ...searchResults,
704
- hasNextPage: nextResults.rows && nextResults.rows.length > 0,
705
- }
706
- }
707
-
708
- export async function fullSearch<T>(
709
- dbName: string,
710
- index: string,
711
- query: SearchFilters,
712
- params: SearchParams
713
- ): Promise<{ rows: Row[] }> {
714
- let limit = params.limit
715
- if (limit == null || isNaN(limit) || limit < 0) {
716
- limit = 1000
717
- }
718
- params.limit = Math.min(limit, 1000)
719
- const rows = await recursiveSearch<T>(dbName, index, query, params)
720
- return { rows }
721
- }
@@ -1 +0,0 @@
1
- export * from "./searchIndexes"