From 379e0e3e0f1ef9640e18b100434feed701a0cbe7 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Mon, 8 Dec 2025 17:17:27 +0100 Subject: [PATCH 1/2] Remove Inertia packages --- .github/dependabot.yml | 14 -- bin/release | 2 - package.json | 4 +- packages/react-inertia/.gitignore | 2 - packages/react-inertia/LICENSE.md | 21 -- packages/react-inertia/README.md | 31 --- packages/react-inertia/package.json | 46 ---- packages/react-inertia/src/index.ts | 220 ------------------ packages/react-inertia/src/types.ts | 32 --- packages/react-inertia/tests/index.test.ts | 235 ------------------- packages/react-inertia/tsconfig.json | 15 -- packages/react-inertia/vitest.config.ts | 7 - packages/vue-inertia/.gitignore | 2 - packages/vue-inertia/LICENSE.md | 21 -- packages/vue-inertia/README.md | 31 --- packages/vue-inertia/package.json | 43 ---- packages/vue-inertia/src/index.ts | 230 ------------------- packages/vue-inertia/src/types.ts | 31 --- packages/vue-inertia/tests/index.test.ts | 249 --------------------- packages/vue-inertia/tsconfig.json | 19 -- 20 files changed, 1 insertion(+), 1254 deletions(-) delete mode 100644 packages/react-inertia/.gitignore delete mode 100644 packages/react-inertia/LICENSE.md delete mode 100644 packages/react-inertia/README.md delete mode 100644 packages/react-inertia/package.json delete mode 100644 packages/react-inertia/src/index.ts delete mode 100644 packages/react-inertia/src/types.ts delete mode 100644 packages/react-inertia/tests/index.test.ts delete mode 100644 packages/react-inertia/tsconfig.json delete mode 100644 packages/react-inertia/vitest.config.ts delete mode 100644 packages/vue-inertia/.gitignore delete mode 100644 packages/vue-inertia/LICENSE.md delete mode 100644 packages/vue-inertia/README.md delete mode 100644 packages/vue-inertia/package.json delete mode 100644 packages/vue-inertia/src/index.ts delete mode 100644 packages/vue-inertia/src/types.ts delete mode 100644 packages/vue-inertia/tests/index.test.ts delete mode 100644 packages/vue-inertia/tsconfig.json diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d1687ba..fecd1ab 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -29,23 +29,9 @@ updates: # Only open pull requests for security updates... open-pull-requests-limit: 0 - - package-ecosystem: "npm" - directory: "/packages/react-inertia" - schedule: - interval: "daily" - # Only open pull requests for security updates... - open-pull-requests-limit: 0 - - package-ecosystem: "npm" directory: "/packages/vue" schedule: interval: "daily" # Only open pull requests for security updates... open-pull-requests-limit: 0 - - - package-ecosystem: "npm" - directory: "/packages/vue-inertia" - schedule: - interval: "daily" - # Only open pull requests for security updates... - open-pull-requests-limit: 0 diff --git a/bin/release b/bin/release index 472f07c..d9df572 100755 --- a/bin/release +++ b/bin/release @@ -13,7 +13,5 @@ fi npm version $1 \ --workspace=packages/core \ --workspace=packages/react \ - --workspace=packages/react-inertia \ --workspace=packages/vue \ - --workspace=packages/vue-inertia \ --workspace=packages/alpine diff --git a/package.json b/package.json index ff11e35..0e26e66 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,11 @@ "workspaces": [ "packages/core", "packages/react", - "packages/react-inertia", "packages/vue", - "packages/vue-inertia", "packages/alpine" ], "scripts": { - "watch": "npx concurrently \"npm run watch --workspace=packages/core\" \"npm run watch --workspace=packages/react\" \"npm run watch --workspace=packages/react-inertia\" \"npm run watch --workspace=packages/vue\" \"npm run watch --workspace=packages/vue-inertia\" \"npm run watch --workspace=packages/alpine\" --names=core,react,react-inertia,vue,vue-inertia,alpine", + "watch": "npx concurrently \"npm run watch --workspace=packages/core\" \"npm run watch --workspace=packages/react\" \"npm run watch \"npm run watch --workspace=packages/vue\" \"npm run watch \"npm run watch --workspace=packages/alpine\" --names=core,react,vue,alpine", "build": "npm run build --workspaces", "link": "npm link --workspaces", "typeCheck": "npm run typeCheck --workspaces", diff --git a/packages/react-inertia/.gitignore b/packages/react-inertia/.gitignore deleted file mode 100644 index c925c21..0000000 --- a/packages/react-inertia/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/dist -/node_modules diff --git a/packages/react-inertia/LICENSE.md b/packages/react-inertia/LICENSE.md deleted file mode 100644 index 79810c8..0000000 --- a/packages/react-inertia/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) Taylor Otwell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/packages/react-inertia/README.md b/packages/react-inertia/README.md deleted file mode 100644 index 0b20012..0000000 --- a/packages/react-inertia/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Laravel Precognition - -Test Status -Build Status -Total Downloads -Latest Stable Version -License - -## Introduction - -Laravel Precognition allows you to anticipate the outcome of a future HTTP request. One of the primary use cases of Precognition is the ability to provide "live" validation in your frontend application. - -## Official Documentation - -Documentation for Laravel Precognition can be found on the [Laravel website](https://laravel.com/docs/precognition). - -## Contributing - -Thank you for considering contributing to Laravel Precognition! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). - -## Code of Conduct - -In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). - -## Security Vulnerabilities - -Please review [our security policy](https://github.com/laravel/precognition/security/policy) on how to report security vulnerabilities. - -## License - -Laravel Precognition is open-sourced software licensed under the [MIT license](LICENSE.md). diff --git a/packages/react-inertia/package.json b/packages/react-inertia/package.json deleted file mode 100644 index cc44e3d..0000000 --- a/packages/react-inertia/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "laravel-precognition-react-inertia", - "version": "0.8.0", - "description": "Laravel Precognition (React w/ Inertia).", - "keywords": [ - "laravel", - "precognition", - "react", - "inertia" - ], - "homepage": "https://github.com/laravel/precognition", - "type": "module", - "repository": { - "type": "git", - "url": "https://github.com/laravel/precognition" - }, - "license": "MIT", - "author": "Laravel", - "main": "dist/index.js", - "files": [ - "/dist" - ], - "scripts": { - "watch": "rm -rf dist && tsc --watch --preserveWatchOutput", - "build": "rm -rf dist && tsc", - "typeCheck": "tsc --noEmit", - "prepublishOnly": "npm run build", - "test": "vitest run", - "version": "npm pkg set dependencies.laravel-precognition=$npm_package_version && npm pkg set dependencies.laravel-precognition-react=$npm_package_version" - }, - "peerDependencies": { - "@inertiajs/react": "^1.0.0 || ^2.0.0", - "react": "^18.0.0 || ^19.0.0" - }, - "dependencies": { - "laravel-precognition": "0.8.0", - "laravel-precognition-react": "0.8.0" - }, - "devDependencies": { - "@testing-library/react": "^16.3.0", - "@types/react-dom": "^18.2.4 || ^19.0.0", - "jsdom": "^27.2.0", - "typescript": "^5.0.0", - "vitest": "^2.0.5" - } -} diff --git a/packages/react-inertia/src/index.ts b/packages/react-inertia/src/index.ts deleted file mode 100644 index 865f001..0000000 --- a/packages/react-inertia/src/index.ts +++ /dev/null @@ -1,220 +0,0 @@ -import { NamedInputEvent, RequestMethod, SimpleValidationErrors, toSimpleValidationErrors, ValidationConfig, ValidationErrors, resolveUrl, resolveMethod } from 'laravel-precognition' -import { useForm as usePrecognitiveForm, client } from 'laravel-precognition-react' -import { useForm as useInertiaForm } from '@inertiajs/react' -import { FormDataKeys, FormDataType, VisitOptions } from '@inertiajs/core' -import { useRef } from 'react' -import { Form, FormDataConvertible } from './types' - -export { client, Form } - -export const useForm = >(method: RequestMethod | (() => RequestMethod), url: string | (() => string), inputs: Data, config: ValidationConfig = {}): Form => { - const booted = useRef(false) - - /** - * The Inertia form. - */ - // @ts-expect-error - const inertiaForm = useInertiaForm(inputs) - - /** - * The React form. - */ - const precognitiveForm = usePrecognitiveForm(method, url, inputs, config) - - /** - * The Inertia set defaults function. - */ - const inertiaSetDefaults = inertiaForm.setDefaults.bind(inertiaForm) - - /** - * The Inertia submit function. - */ - const inertiaSubmit = inertiaForm.submit.bind(inertiaForm) - - /** - * The Inertia reset function. - */ - const inertiaReset = inertiaForm.reset.bind(inertiaForm) - - /** - * The Inertia clear errors function. - */ - const inertiaClearErrors = inertiaForm.clearErrors.bind(inertiaForm) - - /** - * The Inertia set error function. - */ - const inertiaSetError = inertiaForm.setError.bind(inertiaForm) - - /** - * The Inertia set data function. - */ - const inertiaSetData = inertiaForm.setData.bind(inertiaForm) - - /** - * The Inertia trasform function. - */ - const inertiaTransform = inertiaForm.transform.bind(inertiaForm) - - /** - * The transform function. - */ - const transformer = useRef<(data: Data) => Data>((data) => data) - - if (! booted.current) { - /** - * Setup event listeners. - */ - precognitiveForm.validator().on('errorsChanged', () => { - inertiaClearErrors() - - inertiaSetError( - // @ts-expect-error - toSimpleValidationErrors(precognitiveForm.validator().errors()), - ) - }) - - booted.current = true - } - - /** - * Patch the form. - */ - const form = Object.assign(inertiaForm, { - validating: precognitiveForm.validating, - touched: precognitiveForm.touched, - touch(name: Array | string | NamedInputEvent) { - precognitiveForm.touch(name) - - return form - }, - valid: precognitiveForm.valid, - invalid: precognitiveForm.invalid, - setData(key: any, value?: any) { - inertiaSetData(key, value) - - precognitiveForm.setData(key, value) - - return form - }, - clearErrors(...names: FormDataKeys>[]) { - inertiaClearErrors(...names) - - if (names.length === 0) { - precognitiveForm.setErrors({}) - } else { - names.forEach(precognitiveForm.forgetError) - } - - return form - }, - setDefaults(field?: keyof Data | Partial> | ((previousData: FormDataType) => FormDataType), value?: Data[keyof Data]){ - const data = ((): Partial> => { - if (typeof field === 'undefined') { - return inertiaForm.data - } - - if (typeof field === 'function') { - return field(inertiaForm.data) - } - - if (typeof field === 'object') { - return field - } - - // @ts-ignore - return { [field]: value } - })() - - inertiaSetDefaults(data) - - precognitiveForm.validator().defaults(data) - }, - reset(...names: FormDataKeys>[]) { - inertiaReset(...names) - - precognitiveForm.reset(...names) - }, - setErrors(errors: SimpleValidationErrors | ValidationErrors) { - // @ts-expect-error - precognitiveForm.setErrors(errors) - - return form - }, - setError(key: any, value?: any) { - form.setErrors({ - ...inertiaForm.errors, - ...typeof value === 'undefined' - ? key - : { [key]: value }, - }) - - return form - }, - forgetError(name: string | NamedInputEvent) { - precognitiveForm.forgetError(name) - - return form - }, - transform(callback: (data: Data) => Data) { - inertiaTransform(callback) - - transformer.current = callback - - return form - }, - validate(name?: string | NamedInputEvent | ValidationConfig, config?: ValidationConfig) { - precognitiveForm.setData(transformer.current(inertiaForm.data)) - - if (typeof name === 'object' && !('target' in name)) { - config = name - name = undefined - } - - if (typeof name === 'undefined') { - precognitiveForm.validate(config) - } else { - precognitiveForm.validate(name, config) - } - - return form - }, - setValidationTimeout(duration: number) { - precognitiveForm.setValidationTimeout(duration) - - return form - }, - validateFiles() { - precognitiveForm.validateFiles() - - return form - }, - withoutFileValidation() { - precognitiveForm.withoutFileValidation() - - return form - }, - submit(submitMethod: RequestMethod | Omit = {}, submitUrl?: string, submitOptions?: Omit): void { - if (typeof submitMethod !== 'string') { - submitOptions = submitMethod - submitUrl = resolveUrl(url) - submitMethod = resolveMethod(method) - } - - inertiaSubmit(submitMethod, submitUrl!, { - ...submitOptions, - onError: (errors: SimpleValidationErrors): any => { - precognitiveForm.validator().setErrors(errors) - - if (submitOptions?.onError) { - return submitOptions.onError(errors) - } - }, - }) - }, - validator: precognitiveForm.validator, - }) - - // @ts-expect-error - return form -} diff --git a/packages/react-inertia/src/types.ts b/packages/react-inertia/src/types.ts deleted file mode 100644 index d8cd734..0000000 --- a/packages/react-inertia/src/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NamedInputEvent, RequestMethod, SimpleValidationErrors, ValidationConfig, ValidationErrors } from 'laravel-precognition' -import { Form as PrecognitiveForm } from 'laravel-precognition-react/dist/types' -import { InertiaFormProps } from '@inertiajs/react' -import { VisitOptions } from '@inertiajs/core' - -type RedefinedProperties = 'setErrors' | 'touch' | 'forgetError' | 'setValidationTimeout' | 'submit' | 'reset' | 'validateFiles' | 'setData' | 'validate' - -export type Form> = Omit, RedefinedProperties> & InertiaFormProps & { - setErrors(errors: SimpleValidationErrors | ValidationErrors): Form, - touch(name: Array | string | NamedInputEvent): Form, - forgetError(string: keyof Data | NamedInputEvent): Form, - setValidationTimeout(duration: number): Form, - submit(config?: Omit): void, - submit(method: RequestMethod, url: string, options?: Omit): void, - reset(...keys: (keyof Partial)[]): void, - validateFiles(): Form, - withoutFileValidation(): Form, - setData(data: Record): Form, - validate(name?: (keyof Data | NamedInputEvent) | ValidationConfig, config?: ValidationConfig): Form, - setDefaults(): void, - setDefaults(defaults: Partial): void, - setDefaults(defaults: (previousData: Data) => Data): void, - setDefaults(field: K, value: Data[K]): void, -} - -// This type has been duplicated from @inertiajs/core to -// continue supporting Inertia 1. When we drop version 1 -// support we can import this directly from Inertia. -export type FormDataConvertible = Array | { - [key: string]: FormDataConvertible; -} | Blob | FormDataEntryValue | Date | boolean | number | null | undefined; - diff --git a/packages/react-inertia/tests/index.test.ts b/packages/react-inertia/tests/index.test.ts deleted file mode 100644 index 864ff0d..0000000 --- a/packages/react-inertia/tests/index.test.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { it, expect, beforeEach, afterEach, vi } from 'vitest' -import { renderHook, act } from '@testing-library/react' -import { useForm, client } from '../src/index' -import axios from 'axios' -import { Config } from 'laravel-precognition' - -beforeEach(() => { - vi.mock('axios') - client.use(axios) -}) - -afterEach(() => { - vi.restoreAllMocks() -}) - -it('can clear all errors via Inertia\'s clearErrors', () => { - const { result: form } = renderHook(() => useForm('post', '/register', { - name: '', - })) - - act(() => form.current.setErrors({ - name: 'xxxx', - other: 'xxxx', - })) - - expect(form.current.errors).toEqual({ - name: 'xxxx', - other: 'xxxx', - }) - - act(() => form.current.clearErrors()) - - expect(form.current.errors).toEqual({}) - expect(form.current.validator().errors()).toEqual({}) -}) - -it('can clear specific errors via Inertia\'s clearErrors', () => { - const { result: form } = renderHook(() => useForm('post', '/register', { - name: '', - })) - - act(() => form.current.setErrors({ - name: 'xxxx', - email: 'xxxx', - other: 'xxxx', - })) - - expect(form.current.errors).toEqual({ - name: 'xxxx', - email: 'xxxx', - other: 'xxxx', - }) - - act(() => form.current.clearErrors('name', 'email')) - - expect(form.current.errors).toEqual({ - other: 'xxxx', - }) - expect(form.current.validator().errors()).toEqual({ - other: ['xxxx'], - }) -}) - -it('provides default data for validation requests', () => { - const response = { headers: { precognition: 'true', 'precognition-success': 'true' }, status: 204, data: 'data' } - - let config: Config - axios.request.mockImplementation(async (c: Config) => { - config = c - - return response - }) - - const { result: form } = renderHook(() => useForm('post', '/register', { - emails: '', - })) - - act(() => form.current.setData('emails', 'taylor@laravel.com, tim@laravel.com')) - act(() => form.current.validate('emails')) - - expect(config!.data.emails).toEqual('taylor@laravel.com, tim@laravel.com') - expect(form.current.data.emails).toBe('taylor@laravel.com, tim@laravel.com') -}) - -it('transforms data for validation requests', () => { - const response = { headers: { precognition: 'true', 'precognition-success': 'true' }, status: 204, data: 'data' } - - let config: Config - axios.request.mockImplementation(async (c: Config) => { - config = c - - return response - }) - - const { result: form } = renderHook(() => useForm('post', '/register', { - emails: '', - })) - - act(() => form.current.transform((data) => ({ - emails: data.emails.split(',').map((email: string) => email.trim()), - }))) - - act(() => form.current.setData('emails', 'taylor@laravel.com, tim@laravel.com')) - act(() => form.current.validate('emails')) - - expect(config!.data.emails).toEqual(['taylor@laravel.com', 'tim@laravel.com']) - expect(form.current.data.emails).toBe('taylor@laravel.com, tim@laravel.com') -}) - -it('can set individual errors', function () { - const { result: form } = renderHook(() => useForm('post', '/register', { - name: '', - })) - - act(() => form.current.setError('name', 'The name is required.')) - - expect(form.current.errors.name).toBe('The name is required.') -}) - -it('can check that specific fields have been touched', () => { - const { result: form } = renderHook(() => useForm('post', '/register', { - name: '', - email: '', - })) - - expect(form.current.touched('name')).toBe(false) - expect(form.current.touched('email')).toBe(false) - - act(() => form.current.touch('name')) - - expect(form.current.touched('name')).toBe(true) - expect(form.current.touched('email')).toBe(false) -}) - -it('can check it any fields have been touched', () => { - const { result: form } = renderHook(() => useForm('post', '/register', { - name: '', - email: '', - })) - - expect(form.current.touched()).toBe(false) - - act(() => form.current.touch('name')) - - expect(form.current.touched()).toBe(true) -}) - -it('can set defaults with no arguments', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const { result: form } = renderHook(() => useForm('post', '/register', { - name: 'John', - })) - - act(() => form.current.setData('name', 'Jane')) - act(() => form.current.setDefaults()) - - act(() => form.current.setData('name', 'John')) - act(() => form.current.reset()) - expect(form.current.data.name).toBe('Jane') - - act(() => form.current.validate('name')) - expect(requests).toBe(0) -}) - -it('can set defaults with an object', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const { result: form } = renderHook(() => useForm('post', '/register', { - name: 'John', - })) - - act(() => form.current.setDefaults({ name: 'Jane' })) - - act(() => form.current.setData('name', 'John')) - act(() => form.current.reset()) - expect(form.current.data.name).toBe('Jane') - - act(() => form.current.validate('name')) - expect(requests).toBe(0) -}) - -it('can set defaults with a function', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const { result: form } = renderHook(() => useForm('post', '/register', { - name: 'John', - })) - - act(() => form.current.setDefaults((prevData: any) => { - expect(prevData).toEqual({ - name: 'John', - }) - - return { - name: 'Jane', - } - })) - - act(() => form.current.setData('name', 'John')) - act(() => form.current.reset()) - expect(form.current.data.name).toBe('Jane') - - act(() => form.current.validate('name')) - expect(requests).toBe(0) -}) - -it('can set defaults with a field and value', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const { result: form } = renderHook(() => useForm('post', '/register', { - name: 'John', - })) - - act(() => form.current.setDefaults('name', 'Jane')) - - act(() => form.current.setData('name', 'John')) - act(() => form.current.reset()) - expect(form.current.data.name).toBe('Jane') - - act(() => form.current.validate('name')) - expect(requests).toBe(0) -}) diff --git a/packages/react-inertia/tsconfig.json b/packages/react-inertia/tsconfig.json deleted file mode 100644 index d926f37..0000000 --- a/packages/react-inertia/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./dist", - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "node", - "resolveJsonModule": true, - "strict": true, - "declaration": true, - "esModuleInterop": true - }, - "include": [ - "./src/index.ts" - ] -} diff --git a/packages/react-inertia/vitest.config.ts b/packages/react-inertia/vitest.config.ts deleted file mode 100644 index e7ef8ea..0000000 --- a/packages/react-inertia/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - environment: 'jsdom', - }, -}) diff --git a/packages/vue-inertia/.gitignore b/packages/vue-inertia/.gitignore deleted file mode 100644 index c925c21..0000000 --- a/packages/vue-inertia/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/dist -/node_modules diff --git a/packages/vue-inertia/LICENSE.md b/packages/vue-inertia/LICENSE.md deleted file mode 100644 index 79810c8..0000000 --- a/packages/vue-inertia/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) Taylor Otwell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/packages/vue-inertia/README.md b/packages/vue-inertia/README.md deleted file mode 100644 index 0b20012..0000000 --- a/packages/vue-inertia/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Laravel Precognition - -Test Status -Build Status -Total Downloads -Latest Stable Version -License - -## Introduction - -Laravel Precognition allows you to anticipate the outcome of a future HTTP request. One of the primary use cases of Precognition is the ability to provide "live" validation in your frontend application. - -## Official Documentation - -Documentation for Laravel Precognition can be found on the [Laravel website](https://laravel.com/docs/precognition). - -## Contributing - -Thank you for considering contributing to Laravel Precognition! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). - -## Code of Conduct - -In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). - -## Security Vulnerabilities - -Please review [our security policy](https://github.com/laravel/precognition/security/policy) on how to report security vulnerabilities. - -## License - -Laravel Precognition is open-sourced software licensed under the [MIT license](LICENSE.md). diff --git a/packages/vue-inertia/package.json b/packages/vue-inertia/package.json deleted file mode 100644 index b5f74f3..0000000 --- a/packages/vue-inertia/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "laravel-precognition-vue-inertia", - "version": "0.8.0", - "description": "Laravel Precognition (Vue w/ Inertia).", - "keywords": [ - "laravel", - "precognition", - "vue", - "inertia" - ], - "homepage": "https://github.com/laravel/precognition", - "type": "module", - "repository": { - "type": "git", - "url": "https://github.com/laravel/precognition" - }, - "license": "MIT", - "author": "Laravel", - "main": "dist/index.js", - "files": [ - "/dist" - ], - "scripts": { - "watch": "rm -rf dist && tsc --watch --preserveWatchOutput", - "build": "rm -rf dist && tsc", - "typeCheck": "tsc --noEmit", - "prepublishOnly": "npm run build", - "test": "vitest run", - "version": "npm pkg set dependencies.laravel-precognition=$npm_package_version && npm pkg set dependencies.laravel-precognition-vue=$npm_package_version" - }, - "peerDependencies": { - "@inertiajs/vue3": "^1.0.0 || ^2.0.0", - "vue": "^3.0.0" - }, - "dependencies": { - "laravel-precognition": "0.8.0", - "laravel-precognition-vue": "0.8.0" - }, - "devDependencies": { - "typescript": "^5.0.0", - "vitest": "^2.0.5" - } -} diff --git a/packages/vue-inertia/src/index.ts b/packages/vue-inertia/src/index.ts deleted file mode 100644 index 79feb05..0000000 --- a/packages/vue-inertia/src/index.ts +++ /dev/null @@ -1,230 +0,0 @@ -import { NamedInputEvent, RequestMethod, SimpleValidationErrors, toSimpleValidationErrors, ValidationConfig, ValidationErrors, resolveUrl, resolveMethod } from 'laravel-precognition' -import { useForm as usePrecognitiveForm, client } from 'laravel-precognition-vue' -import { useForm as useInertiaForm } from '@inertiajs/vue3' -import { FormDataKeys, FormDataType, VisitOptions } from '@inertiajs/core' -import { watchEffect } from 'vue' -import { Form, FormDataConvertible } from './types' - -export { client, Form } - -export const useForm = >(method: RequestMethod | (() => RequestMethod), url: string | (() => string), inputs: Data | (() => Data), config: ValidationConfig = {}): Form => { - /** - * The Inertia form. - */ - // @ts-expect-error - const inertiaForm = useInertiaForm(inputs) - - /** - * The Precognitive form. - */ - const precognitiveForm = usePrecognitiveForm(method, url, inputs, config) - - /** - * Setup event listeners. - */ - precognitiveForm.validator().on('errorsChanged', () => { - inertiaClearErrors() - - inertiaSetError( - // @ts-expect-error - toSimpleValidationErrors(precognitiveForm.validator().errors()), - ) - }) - - /** - * The Inertia defaults function. - */ - const inertiaDefaults = inertiaForm.defaults.bind(inertiaForm) - - /** - * The Inertia submit function. - */ - const inertiaSubmit = inertiaForm.submit.bind(inertiaForm) - - /** - * The Inertia reset function. - */ - const inertiaReset = inertiaForm.reset.bind(inertiaForm) - - /** - * The Inertia clear errors function. - */ - const inertiaClearErrors = inertiaForm.clearErrors.bind(inertiaForm) - - /** - * The Inertia set error function. - */ - const inertiaSetError = inertiaForm.setError.bind(inertiaForm) - - /** - * The Inertia trasform function. - */ - const inertiaTransform = inertiaForm.transform.bind(inertiaForm) - - /** - * The transform function. - */ - let transformer: (data: Data) => Record = (data) => data - - /** - * Patch the form. - */ - // @ts-expect-error - const form: Form = Object.assign(inertiaForm, { - validating: precognitiveForm.validating, - touched: precognitiveForm.touched, - touch(name: Array | string | NamedInputEvent) { - precognitiveForm.touch(name) - - return form - }, - valid: precognitiveForm.valid, - invalid: precognitiveForm.invalid, - setData(data: Record) { - Object.keys(data).forEach((input) => { - // @ts-expect-error - form[input] = data[input] - }) - - return form - }, - clearErrors(...names: FormDataKeys>[]) { - inertiaClearErrors(...names) - - if (names.length === 0) { - precognitiveForm.setErrors({}) - } else { - names.forEach(precognitiveForm.forgetError) - } - - return form - }, - defaults(field?: keyof Data | Partial> | ((previousData: FormDataType) => FormDataType), value?: Data[keyof Data]){ - const data = ((): Partial> => { - if (typeof field === 'undefined') { - return inertiaForm.data() - } - - if (typeof field === 'function') { - return field(inertiaForm.data()) - } - - if (typeof field === 'object') { - return field - } - - // @ts-ignore - return { [field]: value } - })() - - inertiaDefaults(data) - - precognitiveForm.validator().defaults(data) - }, - reset(...names: FormDataKeys>[]) { - inertiaReset(...names) - - precognitiveForm.reset(...names) - }, - setErrors(errors: SimpleValidationErrors | ValidationErrors) { - // @ts-expect-error - precognitiveForm.setErrors(errors) - - return form - }, - forgetError(name: string | NamedInputEvent) { - precognitiveForm.forgetError(name) - - return form - }, - setError(key: (keyof Data) | Record, value?: string) { - let errors: SimpleValidationErrors - - if (typeof key !== 'object') { - if (typeof value === 'undefined') { - throw new Error('The `value` is required.') - } - - errors = { [key]: value } - } else { - errors = key - } - - form.setErrors({ - ...inertiaForm.errors, - ...errors, - }) - - return form - }, - transform(callback: (data: Data) => Record) { - inertiaTransform(callback) - - transformer = callback - - return form - }, - validate(name?: string | NamedInputEvent | ValidationConfig, config?: ValidationConfig) { - precognitiveForm.setData(transformer(inertiaForm.data())) - - if (typeof name === 'object' && !('target' in name)) { - config = name - name = undefined - } - - if (typeof config === 'object') { - // @ts-expect-error - config.onValidationError = config.onValidationError ?? config?.onError - } - - if (typeof name === 'undefined') { - precognitiveForm.validate(config) - } else { - precognitiveForm.validate(name, config) - } - - return form - }, - setValidationTimeout(duration: number) { - precognitiveForm.setValidationTimeout(duration) - - return form - }, - validateFiles() { - precognitiveForm.validateFiles() - - return form - }, - withoutFileValidation() { - precognitiveForm.withoutFileValidation() - - return form - }, - submit(submitMethod: RequestMethod | Partial = {}, submitUrl?: string, submitOptions?: Partial): void { - if (typeof submitMethod !== 'string') { - submitOptions = submitMethod - submitUrl = resolveUrl(url) - submitMethod = resolveMethod(method) - } - - inertiaSubmit(submitMethod, submitUrl!, { - ...submitOptions, - onError: (errors: SimpleValidationErrors): void => { - precognitiveForm.validator().setErrors(errors) - - if (submitOptions?.onError) { - return submitOptions.onError(errors) - } - }, - }) - }, - validator: precognitiveForm.validator, - }) - - // Due to the nature of `reactive` elements, reactivity is not inherited by - // the patched Inertia form as we have to destructure the Precog form. We - // can handle this by watching for changes and apply the changes manually. - watchEffect(() => form.validating = precognitiveForm.validating) - - return form -} diff --git a/packages/vue-inertia/src/types.ts b/packages/vue-inertia/src/types.ts deleted file mode 100644 index 1eb579c..0000000 --- a/packages/vue-inertia/src/types.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NamedInputEvent, RequestMethod, SimpleValidationErrors, ValidationConfig, ValidationErrors } from 'laravel-precognition' -import { Form as PrecognitiveForm } from 'laravel-precognition-vue/dist/types' -import { InertiaForm } from '@inertiajs/vue3' -import { VisitOptions } from '@inertiajs/core' - -type RedefinedProperties = 'setErrors' | 'touch' | 'forgetError' | 'setValidationTimeout' | 'submit' | 'reset' | 'validateFiles' | 'setData' | 'validate' - -export type Form> = Omit, RedefinedProperties> & InertiaForm & { - setErrors(errors: SimpleValidationErrors | ValidationErrors): Data & Form, - touch(name: Array | string | NamedInputEvent): Data & Form, - forgetError(string: keyof Data | NamedInputEvent): Data & Form, - setValidationTimeout(duration: number): Data & Form, - submit(config?: Partial): void, - submit(method: RequestMethod, url: string, options?: Partial): void, - reset(...keys: (keyof Partial)[]): Data & Form, - validateFiles(): Data & Form, - withoutFileValidation(): Data & Form, - setData(data: Record): Data & Form, - validate(name?: (keyof Data | NamedInputEvent) | ValidationConfig, config?: ValidationConfig): Data & Form, - defaults(): void, - defaults(defaults: Partial): void, - defaults(defaults: (previousData: Data) => Data): void, - defaults(field: K, value: Data[K]): void, -} - -// This type has been duplicated from @inertiajs/core to -// continue supporting Inertia 1. When we drop version 1 -// support we can import this directly from Inertia. -export type FormDataConvertible = Array | { - [key: string]: FormDataConvertible; -} | Blob | FormDataEntryValue | Date | boolean | number | null | undefined; diff --git a/packages/vue-inertia/tests/index.test.ts b/packages/vue-inertia/tests/index.test.ts deleted file mode 100644 index 0a85ca0..0000000 --- a/packages/vue-inertia/tests/index.test.ts +++ /dev/null @@ -1,249 +0,0 @@ -import { it, expect, beforeEach, afterEach, vi } from 'vitest' -import { useForm, client } from '../src/index' -import axios from 'axios' -import { Config } from 'laravel-precognition' - -beforeEach(() => { - vi.mock('axios') - client.use(axios) -}) - -afterEach(() => { - vi.restoreAllMocks() -}) - -it('can clear all errors via Inertia\'s clearErrors', () => { - const form = useForm('post', '/register', { - name: '', - }).setErrors({ - name: 'xxxx', - other: 'xxxx', - }) - - expect(form.errors).toEqual({ - name: 'xxxx', - other: 'xxxx', - }) - - form.clearErrors() - - expect(form.errors).toEqual({}) - expect(form.validator().errors()).toEqual({}) -}) - -it('can clear specific errors via Inertia\'s clearErrors', () => { - const form = useForm('post', '/register', { - name: '', - }).setErrors({ - name: 'xxxx', - email: 'xxxx', - other: 'xxxx', - }) - - expect(form.errors).toEqual({ - name: 'xxxx', - email: 'xxxx', - other: 'xxxx', - }) - - form.clearErrors('name', 'email') - - expect(form.errors).toEqual({ - other: 'xxxx', - }) - expect(form.validator().errors()).toEqual({ - other: ['xxxx'], - }) -}) - -it('provides default data for validation requests', () => { - const response = { headers: { precognition: 'true', 'precognition-success': 'true' }, status: 204, data: 'data' } - - let config: Config - axios.request.mockImplementation(async (c: Config) => { - config = c - - return response - }) - - const form = useForm('post', '/register', { - emails: '', - }) - - form.emails = 'taylor@laravel.com, tim@laravel.com' - form.validate('emails') - - expect(config!.data.emails).toEqual('taylor@laravel.com, tim@laravel.com') - expect(form.emails).toBe('taylor@laravel.com, tim@laravel.com') - expect(form.data().emails).toBe('taylor@laravel.com, tim@laravel.com') -}) - -it('transforms data for validation requests', () => { - const response = { headers: { precognition: 'true', 'precognition-success': 'true' }, status: 204, data: 'data' } - - let config: Config - axios.request.mockImplementation(async (c: Config) => { - config = c - - return response - }) - - const form = useForm('post', '/register', { - emails: '', - }).transform((data) => ({ - emails: data.emails.split(',').map((email) => email.trim()), - })) - - form.emails = 'taylor@laravel.com, tim@laravel.com' - form.validate('emails') - - expect(config!.data.emails).toEqual(['taylor@laravel.com', 'tim@laravel.com']) - expect(form.emails).toBe('taylor@laravel.com, tim@laravel.com') - expect(form.data().emails).toBe('taylor@laravel.com, tim@laravel.com') -}) - -it('can set individual errors', function () { - const form = useForm('post', '/register', { - name: '', - }) - - form.setError('name', 'The name is required.') - - expect(form.errors.name).toBe('The name is required.') -}) - -it('allows getter as data inputs', function () { - let dynamicEmail = 'taylor@laravel.com' - - function getData() { - return { - email: dynamicEmail, - } - } - - const form = useForm('post', '/register', getData) - - expect(form.email).toBe('taylor@laravel.com') - - dynamicEmail = 'tim@laravel.com' - form.reset() - - expect(form.email).toBe('tim@laravel.com') -}) - -it('can check that specific fields have been touched', () => { - const form = useForm('post', '/register', { - name: '', - email: '', - }) - - expect(form.touched('name')).toBe(false) - expect(form.touched('email')).toBe(false) - - form.touch('name') - - expect(form.touched('name')).toBe(true) - expect(form.touched('email')).toBe(false) -}) - -it('can check it any fields have been touched', () => { - const form = useForm('post', '/register', { - name: '', - email: '', - }) - - expect(form.touched()).toBe(false) - - form.touch('name') - - expect(form.touched()).toBe(true) -}) - -it('can set defaults with no arguments', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const form = useForm('post', '/register', { - name: 'John', - }) - - form.name = 'Jane' - form.defaults() - - form.name = 'John' - form.reset() - expect(form.name).toBe('Jane') - - form.validate('name') - expect(requests).toBe(0) -}) - -it('can set defaults with an object', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const form = useForm('post', '/register', { - name: 'John', - }) - - form.defaults({ name: 'Jane' }) - - form.name = 'John' - form.reset() - expect(form.name).toBe('Jane') - - form.validate('name') - expect(requests).toBe(0) -}) - -it('can set defaults with a function', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const form = useForm('post', '/register', { - name: 'John', - }) - - form.defaults((prevData: any) => { - expect(prevData).toEqual({ - name: 'John', - }) - - return { - name: 'Jane', - } - }) - - form.name = 'John' - form.reset() - expect(form.name).toBe('Jane') - - form.validate('name') - expect(requests).toBe(0) -}) - -it('can set defaults with a field and value', () => { - let requests = 0 - axios.request.mockImplementation(async () => { - requests++ - }) - - const form = useForm('post', '/register', { - name: 'John', - }) - - form.defaults('name', 'Jane') - - form.name = 'John' - form.reset() - expect(form.name).toBe('Jane') - - form.validate('name') - expect(requests).toBe(0) -}) diff --git a/packages/vue-inertia/tsconfig.json b/packages/vue-inertia/tsconfig.json deleted file mode 100644 index c4ba78c..0000000 --- a/packages/vue-inertia/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "skipLibCheck": true, - "outDir": "./dist", - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "node", - "resolveJsonModule": true, - "strict": true, - "declaration": true, - "esModuleInterop": true, - "types": [ - "vue" - ] - }, - "include": [ - "./src/index.ts" - ] -} From 11a876557a3386696c18f4f66ebc7ea7937178a5 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Mon, 8 Dec 2025 20:54:21 +0100 Subject: [PATCH 2/2] More cleanup --- .github/ISSUE_TEMPLATE/1_Bug_report.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yml b/.github/ISSUE_TEMPLATE/1_Bug_report.yml index 61881ae..bd54b8a 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yml @@ -25,9 +25,7 @@ body: options: - Alpine - React - - React w/ Inertia - Vue - - Vue w/ Inertia validations: required: true - type: textarea