pcf-scripts
Version:
This package contains a module for building PowerApps Component Framework (PCF) controls. See project homepage how to install.
113 lines (111 loc) • 6.16 kB
JavaScript
// Copyright (C) Microsoft Corporation. All rights reserved.
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPackageVersion = getPackageVersion;
const fs = require("node:fs");
const path = require("node:path");
// Node constants
const constants = {
PACKAGE_LOCK_JSON_PATH: "package-lock.json",
PACKAGE_JSON_PATH: "package.json",
NODE_MODULES: "node_modules",
};
function getPackageVersion(packageName, controlRoot, logger) {
logger?.log(`[getPackageVersion] controlRoot: ${controlRoot}`);
logger?.log(`[getPackageVersion] __dirname: ${__dirname}`);
logger?.log(`[getPackageVersion] __filename: ${__filename}`);
let version;
// Only available when running under Yarn2's PNP https://yarnpkg.com/advanced/pnpapi
if (process.versions.pnp) {
logger?.log(`[getPackageVersion] Using pnpapi`);
version = tryGetPackageVersionFromPnpApi(controlRoot, packageName);
if (version)
return version;
}
// find version from package-lock.json first
const pathToPackageLockJson = path.resolve(controlRoot, constants.PACKAGE_LOCK_JSON_PATH);
logger?.log(`[getPackageVersion] Try extract from package lock file. filePath: ${pathToPackageLockJson}`);
version = tryReadPackageVersionFromPackageLockFile(pathToPackageLockJson, packageName, logger);
if (version)
return version;
// fallback to find version in that package's package.json in node_modules
let pathToPackageJson = path.resolve(controlRoot, constants.NODE_MODULES, packageName, constants.PACKAGE_JSON_PATH);
logger?.log(`[getPackageVersion] Try extract from node_modules folder. filePath: ${pathToPackageJson}`);
version = tryReadPackageVersionFromPackageFile(pathToPackageJson);
if (version)
return version;
// add another fallback to search from the directory of the script itself. This can happen if the user has a customized folder structure
// in which package-lock.json and node_modules don't live at the root of the control project.
// go out one level to be at the root dir of node_modules folder
// WARNING: This relative path is relative to THIS module's script folder.
pathToPackageJson = path.resolve(__dirname, "..", "..", packageName, constants.PACKAGE_JSON_PATH);
logger?.log(`[getPackageVersion] Trying fallback package file relative to script. filePath: ${pathToPackageJson}`);
version = tryReadPackageVersionFromPackageFile(pathToPackageJson);
if (version)
return version;
// Fallback to trying require.resolve just in case this is a mono-repo
try {
const resolvedPathToPackageJson = require.resolve(`${packageName}/${constants.PACKAGE_JSON_PATH}`);
logger?.log(`[getPackageVersion] Try extract from resolved path. filePath: ${resolvedPathToPackageJson}`);
version = tryReadPackageVersionFromPackageFile(resolvedPathToPackageJson);
if (version)
return version;
}
catch {
/* ignore MODULE_NOT_FOUND error */
}
return undefined;
}
/* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access */
function tryGetPackageVersionFromPnpApi(controlRoot, packageName) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const pnpApi = require("pnpapi");
const locator = pnpApi.findPackageLocator(controlRoot);
const packageInfo = pnpApi.getPackageInformation(locator);
// Get strong type from https://yarnpkg.com/advanced/pnpapi#packageinformation
const dependencies = packageInfo.packageDependencies;
const dependency = dependencies.get(packageName);
// If this comes from npm, it'll be something like npm:1.3.3
// If it comes from the virtual cache, it'll be something like virtual:3ad6....34a#npm:5.2.0
if (typeof dependency === "string") {
return dependency.split(":").pop();
}
return undefined;
}
/* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access */
function tryReadPackageVersionFromPackageFile(packageFilePath) {
if (fs.existsSync(packageFilePath)) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const parsedPackage = require(packageFilePath);
const version = parsedPackage?.version;
if (typeof version === "string") {
return version;
}
}
return undefined;
}
/* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access */
function tryReadPackageVersionFromPackageLockFile(packageLockFilePath, packageName, logger) {
if (fs.existsSync(packageLockFilePath)) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const parsedLock = require(packageLockFilePath);
const dependencies = parsedLock?.dependencies;
if (dependencies) {
const version = dependencies[packageName]?.version;
if (typeof version === "string") {
// for local development, the 'version' may actually be a path. In which case, we should pull the version from the package.json in that folder
if (version.startsWith("file:")) {
logger?.log(`[getPackageVersion] Package lock file version had reference to local path folder. version in lock file: '${version}'`);
const pathPart = decodeURI(version).substring(5);
const refPackagePath = path.resolve(path.dirname(packageLockFilePath), pathPart, constants.PACKAGE_JSON_PATH);
logger?.log(`[getPackageVersion] Package lock file version had reference to local path folder. Resolving from there. refPackagePath: ${refPackagePath}`);
return tryReadPackageVersionFromPackageFile(refPackagePath);
}
return version;
}
}
}
return undefined;
}
/* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access */
//# sourceMappingURL=PackageVersionUtils.js.map
;