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

new: Add pack command. #10

Merged
merged 4 commits into from
Nov 15, 2020
Merged
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: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"scripts": {
"prepare": "beemo create-config --silent",
"setup": "beemo typescript",
"build": "NODE_ENV=production yarn run packemon build --addEngines --generateDeclaration=api",
"build:fast": "yarn run packemon build",
"build": "yarn run packemon build",
"validate": "yarn run packemon validate",
"ci": "yarn run type && yarn run test && yarn run lint",
"clean": "rm -rf {build,dts,lib}",
Expand All @@ -22,7 +21,8 @@
"release": "npx np --yolo",
"test": "beemo jest",
"type": "beemo typescript --noEmit",
"prerelease": "yarn run ci && yarn run setup && yarn run build && yarn run validate",
"prerelease": "yarn run ci && yarn run setup && yarn run pack",
"pack": "NODE_ENV=production yarn run packemon pack --addEngines --generateDeclaration=api",
"packemon": "node ./build/bin.js"
},
"repository": "https://github.com/milesj/packemon.git",
Expand Down
2 changes: 1 addition & 1 deletion src/BundleArtifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default class BundleArtifact extends Artifact<BundleBuild> {
toArray(output).map(async (out, index) => {
const { originalFormat = 'lib', ...outOptions } = out;

this.debug('- Writing `%s` output', originalFormat);
this.debug(' - Writing `%s` output', originalFormat);

const result = await bundle.write(outOptions);

Expand Down
12 changes: 6 additions & 6 deletions src/Package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default class Package {
}

async cleanup(): Promise<void> {
this.debug('Cleaning artifacts');
this.debug('Cleaning build artifacts');

await Promise.all(this.artifacts.map((artifact) => artifact.cleanup()));
}
Expand All @@ -104,7 +104,7 @@ export default class Package {
if (this.hasDependency('react')) {
flags.react = true;

this.debug('- React');
this.debug(' - React');
}

// TypeScript
Expand All @@ -120,9 +120,9 @@ export default class Package {
flags.strict = Boolean(tsConfig?.options.strict);

this.debug(
`- TypeScript (${flags.strict ? 'strict' : 'non-strict'}, ${
flags.decorators ? 'decorators' : 'non-decorators'
})`,
' - TypeScript (%s, %s)',
flags.strict ? 'strict' : 'non-strict',
flags.decorators ? 'decorators' : 'non-decorators',
);
}

Expand All @@ -136,7 +136,7 @@ export default class Package {
) {
flags.flow = true;

this.debug('- Flow');
this.debug(' - Flow');
}

return flags;
Expand Down
2 changes: 1 addition & 1 deletion src/PackageValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ export default class PackageValidator {
}

if (isObject(repo)) {
const dir = (repo as { directory?: string }).directory;
const dir = repo.directory;

if (dir && !this.doesPathExist(dir)) {
this.errors.push(`Repository directory "${dir}" does not exist.`);
Expand Down
20 changes: 10 additions & 10 deletions src/Packemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default class Packemon {

readonly root: Path;

constructor(cwd: string) {
constructor(cwd: string = process.cwd()) {
this.root = Path.resolve(cwd);
this.project = new Project(this.root);

Expand All @@ -76,7 +76,7 @@ export default class Packemon {
this.project.checkEngineVersionConstraint();
}

async build(baseOptions: BuildOptions) {
async build(baseOptions: Partial<BuildOptions>) {
debug('Starting `build` process');

const options = optimal(baseOptions, {
Expand Down Expand Up @@ -108,8 +108,6 @@ export default class Packemon {
});
});

debug('Building artifacts');

const { errors } = await pipeline.run();

// Always cleanup whether a successful or failed build
Expand Down Expand Up @@ -146,13 +144,11 @@ export default class Packemon {
pathsToRemove.push(`./${formatFolders}`);
}

debug('Cleaning build artifacts');

await Promise.all(
pathsToRemove.map(
(path) =>
new Promise((resolve, reject) => {
debug('- %s', path);
debug(' - %s', path);

rimraf(path, (error) => {
if (error) {
Expand All @@ -166,7 +162,7 @@ export default class Packemon {
);
}

async validate(baseOptions: ValidateOptions): Promise<PackageValidator[]> {
async validate(baseOptions: Partial<ValidateOptions>): Promise<PackageValidator[]> {
debug('Starting `validate` process');

const options = optimal(baseOptions, {
Expand All @@ -191,6 +187,10 @@ export default class Packemon {
}

protected async findPackages(skipPrivate: boolean = false) {
if (this.packages.length > 0) {
return;
}

debug('Finding packages in project');

const pkgPaths: Path[] = [];
Expand Down Expand Up @@ -221,7 +221,7 @@ export default class Packemon {
const contents = json.parse<PackemonPackage>(await fs.readFile(pkgPath.path(), 'utf8'));

debug(
'- %s: %s',
' - %s: %s',
contents.name,
pkgPath.path().replace(this.root.path(), '').replace('package.json', ''),
);
Expand Down Expand Up @@ -284,7 +284,7 @@ export default class Packemon {
pkg.addArtifact(artifact);
}

debug('- %s: %s', pkg.getName(), pkg.artifacts.join(', '));
debug(' - %s: %s', pkg.getName(), pkg.artifacts.join(', '));
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Program, checkPackageOutdated } from '@boost/cli';
import { BuildCommand, CleanCommand, ValidateCommand } from '.';
import { BuildCommand, CleanCommand, PackCommand, ValidateCommand } from '.';

const version = String(require('../package.json').version);

Expand All @@ -15,6 +15,7 @@ async function run() {
.middleware(checkPackageOutdated('packemon', version))
.register(new BuildCommand())
.register(new CleanCommand())
.register(new PackCommand())
.register(new ValidateCommand());

await program.runAndExit(process.argv);
Expand Down
13 changes: 3 additions & 10 deletions src/commands/Build.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import Build from '../components/Build';
import Packemon from '../Packemon';
import { AnalyzeType, BuildOptions, DeclarationType } from '../types';

export type BuildParams = [string];

@Config('build', 'Build standardized packages for distribution')
export class BuildCommand extends Command<GlobalOptions & BuildOptions, BuildParams> {
export class BuildCommand extends Command<GlobalOptions & BuildOptions> {
@Arg.Flag('Add `engine` versions to each `package.json`')
addEngines: boolean = false;

Expand All @@ -34,15 +32,10 @@ export class BuildCommand extends Command<GlobalOptions & BuildOptions, BuildPar
@Arg.Number('Timeout in milliseconds before a build is cancelled')
timeout: number = 0;

@Arg.Params<BuildParams>({
description: 'Project root that contains a `package.json`',
label: 'cwd',
type: 'string',
})
run(cwd: string = process.cwd()) {
run() {
return (
<Build
packemon={new Packemon(cwd)}
packemon={new Packemon()}
addEngines={this.addEngines}
addExports={this.addExports}
analyzeBundle={this.analyze}
Expand Down
11 changes: 3 additions & 8 deletions src/commands/Clean.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import { Arg, Command, Config, GlobalOptions } from '@boost/cli';
import { Command, Config, GlobalOptions } from '@boost/cli';
import Packemon from '../Packemon';

export type CleanParams = [string];

@Config('clean', 'Clean build artifacts from packages')
export class CleanCommand extends Command<GlobalOptions, CleanParams> {
@Arg.Params<CleanParams>({
description: 'Project root that contains a `package.json`',
label: 'cwd',
type: 'string',
})
async run(cwd: string = process.cwd()) {
await new Packemon(cwd).clean();
async run() {
await new Packemon().clean();
}
}
23 changes: 23 additions & 0 deletions src/commands/Pack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { Config } from '@boost/cli';
import Pack from '../components/Pack';
import Packemon from '../Packemon';
import { BuildCommand } from './Build';

@Config('pack', 'Clean, build, and validate packages for distribution')
export class PackCommand extends BuildCommand {
run() {
return (
<Pack
packemon={new Packemon()}
addEngines={this.addEngines}
addExports={this.addExports}
analyzeBundle={this.analyze}
concurrency={this.concurrency}
generateDeclaration={this.generateDeclaration}
skipPrivate={this.skipPrivate}
timeout={this.timeout}
/>
);
}
}
34 changes: 14 additions & 20 deletions src/commands/Validate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import Packemon from '../Packemon';
import { ValidateOptions } from '../types';
import Validate from '../components/Validate';

export type ValidateParams = [string];

@Config('validate', 'Validate package metadata and configuration')
export class ValidateCommand extends Command<GlobalOptions & ValidateOptions, ValidateParams> {
export class ValidateCommand extends Command<GlobalOptions & ValidateOptions> {
@Arg.Flag('Check that dependencies have valid versions and constraints')
deps: boolean = true;

Expand All @@ -29,22 +27,18 @@ export class ValidateCommand extends Command<GlobalOptions & ValidateOptions, Va
@Arg.Flag('Check that `repository` exists and is a valid URL')
repo: boolean = true;

@Arg.Params<ValidateParams>({
description: 'Project root that contains a `package.json`',
label: 'cwd',
type: 'string',
})
async run(cwd: string = process.cwd()) {
const validators = await new Packemon(cwd).validate({
deps: this.deps,
engines: this.engines,
entries: this.entries,
license: this.license,
links: this.links,
people: this.people,
repo: this.repo,
});

return <Validate validators={validators} />;
run() {
return (
<Validate
packemon={new Packemon()}
deps={this.deps}
engines={this.engines}
entries={this.engines}
license={this.license}
links={this.links}
people={this.people}
repo={this.repo}
/>
);
}
}
37 changes: 15 additions & 22 deletions src/components/Build.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import React, { useEffect, useReducer, useRef, useState } from 'react';
import React, { useRef, useState } from 'react';
import { Box, Static } from 'ink';
import { Header } from '@boost/cli';
import { Header, useProgram } from '@boost/cli';
import Packemon from '../Packemon';
import PackageList from './PackageList';
import PackageRow from './PackageRow';
import Package from '../Package';
import { BuildOptions } from '../types';
import useRenderLoop from './hooks/useRenderLoop';
import useOnMount from './hooks/useOnMount';

export interface BuildProps extends Required<BuildOptions> {
export interface BuildProps extends Partial<BuildOptions> {
packemon: Packemon;
onBuilt?: () => void;
}

export default function Build({ packemon, ...options }: BuildProps) {
const [, forceUpdate] = useReducer((count) => count + 1, 0);
const [error, setError] = useState<Error>();
export default function Build({ packemon, onBuilt, ...options }: BuildProps) {
const { exit } = useProgram();
const [staticPackages, setStaticPackages] = useState<Package[]>([]);
const staticNames = useRef(new Set<string>());
const clearLoop = useRenderLoop();

useEffect(() => {
// Continuously render at 30 FPS
const timer = setInterval(forceUpdate, 1000 / 30);
const clear = () => clearInterval(timer);

// Run the packemon process on mount
void packemon.build(options).catch(setError).finally(clear);
// Run the build process on mount
useOnMount(() => {
void packemon.build(options).then(onBuilt).catch(exit).finally(clearLoop);

// Add complete packages to the static list
const unlisten = packemon.onPackageBuilt.listen((pkg) => {
Expand All @@ -34,23 +33,17 @@ export default function Build({ packemon, ...options }: BuildProps) {
});

return () => {
clear();
clearLoop();
unlisten();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

// Bubble up errors to the program
if (error) {
throw error;
}
});

const runningPackages = packemon.packages.filter((pkg) => pkg.isRunning());

return (
<>
<Static items={staticPackages}>
{(pkg) => <PackageRow key={pkg.getName()} package={pkg} />}
{(pkg) => <PackageRow key={`static-build-${pkg.getName()}`} package={pkg} />}
</Static>

{runningPackages.length > 0 && (
Expand Down
Loading