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

nonstop-pack

v0.2.1

Published

Lib for working with nonstop packages

Downloads

9

Readme

nonstop-pack

This library provides all functionality around the creation and handling of artifact packages for the nonstop CI/CD system.

It is unlikely that you would consume this library directly unless you are working on a package host, build agent, CLI or service host. There are already nonstop projects for each of these use cases.

Running the tests

Before you can run the tests, you'll need to run the ./preTest.sh script that creates a git repository for testing. Failure to do that will result in a lot of failed tests.

Packages

Information

The following information describes a package:

  • project name
  • repository owner
  • branch
  • version
  • build number
  • OS platform (darwin, linux, win32)
  • OS name (optional, default is any)
  • OS version (optional, default is any)
  • OS architecture (x86, x64)

File format

Packages are tarballed and gzipped (.tar.gz), there are no other supported formats at this time.

Name format

The information is combined in order delimited by ~. While this does result in long names, it enables nonstop-index to filter available packages by any of the information listed and means never having to guess what source produced a specific package. It also avoids having to unpack a tarball or ask a central server for information about the package.

Example:

projectName~owner~branch~version~build~osFamily~os~osVersion~architecture

Versioning

nonstop's versioning strategy was designed to produce consistent results against a git repository's commit history. This also eliminates the need for a central coordinator to assign build numbers and results in a solution that will always produce the same build version given a specific commit.

Versioning is determined based on commit history and project version. Once the file containing the version is located, the version is read from this file at each commit. The build number is incremented for every commit in which the version does not change.

Because of this approach, the file which specifies the version for a project must always remain in the same location and have the same file name. Changing this will break nonstop's ability to determine versions across your repository's history.

In the event that nonstop is unable to locate the file specifying your project's version (this is probably only likely in .Net projects) - you can specify the file in the project section of the build file with the versionFile property.

In the event that no commit has ever been made to the repository, the version will fall back to '0.0.0' and build '0'.

API

add( root, packages, packageName )

For use in package hosting (as in nonstop-index)

Adds a package by name to an array of packages by parsing the details from the package name and appending the package information to the packages array. Returns the information that was added to the array.

The relative property of the package data follows the format: project-owner-branch. This will cause all packages with the same project, owner and branch to be stored in a single folder

To get details on what information is provided by the package object, see the section on parse.

// root - provides the base folder where all package subfolders will be created
// packages - an array of package information details
// packageName - the name of the package file

packages.parse( './packages', packageList, 'test~arobson~master~0.1.0~1~darwin~any~any~x64' );

copy( root, temp, packageName, packages )

For use in package hosting (as in nonstop-index)

Copy's a package from a temporary storage directory (i.e. after being uploaded) to the intended long-term path and then removes the temporary file. This also uses the add method to add the package details to the packages list. Returns a promise to indicate success of the copy and remove operations.

// root - provides the base folder where all package subfolders will be created
// temp - the full path to the temporary location of the uploaded file
// packageName - the name of the package file
// packages - an array of package information details
packages.copy(
		'./packages',
		'./tmp/891345iaghakk92thagk.tar.gz',
		'test~arobson~master~0.1.0~1~darwin~any~any~x64.tar.gz',
		packageList
	).then( function() {
		//on success
	} );

create( packageInfo )

For use in build agents/clis:

Creates a new package from a package information data structure. (see getInfo for obtaining the information required to seed this function)

The result will be a tar.gz with the correct package name stored based on data in the packageInfo hash. Returns a promise indicating the success of the package creation. On success, a packageInfo hash is returned with a files property containing an array of all files packaged.

// packageInfo - a data structure containing the information necessary to create the package
var packageInfo = package.getInfo( 'test', config, './' );
packages.create( packageInfo )
	.then( function( packageInfo ) {
		//on success
	} );

find( packages, filter )

For use in package hosting (as in nonstop-index)

Given a set of desired pacakge attributes (in hash format), return a sorted list of packages that satisfy the filter. Packages are sorted by sematic version (version-build) starting with the newest.

// packages - the array of package details
// filter - the hash of attribute values to match
var matches = packages.find( packages, { owner: 'arobson', branch: 'master' } );

getInfo( projectName, projectConfig, repositoryPath )

For use in build agents/clis:

Determines key information about the package by examining the git repository and version file. Returns a promise that should resolve to the hash. The primary use for this data structure is to provide necessary data for package creation.

The format of the object is:

{
	branch: 'master',
	owner: 'arobson',
	version: '0.1.0',
	build: 1,
	commit: '75b73a17ef82f451511a377ecf2149d81ce2fc17',
	name: 'test~arobson~master~0.1.0~1~darwin~any~any~x64',
	output: 'packages/test~arobson~master~0.1.0~1~darwin~any~any~x64.tar.gz',
	pattern: './src/**/*,./node_modules/**/*'
}
// projectName - the name of the project, ex: 'test'
// projectConfig - the build configuration for the project
// repositoryPath - the relative path for the repository
packages.getInfo( 'test', config, './' )
	.then( function( info ) {
		// on success
	} );

getInstalled( filter, installed, [ignored], [noError] )

For use in service hosts (as in nonstop)

Finds the most recent version installed within a relative path. The service host stores all installed versions under a common directory (./installed) and each version has its own directory. Returns the latest version installed on success.

// filter - regular expression to evaluation versions with
// installed - the path which versions have been installed to
// ignored - (optional) - a list of versions to exclude
// noError - (optional) - a flag that causes the function to resolve to undefined in the event of an error

packages.getInstalled( /.*/, './installed', [], true )
	.then( function( latestVersion ) {
		// on success
	} )

getInstalledVersions( filter, installed, [ignored], [noError] )

For use in service hosts (as in nonstop)

Works the same as getInstalled but returns the complete list of installed versions ordered newest to oldest.

getList( root )

For use in package hosting (as in nonstop-index)

Scans a given directory structure starting at a relative path to build an array containing package information for all packages found. Returns a promise that resolves to the array on success.

// root - the path to where all package subfolders are stored
packages.getList( './packages' )
	.then( function( packages ) {
		// on success
	} );

pack( pattern, workingPath, target )

For use in build agents/clis:

This function is called by create and performs the actual packaging. Returns a promise that resolves to a list of the files included in the created archive.

Note: this call will create the target directory if it does not already exist
// pattern - an array or comma delimited list of globs used to identify files for inclusion
// workingPath - the relative working directory for all globs
// target - path (including name) to the archive to create
packages.pack( pattern, workingPath, target )
	.then( function( files ) {
		// on success
	} );

parse( root, packageName, [directory] )

For use in package hosting (as in nonstop-index)

This function parses a package name in order to determine the metadata about the package.

// root - the path where archives are being stored
// packageName - the filename of the archive
var info = packages.parse( './packages', 'test~arobson~master~0.1.0~1~darwin~any~any~x64.tar.gz' );

The optional directory argument provides a way to specify the path a packagefile was found at. This will be reflected in a path and fullPath property on the packageInfo that normally wouldn't provide any different information. This was added to support finding and uploading packages from the CLI (as in nonstop-cli).

terms( packages )

For use in package hosting (as in nonstop-index)

Produce a unique set of valid filter key/value pairs based on the package information array. Returns a promise that resolves to the array of terms on success.

// packages - the array of package information
packages.terms( packages )
	.then( function( terms ) {
		// on success
	} );

promote( root, packageInfo, packages )

Promotes an existing package to a release and adds it the the list of packages.

unpack( artifact, target )

For use in service hosts (as in nonstop)

Unpackages a package (.tar.gz) to a target directory. If the unpack fails, this will attempt to remove the target and any contents. Returns a promise that resolves to the unpacked version or an error if the unpack fails.

// artifact - path including the package file
// target - path to unpack into
packages.unpack(
		'./packages/test~arobson~master~0.1.0~1~darwin~any~any~x64.tar.gz',
		'./installed/test-arobson-master/0.1.0-1' )
	.then( function( version ) {
		// on success
	} );

Dependencies

This would not have been possible without several great Node modules:

  • archiver
  • tar-fs
  • when
  • lodash
  • semver
  • rimraf
  • mkdirp
  • debug
  • globulesce

Dependents

The following nonstop projects rely on this library: