diff --git a/package-lock.json b/package-lock.json index 36a7367..ea12a2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,9 +16,7 @@ "monaco-editor": "^0.49.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-icons": "^5.2.0", - "zod": "^3.23.8", - "zod-error": "^1.5.0" + "react-icons": "^5.2.0" }, "devDependencies": { "@types/react": "^18.3.3", @@ -2244,24 +2242,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" - }, - "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-error": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/zod-error/-/zod-error-1.5.0.tgz", - "integrity": "sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ==", - "license": "MIT", - "dependencies": { - "zod": "^3.20.2" - } } } } diff --git a/package.json b/package.json index 032d883..d17bcaf 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,7 @@ "monaco-editor": "^0.49.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-icons": "^5.2.0", - "zod": "^3.23.8", - "zod-error": "^1.5.0" + "react-icons": "^5.2.0" }, "devDependencies": { "@types/react": "^18.3.3", diff --git a/src/App.tsx b/src/App.tsx index 6d3a9e6..c90deb1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,5 @@ import { ActionIcon, - Badge, Box, Button, Flex, @@ -8,23 +7,27 @@ import { useMantineTheme, } from '@mantine/core' import {notifications} from '@mantine/notifications' -import Editor, {loader} from '@monaco-editor/react' +import Editor, {Monaco, loader, useMonaco} from '@monaco-editor/react' import LZString from 'lz-string' import {editor} from 'monaco-editor' -import {useState} from 'react' +import {useEffect, useState} from 'react' import {FiAlertCircle, FiLink} from 'react-icons/fi' import {LuEraser} from 'react-icons/lu' -import {ZodSchema, z} from 'zod' -import zodTypes from '../node_modules/zod/lib/types.d.ts?raw' -import {dependencies} from '../package.json' import classes from './App.module.css' import {CopyButton} from './features/CopyButton' import {Validation} from './features/ValueEditor/ValueEditor' -import {AppData, appDataSchema} from './types' +import {VersionPicker} from './features/VersionPicker/VersionPicker' import {Header} from './ui/Header/Header' +import * as zod from './zod' -const ZOD_VERSION = dependencies.zod.split('^')[1] +type AppData = { + schema: string + values: string[] + version: string +} + +const ZOD_DEFAULT_VERSION = (await zod.getVersions('latest'))[0] const editorOptions: editor.IStandaloneEditorConstructionOptions = { minimap: {enabled: false}, @@ -46,14 +49,10 @@ const editorOptions: editor.IStandaloneEditorConstructionOptions = { renderLineHighlight: 'none', } -loader.init().then((monaco) => { - monaco.languages.typescript.typescriptDefaults.addExtraLib( - `declare namespace z{${zodTypes}}`, - ) - monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({ - noSemanticValidation: true, - noSyntaxValidation: true, - }) +const monaco = await loader.init() +monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({ + noSemanticValidation: true, + noSyntaxValidation: true, }) const getAppDataFromSearchParams = (): AppData => { @@ -64,13 +63,14 @@ const getAppDataFromSearchParams = (): AppData => { return { schema: '', values: [], + version: ZOD_DEFAULT_VERSION, } const decompressedAppData = LZString.decompressFromEncodedURIComponent(compressedAppData) const appData = JSON.parse(decompressedAppData) - return appDataSchema.parse(appData) + return appData } const getURLwithAppData = (appData: AppData): string => { @@ -83,24 +83,6 @@ const getURLwithAppData = (appData: AppData): string => { return `${window.location.protocol}//${window.location.host}?${queryParams}` } -const schemaSchema = z - .string() - .min(2) - .transform((s, ctx) => { - try { - return eval(s) - } catch (e) { - const errorMessage = e instanceof Error ? e.message : 'Invalid schema' - - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: errorMessage, - }) - return z.NEVER - } - }) - .pipe(z.custom()) - const sampleZodSchema = `z.object({ name: z.string(), birth_year: z.number().optional() @@ -110,15 +92,14 @@ const sampleValue = '{name: "John"}' const appData = getAppDataFromSearchParams() -const evaluateSchema = (schema: string) => { - try { - const evaluatedSchema = schemaSchema.parse(schema) - return {evaluatedSchema} - } catch (e) { - if (e instanceof z.ZodError) return {error: e.message} +const setMonacoDeclarationTypes = async (monaco: Monaco, ver: string) => { + const declarationTypes = await zod.getDeclarationTypes(ver) - return {error: 'Invalid schema'} - } + monaco.languages.typescript.typescriptDefaults.setExtraLibs([ + { + content: `declare namespace z{${declarationTypes}}`, + }, + ]) } const App = () => { @@ -130,10 +111,29 @@ const App = () => { return appData.values.length ? appData.values : [sampleValue] }) - const {evaluatedSchema, error: schemaError} = evaluateSchema(schema) + const [isLoading, setIsLoading] = useState(false) + + const [version, setVersion] = useState(appData.version || ZOD_DEFAULT_VERSION) + + const monaco = useMonaco() + + const {data: evaluatedSchema, error: schemaError} = zod.validateSchema(schema) const theme = useMantineTheme() + useEffect(() => { + if (isLoading || !monaco) return + + async function updateVersion(monaco: Monaco, ver: string) { + setIsLoading(true) + await zod.setVersion(ver) + await setMonacoDeclarationTypes(monaco, ver) + setIsLoading(false) + } + + updateVersion(monaco, version) + }, [version, monaco]) + return (
@@ -147,6 +147,7 @@ const App = () => { const urlWithAppData = getURLwithAppData({ schema, values: values.filter((value) => typeof value == 'string'), + version, }) navigator.clipboard.writeText(urlWithAppData) notifications.show({ @@ -172,9 +173,13 @@ const App = () => { > Zod schema - - v{ZOD_VERSION} - + { + setVersion(ver) + }} + disabled={isLoading} + />