Skip to content

Commit

Permalink
fix: Refactor getPackageInfo and report saffron version correctly.
Browse files Browse the repository at this point in the history
  • Loading branch information
darkobits committed Aug 11, 2022
1 parent 65e8ce4 commit 31643f4
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 45 deletions.
23 changes: 14 additions & 9 deletions src/etc/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,21 @@ export type SaffronInitCallback = (y: typeof yargs) => void | SaffronCustomParse
*/
export interface SaffronBuilderHandlerCommonOptions {
/**
* Normalized package.json.
*
* See: https://github.com/npm/normalize-package-data
*/
packageJson: NormalizedReadResult['packageJson'] | undefined;

/**
* Path to the package root.
* Parsed metadata about Saffron's host package.
*/
packageRoot: string | undefined;
pkg: {
/**
* Normalized package.json.
*
* See: https://github.com/npm/normalize-package-data
*/
json: NormalizedReadResult['packageJson'] | undefined;

/**
* Path to the package root.
*/
root: string | undefined;
};
}


Expand Down
24 changes: 14 additions & 10 deletions src/lib/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from 'etc/types';
import loadConfiguration from 'lib/configuration';
import ow from 'lib/ow';
import getPackageInfo from 'lib/package';
import { getPackageInfo } from 'lib/package';
import yargs from 'lib/yargs';

import type { Argv, ArgumentsCamelCase } from 'yargs';
Expand Down Expand Up @@ -37,7 +37,7 @@ export default function buildCommand<A extends GenericObject = any, C extends Ge

// ----- Get Package Info ----------------------------------------------------

const { pkgJson, pkgRoot } = getPackageInfo();
const hostPkg = getPackageInfo('host');


// ----- Builder Proxy -------------------------------------------------------
Expand All @@ -58,8 +58,8 @@ export default function buildCommand<A extends GenericObject = any, C extends Ge
command.alias('v', 'version');
command.alias('h', 'help');

if (pkgJson?.version) {
command.version(pkgJson.version);
if (hostPkg.json?.version) {
command.version(hostPkg.json.version);
}

command.help();
Expand All @@ -69,8 +69,10 @@ export default function buildCommand<A extends GenericObject = any, C extends Ge
if (options.builder) {
options.builder({
command,
packageJson: pkgJson,
packageRoot: pkgRoot
pkg: {
json: hostPkg.json,
root: hostPkg.root
}
});
}

Expand All @@ -92,8 +94,10 @@ export default function buildCommand<A extends GenericObject = any, C extends Ge
// Convert raw `argv` to camelCase.
handlerOpts.argv = camelcaseKeys<any, any>(argv, {deep: true});

handlerOpts.packageJson = pkgJson;
handlerOpts.packageRoot = pkgRoot;
handlerOpts.pkg = {
json: hostPkg.json,
root: hostPkg.root
};

// Whether we should automatically call command.config() with the data
// from the configuration file.
Expand All @@ -108,7 +112,7 @@ export default function buildCommand<A extends GenericObject = any, C extends Ge
const configResult = await loadConfiguration<C>({
// By default, use the un-scoped portion of the package's name as the
// configuration file name.
fileName: pkgJson?.name ? pkgJson.name.split('/').slice(-1)[0] : undefined,
fileName: hostPkg.json?.name ? hostPkg.json.name.split('/').slice(-1)[0] : undefined,
// N.B. If the user provided a custom fileName, it will overwrite the
// one from package.json above.
...options.config
Expand Down Expand Up @@ -155,7 +159,7 @@ export default function buildCommand<A extends GenericObject = any, C extends Ge

yargs.command<A>({
command: options.command ?? '*',
describe: options?.description ?? pkgJson?.description ?? undefined,
describe: options?.description ?? hostPkg.json?.description ?? undefined,
aliases: options.aliases,
builder,
handler
Expand Down
8 changes: 4 additions & 4 deletions src/lib/init.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import getPackageInfo from 'lib/package';
import { getPackageInfo } from 'lib/package';
import yargs from 'lib/yargs';

import type { SaffronInitCallback } from 'etc/types';
Expand All @@ -8,16 +8,16 @@ import type { SaffronInitCallback } from 'etc/types';
* Yargs parser.
*/
export default function init(cb?: SaffronInitCallback) {
const { pkgJson } = getPackageInfo();
const localPkg = getPackageInfo('local');

// For applications with no sub-commands, this ensures we show help properly
// when the user calls --help from the root command. This is necessary even
// when a default command with these same options has been configured.
yargs.showHelpOnFail(true, 'See --help for usage instructions.');
yargs.wrap(yargs.terminalWidth());

if (pkgJson?.version) {
yargs.version(pkgJson.version);
if (localPkg.json?.version) {
yargs.version(localPkg.json.version);
}

yargs.help();
Expand Down
50 changes: 28 additions & 22 deletions src/lib/package.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
import fs from 'fs';
import path from 'path';

import { dirname } from '@darkobits/fd-name';
import { readPackageUpSync, NormalizedPackageJson } from 'read-pkg-up';


/**
* Object returned by getPackageInfo.
* Object returned by `getPackageInfo`.
*/
export interface PackageData {
pkgJson: NormalizedPackageJson | undefined;
pkgRoot: string | undefined;
export interface PackageInfo {
json: NormalizedPackageJson | undefined;
root: string | undefined;
}


/**
* Module-local cached result from read-pkg-up.
* @private
*
* Module-local cache of package info lookups.
*/
const cachedPackageResult: PackageData = {
pkgJson: undefined,
pkgRoot: undefined
};
const packageCache = new Map<'host' | 'local', PackageInfo>();


/**
* Loads the package.json of the host application, if one exists, and caches the
* result.
* Loads the package.json of the host or local package and returns the
* normalized result and the package's root directory. Results are cached.
*/
export default function getPackageInfo(): PackageData {
if (Object.keys(cachedPackageResult).length === 0) {
const execPath = path.dirname(fs.realpathSync(process.argv[1]));

const packageResult = readPackageUpSync({ cwd: execPath });

if (packageResult) {
cachedPackageResult.pkgJson = packageResult.packageJson;
cachedPackageResult.pkgRoot = path.dirname(packageResult.path);
}
export function getPackageInfo(type: 'host' | 'local'): PackageInfo {
// Cache miss; populate cache.
if (!packageCache.has(type)) {
const cwd = type === 'host'
? path.dirname(fs.realpathSync(process.argv[1]))
: dirname();
if (!cwd) throw new Error(`[getOurPackageInfo] Unable to compute cwd for the ${type} package.`);

const packageResult = readPackageUpSync({ cwd });
if (!packageResult) throw new Error(`[getPackageInfo] Unable to get metadata for the ${type} package.`);

packageCache.set(type, {
json: packageResult.packageJson,
root: path.dirname(packageResult.path)
});
}

return cachedPackageResult;
// Return from cache.
return packageCache.get(type) as PackageInfo;
}

0 comments on commit 31643f4

Please sign in to comment.