From 8ff9839b881bf98c7fb99b5ef2dc9ace3e9618c4 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 00:10:11 +0800 Subject: [PATCH 01/19] update eslint docs --- documentation/docs/30-add-ons/10-eslint.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/30-add-ons/10-eslint.md b/documentation/docs/30-add-ons/10-eslint.md index d12aed33f..70438105d 100644 --- a/documentation/docs/30-add-ons/10-eslint.md +++ b/documentation/docs/30-add-ons/10-eslint.md @@ -14,5 +14,5 @@ npx sv add eslint - the relevant packages installed including `eslint-plugin-svelte` - an `eslint.config.js` file -- updated `.vscode/settings.json` +- updated `.vscode/extensions.json` - configured to work with TypeScript and `prettier` if you're using those packages From f0f2bbd24b3944b5b0d984d9beca2ea6274ef16a Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 00:10:30 +0800 Subject: [PATCH 02/19] add a placeholder for rules --- packages/sv/src/addons/eslint.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/sv/src/addons/eslint.ts b/packages/sv/src/addons/eslint.ts index ec48acfcb..a26497eda 100644 --- a/packages/sv/src/addons/eslint.ts +++ b/packages/sv/src/addons/eslint.ts @@ -109,6 +109,23 @@ export default defineAddon({ eslintConfigs.push(svelteTSParserConfig); } + const rulesOverride = js.object.create({ + rules: {} + }); + eslintConfigs.push(rulesOverride); + + if (rulesOverride.properties[0].type !== 'Property') { + throw new Error('rulesOverride.properties[0].type !== "Property"'); + } + comments.add(rulesOverride.properties[0].key, { + type: 'Line', + value: ' Override or add rule settings here, such as:' + }); + comments.add(rulesOverride.properties[0].key, { + type: 'Line', + value: " 'svelte/rule-name': 'error'" + }); + const exportExpression = js.functions.createCall({ name: 'defineConfig', args: [] }); if (typescript) { exportExpression.arguments.push(...eslintConfigs); From 320c44bab597046cc81f33f5489a8a82af502b7d Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 00:10:50 +0800 Subject: [PATCH 03/19] improve eslint scanning --- packages/sv/src/addons/common.ts | 80 +++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index 23605fe11..f7e581f7f 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -19,8 +19,8 @@ export function addEslintConfigPrettier(content: string): string { svelteImportName = specifier.local.name as string; } } - svelteImportName ??= 'svelte'; + js.imports.addDefault(ast, { from: 'eslint-plugin-svelte', as: svelteImportName }); js.imports.addDefault(ast, { from: 'eslint-config-prettier', as: 'prettier' }); @@ -38,24 +38,68 @@ export function addEslintConfigPrettier(content: string): string { if (!js.common.contains(eslintConfig, sveltePrettierConfig)) nodesToInsert.push(sveltePrettierConfig); - const elements = - eslintConfig.type === 'ArrayExpression' ? eslintConfig.elements : eslintConfig.arguments; - // finds index of `svelte.configs["..."]` - const idx = elements.findIndex( - (el) => - el?.type === 'MemberExpression' && - el.object.type === 'MemberExpression' && - el.object.property.type === 'Identifier' && - el.object.property.name === 'configs' && - el.object.object.type === 'Identifier' && - el.object.object.name === svelteImportName - ); + if (eslintConfig.type === 'CallExpression') { + // export default defineConfig(...) + if ( + eslintConfig.arguments.length === 1 && + eslintConfig.arguments[0].type === 'ArrayExpression' + ) { + // javascript defineConfig([...]) + const idx = eslintConfig.arguments[0].elements.findIndex( + (el) => + el?.type === 'MemberExpression' && + el.object.type === 'MemberExpression' && + el.object.property.type === 'Identifier' && + el.object.property.name === 'configs' && + el.object.object.type === 'Identifier' && + el.object.object.name === svelteImportName + ); + if (idx !== -1) { + eslintConfig.arguments[0].elements.splice(idx + 1, 0, ...nodesToInsert); + } else { + // append to the end as a fallback + eslintConfig.arguments[0].elements.push(...nodesToInsert); + } + } else { + //typescript defineConfig(...) + const idx = eslintConfig.arguments.findIndex( + (el) => + el?.type === 'MemberExpression' && + el.object.type === 'MemberExpression' && + el.object.property.type === 'Identifier' && + el.object.property.name === 'configs' && + el.object.object.type === 'Identifier' && + el.object.object.name === svelteImportName + ); + if (idx !== -1) { + eslintConfig.arguments.splice(idx + 1, 0, ...nodesToInsert); + } else { + // append to the end as a fallback + eslintConfig.arguments.push(...nodesToInsert); + } + } + } - if (idx !== -1) { - elements.splice(idx + 1, 0, ...nodesToInsert); - } else { - // append to the end as a fallback - elements.push(...nodesToInsert); + // export default [] + if (eslintConfig.type === 'ArrayExpression') { + // find index of `...svelte.configs["..."]` + const idx = eslintConfig.elements.findIndex( + (el) => + el?.type === 'SpreadElement' && + el.argument.type === 'MemberExpression' && + el.argument.object.type === 'MemberExpression' && + el.argument.object.property.type === 'Identifier' && + el.argument.object.property.name === 'configs' && + el.argument.object.object.type === 'Identifier' && + el.argument.object.object.name === svelteImportName + ); + + if (idx !== -1) { + eslintConfig.elements.splice(idx + 1, 0, ...nodesToInsert); + } else { + // append to the end as a fallback + eslintConfig.elements.push(...nodesToInsert); + } } return generateCode(); From a0f007a684f8dd0703241831b684ddc6ec6ec202 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 00:34:38 +0800 Subject: [PATCH 04/19] named predicates --- packages/sv/src/addons/common.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index f7e581f7f..55b9e48ad 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -27,8 +27,11 @@ export function addEslintConfigPrettier(content: string): string { const fallbackConfig = js.common.parseExpression('[]'); const defaultExport = js.exports.createDefault(ast, { fallback: fallbackConfig }); const eslintConfig = defaultExport.value; - if (eslintConfig.type !== 'ArrayExpression' && eslintConfig.type !== 'CallExpression') - return content; + + const isDefineConfig = eslintConfig.type === 'CallExpression'; // export default defineConfig() + const isArrayExport = eslintConfig.type === 'ArrayExpression'; // export default [] + + if (!isArrayExport && !isDefineConfig) return content; const prettier = js.common.parseExpression('prettier'); const sveltePrettierConfig = js.common.parseExpression(`${svelteImportName}.configs.prettier`); @@ -38,13 +41,12 @@ export function addEslintConfigPrettier(content: string): string { if (!js.common.contains(eslintConfig, sveltePrettierConfig)) nodesToInsert.push(sveltePrettierConfig); - if (eslintConfig.type === 'CallExpression') { - // export default defineConfig(...) + if (isDefineConfig) { if ( eslintConfig.arguments.length === 1 && eslintConfig.arguments[0].type === 'ArrayExpression' ) { - // javascript defineConfig([...]) + // javascript - defineConfig([...]) const idx = eslintConfig.arguments[0].elements.findIndex( (el) => el?.type === 'MemberExpression' && @@ -61,7 +63,7 @@ export function addEslintConfigPrettier(content: string): string { eslintConfig.arguments[0].elements.push(...nodesToInsert); } } else { - //typescript defineConfig(...) + //typescript - defineConfig(...) const idx = eslintConfig.arguments.findIndex( (el) => el?.type === 'MemberExpression' && @@ -80,8 +82,7 @@ export function addEslintConfigPrettier(content: string): string { } } - // export default [] - if (eslintConfig.type === 'ArrayExpression') { + if (isArrayExport) { // find index of `...svelte.configs["..."]` const idx = eslintConfig.elements.findIndex( (el) => From 6b3f5f2582ccf3815052e91fa54db1535e73083d Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 00:34:48 +0800 Subject: [PATCH 05/19] flatten --- packages/sv/src/addons/common.ts | 75 +++++++++++--------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index 55b9e48ad..e829c2e1b 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -16,7 +16,7 @@ export function addEslintConfigPrettier(content: string): string { let svelteImportName: string; for (const specifier of sveltePluginImport?.specifiers ?? []) { if (specifier.type === 'ImportDefaultSpecifier' && specifier.local?.name) { - svelteImportName = specifier.local.name as string; + svelteImportName = specifier.local.name; } } svelteImportName ??= 'svelte'; @@ -41,64 +41,39 @@ export function addEslintConfigPrettier(content: string): string { if (!js.common.contains(eslintConfig, sveltePrettierConfig)) nodesToInsert.push(sveltePrettierConfig); + // i dont know the type + const isSvelteConfig = (el: any) => { + const maybeSpread = el?.type === 'SpreadElement' ? el?.argument : el; + return ( + maybeSpread?.object.type === 'MemberExpression' && + maybeSpread.object.property.type === 'Identifier' && + maybeSpread.object.property.name === 'configs' && + maybeSpread.object.object.type === 'Identifier' && + maybeSpread.object.object.name === svelteImportName + ); + }; + if (isDefineConfig) { - if ( - eslintConfig.arguments.length === 1 && - eslintConfig.arguments[0].type === 'ArrayExpression' - ) { - // javascript - defineConfig([...]) - const idx = eslintConfig.arguments[0].elements.findIndex( - (el) => - el?.type === 'MemberExpression' && - el.object.type === 'MemberExpression' && - el.object.property.type === 'Identifier' && - el.object.property.name === 'configs' && - el.object.object.type === 'Identifier' && - el.object.object.name === svelteImportName - ); - if (idx !== -1) { - eslintConfig.arguments[0].elements.splice(idx + 1, 0, ...nodesToInsert); - } else { - // append to the end as a fallback - eslintConfig.arguments[0].elements.push(...nodesToInsert); - } + const container = + eslintConfig.arguments.length === 1 && eslintConfig.arguments[0].type === 'ArrayExpression' + ? // javascript - defineConfig([...]) + eslintConfig.arguments[0].elements + : // typescript - defineConfig(...) + eslintConfig.arguments; + + const idx = container.findIndex(isSvelteConfig); + if (idx !== -1) { + container.splice(idx + 1, 0, ...nodesToInsert); } else { - //typescript - defineConfig(...) - const idx = eslintConfig.arguments.findIndex( - (el) => - el?.type === 'MemberExpression' && - el.object.type === 'MemberExpression' && - el.object.property.type === 'Identifier' && - el.object.property.name === 'configs' && - el.object.object.type === 'Identifier' && - el.object.object.name === svelteImportName - ); - if (idx !== -1) { - eslintConfig.arguments.splice(idx + 1, 0, ...nodesToInsert); - } else { - // append to the end as a fallback - eslintConfig.arguments.push(...nodesToInsert); - } + container.push(...nodesToInsert); } } if (isArrayExport) { - // find index of `...svelte.configs["..."]` - const idx = eslintConfig.elements.findIndex( - (el) => - el?.type === 'SpreadElement' && - el.argument.type === 'MemberExpression' && - el.argument.object.type === 'MemberExpression' && - el.argument.object.property.type === 'Identifier' && - el.argument.object.property.name === 'configs' && - el.argument.object.object.type === 'Identifier' && - el.argument.object.object.name === svelteImportName - ); - + const idx = eslintConfig.elements.findIndex(isSvelteConfig); if (idx !== -1) { eslintConfig.elements.splice(idx + 1, 0, ...nodesToInsert); } else { - // append to the end as a fallback eslintConfig.elements.push(...nodesToInsert); } } From 5edfe5b5fcb7165d547e18c711ba4b8be9b6dddd Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 00:58:02 +0800 Subject: [PATCH 06/19] flatten --- packages/sv/src/addons/common.ts | 45 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index e829c2e1b..02a9dcaee 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -45,37 +45,36 @@ export function addEslintConfigPrettier(content: string): string { const isSvelteConfig = (el: any) => { const maybeSpread = el?.type === 'SpreadElement' ? el?.argument : el; return ( - maybeSpread?.object.type === 'MemberExpression' && - maybeSpread.object.property.type === 'Identifier' && - maybeSpread.object.property.name === 'configs' && - maybeSpread.object.object.type === 'Identifier' && - maybeSpread.object.object.name === svelteImportName + maybeSpread?.object?.type === 'MemberExpression' && + maybeSpread?.object?.property?.type === 'Identifier' && + maybeSpread?.object?.property?.name === 'configs' && + maybeSpread?.object?.object?.type === 'Identifier' && + maybeSpread?.object?.object?.name === svelteImportName ); }; + // i dont know the type + let elements: any; + if (isArrayExport) elements = eslintConfig.elements; + if (isDefineConfig) { - const container = - eslintConfig.arguments.length === 1 && eslintConfig.arguments[0].type === 'ArrayExpression' - ? // javascript - defineConfig([...]) - eslintConfig.arguments[0].elements - : // typescript - defineConfig(...) - eslintConfig.arguments; - - const idx = container.findIndex(isSvelteConfig); - if (idx !== -1) { - container.splice(idx + 1, 0, ...nodesToInsert); + if ( + eslintConfig.arguments.length === 1 && + eslintConfig.arguments[0].type === 'ArrayExpression' + ) { + // javascript - defineConfig([...]) + elements = eslintConfig.arguments[0].elements; } else { - container.push(...nodesToInsert); + // typescript - defineConfig(...) + elements = eslintConfig.arguments; } } - if (isArrayExport) { - const idx = eslintConfig.elements.findIndex(isSvelteConfig); - if (idx !== -1) { - eslintConfig.elements.splice(idx + 1, 0, ...nodesToInsert); - } else { - eslintConfig.elements.push(...nodesToInsert); - } + const idx = elements.findIndex(isSvelteConfig); + if (idx !== -1) { + elements.splice(idx + 1, 0, ...nodesToInsert); + } else { + elements.push(...nodesToInsert); } return generateCode(); From a75694930464a25f55fa75310f902726c3667872 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 01:03:35 +0800 Subject: [PATCH 07/19] convert to `as string` --- packages/sv/src/addons/better-auth.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index 1bc641059..5f3c4ad8f 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -241,8 +241,8 @@ export default defineAddon({ ? ` signInEmail: async (event) => { const formData = await event.request.formData(); - const email = formData.get('email')?.toString() ?? ''; - const password = formData.get('password')?.toString() ?? ''; + const email = (formData.get('email') ?? '') as string; + const password = (formData.get('password') ?? '') as string; try { await auth.api.signInEmail({ @@ -263,9 +263,9 @@ export default defineAddon({ }, signUpEmail: async (event) => { const formData = await event.request.formData(); - const email = formData.get('email')?.toString() ?? ''; - const password = formData.get('password')?.toString() ?? ''; - const name = formData.get('name')?.toString() ?? ''; + const email = (formData.get('email') ?? '') as string; + const password = (formData.get('password') ?? '') as string; + const name = (formData.get('name') ?? '') as string; try { await auth.api.signUpEmail({ @@ -291,8 +291,8 @@ export default defineAddon({ ? ` signInSocial: async (event) => { const formData = await event.request.formData(); - const provider = formData.get('provider')?.toString() ?? 'github'; - const callbackURL = formData.get('callbackURL')?.toString() ?? '/demo/better-auth'; + const provider = (formData.get('provider') ?? 'github') as string; + const callbackURL = (formData.get('callbackURL') ?? '/demo/better-auth') as string; const result = await auth.api.signInSocial({ body: { From 9d82dc4542a2f975839c3ccdb2a10f2cbb1c7fc5 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 01:06:51 +0800 Subject: [PATCH 08/19] remove unused async --- packages/sv/src/addons/better-auth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index 5f3c4ad8f..ca8b54f8c 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -317,7 +317,7 @@ export default defineAddon({ import { auth } from '$lib/server/auth'; ${needsAPIError ? "import { APIError } from 'better-auth/api';" : ''} - export const load${ts(': PageServerLoad')} = async (event) => { + export const load${ts(': PageServerLoad')} = (event) => { if (event.locals.user) { return redirect(302, '/demo/better-auth'); } @@ -406,7 +406,7 @@ export default defineAddon({ ${ts("import type { PageServerLoad } from './$types';")} import { auth } from '$lib/server/auth'; - export const load${ts(': PageServerLoad')} = async (event) => { + export const load${ts(': PageServerLoad')} = (event) => { if (!event.locals.user) { return redirect(302, '/demo/better-auth/login'); } From 62495f44dba4dd0aba0c035afef07cddda2724a7 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Thu, 19 Mar 2026 01:14:00 +0800 Subject: [PATCH 09/19] update snapshot --- .../create-with-all-addons/eslint.config.js | 5 +++++ .../src/routes/demo/better-auth/+page.server.ts | 2 +- .../demo/better-auth/login/+page.server.ts | 16 ++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/eslint.config.js b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/eslint.config.js index bd3865858..2687e9fd1 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/eslint.config.js +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/eslint.config.js @@ -35,5 +35,10 @@ export default defineConfig( svelteConfig } } + }, + { + // Override or add rule settings here, such as: + // 'svelte/rule-name': 'error' + rules: {} } ); diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.server.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.server.ts index 7c3083543..92a1f2ec3 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.server.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.server.ts @@ -3,7 +3,7 @@ import type { Actions } from './$types'; import type { PageServerLoad } from './$types'; import { auth } from '$lib/server/auth'; -export const load: PageServerLoad = async (event) => { +export const load: PageServerLoad = (event) => { if (!event.locals.user) { return redirect(302, '/demo/better-auth/login'); } diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts index 2ddbc0e7c..e5f3c649d 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts @@ -4,7 +4,7 @@ import type { PageServerLoad } from './$types'; import { auth } from '$lib/server/auth'; import { APIError } from 'better-auth/api'; -export const load: PageServerLoad = async (event) => { +export const load: PageServerLoad = (event) => { if (event.locals.user) { return redirect(302, '/demo/better-auth'); } @@ -14,8 +14,8 @@ export const load: PageServerLoad = async (event) => { export const actions: Actions = { signInEmail: async (event) => { const formData = await event.request.formData(); - const email = formData.get('email')?.toString() ?? ''; - const password = formData.get('password')?.toString() ?? ''; + const email = (formData.get('email') ?? '') as string; + const password = (formData.get('password') ?? '') as string; try { await auth.api.signInEmail({ @@ -36,9 +36,9 @@ export const actions: Actions = { }, signUpEmail: async (event) => { const formData = await event.request.formData(); - const email = formData.get('email')?.toString() ?? ''; - const password = formData.get('password')?.toString() ?? ''; - const name = formData.get('name')?.toString() ?? ''; + const email = (formData.get('email') ?? '') as string; + const password = (formData.get('password') ?? '') as string; + const name = (formData.get('name') ?? '') as string; try { await auth.api.signUpEmail({ @@ -60,8 +60,8 @@ export const actions: Actions = { }, signInSocial: async (event) => { const formData = await event.request.formData(); - const provider = formData.get('provider')?.toString() ?? 'github'; - const callbackURL = formData.get('callbackURL')?.toString() ?? '/demo/better-auth'; + const provider = (formData.get('provider') ?? 'github') as string; + const callbackURL = (formData.get('callbackURL') ?? '/demo/better-auth') as string; const result = await auth.api.signInSocial({ body: { From 9b2005ad03c6f72ade000805a4a0f01147412ee3 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Sat, 21 Mar 2026 13:10:04 +0800 Subject: [PATCH 10/19] comments are important --- packages/sv/src/addons/common.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index 02a9dcaee..eb9115631 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -74,6 +74,7 @@ export function addEslintConfigPrettier(content: string): string { if (idx !== -1) { elements.splice(idx + 1, 0, ...nodesToInsert); } else { + // append to the end as a fallback elements.push(...nodesToInsert); } From d6e276c59699914d851fd1c1a2e434a23090523f Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Tue, 24 Mar 2026 14:15:59 +0800 Subject: [PATCH 11/19] fix types --- packages/sv/src/addons/common.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index eb9115631..35df14288 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -42,9 +42,10 @@ export function addEslintConfigPrettier(content: string): string { nodesToInsert.push(sveltePrettierConfig); // i dont know the type - const isSvelteConfig = (el: any) => { + const isSvelteConfig = (el: js.AstTypes.Expression | js.AstTypes.SpreadElement | null) => { const maybeSpread = el?.type === 'SpreadElement' ? el?.argument : el; return ( + maybeSpread?.type === 'MemberExpression' && maybeSpread?.object?.type === 'MemberExpression' && maybeSpread?.object?.property?.type === 'Identifier' && maybeSpread?.object?.property?.name === 'configs' && @@ -54,7 +55,7 @@ export function addEslintConfigPrettier(content: string): string { }; // i dont know the type - let elements: any; + let elements: Array = []; if (isArrayExport) elements = eslintConfig.elements; if (isDefineConfig) { From 110e74629c8c7761d093aad540f0401a217a86fb Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Tue, 24 Mar 2026 15:05:29 +0800 Subject: [PATCH 12/19] fix again --- packages/sv/src/addons/common.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index 35df14288..054b705b1 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -33,6 +33,9 @@ export function addEslintConfigPrettier(content: string): string { if (!isArrayExport && !isDefineConfig) return content; + type Arguments = Extract['arguments']; + type Elements = Extract['elements']; + const prettier = js.common.parseExpression('prettier'); const sveltePrettierConfig = js.common.parseExpression(`${svelteImportName}.configs.prettier`); @@ -41,8 +44,7 @@ export function addEslintConfigPrettier(content: string): string { if (!js.common.contains(eslintConfig, sveltePrettierConfig)) nodesToInsert.push(sveltePrettierConfig); - // i dont know the type - const isSvelteConfig = (el: js.AstTypes.Expression | js.AstTypes.SpreadElement | null) => { + const isSvelteConfig = (el: (Arguments | Elements)[number]) => { const maybeSpread = el?.type === 'SpreadElement' ? el?.argument : el; return ( maybeSpread?.type === 'MemberExpression' && @@ -54,8 +56,7 @@ export function addEslintConfigPrettier(content: string): string { ); }; - // i dont know the type - let elements: Array = []; + let elements: Arguments | Elements = []; if (isArrayExport) elements = eslintConfig.elements; if (isDefineConfig) { From 056f90dc3c4d26f56ea8d840d5bbea6a8c71fbe5 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Tue, 24 Mar 2026 15:19:00 +0800 Subject: [PATCH 13/19] no more `as string` --- packages/sv/src/addons/better-auth.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index ca8b54f8c..e22272fa6 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -241,8 +241,8 @@ export default defineAddon({ ? ` signInEmail: async (event) => { const formData = await event.request.formData(); - const email = (formData.get('email') ?? '') as string; - const password = (formData.get('password') ?? '') as string; + const email = typeof formData.get('email') === 'string') ? formData.get('email') : ''; + const password = typeof formData.get('password') === 'string') ? formData.get('password') : ''; try { await auth.api.signInEmail({ @@ -263,9 +263,9 @@ export default defineAddon({ }, signUpEmail: async (event) => { const formData = await event.request.formData(); - const email = (formData.get('email') ?? '') as string; - const password = (formData.get('password') ?? '') as string; - const name = (formData.get('name') ?? '') as string; + const email = typeof formData.get('email') === 'string') ? formData.get('email') : ''; + const password = typeof formData.get('password') === 'string') ? formData.get('password') : ''; + const name = typeof formData.get('name') === 'string') ? formData.get('name') : ''; try { await auth.api.signUpEmail({ @@ -291,8 +291,9 @@ export default defineAddon({ ? ` signInSocial: async (event) => { const formData = await event.request.formData(); - const provider = (formData.get('provider') ?? 'github') as string; - const callbackURL = (formData.get('callbackURL') ?? '/demo/better-auth') as string; + + const provider = typeof formData.get('provider') === 'string') ? formData.get('provider') : 'github'; + const callbackURL = typeof formData.get('callbackURL') === 'string') ? formData.get('callbackURL') : '/demo/better-auth'; const result = await auth.api.signInSocial({ body: { From 132cf17c08d732a96cbb94938da16047b4b251ae Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Tue, 24 Mar 2026 15:26:45 +0800 Subject: [PATCH 14/19] . --- packages/sv/src/addons/better-auth.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index e22272fa6..e2f714fb7 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -241,8 +241,8 @@ export default defineAddon({ ? ` signInEmail: async (event) => { const formData = await event.request.formData(); - const email = typeof formData.get('email') === 'string') ? formData.get('email') : ''; - const password = typeof formData.get('password') === 'string') ? formData.get('password') : ''; + const email = typeof formData.get('email') === 'string' ? formData.get('email') : ''; + const password = typeof formData.get('password') === 'string' ? formData.get('password') : ''; try { await auth.api.signInEmail({ @@ -263,9 +263,9 @@ export default defineAddon({ }, signUpEmail: async (event) => { const formData = await event.request.formData(); - const email = typeof formData.get('email') === 'string') ? formData.get('email') : ''; + const email = typeof formData.get('email') === 'string' ? formData.get('email') : ''; const password = typeof formData.get('password') === 'string') ? formData.get('password') : ''; - const name = typeof formData.get('name') === 'string') ? formData.get('name') : ''; + const name = typeof formData.get('name') === 'string' ? formData.get('name') : ''; try { await auth.api.signUpEmail({ @@ -292,8 +292,8 @@ export default defineAddon({ signInSocial: async (event) => { const formData = await event.request.formData(); - const provider = typeof formData.get('provider') === 'string') ? formData.get('provider') : 'github'; - const callbackURL = typeof formData.get('callbackURL') === 'string') ? formData.get('callbackURL') : '/demo/better-auth'; + const provider = typeof formData.get('provider') === 'string' ? formData.get('provider') : 'github'; + const callbackURL = typeof formData.get('callbackURL') === 'string' ? formData.get('callbackURL') : '/demo/better-auth'; const result = await auth.api.signInSocial({ body: { From 21e3b26accecf93a49af0230c77d9c41f2be09c2 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Sat, 28 Mar 2026 21:16:05 +0800 Subject: [PATCH 15/19] . --- packages/sv/src/addons/better-auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index e2f714fb7..fe6533a45 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -264,7 +264,7 @@ export default defineAddon({ signUpEmail: async (event) => { const formData = await event.request.formData(); const email = typeof formData.get('email') === 'string' ? formData.get('email') : ''; - const password = typeof formData.get('password') === 'string') ? formData.get('password') : ''; + const password = typeof formData.get('password') === 'string' ? formData.get('password') : ''; const name = typeof formData.get('name') === 'string' ? formData.get('name') : ''; try { From 211f34b52245d7f84076399e276b9478e7d3d859 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Sat, 28 Mar 2026 21:38:47 +0800 Subject: [PATCH 16/19] snapshot --- .../routes/demo/better-auth/login/+page.server.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts index e5f3c649d..4a884034a 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/login/+page.server.ts @@ -14,8 +14,8 @@ export const load: PageServerLoad = (event) => { export const actions: Actions = { signInEmail: async (event) => { const formData = await event.request.formData(); - const email = (formData.get('email') ?? '') as string; - const password = (formData.get('password') ?? '') as string; + const email = typeof formData.get('email') === 'string' ? formData.get('email') : ''; + const password = typeof formData.get('password') === 'string' ? formData.get('password') : ''; try { await auth.api.signInEmail({ @@ -36,9 +36,9 @@ export const actions: Actions = { }, signUpEmail: async (event) => { const formData = await event.request.formData(); - const email = (formData.get('email') ?? '') as string; - const password = (formData.get('password') ?? '') as string; - const name = (formData.get('name') ?? '') as string; + const email = typeof formData.get('email') === 'string' ? formData.get('email') : ''; + const password = typeof formData.get('password') === 'string' ? formData.get('password') : ''; + const name = typeof formData.get('name') === 'string' ? formData.get('name') : ''; try { await auth.api.signUpEmail({ @@ -60,8 +60,9 @@ export const actions: Actions = { }, signInSocial: async (event) => { const formData = await event.request.formData(); - const provider = (formData.get('provider') ?? 'github') as string; - const callbackURL = (formData.get('callbackURL') ?? '/demo/better-auth') as string; + + const provider = typeof formData.get('provider') === 'string' ? formData.get('provider') : 'github'; + const callbackURL = typeof formData.get('callbackURL') === 'string' ? formData.get('callbackURL') : '/demo/better-auth'; const result = await auth.api.signInSocial({ body: { From 5a9438a529a68e2d6db684794893fdf580933c56 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Sat, 28 Mar 2026 21:58:39 +0800 Subject: [PATCH 17/19] nit --- packages/sv/src/addons/common.ts | 37 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index 054b705b1..a11387fa5 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -29,12 +29,13 @@ export function addEslintConfigPrettier(content: string): string { const eslintConfig = defaultExport.value; const isDefineConfig = eslintConfig.type === 'CallExpression'; // export default defineConfig() - const isArrayExport = eslintConfig.type === 'ArrayExpression'; // export default [] + const isArray = eslintConfig.type === 'ArrayExpression'; // export default [] - if (!isArrayExport && !isDefineConfig) return content; + if (!isArray && !isDefineConfig) return content; - type Arguments = Extract['arguments']; - type Elements = Extract['elements']; + type Elements = + | Extract['arguments'] + | Extract['elements']; const prettier = js.common.parseExpression('prettier'); const sveltePrettierConfig = js.common.parseExpression(`${svelteImportName}.configs.prettier`); @@ -44,20 +45,8 @@ export function addEslintConfigPrettier(content: string): string { if (!js.common.contains(eslintConfig, sveltePrettierConfig)) nodesToInsert.push(sveltePrettierConfig); - const isSvelteConfig = (el: (Arguments | Elements)[number]) => { - const maybeSpread = el?.type === 'SpreadElement' ? el?.argument : el; - return ( - maybeSpread?.type === 'MemberExpression' && - maybeSpread?.object?.type === 'MemberExpression' && - maybeSpread?.object?.property?.type === 'Identifier' && - maybeSpread?.object?.property?.name === 'configs' && - maybeSpread?.object?.object?.type === 'Identifier' && - maybeSpread?.object?.object?.name === svelteImportName - ); - }; - - let elements: Arguments | Elements = []; - if (isArrayExport) elements = eslintConfig.elements; + let elements: Elements = []; + if (isArray) elements = eslintConfig.elements; if (isDefineConfig) { if ( @@ -72,6 +61,18 @@ export function addEslintConfigPrettier(content: string): string { } } + const isSvelteConfig = (maybeSpread: Elements[number]) => { + const el = maybeSpread?.type === 'SpreadElement' ? maybeSpread?.argument : maybeSpread; + return ( + el && + el.type === 'MemberExpression' && + el.object.type === 'MemberExpression' && + el.object.object.type === 'Identifier' && + el.object.object.name === svelteImportName && + el.object.property.type === 'Identifier' && + el.object.property.name === 'configs' + ); + }; const idx = elements.findIndex(isSvelteConfig); if (idx !== -1) { elements.splice(idx + 1, 0, ...nodesToInsert); From f6bfca552a2af0dbd4beef4844f8602804ed22e2 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Sat, 28 Mar 2026 22:18:32 +0800 Subject: [PATCH 18/19] comment --- packages/sv/src/addons/common.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index a11387fa5..f4921c82c 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -62,13 +62,19 @@ export function addEslintConfigPrettier(content: string): string { } const isSvelteConfig = (maybeSpread: Elements[number]) => { - const el = maybeSpread?.type === 'SpreadElement' ? maybeSpread?.argument : maybeSpread; + const el = + maybeSpread?.type === 'SpreadElement' + ? // ...svelte.configs.* + maybeSpread?.argument + : // svelte.configs.* + maybeSpread; return ( - el && - el.type === 'MemberExpression' && + el?.type === 'MemberExpression' && el.object.type === 'MemberExpression' && + // Check for [svelte].configs.* el.object.object.type === 'Identifier' && el.object.object.name === svelteImportName && + // Check for svelte.[configs].* el.object.property.type === 'Identifier' && el.object.property.name === 'configs' ); From c047c10a5b690fbc6f0660c5e8bc74e5f09d6431 Mon Sep 17 00:00:00 2001 From: Scott Wu Date: Sat, 28 Mar 2026 22:30:03 +0800 Subject: [PATCH 19/19] refactor --- packages/sv/src/addons/common.ts | 34 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/sv/src/addons/common.ts b/packages/sv/src/addons/common.ts index f4921c82c..beba5ae6d 100644 --- a/packages/sv/src/addons/common.ts +++ b/packages/sv/src/addons/common.ts @@ -28,39 +28,39 @@ export function addEslintConfigPrettier(content: string): string { const defaultExport = js.exports.createDefault(ast, { fallback: fallbackConfig }); const eslintConfig = defaultExport.value; - const isDefineConfig = eslintConfig.type === 'CallExpression'; // export default defineConfig() - const isArray = eslintConfig.type === 'ArrayExpression'; // export default [] - - if (!isArray && !isDefineConfig) return content; - type Elements = | Extract['arguments'] | Extract['elements']; - const prettier = js.common.parseExpression('prettier'); - const sveltePrettierConfig = js.common.parseExpression(`${svelteImportName}.configs.prettier`); - - const nodesToInsert = []; - if (!js.common.contains(eslintConfig, prettier)) nodesToInsert.push(prettier); - if (!js.common.contains(eslintConfig, sveltePrettierConfig)) - nodesToInsert.push(sveltePrettierConfig); - let elements: Elements = []; - if (isArray) elements = eslintConfig.elements; - if (isDefineConfig) { + if (eslintConfig.type === 'ArrayExpression') { + // export default [] + elements = eslintConfig.elements; + } else if (eslintConfig.type === 'CallExpression') { if ( eslintConfig.arguments.length === 1 && eslintConfig.arguments[0].type === 'ArrayExpression' ) { - // javascript - defineConfig([...]) + // export default defineConfig([...]) elements = eslintConfig.arguments[0].elements; } else { - // typescript - defineConfig(...) + // export default defineConfig({}, {}) elements = eslintConfig.arguments; } + } else { + // fallback: Not an array or a function call + return content; } + const prettier = js.common.parseExpression('prettier'); + const sveltePrettierConfig = js.common.parseExpression(`${svelteImportName}.configs.prettier`); + + const nodesToInsert = []; + if (!js.common.contains(eslintConfig, prettier)) nodesToInsert.push(prettier); + if (!js.common.contains(eslintConfig, sveltePrettierConfig)) + nodesToInsert.push(sveltePrettierConfig); + const isSvelteConfig = (maybeSpread: Elements[number]) => { const el = maybeSpread?.type === 'SpreadElement'