diff --git a/examples/react/arktype/.eslintrc.cjs b/examples/react/arktype/.eslintrc.cjs new file mode 100644 index 000000000..35853b617 --- /dev/null +++ b/examples/react/arktype/.eslintrc.cjs @@ -0,0 +1,11 @@ +// @ts-check + +/** @type {import('eslint').Linter.Config} */ +const config = { + extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], + rules: { + 'react/no-children-prop': 'off', + }, +} + +module.exports = config diff --git a/examples/react/arktype/.gitignore b/examples/react/arktype/.gitignore new file mode 100644 index 000000000..4673b022e --- /dev/null +++ b/examples/react/arktype/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +pnpm-lock.yaml +yarn.lock +package-lock.json + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/examples/react/arktype/README.md b/examples/react/arktype/README.md new file mode 100644 index 000000000..1cf889265 --- /dev/null +++ b/examples/react/arktype/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run dev` diff --git a/examples/react/arktype/index.html b/examples/react/arktype/index.html new file mode 100644 index 000000000..7415713d8 --- /dev/null +++ b/examples/react/arktype/index.html @@ -0,0 +1,16 @@ + + + + + + + + + TanStack Form React Valibot Example App + + + +
+ + + diff --git a/examples/react/arktype/package.json b/examples/react/arktype/package.json new file mode 100644 index 000000000..1c9e7e898 --- /dev/null +++ b/examples/react/arktype/package.json @@ -0,0 +1,37 @@ +{ + "name": "@tanstack/form-example-react-arktype", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --port=3001", + "build": "vite build", + "preview": "vite preview", + "test:types": "tsc" + }, + "dependencies": { + "@tanstack/arktype-form-adapter": "^0.28.0", + "@tanstack/react-form": "^0.29.1", + "arktype": "2.0.0-beta.5", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "valibot": "^0.37.0" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "vite": "^5.4.0" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/examples/react/arktype/public/emblem-light.svg b/examples/react/arktype/public/emblem-light.svg new file mode 100644 index 000000000..a58e69ad5 --- /dev/null +++ b/examples/react/arktype/public/emblem-light.svg @@ -0,0 +1,13 @@ + + + + emblem-light + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/examples/react/arktype/src/index.tsx b/examples/react/arktype/src/index.tsx new file mode 100644 index 000000000..65950bda0 --- /dev/null +++ b/examples/react/arktype/src/index.tsx @@ -0,0 +1,104 @@ +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import { useForm } from '@tanstack/react-form' +import { arktype, arktypeValidator } from '@tanstack/arktype-form-adapter' +import type { FieldApi } from '@tanstack/react-form' + +function FieldInfo({ field }: { field: FieldApi }) { + return ( + <> + {field.state.meta.isTouched && field.state.meta.errors.length ? ( + {field.state.meta.errors.join(',')} + ) : null} + {field.state.meta.isValidating ? 'Validating...' : null} + + ) +} + +export default function App() { + const form = useForm({ + defaultValues: { + firstName: '', + lastName: '', + }, + onSubmit: async ({ value }) => { + // Do something with form data + console.log(value) + }, + // Add a validator to support Arktype usage in Form and Field + validatorAdapter: arktypeValidator(), + }) + + return ( +
+

Valibot Form Example

+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > +
+ {/* A type-safe field component*/} + 2'), + }} + children={(field) => { + // Avoid hasty abstractions. Render props are great! + return ( + <> + + field.handleChange(e.target.value)} + /> + + + ) + }} + /> +
+
+ ( + <> + + field.handleChange(e.target.value)} + /> + + + )} + /> +
+ [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + + )} + /> + +
+ ) +} + +const rootElement = document.getElementById('root')! + +createRoot(rootElement).render( + + + , +) diff --git a/examples/react/arktype/tsconfig.json b/examples/react/arktype/tsconfig.json new file mode 100644 index 000000000..22b43163b --- /dev/null +++ b/examples/react/arktype/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/packages/arktype-form-adapter/eslint.config.js b/packages/arktype-form-adapter/eslint.config.js new file mode 100644 index 000000000..8ce6ad05f --- /dev/null +++ b/packages/arktype-form-adapter/eslint.config.js @@ -0,0 +1,5 @@ +// @ts-check + +import rootConfig from '../../eslint.config.js' + +export default [...rootConfig] diff --git a/packages/arktype-form-adapter/package.json b/packages/arktype-form-adapter/package.json new file mode 100644 index 000000000..a64a08554 --- /dev/null +++ b/packages/arktype-form-adapter/package.json @@ -0,0 +1,63 @@ +{ + "name": "@tanstack/arktype-form-adapter", + "version": "0.28.0", + "description": "The Arktype adapter for TanStack Form.", + "author": "tannerlinsley", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/TanStack/form.git", + "directory": "packages/zod-form-adapter" + }, + "homepage": "https://tanstack.com/form", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "scripts": { + "clean": "rimraf ./dist && rimraf ./coverage", + "test:eslint": "eslint ./src ./tests", + "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", + "test:types:ts49": "node ../../node_modules/typescript49/lib/tsc.js -p tsconfig.legacy.json", + "test:types:ts50": "node ../../node_modules/typescript50/lib/tsc.js", + "test:types:ts51": "node ../../node_modules/typescript51/lib/tsc.js", + "test:types:ts52": "node ../../node_modules/typescript52/lib/tsc.js", + "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js", + "test:types:ts54": "tsc", + "test:lib": "vitest", + "test:lib:dev": "pnpm run test:lib --watch", + "test:build": "publint --strict", + "build": "vite build" + }, + "type": "module", + "types": "dist/esm/index.d.ts", + "main": "dist/cjs/index.cjs", + "module": "dist/esm/index.js", + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.cts", + "default": "./dist/cjs/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "files": [ + "dist", + "src" + ], + "dependencies": { + "@tanstack/form-core": "workspace:*" + }, + "devDependencies": { + "arktype": "2.0.0-beta.5" + }, + "peerDependencies": { + "arktype": "^2.x" + } +} diff --git a/packages/arktype-form-adapter/src/index.ts b/packages/arktype-form-adapter/src/index.ts new file mode 100644 index 000000000..26e40beb9 --- /dev/null +++ b/packages/arktype-form-adapter/src/index.ts @@ -0,0 +1 @@ +export * from './validator' diff --git a/packages/arktype-form-adapter/src/validator.ts b/packages/arktype-form-adapter/src/validator.ts new file mode 100644 index 000000000..7416218b1 --- /dev/null +++ b/packages/arktype-form-adapter/src/validator.ts @@ -0,0 +1,59 @@ +import { type } from 'arktype' +import type { TypeParser } from 'arktype/internal/type.js' +import type { ValidationError, Validator } from '@tanstack/form-core' +import type { ArkErrors, Type, inferAmbient, validateAmbient } from 'arktype' +import type { inferred } from 'arktype/internal/ast.js' + +type Params = { + transformErrors?: (errors: ArkErrors) => ValidationError +} + +export const arktypeValidator = (params: Params = {}) => + (() => { + return { + validate({ value }, fn) { + console.log(fn, 'XD') + // Call Arktype on the value here and return the error message + const result = fn.type(value) + + console.log(result) + + if (result instanceof type.errors) { + if (params.transformErrors) { + return params.transformErrors(result) + } + + return result.summary + } + + return + }, + async validateAsync({ value }, fn): Promise { + console.log(fn, 'XD') + + // Call Arktype on the value here and return the error message + const result = fn.type(value) + + if (result instanceof type.errors) { + if (params.transformErrors) { + return params.transformErrors(result) + } + + return result.summary + } + + return + }, + } + }) as Validator + +export type cast = { + [inferred]?: t + wow: TypeParser<{}> +} + +export type ParseType = (def: validateAmbient) => { + type: Type> +} + +export const arktype: ParseType = (v) => ({ type: type(v) }) diff --git a/packages/arktype-form-adapter/tests/FieldApi.spec.ts b/packages/arktype-form-adapter/tests/FieldApi.spec.ts new file mode 100644 index 000000000..503bdc608 --- /dev/null +++ b/packages/arktype-form-adapter/tests/FieldApi.spec.ts @@ -0,0 +1,161 @@ +import { describe, expect, it, vi } from 'vitest' + +import { FieldApi, FormApi } from '@tanstack/form-core' +import { type } from 'arktype' +import { arktypeValidator } from '../src/index' +import { sleep } from './utils' + +describe('arktype field api', () => { + it('should run an onChange with z.string validation', () => { + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + const field = new FieldApi({ + form, + validatorAdapter: arktypeValidator(), + name: 'name', + validators: { + onChange: type('string > 3'), + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('a') + expect(field.getMeta().errors).toEqual([ + 'You must have a length of at least 3', + ]) + field.setValue('asdf') + expect(field.getMeta().errors).toEqual([]) + }) + + it('should run an onChange fn with zod validation option enabled', () => { + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + const field = new FieldApi({ + form, + validatorAdapter: arktypeValidator(), + name: 'name', + validators: { + onChange: ({ value }) => (value === 'a' ? 'Test' : undefined), + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('a') + expect(field.getMeta().errors).toEqual(['Test']) + field.setValue('asdf') + expect(field.getMeta().errors).toEqual([]) + }) + + it('should run an onChangeAsync with z.string validation', async () => { + vi.useFakeTimers() + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + const field = new FieldApi({ + form, + validatorAdapter: arktypeValidator(), + name: 'name', + validators: { + onChangeAsync: z.string().refine( + async (val) => { + await sleep(1) + return val.length > 3 + }, + { + message: 'Testing 123', + }, + ), + onChangeAsyncDebounceMs: 0, + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('a') + await vi.advanceTimersByTimeAsync(10) + expect(field.getMeta().errors).toEqual(['Testing 123']) + field.setValue('asdf') + await vi.advanceTimersByTimeAsync(10) + expect(field.getMeta().errors).toEqual([]) + }) + + it('should run an onChangeAsyc fn with zod validation option enabled', async () => { + vi.useFakeTimers() + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + const field = new FieldApi({ + form, + validatorAdapter: arktypeValidator(), + name: 'name', + validators: { + onChangeAsync: async ({ value }) => { + await sleep(1) + return value === 'a' ? 'Test' : undefined + }, + onChangeAsyncDebounceMs: 0, + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('a') + await vi.advanceTimersByTimeAsync(10) + expect(field.getMeta().errors).toEqual(['Test']) + field.setValue('asdf') + await vi.advanceTimersByTimeAsync(10) + expect(field.getMeta().errors).toEqual([]) + }) + + it('should transform errors to display only the first error message', () => { + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + const field = new FieldApi({ + form, + validatorAdapter: arktypeValidator({ + transformErrors: (errors) => errors[0]?.message, + }), + name: 'name', + validators: { + onChange: z + .string() + .min(3, 'You must have a length of at least 3') + .uuid('UUID'), + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('aa') + expect(field.getMeta().errors).toEqual([ + 'You must have a length of at least 3', + ]) + field.setValue('aaa') + expect(field.getMeta().errors).toEqual(['UUID']) + }) +}) diff --git a/packages/arktype-form-adapter/tests/FieldApi.test-d.ts b/packages/arktype-form-adapter/tests/FieldApi.test-d.ts new file mode 100644 index 000000000..65c5bcee4 --- /dev/null +++ b/packages/arktype-form-adapter/tests/FieldApi.test-d.ts @@ -0,0 +1,105 @@ +import { type } from 'arktype' +import { FieldApi, FormApi } from '@tanstack/form-core' +import { assertType, it } from 'vitest' +import { arktypeValidator } from '../src/index' + +it('should allow a Zod validator to be passed in', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validatorAdapter: arktypeValidator(), + }) +}) + +it('should allow a Zod validator to handle the correct Zod type', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validatorAdapter: arktypeValidator(), + validators: { + onChange: type('string'), + }, + }) +}) + +it('should allow a Zod validator to handle the correct Zod type for an async method', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validatorAdapter: arktypeValidator(), + validators: { + onChangeAsync: type('string'), + }, + }) +}) + +it('should allow a functional onChange to be passed when using a validator', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validatorAdapter: arktypeValidator(), + validators: { + onChange: ({ value }) => { + assertType<'test'>(value) + return undefined + }, + }, + }) +}) + +it('should not allow a validator onChange to be passed when not using a validator', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + // @ts-expect-error Requires a validator + onChange: type('string'), + }) +}) + +// This is not possible without higher-kinded types AFAIK +it.skip('should allow not a Zod validator with the wrong Zod type', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validatorAdapter: arktypeValidator(), + validators: { + onChange: type('object'), + }, + }) +}) diff --git a/packages/arktype-form-adapter/tests/FormApi.spec.ts b/packages/arktype-form-adapter/tests/FormApi.spec.ts new file mode 100644 index 000000000..afd76b993 --- /dev/null +++ b/packages/arktype-form-adapter/tests/FormApi.spec.ts @@ -0,0 +1,59 @@ +import { describe, expect, it } from 'vitest' + +import { FieldApi, FormApi } from '@tanstack/form-core' +import { type } from 'arktype' +import { arktypeValidator } from '../src/index' + +describe('zod form api', () => { + it('should run an onChange with z.string validation', () => { + const form = new FormApi({ + defaultValues: { + name: '', + }, + validatorAdapter: arktypeValidator(), + }) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChange: type('string > 2'), + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('a') + expect(field.getMeta().errors).toEqual([ + 'You must have a length of at least 3', + ]) + field.setValue('asdf') + expect(field.getMeta().errors).toEqual([]) + }) + + it('should run an onChange fn with zod validation option enabled', () => { + const form = new FormApi({ + defaultValues: { + name: '', + }, + validatorAdapter: arktypeValidator(), + }) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChange: ({ value }) => (value === 'a' ? 'Test' : undefined), + }, + }) + + field.mount() + + expect(field.getMeta().errors).toEqual([]) + field.setValue('a') + expect(field.getMeta().errors).toEqual(['Test']) + field.setValue('asdf') + expect(field.getMeta().errors).toEqual([]) + }) +}) diff --git a/packages/arktype-form-adapter/tests/FormApi.test-d.ts b/packages/arktype-form-adapter/tests/FormApi.test-d.ts new file mode 100644 index 000000000..d4422dd26 --- /dev/null +++ b/packages/arktype-form-adapter/tests/FormApi.test-d.ts @@ -0,0 +1,100 @@ +import { FieldApi, FormApi } from '@tanstack/form-core' +import { assertType, it } from 'vitest' +import { type } from 'arktype' +import { arktypeValidator } from '../src/index' + +it('should allow a Zod validator to be passed in', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validatorAdapter: arktypeValidator(), + } as const) +}) + +it('should allow a Zod validator to handle the correct Zod type', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validatorAdapter: arktypeValidator(), + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChange: type('string'), + }, + }) +}) + +it('should allow a Zod validator to handle the correct Zod type on async methods', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validatorAdapter: arktypeValidator(), + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChangeAsync: type('string'), + }, + }) +}) + +it('should allow a functional onChange to be passed when using a validator', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validatorAdapter: arktypeValidator(), + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChange: ({ value }) => { + assertType<'test'>(value) + return undefined + }, + }, + }) +}) + +it('should not allow a validator onChange to be passed when not using a validator', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + // @ts-expect-error Requires a validator + onChange: type('string'), + }) +}) + +// This is not possible without higher-kinded types AFAIK +it.skip('should allow not a Zod validator with the wrong Zod type', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validatorAdapter: arktypeValidator(), + validators: { + onChange: type('object'), + }, + }) +}) diff --git a/packages/arktype-form-adapter/tests/utils.ts b/packages/arktype-form-adapter/tests/utils.ts new file mode 100644 index 000000000..1a3a619a2 --- /dev/null +++ b/packages/arktype-form-adapter/tests/utils.ts @@ -0,0 +1,5 @@ +export function sleep(timeout: number): Promise { + return new Promise((resolve, _reject) => { + setTimeout(resolve, timeout) + }) +} diff --git a/packages/arktype-form-adapter/tsconfig.json b/packages/arktype-form-adapter/tsconfig.json new file mode 100644 index 000000000..1b201bda7 --- /dev/null +++ b/packages/arktype-form-adapter/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "moduleResolution": "Bundler", + "paths": { + "@tanstack/form-core": ["../form-core/src"] + } + }, + "include": ["src", "tests", "eslint.config.js", "vite.config.ts"] +} diff --git a/packages/arktype-form-adapter/tsconfig.legacy.json b/packages/arktype-form-adapter/tsconfig.legacy.json new file mode 100644 index 000000000..c9bf46d6c --- /dev/null +++ b/packages/arktype-form-adapter/tsconfig.legacy.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "paths": { + "@tanstack/form-core": ["../form-core/src"] + } + }, + "include": ["src"] +} diff --git a/packages/arktype-form-adapter/vite.config.ts b/packages/arktype-form-adapter/vite.config.ts new file mode 100644 index 000000000..6334a53d9 --- /dev/null +++ b/packages/arktype-form-adapter/vite.config.ts @@ -0,0 +1,22 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/config/vite' +import packageJson from './package.json' + +const config = defineConfig({ + test: { + name: packageJson.name, + dir: './tests', + watch: false, + environment: 'jsdom', + coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] }, + typecheck: { enabled: true }, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ + entry: './src/index.ts', + srcDir: './src', + }), +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3d29a5ab..8e0b9ecbc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -412,6 +412,40 @@ importers: specifier: ^5.4.0 version: 5.4.0(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1) + examples/react/arktype: + dependencies: + '@tanstack/arktype-form-adapter': + specifier: ^0.28.0 + version: link:../../../packages/arktype-form-adapter + '@tanstack/react-form': + specifier: ^0.29.1 + version: link:../../../packages/react-form + arktype: + specifier: 2.0.0-beta.5 + version: 2.0.0-beta.5 + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + valibot: + specifier: ^0.37.0 + version: 0.37.0(typescript@5.4.2) + devDependencies: + '@types/react': + specifier: ^18.3.3 + version: 18.3.3 + '@types/react-dom': + specifier: ^18.3.0 + version: 18.3.0 + '@vitejs/plugin-react': + specifier: ^4.3.1 + version: 4.3.1(vite@5.4.0(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) + vite: + specifier: ^5.4.0 + version: 5.4.0(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1) + examples/react/array: dependencies: '@tanstack/react-form': @@ -1017,6 +1051,16 @@ importers: specifier: ^0.14.10 version: 0.14.10 + packages/arktype-form-adapter: + dependencies: + '@tanstack/form-core': + specifier: workspace:* + version: link:../form-core + devDependencies: + arktype: + specifier: 2.0.0-beta.5 + version: 2.0.0-beta.5 + packages/form-core: dependencies: '@tanstack/store': @@ -1302,6 +1346,12 @@ packages: '@angular/platform-browser': 17.3.12 rxjs: ^6.5.3 || ^7.4.0 + '@ark/schema@0.3.2': + resolution: {integrity: sha512-StWlBec++TxgDgpEUAkOxB7rqCZmOJr1dsW0P44vcgoitGtlQN13eCW1MlHlzScTUWA5iOtyHD+TsA0gKm4X0w==} + + '@ark/util@0.2.1': + resolution: {integrity: sha512-V+h43ZoXCT79K0OiwRE7oebcIeVHZ8YL/Xf0mCUCoIEuWnAJOS8zPwQzwGJGwys7MFHgn3YQYWL/nETuEvgcpQ==} + '@babel/code-frame@7.24.7': resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} @@ -4550,6 +4600,9 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + arktype@2.0.0-beta.5: + resolution: {integrity: sha512-3bNUyiA2iuvyV/rfiErLli9HrrvC6W4XT8Ja6SAEihljM60PRQhYJEr5jM4MGGtj1k/oFxgOkHd++VjQrm6SoA==} + array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} @@ -9417,7 +9470,7 @@ snapshots: '@babel/preset-env': 7.24.0(@babel/core@7.24.0) '@babel/runtime': 7.24.0 '@discoveryjs/json-ext': 0.5.7 - '@ngtools/webpack': 17.3.8(@angular/compiler-cli@17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2))(typescript@5.4.2)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)) + '@ngtools/webpack': 17.3.8(@angular/compiler-cli@17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2))(typescript@5.4.2)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.1.7(@types/node@20.14.10)(less@4.2.0)(sass@1.71.1)(sugarss@4.0.1(postcss@8.4.35))(terser@5.29.1)) ansi-colors: 4.1.3 autoprefixer: 10.4.18(postcss@8.4.35) @@ -9506,7 +9559,7 @@ snapshots: '@babel/preset-env': 7.24.0(@babel/core@7.24.0) '@babel/runtime': 7.24.0 '@discoveryjs/json-ext': 0.5.7 - '@ngtools/webpack': 17.3.8(@angular/compiler-cli@17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2))(typescript@5.4.2)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)) + '@ngtools/webpack': 17.3.8(@angular/compiler-cli@17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2))(typescript@5.4.2)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.1.7(@types/node@20.14.10)(less@4.2.0)(sass@1.71.1)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) ansi-colors: 4.1.3 autoprefixer: 10.4.18(postcss@8.4.35) @@ -9551,7 +9604,7 @@ snapshots: undici: 6.11.1 vite: 5.1.7(@types/node@20.14.10)(less@4.2.0)(sass@1.71.1)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1) watchpack: 2.4.0 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) webpack-dev-middleware: 6.1.2(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) webpack-dev-server: 4.15.1(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) webpack-merge: 5.10.0 @@ -9582,7 +9635,7 @@ snapshots: dependencies: '@angular-devkit/architect': 0.1703.8(chokidar@3.6.0) rxjs: 7.8.1 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) webpack-dev-server: 4.15.1(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) transitivePeerDependencies: - chokidar @@ -9703,6 +9756,12 @@ snapshots: rxjs: 7.8.1 tslib: 2.6.3 + '@ark/schema@0.3.2': + dependencies: + '@ark/util': 0.2.1 + + '@ark/util@0.2.1': {} + '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 @@ -11461,6 +11520,12 @@ snapshots: '@next/swc-win32-x64-msvc@15.0.0-rc.0': optional: true + '@ngtools/webpack@17.3.8(@angular/compiler-cli@17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2))(typescript@5.4.2)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1))': + dependencies: + '@angular/compiler-cli': 17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2) + typescript: 5.4.2 + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) + '@ngtools/webpack@17.3.8(@angular/compiler-cli@17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2))(typescript@5.4.2)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5))': dependencies: '@angular/compiler-cli': 17.3.12(@angular/compiler@17.3.12(@angular/core@17.3.12(rxjs@7.8.1)(zone.js@0.14.10)))(typescript@5.4.2) @@ -12305,8 +12370,8 @@ snapshots: '@types/jsesc': 3.0.3 '@vinxi/react': 0.2.3 '@vinxi/react-server-dom': 0.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(vite@5.4.0(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) - '@vinxi/server-components': 0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) - '@vinxi/server-functions': 0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) + '@vinxi/server-components': 0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) + '@vinxi/server-functions': 0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) import-meta-resolve: 4.1.0 isbot: 5.1.14 jsesc: 3.0.2 @@ -12784,7 +12849,7 @@ snapshots: transitivePeerDependencies: - uWebSockets.js - '@vinxi/plugin-directives@0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1))': + '@vinxi/plugin-directives@0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1))': dependencies: '@babel/parser': 7.25.3 acorn: 8.12.1 @@ -12806,9 +12871,9 @@ snapshots: '@vinxi/react@0.2.3': {} - '@vinxi/server-components@0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1))': + '@vinxi/server-components@0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1))': dependencies: - '@vinxi/plugin-directives': 0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) + '@vinxi/plugin-directives': 0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) acorn: 8.12.1 acorn-loose: 8.4.0 acorn-typescript: 1.4.13(acorn@8.12.1) @@ -12817,9 +12882,9 @@ snapshots: recast: 0.23.9 vinxi: 0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1) - '@vinxi/server-functions@0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1))': + '@vinxi/server-functions@0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1))': dependencies: - '@vinxi/plugin-directives': 0.4.1(vinxi@0.4.1(@types/node@20.14.10)(less@4.2.0)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) + '@vinxi/plugin-directives': 0.4.1(vinxi@0.4.1(@opentelemetry/api@1.9.0)(@types/node@20.14.10)(encoding@0.1.13)(ioredis@5.4.1)(less@4.2.0)(magicast@0.3.4)(sass@1.72.0)(sugarss@4.0.1(postcss@8.4.41))(terser@5.29.1)) acorn: 8.12.1 acorn-loose: 8.4.0 acorn-typescript: 1.4.13(acorn@8.12.1) @@ -13317,6 +13382,11 @@ snapshots: dependencies: dequal: 2.0.3 + arktype@2.0.0-beta.5: + dependencies: + '@ark/schema': 0.3.2 + '@ark/util': 0.2.1 + array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 @@ -13386,7 +13456,7 @@ snapshots: '@babel/core': 7.24.0 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) babel-plugin-add-module-exports@0.2.1: {} @@ -13838,7 +13908,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) core-js-compat@3.37.1: dependencies: @@ -13907,7 +13977,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) css-select@5.1.0: dependencies: @@ -15682,7 +15752,7 @@ snapshots: dependencies: klona: 2.0.6 less: 4.2.0 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) less@4.2.0: dependencies: @@ -15707,7 +15777,7 @@ snapshots: dependencies: webpack-sources: 3.2.3 optionalDependencies: - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) liftoff@5.0.0: dependencies: @@ -15966,7 +16036,7 @@ snapshots: dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) minimalistic-assert@1.0.1: {} @@ -16755,7 +16825,7 @@ snapshots: postcss: 8.4.35 semver: 7.6.3 optionalDependencies: - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) transitivePeerDependencies: - typescript @@ -17268,7 +17338,7 @@ snapshots: neo-async: 2.6.2 optionalDependencies: sass: 1.71.1 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) sass@1.71.1: dependencies: @@ -17579,7 +17649,7 @@ snapshots: dependencies: iconv-lite: 0.6.3 source-map-js: 1.2.0 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) source-map-support@0.5.21: dependencies: @@ -17794,7 +17864,19 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - terser-webpack-plugin@5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)): + terser-webpack-plugin@5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.29.1 + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) + optionalDependencies: + '@swc/core': 1.6.13(@swc/helpers@0.5.11) + esbuild: 0.20.1 + + terser-webpack-plugin@5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 @@ -18487,7 +18569,7 @@ snapshots: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) webpack-dev-middleware@6.1.2(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)): dependencies: @@ -18497,7 +18579,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) webpack-dev-server@4.15.1(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)): dependencies: @@ -18532,7 +18614,7 @@ snapshots: webpack-dev-middleware: 5.3.3(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) ws: 8.18.0 optionalDependencies: - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) transitivePeerDependencies: - bufferutil - debug @@ -18550,10 +18632,41 @@ snapshots: webpack-subresource-integrity@5.1.0(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)): dependencies: typed-assert: 1.0.9 - webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5) + webpack: 5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1) webpack-virtual-modules@0.6.2: {} + webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.12.1 + acorn-import-assertions: 1.9.0(acorn@8.12.1) + browserslist: 4.23.2 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.4.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5): dependencies: '@types/eslint-scope': 3.7.7 @@ -18577,7 +18690,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)) + terser-webpack-plugin: 5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.21.5)(webpack@5.90.3(@swc/core@1.6.13(@swc/helpers@0.5.11))(esbuild@0.20.1)) watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: