Skip to content

Commit dd3afe3

Browse files
committed
feat: warn when using the separate declaration option with a script output
The declarations describe the ESM output, so sharing them with the CommonJS/UMD output isn't correct for a CommonJS consumer. Closes #327
1 parent eaa5668 commit dd3afe3

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

mod.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ export interface BuildOptions {
8989
* a dual ESM and script package to npm.
9090
* * `"separate"` - Emits declaration files to the `types` folder where both
9191
* the ESM and script code share the same type declarations.
92+
*
93+
* @deprecated The shared declarations describe the ESM output, so they're
94+
* not correct for a CommonJS consumer. Use `"inline"` instead.
9295
* * `false` - Do not emit declaration files.
9396
* @default "inline"
9497
*/
@@ -321,6 +324,14 @@ export async function build(options: BuildOptions): Promise<void> {
321324
? "inline"
322325
: options.declaration ?? "inline",
323326
};
327+
if (options.declaration === "separate" && options.scriptModule !== false) {
328+
warn(
329+
`The 'separate' declaration build option outputs the same type ` +
330+
`declarations for the ESM and CommonJS/UMD output, but they describe ` +
331+
`the ESM output. Use the default 'inline' option instead, which ` +
332+
`outputs the declarations beside the code they describe.`,
333+
);
334+
}
324335
const cwd = Deno.cwd();
325336
// the declaration maps point at the `src` directory, so they're only useful
326337
// when it's written out and published alongside them

tests/integration.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,57 @@ 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 without a script 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("declaration build option")),
289+
false,
290+
);
291+
});
292+
242293
Deno.test("should build umd module", async () => {
243294
await runTest("test_project", {
244295
entryPoints: ["mod.ts"],
@@ -1840,6 +1891,20 @@ function assertPreloadModuleOutput(output: Output) {
18401891
assertEquals(filePaths.includes("test_preload"), false);
18411892
}
18421893

1894+
async function captureWarnings(action: () => Promise<void>) {
1895+
const warnings: string[] = [];
1896+
const originalWarn = console.warn;
1897+
console.warn = (...args: unknown[]) => {
1898+
warnings.push(args.join(" "));
1899+
};
1900+
try {
1901+
await action();
1902+
} finally {
1903+
console.warn = originalWarn;
1904+
}
1905+
return warnings;
1906+
}
1907+
18431908
async function captureLogs(action: () => Promise<void>) {
18441909
const logs: string[] = [];
18451910
const originalLog = console.log;

0 commit comments

Comments
 (0)