Skip to content

Commit

Permalink
Support multiple dist configurations and ESM (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan authored Jun 9, 2021
1 parent 00537fe commit 9e72e67
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 78 deletions.
3 changes: 1 addition & 2 deletions action/commands/build.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export declare const distDir = "dist";
export declare const DIST_DIR = "dist";
export declare const buildCommand: import("../command").CommandFactory<{}, {
single?: boolean | undefined;
}>;
export declare function readPackageJson(baseDir: string): Promise<any>;
export declare function validatePackageJson(pkg: any): void;
//# sourceMappingURL=build.d.ts.map
4 changes: 4 additions & 0 deletions action/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export interface BobConfig {
commands?: {
[cmdName: string]: Command;
};
dists?: {
distDir: string;
distPath?: string;
}[];
}
interface UseConfigOptions {
config?: string;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"yargs": "15.3.1"
},
"scripts": {
"prepublish": "yarn build",
"build": "tsc && ncc build src/action.ts -o action"
},
"devDependencies": {
Expand Down
157 changes: 91 additions & 66 deletions src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ interface BuildOptions {
bin?: Record<string, { input: string; sourcemap?: boolean }>;
}

export const distDir = "dist";
export const DIST_DIR = "dist";

interface PackageInfo {
packagePath: string;
cwd: string;
pkg: any;
fullName: string;
}

export const buildCommand = createCommand<
{},
Expand All @@ -42,31 +49,48 @@ export const buildCommand = createCommand<
});
},
async handler(args) {
config.dists = config.dists || [
{
distDir: DIST_DIR,
distPath: ''
}
];
if (args.single) {
await buildSingle();
await buildSingle({ distDir: DIST_DIR });
return;
}

const limit = pLimit(4);
const packages = await globby("packages/**/package.json", {
cwd: process.cwd(),
absolute: true,
ignore: ["**/node_modules/**", `**/${distDir}/**`],
ignore: ["**/node_modules/**", ...config.dists.map(({ distDir }) => `**/${distDir}/**`)],
});

await Promise.all(
packages.map((packagePath) =>
limit(() => build(packagePath, config, reporter))
)
const packageInfoList: PackageInfo[] = await Promise.all(
packages.map(packagePath => limit(async () => {
const cwd = packagePath.replace("/package.json", "");
const pkg = await fs.readJSON(resolve(cwd, 'package.json'));
const fullName: string = pkg.name;
return { packagePath, cwd, pkg, fullName };
}))
);

for (const { distDir, distPath } of config.dists) {
await Promise.all(
packageInfoList.map(({ packagePath, cwd, pkg, fullName }) =>
limit(() => build({ packagePath, cwd, pkg, fullName, config, reporter, distDir, distPath, packageInfoList }))
)
);
}
},
};
});

