Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: relative declaration extension should match the extension of the code output #272

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/loaders/js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { transform } from "esbuild";
import jiti from "jiti";

import type { Loader, LoaderResult } from "../loader";
import { getOutputExtension } from "../utils";

const DECLARATION_RE = /\.d\.[cm]?ts$/;
const CM_LETTER_RE = /(?<=\.)(c|m)(?=[jt]s$)/;
Expand Down Expand Up @@ -55,10 +56,7 @@ export const jsLoader: Loader = async (input, { options }) => {
.replace("module.exports = void 0;", "");
}

let extension = isCjs ? ".js" : ".mjs"; // TODO: Default to .cjs in next major version
if (options.ext) {
extension = options.ext.startsWith(".") ? options.ext : `.${options.ext}`;
}
const extension = getOutputExtension(options);

output.push({
contents,
Expand Down
9 changes: 7 additions & 2 deletions src/utils/dts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { findStaticImports, findExports, findTypeExports } from "mlly";
import { resolve } from "pathe";
import type { TSConfig } from "pkg-types";
import type { MkdistOptions } from "../make";
import { getOutputExtension } from "./index";
import type { CompilerHost, EmitResult } from "typescript";

export async function normalizeCompilerOptions(
Expand Down Expand Up @@ -65,7 +66,10 @@ export function extractDeclarations(
const dtsFilename = filename.replace(JSX_EXT_RE, ".d.$1ts");
let contents = vfs.get(dtsFilename) || "";
if (opts?.addRelativeDeclarationExtensions) {
const ext = filename.match(JS_EXT_RE)?.[0].replace(/ts$/, "js") || ".js";
const srcExt =
filename.match(JS_EXT_RE)?.[0].replace(/ts$/, "js") || ".js";
const ext = getOutputExtension(opts);

const imports = findStaticImports(contents);
const exports = findExports(contents);
const typeExports = findTypeExports(contents);
Expand All @@ -74,7 +78,8 @@ export function extractDeclarations(
continue;
}
const srcPath = resolve(filename, "..", spec.specifier);
const srcDtsPath = srcPath + ext.replace(JS_EXT_RE, ".d.$1ts");
const srcDtsPath = srcPath + srcExt.replace(JS_EXT_RE, ".d.$1ts");

let specifier = spec.specifier;
try {
if (!vfs.get(srcDtsPath)) {
Expand Down
10 changes: 10 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { MkdistOptions } from "../make";

export function getOutputExtension(options: MkdistOptions) {
const isCjs = options.format === "cjs";
let ext = isCjs ? ".js" : ".mjs"; // TODO: Default to .cjs in next major version
if (options.ext) {
ext = options.ext.startsWith(".") ? options.ext : `.${options.ext}`;
}
return ext;
}
194 changes: 178 additions & 16 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,168 @@ describe("mkdist", () => {
"manual declaration",
);

expect(await readFile(resolve(rootDir, "dist/star/index.d.ts"), "utf8"))
.toMatchInlineSnapshot(`
"export * from "./other.mjs";
export type { Other } from "./other.mjs";
"
`);

expect(await readFile(resolve(rootDir, "dist/dir-export.d.ts"), "utf8"))
.toMatchInlineSnapshot(`
"export { default as bar } from "./bar.mjs";
export * from "./star/index.mjs";
"
`);

expect(
await readFile(resolve(rootDir, "dist/bar/esm.d.mts"), "utf8"),
).toMatch("declare");

expect(
await readFile(resolve(rootDir, "dist/components/index.d.ts"), "utf8"),
).toMatchInlineSnapshot(`
"export * as jsx from "./jsx.jsx.mjs";
export * as tsx from "./tsx.tsx.mjs";
export * as blank from "./blank.vue.mjs";
export * as scriptSetupTS from "./script-setup-ts.vue.mjs";
export * as scriptMultiBlock from "./script-multi-block.vue.mjs";
export * as ts from "./ts.vue.mjs";
"
`);

expect(
await readFile(resolve(rootDir, "dist/components/ts.vue.d.ts"), "utf8"),
).toMatchInlineSnapshot(`
"declare const _default: import("vue").DefineComponent<{}, {}, {
test: string;
str: "test";
}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
export default _default;
"
`);

expect(
await readFile(
resolve(rootDir, "dist/components/blank.vue.d.ts"),
"utf8",
),
).toMatchInlineSnapshot(`
"declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
export default _default;
"
`);

expect(
await readFile(
resolve(rootDir, "dist/components/script-multi-block.vue.d.ts"),
"utf8",
),
).toMatchInlineSnapshot(`
"interface MyComponentProps {
msg: string;
}
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MyComponentProps>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MyComponentProps>>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
export default _default;
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? {
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
} : {
type: import('vue').PropType<T[K]>;
required: true;
};
};
"
`);

expect(
await readFile(
resolve(rootDir, "dist/components/script-setup-ts.vue.d.ts"),
"utf8",
),
).toMatchInlineSnapshot(`
"import { Color } from "#prop-types";
type __VLS_Props = {
msg: string;
color: Color;
};
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_Props>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_Props>>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
export default _default;
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? {
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
} : {
type: import('vue').PropType<T[K]>;
required: true;
};
};
"
`);
}, 50_000);

it("mkdist (emit types) [js]", async () => {
const rootDir = resolve(__dirname, "fixture");
const { writtenFiles } = await mkdist({
rootDir,
declaration: true,
addRelativeDeclarationExtensions: true,
ext: "js",
});
expect(writtenFiles.sort()).toEqual(
[
"dist/README.md",
"dist/bar.d.ts",
"dist/bar.js",
"dist/demo.css",
"dist/dir-export.d.ts",
"dist/dir-export.js",
"dist/foo.js",
"dist/foo.d.ts",
"dist/index.js",
"dist/index.d.ts",
"dist/star/index.js",
"dist/star/index.d.ts",
"dist/star/other.js",
"dist/star/other.d.ts",
"dist/types.d.ts",
"dist/components/index.js",
"dist/components/index.d.ts",
"dist/components/blank.vue",
"dist/components/blank.vue.d.ts",
"dist/components/js.vue",
"dist/components/js.vue.d.ts",
"dist/components/script-multi-block.vue",
"dist/components/script-multi-block.vue.d.ts",
"dist/components/script-setup-ts.vue",
"dist/components/script-setup-ts.vue.d.ts",
"dist/components/ts.vue",
"dist/components/ts.vue.d.ts",
"dist/components/jsx.js",
"dist/components/tsx.js",
"dist/components/jsx.d.ts",
"dist/components/tsx.d.ts",
"dist/bar/index.js",
"dist/bar/index.d.ts",
"dist/bar/esm.js",
"dist/bar/esm.d.mts",
"dist/ts/test1.js",
"dist/ts/test2.js",
"dist/ts/test1.d.mts",
"dist/ts/test2.d.cts",
"dist/nested.css",
"dist/prop-types/index.js",
"dist/prop-types/index.d.ts",
]
.map((f) => resolve(rootDir, f))
.sort(),
);

expect(await readFile(resolve(rootDir, "dist/foo.d.ts"), "utf8")).toMatch(
"manual declaration",
);

expect(await readFile(resolve(rootDir, "dist/star/index.d.ts"), "utf8"))
.toMatchInlineSnapshot(`
"export * from "./other.js";
Expand Down Expand Up @@ -611,8 +773,8 @@ describe("mkdist with vue-tsc v1", () => {

expect(await readFile(resolve(rootDir, "dist/star/index.d.ts"), "utf8"))
.toMatchInlineSnapshot(`
"export * from "./other.js";
export type { Other } from "./other.js";
"export * from "./other.mjs";
export type { Other } from "./other.mjs";
"
`);
expect(
Expand All @@ -622,12 +784,12 @@ describe("mkdist with vue-tsc v1", () => {
expect(
await readFile(resolve(rootDir, "dist/components/index.d.ts"), "utf8"),
).toMatchInlineSnapshot(`
"export * as jsx from "./jsx.jsx.js";
export * as tsx from "./tsx.tsx.js";
export * as blank from "./blank.vue.js";
export * as scriptSetupTS from "./script-setup-ts.vue.js";
export * as scriptMultiBlock from "./script-multi-block.vue.js";
export * as ts from "./ts.vue.js";
"export * as jsx from "./jsx.jsx.mjs";
export * as tsx from "./tsx.tsx.mjs";
export * as blank from "./blank.vue.mjs";
export * as scriptSetupTS from "./script-setup-ts.vue.mjs";
export * as scriptMultiBlock from "./script-multi-block.vue.mjs";
export * as ts from "./ts.vue.mjs";
"
`);

Expand Down Expand Up @@ -868,8 +1030,8 @@ describe("mkdist with vue-tsc ~v2.0.21", () => {

expect(await readFile(resolve(rootDir, "dist/star/index.d.ts"), "utf8"))
.toMatchInlineSnapshot(`
"export * from "./other.js";
export type { Other } from "./other.js";
"export * from "./other.mjs";
export type { Other } from "./other.mjs";
"
`);
expect(
Expand All @@ -879,12 +1041,12 @@ describe("mkdist with vue-tsc ~v2.0.21", () => {
expect(
await readFile(resolve(rootDir, "dist/components/index.d.ts"), "utf8"),
).toMatchInlineSnapshot(`
"export * as jsx from "./jsx.jsx.js";
export * as tsx from "./tsx.tsx.js";
export * as blank from "./blank.vue.js";
export * as scriptSetupTS from "./script-setup-ts.vue.js";
export * as scriptMultiBlock from "./script-multi-block.vue.js";
export * as ts from "./ts.vue.js";
"export * as jsx from "./jsx.jsx.mjs";
export * as tsx from "./tsx.tsx.mjs";
export * as blank from "./blank.vue.mjs";
export * as scriptSetupTS from "./script-setup-ts.vue.mjs";
export * as scriptMultiBlock from "./script-multi-block.vue.mjs";
export * as ts from "./ts.vue.mjs";
"
`);

Expand Down