11import { execFileSync } from "node:child_process" ;
2- import { mkdtempSync , readFileSync , rmSync } from "node:fs" ;
2+ import {
3+ existsSync ,
4+ mkdirSync ,
5+ mkdtempSync ,
6+ readFileSync ,
7+ rmSync ,
8+ symlinkSync ,
9+ writeFileSync ,
10+ } from "node:fs" ;
311import { tmpdir } from "node:os" ;
412import { dirname , join } from "node:path" ;
513import { fileURLToPath } from "node:url" ;
614import { describe , expect , it } from "vitest" ;
715
816const root = join ( dirname ( fileURLToPath ( import . meta. url ) ) , ".." ) ;
917const fixtureDir = join ( root , "test/declaration-emit" ) ;
18+ const consumerFixtureDir = join ( root , "test/declaration-emit-consumer" ) ;
19+ const tsc = join ( root , "../../node_modules/typescript/bin/tsc" ) ;
1020
1121/** Soft ceiling well under TS7056 (~1e6 chars). Pre-fix auth emits were
1222 * ~750KB for two fns because ScopeOf/ResolvedVars inlined the module graph. */
@@ -18,13 +28,7 @@ describe("declaration emit (TS7056)", () => {
1828 try {
1929 execFileSync (
2030 process . execPath ,
21- [
22- join ( root , "../../node_modules/typescript/bin/tsc" ) ,
23- "-p" ,
24- join ( fixtureDir , "tsconfig.json" ) ,
25- "--outDir" ,
26- outDir ,
27- ] ,
31+ [ tsc , "-p" , join ( fixtureDir , "tsconfig.json" ) , "--outDir" , outDir ] ,
2832 { cwd : root , stdio : "pipe" } ,
2933 ) ;
3034
@@ -45,3 +49,64 @@ describe("declaration emit (TS7056)", () => {
4549 }
4650 } ) ;
4751} ) ;
52+
53+ describe ( "declaration emit (TS2883 / package entry)" , ( ) => {
54+ it ( "exports e.fn with errors through better-call package entry under node16" , ( ) => {
55+ expect (
56+ existsSync ( join ( root , "dist/index.d.mts" ) ) ,
57+ "dist/index.d.mts missing - run pnpm build in packages/experimental" ,
58+ ) . toBe ( true ) ;
59+
60+ const consumerDir = mkdtempSync ( join ( tmpdir ( ) , "bc-decl-consumer-" ) ) ;
61+ try {
62+ mkdirSync ( join ( consumerDir , "node_modules" ) ) ;
63+ symlinkSync ( root , join ( consumerDir , "node_modules/better-call" ) ) ;
64+ symlinkSync (
65+ join ( consumerFixtureDir , "index.ts" ) ,
66+ join ( consumerDir , "index.ts" ) ,
67+ ) ;
68+ symlinkSync (
69+ join ( consumerFixtureDir , "tsconfig.json" ) ,
70+ join ( consumerDir , "tsconfig.json" ) ,
71+ ) ;
72+ // Written here (not checked in) so this fixture is not a pnpm
73+ // workspace package that knip would police for unlisted deps.
74+ writeFileSync (
75+ join ( consumerDir , "package.json" ) ,
76+ JSON . stringify ( {
77+ name : "better-call-declaration-emit-consumer" ,
78+ private : true ,
79+ type : "module" ,
80+ } ) ,
81+ ) ;
82+
83+ try {
84+ execFileSync ( process . execPath , [ tsc , "-p" , "tsconfig.json" ] , {
85+ cwd : consumerDir ,
86+ stdio : "pipe" ,
87+ } ) ;
88+ } catch ( err ) {
89+ const e = err as { stderr ?: Buffer ; stdout ?: Buffer } ;
90+ throw new Error (
91+ [
92+ "consumer declaration emit failed:" ,
93+ e . stderr ?. toString ( "utf8" ) ,
94+ e . stdout ?. toString ( "utf8" ) ,
95+ ]
96+ . filter ( Boolean )
97+ . join ( "\n" ) ,
98+ ) ;
99+ }
100+
101+ const dts = readFileSync ( join ( consumerDir , "out/index.d.ts" ) , "utf8" ) ;
102+ expect ( dts ) . toMatch ( / e x p o r t d e c l a r e c o n s t s i g n I n E m a i l : / ) ;
103+ expect ( dts ) . toMatch ( / e x p o r t d e c l a r e c o n s t b o u n d : / ) ;
104+ // Portable via package entry - not better-call/dist/fn.mjs (TS2883).
105+ expect ( dts ) . toMatch ( / i m p o r t \( " b e t t e r - c a l l " \) \. F n E r r o r s O f / ) ;
106+ expect ( dts ) . toMatch ( / i m p o r t \( " b e t t e r - c a l l " \) \. B o u n d C a l l / ) ;
107+ expect ( dts ) . not . toMatch ( / d i s t \/ f n \. m j s / ) ;
108+ } finally {
109+ rmSync ( consumerDir , { recursive : true , force : true } ) ;
110+ }
111+ } ) ;
112+ } ) ;
0 commit comments