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

Add flow version based symlink resolution #2

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a13e4d6
Disable legacy build
goodmind May 21, 2019
87084dd
Add flow version parser
goodmind May 21, 2019
951012a
Add getFlowVersion method
goodmind May 21, 2019
4a63f4d
Dispatch new methods to config
goodmind May 21, 2019
5f88da6
Add packages resolution
goodmind May 21, 2019
3bc7f98
Move dependency graph calculation out of loop
goodmind May 21, 2019
77ebde4
Use links hashmap
goodmind May 21, 2019
0247636
Add dependency validation
goodmind May 21, 2019
36f1c87
Remove version checking
goodmind May 24, 2019
54764c9
Use filePath for primaryKey
goodmind Jun 18, 2019
a82c049
Update yarn version
goodmind Jun 18, 2019
bf68a38
Index packages by primary key
goodmind Jun 18, 2019
980e0d1
Add escape quotes to spawn commands
goodmind Jun 18, 2019
71530c0
Refactor publish
goodmind Jun 18, 2019
a2dc082
Add registry option to npm utils
goodmind Jun 18, 2019
8ab9541
Add expected flow to error message
goodmind Jun 18, 2019
5810f5e
Add registry option to publish command
goodmind Jun 18, 2019
6297dea
Add dependencies instead of symlinking
goodmind Jun 18, 2019
d44bfad
Ignore project version for dependencies
goodmind Jun 18, 2019
259596f
Add rename to fs utils
goodmind Jun 18, 2019
73ef420
Check packages in graph before adding from registry
goodmind Jun 18, 2019
49a9439
Ignore .history
goodmind Aug 10, 2019
0ece640
Change error messages
goodmind Aug 10, 2019
c0c841c
Change linking message
goodmind Aug 10, 2019
e7454f3
Use graph paths to resolve internal packages
goodmind Aug 10, 2019
afcc260
Change errors when dependency is unresolved
goodmind Aug 10, 2019
4162cbb
Update flow-bin
goodmind Aug 10, 2019
da2dfef
Add getDistTag
goodmind Aug 10, 2019
20c3cf8
Replace object map with Map
goodmind Aug 10, 2019
e6d9e79
Add version to failed publish message
goodmind Aug 10, 2019
1549e78
Add filter options to publish command
goodmind Aug 10, 2019
6cd83b6
Add experimental version command
goodmind Aug 10, 2019
b0b997e
* Pass registry to npm info
goodmind Aug 10, 2019
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
1 change: 1 addition & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[ignore]
.*/__fixtures__/.*
.*/node_modules/.*

