npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@arkham-engineering/bom

v0.1.0

Published

Bill of Materials (BOM) library.

Downloads

25

Readme

BOM.js

An Node.js module that allows a user to programmatically create a bill of materials (BOM) using only part numbers and the desired quantity. The final bill of materials is built against an outside dataset (database) to generate a detailed list of information.

Overview

The BOM.js module provides a simple mechanism to represent and export a single-level bill of materials (BOM). In the engineering and manufacturing communities, a bill of materials will primarily contain a list of parts that are to be manufactured or purchased to produce a product. It can also be seen as a "formula, recipe, or ingredients list" needed for production. A part, in simple terms, represents a physical item that has a "part number" as means of identification/tracking. Parts also have properties associated with them. Some of these properties include:

  • Title / Description
  • Unit of Measure (UOM)
  • Weight (or Unit Weight)
  • Cost (or Unit Cost)
  • etc.

The information associated with each part is often stored in a database such as those found in a ERP system. These databases will serve as the master source of information. BOM.js is designed to create dynamic bill of materials which can be tied to these master data sources.

Installation

The module is not published to package managers such as npm. The module must be added to a project manually by cloning it from GitHub or by manually adding it as a dependency in a project's package.json. The following illustrates how it can be manually added as a dependency:

// package.json
{
	"dependencies": {
		"bom": "git+https://github.com/arkham-engineering/bom.git"
	}
}

The module then can be referenced using the following syntax:

// CommonJS
const BOM = require("bom")

// ES6 Module Import
import * as BOM from "bom"

Usage

A new bill of materials is created by initializing a new instance of the BOM class. In the example below we will create a new "parts list" as illustrated by the variable list.

Note that parts list is another term used for a bill of materials and that the two terms are often used interchangeably.

let list = new BOM(queryFx, options)

As one can see, the constructor has two arguments. The first argument is a "query function" while the second argument is an optional options object. Refer to the API for information.

Query Function

The query function is a user defined function, that when provided a part number, returns a Promise, that when resolved, is an object containing all the properties associated with the given part. The intent is that this function would query a database (or search some other dataset) that contains all of the relevant properties associated with a part number. The following is an example of a simple query function:

// Part data stored on disc as JSON.
let data = require("./data.json")

// Query function.
function queryFx(pn) {
	return Promise.resolve(data.pn)
}

In this example, the detailed information about all of the parts is stored inside a JSON file. The query function provides the properties inside this dataset based on the given part number. It is recommended that the object returned contain commonly used properties (keys) used in a bill of materials (see Data).

Data

It is recommended that the object return from the query function return the following properties at a minimum:

| Name | Type | Description | | ----------- | ------------------- | ------------------------------------- | | pn | String | Part Number (Unique ID) | | title | String | Part title. | | desc | String | Part description. | | unit | String | Unit (ex: each, in, feet, lbs, etc.). | | unit_cost | Number | Unit cost. | | unit_weight | Number | Unit weight. |

Refer to the API for information.

Methods & Properties

Each BOM instance contains methods to add, remove, and modify items in the bill of materials. In general, most of these methods will require a part number (denoted as pn) and a quantity (denoted as qty). The following sub-sections detail the usage of each method or property within the BOM class.

Add Item .add()

Adds an item to the parts list provided a part number {String} and a quantity {Number}.

// Adds one instance of the part to the list.
list.add(pn)

// Adds specified number of parts to the list.
list.add(pn, qty)

Remove Item .remove()

Removes an item or specific quantity of the item from the parts list depending on the parameters provided.

// Remove an item completely from the list.
list.remove(pn)

// Remove a certain quantity.
list.remove(pn, qty)

Modify Item .set()

Modifies (or in this case sets) the quantity of the part in the parts list. If the quantity is set to zero or a negative number then the part will be removed.

// Set the quantity of an item to a specific value.
list.set(pn, qty)

Length .length

Returns the number (distinct count) of items in the bill of materials.

list.length // Returns {Number}

Items .items

The current list of items in the bill of materials can be accessed using the items property. This will return an array of objects with keys pn and qty representing part number and quantity, respectively.

// Returns the collection of items with basic information.
console.log(list.items);

// Example Result:
[
    {pn: "foo": qty: 10},
    {pn: "bar": qty: 20},
    {pn: "baz": qty: 5}
]

Details .getDetails()

Returns a promise resolving to a detailed bill of materials. This object array will include information provided by the Query Function.

// Returns the collection of items with detailed information.
list
	.getDetails()
	.then((details) => {
		console.log(details)
	})
	.catch((error) => {
		// Handle error spawned from query function.
	})

// Example Result:
/*
[
	{
		pn: "001",
		qty: 10,
		desc: "...",
		unit: "each",
		unit_cost: 20,
		total_cost: 200,
	},
	{
		pn: "002",
		qty: 1,
		desc: "...",
		unit: "each",
		unit_cost: 40,
		total_cost: 40,
	},
	{
		pn: "003",
		qty: 12,
		desc: "...",
		unit: "inch",
		unit_cost: 0.5,
		total_cost: 6,
	}
]
*/

Cost Roll .costRoll()

Returns a promise resolving to the total material cost of the bill of materials. This function depends requires that a unit_cost property is available in each BOM item. This function will throw a type error if one or more items do not have a unit_cost defined.

list.costRoll() // Returns {Promise<Number>}

Export .export()

Exports the bill of materials to a Microsoft Excel file. The destination path should include the ".xlsx" extension. The metadata provided during construction will be used to format the Excel document.

// Exports the
list.export(destinationFilePath) // Returns {Promise}

Build from Template .buildFromTemplate()

A BOM instance can also be populated from a JSON template. This template can be scoped against another data set, thus allowing a user to incorporate logic into the compellation of a bill of materials.

For example, lets assume a bill of materials needs to be constructed against a users input. In this example the user can specify the color of a product to be either red or yellow as well as specify a desired quantity. We can represent this using the following JSON template:

[
	{
		"pn": "110-RED",
		"qty": "count",
		"include": "color === 'red'"
	},
	{
		"pn": "110-YEL",
		"qty": "count",
		"include": "color === 'yellow'"
	}
]

In this template the correct part is chosen based on the selected color. The users input is contained inside a object that at a minimum contains two keys: color and count. The color property will contain the color selection while the count property will indicate the desired quantity. This functionality is achieved using angular-expressions.

The bill of materials would then be constructed doing the following:

let data = { color: "red", count: 3 }
let templatePath = "path/to/json/template.json"
let queryFx = function(pn) {...} // Query function.

let bom = new BOM(queryFx)
bom.buildFromTemplate("templatePath", data)

In this case the bill of materials will have one item: three red "widgets".

Note that for security reasons the object scoped to the BOM template can only evaluate its own properties; properties inside the objects prototype chain are not accessible. This can be overcome using Lodash.toPlainObject() or by doing some other method of data flattening and serialization.

API

More information can be found by reading the API documentation.

License

MIT