@lit-labs/gen-utils
Version:
Utilities for lit code generators
101 lines • 3.83 kB
JavaScript
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
import { promisify } from 'util';
import { exec as execCb } from 'child_process';
import * as fs from 'fs/promises';
import * as path from 'path';
const exec = promisify(execCb);
/**
* Runs `npm i` in the package in the given packageRoot, optionally using
* monorepo packages in place of installing from the registry.
*
* Note that rather than using an `npm link` / symlink approach for substituting
* monorepo packages, we use `npm pack` and point package.json to the tarball
* for that package. This more closely matches how a given test package will be
* installed from the registry, and avoids issues when a monorepo has
* peerDependencies (since a monorepo package will have its own copy of its
* peerDependencies installed, which is not what will happen when installed as a
* dependency itself).
*
* @param packageRoot
* @param linkedPackages
*/
export const installPackage = async (packageRoot, monorepoPackages) => {
// Read package.json
const packageFile = path.join(packageRoot, 'package.json');
const packageText = await fs.readFile(packageFile, 'utf8');
const packageJson = JSON.parse(packageText);
if (monorepoPackages !== undefined) {
let deps;
for (const [pkg, folder] of Object.entries(monorepoPackages)) {
// Figure out what kind of dep the linked dep is
if (packageJson.dependencies?.[pkg] !== undefined) {
deps = packageJson.dependencies;
}
else if (packageJson.devDependencies?.[pkg] !== undefined) {
deps = packageJson.devDependencies;
}
else if (packageJson.peerDependencies?.[pkg] !== undefined) {
deps = packageJson.peerDependencies;
}
else {
// TODO(kschaaf) Would be nice to also validate the monorepo package
// fulfills the generated version constraint
throw new Error(`Linked package '${pkg}' was not a dependency of '${packageFile}'.`);
}
// Make sure the folder for the package to link exists
try {
await fs.access(folder);
}
catch {
throw new Error(`Folder ${folder} for linked package '${pkg}' did not exist.`);
}
// npm pack the linked package into a tarball
const tarballFile = await packPackage(folder);
// Update the package.json dep with a file path to the tarball
deps[pkg] = `file:${tarballFile}`;
}
// Write out the updated package.json
await fs.writeFile(packageFile, JSON.stringify(packageJson, null, 2), 'utf8');
}
try {
// Install
await exec('npm install', { cwd: packageRoot });
}
finally {
// Restore package.json
await fs.writeFile(packageFile, packageText, 'utf8');
}
};
/**
* Runs `npm run build` on the given package
* @param packageRoot
*/
export const buildPackage = async (packageRoot) => {
try {
await exec('npm run build', { cwd: packageRoot });
}
catch (e) {
const { stdout } = e;
throw new Error(`Failed to build package '${packageRoot}': ${stdout}`);
}
};
/**
* Runs `npm pack` on the given package
* @param packageRoot
* @returns Absolute path to the packaged tarball
*/
export const packPackage = async (packageRoot) => {
try {
const { stdout: tarballFile } = await exec('npm pack', { cwd: packageRoot });
return path.resolve(packageRoot, tarballFile.trim());
}
catch (e) {
const { stdout } = e;
throw new Error(`Failed to pack package '${packageRoot}': ${stdout}`);
}
};
//# sourceMappingURL=package-utils.js.map