voluptasmollitia
Version:
Monorepo for the Firebase JavaScript SDK
154 lines (134 loc) • 4.52 kB
text/typescript
/**
* @license
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import glob from 'glob';
import { projectRoot as root } from '../../utils';
import { DepGraph } from 'dependency-graph';
import { promisify } from 'util';
import { writeFile as _writeFile, existsSync, readFileSync } from 'fs';
import clone from 'clone';
const writeFile = promisify(_writeFile);
const {
workspaces: rawWorkspaces
}: { workspaces: string[] } = require(`${root}/package.json`);
const workspaces = rawWorkspaces.map(workspace => `${root}/${workspace}`);
export function mapWorkspaceToPackages(
workspaces: string[]
): Promise<string[]> {
return Promise.all<string[]>(
workspaces.map(
workspace =>
new Promise(resolve => {
glob(workspace, (err, paths) => {
if (err) throw err;
resolve(paths);
});
})
)
).then(paths => paths.reduce((arr, val) => arr.concat(val), []));
}
function mapPackagestoPkgJson(packagePaths: string[]) {
return packagePaths
.map(path => {
try {
return JSON.parse(readFileSync(`${path}/package.json`, 'utf8'));
} catch (err) {
return null;
}
})
.filter(Boolean);
}
function mapPackagesToDepGraph(packagePaths: string[]) {
const graph = new DepGraph();
const packages = mapPackagestoPkgJson(packagePaths);
packages.forEach(pkg => graph.addNode(pkg.name));
packages.forEach(({ name, dependencies, devDependencies }) => {
const allDeps = Object.assign({}, dependencies, devDependencies);
Object.keys(allDeps)
.filter(dep => graph.hasNode(dep))
.forEach(dep => graph.addDependency(name, dep));
});
return graph;
}
export async function mapPkgNameToPkgPath(pkgName: string) {
const packages = await mapWorkspaceToPackages(workspaces);
return packages
.filter(path => {
try {
const json = require(`${path}/package.json`);
return json.name === pkgName;
} catch (err) {
return null;
}
})
.reduce(val => val);
}
export async function getAllPackages() {
const packages = await mapWorkspaceToPackages(workspaces);
const dependencies = mapPackagesToDepGraph(packages);
return dependencies.overallOrder();
}
export async function mapPkgNameToPkgJson(packageName: string) {
const packages = await mapWorkspaceToPackages(workspaces);
return mapPackagestoPkgJson(packages)
.filter(pkg => pkg.name === packageName)
.reduce(val => val);
}
export async function updateWorkspaceVersions(
newVersionObj: { [pkgName: string]: string },
includePeerDeps: boolean
) {
try {
let packages = await mapWorkspaceToPackages(workspaces);
packages = packages.filter(pkg => existsSync(`${pkg}/package.json`));
const pkgJsons = mapPackagestoPkgJson(packages);
pkgJsons.forEach((rawPkg, idx) => {
let pkg = clone(rawPkg);
const pkgJsonPath = `${packages[idx]}/package.json`;
Object.keys(newVersionObj).forEach(updatedPkg => {
/**
* If the current package has been updated, bump the version property
*/
if (pkg.name === updatedPkg) {
pkg = Object.assign({}, pkg, {
version: newVersionObj[updatedPkg]
});
}
/**
* If the packages dependencies, or devDependencies have
* been updated, update that version here
*/
let depKeys = ['dependencies', 'devDependencies'];
if (includePeerDeps) {
depKeys = [...depKeys, 'peerDependencies'];
}
depKeys.forEach(dep => {
const deps = pkg[dep];
if (deps && deps[updatedPkg]) {
pkg = Object.assign({}, pkg, {
[dep]: Object.assign({}, pkg[dep], {
[updatedPkg]: newVersionObj[updatedPkg]
})
});
}
});
});
writeFile(pkgJsonPath, `${JSON.stringify(pkg, null, 2)}\n`);
});
} catch (err) {
console.log(err);
}
}