@budibase/backend-core 2.13.5 → 2.13.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 (42) hide show
  1. package/dist/index.js +55 -23
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +4 -4
  5. package/dist/plugins.js.meta.json +1 -1
  6. package/dist/src/cache/appMetadata.js.map +1 -1
  7. package/dist/src/constants/db.d.ts +1 -3
  8. package/dist/src/constants/db.js.map +1 -1
  9. package/dist/src/context/Context.d.ts +1 -1
  10. package/dist/src/context/Context.js.map +1 -1
  11. package/dist/src/context/identity.d.ts +3 -3
  12. package/dist/src/context/mainContext.d.ts +7 -7
  13. package/dist/src/context/mainContext.js +3 -0
  14. package/dist/src/context/mainContext.js.map +1 -1
  15. package/dist/src/db/couch/DatabaseImpl.d.ts +7 -4
  16. package/dist/src/db/couch/DatabaseImpl.js +20 -3
  17. package/dist/src/db/couch/DatabaseImpl.js.map +1 -1
  18. package/dist/src/db/db.d.ts +3 -4
  19. package/dist/src/db/db.js +2 -14
  20. package/dist/src/db/db.js.map +1 -1
  21. package/dist/src/db/views.d.ts +7 -7
  22. package/dist/src/db/views.js +4 -5
  23. package/dist/src/db/views.js.map +1 -1
  24. package/dist/src/index.d.ts +8 -8
  25. package/dist/src/users/db.js +1 -1
  26. package/dist/src/users/db.js.map +1 -1
  27. package/dist/src/users/users.js.map +1 -1
  28. package/dist/src/utils/utils.d.ts +1 -0
  29. package/dist/src/utils/utils.js +16 -1
  30. package/dist/src/utils/utils.js.map +1 -1
  31. package/package.json +4 -4
  32. package/src/cache/appMetadata.ts +1 -1
  33. package/src/constants/db.ts +1 -1
  34. package/src/context/Context.ts +1 -1
  35. package/src/context/mainContext.ts +13 -10
  36. package/src/db/couch/DatabaseImpl.ts +28 -7
  37. package/src/db/db.ts +3 -13
  38. package/src/db/views.ts +22 -23
  39. package/src/users/db.ts +4 -6
  40. package/src/users/users.ts +1 -1
  41. package/src/utils/tests/utils.spec.ts +13 -0
  42. package/src/utils/utils.ts +14 -0
package/src/db/views.ts CHANGED
@@ -7,12 +7,19 @@ import {
7
7
  } from "../constants"
8
8
  import { getGlobalDB } from "../context"
9
9
  import { doWithDB } from "./"
10
- import { AllDocsResponse, Database, DatabaseQueryOpts } from "@budibase/types"
10
+ import {
11
+ AllDocsResponse,
12
+ Database,
13
+ DatabaseQueryOpts,
14
+ Document,
15
+ DesignDocument,
16
+ DBView,
17
+ } from "@budibase/types"
11
18
  import env from "../environment"
12
19
 
13
20
  const DESIGN_DB = "_design/database"
14
21
 
