@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
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"