From 84a22ed475550bd9ed64c2a35964c2945838e6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 9 Oct 2020 12:15:20 +0200 Subject: [PATCH] chore(catalog-backend): removing redudant classes and some functions --- .../catalog/CoalescedEntitiesCatalog.test.ts | 162 ------------------ .../src/catalog/CoalescedEntitiesCatalog.ts | 100 ----------- .../catalog/DatabaseEntitiesCatalog.test.ts | 7 +- .../src/catalog/DatabaseEntitiesCatalog.ts | 10 +- .../src/catalog/StaticEntitiesCatalog.ts | 60 ------- plugins/catalog-backend/src/catalog/index.ts | 1 - .../src/database/CommonDatabase.test.ts | 111 ++++++------ .../src/database/CommonDatabase.ts | 8 +- plugins/catalog-backend/src/database/types.ts | 16 +- 9 files changed, 78 insertions(+), 397 deletions(-) delete mode 100644 plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.test.ts delete mode 100644 plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.ts delete mode 100644 plugins/catalog-backend/src/catalog/StaticEntitiesCatalog.ts diff --git a/plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.test.ts deleted file mode 100644 index f127c2e0bd..0000000000 --- a/plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; -import { Logger } from 'winston'; -import { CoalescedEntitiesCatalog } from './CoalescedEntitiesCatalog'; -import { EntitiesCatalog } from './types'; - -describe('CoalescedEntitiesCatalog', () => { - const e1: Entity = { - apiVersion: 'a', - kind: 'k', - metadata: { name: 'n1' }, - }; - - const e2: Entity = { - apiVersion: 'a', - kind: 'k', - metadata: { name: 'n2' }, - }; - - const c1: jest.Mocked = { - entities: jest.fn(), - entityByUid: jest.fn(), - entityByName: jest.fn(), - addOrUpdateEntity: jest.fn(), - addEntities: jest.fn(), - removeEntityByUid: jest.fn(), - }; - - const c2: jest.Mocked = { - entities: jest.fn(), - entityByUid: jest.fn(), - entityByName: jest.fn(), - addOrUpdateEntity: jest.fn(), - addEntities: jest.fn(), - removeEntityByUid: jest.fn(), - }; - - const mockLogger = { - warn: jest.fn(), - }; - const logger = (mockLogger as unknown) as Logger; - - beforeEach(() => { - jest.resetAllMocks(); - }); - - describe('entities', () => { - it('flattens results from multiple sources', async () => { - c1.entities.mockResolvedValueOnce([e1]); - c2.entities.mockResolvedValueOnce([e2]); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect(catalog.entities()).resolves.toEqual( - expect.arrayContaining([e1, e2]), - ); - expect(c1.entities).toBeCalledTimes(1); - expect(c2.entities).toBeCalledTimes(1); - }); - - it('logs an error if any source throws', async () => { - c1.entities.mockResolvedValueOnce([e1]); - c2.entities.mockRejectedValueOnce(new Error('boo')); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect(catalog.entities()).resolves.toEqual([e1]); - expect(c1.entities).toBeCalledTimes(1); - expect(c2.entities).toBeCalledTimes(1); - expect(mockLogger.warn).toBeCalledWith(expect.stringMatching(/boo/)); - }); - }); - - describe('entityByUid', () => { - it('returns the first non-undefined result', async () => { - c1.entityByUid.mockResolvedValueOnce(undefined); - c2.entityByUid.mockResolvedValueOnce(e2); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect(catalog.entityByUid('e2')).resolves.toBe(e2); - expect(c1.entityByUid).toBeCalledTimes(1); - expect(c2.entityByUid).toBeCalledTimes(1); - }); - - it('returns undefined if all results were undefined', async () => { - c1.entityByUid.mockResolvedValueOnce(undefined); - c2.entityByUid.mockResolvedValueOnce(undefined); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect(catalog.entityByUid('e2')).resolves.toBeUndefined(); - expect(c1.entityByUid).toBeCalledTimes(1); - expect(c2.entityByUid).toBeCalledTimes(1); - }); - - it('logs an error if any source throws', async () => { - c1.entityByUid.mockResolvedValueOnce(e1); - c2.entityByUid.mockRejectedValueOnce(new Error('boo')); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect(catalog.entityByUid('e2')).resolves.toBe(e1); - expect(c1.entityByUid).toBeCalledTimes(1); - expect(c2.entityByUid).toBeCalledTimes(1); - expect(mockLogger.warn).toBeCalledWith(expect.stringMatching(/boo/)); - }); - }); - - describe('entityByName', () => { - it('returns the first non-undefined result', async () => { - c1.entityByName.mockResolvedValueOnce(undefined); - c2.entityByName.mockResolvedValueOnce(e2); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect( - catalog.entityByName({ - kind: 'k', - namespace: ENTITY_DEFAULT_NAMESPACE, - name: 'n2', - }), - ).resolves.toBe(e2); - expect(c1.entityByName).toBeCalledTimes(1); - expect(c2.entityByName).toBeCalledTimes(1); - }); - - it('returns undefined if all results were undefined', async () => { - c1.entityByName.mockResolvedValueOnce(undefined); - c2.entityByName.mockResolvedValueOnce(undefined); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect( - catalog.entityByName({ - kind: 'k', - namespace: ENTITY_DEFAULT_NAMESPACE, - name: 'n2', - }), - ).resolves.toBeUndefined(); - expect(c1.entityByName).toBeCalledTimes(1); - expect(c2.entityByName).toBeCalledTimes(1); - }); - - it('logs an error if any source throws', async () => { - c1.entityByName.mockResolvedValueOnce(e1); - c2.entityByName.mockRejectedValueOnce(new Error('boo')); - const catalog = new CoalescedEntitiesCatalog([c1, c2], logger); - await expect( - catalog.entityByName({ - kind: 'k', - namespace: ENTITY_DEFAULT_NAMESPACE, - name: 'n2', - }), - ).resolves.toBe(e1); - expect(c1.entityByName).toBeCalledTimes(1); - expect(c2.entityByName).toBeCalledTimes(1); - expect(mockLogger.warn).toBeCalledWith(expect.stringMatching(/boo/)); - }); - }); -}); diff --git a/plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.ts b/plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.ts deleted file mode 100644 index 705a210f60..0000000000 --- a/plugins/catalog-backend/src/catalog/CoalescedEntitiesCatalog.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity, EntityName } from '@backstage/catalog-model'; -import { Logger } from 'winston'; -import { EntityFilters } from '../database'; -import { EntitiesCatalog } from './types'; - -/** - * A simple coalescing catalog wrapper, that acts as a front for collecting - * catalog data from multiple sources. - * - * One possible usage could be to have this as a front to both a - * DatabaseEntitiesCatalog that holds Component kinds, and another company- - * specific catalog that is a thin wrapper on top of LDAP that supplies Group - * and User entities. That way you'll get a coherent view of two very different - * entity sources. - * - * This is mainly meant as a functional example, and you may want to provide - * your own more specialized collector if you have this distinct need. This - * one does not support adding/updating entities through the API for example. - * A more competent implementation may direct the writes to different catalogs - * based on entity kind or similar. - */ -export class CoalescedEntitiesCatalog implements EntitiesCatalog { - private inner: EntitiesCatalog[]; - private logger: Logger; - - constructor(inner: EntitiesCatalog[], logger: Logger) { - this.inner = inner; - this.logger = logger; - } - - async entities(filters?: EntityFilters): Promise { - const ops = this.inner.map(async catalog => { - try { - return await catalog.entities(filters); - } catch (e) { - this.logger.warn(`Inner entities call failed, ${e}`); - return []; - } - }); - - const results = await Promise.all(ops); - return results.flat(); - } - - async entityByUid(uid: string): Promise { - const ops = this.inner.map(async catalog => { - try { - return await catalog.entityByUid(uid); - } catch (e) { - this.logger.warn(`Inner entityByUid call failed, ${e}`); - return undefined; - } - }); - - const results = await Promise.all(ops); - return results.find(Boolean); - } - - async entityByName(name: EntityName): Promise { - const ops = this.inner.map(async catalog => { - try { - return await catalog.entityByName(name); - } catch (e) { - this.logger.warn(`Inner entityByName call failed, ${e}`); - return undefined; - } - }); - - const results = await Promise.all(ops); - return results.find(Boolean); - } - - addOrUpdateEntity(): Promise { - throw new Error('Method not implemented.'); - } - - addEntities(): Promise { - throw new Error('Method not implemented.'); - } - - removeEntityByUid(): Promise { - throw new Error('Method not implemented.'); - } -} diff --git a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts index a9444af0f9..8ef685e6b0 100644 --- a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts @@ -24,13 +24,12 @@ describe('DatabaseEntitiesCatalog', () => { beforeAll(() => { db = { transaction: jest.fn(), - addEntity: jest.fn(), addEntities: jest.fn(), updateEntity: jest.fn(), entities: jest.fn(), entityByName: jest.fn(), entityByUid: jest.fn(), - removeEntity: jest.fn(), + removeEntityByUid: jest.fn(), addLocation: jest.fn(), removeLocation: jest.fn(), location: jest.fn(), @@ -57,7 +56,7 @@ describe('DatabaseEntitiesCatalog', () => { }; db.entities.mockResolvedValue([]); - db.addEntity.mockResolvedValue({ entity }); + db.addEntities.mockResolvedValue([{ entity }]); const catalog = new DatabaseEntitiesCatalog(db); const result = await catalog.addOrUpdateEntity(entity); @@ -68,7 +67,7 @@ describe('DatabaseEntitiesCatalog', () => { namespace: 'd', name: 'c', }); - expect(db.addEntity).toHaveBeenCalledTimes(1); + expect(db.addEntities).toHaveBeenCalledTimes(1); expect(result).toBe(entity); }); diff --git a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts index 82ef680b09..2575411e7c 100644 --- a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts @@ -72,7 +72,10 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { existing.entity.metadata.generation, ); } else { - response = await this.database.addEntity(tx, { locationId, entity }); + const added = await this.database.addEntities(tx, [ + { locationId, entity }, + ]); + response = added[0]; } return response.entity; @@ -105,7 +108,10 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { ]) : [entityResponse]; for (const dbResponse of colocatedEntities) { - await this.database.removeEntity(tx, dbResponse?.entity.metadata.uid!); + await this.database.removeEntityByUid( + tx, + dbResponse?.entity.metadata.uid!, + ); } if (entityResponse.locationId) { diff --git a/plugins/catalog-backend/src/catalog/StaticEntitiesCatalog.ts b/plugins/catalog-backend/src/catalog/StaticEntitiesCatalog.ts deleted file mode 100644 index b9d50cfc62..0000000000 --- a/plugins/catalog-backend/src/catalog/StaticEntitiesCatalog.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity, EntityName, getEntityName } from '@backstage/catalog-model'; -import lodash from 'lodash'; -import type { EntitiesCatalog } from './types'; - -export class StaticEntitiesCatalog implements EntitiesCatalog { - private _entities: Entity[]; - - constructor(entities: Entity[]) { - this._entities = entities; - } - - async entities(): Promise { - return lodash.cloneDeep(this._entities); - } - - async entityByUid(uid: string): Promise { - const item = this._entities.find(e => uid === e.metadata.uid); - return item ? lodash.cloneDeep(item) : undefined; - } - - async entityByName(name: EntityName): Promise { - const item = this._entities.find(e => { - const candidate = getEntityName(e); - return ( - name.kind.toLowerCase() === candidate.kind.toLowerCase() && - name.namespace.toLowerCase() === candidate.namespace.toLowerCase() && - name.name.toLowerCase() === candidate.name.toLowerCase() - ); - }); - return item ? lodash.cloneDeep(item) : undefined; - } - - async addOrUpdateEntity(): Promise { - throw new Error('Not supported'); - } - - async addEntities(): Promise { - throw new Error('Not supported'); - } - - async removeEntityByUid(): Promise { - throw new Error('Not supported'); - } -} diff --git a/plugins/catalog-backend/src/catalog/index.ts b/plugins/catalog-backend/src/catalog/index.ts index 308078b1fc..ce429327a0 100644 --- a/plugins/catalog-backend/src/catalog/index.ts +++ b/plugins/catalog-backend/src/catalog/index.ts @@ -16,5 +16,4 @@ export { DatabaseEntitiesCatalog } from './DatabaseEntitiesCatalog'; export { DatabaseLocationsCatalog } from './DatabaseLocationsCatalog'; -export { StaticEntitiesCatalog } from './StaticEntitiesCatalog'; export type { EntitiesCatalog, LocationsCatalog } from './types'; diff --git a/plugins/catalog-backend/src/database/CommonDatabase.test.ts b/plugins/catalog-backend/src/database/CommonDatabase.test.ts index 2883d81b3d..840af74825 100644 --- a/plugins/catalog-backend/src/database/CommonDatabase.test.ts +++ b/plugins/catalog-backend/src/database/CommonDatabase.test.ts @@ -17,12 +17,12 @@ import { ConflictError } from '@backstage/backend-common'; import type { Entity, Location } from '@backstage/catalog-model'; import { DatabaseManager } from './DatabaseManager'; -import { Database, DatabaseLocationUpdateLogStatus } from './types'; import type { DbEntityRequest, DbEntityResponse, DbLocationsRowWithStatus, } from './types'; +import { Database, DatabaseLocationUpdateLogStatus } from './types'; const bootstrapLocation = { id: expect.any(String), @@ -135,43 +135,12 @@ describe('CommonDatabase', () => { await expect(db.location(location.id)).rejects.toThrow(/Found no location/); }); - describe('addEntity', () => { - it('happy path: adds entity to empty database', async () => { - const added = await db.transaction(tx => db.addEntity(tx, entityRequest)); - expect(added).toStrictEqual(entityResponse); - expect(added.entity.metadata.generation).toBe(1); - }); - - it('rejects adding the same-named entity twice', async () => { - await db.transaction(tx => db.addEntity(tx, entityRequest)); - await expect( - db.transaction(tx => db.addEntity(tx, entityRequest)), - ).rejects.toThrow(ConflictError); - }); - - it('rejects adding the almost-same-namespace entity twice', async () => { - entityRequest.entity.metadata.namespace = undefined; - await db.transaction(tx => db.addEntity(tx, entityRequest)); - entityRequest.entity.metadata.namespace = ''; - await expect( - db.transaction(tx => db.addEntity(tx, entityRequest)), - ).rejects.toThrow(ConflictError); - }); - - it('accepts adding the same-named entity twice if on different namespaces', async () => { - entityRequest.entity.metadata.namespace = 'namespace1'; - await db.transaction(tx => db.addEntity(tx, entityRequest)); - entityRequest.entity.metadata.namespace = 'namespace2'; - await expect( - db.transaction(tx => db.addEntity(tx, entityRequest)), - ).resolves.toBeDefined(); - }); - }); - describe('addEntities', () => { it('happy path: adds entities to empty database', async () => { - await db.transaction(tx => db.addEntities(tx, [entityRequest])); - expect(true).toBeTruthy(); + const result = await db.transaction(tx => + db.addEntities(tx, [entityRequest]), + ); + expect(result).toEqual([entityResponse]); }); it('rejects adding the same-named entity twice', async () => { @@ -237,7 +206,28 @@ describe('CommonDatabase', () => { ]; await expect( db.transaction(tx => db.addEntities(tx, req)), - ).resolves.toBeUndefined(); + ).resolves.toEqual([ + { + entity: expect.objectContaining({ + metadata: expect.objectContaining({ + namespace: 'ns1', + uid: expect.any(String), + etag: expect.any(String), + generation: expect.any(Number), + }), + }), + }, + { + entity: expect.objectContaining({ + metadata: expect.objectContaining({ + namespace: 'ns2', + uid: expect.any(String), + etag: expect.any(String), + generation: expect.any(Number), + }), + }), + }, + ]); }); }); @@ -289,7 +279,9 @@ describe('CommonDatabase', () => { describe('updateEntity', () => { it('can read and no-op-update an entity', async () => { - const added = await db.transaction(tx => db.addEntity(tx, entityRequest)); + const [added] = await db.transaction(tx => + db.addEntities(tx, [entityRequest]), + ); const updated = await db.transaction(tx => db.updateEntity(tx, { entity: added.entity }), ); @@ -306,7 +298,9 @@ describe('CommonDatabase', () => { }); it('can update name if uid matches', async () => { - const added = await db.transaction(tx => db.addEntity(tx, entityRequest)); + const [added] = await db.transaction(tx => + db.addEntities(tx, [entityRequest]), + ); added.entity.metadata.name! = 'new!'; const updated = await db.transaction(tx => db.updateEntity(tx, { entity: added.entity }), @@ -315,7 +309,9 @@ describe('CommonDatabase', () => { }); it('fails to update an entity if etag does not match', async () => { - const added = await db.transaction(tx => db.addEntity(tx, entityRequest)); + const [added] = await db.transaction(tx => + db.addEntities(tx, [entityRequest]), + ); await expect( db.transaction(tx => db.updateEntity(tx, { entity: added.entity }, 'garbage'), @@ -324,7 +320,9 @@ describe('CommonDatabase', () => { }); it('fails to update an entity if generation does not match', async () => { - const added = await db.transaction(tx => db.addEntity(tx, entityRequest)); + const [added] = await db.transaction(tx => + db.addEntities(tx, [entityRequest]), + ); await expect( db.transaction(tx => db.updateEntity(tx, { entity: added.entity }, undefined, 1e20), @@ -347,8 +345,7 @@ describe('CommonDatabase', () => { spec: { c: null }, }; await db.transaction(async tx => { - await db.addEntity(tx, { entity: e1 }); - await db.addEntity(tx, { entity: e2 }); + await db.addEntities(tx, [{ entity: e1 }, { entity: e2 }]); }); const result = await db.transaction(async tx => db.entities(tx, [])); expect(result.length).toEqual(2); @@ -384,9 +381,10 @@ describe('CommonDatabase', () => { ]; await db.transaction(async tx => { - for (const entity of entities) { - await db.addEntity(tx, { entity }); - } + await db.addEntities( + tx, + entities.map(entity => ({ entity })), + ); }); await expect( @@ -422,9 +420,10 @@ describe('CommonDatabase', () => { ]; await db.transaction(async tx => { - for (const entity of entities) { - await db.addEntity(tx, { entity }); - } + await db.addEntities( + tx, + entities.map(entity => ({ entity })), + ); }); const rows = await db.transaction(async tx => @@ -471,9 +470,10 @@ describe('CommonDatabase', () => { ]; await db.transaction(async tx => { - for (const entity of entities) { - await db.addEntity(tx, { entity }); - } + await db.addEntities( + tx, + entities.map(entity => ({ entity })), + ); }); const rows = await db.transaction(async tx => @@ -519,9 +519,10 @@ describe('CommonDatabase', () => { ]; await db.transaction(async tx => { - for (const entity of entities) { - await db.addEntity(tx, { entity }); - } + await db.addEntities( + tx, + entities.map(entity => ({ entity })), + ); }); const e1 = await db.transaction(async tx => diff --git a/plugins/catalog-backend/src/database/CommonDatabase.ts b/plugins/catalog-backend/src/database/CommonDatabase.ts index c583217711..49b36e0933 100644 --- a/plugins/catalog-backend/src/database/CommonDatabase.ts +++ b/plugins/catalog-backend/src/database/CommonDatabase.ts @@ -109,9 +109,10 @@ export class CommonDatabase implements Database { async addEntities( txOpaque: unknown, request: DbEntityRequest[], - ): Promise { + ): Promise { const tx = txOpaque as Knex.Transaction; + const result: DbEntityResponse[] = []; const entityRows: DbEntitiesRow[] = []; const searchRows: DbEntitiesSearchRow[] = []; @@ -134,6 +135,7 @@ export class CommonDatabase implements Database { }, }; + result.push({ entity: newEntity, locationId }); entityRows.push(this.toEntityRow(locationId, newEntity)); searchRows.push(...buildEntitySearch(newEntity.metadata.uid, newEntity)); } @@ -146,6 +148,8 @@ export class CommonDatabase implements Database { ) .del(); await tx.batchInsert('entities_search', searchRows, BATCH_SIZE); + + return result; } async updateEntity( @@ -315,7 +319,7 @@ export class CommonDatabase implements Database { return this.toEntityResponse(rows[0]); } - async removeEntity(txOpaque: unknown, uid: string): Promise { + async removeEntityByUid(txOpaque: unknown, uid: string): Promise { const tx = txOpaque as Knex.Transaction; const result = await tx('entities').where({ id: uid }).del(); diff --git a/plugins/catalog-backend/src/database/types.ts b/plugins/catalog-backend/src/database/types.ts index 36de5c2152..20cc123c0a 100644 --- a/plugins/catalog-backend/src/database/types.ts +++ b/plugins/catalog-backend/src/database/types.ts @@ -88,22 +88,16 @@ export type Database = { */ transaction(fn: (tx: unknown) => Promise): Promise; - /** - * Adds a new entity to the catalog. - * - * @param tx An ongoing transaction - * @param request The entity being added - * @returns The added entity, with uid, etag and generation set - */ - addEntity(tx: unknown, request: DbEntityRequest): Promise; - /** * Adds a set of new entities to the catalog. * * @param tx An ongoing transaction * @param request The entities being added */ - addEntities(tx: unknown, request: DbEntityRequest[]): Promise; + addEntities( + tx: unknown, + request: DbEntityRequest[], + ): Promise; /** * Updates an existing entity in the catalog. @@ -140,7 +134,7 @@ export type Database = { entityByUid(tx: unknown, uid: string): Promise; - removeEntity(tx: unknown, uid: string): Promise; + removeEntityByUid(tx: unknown, uid: string): Promise; addLocation(location: Location): Promise;