diff --git a/package-lock.json b/package-lock.json index f82cef66..bd6de8f8 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 c2cbb28c..754f4750 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; +};