From 2e296e7c15e3847fe92fda2995c6479346befc0c Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Tue, 12 Mar 2024 20:09:42 +0800 Subject: [PATCH] Improve type safety Allow resource schemata to be run via valibot's Output. --- src/core.ts | 8 ++++---- src/server.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core.ts b/src/core.ts index b31c25d..80358df 100644 --- a/src/core.ts +++ b/src/core.ts @@ -27,7 +27,7 @@ export interface Resource { routeName?: string; dataSource: DataSource; newId(dataSource: DataSource): string | number | unknown; - schema: Parameters[0]; + schema: v.BaseSchema; } interface GenerationStrategy { @@ -38,7 +38,7 @@ interface IdParams { generationStrategy: GenerationStrategy; } -export const resource = (schema: Parameters[0]) => { +export const resource = (schema: T) => { let theIdAttr: string; let theItemName: string; let theCollectionName: string; @@ -56,7 +56,7 @@ export const resource = (schema: Parameters[0]) => { return idGenerationStrategy(dataSource); }, fullText(fullTextAttr: string) { - if (schema[fullTextAttr]?.type === 'string') { + if (schema.type === 'object' && (schema as unknown as v.ObjectSchema, undefined, Record>).entries[fullTextAttr]?.type === 'string') { fullTextAttrs.add(fullTextAttr); return this; } @@ -155,7 +155,7 @@ const handleCreate = async ( return; } - await v.parseAsync(v.object(resource.schema), bodyDeserialized, { abortEarly: false }); + bodyDeserialized = await v.parseAsync(resource.schema, bodyDeserialized, { abortEarly: false }); } catch (err) { res.statusCode = constants.HTTP_STATUS_BAD_REQUEST; res.statusMessage = `Invalid ${resource.itemName}`; diff --git a/src/server.ts b/src/server.ts index 874f12e..5f70945 100644 --- a/src/server.ts +++ b/src/server.ts @@ -50,9 +50,9 @@ const TEXT_SERIALIZER_PAIR = { deserialize: (str: string) => str as T }; -const Piano = resource({ +const Piano = resource(v.object({ brand: v.string() -}) +})) .name('Piano') .id('id', { generationStrategy: autoIncrement, @@ -60,13 +60,13 @@ const Piano = resource({ // TODO implement authentication and RBAC on each resource -const User = resource({ +const User = resource(v.object({ firstName: v.string(), middleName: v.string(), lastName: v.string(), bio: v.string(), createdAt: v.date() -}) +})) .name('User') .fullText('bio') .id('id', {