[include]

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ coverage/
!**/__fixtures__/**/node_modules/
example-2
.vscode/
.history/
**/.DS_Store
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"format": "prettier --write src/**/*.js",
"build:legacy": "cross-env BABEL_ENV=legacy babel src -d dist/legacy",
"build:modern": "cross-env BABEL_ENV=modern babel src -d dist/modern",
"build": "yarn run clean && yarn build:legacy && yarn build:modern",
"build": "yarn run clean && yarn build:modern",
"prepare": "yarn build",
"prepublishOnly": "yarn build",
"precommit": "lint-staged"
Expand All @@ -35,7 +35,7 @@
"babel-preset-flow": "^6.23.0",
"cross-env": "^5.1.3",
"fixturez": "^1.1.0",
"flow-bin": "^0.68.0",
"flow-bin": "^0.84.0",
"husky": "^0.14.3",
"jest": "^20.0.4",
"jest-expect-contain-deep": "^1.0.1",
Expand Down Expand Up @@ -72,12 +72,14 @@
"read-pkg": "^2.0.0",
"rimraf": "^2.6.1",
"semver": "^5.4.1",
"signal-exit": "^3.0.2",
"slash": "^1.0.0",
"sort-object": "^3.0.2",
"task-graph-runner": "^1.0.1",
"temp-write": "^3.4.0",
"typeable-promisify": "^2.0.1",
"yarn": "^1.9.4"
"write-pkg": "^4.0.0",
"yarn": "^1.16.0"
},
"jest": {
"resetMocks": true,
Expand Down
23 changes: 23 additions & 0 deletions src/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as path from 'path';
import * as globs from './utils/globs';
import * as logger from './utils/logger';
import * as messages from './utils/messages';
import * as flowVersion from './utils/flowVersion';
import { BoltError } from './utils/errors';

async function getPackageStack(cwd: string) {
Expand Down Expand Up @@ -195,6 +196,23 @@ export default class Config {
return name;
}

getDistTag(): string {
let config = this.getConfig();
let { tag = 'latest' } = config.publishConfig || {};
return tag;
}

getPrimaryKey(): string {
let config = this.getConfig();
let name = config.name;
if (typeof name !== 'string') {
throw new BoltError(
`package.json#name must be a string. See "${this.filePath}"`
);
}
return this.filePath;
}

getVersion(): string {
let config = this.getConfig();
let version = config.version;
Expand All @@ -206,6 +224,11 @@ export default class Config {
return version;
}

getFlowVersion(): flowVersion.FlowVersion {
let config = this.getConfig();
return flowVersion.parseDirString(config.flowVersion);
}

getPrivate(): boolean | void {
let config = this.getConfig();
let priv = config.private;
Expand Down
8 changes: 8 additions & 0 deletions src/Package.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,18 @@ export default class Package {
return this.config.getName();
}

getPrimaryKey() {
return this.config.getPrimaryKey();
}

getVersion() {
return this.config.getVersion();
}

getFlowVersion() {
return this.config.getFlowVersion();
}

getBins(): Array<{ name: string, filePath: string }> {
let bin = this.config.getBin();
if (typeof bin === 'undefined') {
Expand Down
120 changes: 96 additions & 24 deletions src/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import * as globs from './utils/globs';
import taskGraphRunner from 'task-graph-runner';
import minimatch from 'minimatch';
import * as env from './utils/env';
import * as flowVersion from './utils/flowVersion';
import chunkd from 'chunkd';

type GenericTask<T> = (pkg: Package) => Promise<T>;
Expand Down Expand Up @@ -71,7 +72,6 @@ export default class Project {

queue.push(pkg);
packages.push(pkg);

}
}

Expand All @@ -83,48 +83,116 @@ export default class Project {
string,
{ pkg: Package, dependencies: Array<string> }
> = new Map();
let paths: Map<Package, Map<string, Package>> = new Map();
let queue = [this.pkg];
let packagesByName = { [this.pkg.getName()]: this.pkg };
let packagesByName: Map<string, Array<Package>> = new Map([
[this.pkg.getName(), this.pkg]
]);
let valid = true;

for (let pkg of packages) {
if (!packagesByName.has(pkg.getName())) {
packagesByName.set(pkg.getName(), []);
}

queue.push(pkg);
packagesByName[pkg.getName()] = pkg;
packagesByName.get(pkg.getName()).push(pkg);
}

for (let pkg of queue) {
let name = pkg.config.getName();
let version = pkg.config.getVersion();
let primaryKey = pkg.config.getPrimaryKey();
let currentFlowVersion = pkg.config.getFlowVersion();
let dependencies = [];
let allDependencies = pkg.getAllDependencies();

for (let [depName, depVersion] of allDependencies) {
let match = packagesByName[depName];
let match = packagesByName.get(depName);
if (!match) continue;

let actual = depVersion;
let expected = match.config.getVersion();

// Workspace dependencies only need to semver satisfy, not '==='
if (!semver.satisfies(expected, depVersion)) {
if (match.length === 0) continue;

let errorMessages = [];
let flowVersions = match
.map(childPkg => {
const _flowVersion = childPkg.config.getFlowVersion();
return {
parentPkg: pkg,
pkg: childPkg,
isDisjoint: flowVersion.disjointVersions(
_flowVersion,
currentFlowVersion
)
};
})
.filter(data => {
const isValid = semver.satisfies(data.pkg.getVersion(), depVersion);
if (!isValid && !data.isDisjoint)
errorMessages.push(
messages.packageMustDependOnCurrentVersion(
name,
version,
depName,
data.pkg.getVersion(),
depVersion,
flowVersion.toSemverString(currentFlowVersion)
)
);
return isValid;
})
.filter(data => {
if (data.isDisjoint)
errorMessages.push(
messages.packageMustDependOnCurrentVersion(
name,
version,
depName,
flowVersion.toSemverString(currentFlowVersion),
flowVersion.toDirString(data.pkg.getFlowVersion()),
flowVersion.toSemverString(currentFlowVersion)
)
);
return !data.isDisjoint;
});

let link = flowVersions[0];
if (link) {
if (paths.has(link.parentPkg)) {
paths.get(link.parentPkg).set(link.pkg.getName(), link.pkg);
} else {
paths.set(
link.parentPkg,
new Map([[link.pkg.getName(), link.pkg]])
);
}
} else {
valid = false;
logger.error(
messages.packageMustDependOnCurrentVersion(
name,
depName,
expected,
depVersion
)
);
// TODO: improve errors
errorMessages.forEach(msg => logger.error(msg));
continue;
}

// Workspace dependencies only need to semver satisfy, not '==='
// if (!semver.satisfies(expected, depVersion)) {
// valid = false;
// logger.error(
// messages.packageMustDependOnCurrentVersion(
// name,
// depName,
// expected,
// depVersion
// )
// );
// continue;
// }

dependencies.push(depName);
}

graph.set(name, { pkg, dependencies });
graph.set(primaryKey, { pkg, dependencies });
}

return { graph, valid };
return { graph, paths, packagesByName, valid };
}

async getDependentsGraph(packages: Array<Package>) {
Expand Down Expand Up @@ -236,15 +304,15 @@ export default class Project {

let graph = new Map();

for (let [pkgName, pkgInfo] of dependentsGraph) {
graph.set(pkgName, pkgInfo.dependencies);
for (let [pkgPrimaryKey, pkgInfo] of dependentsGraph) {
graph.set(pkgPrimaryKey, pkgInfo.dependencies);
}

let { safe, values } = await taskGraphRunner({
graph,
force: true,
task: async pkgName => {
let pkg = this.getPackageByName(packages, pkgName);
task: async pkgPrimaryKey => {
let pkg = this.getPackageByPrimaryKey(packages, pkgPrimaryKey);
if (pkg) {
return task(pkg);
}
Expand All @@ -261,6 +329,10 @@ export default class Project {
return packages.find(pkg => pkg.getName() === pkgName);
}

getPackageByPrimaryKey(packages: Array<Package>, pkgPrimaryKey: string) {
return packages.find(pkg => pkg.getPrimaryKey() === pkgPrimaryKey);
}

filterPackages(packages: Array<Package>, opts: FilterOpts) {
let relativeDir = (pkg: Package) => path.relative(this.pkg.dir, pkg.dir);

Expand Down
23 changes: 20 additions & 3 deletions src/commands/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import * as path from 'path';
import * as logger from '../utils/logger';
import * as messages from '../utils/messages';
import validateProject from '../utils/validateProject';
import addDependenciesToPackage from '../utils/addDependenciesToPackages';
import symlinkPackageDependencies from '../utils/symlinkPackageDependencies';
import symlinkPackagesBinaries from '../utils/symlinkPackagesBinariesToProject';
import * as yarn from '../utils/yarn';
import * as flowVersion from '../utils/flowVersion';
import pathIsInside from 'path-is-inside';
import { BoltError } from '../utils/errors';
import { BOLT_VERSION } from '../constants';
Expand Down Expand Up @@ -53,10 +55,25 @@ export async function install(opts: InstallOptions) {
prefix: false
});

let packagesGraph = await project.getDependencyGraph(packages);
for (let pkg of packages) {
let dependencies = Array.from(pkg.getAllDependencies().keys());
logger.info(`Linking ${pkg.config.json.name}`, {});
await symlinkPackageDependencies(project, pkg, dependencies, packages);
let dependencies = Array.from(pkg.getAllDependencies().entries());
logger.info(
messages.linkingPackage(
pkg.config.json.name,
pkg.getVersion(),
flowVersion.toSemverString(pkg.getFlowVersion())
),
{}
);
// TODO: reconsider this
await addDependenciesToPackage(
project,
pkg,
dependencies.map(([key, value]) => ({ name: key, version: value })),
packages,
packagesGraph
);
}

logger.info(messages.linkingWorkspaceBinaries(), {
Expand Down
12 changes: 7 additions & 5 deletions src/commands/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export function toPublishOptions(
): PublishOptions {
return {
cwd: options.string(flags.cwd, 'cwd'),
access: options.string(flags.access, 'access')
access: options.string(flags.access, 'access'),
registry: options.string(flags.registry, 'registry'),
filterOpts: options.toFilterOpts(flags)
};
}

Expand All @@ -41,14 +43,14 @@ export async function publish(opts: PublishOptions) {
}

for (const pkg of unsuccessful) {
logger.error(messages.failedToPublishPackage(pkg.name));
logger.error(messages.failedToPublishPackage(pkg.name, pkg.newVersion));
}

if (unsuccessful.length > 0) {
throw new BoltError(
`Failed to publish ${unsuccessful.length} ${unsuccessful.length === 1
? 'package'
: 'packages'}`
`Failed to publish ${unsuccessful.length} ${
unsuccessful.length === 1 ? 'package' : 'packages'
}`
);
}
}
Loading