diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/README.md b/lib/node_modules/@stdlib/_tools/lint/manifest-json/README.md new file mode 100644 index 000000000000..d8f026519220 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/README.md @@ -0,0 +1,294 @@ + + +# Lint + +> Lint `manifest.json` files. + +
+ +## Usage + +```javascript +var lint = require( '@stdlib/_tools/lint/manifest-json' ); +``` + +#### lint( \[options,] clbk ) + +Asynchronously lints `manifest.json` files. + +```javascript +lint( done ); + +function done( error, errs ) { + if ( error ) { + throw error; + } + if ( errs ) { + console.dir( errs ); + } else { + console.log( 'Success!' ); + } +} +``` + +The function accepts the following `options`: + +- **dir**: root directory from which to search for manifest.json files. May be either an absolute file path or a path relative to the current working directory. Default: current working directory. +- **pattern**: glob pattern used to find manifest.json files. Default: `'**/@stdlib/**/manifest.json'` (note: pattern **must** end with `manifest.json`). +- **ignore**: list of glob patterns used to exclude matches. + +To search from an alternative directory, set the `dir` option. + +```javascript +var opts = { + 'dir': '/foo/bar/baz' +}; + +lint( opts, done ); + +function done( error, errs ) { + if ( error ) { + throw error; + } + if ( errs ) { + console.dir( errs ); + } else { + console.log( 'Success!' ); + } +} +``` + +To provide an alternative include filter, set the `pattern` option. + +```javascript +var opts = { + 'pattern': '**/@stdlib/math/**/manifest.json' +}; + +lint( opts, done ); + +function done( error, errs ) { + if ( error ) { + throw error; + } + if ( errs ) { + console.dir( errs ); + } else { + console.log( 'Success!' ); + } +} +``` + +To exclude matches, set the `ignore` option. + +```javascript +var opts = { + 'ignore': [ + 'node_modules/**', + 'build/**', + 'reports/**' + ] +}; + +lint( opts, done ); + +function done( error, errs ) { + if ( error ) { + throw error; + } + if ( errs ) { + console.dir( errs ); + } else { + console.log( 'Success!' ); + } +} +``` + +#### lint.sync( \[options] ) + +Synchronously lints `manifest.json` files. + +```javascript +var errs = lint.sync(); +if ( errs ) { + console.dir( errs ); +} else { + console.log( 'Success!' ); +} +``` + +The function accepts the same `options` as `lint()` above. + +
+ + + +
+ +
+ + + +
+ +## Examples + + + +```javascript +var lint = require( '@stdlib/_tools/lint/manifest-json' ); + +lint( done ); + +function done( error, errs ) { + if ( error ) { + throw error; + } + if ( errs ) { + console.dir( errs ); + } else { + console.log( 'Success!' ); + } +} +``` + +
+ + + +* * * + +
+ +## CLI + +
+ +### Usage + +```text +Usage: lint-manifest-json [options] [dir] + +Options: + + -h, --help Print this message. + -V, --version Print the package version. + --pattern pattern Inclusion glob pattern. + --ignore pattern Exclusion glob pattern. + --format format Output format: ndjson, pretty. + --split sep Separator used to split stdin data. Default: /\\r?\\n/. +``` + +
+ + + +
+ +### Notes + +- If part of a [standard stream][standard-stream] pipeline, results are written to `stdout` as newline-delimited JSON ([NDJSON][ndjson]). Otherwise, results are pretty printed by default. + +- If not provided a `dir` argument, the current working directory is the search directory. + +- To provide multiple exclusion glob patterns, set multiple `--ignore` option arguments. + + ```bash + $ lint-manifest-json --ignore=node_modules/** --ignore=build/** --ignore=reports/** + ``` + +- If the split separator is a [regular expression][regexp], ensure that the `split` option is properly **escaped**. + + ```bash + # Not escaped... + $ | lint-manifest-json --split /\r?\n/ + + # Escaped... + $ | lint-manifest-json --split /\\r?\\n/ + ``` + +- If provided a list of filenames via `stdin`, each filename is resolved relative to the current working directory. To specify an alternative directory, provide a `dir` argument. + +
+ + + +
+ +### Examples + +```bash +$ lint-manifest-json + +/path/to/manifest.json + + message: should have required property 'confs' + field: . + data: {"options":{},"fields":[]} + +1 errors +``` + +To output results as newline-delimited JSON ([NDJSON][ndjson]), + +```bash +$ lint-manifest-json --format ndjson +{"file":"...","errors":[...]} +{"file":"...","errors":[...]} +... +``` + +To use as a part of a [standard stream][standard-stream] pipeline, + +```bash +$ echo -n $'./manifest.json' | lint-manifest-json +... +``` + +
+ + + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/bin/cli b/lib/node_modules/@stdlib/_tools/lint/manifest-json/bin/cli new file mode 100755 index 000000000000..10a53f6bbd28 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/bin/cli @@ -0,0 +1,213 @@ +#!/usr/bin/env node + +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var readFileSync = require( '@stdlib/fs/read-file' ).sync; +var CLI = require( '@stdlib/cli/ctor' ); +var stdin = require( '@stdlib/process/read-stdin' ); +var stdinStream = require( '@stdlib/streams/node/stdin' ); +var stdoutStream = require( '@stdlib/streams/node/stdout' ); +var RE_EOL = require( '@stdlib/regexp/eol' ).REGEXP; +var isRegExpString = require( '@stdlib/assert/is-regexp-string' ); +var reFromString = require( '@stdlib/utils/regexp-from-string' ); +var cwd = require( '@stdlib/process/cwd' ); +var lint = require( './../lib' ); +var lintManifestJSON = require( './../lib/lint.js' ); + + +// FUNCTIONS // + +/** +* Prints lint errors as newline-delimited JSON. +* +* @private +* @param {ObjectArray} errs - lint errors +*/ +function ndjson( errs ) { + var i; + for ( i = 0; i < errs.length; i++ ) { + console.error( JSON.stringify( errs[ i ] ) ); // eslint-disable-line no-console + } +} + +/** +* Pretty prints lint errors. +* +* @private +* @param {ObjectArray} errors - lint errors +*/ +function prettyPrint( errors ) { + /* eslint-disable no-console */ + var total; + var error; + var errs; + var err; + var i; + var j; + + total = 0; + + console.error( '' ); + for ( i = 0; i < errors.length; i++ ) { + error = errors[ i ]; + console.error( error.file ); + + errs = error.errors; + total += errs.length; + for ( j = 0; j < errs.length; j++ ) { + err = errs[ j ]; + console.error( '' ); + console.error( ' message: %s', err.message ); + console.error( ' field: %s', err.dataPath ); + console.error( ' data: %s', JSON.stringify( err.data ) ); + } + console.error( '' ); + } + console.error( '%d errors', total ); + console.error( '' ); + + /* eslint-enable no-console */ +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +* @returns {void} +*/ +function main() { + var flags; + var args; + var opts; + var cli; + var fmt; + + // Create a command-line interface: + cli = new CLI({ + 'pkg': require( './../package.json' ), + 'options': require( './../etc/cli_opts.json' ), + 'help': readFileSync( resolve( __dirname, '..', 'docs', 'usage.txt' ), { + 'encoding': 'utf8' + }) + }); + + // Get any provided command-line options: + flags = cli.flags(); + if ( flags.help || flags.version ) { + return; + } + + // Get any provided command-line arguments: + args = cli.args(); + + if ( flags.format ) { + fmt = flags.format; + } else if ( stdoutStream.isTTY ) { + fmt = 'pretty'; + } else { + fmt = 'ndjson'; + } + opts = {}; + opts.dir = args[ 0 ] || cwd(); + + // Check if we are receiving a list of filenames from `stdin`... + if ( !stdinStream.isTTY ) { + if ( flags.split ) { + if ( !isRegExpString( flags.split ) ) { + flags.split = '/'+flags.split+'/'; + } + opts.split = reFromString( flags.split ); + } else { + opts.split = RE_EOL; + } + return stdin( onRead ); + } + if ( flags.pattern ) { + opts.pattern = flags.pattern; + } + if ( flags.ignore ) { + if ( typeof flags.ignore === 'string' ) { + opts.ignore = [ flags.ignore ]; + } else { + opts.ignore = flags.ignore; + } + } + lint( opts, onFinish ); + + /** + * Callback invoked upon reading from `stdin`. + * + * @private + * @param {(Error|null)} error - error object + * @param {Buffer} data - data + * @returns {void} + */ + function onRead( error, data ) { + var i; + if ( error ) { + return cli.error( error ); + } + data = data.toString().split( opts.split ); + + // Check if input data had a trailing newline... + if ( data[ data.length-1 ] === '' ) { + data.length -= 1; + } + if ( data.length === 0 ) { + return; + } + // Resolve absolute file paths... + for ( i = 0; i < data.length; i++ ) { + data[ i ] = resolve( opts.dir, data[i] ); + } + lintManifestJSON( data, onFinish ); + } + + /** + * Callback invoked after linting. + * + * @private + * @param {(Error|null)} error - error object + * @param {(ObjectArray|null)} errs - lint errors + * @returns {void} + */ + function onFinish( error, errs ) { + if ( error ) { + return cli.error( error ); + } + if ( errs ) { + if ( fmt === 'ndjson' ) { + ndjson( errs ); + } else { + prettyPrint( errs ); + } + return cli.close( 1 ); + } + } +} + +main(); diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/docs/usage.txt b/lib/node_modules/@stdlib/_tools/lint/manifest-json/docs/usage.txt new file mode 100644 index 000000000000..7978126ace87 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/docs/usage.txt @@ -0,0 +1,12 @@ + +Usage: lint-manifest-json [options] [dir] + +Options: + + -h, --help Print this message. + -V, --version Print the package version. + --pattern pattern Inclusion glob pattern. + --ignore pattern Exclusion glob pattern. + --format format Output format: ndjson, pretty. + --split sep Separator used to split stdin data. Default: /\\r?\\n/. + diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/etc/cli_opts.json b/lib/node_modules/@stdlib/_tools/lint/manifest-json/etc/cli_opts.json new file mode 100644 index 000000000000..c282ddbb4e7a --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/etc/cli_opts.json @@ -0,0 +1,20 @@ +{ + "string": [ + "pattern", + "ignore", + "format", + "split" + ], + "boolean": [ + "help", + "version" + ], + "alias": { + "help": [ + "h" + ], + "version": [ + "V" + ] + } +} diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/examples/index.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/examples/index.js new file mode 100644 index 000000000000..33ea9834f472 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/examples/index.js @@ -0,0 +1,34 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var lint = require( './../lib' ); + +lint( done ); + +function done( error, errs ) { + if ( error ) { + throw error; + } + if ( errs ) { + console.dir( errs ); + } else { + console.log( 'Success!' ); + } +} diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/async.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/async.js new file mode 100644 index 000000000000..956ec82e6cb5 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/async.js @@ -0,0 +1,147 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var logger = require( 'debug' ); +var glob = require( 'glob' ); +var isFunction = require( '@stdlib/assert/is-function' ); +var format = require( '@stdlib/string/format' ); +var copy = require( '@stdlib/utils/copy' ); +var cwd = require( '@stdlib/process/cwd' ); +var config = require( './config.json' ); +var validate = require( './validate.js' ); +var linter = require( './lint.js' ); + + +// VARIABLES // + +var debug = logger( 'lint:manifest-json:async' ); + + +// MAIN // + +/** +* Asynchronously lint `manifest.json` files. +* +* @param {Options} [options] - function options +* @param {string} [options.dir] - root directory from which to search for manifest.json files +* @param {string} [options.pattern='**\/@stdlib/**\/manifest.json'] - glob pattern +* @param {StringArray} [options.ignore] - glob pattern(s) to exclude matches +* @param {Callback} clbk - callback to invoke after completion +* @throws {TypeError} callback argument must be a function +* @throws {TypeError} options argument must be an object +* @throws {TypeError} must provide valid options +* @throws {Error} `pattern` option must end with `manifest.json` +* +* @example +* lint( clbk ); +* +* function clbk( error, errs ) { +* if ( error ) { +* throw error; +* } +* if ( errs ) { +* console.dir( errs ); +* } else { +* console.log( 'Success!' ); +* } +* } +*/ +function lint() { + var options; + var gopts; + var opts; + var clbk; + var err; + var dir; + + opts = copy( config ); + if ( arguments.length < 2 ) { + clbk = arguments[ 0 ]; + } else { + options = arguments[ 0 ]; + clbk = arguments[ 1 ]; + err = validate( opts, options ); + if ( err ) { + throw err; + } + } + if ( !isFunction( clbk ) ) { + throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', clbk ) ); + } + if ( opts.dir ) { + dir = resolve( cwd(), opts.dir ); + } else { + dir = cwd(); + } + gopts = { + 'cwd': dir, + 'ignore': opts.ignore, + 'realpath': true // return absolute file paths + }; + debug( 'Glob options: %s', JSON.stringify( gopts ) ); + + debug( 'Searching for `manifest.json` files.' ); + glob( opts.pattern, gopts, onGlob ); + + /** + * Callback invoked after matching files. + * + * @private + * @param {(Error|null)} error - error object + * @param {StringArray} files - list of matching files + * @returns {void} + */ + function onGlob( error, files ) { + if ( error ) { + debug( 'Encountered an error when searching for files: %s', error.message ); + return done( error ); + } + debug( 'Found %d files.', files.length ); + if ( files.length ) { + debug( 'Processing files.' ); + linter( files, done ); + } else { + done( null, null ); + } + } + + /** + * Callback invoked upon reading manifests. + * + * @private + * @param {(Error|null)} error - error object + * @param {(ObjectArray|null)} errs - lint errs + * @returns {void} + */ + function done( error, errs ) { + if ( error ) { + return clbk( error ); + } + clbk( null, errs ); + } +} + + +// EXPORTS // + +module.exports = lint; diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/config.json b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/config.json new file mode 100644 index 000000000000..be80c2c859e6 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/config.json @@ -0,0 +1,11 @@ +{ + "dir": "./lib/node_modules", + "pattern": "**/@stdlib/**/manifest.json", + "ignore": [ + "**/snippets/manifest.json", + "node_modules/**", + "**/build/**", + "reports/**", + ".git*" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/index.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/index.js new file mode 100644 index 000000000000..11b3b887ff96 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/index.js @@ -0,0 +1,67 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Lint `manifest.json` files. +* +* @module @stdlib/_tools/lint/manifest-json +* +* @example +* var lint = require( '@stdlib/_tools/lint/manifest-json' ); +* +* lint( clbk ); +* +* function clbk( error, errs ) { +* if ( error ) { +* throw error; +* } +* if ( errs ) { +* console.dir( errs ); +* } else { +* console.log( 'Success!' ); +* } +* } +* +* @example +* var lint = require( '@stdlib/_tools/lint/manifest-json' ); +* +* var errs = lint.sync(); +* if ( errs ) { +* console.dir( errs ); +* } else { +* console.log( 'Success!' ); +* } +*/ + +// MODULES // + +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var lint = require( './async.js' ); +var sync = require( './sync.js' ); + + +// MAIN // + +setReadOnly( lint, 'sync', sync ); + + +// EXPORTS // + +module.exports = lint; diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/lint.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/lint.js new file mode 100644 index 000000000000..3e3f15e91150 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/lint.js @@ -0,0 +1,127 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var logger = require( 'debug' ); +var readJSON = require( '@stdlib/fs/read-json' ); +var isValid = require( '@stdlib/_tools/manifest-json/validate' ); + + +// VARIABLES // + +var debug = logger( 'lint:manifest-json:linter' ); + + +// MAIN // + +/** +* Reads and lints `manifest.json` files. +* +* @private +* @param {StringArray} files - list of `manifest.json` files +* @param {Callback} clbk - callback to invoke upon completion +*/ +function lint( files, clbk ) { + var total; + var out; + var i; + + total = files.length; + out = []; + i = -1; + + next(); + + /** + * Processes the next `manifest.json` file. + * + * @private + */ + function next() { + i += 1; + debug( 'Processing file %d of %d: %s', i+1, total, files[ i ] ); + readJSON( files[ i ], onRead ); + } + + /** + * Callback invoked upon reading a `manifest.json` file. + * + * @private + * @param {(Error|null)} error - error object + * @param {Object} json - JSON object + * @returns {void} + */ + function onRead( error, json ) { + var bool; + var j; + + j = i + 1; + if ( error ) { + debug( 'Encountered an error reading file: %s (%d of %d). Error: %s', files[ i ], j, total, error.message ); + out.push({ + 'file': files[ i ], + 'errors': [ + { + 'message': error.message + } + ] + }); + } else { + debug( 'Successfully read file: %s (%d of %d).', files[ i ], j, total ); + + debug( 'Validating file.' ); + bool = isValid( json ); + if ( bool ) { + debug( 'File is valid.' ); + } else { + debug( 'File is invalid: %s.', JSON.stringify( isValid.errors ) ); + out.push({ + 'file': files[ i ], + 'errors': isValid.errors + }); + } + } + if ( j < total ) { + debug( 'Processed %d of %d files.', j, total ); + return next(); + } + debug( 'Processed all files.' ); + return done(); + } + + /** + * Callback invoked upon completion. + * + * @private + */ + function done() { + if ( out.length ) { + clbk( null, out ); + } else { + clbk( null, null ); + } + } +} + + +// EXPORTS // + +module.exports = lint; diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/sync.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/sync.js new file mode 100644 index 000000000000..261c5c1dda23 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/sync.js @@ -0,0 +1,143 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var logger = require( 'debug' ); +var glob = require( 'glob' ).sync; +var cwd = require( '@stdlib/process/cwd' ); +var copy = require( '@stdlib/utils/copy' ); +var readJSON = require( '@stdlib/fs/read-json' ).sync; +var isValid = require( '@stdlib/_tools/manifest-json/validate' ); +var config = require( './config.json' ); +var validate = require( './validate.js' ); + + +// VARIABLES // + +var debug = logger( 'lint:manifest-json:sync' ); + + +// MAIN // + +/** +* Synchronously lint `manifest.json` files. +* +* @param {Options} [options] - function options +* @param {string} [options.dir] - root directory from which to search for manifest.json files +* @param {string} [options.pattern='**\/@stdlib/**\/manifest.json'] - glob pattern +* @param {StringArray} [options.ignore] - glob pattern(s) to exclude matches +* @throws {TypeError} options argument must be an object +* @throws {TypeError} must provide valid options +* @throws {Error} `pattern` option must end with `manifest.json` +* @returns {(ObjectArray|null)} lint errors or `null` +* +* @example +* var errs = lint(); +* if ( errs ) { +* console.dir( errs ); +* } else { +* console.log( 'Success!' ); +* } +*/ +function lint( options ) { + var files; + var gopts; + var total; + var file; + var opts; + var bool; + var err; + var dir; + var out; + var i; + var j; + + opts = copy( config ); + if ( arguments.length ) { + err = validate( opts, options ); + if ( err ) { + throw err; + } + } + if ( opts.dir ) { + dir = resolve( cwd(), opts.dir ); + } else { + dir = cwd(); + } + gopts = { + 'cwd': dir, + 'ignore': opts.ignore, + 'realpath': true // return absolute file paths + }; + debug( 'Glob options: %s', JSON.stringify( gopts ) ); + + debug( 'Searching for `manifest.json` files.' ); + files = glob( opts.pattern, gopts ); + + total = files.length; + debug( 'Found %d files.', total ); + if ( total === 0 ) { + return null; + } + debug( 'Processing files.' ); + out = []; + for ( i = 0; i < total; i++ ) { + j = i + 1; + debug( 'Reading file: %s (%d of %d).', files[ i ], j, total ); + file = readJSON( files[ i ] ); + if ( file instanceof Error ) { + debug( 'Encountered an error reading file: %s (%d of %d). Error: %s', files[ i ], j, total, file.message ); + out.push({ + 'file': files[ i ], + 'errors': [ + { + 'message': file.message + } + ] + }); + } else { + debug( 'Successfully read file: %s (%d of %d).', files[ i ], j, total ); + debug( 'Linting file.' ); + bool = isValid( file ); + if ( bool ) { + debug( 'File is valid.' ); + } else { + debug( 'File is invalid: %s.', JSON.stringify( isValid.errors ) ); + out.push({ + 'file': files[ i ], + 'errors': isValid.errors + }); + } + } + debug( 'Processed %d of %d files.', j, total ); + } + debug( 'Processed all files.' ); + if ( out.length ) { + return out; + } + return null; +} + + +// EXPORTS // + +module.exports = lint; diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/validate.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/validate.js new file mode 100644 index 000000000000..8987156edcc5 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/lib/validate.js @@ -0,0 +1,90 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var isObject = require( '@stdlib/assert/is-plain-object' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var format = require( '@stdlib/string/format' ); + + +// VARIABLES // + +var RE = /manifest\.json$/; + + +// MAIN // + +/** +* Validates function options. +* +* @private +* @param {Object} opts - destination object +* @param {Options} options - function options +* @param {string} [options.dir] - root directory from which to search for manifest.json files +* @param {string} [options.pattern] - glob pattern +* @param {StringArray} [options.ignore] - glob pattern(s) to exclude matches +* @returns {(Error|null)} error object or null +* +* @example +* var opts = {}; +* var options = { +* 'dir': '/foo/bar/baz' +* }; +* +* var err = validate( opts, options ); +* if ( err ) { +* throw err; +* } +*/ +function validate( opts, options ) { + if ( !isObject( options ) ) { + return new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + if ( hasOwnProp( options, 'dir' ) ) { + opts.dir = options.dir; + if ( !isString( opts.dir ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'dir', opts.dir ) ); + } + } + if ( hasOwnProp( options, 'pattern' ) ) { + opts.pattern = options.pattern; + if ( !isString( opts.pattern ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'pattern', opts.pattern ) ); + } + if ( !RE.test( opts.pattern ) ) { + return new Error( format( 'invalid option. `%s` option must end with "manifest.json". Option: `%s`.', 'pattern', opts.pattern ) ); + } + } + if ( hasOwnProp( options, 'ignore' ) ) { + opts.ignore = options.ignore; + if ( !isStringArray( opts.ignore ) ) { + return new TypeError( format( 'invalid option. `%s` option must be an array of strings. Option: `%s`.', 'ignore', opts.ignore ) ); + } + } + return null; +} + + +// EXPORTS // + +module.exports = validate; diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/package.json b/lib/node_modules/@stdlib/_tools/lint/manifest-json/package.json new file mode 100644 index 000000000000..12b41001f247 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/_tools/lint/manifest-json", + "version": "0.0.0", + "description": "Lint manifest.json files.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "bin": { + "lint-manifest-json": "./bin/cli" + }, + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "tools", + "tool", + "lint", + "linter", + "manifest", + "json", + "manifest.json", + "validate", + "valid", + "check", + "schema" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/fixtures/bad.json b/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/fixtures/bad.json new file mode 100644 index 000000000000..5c074a64b465 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/fixtures/bad.json @@ -0,0 +1,10 @@ +{ + "options": {}, + "fields": [ + { + "field": "src", + "resolve": true, + "relative": true + } + ] +} diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/fixtures/invalid.json b/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/fixtures/invalid.json new file mode 100644 index 000000000000..865e9e624f72 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/fixtures/invalid.json @@ -0,0 +1 @@ +{invalid json content[} diff --git a/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/test.js b/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/test.js new file mode 100644 index 000000000000..bc774d842cb4 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/lint/manifest-json/test/test.js @@ -0,0 +1,38 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var lint = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof lint, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'attached to the main export is a method to synchronously lint files', function test( t ) { + t.strictEqual( typeof lint.sync, 'function', 'has sync method' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/README.md b/lib/node_modules/@stdlib/_tools/manifest-json/validate/README.md new file mode 100644 index 000000000000..01c0a5316427 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/README.md @@ -0,0 +1,169 @@ + + +# Validate + +> Validate a `manifest.json` object. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var isValid = require( '@stdlib/_tools/manifest-json/validate' ); +``` + +#### isValid( manifest ) + +Validates a `manifest.json` object. + +```javascript +var manifest = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/good.json' ); + +var bool = isValid( manifest ); +// returns + +var errs = isValid.errors; +// returns || null +``` + +
+ + + + + +
+ +
+ + + + + +
+ +## Examples + + + +```javascript +var isValid = require( '@stdlib/_tools/manifest-json/validate' ); + +var manifest = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/good.json' ); + +var bool = isValid( manifest ); +var errs = isValid.errors; +``` + +
+ + + + + +* * * + +
+ +## CLI + + + +
+ +### Usage + +```bash +Usage: validate-manifest-json [options] [json] + +Options: + + -h, --help Print this message. + -V, --version Print the package version. +``` + +
+ + + + + +
+ +### Notes + +- If successful, the program prints `true` to `stdout`. If not successful, the program prints validation errors to `stderr`. + +
+ + + + + +
+ +### Examples + +```bash +$ validate-manifest-json "$(cat ./manifest.json)" +``` + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/bin/cli b/lib/node_modules/@stdlib/_tools/manifest-json/validate/bin/cli new file mode 100755 index 000000000000..4bdfe646a6b8 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/bin/cli @@ -0,0 +1,112 @@ +#!/usr/bin/env node + +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var readFileSync = require( '@stdlib/fs/read-file' ).sync; +var parseJSON = require( '@stdlib/utils/parse-json' ); +var stdin = require( '@stdlib/process/read-stdin' ); +var CLI = require( '@stdlib/cli/ctor' ); +var stdinStream = require( '@stdlib/streams/node/stdin' ); +var nextTick = require( '@stdlib/utils/next-tick' ); +var validate = require( './../lib' ); + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +* @returns {void} +*/ +function main() { + var flags; + var args; + var json; + var cli; + + // Create a command-line interface: + cli = new CLI({ + 'pkg': require( './../package.json' ), + 'options': require( './../etc/cli_opts.json' ), + 'help': readFileSync( resolve( __dirname, '..', 'docs', 'usage.txt' ), { + 'encoding': 'utf8' + }) + }); + + // Get any provided command-line options: + flags = cli.flags(); + if ( flags.help || flags.version ) { + return; + } + + // Get any provided command-line arguments: + args = cli.args(); + + // Check if we are receiving data from `stdin`... + if ( !stdinStream.isTTY ) { + return stdin( onRead ); + } + json = args[ 0 ]; + nextTick( next ); + + /** + * Callback invoked upon reading from `stdin`. + * + * @private + * @param {(Error|null)} error - error object + * @param {Buffer} data - data + * @returns {void} + */ + function onRead( error, data ) { + if ( error ) { + return cli.error( error ); + } + json = data.toString(); + next(); + } + + /** + * Validates a `manifest.json`. + * + * @private + * @returns {void} + */ + function next() { + var bool; + + json = parseJSON( json ); + if ( json instanceof Error ) { + return cli.error( json ); + } + bool = validate( json ); + if ( bool ) { + console.log( true ); // eslint-disable-line no-console + } else { + console.error( validate.errors ); // eslint-disable-line no-console + } + } +} + +main(); diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/docs/usage.txt b/lib/node_modules/@stdlib/_tools/manifest-json/validate/docs/usage.txt new file mode 100644 index 000000000000..33a0e7cefd93 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/docs/usage.txt @@ -0,0 +1,8 @@ + +Usage: validate-manifest-json [options] [json] + +Options: + + -h, --help Print this message. + -V, --version Print the package version. + diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/etc/cli_opts.json b/lib/node_modules/@stdlib/_tools/manifest-json/validate/etc/cli_opts.json new file mode 100644 index 000000000000..f245a17e6317 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/etc/cli_opts.json @@ -0,0 +1,14 @@ +{ + "boolean": [ + "help", + "version" + ], + "alias": { + "help": [ + "h" + ], + "version": [ + "V" + ] + } +} diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/examples/index.js b/lib/node_modules/@stdlib/_tools/manifest-json/validate/examples/index.js new file mode 100644 index 000000000000..945ae1cf9ab6 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/examples/index.js @@ -0,0 +1,28 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var manifest = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/good.json' ); +var isValid = require( './../lib' ); + +var bool = isValid( manifest ); +console.log( bool ); + +var errs = isValid.errors; +console.log( errs ); diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/lib/index.js b/lib/node_modules/@stdlib/_tools/manifest-json/validate/lib/index.js new file mode 100644 index 000000000000..0e52e75d5edc --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/lib/index.js @@ -0,0 +1,41 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Validate a manifest.json. +* +* @module @stdlib/_tools/manifest-json/validate +* +* @example +* var manifest = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/good.json' ); +* var isValid = require( '@stdlib/_tools/manifest-json/validate' ); +* +* var bool = isValid( manifest ); +* var errs = isValid.errors; +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/lib/main.js b/lib/node_modules/@stdlib/_tools/manifest-json/validate/lib/main.js new file mode 100644 index 000000000000..dba7b08240da --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/lib/main.js @@ -0,0 +1,61 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var Ajv = require( 'ajv' ); +var schema = require( './../../schema' ); // eslint-disable-line node/no-unpublished-require + + +// MAIN // + +/** +* Returns a function to validate `manifest.json`. +* +* @private +* @returns {Function} validation function +* +* @example +* var isValid = validator(); +*/ +function validator() { + var opts; + var ajv; + + opts = {}; + + // Collect all errors: + opts.allErrors = true; + + // Include the schema reference and invalid data in error output: + opts.verbose = true; + + // Perform "full" validation: + opts.format = 'full'; + + // Create a new `Ajv` instance and compile the schema: + ajv = new Ajv( opts ); + return ajv.compile( schema() ); +} + + +// EXPORTS // + +module.exports = validator(); // eslint-disable-line stdlib/no-dynamic-exports diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/package.json b/lib/node_modules/@stdlib/_tools/manifest-json/validate/package.json new file mode 100644 index 000000000000..5fb7945dc83d --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/package.json @@ -0,0 +1,56 @@ +{ + "name": "@stdlib/_tools/manifest-json/validate", + "version": "0.0.0", + "description": "Validate a manifest.json file.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "bin": { + "validate-manifest-json": "./bin/cli" + }, + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "keywords": [ + "stdlib", + "tools", + "tool", + "json", + "manifest", + "manifest.json", + "meta", + "validate", + "valid", + "check", + "test", + "isvalid", + "is" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/manifest-json/validate/test/test.js b/lib/node_modules/@stdlib/_tools/manifest-json/validate/test/test.js new file mode 100644 index 000000000000..1491da484c0c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/manifest-json/validate/test/test.js @@ -0,0 +1,102 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var isArray = require( '@stdlib/assert/is-array' ); +var goodManifest = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/good.json' ); +var missingConfs = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/missing_confs.json' ); +var missingFields = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/missing_fields.json' ); +var missingOptions = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/missing_options.json' ); +var badConfs = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/bad_confs1.json' ); +var badFields = require( '@stdlib/_tools/manifest-json/schema/test/fixtures/bad_fields1.json' ); +var isValid = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof isValid, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns `true` if provided a valid `manifest.json`', function test( t ) { + var bool = isValid( goodManifest ); + + t.strictEqual( bool, true, 'returns expected value' ); + t.strictEqual( isValid.errors, null, 'errors property is `null`' ); + t.end(); +}); + +tape( 'the function returns `false` if provided an invalid `manifest.json` (missing configurations)', function test( t ) { + var bool = isValid( missingConfs ); + + t.strictEqual( bool, false, 'returns expected value' ); + t.strictEqual( isArray( isValid.errors ), true, 'errors property is an array' ); + t.end(); +}); + +tape( 'the function returns `false` if provided an invalid `manifest.json` (missing fields)', function test( t ) { + var bool = isValid( missingFields ); + + t.strictEqual( bool, false, 'returns expected value' ); + t.strictEqual( isArray( isValid.errors ), true, 'errors property is an array' ); + t.end(); +}); + +tape( 'the function returns `false` if provided an invalid `manifest.json` (missing options)', function test( t ) { + var bool = isValid( missingOptions ); + + t.strictEqual( bool, false, 'returns expected value' ); + t.strictEqual( isArray( isValid.errors ), true, 'errors property is an array' ); + t.end(); +}); + +tape( 'the function returns `false` if provided an invalid `manifest.json` (bad configurations)', function test( t ) { + var bool = isValid( badConfs ); + + t.strictEqual( bool, false, 'returns expected value' ); + t.strictEqual( isArray( isValid.errors ), true, 'errors property is an array' ); + t.end(); +}); + +tape( 'the function returns `false` if provided an invalid `manifest.json` (bad fields)', function test( t ) { + var bool = isValid( badFields ); + + t.strictEqual( bool, false, 'returns expected value' ); + t.strictEqual( isArray( isValid.errors ), true, 'errors property is an array' ); + t.end(); +}); + +tape( 'the function returns `false` if provided an invalid object', function test( t ) { + var manifest; + var bool; + + manifest = { + 'beep': 'boop' + }; + bool = isValid( manifest ); + + t.strictEqual( bool, false, 'returns expected value' ); + t.strictEqual( isArray( isValid.errors ), true, 'errors property is an array' ); + t.end(); +});