Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: delete() by docId not versionId(s) #424

Merged
merged 2 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/datatype/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,5 @@ export class DataType<
>
>(versionId: string | string[], value: T): Promise<TDoc & { forks: string[] }>

delete(versionId: string | string[]): Promise<TDoc & { forks: string[] }>
delete(docId: string): Promise<TDoc & { forks: string[] }>
}
23 changes: 10 additions & 13 deletions src/datatype/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { validate } from '@mapeo/schema'
import { getTableConfig } from 'drizzle-orm/sqlite-core'
import { eq, inArray, placeholder } from 'drizzle-orm'
import { randomBytes } from 'node:crypto'
import { deNullify, valueOf } from '../utils.js'
import { deNullify } from '../utils.js'
import crypto from 'hypercore-crypto'
import { TypedEmitter } from 'tiny-typed-emitter'

Expand Down Expand Up @@ -208,25 +208,22 @@ export class DataType extends TypedEmitter {
}

/**
* Not yet implemented
* @param {string | string[]} versionId
* @param {string} docId
*/
async delete(versionId) {
async delete(docId) {
await this.#dataStore.indexer.idle()
const links = Array.isArray(versionId) ? versionId : [versionId]
const { docId, createdAt, createdBy } = await this.#validateLinks(links)
const existingDoc = await this.getByDocId(docId)

const existingDoc = await this.getByVersionId(links[links.length - 1])
if ('deleted' in existingDoc && existingDoc.deleted) {
throw new Error('Doc already deleted')
}

/** @type {any} */
const doc = {
...valueOf(existingDoc),
docId,
createdAt,
...existingDoc,
updatedAt: new Date().toISOString(),
createdBy,
links,
schemaName: this.#schemaName,
// @ts-expect-error - TS just doesn't work in this class
links: [existingDoc.versionId, ...existingDoc.forks],
deleted: true,
}
await this.#dataStore.write(doc)
Expand Down
61 changes: 61 additions & 0 deletions test-e2e/project-crud.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,66 @@ test('CRUD operations', async (t) => {
'expected values returned before closing and after re-opening'
)
})

await t.test(`create and delete ${schemaName}`, async (st) => {
const projectId = await manager.createProject()
const project = await manager.getProject(projectId)
const writePromises = []
let i = 0
while (i++ < CREATE_COUNT) {
const value = valueOf(generate(schemaName)[0])
writePromises.push(
// @ts-ignore
project[schemaName].create(value)
)
}
const written = await Promise.all(writePromises)
const deleted = await Promise.all(
written.map((doc) => project[schemaName].delete(doc.docId))
)
const read = await Promise.all(
written.map((doc) => project[schemaName].getByDocId(doc.docId))
)
st.ok(
deleted.every((doc) => doc.deleted),
'all docs are deleted'
)
st.alike(
sortById(deleted),
sortById(read),
'return create() matches return of getByDocId()'
)
})

await t.test('delete forks', async (st) => {
const projectId = await manager.createProject()
const project = await manager.getProject(projectId)
// @ts-ignore
const written = await project[schemaName].create(value)
const updateValue = getUpdateFixture(value)
// @ts-ignore
const updatedFork1 = await project[schemaName].update(
written.versionId,
updateValue
)
// @ts-ignore
const updatedFork2 = await project[schemaName].update(
written.versionId,
updateValue
)
const updatedReRead = await project[schemaName].getByDocId(written.docId)
st.alike(
updatedFork2,
updatedReRead,
'return of update() matched return of getByDocId()'
)
st.alike(updatedReRead.forks, [updatedFork1.versionId], 'doc is forked')
const deleted = await project[schemaName].delete(written.docId)
st.ok(deleted.deleted, 'doc is deleted')
st.is(deleted.forks.length, 0, 'forks are deleted')
const deletedReRead = await project[schemaName].getByDocId(written.docId)
st.ok(deletedReRead.deleted, 'doc is deleted')
st.is(deletedReRead.forks.length, 0, 'forks are deleted')
})
}
})
3 changes: 3 additions & 0 deletions test-types/data-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ mapeoProject.observation.on('updated-docs', (docs) => {
Expect<Equal<Observation[], typeof docs>>
})

const deletedObservation = await mapeoProject.observation.delete('abc')
Expect<Equal<Observation & { forks: string[] }, typeof deletedObservation>>

///// Presets

const createdPreset = await mapeoProject.preset.create({} as PresetValue)
Expand Down
2 changes: 1 addition & 1 deletion tests/data-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ test('delete()', async (t) => {
const { dataType } = await testenv({ projectKey })
const doc = await dataType.create(obsFixture)
t.is(doc.deleted, false, `'deleted' field is false before deletion`)
const deletedDoc = await dataType.delete(doc.versionId)
const deletedDoc = await dataType.delete(doc.docId)
t.is(deletedDoc.deleted, true, `'deleted' field is true after deletion`)
t.alike(
deletedDoc.links,
Expand Down
Loading