15
- function DesignDoc() {
22
+ function DesignDoc(): DesignDocument {
16
23
  return {
17
24
  _id: DESIGN_DB,
18
25
  // view collation information, read before writing any complex views:
@@ -21,20 +28,14 @@ function DesignDoc() {
21
28
  }
22
29
  }
23
30
 
24
- interface DesignDocument {
25
- views: any
26
- }
27
-
28
31
  async function removeDeprecated(db: Database, viewName: ViewName) {
29
- // @ts-ignore
30
32
  if (!DeprecatedViews[viewName]) {
31
33
  return
32
34
  }
33
35
  try {
34
36
  const designDoc = await db.get<DesignDocument>(DESIGN_DB)
35
- // @ts-ignore
36
37
  for (let deprecatedNames of DeprecatedViews[viewName]) {
37
- delete designDoc.views[deprecatedNames]
38
+ delete designDoc.views?.[deprecatedNames]
38
39
  }
39
40
  await db.put(designDoc)
40
41
  } catch (err) {
@@ -43,18 +44,18 @@ async function removeDeprecated(db: Database, viewName: ViewName) {
43
44
  }
44
45
 
45
46
  export async function createView(
46
- db: any,
47
+ db: Database,
47
48
  viewJs: string,
48
49
  viewName: string
49
50
  ): Promise<void> {
50
51
  let designDoc
51
52
  try {
52
- designDoc = (await db.get(DESIGN_DB)) as DesignDocument
53
+ designDoc = await db.get<DesignDocument>(DESIGN_DB)
53
54
  } catch (err) {
54
55
  // no design doc, make one
55
56
  designDoc = DesignDoc()
56
57
  }
57
- const view = {
58
+ const view: DBView = {
58
59
  map: viewJs,
59
60
  }
60
61
  designDoc.views = {
@@ -109,7 +110,7 @@ export interface QueryViewOptions {
109
110
  arrayResponse?: boolean
110
111
  }
111
112
 
112
- export async function queryViewRaw<T>(
113
+ export async function queryViewRaw<T extends Document>(
113
114
  viewName: ViewName,
114
115
  params: DatabaseQueryOpts,
115
116
  db: Database,
@@ -137,18 +138,16 @@ export async function queryViewRaw<T>(
137
138
  }
138
139
  }
139
140
 
140
- export const queryView = async <T>(
141
+ export const queryView = async <T extends Document>(
141
142
  viewName: ViewName,
142
143
  params: DatabaseQueryOpts,
143
144
  db: Database,
144
145
  createFunc: any,
145
146
  opts?: QueryViewOptions
146
- ): Promise<T[] | T | undefined> => {
147
+ ): Promise<T[] | T> => {
147
148
  const response = await queryViewRaw<T>(viewName, params, db, createFunc, opts)
148
149
  const rows = response.rows
149
- const docs = rows.map((row: any) =>
150
- params.include_docs ? row.doc : row.value
151
- )
150
+ const docs = rows.map(row => (params.include_docs ? row.doc! : row.value))
152
151
 
153
152
  // if arrayResponse has been requested, always return array regardless of length
154
153
  if (opts?.arrayResponse) {
@@ -198,11 +197,11 @@ export const createPlatformUserView = async () => {
198
197
  await createPlatformView(viewJs, ViewName.PLATFORM_USERS_LOWERCASE)
199
198
  }
200
199
 
201
- export const queryPlatformView = async <T>(
200
+ export const queryPlatformView = async <T extends Document>(
202
201
  viewName: ViewName,
203
202
  params: DatabaseQueryOpts,
204
203
  opts?: QueryViewOptions
205
- ): Promise<T[] | T | undefined> => {
204
+ ): Promise<T[] | T> => {
206
205
  const CreateFuncByName: any = {
207
206
  [ViewName.ACCOUNT_BY_EMAIL]: createPlatformAccountEmailView,
208
207
  [ViewName.PLATFORM_USERS_LOWERCASE]: createPlatformUserView,
@@ -220,7 +219,7 @@ const CreateFuncByName: any = {
220
219
  [ViewName.USER_BY_APP]: createUserAppView,
221
220
  }
222
221
 
223
- export const queryGlobalView = async <T>(
222
+ export const queryGlobalView = async <T extends Document>(
224
223
  viewName: ViewName,
225
224
  params: DatabaseQueryOpts,
226
225
  db?: Database,
@@ -231,10 +230,10 @@ export const queryGlobalView = async <T>(
231
230
  db = getGlobalDB()
232
231
  }
233
232
  const createFn = CreateFuncByName[viewName]
234
- return queryView(viewName, params, db!, createFn, opts)
233
+ return queryView<T>(viewName, params, db!, createFn, opts)
235
234
  }
236
235
 
237
- export async function queryGlobalViewRaw<T>(
236
+ export async function queryGlobalViewRaw<T extends Document>(
238
237
  viewName: ViewName,
239
238
  params: DatabaseQueryOpts,
240
239
  opts?: QueryViewOptions
package/src/users/db.ts CHANGED
@@ -413,15 +413,13 @@ export class UserDB {
413
413
  }
414
414
 
415
415
  // Get users and delete
416
- const allDocsResponse: AllDocsResponse<User> = await db.allDocs({
416
+ const allDocsResponse = await db.allDocs<User>({
417
417
  include_docs: true,
418
418
  keys: userIds,
419
419
  })
420
- const usersToDelete: User[] = allDocsResponse.rows.map(
421
- (user: RowResponse<User>) => {
422
- return user.doc
423
- }
424
- )
420
+ const usersToDelete = allDocsResponse.rows.map(user => {
421
+ return user.doc!
422
+ })
425
423
 
426
424
  // Delete from DB
427
425
  const toDelete = usersToDelete.map(user => ({
@@ -151,7 +151,7 @@ export const searchGlobalUsersByApp = async (
151
151
  include_docs: true,
152
152
  })
153
153
  params.startkey = opts && opts.startkey ? opts.startkey : params.startkey
154
- let response = await queryGlobalView(ViewName.USER_BY_APP, params)
154
+ let response = await queryGlobalView<User>(ViewName.USER_BY_APP, params)
155
155
 
156
156
  if (!response) {
157
157
  response = []
@@ -188,4 +188,17 @@ describe("utils", () => {
188
188
  expectResult(false)
189
189
  })
190
190
  })
191
+
192
+ describe("hasCircularStructure", () => {
193
+ it("should detect a circular structure", () => {
194
+ const a: any = { b: "b" }
195
+ const b = { a }
196
+ a.b = b
197
+ expect(utils.hasCircularStructure(b)).toBe(true)
198
+ })
199
+
200
+ it("should allow none circular structures", () => {
201
+ expect(utils.hasCircularStructure({ a: "b" })).toBe(false)
202
+ })
203
+ })
191
204
  })
@@ -237,3 +237,17 @@ export function timeout(timeMs: number) {
237
237
  export function isAudited(event: Event) {
238
238
  return !!AuditedEventFriendlyName[event]
239
239
  }
240
+
241
+ export function hasCircularStructure(json: any) {
242
+ if (typeof json !== "object") {
243
+ return false
244
+ }
245
+ try {
246
+ JSON.stringify(json)
247
+ } catch (err) {
248
+ if (err instanceof Error && err?.message.includes("circular structure")) {
249
+ return true
250
+ }
251
+ }
252
+ return false
253
+ }