diff --git a/.changeset/humble-paths-fly.md b/.changeset/humble-paths-fly.md new file mode 100644 index 0000000000..a33d0ea32b --- /dev/null +++ b/.changeset/humble-paths-fly.md @@ -0,0 +1,5 @@ +--- +'@fuzdev/gro': minor +--- + +feat: rewrite `.ts` to `.js` in dist files diff --git a/CLAUDE.md b/CLAUDE.md index 85ed11ac60..605ee2b05d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -275,7 +275,8 @@ Builtin plugins: - `gro_plugin_sveltekit_app` - runs `vite dev` or `vite build` for SvelteKit frontends ([docs](src/docs/gro_plugin_sveltekit_app.md)) - `gro_plugin_sveltekit_library` - runs `svelte-package` to publish from - `src/lib/` ([docs](src/docs/gro_plugin_sveltekit_library.md)) + `src/lib/`, then rewrites relative `.ts`→`.js` import specifiers in the + emitted `.d.ts`/`.svelte` ([docs](src/docs/gro_plugin_sveltekit_library.md)) - `gro_plugin_server` - runs Node servers with auto-restart on changes ### Configuration diff --git a/src/docs/gro_plugin_sveltekit_library.md b/src/docs/gro_plugin_sveltekit_library.md index dd0e98e745..d6a461c15e 100644 --- a/src/docs/gro_plugin_sveltekit_library.md +++ b/src/docs/gro_plugin_sveltekit_library.md @@ -22,7 +22,14 @@ npm i -D @sveltejs/package ## behavior In production (`gro build`), runs `svelte-package` during `setup` -to compile `src/lib/` into `dist/`. +to compile `src/lib/` into `dist/`, then rewrites relative `.ts` import +specifiers to `.js` (and `.svelte.ts` to `.svelte.js`) in the emitted `.d.ts` +declarations and `.svelte` ` + +{icon_link} +`; + const expected = ` + +{icon_link} +`; + assert.equal(rewrite_svelte_ts_imports(input), expected); + }); + + test('rewrites both module and instance ` + +`; + const expected = ` + +`; + assert.equal(rewrite_svelte_ts_imports(input), expected); + }); + + test('preserves `$`-sequences ($$props, $:) while rewriting specifiers', () => { + const input = ` +`; + const expected = ` +`; + assert.equal(rewrite_svelte_ts_imports(input), expected); + }); + + test('leaves a `.svelte` with no rewritable specifiers untouched', () => { + const input = ` +
hi
+`; + assert.equal(rewrite_svelte_ts_imports(input), input); + }); +}); + +describe('rewrite_dist_imports', () => { + let dir: string; + + beforeEach(async () => { + dir = await mkdtemp(join(tmpdir(), 'gro-dist-rewrite-')); + }); + + afterEach(async () => { + await rm(dir, {recursive: true, force: true}); + }); + + test('rewrites `.d.ts`, `.svelte.d.ts`, and `.svelte`, leaving `.js` and maps alone', async () => { + await mkdir(join(dir, 'nested'), {recursive: true}); + await writeFile(join(dir, 'a.d.ts'), `import type {B} from './b.ts';\n`); + await writeFile(join(dir, 'Comp.svelte.d.ts'), `import {type P} from './helpers.ts';\n`); + await writeFile( + join(dir, 'Comp.svelte'), + `\n`, + ); + // already emitted by tsc — must stay untouched + await writeFile(join(dir, 'a.js'), `import {b} from './b.js';\n`); + await writeFile(join(dir, 'a.d.ts.map'), `{"sources":["../src/lib/a.ts"]}\n`); + await writeFile(join(dir, 'nested', 'c.d.ts'), `export * from '../a.ts';\n`); + + const result = await rewrite_dist_imports(dir); + + assert.equal(await readFile(join(dir, 'a.d.ts'), 'utf8'), `import type {B} from './b.js';\n`); + assert.equal( + await readFile(join(dir, 'Comp.svelte.d.ts'), 'utf8'), + `import {type P} from './helpers.js';\n`, + ); + assert.equal( + await readFile(join(dir, 'Comp.svelte'), 'utf8'), + `\n`, + ); + assert.equal(await readFile(join(dir, 'a.js'), 'utf8'), `import {b} from './b.js';\n`); + assert.equal( + await readFile(join(dir, 'a.d.ts.map'), 'utf8'), + `{"sources":["../src/lib/a.ts"]}\n`, + ); + assert.equal( + await readFile(join(dir, 'nested', 'c.d.ts'), 'utf8'), + `export * from '../a.js';\n`, + ); + + // 4 files scanned (a.d.ts, Comp.svelte.d.ts, Comp.svelte, nested/c.d.ts); all 4 rewritten + assert.equal(result.scanned, 4); + assert.equal(result.rewritten, 4); + }); + + test('returns zero rewrites for a missing directory', async () => { + const result = await rewrite_dist_imports(join(dir, 'does-not-exist')); + assert.equal(result.scanned, 0); + assert.equal(result.rewritten, 0); + }); +});