async function buildSingle() {
async function buildSingle({ distDir, distPath = '' }: { distDir: string; distPath?: string; }) {
const cwd = process.cwd();
const packagePath = join(process.cwd(), "package.json");
const pkg = await readPackageJson(cwd);
const pkg = await fs.readJSON(packagePath);

validatePackageJson(pkg);

Expand All @@ -87,7 +111,7 @@ async function buildSingle() {
}),
typescript(),
generatePackageJson({
baseContents: rewritePackageJson(pkg),
baseContents: rewritePackageJson(pkg, distPath),
additionalDependencies: Object.keys(pkg.dependencies || {}),
}),
],
Expand All @@ -108,24 +132,16 @@ async function buildSingle() {
const generates = [
{
...commonOutputOptions,
file: join(distDir, "index.cjs.js"),
file: join(distDir, "index.js"),
format: "cjs" as const,
},
{
...commonOutputOptions,
file: join(distDir, "index.esm.js"),
file: join(distDir, "index.mjs"),
format: "esm" as const,
},
];

if (pkg.exports) {
generates.push({
...commonOutputOptions,
file: join(distDir, "index.mjs"),
format: "esm" as const,
});
}

await Promise.all(
generates.map(async (outputOptions) => {
await bundle.write(outputOptions);
Expand All @@ -135,26 +151,22 @@ async function buildSingle() {
// move README.md and LICENSE
await copyToDist(
cwd,
["README.md", "LICENSE"].concat(buildOptions?.copy || [])
["README.md", "LICENSE"].concat(buildOptions?.copy || []),
DIST_DIR + distPath
);
}

async function build(
packagePath: string,
config: BobConfig,
reporter: Consola
{ packagePath, cwd, pkg, fullName, config, reporter, distDir, distPath = '', packageInfoList }: { packagePath: string; cwd: string; pkg: any; fullName: string; config: BobConfig; reporter: Consola; distDir: string; distPath?: string; packageInfoList: PackageInfo[] },
) {
const scope = config.scope;
const cwd = packagePath.replace("/package.json", "");
const pkg = await readPackageJson(cwd);
const fullName: string = pkg.name;

if ((config.ignore || []).includes(fullName)) {
reporter.warn(`Ignored ${fullName}`);
return;
}

const name = fullName.replace(`${scope}/`, "");
const name = fullName.replace(`${scope}/`, distPath);

validatePackageJson(pkg);

Expand Down Expand Up @@ -184,7 +196,7 @@ async function build(
packageJSONPath: packagePath,
}),
generatePackageJson({
baseContents: rewritePackageJson(pkg),
baseContents: rewritePackageJson(pkg, distPath),
additionalDependencies: Object.keys(pkg.dependencies || {}),
}),
],
Expand All @@ -205,24 +217,16 @@ async function build(
const generates = [
{
...commonOutputOptions,
file: join(bobProjectDir, "index.cjs.js"),
file: join(bobProjectDir, "index.js"),
format: "cjs" as const,
},
{
...commonOutputOptions,
file: join(bobProjectDir, "index.esm.js"),
file: join(bobProjectDir, "index.mjs"),
format: "esm" as const,
},
];

if (pkg.exports) {
generates.push({
...commonOutputOptions,
file: join(distDir, "index.mjs"),
format: "esm" as const,
});
}

const declarations = await globby("**/*.d.ts", {
cwd: distProjectSrcDir,
ignore: ["**/node_modules/**"],
Expand Down Expand Up @@ -269,37 +273,45 @@ async function build(
banner: `#!/usr/bin/env node`,
preferConst: true,
sourcemap: options.sourcemap,
file: join(bobProjectDir, pkg.bin[alias].replace(`${distDir}/`, "")),
file: join(bobProjectDir, pkg.bin[alias].replace(`${DIST_DIR}/`, "")),
format: "cjs",
});
})
);
}

// remove <project>/dist
await fs.remove(join(cwd, distDir));
await fs.remove(join(cwd, DIST_DIR + distPath));

// fix distPath import in extra dists
function replaceAll(str: string, from: string, to: string) {
return str.split(from).join(to);
}
if (distPath) {
await Promise.all(
generates.map(({ file }) => limit(async () => {
let content = await fs.readFile(file, 'utf8');
for (const { fullName } of packageInfoList) {
content = replaceAll(content, `'${fullName}'`, `'${fullName}${distPath}'`);
}
await fs.writeFile(file, content, { encoding: 'utf8', flag: 'w' });
}))
)
}

// move bob/<project-name> to <project>/dist
await fs.move(bobProjectDir, join(cwd, distDir));
await fs.move(bobProjectDir, join(cwd, DIST_DIR + distPath));
// move README.md and LICENSE
await copyToDist(
cwd,
["README.md", "LICENSE"].concat(pkg.buildOptions?.copy || [])
["README.md", "LICENSE"].concat(pkg.buildOptions?.copy || []),
DIST_DIR + distPath
);

reporter.success(`Built ${pkg.name}`);
}

//

export async function readPackageJson(baseDir: string) {
return JSON.parse(
await fs.readFile(resolve(baseDir, "package.json"), {
encoding: "utf-8",
})
);
}

