Skip to content

Commit f946d30

Browse files
authored
feat: warn when using the separate declaration option with a script output (#513)
1 parent edbcc92 commit f946d30

2 files changed

Lines changed: 105 additions & 1 deletion

File tree

mod.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export interface BuildOptions {
8888
* the esm and script folders. This is the recommended option when publishing
8989
* a dual ESM and script package to npm.
9090
* * `"separate"` - Emits declaration files to the `types` folder where both
91-
* the ESM and script code share the same type declarations.
91+
* the ESM and script code share the same type declarations. Deprecated,
92+
* because the shared declarations describe the ESM output, so they're not
93+
* correct for a CommonJS consumer. Use `"inline"` instead.
9294
* * `false` - Do not emit declaration files.
9395
* @default "inline"
9496
*/
@@ -332,6 +334,17 @@ export async function build(options: BuildOptions): Promise<void> {
332334
? "inline"
333335
: options.declaration ?? "inline",
334336
};
337+
if (
338+
options.declaration === "separate" && options.scriptModule !== false &&
339+
options.esModule !== false
340+
) {
341+
warn(
342+
`The 'separate' declaration build option outputs the same type ` +
343+
`declarations for the ESM and CommonJS/UMD output, but they describe ` +
344+
`the ESM output. Use the default 'inline' option instead, which ` +
345+
`outputs the declarations beside the code they describe.`,
346+
);
347+
}
335348
const cwd = Deno.cwd();
336349
// the declaration maps point at the `src` directory, so they're only useful
337350
// when it's written out and published alongside them

tests/integration.test.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,83 @@ pnpm-lock.yaml
239239
});
240240
});
241241

242+
Deno.test("should warn when using separate declarations with a script output", async () => {
243+
const warnings = await captureWarnings(() =>
244+
runTest("test_project", {
245+
entryPoints: ["mod.ts"],
246+
outDir: "./npm",
247+
declaration: "separate",
248+
shims: {
249+
deno: "dev",
250+
},
251+
test: false,
252+
typeCheck: false,
253+
skipNpmInstall: true,
254+
package: {
255+
name: "add",
256+
version: "1.0.0",
257+
},
258+
})
259+
);
260+
261+
assertStringIncludes(
262+
warnings.join("\n"),
263+
"The 'separate' declaration build option",
264+
);
265+
});
266+
267+
Deno.test("should not warn about separate declarations with a single output", async () => {
268+
const warnings = await captureWarnings(() =>
269+
runTest("test_project", {
270+
entryPoints: ["mod.ts"],
271+
outDir: "./npm",
272+
declaration: "separate",
273+
scriptModule: false,
274+
shims: {
275+
deno: "dev",
276+
},
277+
test: false,
278+
typeCheck: false,
279+
skipNpmInstall: true,
280+
package: {
281+
name: "add",
282+
version: "1.0.0",
283+
},
284+
})
285+
);
286+
287+
assertEquals(
288+
warnings.some((w) => w.includes("The 'separate' declaration build option")),
289+
false,
290+
);
291+
});
292+
293+
Deno.test("should not warn about separate declarations without an esm output", async () => {
294+
const warnings = await captureWarnings(() =>
295+
runTest("test_project", {
296+
entryPoints: ["mod.ts"],
297+
outDir: "./npm",
298+
declaration: "separate",
299+
esModule: false,
300+
shims: {
301+
deno: "dev",
302+
},
303+
test: false,
304+
typeCheck: false,
305+
skipNpmInstall: true,
306+
package: {
307+
name: "add",
308+
version: "1.0.0",
309+
},
310+
})
311+
);
312+
313+
assertEquals(
314+
warnings.some((w) => w.includes("The 'separate' declaration build option")),
315+
false,
316+
);
317+
});
318+
242319
Deno.test("should build umd module", async () => {
243320
await runTest("test_project", {
244321
entryPoints: ["mod.ts"],
@@ -1857,6 +1934,20 @@ function assertPreloadModuleOutput(output: Output) {
18571934
assertEquals(filePaths.includes("test_preload"), false);
18581935
}
18591936

1937+
async function captureWarnings(action: () => Promise<void>) {
1938+
const warnings: string[] = [];
1939+
const originalWarn = console.warn;
1940+
console.warn = (...args: unknown[]) => {
1941+
warnings.push(args.join(" "));
1942+
};
1943+
try {
1944+
await action();
1945+
} finally {
1946+
console.warn = originalWarn;
1947+
}
1948+
return warnings;
1949+
}
1950+
18601951
async function captureLogs(action: () => Promise<void>) {
18611952
const logs: string[] = [];
18621953
const originalLog = console.log;

0 commit comments

Comments
 (0)