From 2a84be7633988a8d25c60d5182be1652b077b660 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Mon, 14 Jul 2025 21:17:17 +0200 Subject: [PATCH] feat(core): dev schema --- package-lock.json | 16 ++++++++- packages/core/package.json | 3 +- packages/core/src/types/doc-data.ts | 1 + packages/core/src/types/errors.ts | 12 +++++++ packages/core/src/utils/schema.utils.ts | 44 +++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 packages/core/src/types/doc-data.ts create mode 100644 packages/core/src/utils/schema.utils.ts diff --git a/package-lock.json b/package-lock.json index 3e2ce70e..dbda3d22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2069,6 +2069,13 @@ "size-limit": "11.2.0" } }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT", + "peer": true + }, "node_modules/@tokenizer/inflate": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", @@ -9198,7 +9205,8 @@ "@dfinity/candid": "^2.3.0", "@dfinity/identity": "^2.3.0", "@dfinity/principal": "^2.3.0", - "@dfinity/utils": "^2" + "@dfinity/utils": "^2", + "@standard-schema/spec": "^1.0.0" } }, "packages/core-peer": { @@ -10478,6 +10486,12 @@ "size-limit": "11.2.0" } }, + "@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "peer": true + }, "@tokenizer/inflate": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", diff --git a/packages/core/package.json b/packages/core/package.json index be8ee1bd..476c3a8d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -60,6 +60,7 @@ "@dfinity/candid": "^2.3.0", "@dfinity/identity": "^2.3.0", "@dfinity/principal": "^2.3.0", - "@dfinity/utils": "^2" + "@dfinity/utils": "^2", + "@standard-schema/spec": "^1.0.0" } } diff --git a/packages/core/src/types/doc-data.ts b/packages/core/src/types/doc-data.ts new file mode 100644 index 00000000..f142a7c4 --- /dev/null +++ b/packages/core/src/types/doc-data.ts @@ -0,0 +1 @@ +export type DocDataSchema = {} \ No newline at end of file diff --git a/packages/core/src/types/errors.ts b/packages/core/src/types/errors.ts index 1e451f69..4659a3b1 100644 --- a/packages/core/src/types/errors.ts +++ b/packages/core/src/types/errors.ts @@ -1,3 +1,5 @@ +import {StandardSchemaV1} from '@standard-schema/spec'; + export class SignInError extends Error {} export class SignInInitError extends Error {} export class SignInUserInterruptError extends Error {} @@ -5,3 +7,13 @@ export class SignInUserInterruptError extends Error {} export class InitError extends Error {} export class ListError extends Error {} + +export class SchemaError extends Error { + readonly issues: ReadonlyArray; + + constructor(issues: ReadonlyArray) { + super(issues[0]?.message); + + this.issues = issues; + } +} \ No newline at end of file diff --git a/packages/core/src/utils/schema.utils.ts b/packages/core/src/utils/schema.utils.ts new file mode 100644 index 00000000..12719944 --- /dev/null +++ b/packages/core/src/utils/schema.utils.ts @@ -0,0 +1,44 @@ +import {nonNullish} from '@dfinity/utils'; +import type {StandardSchemaV1} from '@standard-schema/spec'; +import {SchemaError} from '../types/errors'; + +export const assertDataSchema = async ({ + input, + schema +}: { + input: StandardSchemaV1.InferInput; + schema?: T; +}): Promise => { + const withSchema = + nonNullish(schema) && nonNullish(schema['~standard']) && 'validate' in schema['~standard']; + + if (withSchema) { + await validateSchema({input, schema}); + } +}; + +const validateSchema = async ({ + input, + schema +}: { + input: StandardSchemaV1.InferInput; + schema: T; +}): Promise> => { + const validate = async (): Promise> => { + const result = schema['~standard'].validate(input); + + if (result instanceof Promise) { + return await result; + } + + return result; + }; + + const {issues, ...value} = await validate(); + + if (issues !== undefined) { + throw new SchemaError(issues); + } + + return value; +};