From ff4a7f1df37fa77ef3ea6184186d698cd49ccc72 Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 23 Feb 2026 22:35:43 +0100 Subject: [PATCH 01/10] add tests --- packages/sv/src/cli/tests/cli.ts | 38 +++++++++++++++----------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/packages/sv/src/cli/tests/cli.ts b/packages/sv/src/cli/tests/cli.ts index 4b8564853..95cef13d7 100644 --- a/packages/sv/src/cli/tests/cli.ts +++ b/packages/sv/src/cli/tests/cli.ts @@ -16,7 +16,7 @@ beforeAll(() => { describe('cli', () => { const testCases = [ - { projectName: 'create-only', args: ['--no-add-ons'] }, + { projectName: 'create-only', args: ['--no-add-ons'], cmds: [] }, { projectName: 'create-with-all-addons', args: [ @@ -34,20 +34,26 @@ describe('cli', () => { 'paraglide=languageTags:en,es+demo:yes', 'mcp=ide:claude-code,cursor,gemini,opencode,vscode,other+setup:local' // 'storybook' // No storybook addon during tests! + ], + cmds: [ + ['i'], + ['run', 'auth:schema'], //['run', 'build'], + ['exec', 'eslint', '--', '.'] ] }, { projectName: '@my-org/sv', template: 'addon', - args: [] + args: [], + cmds: [['i'], ['run', 'demo-create'], ['run', 'demo-add:ci'], ['run', 'test']] } ]; it.for(testCases)( 'should create a new project with name $projectName', - { timeout: 51_000 }, + { timeout: 101_000 }, async (testCase) => { - const { projectName, args, template = 'minimal' } = testCase; + const { projectName, args, template = 'minimal', cmds } = testCase; const testOutputPath = path.relative( monoRepoPath, @@ -124,23 +130,15 @@ describe('cli', () => { packageJsonPath, JSON.stringify(packageJson, null, 3).replaceAll(' ', '\t') ); + } - const cmds = [ - // list of cmds to test - ['i'], - ['run', 'demo-create'], - ['run', 'demo-add:ci'], - ['run', 'test'] - ]; - for (const cmd of cmds) { - const res = await exec('npm', cmd, { - nodeOptions: { stdio: 'pipe', cwd: testOutputPath } - }); - expect( - res.exitCode, - `Error addon test: '${cmd}' -> ${JSON.stringify(res, null, 2)}` - ).toBe(0); - } + for (const cmd of cmds) { + const res = await exec('npm', cmd, { + nodeOptions: { stdio: 'pipe', cwd: testOutputPath } + }); + expect(res.exitCode, `Error addon test: '${cmd}' -> ${JSON.stringify(res, null, 2)}`).toBe( + 0 + ); } } ); From 7d47ca970cf093fccc188d40b320dbc3b8458ada Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 23 Feb 2026 22:35:47 +0100 Subject: [PATCH 02/10] update conf --- packages/sv/src/addons/eslint.ts | 3 ++- .../snapshots/create-with-all-addons/eslint.config.js | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/sv/src/addons/eslint.ts b/packages/sv/src/addons/eslint.ts index b5fd010c5..93b80ca4a 100644 --- a/packages/sv/src/addons/eslint.ts +++ b/packages/sv/src/addons/eslint.ts @@ -48,7 +48,7 @@ export default defineAddon({ eslintConfigs.push(jsConfig); if (typescript) { - const tsConfig = js.common.parseExpression('ts.configs.recommended'); + const tsConfig = js.common.parseExpression('ts.configs.recommendedTypeChecked'); eslintConfigs.push(js.common.createSpread(tsConfig)); } @@ -77,6 +77,7 @@ export default defineAddon({ const globalsConfig = js.object.create({ languageOptions: { + parserOptions: typescript ? { projectService: true } : undefined, globals: globalsObjLiteral }, rules: typescript ? rules : undefined 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 ef3e6616b..4c63b101a 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 @@ -13,12 +13,15 @@ const gitignorePath = path.resolve(import.meta.dirname, '.gitignore'); export default defineConfig( includeIgnoreFile(gitignorePath), js.configs.recommended, - ...ts.configs.recommended, + ...ts.configs.recommendedTypeChecked, ...svelte.configs.recommended, prettier, ...svelte.configs.prettier, { - languageOptions: { globals: { ...globals.browser, ...globals.node } }, + languageOptions: { + parserOptions: { projectService: true }, + globals: { ...globals.browser, ...globals.node } + }, rules: { // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors From 26817aefa79a0d4778e53c33e94240563f3ea8f5 Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 23 Feb 2026 23:09:41 +0100 Subject: [PATCH 03/10] update tests --- packages/sv/src/cli/tests/cli.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/sv/src/cli/tests/cli.ts b/packages/sv/src/cli/tests/cli.ts index 95cef13d7..5a3927a89 100644 --- a/packages/sv/src/cli/tests/cli.ts +++ b/packages/sv/src/cli/tests/cli.ts @@ -37,7 +37,8 @@ describe('cli', () => { ], cmds: [ ['i'], - ['run', 'auth:schema'], //['run', 'build'], + ['run', 'auth:schema'], + ['run', 'build'], ['exec', 'eslint', '--', '.'] ] }, From 49796ebb2a9a7a6b969524973b60526111e9b71c Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 23 Feb 2026 23:09:47 +0100 Subject: [PATCH 04/10] add changelog --- .changeset/plenty-deserts-tan.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/plenty-deserts-tan.md diff --git a/.changeset/plenty-deserts-tan.md b/.changeset/plenty-deserts-tan.md new file mode 100644 index 000000000..9a81c6cb6 --- /dev/null +++ b/.changeset/plenty-deserts-tan.md @@ -0,0 +1,5 @@ +--- +'sv': patch +--- + +feat(eslint): add `recommendedTypeChecked` config From a8ebe101e0925f29467fc1e09d8ef1d96a4adf4a Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 23 Feb 2026 23:12:16 +0100 Subject: [PATCH 05/10] first pass --- packages/sv/src/addons/better-auth.ts | 19 ++++++++++--------- packages/sv/src/addons/drizzle.ts | 10 ++++++++++ packages/sv/src/addons/eslint.ts | 11 +++++++++++ packages/sv/src/addons/paraglide.ts | 7 +++++-- packages/sv/src/addons/playwright.ts | 11 +++++++++++ .../create-only/src/routes/+layout.svelte | 3 ++- .../create-with-all-addons/src/hooks.ts | 2 +- .../src/routes/+layout.svelte | 6 ++++-- .../routes/demo/better-auth/+page.server.ts | 2 +- .../src/routes/demo/better-auth/+page.svelte | 1 + .../demo/better-auth/login/+page.server.ts | 16 ++++++++-------- .../create-with-all-addons/tsconfig.json | 14 ++++++++------ .../minimal/src/routes/+layout.svelte | 3 ++- 13 files changed, 74 insertions(+), 31 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index cd55b0277..895c1d3ff 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -240,8 +240,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({ @@ -262,9 +262,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({ @@ -290,8 +290,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: { @@ -316,7 +316,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'); } @@ -405,7 +405,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'); } @@ -443,6 +443,7 @@ export default defineAddon({ ${s5(`let { data }${ts(': { data: PageServerData }')} = $props();`, `export let data${ts(': PageServerData')};`)} +

Hi, {data.user.name}!

Your user ID is {data.user.id}.

diff --git a/packages/sv/src/addons/drizzle.ts b/packages/sv/src/addons/drizzle.ts index 94a61e00d..094c3ab0b 100644 --- a/packages/sv/src/addons/drizzle.ts +++ b/packages/sv/src/addons/drizzle.ts @@ -410,6 +410,16 @@ export default defineAddon({ return generateCode(); }); + + if (typescript) { + sv.file('tsconfig.json', (content) => { + const { data, generateCode } = parse.json(content); + const file = `drizzle.config.${language}`; + if (!data.files) data.files = []; + if (!data.files.includes(file)) data.files.push(file); + return generateCode(); + }); + } }, nextSteps: ({ options, packageManager }) => { const steps: string[] = []; diff --git a/packages/sv/src/addons/eslint.ts b/packages/sv/src/addons/eslint.ts index 93b80ca4a..6c23f6fe9 100644 --- a/packages/sv/src/addons/eslint.ts +++ b/packages/sv/src/addons/eslint.ts @@ -153,5 +153,16 @@ export default defineAddon({ if (prettierInstalled) { sv.file(files.eslintConfig, addEslintConfigPrettier); } + + if (typescript) { + sv.file('tsconfig.json', (content) => { + const { data, generateCode } = parse.json(content); + if (!data.files) data.files = []; + for (const file of ['svelte.config.js', files.eslintConfig]) { + if (!data.files.includes(file)) data.files.push(file); + } + return generateCode(); + }); + } } }); diff --git a/packages/sv/src/addons/paraglide.ts b/packages/sv/src/addons/paraglide.ts index 53ac29d76..4dbc46e64 100644 --- a/packages/sv/src/addons/paraglide.ts +++ b/packages/sv/src/addons/paraglide.ts @@ -85,7 +85,9 @@ export default defineAddon({ }); const expression = js.common.parseExpression( - '(request) => deLocalizeUrl(request.url).pathname' + language === 'ts' + ? '(request: { url: URL }) => deLocalizeUrl(request.url).pathname' + : '(request) => deLocalizeUrl(request.url).pathname' ); const rerouteIdentifier = js.variables.declaration(ast, { kind: 'const', @@ -184,7 +186,8 @@ export default defineAddon({ svelte.addFragment( ast, `
- {#each locales as locale} + {#each locales as locale (locale)} + {locale} {/each}
` diff --git a/packages/sv/src/addons/playwright.ts b/packages/sv/src/addons/playwright.ts index d886ec498..2382d0c92 100644 --- a/packages/sv/src/addons/playwright.ts +++ b/packages/sv/src/addons/playwright.ts @@ -37,6 +37,17 @@ export default defineAddon({ `; }); + if (language === 'ts') { + sv.file('tsconfig.json', (content) => { + const { data, generateCode } = parse.json(content); + if (!data.files) data.files = []; + for (const file of [`playwright.config.ts`, `e2e/demo.test.ts`]) { + if (!data.files.includes(file)) data.files.push(file); + } + return generateCode(); + }); + } + sv.file(`playwright.config.${language}`, (content) => { const { ast, generateCode } = parse.script(content); const defineConfig = js.common.parseExpression('defineConfig({})'); diff --git a/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte index 9cebde545..671636796 100644 --- a/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte @@ -1,7 +1,8 @@ diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.ts index e75600b3e..0988131ea 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.ts @@ -1,3 +1,3 @@ import { deLocalizeUrl } from '$lib/paraglide/runtime'; -export const reroute = (request) => deLocalizeUrl(request.url).pathname; +export const reroute = (request: { url: URL }) => deLocalizeUrl(request.url).pathname; diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte index b22ec360f..f17ab4b7d 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte @@ -2,16 +2,18 @@ import { page } from '$app/state'; import { locales, localizeHref } from '$lib/paraglide/runtime'; import './layout.css'; + import type { Snippet } from 'svelte'; import favicon from '$lib/assets/favicon.svg'; - let { children } = $props(); + let { children }: { children: Snippet } = $props(); {@render children()}
- {#each locales as locale} + {#each locales as locale (locale)} + {locale} {/each}
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/+page.svelte b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte index 87a24ab7c..900ba24e6 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte @@ -5,6 +5,7 @@ let { data }: { data: PageServerData } = $props(); +

Hi, {data.user.name}!

Your user ID is {data.user.id}.

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: { diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/tsconfig.json b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/tsconfig.json index 2c2ed3c4d..d61687cf7 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/tsconfig.json +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/tsconfig.json @@ -11,10 +11,12 @@ "sourceMap": true, "strict": true, "moduleResolution": "bundler" - } - // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias - // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files - // - // To make changes to top-level options such as include and exclude, we recommend extending - // the generated config; see https://svelte.dev/docs/kit/configuration#typescript + }, + "files": [ + "svelte.config.js", + "eslint.config.js", + "playwright.config.ts", + "e2e/demo.test.ts", + "drizzle.config.ts" + ] } diff --git a/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte b/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte index 9cebde545..671636796 100644 --- a/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte +++ b/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte @@ -1,7 +1,8 @@ From 65c4fed2bac3836fc4fbe9def06fb00810d01a52 Mon Sep 17 00:00:00 2001 From: jycouet Date: Fri, 27 Feb 2026 23:31:44 +0100 Subject: [PATCH 06/10] adding some fixes --- packages/sv/src/addons/better-auth.ts | 1 - packages/sv/src/addons/paraglide.ts | 4 ++-- packages/sv/src/cli/tests/cli.ts | 7 +------ .../tests/snapshots/create-only/src/routes/+layout.svelte | 3 +-- .../create-with-all-addons/src/routes/+layout.svelte | 7 +++---- .../src/routes/demo/better-auth/+page.svelte | 1 - .../src/create/templates/minimal/src/routes/+layout.svelte | 3 +-- 7 files changed, 8 insertions(+), 18 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index 895c1d3ff..02386310b 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -443,7 +443,6 @@ export default defineAddon({ ${s5(`let { data }${ts(': { data: PageServerData }')} = $props();`, `export let data${ts(': PageServerData')};`)} -

Hi, {data.user.name}!

Your user ID is {data.user.id}.

diff --git a/packages/sv/src/addons/paraglide.ts b/packages/sv/src/addons/paraglide.ts index 4dbc46e64..f69cc3f70 100644 --- a/packages/sv/src/addons/paraglide.ts +++ b/packages/sv/src/addons/paraglide.ts @@ -183,12 +183,12 @@ export default defineAddon({ from: '$lib/paraglide/runtime' }); js.imports.addNamed(ast.instance.content, { imports: ['page'], from: '$app/state' }); + js.imports.addNamed(ast.instance.content, { imports: ['resolve'], from: '$app/paths' }); svelte.addFragment( ast, `
{#each locales as locale (locale)} - - {locale} + {locale} {/each}
` ); diff --git a/packages/sv/src/cli/tests/cli.ts b/packages/sv/src/cli/tests/cli.ts index 5a3927a89..526ef4a4b 100644 --- a/packages/sv/src/cli/tests/cli.ts +++ b/packages/sv/src/cli/tests/cli.ts @@ -35,12 +35,7 @@ describe('cli', () => { 'mcp=ide:claude-code,cursor,gemini,opencode,vscode,other+setup:local' // 'storybook' // No storybook addon during tests! ], - cmds: [ - ['i'], - ['run', 'auth:schema'], - ['run', 'build'], - ['exec', 'eslint', '--', '.'] - ] + cmds: [['i'], ['run', 'auth:schema'], ['run', 'build'], ['exec', 'eslint', '--', '.']] }, { projectName: '@my-org/sv', diff --git a/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte index 671636796..9cebde545 100644 --- a/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte @@ -1,8 +1,7 @@ diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte index f17ab4b7d..ff836b4be 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte @@ -1,11 +1,11 @@ @@ -13,7 +13,6 @@
{#each locales as locale (locale)} - - {locale} + {locale} {/each}
diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte index 900ba24e6..87a24ab7c 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/demo/better-auth/+page.svelte @@ -5,7 +5,6 @@ let { data }: { data: PageServerData } = $props(); -

Hi, {data.user.name}!

Your user ID is {data.user.id}.

diff --git a/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte b/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte index 671636796..9cebde545 100644 --- a/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte +++ b/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte @@ -1,8 +1,7 @@ From ee6fda0bf86eb4f36636431a56e3bacac1bec37f Mon Sep 17 00:00:00 2001 From: jycouet Date: Sun, 1 Mar 2026 17:07:05 +0100 Subject: [PATCH 07/10] snap --- .../create-with-all-addons/src/routes/+layout.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte index ff836b4be..0a86b1b0b 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte @@ -13,6 +13,8 @@
{#each locales as locale (locale)} - {locale} + {locale} {/each}
From 81c7dc54fd8fb096ed69dd688e282db5e2f5856b Mon Sep 17 00:00:00 2001 From: jycouet Date: Sun, 1 Mar 2026 18:10:12 +0100 Subject: [PATCH 08/10] 1.4 --- packages/sv/src/addons/better-auth.ts | 4 ++-- .../cli/tests/snapshots/create-with-all-addons/package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index 357806ecf..9ec3ce601 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -50,8 +50,8 @@ export default defineAddon({ let drizzleDialect: Dialect; - sv.devDependency('better-auth', '^1.4.18'); - sv.devDependency('@better-auth/cli', '^1.4.18'); + sv.devDependency('better-auth', '~1.4.18'); + sv.devDependency('@better-auth/cli', '~1.4.18'); sv.file(`drizzle.config.${language}`, (content) => { const { ast, generateCode } = parse.script(content); diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json index 5cd80f37d..c8a3d3e3a 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json @@ -22,7 +22,7 @@ "auth:schema": "better-auth generate --config src/lib/server/auth.ts --output src/lib/server/db/auth.schema.ts --yes" }, "devDependencies": { - "@better-auth/cli": "^1.4.18", + "@better-auth/cli": "~1.4.18", "@eslint/compat": "^2.0.2", "@eslint/js": "^9.39.2", "@inlang/paraglide-js": "^2.10.0", @@ -35,7 +35,7 @@ "@tailwindcss/typography": "^0.5.19", "@tailwindcss/vite": "^4.1.18", "@vitest/browser-playwright": "^4.0.18", - "better-auth": "^1.4.18", + "better-auth": "~1.4.18", "drizzle-kit": "^0.31.8", "drizzle-orm": "^0.45.1", "eslint": "^9.39.2", From 231a51a78617e1156919fef0040ceb9e9c0be49e Mon Sep 17 00:00:00 2001 From: jycouet Date: Sun, 1 Mar 2026 18:30:16 +0100 Subject: [PATCH 09/10] only ONE left --- packages/sv/src/addons/better-auth.ts | 16 +++++++++++++++- packages/sv/src/cli/tests/cli.ts | 7 ++++++- .../create-with-all-addons/src/app.d.ts | 5 +++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index 9ec3ce601..e9934b6d3 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -164,6 +164,20 @@ export default defineAddon({ isType: true }); + // Add UserInfo interface that extends User with explicit properties + // so that type-checked eslint can resolve member access (due to better-auth/minimal not exporting User) + const userInfoInterface = js.common.parseStatement( + 'interface UserInfo extends User { id: string; name: string; }' + ); + const declareGlobalIndex = ast.body.findIndex( + (node: AstTypes.Node) => node.type === 'TSModuleDeclaration' + ); + if (declareGlobalIndex !== -1) { + ast.body.splice(declareGlobalIndex, 0, userInfoInterface); + } else { + ast.body.push(userInfoInterface); + } + const locals = js.kit.addGlobalAppInterface(ast, { name: 'Locals' }); if (!locals) { throw new Error('Failed detecting `locals` interface in `src/app.d.ts`'); @@ -180,7 +194,7 @@ export default defineAddon({ ); if (!user) { - locals.body.body.push(js.common.createTypeProperty('user', 'User', true)); + locals.body.body.push(js.common.createTypeProperty('user', 'UserInfo', true)); } if (!session) { locals.body.body.push(js.common.createTypeProperty('session', 'Session', true)); diff --git a/packages/sv/src/cli/tests/cli.ts b/packages/sv/src/cli/tests/cli.ts index 6b37c15db..9d98131f0 100644 --- a/packages/sv/src/cli/tests/cli.ts +++ b/packages/sv/src/cli/tests/cli.ts @@ -35,7 +35,12 @@ describe('cli', () => { 'mcp=ide:claude-code,cursor,gemini,opencode,vscode,other+setup:local' // 'storybook' // No storybook addon during tests! ], - cmds: [['i'], ['run', 'auth:schema'], ['run', 'build'], ['exec', 'eslint', '--', '.']] + cmds: [ + ['i'], + ['run', 'auth:schema'], + ['run', 'build'], // needed for paraglide addon + ['exec', 'eslint', '--', '.'] + ] }, { projectName: '@my-org/sv', diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts index 87f8dbd97..413d2f670 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts @@ -1,10 +1,11 @@ import type { User, Session } from 'better-auth/minimal'; -// See https://svelte.dev/docs/kit/types#app.d.ts +interface // See https://svelte.dev/docs/kit/types#app.d.ts UserInfo extends User { id: string; name: string } + // for information about these interfaces declare global { namespace App { - interface Locals { user?: User; session?: Session } + interface Locals { user?: UserInfo; session?: Session } // interface Error {} // interface PageData {} From 940f25ef34490fc4049ce9b14d90742bdce61997 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sun, 1 Mar 2026 18:59:23 +0100 Subject: [PATCH 10/10] better auth --- packages/sv/src/addons/better-auth.ts | 21 +++++++------------ .../create-only/src/routes/+layout.svelte | 3 ++- .../create-with-all-addons/src/app.d.ts | 5 +++-- .../src/routes/+layout.svelte | 3 ++- .../minimal/src/routes/+layout.svelte | 3 ++- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/sv/src/addons/better-auth.ts b/packages/sv/src/addons/better-auth.ts index e9934b6d3..2afbed850 100644 --- a/packages/sv/src/addons/better-auth.ts +++ b/packages/sv/src/addons/better-auth.ts @@ -164,25 +164,18 @@ export default defineAddon({ isType: true }); - // Add UserInfo interface that extends User with explicit properties - // so that type-checked eslint can resolve member access (due to better-auth/minimal not exporting User) - const userInfoInterface = js.common.parseStatement( - 'interface UserInfo extends User { id: string; name: string; }' - ); - const declareGlobalIndex = ast.body.findIndex( - (node: AstTypes.Node) => node.type === 'TSModuleDeclaration' - ); - if (declareGlobalIndex !== -1) { - ast.body.splice(declareGlobalIndex, 0, userInfoInterface); - } else { - ast.body.push(userInfoInterface); - } - const locals = js.kit.addGlobalAppInterface(ast, { name: 'Locals' }); if (!locals) { throw new Error('Failed detecting `locals` interface in `src/app.d.ts`'); } + // Add UserInfo interface with explicit properties + // as better-auth/minimal does not export User type + js.common.appendFromString(ast, { + code: 'interface UserInfo extends User { id: string; name: string; }', + comments + }); + // remove the commented out placeholder since we're adding the real one comments.remove((c) => c.type === 'Line' && c.value.trim() === 'interface Locals {}'); diff --git a/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte index 9cebde545..671636796 100644 --- a/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-only/src/routes/+layout.svelte @@ -1,7 +1,8 @@ diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts index 413d2f670..8c917b12e 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/app.d.ts @@ -1,7 +1,6 @@ import type { User, Session } from 'better-auth/minimal'; -interface // See https://svelte.dev/docs/kit/types#app.d.ts UserInfo extends User { id: string; name: string } - +// See https://svelte.dev/docs/kit/types#app.d.ts // for information about these interfaces declare global { namespace App { @@ -15,3 +14,5 @@ declare global { } export {}; + +interface UserInfo extends User { id: string; name: string } diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte index 0a86b1b0b..78dc893ec 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/routes/+layout.svelte @@ -3,9 +3,10 @@ import { page } from '$app/state'; import { locales, localizeHref } from '$lib/paraglide/runtime'; import './layout.css'; + import type { Snippet } from 'svelte'; import favicon from '$lib/assets/favicon.svg'; - let { children } = $props(); + let { children }: { children: Snippet } = $props(); diff --git a/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte b/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte index 9cebde545..671636796 100644 --- a/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte +++ b/packages/sv/src/create/templates/minimal/src/routes/+layout.svelte @@ -1,7 +1,8 @@