function rewritePackageJson(pkg: Record<string, any>) {
function rewritePackageJson(pkg: Record<string, any>, distPath: string) {
const newPkg: Record<string, any> = {};
const fields = [
"name",
Expand All @@ -323,18 +335,30 @@ function rewritePackageJson(pkg: Record<string, any>) {
}
});

newPkg.main = "index.cjs.js";
newPkg.module = "index.esm.js";
newPkg.name += distPath;
newPkg.main = "index.js";
newPkg.module = "index.mjs";
newPkg.typings = "index.d.ts";
newPkg.typescript = {
definition: newPkg.typings,
};

newPkg.exports = {
".": {
require: "./index.js",
import: "./index.mjs",
},
"./*": {
require: "./*.js",
import: "./*.mjs",
},
};

if (pkg.bin) {
newPkg.bin = {};

for (const alias in pkg.bin) {
newPkg.bin[alias] = pkg.bin[alias].replace(`${distDir}/`, "");
newPkg.bin[alias] = pkg.bin[alias].replace(`${DIST_DIR}/`, "");
}
}

Expand All @@ -352,18 +376,19 @@ export function validatePackageJson(pkg: any) {
}
}

expect("main", `${distDir}/index.cjs.js`);
expect("module", `${distDir}/index.esm.js`);
expect("typings", `${distDir}/index.d.ts`);
expect("typescript.definition", `${distDir}/index.d.ts`);
expect("main", `${DIST_DIR}/index.js`);
expect("module", `${DIST_DIR}/index.mjs`);
expect("typings", `${DIST_DIR}/index.d.ts`);
expect("typescript.definition", `${DIST_DIR}/index.d.ts`);

if (pkg.exports) {
expect("exports.require", `./${pkg.main}`);
expect("exports.default", `./${distDir}/index.mjs`);
}
expect("exports['.'].require", `./${DIST_DIR}/index.js`);
expect("exports['.'].import", `./${DIST_DIR}/index.mjs`);

expect("exports['./*'].require", `./${DIST_DIR}/*.js`);
expect("exports['./*'].import", `./${DIST_DIR}/*.mjs`);
}

async function copyToDist(cwd: string, files: string[]) {
async function copyToDist(cwd: string, files: string[], distDir: string) {
const allFiles = await globby(files, { cwd });

return Promise.all(
Expand Down
12 changes: 6 additions & 6 deletions src/commands/pack-flat.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import globby from "globby";
import pLimit from "p-limit";
import fs from "fs-extra";
import fs, { readJSON } from "fs-extra";
import { resolve, join } from "path";
import { execSync } from "child_process";
import { Consola } from "consola";
import { paramCase } from "param-case";

import { createCommand } from "../command";
import { BobConfig } from "../config";
import { readPackageJson, distDir } from "./build";
import { DIST_DIR } from "./build";

export const packFlatCommand = createCommand<
{},
Expand Down Expand Up @@ -36,7 +36,7 @@ export const packFlatCommand = createCommand<
const packages = await globby("packages/**/package.json", {
cwd: process.cwd(),
absolute: true,
ignore: ["**/node_modules/**", `**/${distDir}/**`],
ignore: ["**/node_modules/**", `**/${DIST_DIR}/**`],
});

await Promise.all(
Expand All @@ -50,19 +50,19 @@ export const packFlatCommand = createCommand<

async function pack(packagePath: string, commit: string, config: BobConfig, reporter: Consola) {
const cwd = packagePath.replace("/package.json", "");
const pkg = await readPackageJson(cwd);
const pkg = await readJSON(packagePath);
const fullName: string = pkg.name;

if ((config.ignore || []).includes(fullName)) {
reporter.warn(`Ignored ${fullName}`);
return;
}

const projectDistDir = join(cwd, distDir);
const projectDistDir = join(cwd, DIST_DIR);
const bobDir = resolve(process.cwd(), ".bob-packed");

// replace version to 0.0.0-canary-${commit}
const distPkg = await readPackageJson(projectDistDir);
const distPkg = await readJSON(join(projectDistDir, 'package.json'));
const version = `0.0.0-canary-${commit}`;
distPkg.version = version;
await fs.writeFile(join(projectDistDir, 'package.json'), JSON.stringify(distPkg, null, 2), {
Expand Down
Loading

0 comments on commit 9e72e67

Please sign in to comment.