From 7f231ffc1d2a3829720e8a3918b247513020d9f3 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Wed, 13 Mar 2024 14:35:20 +0800 Subject: [PATCH] Fix data source method invocation Properly initialize data source before making use in POST and PUT endpoints. --- src/core.ts | 2 +- src/data-sources/file-jsonl.ts | 5 +++-- src/handlers.ts | 22 +++++++++++++--------- src/index.ts | 2 +- src/server.ts | 8 ++++++-- src/validation.ts | 13 +++++++++++++ 6 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 src/validation.ts diff --git a/src/core.ts b/src/core.ts index 852b39d..5ec5288 100644 --- a/src/core.ts +++ b/src/core.ts @@ -18,7 +18,7 @@ export interface DataSource { getSingle(id: string): Promise; create(data: Partial): Promise; delete(id: string): Promise; - emplace(id: string, data: Partial): Promise; + emplace(id: string, data: Partial): Promise<[T, boolean]>; patch(id: string, data: Partial): Promise; } diff --git a/src/data-sources/file-jsonl.ts b/src/data-sources/file-jsonl.ts index 0f0c951..7e9911c 100644 --- a/src/data-sources/file-jsonl.ts +++ b/src/data-sources/file-jsonl.ts @@ -75,10 +75,11 @@ export class DataSource> implements DataSourceI await writeFile(this.path, newData.map((d) => JSON.stringify(d)).join('\n')); - return data as T; + return [data, false] as [T, boolean]; } - return this.create(dataToEmplace); + const newData = await this.create(dataToEmplace); + return [newData, true] as [T, boolean]; } async patch(id: string, data: Partial) { diff --git a/src/handlers.ts b/src/handlers.ts index 9737f13..00e8281 100644 --- a/src/handlers.ts +++ b/src/handlers.ts @@ -501,10 +501,10 @@ export const handleCreateItem: Middleware = ({ } try { + await theResource.dataSource.initialize(); const newId = await theResource.newId(theResource.dataSource); const params = bodyDeserialized as Record; params[theResource.idAttr] = newId; - await theResource.dataSource.initialize(); const newObject = await theResource.dataSource.create(params); const theFormatted = theSerializerPair.serialize(newObject); res.writeHead(constants.HTTP_STATUS_OK, { @@ -622,16 +622,20 @@ export const handleEmplaceItem: Middleware = ({ } try { - const newId = await theResource.newId(theResource.dataSource); - const params = bodyDeserialized as Record; - params[theResource.idAttr] = newId; await theResource.dataSource.initialize(); - const newObject = await theResource.dataSource.emplace(mainResourceId, params); + const params = bodyDeserialized as Record; + const [newObject, isCreated] = await theResource.dataSource.emplace(mainResourceId, params); const theFormatted = theSerializerPair.serialize(newObject); - res.writeHead(constants.HTTP_STATUS_OK, { - 'Content-Type': theMediaType, - 'Location': `${serverParams.baseUrl}/${theResource.routeName}/${newId}` - }); + if (isCreated) { + res.writeHead(constants.HTTP_STATUS_CREATED, { + 'Content-Type': theMediaType, + 'Location': `${serverParams.baseUrl}/${theResource.routeName}/${mainResourceId}` + }); + } else { + res.writeHead(constants.HTTP_STATUS_OK, { + 'Content-Type': theMediaType, + }); + } res.end(theFormatted); } catch { res.statusCode = constants.HTTP_STATUS_INTERNAL_SERVER_ERROR; diff --git a/src/index.ts b/src/index.ts index 76c8025..bb98720 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ export * from './core'; -export * as valibot from 'valibot'; +export * as valibot from './validation'; export * as dataSources from './data-sources'; export * as serializers from './serializers'; diff --git a/src/server.ts b/src/server.ts index c9a0bf5..a57bea2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -15,7 +15,11 @@ const autoIncrement = async (dataSource: DataSource) => { -Infinity ); - return (highestId + 1).toString(); + if (Number.isFinite(highestId)) { + return (highestId + 1).toString(); + } + + return "1"; }; @@ -67,7 +71,7 @@ const User = resource(v.object( middleName: v.string(), lastName: v.string(), bio: v.string(), - createdAt: v.date() + birthday: v.datelike() }, v.never() )) diff --git a/src/validation.ts b/src/validation.ts new file mode 100644 index 0000000..1120a62 --- /dev/null +++ b/src/validation.ts @@ -0,0 +1,13 @@ +import * as v from 'valibot'; +export * from 'valibot'; + +export const datelike = () => v.transform( + v.union([ + v.string([v.isoDate()]), + v.string([v.isoDateTime()]), + v.number(), + v.date() + ]), + (value) => new Date(value).toISOString(), + v.string([v.isoTimestamp()]) +);