Skip to content

Commit 6d49878

Browse files
gobengotylerchilds
authored andcommitted
initial delete space
1 parent 9339d29 commit 6d49878

File tree

7 files changed

+87
-4
lines changed

7 files changed

+87
-4
lines changed

database/src/space-repository.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ export default class SpaceRepository implements IRepository<ISpace> {
6161
})
6262
}
6363
}
64+
async deleteById(spaceId: string) {
65+
await this.#database.deleteFrom('space')
66+
.where('uuid', '=', spaceId)
67+
.executeTakeFirstOrThrow()
68+
}
6469
async put(space: Updateable<ISpace> & Pick<ISpace, 'uuid'>) {
6570
const rowForSpace = {
6671
controller: space.controller,

database/src/test/test-crud-space.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,16 @@ describe('CRUD Space', async () => {
3333
assert.equal(space.name, spaceToCreate.name)
3434
assert.equal(space.uuid, spaceToCreate.uuid)
3535
});
36+
37+
// get by id
38+
const gotById1 = await new SpaceRepository(database).getById(space.uuid);
39+
assert.ok(gotById1)
40+
41+
// delete space
42+
await new SpaceRepository(database).deleteById(space.uuid);
43+
44+
// after delete, get by id -> SpaceNotFound
45+
const gotById2 = new SpaceRepository(database).getById(space.uuid);
46+
assert.rejects(gotById2, 'SpaceNotFound')
3647
});
3748
})

database/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface SpaceTable {
2929
export interface IRepository<T> {
3030
getById(id: string): Promise<Selectable<T> | null>
3131
create(item: Insertable<T>): Promise<void>
32+
deleteById(id: string): Promise<boolean|void>
3233
toArray(): Promise<Selectable<T>[]>
3334
}
3435

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/src/routes/space.$uuid.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function GET(
2929
}
3030

3131
/**
32-
* build a route to get a space by uuid from a space repository
32+
* build a route to PUT/update a space by uuid from a space repository
3333
* @param spaces - the space repository to query
3434
* @returns - hono handler
3535
*/
@@ -51,6 +51,25 @@ export function PUT(
5151
}
5252
}
5353

54+
55+
/**
56+
* build a route to delete a space by uuid from a space repository
57+
* @param spaces - the space repository to query
58+
* @returns - hono handler
59+
*/
60+
export function DELETE(
61+
spaces: Pick<SpaceRepository, 'deleteById'>,
62+
) {
63+
// hono request handler
64+
// use like
65+
// (new Hono).get('/spaces/:uuid', GET(spaces))
66+
return async (c: Context<any, '/:uuid'>) => {
67+
const uuid = c.req.param('uuid')
68+
await spaces.deleteById(uuid)
69+
return c.newResponse(null, 204)
70+
}
71+
}
72+
5473
class AuthorizationMissing extends Error { }
5574
class NotAuthorized extends Error {}
5675

server/src/server.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { GET as getSpacesIndex } from './routes/spaces._index.ts'
66
import { POST as postSpacesIndex } from './routes/spaces._index.ts'
77
import { GET as getSpaceByUuid } from './routes/space.$uuid.ts'
88
import { PUT as putSpaceByUuid } from './routes/space.$uuid.ts'
9+
import { DELETE as deleteSpaceByUuid } from './routes/space.$uuid.ts'
910
import { cors } from 'hono/cors'
1011
import { authorizeWithSpace } from './lib/authz-middleware.ts'
1112
import { SpaceResourceHono } from "./routes/space.$uuid.$name.ts"
@@ -69,6 +70,13 @@ export class ServerHono extends Hono {
6970
allowWhenSpaceNotFound: true,
7071
}),
7172
putSpaceByUuid(spaces))
73+
// DELETE /space/:uuid
74+
hono.delete('/space/:uuid',
75+
authorizeWithSpace({
76+
data,
77+
space: async (c) => spaces.getById(c.req.param('uuid')),
78+
}),
79+
deleteSpaceByUuid(spaces))
7280

7381
// resources in a space
7482
// * /space/:space/:name{.*}

server/src/test/server.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,43 @@ await describe('server', async t => {
224224
assert.equal(spaceFromGet.name, spaceWithName.name, `space name from GET MUST match space name from most recent PUT`)
225225
}
226226
})
227+
228+
await test('DELETE /space/:uuid', async t => {
229+
const spaceUuid = crypto.randomUUID()
230+
231+
// first create the space
232+
{
233+
const responseToCreateSpace = await server.fetch(new Request(
234+
new URL(`/space/${spaceUuid}`, 'http://example.example'),
235+
{
236+
method: 'PUT',
237+
body: JSON.stringify({ name: `space ${spaceUuid}` }),
238+
headers: {
239+
'Content-Type': 'application/json',
240+
},
241+
}
242+
))
243+
assert.ok(responseToCreateSpace.ok)
244+
}
245+
246+
const request = new Request(new URL(`/space/${spaceUuid}`, 'http://example.example'), {
247+
method: 'DELETE',
248+
headers: {
249+
'Content-Type': 'application/json',
250+
},
251+
})
252+
const response = await server.fetch(request)
253+
assert.equal(response.status, 204, 'response status to DELETE /spaces/ MUST be 204')
254+
255+
// now try to GET it and see if it was deleted
256+
const responseToGetSpace = await server.fetch(new Request(new URL(`/space/${spaceUuid}`, 'http://example.example'), {
257+
method: 'GET',
258+
headers: {
259+
'Accept': 'application/json',
260+
},
261+
}))
262+
assert.equal(
263+
responseToGetSpace.status, 404,
264+
`response status to GET /space/:uuid MUST be 404 after DELETE`)
265+
})
227266
})

0 commit comments

Comments
 (0)