diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index e3710503c..665554411 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -32,6 +32,9 @@ jobs: - name: Type-check test-app run: cd packages/${{ matrix.adapter == 'vue' && 'vue3' || matrix.adapter }}/test-app && pnpm run type-check + - name: ESLint test-app + run: cd packages/${{ matrix.adapter == 'vue' && 'vue3' || matrix.adapter }}/test-app && pnpm run lint + - name: Install Playwright Browsers run: pnpm playwright install chromium diff --git a/package.json b/package.json index 0b13e596e..cb69d3508 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,10 @@ "dev:test-app:svelte": "pnpx concurrently -c \"#c4b5fd,#ffa800\" \"cd tests/app && PACKAGE=svelte pnpm serve:watch\" \"cd packages/svelte/test-app && pnpm run dev\" --names=server,vite", "dev:test-app:vue": "pnpx concurrently -c \"#c4b5fd,#ffa800\" \"cd tests/app && PACKAGE=vue3 pnpm serve:watch\" \"cd packages/vue3/test-app && pnpm run dev\" --names=server,vite", "es2020-check": "pnpm -r --filter './packages/*' es2020-check", + "lint:test-app": "pnpm -r --filter './packages/*/test-app' lint", + "lint:test-app:react": "cd packages/react/test-app && pnpm run lint", + "lint:test-app:svelte": "cd packages/svelte/test-app && pnpm run lint", + "lint:test-app:vue": "cd packages/vue3/test-app && pnpm run lint", "type-check:test-app": "pnpm -r --filter './packages/*/test-app' type-check", "type-check:test-app:react": "cd packages/react/test-app && pnpm run type-check", "type-check:test-app:svelte": "cd packages/svelte/test-app && pnpm run type-check", @@ -28,13 +32,13 @@ "format": "prettier --write ." }, "dependencies": { - "@playwright/test": "^1.56.0", + "@playwright/test": "^1.56.1", "prettier": "^3.6.2", "prettier-plugin-organize-imports": "^4.3.0", "prettier-plugin-svelte": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.14" }, "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "^4.52.4" + "@rollup/rollup-linux-x64-gnu": "^4.52.5" } } diff --git a/packages/react/test-app/Layouts/NestedLayout.tsx b/packages/react/test-app/Layouts/NestedLayout.tsx index ce99e1d9a..3bcf8654c 100644 --- a/packages/react/test-app/Layouts/NestedLayout.tsx +++ b/packages/react/test-app/Layouts/NestedLayout.tsx @@ -2,7 +2,7 @@ import { usePage } from '@inertiajs/react' import { useId, useState } from 'react' export default ({ children }: { children: React.ReactNode }) => { - const [createdAt, setCreatedAt] = useState(Date.now()) + const [createdAt] = useState(Date.now()) window._inertia_nested_layout_id = useId() window._inertia_nested_layout_props = usePage().props diff --git a/packages/react/test-app/Layouts/SiteLayout.tsx b/packages/react/test-app/Layouts/SiteLayout.tsx index 04cd640d7..8f0e381bd 100644 --- a/packages/react/test-app/Layouts/SiteLayout.tsx +++ b/packages/react/test-app/Layouts/SiteLayout.tsx @@ -2,7 +2,7 @@ import { usePage } from '@inertiajs/react' import { useId, useState } from 'react' export default ({ children }: { children: React.ReactNode }) => { - const [createdAt, setCreatedAt] = useState(Date.now()) + const [createdAt] = useState(Date.now()) window._inertia_layout_id = useId() window._inertia_site_layout_props = usePage().props diff --git a/packages/react/test-app/Pages/ClientSideVisit/Page1.tsx b/packages/react/test-app/Pages/ClientSideVisit/Page1.tsx index 05336f5bc..784deaf0f 100644 --- a/packages/react/test-app/Pages/ClientSideVisit/Page1.tsx +++ b/packages/react/test-app/Pages/ClientSideVisit/Page1.tsx @@ -11,7 +11,7 @@ export default ({ foo, bar }: PageProps) => { const [errors, setErrors] = useState(0) const [finished, setFinished] = useState(0) const [success, setSuccess] = useState(0) - const [random, setRandom] = useState(Math.random()) + const [random] = useState(Math.random()) const bagErrors = () => { router.replace({ diff --git a/packages/react/test-app/Pages/DeepMergeProps.tsx b/packages/react/test-app/Pages/DeepMergeProps.tsx index 4c8ce6fa6..e6dad4f79 100644 --- a/packages/react/test-app/Pages/DeepMergeProps.tsx +++ b/packages/react/test-app/Pages/DeepMergeProps.tsx @@ -1,15 +1,13 @@ import { router } from '@inertiajs/react' import { useState } from 'react' -export default ({ - bar, - foo, - baz, -}: { +type PageProps = { bar: number[] foo: { page: number; data: number[]; per_page: number; meta: { label: string } } baz: number[] -}) => { +} + +export default ({ bar, foo, baz }: PageProps) => { const [page, setPage] = useState(foo.page) const reloadIt = () => { @@ -19,7 +17,7 @@ export default ({ }, only: ['foo', 'baz'], onSuccess(visit) { - setPage((visit.props as any).foo.page) + setPage((visit.props as unknown as PageProps).foo.page) }, }) } diff --git a/packages/react/test-app/Pages/Dump.tsx b/packages/react/test-app/Pages/Dump.tsx index ad606a4b0..3728f8a72 100644 --- a/packages/react/test-app/Pages/Dump.tsx +++ b/packages/react/test-app/Pages/Dump.tsx @@ -1,6 +1,6 @@ import type { Method } from '@inertiajs/core' import { usePage } from '@inertiajs/react' -import { useEffect } from 'react' +import { useEffect, useMemo } from 'react' import type { MulterFile } from '../types' export default ({ @@ -20,19 +20,22 @@ export default ({ }) => { const page = usePage() - const dump = { - headers, - method, - form, - files: files ? files : {}, - query, - url, - $page: page, - } + const dump = useMemo( + () => ({ + headers, + method, + form, + files: files ? files : {}, + query, + url, + $page: page, + }), + [headers, method, form, files, query, url, page], + ) useEffect(() => { window._inertia_request_dump = dump - }, []) + }, [dump]) return (
diff --git a/packages/react/test-app/Pages/Events.tsx b/packages/react/test-app/Pages/Events.tsx index 6ae27ec83..724e0925d 100644 --- a/packages/react/test-app/Pages/Events.tsx +++ b/packages/react/test-app/Pages/Events.tsx @@ -2,7 +2,7 @@ import { Link, router, usePage } from '@inertiajs/react' declare global { interface Window { - messages: string[] + messages: unknown[] } } @@ -15,7 +15,7 @@ export default () => { const page = usePage() - const internalAlert = (...args: any[]) => { + const internalAlert = (...args: unknown[]) => { args.forEach((arg) => window.messages.push(arg)) } @@ -87,7 +87,7 @@ export default () => { const beforeVisitPreventGlobalInertia = (e: React.MouseEvent) => { e.preventDefault() document.addEventListener('inertia:before', () => internalAlert('addEventListener(inertia:before)')) - router.on('before', (visit) => { + router.on('before', () => { internalAlert('Inertia.on(before)') return false }) @@ -502,7 +502,7 @@ export default () => { { + onBefore={() => { internalAlert('linkOnBefore') return false }} diff --git a/packages/react/test-app/Pages/FormComponent/Reset.tsx b/packages/react/test-app/Pages/FormComponent/Reset.tsx index 8e103bcc9..c3702266d 100644 --- a/packages/react/test-app/Pages/FormComponent/Reset.tsx +++ b/packages/react/test-app/Pages/FormComponent/Reset.tsx @@ -1,3 +1,4 @@ +import { FormComponentRef } from '@inertiajs/core' import { Form } from '@inertiajs/react' import { useRef } from 'react' @@ -8,11 +9,10 @@ declare global { } export default function Reset() { - const formRef = useRef(null) + const formRef = useRef(null) // Expose reset function to window for testing window.resetForm = (...fields: string[]) => { - // @ts-expect-error formRef.current?.reset(...fields) } diff --git a/packages/react/test-app/Pages/FormHelper/Data.tsx b/packages/react/test-app/Pages/FormHelper/Data.tsx index a0306eaa1..688b86611 100644 --- a/packages/react/test-app/Pages/FormHelper/Data.tsx +++ b/packages/react/test-app/Pages/FormHelper/Data.tsx @@ -1,6 +1,6 @@ import { useForm, usePage } from '@inertiajs/react' -export default ({ errors }: { errors?: { name?: string; handle?: string } }) => { +export default () => { const form = useForm({ name: 'foo', handle: 'example', diff --git a/packages/react/test-app/Pages/FormHelper/EffectCount.tsx b/packages/react/test-app/Pages/FormHelper/EffectCount.tsx index 2efb35019..06d0cadb3 100644 --- a/packages/react/test-app/Pages/FormHelper/EffectCount.tsx +++ b/packages/react/test-app/Pages/FormHelper/EffectCount.tsx @@ -9,7 +9,7 @@ export default () => { useEffect(() => { setData('count', count) setDefaults() - setEffectCount(effectCount + 1) + setEffectCount((e) => e + 1) }, [count, setData, setDefaults]) return ( diff --git a/packages/react/test-app/Pages/FormHelper/Errors.tsx b/packages/react/test-app/Pages/FormHelper/Errors.tsx index c67643f3d..9aba8b624 100644 --- a/packages/react/test-app/Pages/FormHelper/Errors.tsx +++ b/packages/react/test-app/Pages/FormHelper/Errors.tsx @@ -1,6 +1,6 @@ import { useForm } from '@inertiajs/react' -export default ({ errors }: { errors?: { name?: string; handle?: string } }) => { +export default () => { const form = useForm({ name: 'foo', handle: 'example', remember: false }) const submit = () => { diff --git a/packages/react/test-app/Pages/FormHelper/Events.tsx b/packages/react/test-app/Pages/FormHelper/Events.tsx index 281176426..f7d0076da 100644 --- a/packages/react/test-app/Pages/FormHelper/Events.tsx +++ b/packages/react/test-app/Pages/FormHelper/Events.tsx @@ -1,6 +1,6 @@ import type { Errors, Page, PendingVisit } from '@inertiajs/core' import { useForm, usePage } from '@inertiajs/react' -import type { CancelTokenSource } from 'axios' +import type { AxiosProgressEvent, CancelTokenSource } from 'axios' import { useEffect } from 'react' declare global { @@ -39,7 +39,7 @@ const callbacks = (overrides = {}) => ({ ...overrides, }) -export default ({ errors }: { errors?: { name?: string; handle?: string } }) => { +export default () => { const form = useForm({ name: 'foo', remember: false }) const page = usePage() @@ -95,7 +95,7 @@ export default ({ errors }: { errors?: { name?: string; handle?: string } }) => const onBeforeVisitCancelled = () => { form.post('/sleep', { ...callbacks({ - onBefore: (visit: PendingVisit) => { + onBefore: () => { pushEvent('onBefore') return false }, @@ -121,7 +121,7 @@ export default ({ errors }: { errors?: { name?: string; handle?: string } }) => form.post('/dump/post', { ...callbacks({ - onProgress: (event: any) => { + onProgress: (event: AxiosProgressEvent) => { pushEvent('onProgress') pushData('progressEvent', event) }, @@ -157,7 +157,7 @@ export default ({ errors }: { errors?: { name?: string; handle?: string } }) => const onSuccessPromiseVisit = () => { form.post('/dump/post', { ...callbacks({ - onSuccess: (page: Page) => { + onSuccess: () => { pushEvent('onSuccess') setTimeout(() => pushEvent('onFinish should have been fired by now if Promise functionality did not work'), 5) return new Promise((resolve) => setTimeout(resolve, 20)) @@ -180,7 +180,7 @@ export default ({ errors }: { errors?: { name?: string; handle?: string } }) => const onErrorPromiseVisit = () => { form.post('/form-helper/events/errors', { ...callbacks({ - onError: (errors: Errors) => { + onError: () => { pushEvent('onError') setTimeout(() => pushEvent('onFinish should have been fired by now if Promise functionality did not work'), 5) return new Promise((resolve) => setTimeout(resolve, 20)) @@ -196,7 +196,7 @@ export default ({ errors }: { errors?: { name?: string; handle?: string } }) => const onSuccessResetValue = () => { form.post(page.url, { ...callbacks({ - onSuccess: (page: Page) => { + onSuccess: () => { form.reset() }, }), diff --git a/packages/react/test-app/Pages/FormHelper/TypeScript/DynamicInputName.tsx b/packages/react/test-app/Pages/FormHelper/TypeScript/DynamicInputName.tsx index acc2681ec..0f3994d70 100644 --- a/packages/react/test-app/Pages/FormHelper/TypeScript/DynamicInputName.tsx +++ b/packages/react/test-app/Pages/FormHelper/TypeScript/DynamicInputName.tsx @@ -3,7 +3,7 @@ import { useForm } from '@inertiajs/react' interface ClientForm { name: string - [key: string]: any + [key: string]: any // eslint-disable-line @typescript-eslint/no-explicit-any } export default function DynamicInputName() { diff --git a/packages/react/test-app/Pages/FormHelper/TypeScript/Errors.tsx b/packages/react/test-app/Pages/FormHelper/TypeScript/Errors.tsx index 3afd7410d..ec33db96c 100644 --- a/packages/react/test-app/Pages/FormHelper/TypeScript/Errors.tsx +++ b/packages/react/test-app/Pages/FormHelper/TypeScript/Errors.tsx @@ -17,8 +17,8 @@ export default function Errors() { const form = useForm(defaultData) // Get Errors - form.errors.name - form.errors['company.name'] + console.log(form.errors.name) + console.log(form.errors['company.name']) // Clear Errors form.clearErrors('name') @@ -53,9 +53,9 @@ export default function Errors() { form.setError({ 'users.0.name': 'Validation error' }) // @ts-expect-error - Form has no email field - form.errors.email + console.log(form.errors.email) // @ts-expect-error - Company has no email field - form.errors['company.email'] + console.log(form.errors['company.email']) // @ts-expect-error - Form has no email field form.clearErrors('email') @@ -83,6 +83,4 @@ export default function Errors() { form.setError('users.0.email', 'Validation error') // @ts-expect-error - A user has no email field form.setError({ 'users.0.email': 'Validation error' }) - - return null } diff --git a/packages/react/test-app/Pages/FormHelper/TypeScript/Generic.tsx b/packages/react/test-app/Pages/FormHelper/TypeScript/Generic.tsx index 59c5c5591..3a183d073 100644 --- a/packages/react/test-app/Pages/FormHelper/TypeScript/Generic.tsx +++ b/packages/react/test-app/Pages/FormHelper/TypeScript/Generic.tsx @@ -9,5 +9,6 @@ interface GenericProps> { export default function Generic>({ form, }: GenericProps) { + console.log(form) return
{/* Generic form component */}
} diff --git a/packages/react/test-app/Pages/FormHelper/TypeScript/ValidationKey.tsx b/packages/react/test-app/Pages/FormHelper/TypeScript/ValidationKey.tsx index 2e38e9afb..0ff12fbd4 100644 --- a/packages/react/test-app/Pages/FormHelper/TypeScript/ValidationKey.tsx +++ b/packages/react/test-app/Pages/FormHelper/TypeScript/ValidationKey.tsx @@ -21,5 +21,7 @@ const validation = >(errors: () => } export default function ValidationKey() { + validation(() => ({ name: 'Validation error' })) + return
{/* ValidationKey component */}
} diff --git a/packages/react/test-app/Pages/Head.tsx b/packages/react/test-app/Pages/Head.tsx index 664c08720..615695dfe 100644 --- a/packages/react/test-app/Pages/Head.tsx +++ b/packages/react/test-app/Pages/Head.tsx @@ -9,13 +9,13 @@ export default () => { {/* @ts-expect-error - The content attribute must be a string, we support passing other types for backwards compatibility */} - {/* @ts-expect-error */} + {/* @ts-expect-error - same as above */} - {/* @ts-expect-error */} + {/* @ts-expect-error - same as above */} - {/* @ts-expect-error */} + {/* @ts-expect-error - same as above */} - {/* @ts-expect-error */} + {/* @ts-expect-error - same as above */} diff --git a/packages/react/test-app/Pages/InfiniteScroll/Filtering.tsx b/packages/react/test-app/Pages/InfiniteScroll/Filtering.tsx index b419c3eab..35bc84800 100644 --- a/packages/react/test-app/Pages/InfiniteScroll/Filtering.tsx +++ b/packages/react/test-app/Pages/InfiniteScroll/Filtering.tsx @@ -1,6 +1,6 @@ import { InfiniteScroll, Link, useForm } from '@inertiajs/react' import { debounce } from 'lodash-es' -import { useCallback, useEffect } from 'react' +import { useEffect, useMemo } from 'react' import UserCard, { User } from './UserCard' interface Props { @@ -17,23 +17,24 @@ export default ({ users, preserveState, filter, search }: Props) => { search: search, }) - const debouncedSearch = useCallback( - debounce(() => { - get( - '', - preserveState - ? { - preserveState: true, - replace: true, - only: ['users', 'search', 'filter'], - reset: ['users'], - } - : { - replace: true, - }, - ) - }, 250), - [get], + const debouncedSearch = useMemo( + () => + debounce(() => { + get( + '', + preserveState + ? { + preserveState: true, + replace: true, + only: ['users', 'search', 'filter'], + reset: ['users'], + } + : { + replace: true, + }, + ) + }, 250), + [get, preserveState], ) useEffect(() => { diff --git a/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx b/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx index ef8ddf20c..387083424 100644 --- a/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx +++ b/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx @@ -10,7 +10,7 @@ export default ({ users }: { users: { data: User[] } }) => {
Loading more users...
)} > - {({ loading, loadingPrevious, loadingNext }) => users.data.map((user) => )} + {() => users.data.map((user) => )} ) } diff --git a/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx b/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx index 8b8edda88..5e0578639 100644 --- a/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx +++ b/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx @@ -1,6 +1,6 @@ import { InfiniteScrollRef } from '@inertiajs/core' import { InfiniteScroll } from '@inertiajs/react' -import { useEffect, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import UserCard, { User } from './UserCard' export default ({ users }: { users: { data: User[] } }) => { @@ -8,10 +8,10 @@ export default ({ users }: { users: { data: User[] } }) => { const [hasPrevious, setHasMoreBefore] = useState(false) const [hasNext, setHasMoreAfter] = useState(false) - const updateStates = () => { + const updateStates = useCallback(() => { setHasMoreBefore(infRef?.hasPrevious() || false) setHasMoreAfter(infRef?.hasNext() || false) - } + }, [infRef]) const fetchNext = () => { if (infRef) { @@ -27,7 +27,7 @@ export default ({ users }: { users: { data: User[] } }) => { useEffect(() => { updateStates() - }, [infRef]) + }, [infRef, updateStates]) return (
diff --git a/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx b/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx index 90d20c4af..ea9f2217c 100644 --- a/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx +++ b/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx @@ -4,7 +4,7 @@ import { User } from './UserCard' export default ({ users }: { users: { data: User[] } }) => { return ( - {({ loadingPrevious, loadingNext }) => ( + {() => ( {users.data.map((user) => ( diff --git a/packages/react/test-app/Pages/Links/AsComponent.tsx b/packages/react/test-app/Pages/Links/AsComponent.tsx index 6b17de88d..6f882c2c1 100644 --- a/packages/react/test-app/Pages/Links/AsComponent.tsx +++ b/packages/react/test-app/Pages/Links/AsComponent.tsx @@ -3,13 +3,13 @@ import { useRef } from 'react' declare global { interface Window { - componentEvents: Array<{ eventName: string; data: any; timestamp: number }> + componentEvents: Array<{ eventName: string; data: unknown; timestamp: number }> } } window.componentEvents = [] -const CustomButton = ({ children, ...props }: { children: React.ReactNode; [key: string]: any }) => ( +const CustomButton = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => ( diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/Filtering.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/Filtering.svelte index 7c7ef2de3..92807b596 100644 --- a/packages/svelte/test-app/Pages/InfiniteScroll/Filtering.svelte +++ b/packages/svelte/test-app/Pages/InfiniteScroll/Filtering.svelte @@ -43,6 +43,7 @@ } : { replace: true }, ) + // eslint-disable-next-line svelte/infinite-reactive-loop previousSearch = $form.search }, 250) } diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte index 36e1b9518..961225877 100644 --- a/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte +++ b/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte @@ -2,10 +2,11 @@ import { InfiniteScroll } from '@inertiajs/svelte' import { onMount } from 'svelte' import UserCard, { type User } from './UserCard.svelte' + import type { InfiniteScrollRef } from '@inertiajs/core' export let users: { data: User[] } // Use the actual component type like Form component does - let infRef: any = null + let infRef: InfiniteScrollRef | null = null let hasPrevious = false let hasNext = false @@ -15,15 +16,11 @@ } function fetchNext() { - if (infRef) { - infRef.fetchNext({ onFinish: updateStates }) - } + infRef?.fetchNext({ onFinish: updateStates }) } function fetchPrevious() { - if (infRef) { - infRef.fetchPrevious({ onFinish: updateStates }) - } + infRef?.fetchPrevious({ onFinish: updateStates }) } onMount(() => setTimeout(updateStates)) diff --git a/packages/svelte/test-app/Pages/Links/PreserveUrl.svelte b/packages/svelte/test-app/Pages/Links/PreserveUrl.svelte index b960e4deb..73d66f8d6 100644 --- a/packages/svelte/test-app/Pages/Links/PreserveUrl.svelte +++ b/packages/svelte/test-app/Pages/Links/PreserveUrl.svelte @@ -35,7 +35,7 @@ {#if items}
- {#each items.data as item} + {#each items.data as item, index (index)}
{item}
{/each}
diff --git a/packages/svelte/test-app/Pages/MatchPropsOnKey.svelte b/packages/svelte/test-app/Pages/MatchPropsOnKey.svelte index bb6a5e07d..9b0998943 100644 --- a/packages/svelte/test-app/Pages/MatchPropsOnKey.svelte +++ b/packages/svelte/test-app/Pages/MatchPropsOnKey.svelte @@ -1,16 +1,22 @@ @@ -13,7 +13,7 @@ let logs: string[] = [] - const log = (...args: any[]) => { + const log = (...args: unknown[]) => { const message = args.join(' ') window.progressTests.push(...args) logs = [...logs, message] diff --git a/packages/svelte/test-app/eslint.config.js b/packages/svelte/test-app/eslint.config.js new file mode 100644 index 000000000..1b1852ccd --- /dev/null +++ b/packages/svelte/test-app/eslint.config.js @@ -0,0 +1,59 @@ +import js from '@eslint/js' +import svelte from 'eslint-plugin-svelte' +import globals from 'globals' +import ts from 'typescript-eslint' +import svelteConfig from './svelte.config.js' + +export default ts.config( + { + files: ['**/*.js', '**/*.ts', '**/*.svelte'], + }, + { + ignores: ['node_modules', 'dist/**/*', '*.config.js', '**/*.d.ts'], + }, + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs.recommended, + { + languageOptions: { + ecmaVersion: 2020, + sourceType: 'module', + globals: { + ...globals.browser, + ...globals.es2020, + }, + }, + }, + { + files: ['**/*.ts', '**/*.svelte'], + // See more details at: https://typescript-eslint.io/packages/parser/ + languageOptions: { + parserOptions: { + projectService: true, + extraFileExtensions: ['.svelte'], // Add support for additional file extensions, such as .svelte + parser: ts.parser, + // Specify a parser for each language, if needed: + // parser: { + // ts: ts.parser, + // js: espree, // Use espree for .js files (add: import espree from 'espree') + // typescript: ts.parser + // }, + + // We recommend importing and specifying svelte.config.js. + // By doing so, some rules in eslint-plugin-svelte will automatically read the configuration and adjust their behavior accordingly. + // While certain Svelte settings may be statically loaded from svelte.config.js even if you don’t specify it, + // explicitly specifying it ensures better compatibility and functionality. + // + // If non-serializable properties are included, running ESLint with the --cache flag will fail. + // In that case, please remove the non-serializable properties. (e.g. `svelteConfig: { ...svelteConfig, kit: { ...svelteConfig.kit, typescript: undefined }}`) + svelteConfig, + }, + }, + }, + { + rules: { + 'svelte/no-navigation-without-resolve': 'off', + 'svelte/no-useless-mustaches': 'off', + }, + }, +) diff --git a/packages/svelte/test-app/package.json b/packages/svelte/test-app/package.json index 322e595c0..1c20d49a0 100644 --- a/packages/svelte/test-app/package.json +++ b/packages/svelte/test-app/package.json @@ -3,15 +3,22 @@ "scripts": { "build": "vite build .", "dev": "nodemon --watch . --watch ../../core/dist --watch ../../svelte/dist --ext js,ts,svelte,html,json --ignore dist/ --exec 'vite build .'", + "lint": "eslint .", "type-check": "svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { + "@eslint/js": "^9.38.0", + "@sveltejs/eslint-config": "^8.3.4", "@sveltejs/vite-plugin-svelte": "^3.1.2", "@tsconfig/svelte": "^5.0.5", + "eslint": "^9.38.0", + "eslint-plugin-svelte": "^3.12.5", + "globals": "^16.4.0", "nodemon": "^3.1.10", "svelte": "^4.2.20", "svelte-check": "^4.3.3", "typescript": "^5.9.3", + "typescript-eslint": "^8.46.2", "vite": "^5.4.21" }, "dependencies": { diff --git a/packages/svelte/test-app/svelte-html.d.ts b/packages/svelte/test-app/svelte-html.d.ts new file mode 100644 index 000000000..8c877c476 --- /dev/null +++ b/packages/svelte/test-app/svelte-html.d.ts @@ -0,0 +1,7 @@ +declare module 'svelte/elements' { + export interface HTMLAttributes { + 'scroll-region'?: boolean | '' | undefined + } +} + +export {} diff --git a/packages/svelte/test-app/svelte.config.js b/packages/svelte/test-app/svelte.config.js index 171e710a4..7bb74fd41 100644 --- a/packages/svelte/test-app/svelte.config.js +++ b/packages/svelte/test-app/svelte.config.js @@ -1,12 +1,6 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' const config = { - onwarn(warning, onwarn) { - if (/A11y/.test(warning.message)) return - - onwarn(warning) - }, - // Consult https://kit.svelte.dev/docs/integrations#preprocessors // for more information about preprocessors preprocess: vitePreprocess(), diff --git a/packages/svelte/test-app/types.d.ts b/packages/svelte/test-app/types.d.ts index d661c5c57..d682c2765 100644 --- a/packages/svelte/test-app/types.d.ts +++ b/packages/svelte/test-app/types.d.ts @@ -9,9 +9,10 @@ declare global { _inertia_request_dump: { headers: Record method: Method - form: Record | undefined + form: Record | undefined files: MulterFile[] | object - query: Record + query: Record + url: string $page: Page } _inertia_page_key: string | undefined diff --git a/packages/vue3/package.json b/packages/vue3/package.json index 804c7e556..07b289774 100644 --- a/packages/vue3/package.json +++ b/packages/vue3/package.json @@ -51,7 +51,7 @@ "es2020-check": "pnpm build:with-deps && es-check es2020 \"dist/index.esm.js\" --checkFeatures --module --noCache --verbose" }, "devDependencies": { - "@types/node": "^22.18.10", + "@types/node": "^22.18.12", "axios": "^1.12.2", "es-check": "^9.4.4", "esbuild": "^0.25.11", diff --git a/packages/vue3/test-app/Pages/ClientSideVisit/Page1.vue b/packages/vue3/test-app/Pages/ClientSideVisit/Page1.vue index 6356434be..5620feaa7 100644 --- a/packages/vue3/test-app/Pages/ClientSideVisit/Page1.vue +++ b/packages/vue3/test-app/Pages/ClientSideVisit/Page1.vue @@ -8,7 +8,7 @@ interface PageProps { bar: string } -const props = defineProps() +defineProps() const errors = ref(0) const finished = ref(0) diff --git a/packages/vue3/test-app/Pages/Dump.vue b/packages/vue3/test-app/Pages/Dump.vue index bd8e30239..096c30c93 100644 --- a/packages/vue3/test-app/Pages/Dump.vue +++ b/packages/vue3/test-app/Pages/Dump.vue @@ -7,9 +7,9 @@ import type { MulterFile } from '../types' const props = defineProps<{ headers: Record method: Method - form: Record | undefined + form: Record | undefined files: MulterFile[] | object - query: Record + query: Record url: string }>() diff --git a/packages/vue3/test-app/Pages/Events.vue b/packages/vue3/test-app/Pages/Events.vue index d02b284ad..b46278a1d 100644 --- a/packages/vue3/test-app/Pages/Events.vue +++ b/packages/vue3/test-app/Pages/Events.vue @@ -3,7 +3,7 @@ import { Link, router, usePage } from '@inertiajs/vue3' declare global { interface Window { - messages: any[] + messages: unknown[] } } @@ -15,7 +15,7 @@ const page = usePage() window.messages = [] -const internalAlert = (...args: any[]) => { +const internalAlert = (...args: unknown[]) => { window.messages.push(...args) } @@ -82,7 +82,7 @@ const beforeVisitPreventLocal = () => { const beforeVisitPreventGlobalInertia = () => { document.addEventListener('inertia:before', () => internalAlert('addEventListener(inertia:before)')) - router.on('before', (visit) => { + router.on('before', () => { internalAlert('Inertia.on(before)') return false }) @@ -490,7 +490,7 @@ const callbackSuccessErrorPromise = (eventName: string) => { :href="$page.url" method="post" @before=" - (visit) => { + () => { internalAlert('linkOnBefore') return false } diff --git a/packages/vue3/test-app/Pages/FormComponent/Reset.vue b/packages/vue3/test-app/Pages/FormComponent/Reset.vue index 03ea2afb4..e97937bc6 100644 --- a/packages/vue3/test-app/Pages/FormComponent/Reset.vue +++ b/packages/vue3/test-app/Pages/FormComponent/Reset.vue @@ -1,8 +1,9 @@ diff --git a/packages/vue3/test-app/Pages/FormHelper/Events.vue b/packages/vue3/test-app/Pages/FormHelper/Events.vue index 45598cd14..259c5bc26 100644 --- a/packages/vue3/test-app/Pages/FormHelper/Events.vue +++ b/packages/vue3/test-app/Pages/FormHelper/Events.vue @@ -126,7 +126,7 @@ const onBeforeVisit = () => { const onBeforeVisitCancelled = () => { form.post('/sleep', { ...callbacks({ - onBefore: (visit: PendingVisit) => { + onBefore: () => { pushEvent('onBefore') return false }, @@ -190,7 +190,7 @@ const onSuccessVisit = () => { const onSuccessPromiseVisit = () => { form.post('/dump/post', { ...callbacks({ - onSuccess: (page: Page) => { + onSuccess: () => { pushEvent('onSuccess') setTimeout(() => pushEvent('onFinish should have been fired by now if Promise functionality did not work'), 5) @@ -203,7 +203,7 @@ const onSuccessPromiseVisit = () => { const onSuccessResetValue = () => { form.post(page.url, { ...callbacks({ - onSuccess: (page: Page) => { + onSuccess: () => { form.reset() }, }), @@ -224,7 +224,7 @@ const onErrorVisit = () => { const onErrorPromiseVisit = () => { form.post('/form-helper/events/errors', { ...callbacks({ - onError: (errors: Errors) => { + onError: () => { pushEvent('onError') setTimeout(() => pushEvent('onFinish should have been fired by now if Promise functionality did not work'), 5) diff --git a/packages/vue3/test-app/Pages/FormHelper/RememberEdit.vue b/packages/vue3/test-app/Pages/FormHelper/RememberEdit.vue index f2fe02b56..d8c463eb4 100644 --- a/packages/vue3/test-app/Pages/FormHelper/RememberEdit.vue +++ b/packages/vue3/test-app/Pages/FormHelper/RememberEdit.vue @@ -1,8 +1,11 @@ - diff --git a/packages/vue3/test-app/Pages/FormHelper/TypeScript/DynamicInputName.vue b/packages/vue3/test-app/Pages/FormHelper/TypeScript/DynamicInputName.vue index b779cbe44..1316cfd0c 100644 --- a/packages/vue3/test-app/Pages/FormHelper/TypeScript/DynamicInputName.vue +++ b/packages/vue3/test-app/Pages/FormHelper/TypeScript/DynamicInputName.vue @@ -4,7 +4,7 @@ import { useForm } from '@inertiajs/vue3' interface ClientForm { name: string - [key: string]: any + [key: string]: any // eslint-disable-line @typescript-eslint/no-explicit-any } const form = useForm({ diff --git a/packages/vue3/test-app/Pages/FormHelper/TypeScript/Errors.vue b/packages/vue3/test-app/Pages/FormHelper/TypeScript/Errors.vue index f7b409917..2c8fe44d5 100644 --- a/packages/vue3/test-app/Pages/FormHelper/TypeScript/Errors.vue +++ b/packages/vue3/test-app/Pages/FormHelper/TypeScript/Errors.vue @@ -17,8 +17,8 @@ const defaultData = { const form = useForm(defaultData) // Get Errors -form.errors.name -form.errors['company.name'] +console.log(form.errors.name) +console.log(form.errors['company.name']) // Clear Errors form.clearErrors('name') @@ -53,9 +53,9 @@ form.setError({ 'users.0': 'Validation error' }) form.setError({ 'users.0.name': 'Validation error' }) // @ts-expect-error - Form has no email field -form.errors.email +console.log(form.errors.email) // @ts-expect-error - Company has no email field -form.errors['company.email'] +console.log(form.errors['company.email']) // @ts-expect-error - Form has no email field form.clearErrors('email') diff --git a/packages/vue3/test-app/Pages/FormHelper/TypeScript/Generic.vue b/packages/vue3/test-app/Pages/FormHelper/TypeScript/Generic.vue index 53db02645..871dfe2ae 100644 --- a/packages/vue3/test-app/Pages/FormHelper/TypeScript/Generic.vue +++ b/packages/vue3/test-app/Pages/FormHelper/TypeScript/Generic.vue @@ -3,7 +3,7 @@ import type { FormDataConvertible } from '@inertiajs/core' import type { InertiaForm } from '@inertiajs/vue3' -const props = defineProps<{ +defineProps<{ form: InertiaForm }>() diff --git a/packages/vue3/test-app/Pages/FormHelper/TypeScript/ValidationKey.vue b/packages/vue3/test-app/Pages/FormHelper/TypeScript/ValidationKey.vue index 82dc72a02..b0f5682c3 100644 --- a/packages/vue3/test-app/Pages/FormHelper/TypeScript/ValidationKey.vue +++ b/packages/vue3/test-app/Pages/FormHelper/TypeScript/ValidationKey.vue @@ -19,3 +19,7 @@ const validation = >(errors: () => return { filterAndMap, unique } } + + diff --git a/packages/vue3/test-app/Pages/Home.vue b/packages/vue3/test-app/Pages/Home.vue index 0ae60a726..03415b10e 100644 --- a/packages/vue3/test-app/Pages/Home.vue +++ b/packages/vue3/test-app/Pages/Home.vue @@ -1,5 +1,5 @@