Skip to content

Commit

Permalink
feat(cli): updated build command to typecheck fewer files (#602)
Browse files Browse the repository at this point in the history
  • Loading branch information
pluvrt authored Apr 14, 2024
1 parent f1d6fee commit 42707d2
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/wicked-tigers-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"pluv": patch
---

Updated the pluv cli's `build` command so that only the pluv entry file and all necessary dependencies are type-checked, instead of all TypeScript files in the project workspace.
5 changes: 3 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@
"react": "^18.2.0",
"rollup": "^4.14.2",
"rollup-plugin-node-polyfills": "^0.2.1",
"tslib": "^2.6.2",
"typescript": "^5.4.5",
"zod": "^3.22.4"
},
"devDependencies": {
"@pluv/tsconfig": "workspace:^",
"eslint": "^8.57.0",
"eslint-config-pluv": "workspace:^",
"typescript": "^5.4.5"
"eslint-config-pluv": "workspace:^"
}
}
3 changes: 2 additions & 1 deletion packages/cli/src/hooks/useBuildApp.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useApp } from "ink";
import { useState } from "react";
import { BuildAppOptions, buildApp } from "../utils/buildApp.js";
import type { BuildAppOptions } from "../utils/index.js";
import { buildApp } from "../utils/index.js";
import { useMountEffect } from "./useMountEffect.js";

export const useBuildApp = (options: BuildAppOptions) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/hooks/useConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import { getConfig } from "../utils/config.js";
import { getConfig } from "../utils/index.js";

export const useConfig = () => {
const [config] = useState(() => getConfig());
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/schemas/ZodPluvConfig.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { z } from "zod";

export const ZodPluvConfig = z.object({
env: z
.intersection(z.record(z.string(), z.string()), z.string())
.optional(),
env: z.record(z.string(), z.string()).optional(),
input: z.string().default("./pluv.ts"),
outDir: z.string().default("./.pluv"),
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import terser from "@rollup/plugin-terser";
import typescript from "@rollup/plugin-typescript";
import dotenv from "dotenv";
import fs from "fs-extra";
import path from "path";
import path from "node:path";
import { OutputAsset, OutputChunk, Plugin, rollup } from "rollup";
import nodePolyfills from "rollup-plugin-node-polyfills";
import { resolveDependenciesTransformer } from "./resolveDependenciesTransformer.js";

const isOutputValid = (chunks: (OutputChunk | OutputAsset)[]): boolean => {
return chunks.some((chunk) => {
Expand Down Expand Up @@ -52,6 +53,9 @@ export interface BuildAppOptions {
export const buildApp = async (options: BuildAppOptions) => {
const { env, input, outDir: _outDir } = options;

const outDir = path.resolve(process.cwd(), options.outDir);
const outFile = path.resolve(outDir, "./index.js");

const replaceEnv = Object.entries(getEnv(env)).reduce<
Record<string, string>
>(
Expand All @@ -64,13 +68,16 @@ export const buildApp = async (options: BuildAppOptions) => {

const bundle = await rollup({
input,
output: { format: "esm" },
output: { format: "esm", file: outFile },
onLog: (level, log) => {
const { frame, loc, message } = log;

if (loc) {
console.warn(
`${loc.file} (${loc.line}:${loc.column}) ${message}`,
`${message}`
.replace(/\s*\[plugin\s+\w+\]\s*/gi, "")
.replace(/\s*@rollup\/plugin\S+\s*/gi, "")
.replace(/\s*rollup\S+\s*/gi, ""),
);
if (frame) console.warn(frame);
} else {
Expand Down Expand Up @@ -103,6 +110,8 @@ export const buildApp = async (options: BuildAppOptions) => {
skipLibCheck: true,
strict: true,
target: "es2021",
transformers: { before: [resolveDependenciesTransformer] },
include: input,
}),
// Converts CommonJS modules to ES6.
(commonjs as unknown as typeof commonjs.default)({
Expand All @@ -128,10 +137,8 @@ export const buildApp = async (options: BuildAppOptions) => {
],
});

const outDir = path.resolve(process.cwd(), options.outDir);

const { output } = await bundle.generate({
file: path.resolve(outDir, "./index.js"),
file: outFile,
format: "esm",
});

Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/utils/buildApp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { buildApp } from "./buildApp.js";
export type { BuildAppOptions } from "./buildApp.js";
68 changes: 68 additions & 0 deletions packages/cli/src/utils/buildApp/resolveDependenciesTransformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ProgramTransformerFactory } from "@rollup/plugin-typescript";
import path from "node:path";
import type { SourceFile, TransformerFactory } from "typescript";
import ts from "typescript";

const resolveDependencies = (entryFilePath: string): string[] => {
const dependencies = new Set<string>();
const visited = new Set<string>();

const visit = (filePath: string) => {
if (visited.has(filePath)) return;

visited.add(filePath);

const sourceText = ts.sys.readFile(filePath);

if (!sourceText) return;

let sourceFile: SourceFile = ts.createSourceFile(
filePath,
sourceText,
ts.ScriptTarget.ESNext,
true,
);

if (!sourceFile) return;

ts.forEachChild(sourceFile, (node) => {
if (!ts.isImportDeclaration(node)) return;

const importPath = node.moduleSpecifier.getText();
const absolutePath = path.resolve(
path.dirname(filePath),
importPath,
);

dependencies.add(importPath);

visit(absolutePath);
});
};

visit(entryFilePath);

return Array.from(dependencies.values());
};

export const resolveDependenciesTransformer: ProgramTransformerFactory<"before"> =
{
type: "program",
factory: (program): TransformerFactory<ts.SourceFile> => {
return (context) => {
return (node) => {
const dependencies = resolveDependencies(node.fileName);

dependencies.forEach((dependency) => {
const sourceFile = program.getSourceFile(dependency);

try {
program.emit(sourceFile);
} catch {}
});

return node;
};
};
},
};
File renamed without changes.
5 changes: 4 additions & 1 deletion packages/cli/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from "./config.js";
export { buildApp } from "./buildApp/index.js";
export type { BuildAppOptions } from "./buildApp/index.js";
export { getConfig } from "./getConfig.js";
export type { ParsedPluvConfig, PluvConfig } from "./getConfig.js";
16 changes: 10 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 42707d2

Please sign in to comment.