// Nuxt auto-imports every export of app/utils and app/composables. A name // exported from two of those files is a "Duplicated imports" warning on // every build of an app with the layer (an interface re-exported next to // its declaration counts), so each name has one home. import { test } from 'node:test' import assert from 'node:assert/strict' import { readdirSync, readFileSync } from 'node:fs' import { join } from 'node:path' const root = new URL('..', import.meta.url).pathname /** The names a module exports: declarations and export lists. */ function exportedNames(source: string): string[] { const names: string[] = [] const decl = /^export\s+(?:declare\s+)?(?:async\s+)?(?:interface|type|function\*?|const|let|var|class|enum)\s+([A-Za-z_$][\w$]*)/gm for (const m of source.matchAll(decl)) names.push(m[1]!) const list = /^export\s+(?:type\s+)?\{([^}]*)\}/gm for (const m of source.matchAll(list)) { for (const part of m[1]!.split(',')) { const name = part.trim().split(/\s+as\s+/).pop()?.replace(/^type\s+/, '').trim() if (name) names.push(name) } } return names } function autoImportedFiles(): string[] { const out: string[] = [] for (const dir of ['app/utils', 'app/composables']) { for (const f of readdirSync(join(root, dir))) { if (/\.(ts|mts|js|mjs)$/.test(f) && !f.endsWith('.d.ts')) out.push(join(dir, f)) } } return out } test('exportedNames reads declarations and export lists', () => { assert.deepEqual( exportedNames("export interface A {}\nexport type B = 1\nexport function c() {}\nexport const d = 1\nexport type { E }\nexport { f as g, type H }\n"), ['A', 'B', 'c', 'd', 'E', 'g', 'H'], ) }) test('a name re-exported next to its declaration is a duplicate', () => { const files = { 'app/utils/srcset.ts': 'export interface JournalImageVariant { width: number }', 'app/utils/types.ts': "import type { JournalImageVariant } from './srcset.ts'\nexport type { JournalImageVariant }", } const seen = new Map() for (const [file, src] of Object.entries(files)) { for (const name of exportedNames(src)) seen.set(name, [...(seen.get(name) ?? []), file]) } assert.deepEqual(seen.get('JournalImageVariant'), ['app/utils/srcset.ts', 'app/utils/types.ts']) }) test('every auto-imported name is exported from one file only', () => { const homes = new Map() for (const file of autoImportedFiles()) { for (const name of exportedNames(readFileSync(join(root, file), 'utf8'))) { homes.set(name, [...(homes.get(name) ?? []), file]) } } const duplicates = [...homes].filter(([, files]) => files.length > 1).map(([name, files]) => `${name}: ${files.join(', ')}`) assert.deepEqual(duplicates, []) assert.ok(homes.has('JournalImageVariant'), 'JournalImageVariant is still auto-imported') })