Skip to content

Commit

Permalink
new: Add pack command. (#10)
Browse files Browse the repository at this point in the history
* Add pack command.

* Removed cwd.

* Rework components.

* Polish.
  • Loading branch information
milesj authored Nov 15, 2020
1 parent 550dbbe commit 31508cc
Show file tree
Hide file tree
Showing 19 changed files with 208 additions and 115 deletions.
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

0 comments on commit 31508cc

Please sign in to comment.