From be2a96ac22929666c5dfe8aadde1c6ea053738b0 Mon Sep 17 00:00:00 2001 From: Henrique Ramos Date: Mon, 3 Feb 2025 11:15:47 -0300 Subject: [PATCH] chore: use arktype for schema validation --- .vscode/settings.json | 8 +++++++- package.json | 3 ++- pnpm-lock.yaml | 23 +++++++++++++++++++++++ src/slides/flexbox/index.astro | 8 ++++---- src/utils/getAstroPages.ts | 15 ++++++--------- src/utils/getSlides.ts | 11 ++++++++--- tsconfig.json | 5 ++++- 7 files changed, 54 insertions(+), 19 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4f37590..561f047 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,9 @@ { - "editor.defaultFormatter": "biomejs.biome" + "editor.defaultFormatter": "biomejs.biome", + // allow autocomplete for ArkType expressions like "string | num" + "editor.quickSuggestions": { + "strings": "on" + }, + // prioritize ArkType's "type" for autoimports + "typescript.preferences.autoImportSpecifierExcludeRegexes": ["^(node:)?os$"] } diff --git a/package.json b/package.json index a970ae6..484b12c 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.9.4", - "@types/reveal.js": "^5.0.5" + "@types/reveal.js": "^5.0.5", + "arktype": "^2.0.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37374e3..42f82e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,9 +21,18 @@ importers: '@types/reveal.js': specifier: ^5.0.5 version: 5.0.5 + arktype: + specifier: ^2.0.4 + version: 2.0.4 packages: + '@ark/schema@0.39.0': + resolution: {integrity: sha512-LQbQUb3Sj461LgklXObAyUJNtsUUCBxZlO2HqRLYvRSqpStm0xTMrXn51DwBNNxeSULvKVpXFwoxiSec9kwKww==} + + '@ark/util@0.39.0': + resolution: {integrity: sha512-90APHVklk8BP4kku7hIh1BgrhuyKYqoZ4O7EybtFRo7cDl9mIyc/QUbGvYDg//73s0J2H0I/gW9pzroA1R4IBQ==} + '@astrojs/compiler@2.10.3': resolution: {integrity: sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==} @@ -658,6 +667,9 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + arktype@2.0.4: + resolution: {integrity: sha512-S68rWVDnJauwH7/QCm8zCUM3aTe9Xk6oRihdcc3FSUAtxCo/q1Fwq46JhcwB5Ufv1YStwdQRz+00Y/URlvbhAQ==} + array-iterate@2.0.1: resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} @@ -1675,6 +1687,12 @@ packages: snapshots: + '@ark/schema@0.39.0': + dependencies: + '@ark/util': 0.39.0 + + '@ark/util@0.39.0': {} + '@astrojs/compiler@2.10.3': {} '@astrojs/internal-helpers@0.5.0': {} @@ -2153,6 +2171,11 @@ snapshots: aria-query@5.3.2: {} + arktype@2.0.4: + dependencies: + '@ark/schema': 0.39.0 + '@ark/util': 0.39.0 + array-iterate@2.0.1: {} astro@5.2.3(rollup@4.28.1)(sass@1.83.0)(typescript@5.7.2): diff --git a/src/slides/flexbox/index.astro b/src/slides/flexbox/index.astro index 22f83da..14ee66c 100644 --- a/src/slides/flexbox/index.astro +++ b/src/slides/flexbox/index.astro @@ -1,8 +1,8 @@ --- -export const title = "CSS Flexbox" -export const authors = ["Henrique Ramos"] -export const publishedAt = "2025-01-27" -export const description = "Do you even flex?" +export const title = "CSS Flexbox"; +export const authors = ["Henrique Ramos"]; +export const publishedAt = "2025-01-27"; +export const description = "Do you even flex?"; ---
diff --git a/src/utils/getAstroPages.ts b/src/utils/getAstroPages.ts index 27732fc..011114c 100644 --- a/src/utils/getAstroPages.ts +++ b/src/utils/getAstroPages.ts @@ -1,8 +1,9 @@ import type { AstroInstance } from "astro"; +import { type } from "arktype"; type Opts> = { files: Record; - requiredFields?: string[]; + schema: type; }; /** @@ -14,16 +15,12 @@ type Opts> = { */ const getAstroPages = & AstroInstance>({ files, - requiredFields = [], + schema, }: Opts) => Object.values(files).map((module) => { - if (!requiredFields.every((field) => module[field as keyof T])) { - throw new Error( - `Missing required fields for ${module.file}: ${requiredFields - .filter((field) => !module[field as keyof T]) - .join(", ")}`, - ); - } + const validate = schema(module); + if (validate instanceof type.errors) + return console.error(`Invalid module${module.file}: ${validate.summary}`); return { id: ( diff --git a/src/utils/getSlides.ts b/src/utils/getSlides.ts index 6a583d2..2dab6ee 100644 --- a/src/utils/getSlides.ts +++ b/src/utils/getSlides.ts @@ -1,5 +1,6 @@ import type { AstroInstance } from "astro"; import getAstroPages from "./getAstroPages"; +import { type } from "arktype"; type Slide = AstroInstance & { [key: string]: unknown; @@ -9,8 +10,7 @@ type Slide = AstroInstance & { publishedAt: string; }; -const slideRequiredFields = ["title", "description", "authors", "publishedAt"]; - +/** /** * Get all slides from the slides directory. * @returns The slides. @@ -21,5 +21,10 @@ export const getSlides = () => ["@slides/**/index.astro", "@slides/*.astro"], { eager: true }, ), - requiredFields: slideRequiredFields, + schema: type({ + title: "string", + description: "string", + authors: "string[]", + publishedAt: "string", + }), }); diff --git a/tsconfig.json b/tsconfig.json index 8d16c2e..27d8754 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,10 @@ }, "moduleResolution": "Bundler", "strictNullChecks": true, - "allowJs": true + "allowJs": true, + "strict": true, + "skipLibCheck": true, + "exactOptionalPropertyTypes": true }, "exclude": ["dist"] }