Merge branch 'master' into feat/row-actions

This commit is contained in:
Adria Navarro 2024-07-25 15:26:50 +02:00 committed by GitHub
commit 22f86be34d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 79 additions and 51 deletions

View File

@ -1,6 +1,6 @@
{ {
"$schema": "node_modules/lerna/schemas/lerna-schema.json", "$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "2.29.24", "version": "2.29.25",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*", "packages/*",

View File

@ -56,24 +56,24 @@ class CouchDBError extends Error implements DBError {
constructor( constructor(
message: string, message: string,
info: { info: {
status: number | undefined status?: number
statusCode: number | undefined statusCode?: number
name: string name: string
errid: string errid?: string
description: string description?: string
reason: string reason?: string
error: string error?: string
} }
) { ) {
super(message) super(message)
const statusCode = info.status || info.statusCode || 500 const statusCode = info.status || info.statusCode || 500
this.status = statusCode this.status = statusCode
this.statusCode = statusCode this.statusCode = statusCode
this.reason = info.reason this.reason = info.reason || "Unknown"
this.name = info.name this.name = info.name
this.errid = info.errid this.errid = info.errid || "Unknown"
this.description = info.description this.description = info.description || "Unknown"
this.error = info.error this.error = info.error || "Not found"
} }
} }
@ -246,6 +246,35 @@ export class DatabaseImpl implements Database {
}) })
} }
async bulkRemove(documents: Document[], opts?: { silenceErrors?: boolean }) {
const response: Nano.DocumentBulkResponse[] = await this.performCall(db => {
return () =>
db.bulk({
docs: documents.map(doc => ({
...doc,
_deleted: true,
})),
})
})
if (opts?.silenceErrors) {
return
}
let errorFound = false
let errorMessage: string = "Unable to bulk remove documents: "
for (let res of response) {
if (res.error) {
errorFound = true
errorMessage += res.error
}
}
if (errorFound) {
throw new CouchDBError(errorMessage, {
name: this.name,
status: 400,
})
}
}
async post(document: AnyDocument, opts?: DatabasePutOpts) { async post(document: AnyDocument, opts?: DatabasePutOpts) {
if (!document._id) { if (!document._id) {
document._id = newid() document._id = newid()

View File

@ -71,6 +71,16 @@ export class DDInstrumentedDatabase implements Database {
}) })
} }
bulkRemove(
documents: Document[],
opts?: { silenceErrors?: boolean }
): Promise<void> {
return tracer.trace("db.bulkRemove", span => {
span?.addTags({ db_name: this.name, num_docs: documents.length })
return this.db.bulkRemove(documents, opts)
})
}
put( put(
document: AnyDocument, document: AnyDocument,
opts?: DatabasePutOpts | undefined opts?: DatabasePutOpts | undefined

View File

@ -113,15 +113,12 @@ export async function addUser(
export async function removeUser(user: User) { export async function removeUser(user: User) {
const db = getPlatformDB() const db = getPlatformDB()
const keys = [user._id!, user.email] const keys = [user._id!, user.email]
const userDocs = await db.allDocs({ const userDocs = await db.allDocs<User>({
keys, keys,
include_docs: true, include_docs: true,
}) })
const toDelete = userDocs.rows.map((row: any) => { await db.bulkRemove(
return { userDocs.rows.map(row => row.doc!),
...row.doc, { silenceErrors: true }
_deleted: true, )
}
})
await db.bulkDocs(toDelete)
} }

View File

@ -115,6 +115,7 @@
}) })
$: fields = bindings $: fields = bindings
.filter(x => arrayTypes.includes(x.fieldSchema?.type)) .filter(x => arrayTypes.includes(x.fieldSchema?.type))
.filter(x => x.fieldSchema?.tableId != null)
.map(binding => { .map(binding => {
const { providerId, readableBinding, runtimeBinding } = binding const { providerId, readableBinding, runtimeBinding } = binding
const { name, type, tableId } = binding.fieldSchema const { name, type, tableId } = binding.fieldSchema

View File

@ -6,7 +6,6 @@ import {
Database, Database,
FieldSchema, FieldSchema,
FieldType, FieldType,
LinkDocumentValue,
RelationshipFieldMetadata, RelationshipFieldMetadata,
RelationshipType, RelationshipType,
Row, Row,
@ -213,11 +212,10 @@ class LinkController {
linkedSchema?.relationshipType === RelationshipType.ONE_TO_MANY linkedSchema?.relationshipType === RelationshipType.ONE_TO_MANY
) { ) {
let links = ( let links = (
(await getLinkDocuments({ await getLinkDocuments({
tableId: field.tableId, tableId: field.tableId,
rowId: linkId, rowId: linkId,
includeDocs: IncludeDocs.EXCLUDE, })
})) as LinkDocumentValue[]
).filter( ).filter(
link => link =>
link.id !== row._id && link.fieldName === linkedSchema.name link.id !== row._id && link.fieldName === linkedSchema.name
@ -295,13 +293,7 @@ class LinkController {
if (linkDocs.length === 0) { if (linkDocs.length === 0) {
return null return null
} }
const toDelete = linkDocs.map(doc => { await this._db.bulkRemove(linkDocs, { silenceErrors: true })
return {
...doc,
_deleted: true,
}
})
await this._db.bulkDocs(toDelete)
return row return row
} }
@ -321,14 +313,8 @@ class LinkController {
: linkDoc.doc2.fieldName : linkDoc.doc2.fieldName
return correctFieldName === fieldName return correctFieldName === fieldName
}) })
await this._db.bulkDocs( await this._db.bulkRemove(toDelete, { silenceErrors: true })
toDelete.map(doc => {
return {
...doc,
_deleted: true,
}
})
)
try { try {
// remove schema from other table, if it exists // remove schema from other table, if it exists
let linkedTable = await this._db.get<Table>(field.tableId) let linkedTable = await this._db.get<Table>(field.tableId)
@ -453,13 +439,7 @@ class LinkController {
return null return null
} }
// get link docs for this table and configure for deletion // get link docs for this table and configure for deletion
const toDelete = linkDocs.map(doc => { await this._db.bulkRemove(linkDocs, { silenceErrors: true })
return {
...doc,
_deleted: true,
}
})
await this._db.bulkDocs(toDelete)
return table return table
} }
} }

View File

@ -1,6 +1,5 @@
import LinkController from "./LinkController" import LinkController from "./LinkController"
import { import {
IncludeDocs,
getLinkDocuments, getLinkDocuments,
getUniqueByProp, getUniqueByProp,
getRelatedTableForField, getRelatedTableForField,
@ -56,12 +55,9 @@ async function getLinksForRows(rows: Row[]): Promise<LinkDocumentValue[]> {
const promises = tableIds.map(tableId => const promises = tableIds.map(tableId =>
getLinkDocuments({ getLinkDocuments({
tableId: tableId, tableId: tableId,
includeDocs: IncludeDocs.EXCLUDE,
}) })
) )
const responses = flatten( const responses = flatten(await Promise.all(promises))
(await Promise.all(promises)) as LinkDocumentValue[][]
)
// have to get unique as the previous table query can // have to get unique as the previous table query can
// return duplicates, could be querying for both tables in a relation // return duplicates, could be querying for both tables in a relation
return getUniqueByProp( return getUniqueByProp(

View File

@ -34,6 +34,17 @@ export const IncludeDocs = {
* @returns This will return an array of the linking documents that were found * @returns This will return an array of the linking documents that were found
* (if any). * (if any).
*/ */
export function getLinkDocuments(args: {
tableId?: string
rowId?: string
fieldName?: string
includeDocs: boolean
}): Promise<LinkDocument[]>
export function getLinkDocuments(args: {
tableId?: string
rowId?: string
fieldName?: string
}): Promise<LinkDocumentValue[]>
export async function getLinkDocuments(args: { export async function getLinkDocuments(args: {
tableId?: string tableId?: string
rowId?: string rowId?: string

View File

@ -555,7 +555,7 @@ export const runQuery = (docs: Record<string, any>[], query: SearchFilters) => {
if (Array.isArray(docValue)) { if (Array.isArray(docValue)) {
return docValue.length === 0 return docValue.length === 0
} }
if (typeof docValue === "object") { if (docValue && typeof docValue === "object") {
return Object.keys(docValue).length === 0 return Object.keys(docValue).length === 0
} }
return docValue == null return docValue == null

View File

@ -137,6 +137,10 @@ export interface Database {
): Promise<T[]> ): Promise<T[]>
remove(idOrDoc: Document): Promise<Nano.DocumentDestroyResponse> remove(idOrDoc: Document): Promise<Nano.DocumentDestroyResponse>
remove(idOrDoc: string, rev?: string): Promise<Nano.DocumentDestroyResponse> remove(idOrDoc: string, rev?: string): Promise<Nano.DocumentDestroyResponse>
bulkRemove(
documents: Document[],
opts?: { silenceErrors?: boolean }
): Promise<void>
put( put(
document: AnyDocument, document: AnyDocument,
opts?: DatabasePutOpts opts?: DatabasePutOpts