0.7.0 • Published 12 months ago

@typhonjs-utils/package-json v0.7.0

Weekly downloads
-
License
MPL-2.0
Repository
github
Last release
12 months ago

@typhonjs-utils/package-json

NPM Code Style License Discord Twitch

Provides an ES Module with several utility functions for working with and retrieving package.json along with a TyphonJS plugin for Node.js v12.0+. All of these functions are synchronous and there is no caching of results between queries made.

API documentation

Why:

When developing in an ES Module environment on Node these functions make it easy to retrieve any local package.json through the use of a file path or file URL including import.meta.url. There are a few variations on specific information retrieved from the loaded package.json such as the module type which is accomplished with getPackageType. There is additional flexibility in finding a specific package.json through the use of an optional callback function that is invoked during traversal of the file system as each package.json is loaded.

Installation:

npm install @typhonjs-utils/package-json or include @typhonjs-utils/package-json in dependencies.

Highlights:

There are five functions available as named exports:

Function NameDescription
formatPackageAccepts a loaded package object and normalizes the data.
getPackageRetrieves the package object specified by the query.
getPackageAndFormatRetrieves the package object then returns the formatted result.
getPackageTypeRetrieves the package object then returns the type property; either module or commonjs.
getPackageWithPathRetrieves the package object and returns it with the file path.

Package query object:

While formatPackage accepts a loaded package.json object all other functions require a query object containing the following data:

PropertyTypeDescription
filepathstring / URLInitial file or directory path to traverse for package.json.
basepathstring / URLOptional: Base path to stop traversing. Set to the root path of filepath if not provided.
callbackFunctionOptional: A function that evaluates a loaded package.json object and associated traversal data returning a truthy value to stop or continue the traversal.

filepath is required and may be a file or directory path as a string or file URL including import.meta.url. It should be noted that if the path references a file that this file does not need to exist, but the containing directory does need to exist. Likewise, the same condition applies to any optional basepath supplied.

A caveat with this handling of filepath is that if a non-existent path is given such as 'a bad path' this will resolve to '.' or the current working directory. In practice this is not an issue, but something to keep in mind.

basepath should be a parent path of filepath for it to have any effect on stopping traversal early.

Package resolution:

By default Node.js will load the nearest package.json in a given file structure. This is important to realize when dealing with the type property as intermediary package.json files above the module root path will be loaded to determine the type of source for *.js files at that directory path and lower. If the intermediary package.json does not contain a type property then commonjs is assumed by default. To match this behavior getPackageType stops traversal at the first package.json found from a given query.

getPackageWithPath / PackageObjData:

All functions besides formatPackage rely on getPackageWithPath. getPackageWithPath will not throw on any errors encountered and will always return a PackageObjData object. If an error occurs the error property will contain the error thrown and packageObj will be undefined and filepath / filepathUnix may be defined if the error occurred loading a specific package.json; IE when malformed. If traversal completes without locating package.json then error will contain a message indicating this failure. On success packageObj, filepath, and filepathUnix are defined and error is undefined.

PropertyTypeDescription
packageObjobject / undefinedLoaded package.json object.
filepathstring / undefinedFile path of loaded package.json object.
filepathUnixstring / undefinedFile path of loaded package.json object as Unix styled path.
errorError / undefinedA potential error instance.

getPackageType:

getPackageType always returns either module or commonjs depending on the type property of the located package.json; module is only returned if "type": "module" is set. By default, traversal stops at the first encountered package.json. Any error condition / malformed package.json or failure to locate package.json will return commonjs.

Traversal callback function / data object:

If a callback function is included in the query object it will be invoked with a TraversalData object with all paths converted to Unix styled paths as the only function parameter. On Windows any \ and \\ path separators are converted to /. The data available in the traversal callback object:

PropertyTypeDescription
baseDirstringStores the basepath directory as a Unix styled path.
cntrnumberStores the number of times a package.json has been processed.
currentDirstringCurrent directory of traversal as a Unix styled path.
packageObjobjectCurrent loaded package.json object.
filepathstringCurrent loaded package.json file path as a Unix styled path.
relativeDirstringCurrent directory of traversal as a relative Unix styled path from process.cwd.
rootPathstringThe root path to stop traversal as a Unix styled path.

Examples:

import { formatPackage } from '@typhonjs-utils/package-json';

const result = formatPackage(packageObj);

// Prints a consistent formatted message with the package info.
console.log(result.formattedMessage);
import { getPackageWithPath } from '@typhonjs-utils/package-json';

// Loads first encountered `package.json` from traversal from current source directory.
const { packageObj, filepath } = getPackageWithPath({ filepath: import.meta.url }); 
import { getPackage } from '@typhonjs-utils/package-json';

// Loads first encountered `package.json` from traversal from current source directory.
const packageObj = getPackage({ filepath: import.meta.url }); 
import { getPackageType } from '@typhonjs-utils/package-json';

// Type is 'module' or 'commonjs' based on first encountered package.json from traversal from current source directory. 
const type = getPackageType({ filepath: import.meta.url }); 
import { getPackage } from '@typhonjs-utils/package-json';

// Loads a specific `package.json` with name property matching 'target-package' from traversal from current source directory.
const packageObj = getPackage({ 
   filepath: import.meta.url, 
   callback: (data) => data.packageObj.name === 'target-package' 
});

formatPackage / getPackageAndFormat / PackageObjFormatted:

formatPackage is useful to normalize essential data found in a loaded package.json object. getPackageAndFormat will first attempt to load a package.json object then return the formatted result. The resulting object is guaranteed to have these properties defined and empty strings for any properties not defined in the given package.json object. If formatPackage does not receive an object then undefined is returned.

PropertyTypeDescription
namestringName property.
versionstringVersion property.
typestringmodule or commonjs regardless if target package object defines it.
descriptionstringDescription property.
homepagestringHomepage property.
licensestringLicense property.
repositorystringThe URL or unparsed repository string.
bugsURLstringURL from bugs property.
bugsEmailstringEmail from bugs property.
formattedMessagestringA consistently formatted message describing the package.

In various TyphonJS modules getPackageAndFormat is used in combination with @typhonjs-utils/error-parser primarily to print / log a consistent message in error reporting about any offending module.


TyphonJS plugin:

For Node v12.17+ there is a specific export for the TyphonJS plugin via the exports property: @typhonjs-utils/package-json/plugin.

This plugin works with @typhonjs-plugin/manager and simply registers the functions above on the plugin manager eventbus under the following event names:

Event NameFunction Invoked
typhonjs:utils:package:json:formatformatPackage
typhonjs:utils:package:json:format:getgetPackageAndFormat
typhonjs:utils:package:json:getgetPackage
typhonjs:utils:package:json:path:getgetPackageWithPath
typhonjs:utils:package:json:type:getgetPackageType

An abbreviated pseudocode example of loading and using the plugin follows:

import { PluginManager } from '@typhonjs-plugin/manager';

const pluginManager = new PluginManager();
const eventbus = pluginManager.getEventbus();

await pluginManager.add({ name: '@typhonjs-utils/package-json/plugin' });

const packageObj = eventbus.triggerSync('typhonjs:utils:package:json:get', { filepath: import.meta.url });

Please refer to the @typhonjs-plugin/manager documentation for more details.