From 11f9f1b57e790fb7d99e9bb7d7958390257e2bd2 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Tue, 15 Sep 2026 23:59:28 +0300 Subject: [PATCH] fix(types): align Vue fallback declarations The app and SDK ambient SFC declarations disagreed on indexed props. SDK-first declaration order reproduced all twelve Storybook default-argument errors. Use the same opaque fallback and compile existing stories under both declaration orders as a regression check. --- packages/vue/src/global.d.ts | 3 +- tools/lint/tests/vue-module.test.ts | 47 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tools/lint/tests/vue-module.test.ts diff --git a/packages/vue/src/global.d.ts b/packages/vue/src/global.d.ts index 6afa97ac0..8b2ed4a27 100644 --- a/packages/vue/src/global.d.ts +++ b/packages/vue/src/global.d.ts @@ -13,6 +13,7 @@ declare module '*?raw' { declare module '*.vue' { import type { DefineComponent } from 'vue' - const component: DefineComponent, Record, unknown> + // Match the app's opaque fallback: an index signature breaks Storybook default-arg inference. + const component: DefineComponent export default component } diff --git a/tools/lint/tests/vue-module.test.ts b/tools/lint/tests/vue-module.test.ts new file mode 100644 index 000000000..cc40f9e6b --- /dev/null +++ b/tools/lint/tests/vue-module.test.ts @@ -0,0 +1,47 @@ +import { expect, test } from 'bun:test' +import { execFile } from 'node:child_process' +import { mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join, resolve } from 'node:path' +import { promisify } from 'node:util' + +const execute = promisify(execFile) +const root = resolve(import.meta.dir, '../../..') + +test.each(['app-first', 'sdk-first'])( + 'Vue module declarations preserve Storybook default args (%s)', + async (order) => { + const directory = await mkdtemp(join(tmpdir(), 'open-pencil-vue-module-')) + try { + const declarations = [join(root, 'src/env.d.ts'), join(root, 'packages/vue/src/global.d.ts')] + if (order === 'sdk-first') declarations.reverse() + const project = join(directory, 'tsconfig.json') + await writeFile( + project, + JSON.stringify({ + extends: join(root, 'tsconfig.json'), + include: [], + files: [ + ...declarations, + join(root, 'src/components/ui/paint/FillSwatchTrigger.stories.ts') + ] + }) + ) + const result = await execute( + process.execPath, + [ + join(root, 'node_modules/@typescript/native-preview/bin/tsgo'), + '--noEmit', + '--project', + project + ], + { cwd: root, timeout: 20_000, maxBuffer: 2 * 1024 * 1024 } + ) + expect(result.stdout).toBe('') + expect(result.stderr).toBe('') + } finally { + await rm(directory, { recursive: true, force: true }) + } + }, + 30_000 +)