# @typhonjs-utils/package-json

> Provides several utility functions for working with and retrieving `package.json`.

Latest version **0.7.0** (published 2024-01-07) · MPL-2.0 license · 0 weekly downloads

## Install

```sh
npm install @typhonjs-utils/package-json
pnpm add @typhonjs-utils/package-json
yarn add @typhonjs-utils/package-json
bun add @typhonjs-utils/package-json
```

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.7.0 |
| Published | 2024-01-07 |
| First published | 2021-04-26 |
| Weekly downloads | 0 |
| License | MPL-2.0 |
| TypeScript types | none |
| Module format | ESM |
| Node | >=12 |
| Dependencies | 0 |
| Unpacked size | 55.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Michael Leahy |
| Maintainers | typhonrt |
| Keywords | typhonjs, utils, package.json |

## Links

- npm: https://www.npmjs.com/package/@typhonjs-utils/package-json
- Repository: https://github.com/typhonjs-node-utils/package-json
- Homepage: https://github.com/typhonjs-node-utils/package-json#readme
- Issues: https://github.com/typhonjs-node-utils/package-json/issues
- npm.io page: https://npm.io/package/@typhonjs-utils/package-json

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 0.7.0 (latest) — 2024-01-07
- 0.6.0 — 2021-06-04
- 0.5.0 — 2021-05-09
- 0.4.0 — 2021-05-06
- 0.3.0 — 2021-05-05
- 0.2.0 — 2021-05-05
- 0.1.0 — 2021-05-05
- 0.0.10 — 2021-04-26

## README

![@typhonjs-utils/package-json](https://i.imgur.com/C8LtPVY.png)

[![NPM](https://img.shields.io/npm/v/@typhonjs-utils/package-json.svg?label=npm)](https://www.npmjs.com/package/@typhonjs-utils/package-json)
[![Code Style](https://img.shields.io/badge/code%20style-allman-yellowgreen.svg?style=flat)](https://en.wikipedia.org/wiki/Indent_style#Allman_style)
[![License](https://img.shields.io/badge/license-MPLv2-yellowgreen.svg?style=flat)](https://github.com/typhonjs-node-utils/package-json/blob/main/LICENSE)
[![Discord](https://img.shields.io/discord/737953117999726592?label=TyphonJS%20Discord)](https://typhonjs.io/discord/)
[![Twitch](https://img.shields.io/twitch/status/typhonrt?style=social)](https://www.twitch.tv/typhonrt)

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](https://typhonjs-node-utils.github.io/package-json/)

### 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 Name       | Description                                                                                   |
| ------------------- | --------------------------------------------------------------------------------------------- |
| formatPackage       | Accepts a loaded package object and normalizes the data.                                      | 
| getPackage          | Retrieves the package object specified by the query.                                          |
| getPackageAndFormat | Retrieves the package object then returns the formatted result.                               |
| getPackageType      | Retrieves the package object then returns the `type` property; either `module` or `commonjs`. |
| getPackageWithPath  | Retrieves 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:

| Property   | Type         | Description                                                                                                                                                 |
| ---------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| filepath   | string / URL | Initial file or directory path to traverse for `package.json`.                                                                                              | 
| [basepath] | string / URL | Optional: Base path to stop traversing. Set to the root path of `filepath` if not provided.                                                                 |
| [callback] | Function     | Optional: 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.

| Property       | Type               | Description                                                    |
| -------------- | ------------------ | -------------------------------------------------------------- |
| [packageObj]   | object / undefined | Loaded `package.json` object.                                  | 
| [filepath]     | string / undefined | File path of loaded `package.json` object.                     |
| [filepathUnix] | string / undefined | File path of loaded `package.json` object as Unix styled path. |
| [error]        | Error / undefined  | A 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:

| Property    | Type   | Description                                                                       |
| ----------- | ------ | --------------------------------------------------------------------------------- |
| baseDir     | string | Stores the `basepath` directory as a Unix styled path.                            | 
| cntr        | number | Stores the number of times a `package.json` has been processed.                   |
| currentDir  | string | Current directory of traversal as a Unix styled path.                             |
| packageObj  | object | Current loaded `package.json` object.                                             |
| filepath    | string | Current loaded `package.json` file path as a Unix styled path.                    |
| relativeDir | string | Current directory of traversal as a relative Unix styled path from `process.cwd`. |
| rootPath    | string | The root path to stop traversal as a Unix styled path.                            |

### Examples:
```js
import { formatPackage } from '@typhonjs-utils/package-json';

const result = formatPackage(packageObj);

// Prints a consistent formatted message with the package info.
console.log(result.formattedMessage);
```

```js
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 }); 
```

```js
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 }); 
```

```js
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 }); 
```

```js
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. 

| Property         | Type   | Description                                                                                                                 |
| ---------------- | ------ | ------------------------------------------------------------------------- |
| name             | string | Name property.                                                            | 
| version          | string | Version property.                                                         |
| type             | string | `module` or `commonjs` regardless if target package object defines it.    |
| description      | string | Description property.                                                     |
| homepage         | string | Homepage property.                                                        |
| license          | string | License property.                                                         |
| repository       | string | The URL or unparsed repository string.                                    |
| bugsURL          | string | URL from bugs property.                                                   |
| bugsEmail        | string | Email from bugs property.                                                 |
| formattedMessage | string | A consistently formatted message describing the package.                  |

In various TyphonJS modules `getPackageAndFormat` is used in combination with
[@typhonjs-utils/error-parser](https://www.npmjs.com/package/@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](https://www.npmjs.com/package/@typhonjs-plugin/manager) and simply 
registers the functions above on the plugin manager eventbus under the following event names:

| Event Name                               | Function Invoked    |
| ---------------------------------------- | ------------------- |
| `typhonjs:utils:package:json:format`     | formatPackage       | 
| `typhonjs:utils:package:json:format:get` | getPackageAndFormat |
| `typhonjs:utils:package:json:get`        | getPackage          |
| `typhonjs:utils:package:json:path:get`   | getPackageWithPath  |
| `typhonjs:utils:package:json:type:get`   | getPackageType      |

An abbreviated pseudocode example of loading and using the plugin follows:
```js
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.

---
_Source: https://npm.io/package/@typhonjs-utils/package-json · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
