Skip to content

Commit

Permalink
fix: Rework React components.
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj committed Oct 8, 2020
1 parent 9d74d94 commit 9f7ec36
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 130 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
],
"scripts": {
"prepare": "beemo create-config --silent",
"build": "beemo typescript",
"build": "yarn run packemon",
"ci": "yarn run type && yarn run test && yarn run lint",
"coverage": "yarn run test --coverage",
"format": "beemo prettier",
Expand All @@ -19,7 +19,7 @@
"test": "beemo jest",
"type": "beemo typescript --noEmit",
"prerelease": "yarn run ci && yarn run build",
"packemon": "node ./lib/src/bin.js"
"packemon": "node ./bin/packemon.js"
},
"repository": "https://github.com/milesj/packemon.git",
"author": "Miles Johnson",
Expand Down
1 change: 1 addition & 0 deletions src/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"rules": {
"no-console": "off",
"no-magic-numbers": "off",
"sort-keys": "off",
"promise/always-return": "off"
}
Expand Down
39 changes: 24 additions & 15 deletions src/Packemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export default class Packemon extends Contract<PackemonOptions> {

project: Project;

readonly onComplete = new Event('complete');

readonly onBootProgress = new Event<[number, number]>('boot-progress');

constructor(cwd: string, options: PackemonOptions) {
Expand All @@ -59,11 +61,13 @@ export default class Packemon extends Contract<PackemonOptions> {
async boot() {
const result = await this.getPackagesAndWorkspaces();

return this.generateBuilds(result.packages, result.workspaces);
this.builds = this.generateBuilds(result.packages, result.workspaces);
}

async build(builds: Build[]) {
this.builds = builds;
async build() {
if (this.builds.length === 0) {
throw new Error('No builds found. Aborting.');
}

const pipeline = new PooledPipeline(new Context());

Expand All @@ -72,15 +76,15 @@ export default class Packemon extends Contract<PackemonOptions> {
timeout: this.options.timeout,
});

builds.forEach((build) => {
this.builds.forEach((build) => {
pipeline.add(`Building ${build.package.name}`, () => this.buildWithRollup(build));
});

const result = await pipeline.run();

// Mark all running builds as skipped
if (result.errors.length > 0) {
builds.forEach((build) => {
this.builds.forEach((build) => {
if (build.status === 'building') {
build.status = 'skipped';
}
Expand Down Expand Up @@ -142,7 +146,11 @@ export default class Packemon extends Contract<PackemonOptions> {
build.result.time = Date.now() - start;
}

generateBuilds(packages: PackemonPackage[], workspaces: string[]): Build[] {
async pack() {
this.onComplete.emit([]);
}

protected generateBuilds(packages: PackemonPackage[], workspaces: string[]): Build[] {
return packages.map((pkg) => {
const config = pkg.packemon;
const flags: BuildFlags = {};
Expand Down Expand Up @@ -183,27 +191,26 @@ export default class Packemon extends Contract<PackemonOptions> {
});
}

getFeatureFlags(build: Build): FeatureFlags {
protected getFeatureFlags(build: Build): FeatureFlags {
return {
...this.getRootFeatureFlags(),
...build.getFeatureFlags(),
};
}

@Memoize()
getRootFeatureFlags(): FeatureFlags {
protected getRootFeatureFlags(): FeatureFlags {
return new Build(this.root, this.project.getPackage<PackemonPackage>(), []).getFeatureFlags();
}

async getPackagesAndWorkspaces(): Promise<{
protected async getPackagesAndWorkspaces(): Promise<{
packages: PackemonPackage[];
workspaces: string[];
}> {
const workspaces = this.project.getWorkspaceGlobs({ relative: true });
const pkgPaths: Path[] = [];
const pkgLength = pkgPaths.length;

this.onBootProgress.emit([0, pkgLength]);
this.onBootProgress.emit([0, pkgPaths.length]);

// Multi package repo
if (workspaces.length > 0) {
Expand All @@ -216,7 +223,7 @@ export default class Packemon extends Contract<PackemonOptions> {
pkgPaths.push(this.root.append('package.json'));
}

this.onBootProgress.emit([0, pkgLength]);
this.onBootProgress.emit([0, pkgPaths.length]);

let counter = 0;
let packages: WorkspacePackage<PackemonPackage>[] = await Promise.all(
Expand All @@ -227,7 +234,7 @@ export default class Packemon extends Contract<PackemonOptions> {
);

counter += 1;
this.onBootProgress.emit([counter, pkgLength]);
this.onBootProgress.emit([counter, pkgPaths.length]);

return {
metadata: this.project.createWorkspaceMetadata(pkgPath),
Expand All @@ -236,7 +243,7 @@ export default class Packemon extends Contract<PackemonOptions> {
}),
);

this.onBootProgress.emit([pkgLength, pkgLength]);
this.onBootProgress.emit([pkgPaths.length, pkgPaths.length]);

// Skip `private` packages
if (this.options.skipPrivate) {
Expand All @@ -249,7 +256,9 @@ export default class Packemon extends Contract<PackemonOptions> {
};
}

validateAndPreparePackages(packages: WorkspacePackage<PackemonPackage>[]): PackemonPackage[] {
protected validateAndPreparePackages(
packages: WorkspacePackage<PackemonPackage>[],
): PackemonPackage[] {
const spdxLicenseTypes = new Set(
Object.keys(spdxLicenses).map((key) => key.toLocaleLowerCase()),
);
Expand Down
5 changes: 5 additions & 0 deletions src/components/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-use-before-define": "off"
}
}
29 changes: 13 additions & 16 deletions src/components/BootPhase/index.tsx → src/components/BootPhase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,16 @@ import React, { useEffect, useState } from 'react';
import { Box } from 'ink';
import ProgressBar from 'ink-progress-bar';
import { Header } from '@boost/cli';
import Packemon from '../../Packemon';
import Build from '../../Build';

const DELAY_PHASE = 100;
import Packemon from '../Packemon';

export interface BootPhaseProps {
packemon: Packemon;
onBooted: (builds: Build[]) => void;
onBooted: () => void;
}

export default function BootPhase({ packemon, onBooted }: BootPhaseProps) {
const [progress, setProgress] = useState(0);

// Find all packages and generate builds on mount
useEffect(() => {
void packemon.boot().then((builds) => {
// Delay next phase to show progress bar
setTimeout(() => {
onBooted(builds);
}, DELAY_PHASE);
});
}, [packemon, onBooted]);

// Monitor generation progress
useEffect(() => {
const handleProgress = (current: number, total: number) => {
Expand All @@ -38,10 +25,20 @@ export default function BootPhase({ packemon, onBooted }: BootPhaseProps) {
};
}, [packemon]);

// Find all packages and generate builds on mount
useEffect(() => {
void packemon.boot().then(() => {
// Delay next phase to show progress bar
setTimeout(() => {
onBooted();
}, 1000);
});
}, [packemon, onBooted]);

return (
<Box flexDirection="column">
<Header label="Bootstrapping packages and generating build requests" />
<ProgressBar percent={progress} />
<ProgressBar percent={progress || 0.1} />
</Box>
);
}
22 changes: 18 additions & 4 deletions src/components/BuildPhase/Row.tsx → src/components/BuildList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { Box } from 'ink';
import Spinner from 'ink-spinner';
import { formatMs } from '@boost/common';
import { Style, StyleType } from '@boost/cli';
import Build from '../../Build';
import TargetPlatforms from '../TargetPlatforms';
import { BuildStatus } from '../../types';
import Build from '../Build';
import { BuildStatus } from '../types';
import TargetPlatforms from './TargetPlatforms';

const STATUS_COLORS: { [K in BuildStatus]: StyleType } = {
pending: 'muted',
Expand All @@ -19,7 +19,7 @@ export interface BuildRowProps {
build: Build;
}

export default function BuildRow({ build }: BuildRowProps) {
export function BuildRow({ build }: BuildRowProps) {
return (
<Box flexDirection="column" marginTop={1}>
<Box flexDirection="row">
Expand Down Expand Up @@ -58,3 +58,17 @@ export default function BuildRow({ build }: BuildRowProps) {
</Box>
);
}

export interface BuildListProps {
builds: Build[];
}

export default function BuildList({ builds }: BuildListProps) {
return (
<>
{builds.map((build) => (
<BuildRow key={build.package.name} build={build} />
))}
</>
);
}
59 changes: 59 additions & 0 deletions src/components/BuildPhase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useEffect, useState } from 'react';
import { Box } from 'ink';
import { Header } from '@boost/cli';
import BuildList from './BuildList';
import Packemon from '../Packemon';
import Build from '../Build';

export interface BuildPhaseProps {
packemon: Packemon;
onBuilt: () => void;
}

export default function BuildPhase({ packemon, onBuilt }: BuildPhaseProps) {
const [errors, setErrors] = useState<Error[]>([]);

// Start building packages on mount
useEffect(() => {
void packemon.build().then((result) => {
setTimeout(() => {
if (result.errors.length > 0) {
setErrors(result.errors);
} else {
onBuilt();
}
}, 1000);
});
}, [packemon, onBuilt]);

// Update and sort build list states
const pendingBuilds: Build[] = [];
const runningBuilds: Build[] = [];

packemon.builds.forEach((build) => {
if (build.status === 'building') {
runningBuilds.push(build);
} else if (build.status === 'pending') {
pendingBuilds.push(build);
}
});

// Bubble up errors to the main application
if (errors.length > 0) {
throw errors[0];
}

// Phase label
let label = `Building ${runningBuilds.length} packages`;

if (pendingBuilds.length > 0) {
label += ` (${pendingBuilds.length} pending)`;
}

return (
<Box flexDirection="column">
<Header label={label} />
<BuildList builds={runningBuilds} />
</Box>
);
}
17 changes: 0 additions & 17 deletions src/components/BuildPhase/List.tsx

This file was deleted.

68 changes: 0 additions & 68 deletions src/components/BuildPhase/index.tsx

This file was deleted.

Loading

0 comments on commit 9f7ec36

Please sign in to comment.