├── .editorconfig
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .travis.yml
├── .verb.md
├── LICENSE
├── README.md
├── bin
└── cli.js
├── bower.json
├── example.js
├── index.js
├── lib
├── keys.js
├── merge.js
├── normalizers
│ ├── bin.js
│ ├── bugs.js
│ ├── engineStrict.js
│ ├── files.js
│ ├── helpers
│ │ ├── git.js
│ │ └── owner.js
│ ├── homepage.js
│ ├── index.js
│ ├── keywords.js
│ ├── license.js
│ ├── licenses.js
│ ├── main.js
│ ├── name.js
│ ├── person.js
│ ├── repository.js
│ ├── scripts.js
│ └── typings.js
├── schema.js
├── utils.js
└── validators
│ ├── index.js
│ ├── name.js
│ ├── preferGlobal.js
│ └── version.js
├── package.json
└── test
├── .eslintrc.json
├── actual
└── normalized.json
├── fixtures
├── author-condensed.json
├── authors-condensed.json
├── bin.json
├── engine-strict.json
├── licenses.json
├── main.json
├── missing.json
├── package.json
├── people-condensed.json
├── people.json
├── project-bin
│ ├── bin
│ │ └── foo.js
│ ├── cli.js
│ ├── main.js
│ └── package.json
├── project-no-git
│ ├── main.js
│ └── package.json
├── project-no-package
│ └── main.js
├── project
│ ├── main.js
│ └── package.json
├── verb.json
└── wrong.json
├── support
└── git.js
├── test-bin.js
├── test-no-git.js
├── test-no-package.js
├── test.js
└── utils.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | end_of_line = lf
6 | charset = utf-8
7 | indent_size = 2
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [{**/{actual,fixtures,expected,templates}/**,*.md}]
12 | trim_trailing_whitespace = false
13 | insert_final_newline = false
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "eslint:recommended"
4 | ],
5 |
6 | "env": {
7 | "es6": true,
8 | "node": true
9 | },
10 |
11 | "parserOptions": {
12 | "ecmaVersion": 9
13 | },
14 |
15 | "rules": {
16 | "accessor-pairs": 2,
17 | "arrow-parens": [2, "as-needed"],
18 | "arrow-spacing": [2, { "before": true, "after": true }],
19 | "block-spacing": [2, "always"],
20 | "brace-style": [2, "1tbs", { "allowSingleLine": true }],
21 | "comma-dangle": [2, "never"],
22 | "comma-spacing": [2, { "before": false, "after": true }],
23 | "comma-style": [2, "last"],
24 | "constructor-super": 2,
25 | "curly": [2, "multi-line"],
26 | "dot-location": [2, "property"],
27 | "eol-last": 2,
28 | "eqeqeq": [2, "allow-null"],
29 | "generator-star-spacing": [2, { "before": true, "after": true }],
30 | "handle-callback-err": [2, "^(err|error)$"],
31 | "indent": [2, 2, { "SwitchCase": 1 }],
32 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
33 | "keyword-spacing": [2, { "before": true, "after": true }],
34 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }],
35 | "new-parens": 2,
36 | "no-array-constructor": 2,
37 | "no-caller": 2,
38 | "no-class-assign": 2,
39 | "no-cond-assign": 2,
40 | "no-const-assign": 2,
41 | "no-control-regex": 2,
42 | "no-debugger": 2,
43 | "no-delete-var": 2,
44 | "no-dupe-args": 2,
45 | "no-dupe-class-members": 2,
46 | "no-dupe-keys": 2,
47 | "no-duplicate-case": 2,
48 | "no-empty-character-class": 2,
49 | "no-eval": 2,
50 | "no-ex-assign": 2,
51 | "no-extend-native": 2,
52 | "no-extra-bind": 2,
53 | "no-extra-boolean-cast": 2,
54 | "no-extra-parens": [2, "functions"],
55 | "no-fallthrough": 2,
56 | "no-floating-decimal": 2,
57 | "no-func-assign": 2,
58 | "no-implied-eval": 2,
59 | "no-implicit-coercion": 2,
60 | "no-inner-declarations": [2, "functions"],
61 | "no-invalid-regexp": 2,
62 | "no-irregular-whitespace": 2,
63 | "no-iterator": 2,
64 | "no-label-var": 2,
65 | "no-labels": 2,
66 | "no-lone-blocks": 2,
67 | "no-lonely-if": 2,
68 | "no-mixed-spaces-and-tabs": 2,
69 | "no-multi-spaces": 0,
70 | "no-multi-str": 2,
71 | "no-multiple-empty-lines": [2, { "max": 1 }],
72 | "no-native-reassign": 2,
73 | "no-negated-in-lhs": 2,
74 | "no-new": 2,
75 | "no-new-func": 2,
76 | "no-new-object": 2,
77 | "no-new-require": 2,
78 | "no-new-wrappers": 2,
79 | "no-obj-calls": 2,
80 | "no-octal": 2,
81 | "no-octal-escape": 2,
82 | "no-proto": 2,
83 | "no-redeclare": 2,
84 | "no-regex-spaces": 2,
85 | "no-return-assign": 2,
86 | "no-self-compare": 2,
87 | "no-sequences": 2,
88 | "no-shadow-restricted-names": 2,
89 | "no-spaced-func": 2,
90 | "no-sparse-arrays": 2,
91 | "no-this-before-super": 2,
92 | "no-throw-literal": 2,
93 | "no-trailing-spaces": 2,
94 | "no-undef": 2,
95 | "no-undef-init": 2,
96 | "no-unexpected-multiline": 2,
97 | "no-unneeded-ternary": [2, { "defaultAssignment": false }],
98 | "no-unreachable": 2,
99 | "no-unused-expressions": 2,
100 | "no-unused-vars": [2, { "vars": "all", "args": "none" }],
101 | "no-useless-call": 2,
102 | "no-with": 2,
103 | "object-curly-spacing": ["error", "always", { "objectsInObjects": true }],
104 | "one-var": [2, { "initialized": "never" }],
105 | "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }],
106 | "padded-blocks": [0, "never"],
107 | "prefer-const": [2, { "destructuring": "all", "ignoreReadBeforeAssign": false }],
108 | "quotes": [2, "single", "avoid-escape"],
109 | "radix": 2,
110 | "semi": [2, "always"],
111 | "semi-spacing": [2, { "before": false, "after": true }],
112 | "space-before-blocks": [2, "always"],
113 | "space-before-function-paren": [2, { "anonymous": "never", "named": "never", "asyncArrow": "always" }],
114 | "space-in-parens": [2, "never"],
115 | "space-infix-ops": 2,
116 | "space-unary-ops": [2, { "words": true, "nonwords": false }],
117 | "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }],
118 | "strict": 2,
119 | "use-isnan": 2,
120 | "valid-typeof": 2,
121 | "wrap-iife": [2, "any"],
122 | "yoda": [2, "never"]
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Enforce Unix newlines
2 | *.* text eol=lf
3 | *.css text eol=lf
4 | *.html text eol=lf
5 | *.js text eol=lf
6 | *.json text eol=lf
7 | *.less text eol=lf
8 | *.md text eol=lf
9 | *.yml text eol=lf
10 |
11 | *.jpg binary
12 | *.gif binary
13 | *.png binary
14 | *.jpeg binary
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # always ignore files
2 | *.DS_Store
3 | *.sublime-*
4 |
5 | # test related, or directories generated by tests
6 | test/actual
7 | actual
8 | coverage
9 | .nyc*
10 |
11 | # npm
12 | node_modules
13 | npm-debug.log
14 |
15 | # yarn
16 | yarn.lock
17 | yarn-error.log
18 |
19 | # misc
20 | _gh_pages
21 | _draft
22 | _drafts
23 | bower_components
24 | vendor
25 | temp
26 | tmp
27 | TODO.md
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | os:
3 | - linux
4 | - osx
5 | language: node_js
6 | node_js:
7 | - node
8 | - '7'
9 | - '6'
10 | - '5'
11 | - '4'
12 | - '0.12'
13 | - '0.10'
14 |
--------------------------------------------------------------------------------
/.verb.md:
--------------------------------------------------------------------------------
1 | ## Install
2 |
3 | {%= include("install-bower", {save: true}) %}
4 |
5 | ## Usage
6 |
7 | ```js
8 | var config = require('./')();
9 | var pkg = config.normalize(require('./package'));
10 | ```
11 |
12 | ## Features
13 |
14 | Normalizes most package.json fields, and:
15 |
16 | - converts `repository` objects to a string
17 | - stringifies `author` object
18 | - stringifies each "person" object in `maintainers`, `contributors` and `collaborators`
19 | - converts `licenses` arrays and objects to a `license` string
20 | - removes files that don't exist from `bin`, `main` and the `files` array
21 | - adds `cli.js` to `bin` if it exists
22 | - creates `keywords` array from `name` if not defined
23 |
24 | See the [schema](lib/schema.js), [normalizers](lib/normalizers), and [unit tests](test) for more examples.
25 |
26 | ## Schema
27 |
28 | Values are normalized using a [schema](lib/schema.js) that is passed to [map-schema][].
29 |
30 | - only properties that have a corresponding field on the schema will be normalized.
31 | - any properties that do not have a corresponding field are returned unmodified.
32 |
33 | See the [.field docs](#field) to learn how to add or overwrite a field on the schema.
34 |
35 | ## Defaults
36 |
37 | A `default` value may optionally be defined when a `.field` is registered. When `.normalize` is run and a property that is required or recommended by npm is missing, `normalize-pkg` attempts to create the field if valid data can be found in the repository.
38 |
39 | built-in fields have a default value:
40 |
41 | - `version`: `'0.1.0'`
42 | - `license`: `'MIT'`
43 | - `engines`: `{node: '>= 0.10.0'}`
44 |
45 | For example:
46 |
47 | - `name`: the [project-name][] library is used to fill in the name
48 | - `bin`: if empty, populated with `cli.js` or `bin` if either exists on the file system
49 |
50 | **Example**
51 |
52 | The following:
53 |
54 | ```js
55 | var config = require('./')();
56 |
57 | // no package.json is passed, just an empty object
58 | var pkg = config.normalize({});
59 | console.log(pkg);
60 | ```
61 |
62 | **Results**
63 |
64 | Since an empty object was passed, `normalize-pkg` was smart enough to fill in missing fields looking for info in the project. In this case, specifically from parsing `.git` config and using any defaults defined on the schema.
65 |
66 | ```js
67 | { name: 'normalize-pkg',
68 | version: '0.1.0',
69 | homepage: 'https://github.com/jonschlinkert/normalize-pkg',
70 | repository: 'jonschlinkert/normalize-pkg',
71 | license: 'MIT',
72 | files: [ 'index.js' ],
73 | main: 'index.js',
74 | engines: { node: '>= 0.10.0' } }
75 | ```
76 |
77 | ## API
78 | {%= apidocs("index.js") %}
79 |
80 | ## Options
81 |
82 | ### options.knownOnly
83 |
84 | **Type**: `boolean`
85 |
86 | **Default**: `undefined`
87 |
88 | Omit properties from package.json that do not have a field registered on the schema.
89 |
90 | ```js
91 | var Config = require('{%= name %}');
92 | var config = new Config({knownOnly: true});
93 |
94 | var pkg = config.normalize({name: 'my-project', foo: 'bar'});
95 | console.log(pkg);
96 | //=> {name: 'my-project'}
97 | ```
98 |
99 | ### options.pick
100 |
101 | **Type**: `array`
102 |
103 | **Default**: `undefined`
104 |
105 | Filter the resulting object to contain only the specified keys.
106 |
107 | ### options.omit
108 |
109 | **Type**: `array`
110 |
111 | **Default**: `undefined`
112 |
113 | Remove the specified keys from the resulting object.
114 |
115 | ### options.fields
116 |
117 | Pass a `fields` object on the options to customize any fields on the schema (also see [options.extend](#options-extend)):
118 |
119 | ```js
120 | var pkg = config.normalize(require('./package'), {
121 | extend: true,
122 | fields: {
123 | name: {
124 | normalize: function() {
125 | return 'bar'
126 | }
127 | }
128 | }
129 | });
130 |
131 | console.log(pkg.name);
132 | //=> 'bar'
133 | ```
134 |
135 | ### options.extend
136 |
137 | **Type**: `boolean`
138 |
139 | **Default**: `undefined`
140 |
141 | Used with [options.field](#options-field), pass ` true` if you want to extend a field that is already defined on the schema.
142 |
143 | ```js
144 | var pkg = config.normalize(require('./package'), {
145 | extend: true,
146 | fields: {
147 | name: {
148 | normalize: function() {
149 | return 'bar'
150 | }
151 | }
152 | }
153 | });
154 |
155 | console.log(pkg.name);
156 | //=> 'bar'
157 | ```
158 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-present, Jon Schlinkert
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # normalize-pkg [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [](https://www.npmjs.com/package/normalize-pkg) [](https://npmjs.org/package/normalize-pkg) [](https://npmjs.org/package/normalize-pkg) [](https://travis-ci.org/jonschlinkert/normalize-pkg)
2 |
3 | > Normalize values in package.json using the map-schema library.
4 |
5 | Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
6 |
7 | ## Table of Contents
8 |
9 |
10 | Details
11 |
12 | - [Install](#install)
13 | - [Install](#install-1)
14 | - [Usage](#usage)
15 | - [Features](#features)
16 | - [Schema](#schema)
17 | - [Defaults](#defaults)
18 | - [API](#api)
19 | - [Options](#options)
20 | * [options.knownOnly](#optionsknownonly)
21 | * [options.pick](#optionspick)
22 | * [options.omit](#optionsomit)
23 | * [options.fields](#optionsfields)
24 | * [options.extend](#optionsextend)
25 | - [About](#about)
26 |
27 |
28 |
29 | ## Install
30 |
31 | Install with [npm](https://www.npmjs.com/) (requires [Node.js](https://nodejs.org/en/) >= 0.10.0):
32 |
33 | ```sh
34 | $ npm install --save normalize-pkg
35 | ```
36 |
37 | ## Install
38 |
39 | Install with [bower](https://bower.io/)
40 |
41 | ```sh
42 | $ bower install normalize-pkg --save
43 | ```
44 |
45 | ## Usage
46 |
47 | ```js
48 | var config = require('./')();
49 | var pkg = config.normalize(require('./package'));
50 | ```
51 |
52 | ## Features
53 |
54 | Normalizes most package.json fields, and:
55 |
56 | * converts `repository` objects to a string
57 | * stringifies `author` object
58 | * stringifies each "person" object in `maintainers`, `contributors` and `collaborators`
59 | * converts `licenses` arrays and objects to a `license` string
60 | * removes files that don't exist from `bin`, `main` and the `files` array
61 | * adds `cli.js` to `bin` if it exists
62 | * creates `keywords` array from `name` if not defined
63 |
64 | See the [schema](lib/schema.js), [normalizers](lib/normalizers), and [unit tests](test) for more examples.
65 |
66 | ## Schema
67 |
68 | Values are normalized using a [schema](lib/schema.js) that is passed to [map-schema](https://github.com/jonschlinkert/map-schema).
69 |
70 | * only properties that have a corresponding field on the schema will be normalized.
71 | * any properties that do not have a corresponding field are returned unmodified.
72 |
73 | See the [.field docs](#field) to learn how to add or overwrite a field on the schema.
74 |
75 | ## Defaults
76 |
77 | A `default` value may optionally be defined when a `.field` is registered. When `.normalize` is run and a property that is required or recommended by npm is missing, `normalize-pkg` attempts to create the field if valid data can be found in the repository.
78 |
79 | built-in fields have a default value:
80 |
81 | * `version`: `'0.1.0'`
82 | * `license`: `'MIT'`
83 | * `engines`: `{node: '>= 0.10.0'}`
84 |
85 | For example:
86 |
87 | * `name`: the [project-name](https://github.com/jonschlinkert/project-name) library is used to fill in the name
88 | * `bin`: if empty, populated with `cli.js` or `bin` if either exists on the file system
89 |
90 | **Example**
91 |
92 | The following:
93 |
94 | ```js
95 | var config = require('./')();
96 |
97 | // no package.json is passed, just an empty object
98 | var pkg = config.normalize({});
99 | console.log(pkg);
100 | ```
101 |
102 | **Results**
103 |
104 | Since an empty object was passed, `normalize-pkg` was smart enough to fill in missing fields looking for info in the project. In this case, specifically from parsing `.git` config and using any defaults defined on the schema.
105 |
106 | ```js
107 | { name: 'normalize-pkg',
108 | version: '0.1.0',
109 | homepage: 'https://github.com/jonschlinkert/normalize-pkg',
110 | repository: 'jonschlinkert/normalize-pkg',
111 | license: 'MIT',
112 | files: [ 'index.js' ],
113 | main: 'index.js',
114 | engines: { node: '>= 0.10.0' } }
115 | ```
116 |
117 | ## API
118 |
119 | **Params**
120 |
121 | * `options` **{Object}**
122 |
123 | **Example**
124 |
125 | ```js
126 | const config = new NormalizePkg();
127 | const pkg = config.normalize({
128 | author: {
129 | name: 'Jon Schlinkert',
130 | url: 'https://github.com/jonschlinkert'
131 | }
132 | });
133 | console.log(pkg);
134 | //=> {author: 'Jon Schlinkert (https://github.com/jonschlinkert)'}
135 | ```
136 |
137 | * `normalize` **{Function}**: function to be called on the value when the `.normalize` method is called
138 | * `default` **{any}**: default value to be used when the package.json property is undefined.
139 | * `required` **{Boolean}**: define `true` if the property is required
140 |
141 | **Params**
142 |
143 | * `name` **{String}**: Field name (required)
144 | * `type` **{String|Array}**: One or more native javascript types allowed for the property value (required)
145 | * `options` **{Object}**
146 | * `returns` **{Object}**: Returns the instance
147 |
148 | **Example**
149 |
150 | ```js
151 | const config = new NormalizePkg();
152 |
153 | config.field('foo', 'string', {
154 | default: 'bar'
155 | });
156 |
157 | const pkg = config.normalize({});
158 | console.log(pkg);
159 | //=> {foo: 'bar'}
160 | ```
161 |
162 | **Params**
163 |
164 | * `pkg` **{Object}**: The `package.json` object to normalize
165 | * `options` **{Object}**
166 | * `returns` **{Object}**: Returns a normalized package.json object.
167 |
168 | **Example**
169 |
170 | ```js
171 | const config = new NormalizePkg();
172 | const pkg = config.normalize(require('./package.json'));
173 | ```
174 |
175 | ## Options
176 |
177 | ### options.knownOnly
178 |
179 | **Type**: `boolean`
180 |
181 | **Default**: `undefined`
182 |
183 | Omit properties from package.json that do not have a field registered on the schema.
184 |
185 | ```js
186 | var Config = require('normalize-pkg');
187 | var config = new Config({knownOnly: true});
188 |
189 | var pkg = config.normalize({name: 'my-project', foo: 'bar'});
190 | console.log(pkg);
191 | //=> {name: 'my-project'}
192 | ```
193 |
194 | ### options.pick
195 |
196 | **Type**: `array`
197 |
198 | **Default**: `undefined`
199 |
200 | Filter the resulting object to contain only the specified keys.
201 |
202 | ### options.omit
203 |
204 | **Type**: `array`
205 |
206 | **Default**: `undefined`
207 |
208 | Remove the specified keys from the resulting object.
209 |
210 | ### options.fields
211 |
212 | Pass a `fields` object on the options to customize any fields on the schema (also see [options.extend](#options-extend)):
213 |
214 | ```js
215 | var pkg = config.normalize(require('./package'), {
216 | extend: true,
217 | fields: {
218 | name: {
219 | normalize: function() {
220 | return 'bar'
221 | }
222 | }
223 | }
224 | });
225 |
226 | console.log(pkg.name);
227 | //=> 'bar'
228 | ```
229 |
230 | ### options.extend
231 |
232 | **Type**: `boolean`
233 |
234 | **Default**: `undefined`
235 |
236 | Used with [options.field](#options-field), pass `true` if you want to extend a field that is already defined on the schema.
237 |
238 | ```js
239 | var pkg = config.normalize(require('./package'), {
240 | extend: true,
241 | fields: {
242 | name: {
243 | normalize: function() {
244 | return 'bar'
245 | }
246 | }
247 | }
248 | });
249 |
250 | console.log(pkg.name);
251 | //=> 'bar'
252 | ```
253 |
254 | ## About
255 |
256 |
257 | Contributing
258 |
259 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
260 |
261 |
262 |
263 |
264 | Running Tests
265 |
266 | Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
267 |
268 | ```sh
269 | $ npm install && npm test
270 | ```
271 |
272 |
273 |
274 |
275 | Building docs
276 |
277 | _(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
278 |
279 | To generate the readme, run the following command:
280 |
281 | ```sh
282 | $ npm install -g verbose/verb#dev verb-generate-readme && verb
283 | ```
284 |
285 |
286 |
287 | ### Related projects
288 |
289 | You might also be interested in these projects:
290 |
291 | [update](https://www.npmjs.com/package/update): Be scalable! Update is a new, open source developer framework and CLI for automating updates… [more](https://github.com/update/update) | [homepage](https://github.com/update/update "Be scalable! Update is a new, open source developer framework and CLI for automating updates of any kind in code projects.")
292 |
293 | ### Contributors
294 |
295 | | **Commits** | **Contributor** |
296 | | --- | --- |
297 | | 154 | [jonschlinkert](https://github.com/jonschlinkert) |
298 | | 16 | [doowb](https://github.com/doowb) |
299 | | 2 | [pdehaan](https://github.com/pdehaan) |
300 |
301 | ### Author
302 |
303 | **Jon Schlinkert**
304 |
305 | * [GitHub Profile](https://github.com/jonschlinkert)
306 | * [Twitter Profile](https://twitter.com/jonschlinkert)
307 | * [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
308 |
309 | ### License
310 |
311 | Copyright © 2020, [Jon Schlinkert](https://github.com/jonschlinkert).
312 | Released under the [MIT License](LICENSE).
313 |
314 | ***
315 |
316 | _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on March 01, 2020._
--------------------------------------------------------------------------------
/bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const path = require('path');
4 | const argv = require('minimist')(process.argv.slice(2));
5 | const writeJson = require('write-json');
6 | const Normalizer = require('..');
7 | const config = new Normalizer();
8 |
9 | /**
10 | * Optionally specific a destination path
11 | */
12 |
13 | const dest = argv.dest || argv.d || 'package.json';
14 |
15 | /**
16 | * Write the file
17 | */
18 |
19 | writeJson(dest, config.normalize(), err => {
20 | if (err) {
21 | console.error(err);
22 | process.exit(1);
23 | }
24 | console.log('done');
25 | });
26 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "normalize-pkg",
3 | "description": "Normalize values in package.json.",
4 | "repository": "jonschlinkert/normalize-pkg",
5 | "license": "MIT",
6 | "homepage": "https://github.com/jonschlinkert/normalize-pkg",
7 | "authors": [
8 | "Jon Schlinkert (https://github.com/jonschlinkert)"
9 | ],
10 | "main": [
11 | "index.js"
12 | ],
13 | "dependencies": {
14 | "arr-union": "^3.1.0",
15 | "array-unique": "^0.2.1",
16 | "component-emitter": "^1.2.0",
17 | "define-property": "^0.2.5",
18 | "export-files": "^2.1.1",
19 | "get-value": "^2.0.3",
20 | "is-primitive": "^2.0.0",
21 | "kind-of": "^3.0.2",
22 | "lazy-cache": "^1.0.3",
23 | "map-schema": "^0.2.1",
24 | "minimist": "^1.2.0",
25 | "mixin-deep": "^1.1.3",
26 | "omit-empty": "^0.3.3",
27 | "parse-git-config": "^0.4.0",
28 | "parse-github-url": "^0.3.0",
29 | "project-name": "^0.2.4",
30 | "remote-origin-url": "^0.5.1",
31 | "resolve-dir": "^0.1.0",
32 | "semver": "^5.1.0",
33 | "stringify-author": "^0.1.3",
34 | "write-json": "^0.2.2"
35 | },
36 | "devDependencies": {
37 | "delete": "^0.3.0",
38 | "gitty": "^3.3.4",
39 | "gulp": "^3.9.1",
40 | "gulp-eslint": "^2.0.0",
41 | "gulp-format-md": "^0.1.7",
42 | "gulp-istanbul": "^0.10.3",
43 | "gulp-mocha": "^2.2.0",
44 | "mocha": "^2.4.5"
45 | },
46 | "keywords": [
47 | "config",
48 | "fix",
49 | "json",
50 | "normalize",
51 | "package",
52 | "package-json",
53 | "pkg",
54 | "properties",
55 | "values"
56 | ]
57 | }
58 |
--------------------------------------------------------------------------------
/example.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Normalizer = require('./');
4 | const config = new Normalizer();
5 |
6 | console.log(JSON.stringify(config.normalize(require('./test/fixtures/people')), null, 2));
7 |
8 | console.log(JSON.stringify(config.normalize(require('./test/fixtures/bin'), {
9 | only: ['bin', 'name']
10 | }), null, 2));
11 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const Events = require('events');
5 | const schema = require('./lib/schema');
6 | const utils = require('./lib/utils');
7 |
8 | /**
9 | * Create an instance of `NormalizePkg` with the given `options`.
10 | *
11 | * ```js
12 | * const config = new NormalizePkg();
13 | * const pkg = config.normalize({
14 | * author: {
15 | * name: 'Jon Schlinkert',
16 | * url: 'https://github.com/jonschlinkert'
17 | * }
18 | * });
19 | * console.log(pkg);
20 | * //=> {author: 'Jon Schlinkert (https://github.com/jonschlinkert)'}
21 | * ```
22 | * @param {Object} `options`
23 | * @api public
24 | */
25 |
26 | class NormalizePkg extends Events {
27 | constructor(options) {
28 | super();
29 | this.options = { ...options };
30 | this.schema = schema(this.options);
31 | this.data = this.schema.data;
32 | this.schema.on('warning', this.emit.bind(this, 'warning'));
33 | this.schema.on('error', this.emit.bind(this, 'error'));
34 |
35 | this.schema.union = (key, config, arr) => {
36 | config[key] = utils.arrayify(config[key]);
37 | config[key] = utils.union([], config[key], utils.arrayify(arr));
38 | };
39 | }
40 |
41 | /**
42 | * Add a field to the schema, or overwrite or extend an existing field. The last
43 | * argument is an `options` object that supports the following properties:
44 | *
45 | * - `normalize` **{Function}**: function to be called on the value when the `.normalize` method is called
46 | * - `default` **{any}**: default value to be used when the package.json property is undefined.
47 | * - `required` **{Boolean}**: define `true` if the property is required
48 | *
49 | * ```js
50 | * const config = new NormalizePkg();
51 | *
52 | * config.field('foo', 'string', {
53 | * default: 'bar'
54 | * });
55 | *
56 | * const pkg = config.normalize({});
57 | * console.log(pkg);
58 | * //=> {foo: 'bar'}
59 | * ```
60 | *
61 | * @param {String} `name` Field name (required)
62 | * @param {String|Array} `type` One or more native javascript types allowed for the property value (required)
63 | * @param {Object} `options`
64 | * @return {Object} Returns the instance
65 | * @api public
66 | */
67 |
68 | field(field, type, options) {
69 | if (typeof options === 'function') {
70 | options = { normalize: options };
71 | }
72 | options = options || {};
73 | if (options.extend === true) {
74 | options = utils.merge({}, this.schema.get(field), options);
75 | }
76 | this.schema.field(field, type, options);
77 | return this;
78 | }
79 |
80 | /**
81 | * Iterate over `pkg` properties and normalize values that have corresponding
82 | * [fields](#field) registered on the schema.
83 | *
84 | * ```js
85 | * const config = new NormalizePkg();
86 | * const pkg = config.normalize(require('./package.json'));
87 | * ```
88 | * @param {Object} `pkg` The `package.json` object to normalize
89 | * @param {Object} `options`
90 | * @return {Object} Returns a normalized package.json object.
91 | * @api public
92 | */
93 |
94 | normalize(pkg, options) {
95 | if (typeof pkg === 'undefined') {
96 | pkg = path.resolve(process.cwd(), 'package.json');
97 | }
98 | if (typeof pkg === 'string') {
99 | pkg = utils.requirePackage(pkg);
100 | }
101 |
102 | if (options && options.fields) {
103 | const fields = options.fields;
104 | delete options.fields;
105 |
106 | for (const key in fields) {
107 | if (fields.hasOwnProperty(key)) {
108 | const val = utils.merge({}, options, fields[key]);
109 | this.field(key, val.type, val);
110 | }
111 | }
112 | }
113 |
114 | this.schema.options = utils.merge({}, this.schema.options, options);
115 | const obj = this.schema.normalize(pkg, this.schema.options);
116 | this.schema.emit('normalized', obj);
117 | this.emit('normalized', obj);
118 | return obj;
119 | }
120 | }
121 |
122 | /**
123 | * NormalizePkg
124 | */
125 |
126 | module.exports = NormalizePkg;
127 |
--------------------------------------------------------------------------------
/lib/keys.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = [
4 | 'name',
5 | 'private',
6 | 'description',
7 | 'version',
8 | 'homepage',
9 |
10 | 'author',
11 | 'authors',
12 | 'maintainers',
13 | 'contributors',
14 | 'collaborators',
15 |
16 | 'repository',
17 | 'bugs',
18 |
19 | 'license',
20 | 'licenses',
21 |
22 | 'files',
23 | 'main',
24 | 'typings',
25 | 'types',
26 | 'preferGlobal',
27 | 'bin',
28 | 'engines',
29 | 'scripts',
30 | 'dependencies',
31 | 'devDependencies',
32 | 'keywords'
33 | ];
34 |
--------------------------------------------------------------------------------
/lib/merge.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const keys = require('./keys');
4 | const { pick, merge } = require('./utils');
5 |
6 | module.exports = function(config, schema) {
7 | if (schema.isMerged) return;
8 |
9 | schema.checked = schema.checked || {};
10 | schema.isMerged = true;
11 |
12 | // shallow clone schema.data
13 | const schemaOpts = pick(schema.options, keys);
14 | const data = Object.assign({}, schema.data);
15 | const obj = merge({}, config, data, schemaOpts);
16 | merge(config, obj);
17 | };
18 |
--------------------------------------------------------------------------------
/lib/normalizers/bin.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 | const utils = require('../utils');
6 | const merge = require('../merge');
7 |
8 | module.exports = function(bin, key, config, schema) {
9 | merge(config, schema);
10 |
11 | if (schema.checked[key]) {
12 | return bin;
13 | }
14 |
15 | const opts = utils.merge({}, schema.options);
16 | if (opts.bin === false) {
17 | bin = schema.data.get('bin') || config.bin || bin;
18 | if (typeof bin === 'string') {
19 | schema.union('files', config, bin);
20 | }
21 | schema.checked[key] = true;
22 | return bin;
23 | }
24 |
25 | if (typeof bin === 'string') {
26 | schema.union('files', config, bin);
27 | schema.checked[key] = true;
28 | return bin;
29 | }
30 |
31 | if (typeof bin === 'undefined') {
32 | bin = {};
33 | }
34 |
35 | // ensure `name` is defined before continuing
36 | schema.update('name', config);
37 |
38 | const obj = {};
39 | let num = 0;
40 |
41 | if (utils.isObject(bin)) {
42 | for (var prop in bin) {
43 | if (utils.exists(bin[prop])) {
44 | obj[prop] = bin[prop];
45 | num++;
46 | }
47 | }
48 | bin = obj;
49 | }
50 |
51 | // add cli.js or "bin/" if they exist
52 | const dir = path.resolve(process.cwd(), 'bin');
53 | if (num === 0 && utils.exists(dir)) {
54 | fs.readdirSync(dir).forEach(function(fp) {
55 | bin[config.name] = path.relative(process.cwd(), path.join(dir, fp));
56 | num++;
57 | });
58 | }
59 |
60 | if (num === 0 && utils.exists(path.resolve(process.cwd(), 'cli.js'))) {
61 | bin[config.name] = 'cli.js';
62 | }
63 |
64 | if (!utils.isEmpty(bin)) {
65 | if (typeof bin === 'string') {
66 | schema.union('files', config, bin);
67 | }
68 |
69 | config[key] = bin;
70 | schema.checked[key] = true;
71 | return bin;
72 | }
73 |
74 | schema.omit(key);
75 | return;
76 | };
77 |
--------------------------------------------------------------------------------
/lib/normalizers/bugs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getOwner = require('./helpers/owner');
4 | const utils = require('../utils');
5 | const merge = require('../merge');
6 |
7 | module.exports = function(val, key, config, schema) {
8 | merge(config, schema);
9 |
10 | val = val || config[key];
11 | if (schema.checked[key]) {
12 | return val;
13 | }
14 |
15 | let owner = config.owner;
16 | if (!utils.isString(owner)) {
17 | owner = getOwner(val, key, config, schema);
18 | }
19 |
20 | if (utils.isObject(val) && utils.isString(val.url) && hasOwner(owner, val.url)) {
21 | val = config[key] = { url: utils.repo.issues(utils.repo.homepage(val.url)) };
22 | return val;
23 | }
24 |
25 | schema.update('repository', config);
26 | if (utils.isString(config.repository) && hasOwner(owner, config.repository)) {
27 | return { url: utils.repo.issues(config.repository) };
28 | }
29 |
30 | if (utils.isString(config.homepage) && hasOwner(owner, config.homepage)) {
31 | return { url: utils.repo.issues(config.homepage) };
32 | }
33 | };
34 |
35 | function hasOwner(owner, str) {
36 | return str.indexOf(owner + '/') !== -1;
37 | }
38 |
--------------------------------------------------------------------------------
/lib/normalizers/engineStrict.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(val, key, config, schema) {
4 | if (typeof val === 'boolean') {
5 | schema.warning('deprecated', key, { actual: key, expected: 'engine-strict' });
6 | config['engine-strict'] = val;
7 | }
8 | schema.omit(key);
9 | };
10 |
--------------------------------------------------------------------------------
/lib/normalizers/files.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const utils = require('../utils');
5 | const merge = require('../merge');
6 |
7 | module.exports = function(files, key, config, schema) {
8 | merge(config, schema);
9 |
10 | files = files || config[key];
11 | if (schema.checked[key]) {
12 | return files;
13 | }
14 |
15 | files = utils.arrayify(files).filter(Boolean);
16 | files = utils.union([], files, config.files);
17 | const opts = utils.merge({}, schema.options);
18 |
19 | const len = files.length;
20 | let idx = -1;
21 | const res = Array.isArray(opts.files) ? opts.files : [];
22 |
23 | while (++idx < len) {
24 | const file = files[idx];
25 | if (utils.exists(path.resolve(process.cwd(), file))) {
26 | utils.union(res, utils.stripSlash(file));
27 | }
28 | }
29 |
30 | // commond directories
31 | addPath(res, 'lib', opts, config);
32 | addPath(res, 'dist', opts, config);
33 | addPath(res, 'bin', opts, config);
34 |
35 | // common files
36 | addPath(res, 'index.js', opts, config);
37 | addPath(res, 'utils.js', opts, config);
38 | addPath(res, 'cli.js', opts, config);
39 |
40 | if (/^(generate|verb|assemble|updater)-/.test(config.name)) {
41 | addPath(res, 'updatefile.js', opts, config);
42 | addPath(res, 'generator.js', opts, config);
43 | addPath(res, 'templates', opts, config);
44 | }
45 |
46 | if (res.length) {
47 | res.sort();
48 | config[key] = res;
49 | schema.update('bin', config);
50 | schema.checked[key] = true;
51 | return res;
52 | }
53 |
54 | // don't use `omit`, so the key can be re-added if needed
55 | delete config[key];
56 | return;
57 | };
58 |
59 | function addPath(files, file, opts, config) {
60 | if (Array.isArray(opts.files) && opts.files.indexOf(file) === -1) {
61 | return;
62 | }
63 | if (files.indexOf(file) !== -1) {
64 | return;
65 | }
66 | if (utils.exists(path.resolve(process.cwd(), file))) {
67 | utils.union(files, file);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib/normalizers/helpers/git.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../../utils');
4 |
5 | module.exports = function(val, key, config, schema) {
6 | let git = schema.data.get('git');
7 | if (git) return git;
8 |
9 | git = tryGitConfig();
10 | if (utils.isObject(git)) {
11 | schema.data.set('git', git);
12 | return git;
13 | }
14 | };
15 |
16 | function tryGitConfig() {
17 | try {
18 | const git = utils.repo.gitConfig({ type: 'local' })
19 | || utils.repo.gitConfig({ type: 'global' });
20 |
21 | return parseKeys(git);
22 | } catch (err) {}
23 | }
24 |
25 | function parseKeys(git) {
26 | return utils.merge({}, git, utils.parseGitConfig.expandKeys(git));
27 | }
28 |
--------------------------------------------------------------------------------
/lib/normalizers/helpers/owner.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../../utils');
4 | const git = require('./git');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | let owner = config.owner;
8 | let url = val;
9 |
10 | if (utils.isObject(url)) {
11 | url = val.url;
12 | }
13 |
14 | let repo = config.repository;
15 | if (utils.isObject(repo) && repo.url) {
16 | repo = repo.url;
17 | }
18 |
19 | let obj;
20 | if (utils.isString(url)) {
21 | obj = utils.repo.parseUrl(url);
22 | schema.data.set('owner', obj.owner);
23 | return obj.owner;
24 | }
25 |
26 | if (utils.isString(repo)) {
27 | obj = utils.repo.parseUrl(repo);
28 | schema.data.set('owner', obj.owner);
29 | return obj.owner;
30 | }
31 |
32 | const parsed = git(val, key, config, schema);
33 | if (utils.isObject(parsed)) {
34 | schema.data.set('git', parsed);
35 | owner = parsed.user && parsed.user.name;
36 |
37 | if (owner) {
38 | schema.data.set('owner', owner);
39 | return owner;
40 | }
41 | }
42 | };
43 |
--------------------------------------------------------------------------------
/lib/normalizers/homepage.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getOwner = require('./helpers/owner');
4 | const utils = require('../utils');
5 | const merge = require('../merge');
6 |
7 | module.exports = function(val, key, config, schema) {
8 | merge(config, schema);
9 | let res;
10 |
11 | val = val || config[key];
12 | if (utils.isString(val) && /:\/\//.test(val)) {
13 | return val;
14 | }
15 |
16 | schema.update('repository', config);
17 |
18 | if (utils.isString(config.repository)) {
19 | res = utils.repo.homepage(config.repository);
20 | schema.checked[key] = true;
21 | return res;
22 | }
23 |
24 | let owner = config.owner;
25 | if (!utils.isString(owner)) {
26 | owner = getOwner(val, key, config, schema);
27 | }
28 |
29 | if (utils.isString(owner) && utils.isString(config.name)) {
30 | res = utils.repo.homepage(owner + '/' + config.name);
31 | schema.checked[key] = true;
32 | return res;
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/lib/normalizers/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('export-files')(__dirname);
4 |
--------------------------------------------------------------------------------
/lib/normalizers/keywords.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 | const merge = require('../merge');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | merge(config, schema);
8 |
9 | val = utils.arrayify(val || config[key]);
10 | if (schema.checked[key]) {
11 | return val;
12 | }
13 |
14 | if (val.length === 0) {
15 | schema.update('name', config);
16 | val = config[key] = config.name.split(/\W+/).filter(Boolean);
17 | }
18 |
19 | const res = utils.unique(val).sort();
20 | schema.checked[key] = true;
21 | return res;
22 | };
23 |
24 |
--------------------------------------------------------------------------------
/lib/normalizers/license.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 | const merge = require('../merge');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | merge(config, schema);
8 | val = val || config[key];
9 |
10 | switch (utils.typeOf(val)) {
11 | case 'object':
12 | return val.type;
13 | case 'array':
14 | return val[0].type;
15 | case 'string':
16 | default: {
17 | return val;
18 | }
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/lib/normalizers/licenses.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const license = require('./license');
4 | const merge = require('../merge');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | merge(config, schema);
8 | if (Array.isArray(val)) {
9 | schema.warning('deprecated', key, { actual: key, expected: 'license' });
10 | schema.update('license', val[0].type, config);
11 | delete config[key];
12 | } else {
13 | delete config[key];
14 | return license(val, 'license', config, schema);
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/lib/normalizers/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 | const merge = require('../merge');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | merge(config, schema);
8 | val = val || config[key];
9 |
10 | if (typeof val === 'undefined') {
11 | val = 'index.js';
12 | }
13 |
14 | if (!utils.exists(val)) {
15 | delete config[key];
16 | return;
17 | }
18 |
19 | schema.update('files', config);
20 | schema.union('files', config, val);
21 | return val;
22 | };
23 |
--------------------------------------------------------------------------------
/lib/normalizers/name.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 | const merge = require('../merge');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | merge(config, schema);
8 | val = val || config[key];
9 |
10 | if (utils.isString(val)) {
11 | return val;
12 | }
13 |
14 | if (schema.checked[key]) {
15 | return val;
16 | }
17 |
18 | schema.update('repository', config);
19 | const res = config.name || utils.repo.name(process.cwd());
20 | schema.checked[key] = true;
21 | return res;
22 | };
23 |
--------------------------------------------------------------------------------
/lib/normalizers/person.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 | const merge = require('../merge');
5 |
6 | /**
7 | * Stringify a person object, or array of person objects, such as
8 | * `maintainer`, `collaborator`, `contributor`, and `author`.
9 | *
10 | * @param {Object|Array|String} `val` If an object is passed, it will be converted to a string. If an array of objects is passed, it will be converted to an array of strings.
11 | * @return {String}
12 | * @api public
13 | */
14 |
15 | module.exports = function person(val, key, config, schema) {
16 | merge(config, schema);
17 |
18 | if (Array.isArray(val)) {
19 | val = val.map(str => person(str, key, config, schema));
20 | }
21 |
22 | if (utils.isObject(val)) {
23 | val = utils.stringify(val);
24 | }
25 |
26 | return val;
27 | };
28 |
--------------------------------------------------------------------------------
/lib/normalizers/repository.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const git = require('./helpers/git');
4 | const getOwner = require('./helpers/owner');
5 | const utils = require('../utils');
6 | const merge = require('../merge');
7 |
8 | module.exports = function(val, key, config, schema) {
9 | merge(config, schema);
10 | let owner = config.owner;
11 |
12 | val = val || config[key];
13 | if (schema.checked[key]) {
14 | return val;
15 | }
16 |
17 | if (utils.isObject(val) && val.url) {
18 | val = val.url;
19 | }
20 |
21 | if (!utils.isString(val)) {
22 | const parsed = git(val, key, config, schema);
23 | const remote = utils.get(parsed, 'remote.origin.url');
24 |
25 | if (parsed.user && parsed.user.username) {
26 | owner = parsed.user.username;
27 | config.owner = owner;
28 | schema.checked.owner = true;
29 | }
30 |
31 | if (remote) {
32 | const expanded = utils.repo.expandUrl(remote);
33 | const data = utils.merge({}, expanded, config);
34 | utils.merge(config, data);
35 | schema.data.merge(data);
36 | }
37 | }
38 |
39 | if (!utils.isString(val) && config.homepage) {
40 | val = config.homepage;
41 | }
42 |
43 | if (!owner) {
44 | owner = getOwner(val, key, config, schema);
45 | }
46 | if (config.name && owner) {
47 | val = owner + '/' + config.name;
48 | }
49 |
50 | if (utils.isString(val)) {
51 | schema.checked[key] = true;
52 | return utils.repo.repository(val);
53 | }
54 |
55 | // if not returned already, val is invalid
56 | delete config[key];
57 | return;
58 | };
59 |
--------------------------------------------------------------------------------
/lib/normalizers/scripts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 | const merge = require('../merge');
5 |
6 | module.exports = function(val, key, config, schema) {
7 | merge(config, schema);
8 | val = val || config[key];
9 |
10 | if (utils.isObject(val) && utils.isString(val.test) && /mocha -R \w+$/.test(val.test)) {
11 | val.test = 'mocha';
12 | }
13 | return val;
14 | };
15 |
--------------------------------------------------------------------------------
/lib/normalizers/typings.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const glob = require('matched');
4 | const utils = require('../utils');
5 |
6 | /**
7 | * TypeScript declarations
8 | */
9 |
10 | module.exports = function(val, key, config, schema) {
11 | val = val || config[key];
12 |
13 | if (typeof val === 'undefined') {
14 | const files = glob.sync('*.d.ts', { cwd: process.cwd() });
15 | if (files.length) {
16 | val = files[0];
17 | }
18 | }
19 |
20 | if (!utils.exists(val)) {
21 | delete config[key];
22 | return;
23 | }
24 |
25 | config[key] = val;
26 | return val;
27 | };
28 |
--------------------------------------------------------------------------------
/lib/schema.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Schema = require('map-schema');
4 | const normalizers = require('./normalizers');
5 | const validators = require('./validators');
6 | const utils = require('./utils');
7 | const keys = require('./keys');
8 |
9 | /**
10 | * Normalize package.json using a schema.
11 | */
12 |
13 | module.exports = options => {
14 | const opts = Object.assign({}, options);
15 | const omit = utils.arrayify(opts.omit);
16 | const config = Object.assign({}, opts, { keys: keys, omit: omit });
17 |
18 | const schema = new Schema(config)
19 | .field('name', ['string'], {
20 | validate: validators.name,
21 | normalize: normalizers.name,
22 | required: true
23 | })
24 | .field('private', 'boolean')
25 | .field('description', 'string')
26 | .field('version', 'string', {
27 | validate: validators.version,
28 | default: '0.1.0',
29 | required: true
30 | })
31 | .field('homepage', 'string', {
32 | normalize: normalizers.homepage
33 | })
34 |
35 | /**
36 | * Person fields
37 | */
38 |
39 | .field('author', ['object', 'string'], { normalize: normalizers.person })
40 | .field('authors', 'array', { normalize: normalizers.person })
41 | .field('maintainers', 'array', { normalize: normalizers.person })
42 | .field('contributors', 'array', { normalize: normalizers.person })
43 | .field('collaborators', 'array', { normalize: normalizers.person })
44 |
45 | /**
46 | * Bugs, repo and license
47 | */
48 |
49 | .field('bugs', ['object', 'string'], {
50 | normalize: normalizers.bugs
51 | })
52 | .field('repository', ['object', 'string'], {
53 | normalize: normalizers.repository
54 | })
55 | .field('license', 'string', {
56 | normalize: normalizers.license,
57 | default: 'MIT'
58 | })
59 | .field('licenses', ['array', 'object'], {
60 | normalize: normalizers.licenses,
61 | validate: validators.licenses
62 | })
63 |
64 | /**
65 | * Files, main
66 | */
67 |
68 | .field('files', 'array', {
69 | normalize: normalizers.files
70 | })
71 | .field('main', 'string', {
72 | normalize: normalizers.main,
73 | validate: function(filepath) {
74 | return utils.exists(filepath);
75 | }
76 | })
77 | .field('types', 'string', {
78 | normalize: normalizers.typings
79 | })
80 | .field('typings', 'string', {
81 | normalize: normalizers.typings
82 | })
83 |
84 | /**
85 | * Scripts, binaries and related
86 | */
87 |
88 | .field('preferGlobal', 'boolean', {
89 | validate: validators.preferGlobal
90 | })
91 | .field('bin', ['object', 'string'], {
92 | normalize: normalizers.bin
93 | })
94 | .field('scripts', 'object', {
95 | normalize: normalizers.scripts
96 | })
97 |
98 | /**
99 | * Engine
100 | */
101 |
102 | .field('engines', 'object', {
103 | default: { node: '>= 0.10.0' }
104 | })
105 | .field('engine-strict', 'boolean', {
106 | validate: validators['engine-strict']
107 | })
108 | .field('engineStrict', 'boolean', {
109 | normalize: normalizers.engineStrict
110 | })
111 |
112 | /**
113 | * Dependencies
114 | */
115 |
116 | .field('dependencies', 'object')
117 | .field('devDependencies', 'object')
118 | .field('peerDependencies', 'object')
119 | .field('optionalDependencies', 'object')
120 |
121 | /**
122 | * Project metadata
123 | */
124 |
125 | .field('man', ['array', 'string'])
126 | .field('keywords', 'array', {
127 | normalize: normalizers.keywords
128 | });
129 |
130 | // Add fields defined on `options.fields`
131 | schema.addFields(opts);
132 | return schema;
133 | };
134 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const { defineProperty } = Reflect;
4 | const fs = require('fs');
5 | const path = require('path');
6 |
7 | const define = (obj, key, fn) => {
8 | defineProperty(obj, key, { get: fn });
9 | };
10 |
11 | /**
12 | * Lazily required module depedencies
13 | */
14 |
15 | define(exports, 'union', () => require('arr-union'));
16 | define(exports, 'get', () => require('get-value'));
17 | define(exports, 'typeOf', () => require('kind-of'));
18 | define(exports, 'merge', () => require('mixin-deep'));
19 | define(exports, 'pick', () => require('object.pick'));
20 | define(exports, 'omitEmpty', () => require('omit-empty'));
21 | define(exports, 'parseGitConfig', () => require('parse-git-config'));
22 | define(exports, 'repo', () => require('repo-utils'));
23 | define(exports, 'semver', () => require('semver'));
24 | define(exports, 'stringify', () => require('stringify-author'));
25 |
26 | /**
27 | * Return true if `val` is empty
28 | */
29 |
30 | exports.isEmpty = val => {
31 | return Object.keys(exports.omitEmpty(val)).length === 0;
32 | };
33 |
34 | exports.unique = value => {
35 | return [...new Set([].concat(value))];
36 | };
37 |
38 | exports.exists = filepath => fs.existsSync(filepath);
39 |
40 | /**
41 | * Return true if `val` is an object
42 | */
43 |
44 | exports.isObject = val => {
45 | return exports.typeOf(val) === 'object';
46 | };
47 |
48 | /**
49 | * Return true if `val` is a string with a non-zero length
50 | */
51 |
52 | exports.isString = val => {
53 | return val && typeof val === 'string';
54 | };
55 |
56 | /**
57 | * Cast `val` to an array
58 | */
59 |
60 | exports.arrayify = val => {
61 | return val ? (Array.isArray(val) ? val : [val]) : [];
62 | };
63 |
64 | /**
65 | * Try to require the package.json at the given filepath
66 | */
67 |
68 | exports.requirePackage = filepath => {
69 | filepath = path.resolve(filepath);
70 | try {
71 | var stat = fs.statSync(filepath);
72 | if (stat.isDirectory()) {
73 | filepath = path.join(filepath, 'package.json');
74 | } else if (!/package\.json$/.test(filepath)) {
75 | filepath = path.join(path.dirname(filepath), 'package.json');
76 | }
77 | return require(filepath);
78 | } catch (err) {}
79 | return {};
80 | };
81 |
82 | /**
83 | * Strip a trailing slash from a string.
84 | *
85 | * @param {String} `str`
86 | * @return {String}
87 | */
88 |
89 | exports.stripSlash = str => str.replace(/\W+$/, '');
90 |
--------------------------------------------------------------------------------
/lib/validators/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('export-files')(__dirname);
4 |
--------------------------------------------------------------------------------
/lib/validators/name.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(val) {
4 | return val && typeof val === 'string';
5 | };
6 |
--------------------------------------------------------------------------------
/lib/validators/preferGlobal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(val, key, config, schema) {
4 | schema.update('bin', config);
5 | if (!config.hasOwnProperty('bin') && val === true) {
6 | schema.warning('custom', key, 'expected "bin" to be defined when "preferGlobal" is true');
7 | }
8 | return val === true;
9 | };
10 |
--------------------------------------------------------------------------------
/lib/validators/version.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('../utils');
4 |
5 | module.exports = function(val) {
6 | if (utils.semver.valid(val) === null) {
7 | throw new Error('invalid semver version "' + val + '" defined in package.json');
8 | }
9 | return true;
10 | };
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "normalize-pkg",
3 | "description": "Normalize values in package.json using the map-schema library.",
4 | "version": "0.5.0",
5 | "homepage": "https://github.com/jonschlinkert/normalize-pkg",
6 | "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
7 | "contributors": [
8 | "Brian Woodward (https://twitter.com/doowb)",
9 | "Jon Schlinkert (http://twitter.com/jonschlinkert)",
10 | "Peter deHaan (http://about.me/peterdehaan)"
11 | ],
12 | "funding": "https://github.com/sponsors/jonschlinkert",
13 | "repository": "jonschlinkert/normalize-pkg",
14 | "bugs": {
15 | "url": "https://github.com/jonschlinkert/normalize-pkg/issues"
16 | },
17 | "license": "MIT",
18 | "files": [
19 | "bin",
20 | "index.js",
21 | "lib"
22 | ],
23 | "main": "index.js",
24 | "bin": {
25 | "normalize-pkg": "bin/cli.js"
26 | },
27 | "engines": {
28 | "node": ">=10"
29 | },
30 | "scripts": {
31 | "test": "mocha"
32 | },
33 | "dependencies": {
34 | "arr-union": "^3.1.0",
35 | "export-files": "^2.1.1",
36 | "get-value": "^3.0.1",
37 | "kind-of": "^6.0.3",
38 | "map-schema": "^0.3.0",
39 | "matched": "^5.0.0",
40 | "minimist": "^1.2.0",
41 | "mixin-deep": "^2.0.1",
42 | "object.pick": "^1.3.0",
43 | "omit-empty": "^1.0.0",
44 | "parse-git-config": "^3.0.0",
45 | "repo-utils": "^0.4.1",
46 | "semver": "^7.1.3",
47 | "stringify-author": "^0.1.3",
48 | "write-json": "^3.0.1"
49 | },
50 | "devDependencies": {
51 | "delete": "^1.1.0",
52 | "gitty": "^3.7.1",
53 | "gulp-format-md": "^2.0.0",
54 | "mocha": "^7.1.0"
55 | },
56 | "keywords": [
57 | "config",
58 | "fix",
59 | "json",
60 | "normalize",
61 | "package",
62 | "package-json",
63 | "pkg",
64 | "properties",
65 | "values"
66 | ],
67 | "verb": {
68 | "run": true,
69 | "toc": "collapsible",
70 | "layout": "default",
71 | "tasks": [
72 | "readme"
73 | ],
74 | "plugins": [
75 | "gulp-format-md"
76 | ],
77 | "related": {
78 | "list": [
79 | "update"
80 | ]
81 | },
82 | "reflinks": [
83 | "map-schema",
84 | "project-name",
85 | "verb",
86 | "verb-readme-generator"
87 | ],
88 | "lint": {
89 | "reflinks": true
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/test/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../.eslintrc.json"
4 | ],
5 | "env": {
6 | "mocha": true
7 | }
8 | }
--------------------------------------------------------------------------------
/test/actual/normalized.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "foo",
3 | "version": "0.4.11",
4 | "description": "Create new Assemble projects.",
5 | "homepage": "https://github.com/assemble/generator-assemble",
6 | "main": "app/index.js",
7 | "scripts": {
8 | "test": "mocha --reporter spec"
9 | }
10 | }
--------------------------------------------------------------------------------
/test/fixtures/author-condensed.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "normalize-pkg",
3 | "private": true,
4 | "version": "0.1.0",
5 | "homepage": "https://github.com/jonschlinkert/normalize-pkg",
6 | "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
7 | "repository": "jonschlinkert/normalize-pkg",
8 | "license": "MIT",
9 | "files": [
10 | "index.js"
11 | ],
12 | "main": "index.js",
13 | "engines": {
14 | "node": ">= 0.10.0"
15 | },
16 | "keywords": [
17 | "normalize",
18 | "pkg"
19 | ]
20 | }
--------------------------------------------------------------------------------
/test/fixtures/authors-condensed.json:
--------------------------------------------------------------------------------
1 | {
2 | "authors": [
3 | "Brian Woodward (https://github.com/doowb)",
4 | "Jon Schlinkert (https://github.com/jonschlinkert)"
5 | ]
6 | }
--------------------------------------------------------------------------------
/test/fixtures/bin.json:
--------------------------------------------------------------------------------
1 | {
2 | }
--------------------------------------------------------------------------------
/test/fixtures/engine-strict.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expand-pkg",
3 | "private": true,
4 | "engineStrict": true,
5 | "keywords": [
6 | "package-json",
7 | "config",
8 | "values",
9 | "fix",
10 | "json",
11 | "pkg",
12 | "normalize",
13 | "package",
14 | "properties"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/test/fixtures/licenses.json:
--------------------------------------------------------------------------------
1 | {
2 | "licenses": [
3 | {
4 | "type": "Blah",
5 | "url": "foo"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/test/fixtures/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "main": null
3 | }
--------------------------------------------------------------------------------
/test/fixtures/missing.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "foo",
3 | "private": true,
4 | "version": "0.4.11",
5 | "description": "Create new Assemble projects.",
6 | "homepage": "https://github.com/assemble/generator-assemble",
7 | "main": "app/index.js",
8 | "scripts": {
9 | "test": "mocha --reporter spec"
10 | }
11 | }
--------------------------------------------------------------------------------
/test/fixtures/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expand-pkg",
3 | "private": true,
4 | "description": "Normalize values in package.json to improve compatibility, programmatic readability and usefulness with third party libs.",
5 | "version": "0.2.5",
6 | "homepage": "https://github.com/jonschlinkert/expand-pkg/",
7 | "author": {
8 | "name": "Jon Schlinkert",
9 | "url": "https://github.com/jonschlinkert"
10 | },
11 | "repository": {
12 | "url": "https://github.com/jonschlinkert/expand-pkg.git"
13 | },
14 | "bugs": {
15 | "url": "https://github.com/jonschlinkert/expand-pkg/issues"
16 | },
17 | "license": "MIT",
18 | "files": [
19 | "index.js",
20 | "lib"
21 | ],
22 | "engines": {
23 | "node": ">= 0.10.0"
24 | },
25 | "scripts": {
26 | "test": "mocha"
27 | },
28 | "dependencies": {
29 | "array-unique": "^0.2.1",
30 | "define-property": "^0.2.5",
31 | "expand": "^0.3.2",
32 | "extend-shallow": "^2.0.1",
33 | "get-value": "^2.0.0",
34 | "kind-of": "^3.0.2",
35 | "lazy-cache": "^1.0.2",
36 | "matched": "^0.3.2",
37 | "mixin-deep": "^1.1.3",
38 | "object.omit": "^2.0.0",
39 | "parse-author": "^0.2.0",
40 | "parse-github-url": "^0.2.1",
41 | "project-name": "^0.2.3",
42 | "remote-origin-url": "^0.4.0",
43 | "set-value": "^0.3.1",
44 | "stringify-author": "^0.1.3"
45 | },
46 | "devDependencies": {
47 | "gulp": "^3.9.0",
48 | "gulp-eslint": "^1.0.0",
49 | "gulp-istanbul": "^0.10.2",
50 | "gulp-mocha": "^2.1.3",
51 | "mocha": "*"
52 | },
53 | "keywords": [
54 | "config",
55 | "fix",
56 | "json",
57 | "normalize",
58 | "package",
59 | "package-json",
60 | "pkg",
61 | "properties",
62 | "values"
63 | ],
64 | "verb": {
65 | "related": {
66 | "list": [
67 | "update"
68 | ]
69 | },
70 | "plugins": "gulp-format-md",
71 | "layout": null
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/test/fixtures/people-condensed.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "normalize-pkg",
3 | "private": true,
4 | "version": "0.1.0",
5 | "homepage": "https://github.com/jonschlinkert/normalize-pkg",
6 | "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
7 | "authors": [
8 | "Brian Woodward (https://github.com/doowb)",
9 | "Jon Schlinkert (https://github.com/jonschlinkert)"
10 | ],
11 | "contributors": [
12 | "Brian Woodward (https://github.com/doowb)",
13 | "Jon Schlinkert (https://github.com/jonschlinkert)"
14 | ],
15 | "collaborators": [
16 | "Brian Woodward (https://github.com/doowb)",
17 | "Jon Schlinkert (https://github.com/jonschlinkert)"
18 | ],
19 | "repository": "jonschlinkert/normalize-pkg",
20 | "license": "MIT",
21 | "files": [
22 | "index.js"
23 | ],
24 | "main": "index.js",
25 | "engines": {
26 | "node": ">= 0.10.0"
27 | },
28 | "keywords": [
29 | "normalize",
30 | "pkg"
31 | ]
32 | }
--------------------------------------------------------------------------------
/test/fixtures/people.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expand-pkg",
3 | "private": true,
4 | "author": {
5 | "name": "Jon Schlinkert",
6 | "url": "https://github.com/jonschlinkert"
7 | },
8 | "authors": [
9 | {
10 | "name": "Jon Schlinkert",
11 | "url": "https://github.com/jonschlinkert"
12 | },
13 | {
14 | "name": "Brian Woodward",
15 | "url": "https://github.com/doowb"
16 | }
17 | ],
18 | "contributors": [
19 | {
20 | "name": "Jon Schlinkert",
21 | "url": "https://github.com/jonschlinkert"
22 | },
23 | {
24 | "name": "Brian Woodward",
25 | "url": "https://github.com/doowb"
26 | }
27 | ],
28 | "collaborators": [
29 | {
30 | "name": "Jon Schlinkert",
31 | "url": "https://github.com/jonschlinkert"
32 | },
33 | {
34 | "name": "Brian Woodward",
35 | "url": "https://github.com/doowb"
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/test/fixtures/project-bin/bin/foo.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 |
--------------------------------------------------------------------------------
/test/fixtures/project-bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
--------------------------------------------------------------------------------
/test/fixtures/project-bin/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function() {};
4 |
--------------------------------------------------------------------------------
/test/fixtures/project-bin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-project",
3 | "private": true,
4 | "description": "",
5 | "version": "0.0.0",
6 | "repository": {
7 | "url": "https://github.com/jonschlinkert/test-project.git"
8 | },
9 | "license": "MIT"
10 | }
11 |
--------------------------------------------------------------------------------
/test/fixtures/project-no-git/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function() {};
4 |
--------------------------------------------------------------------------------
/test/fixtures/project-no-git/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "project-no-git",
3 | "private": true,
4 | "description": "",
5 | "version": "0.0.0",
6 | "repository": {
7 | "url": "https://github.com/jonschlinkert/project-no-git.git"
8 | },
9 | "license": "MIT"
10 | }
11 |
--------------------------------------------------------------------------------
/test/fixtures/project-no-package/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function() {};
4 |
--------------------------------------------------------------------------------
/test/fixtures/project/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function() {};
4 |
--------------------------------------------------------------------------------
/test/fixtures/project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-project",
3 | "private": true,
4 | "description": "",
5 | "version": "0.0.0",
6 | "repository": {
7 | "url": "https://github.com/jonschlinkert/test-project.git"
8 | },
9 | "license": "MIT"
10 | }
11 |
--------------------------------------------------------------------------------
/test/fixtures/verb.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expand-pkg",
3 | "private": true,
4 | "keywords": [
5 | "package-json",
6 | "config",
7 | "values",
8 | "fix",
9 | "json",
10 | "pkg",
11 | "normalize",
12 | "package",
13 | "properties"
14 | ],
15 | "verb": {
16 | "related": {
17 | "list": [
18 | "update"
19 | ]
20 | },
21 | "plugins": "gulp-format-md",
22 | "layout": "default"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/test/fixtures/wrong.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "foo",
3 | "version": "0.4.11",
4 | "description": "Create new Assemble projects.",
5 | "author": "Jon Schlinkert",
6 | "license": "MIT",
7 | "homepage": "https://github.com/assemble/generator-assemble",
8 | "repository": "https://github.com/assemble/generator-assemble.git",
9 | "bugs": "https://github.com/assemble/generator-assemble/issues",
10 | "main": "app/index.js",
11 | "scripts": {
12 | "test": "mocha --reporter spec"
13 | }
14 | }
--------------------------------------------------------------------------------
/test/support/git.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const del = require('delete');
5 | const gitty = require('gitty');
6 |
7 | module.exports = function(cwd, remote, cb) {
8 | const repo = gitty(cwd);
9 |
10 | del(path.join(cwd, '.git'), function(err) {
11 | if (err) return cb(err);
12 |
13 | repo.init(function(err) {
14 | if (err) return cb(err);
15 | gitAdd(repo, remote, cb);
16 | });
17 | });
18 | };
19 |
20 | function gitAdd(repo, remote, cb) {
21 | repo.add(['.'], function(err) {
22 | if (err) return cb(err);
23 |
24 | firstCommit(repo, remote, cb);
25 | });
26 | }
27 |
28 | function firstCommit(repo, remote, cb) {
29 | repo.commit('first commit', function(err) {
30 | if (err) return cb(err);
31 | if (typeof remote === 'string') {
32 | repo.addRemote('origin', remote, cb);
33 | } else {
34 | cb();
35 | }
36 | });
37 | }
38 |
--------------------------------------------------------------------------------
/test/test-bin.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('mocha');
4 | const fs = require('fs');
5 | const path = require('path');
6 | const assert = require('assert');
7 | const del = require('delete');
8 | const createRepo = require('./support/git');
9 | const Normalizer = require('..');
10 | let config;
11 |
12 | const origCwd = process.cwd();
13 | const project = path.resolve(__dirname, 'fixtures/project-bin');
14 | const remote = `https://github.com/jonschlinkert/${path.basename(project)}.git`;
15 | const gitPath = path.resolve(project, '.git');
16 |
17 | describe('normalize (bin)', () => {
18 | beforeEach(() => {
19 | config = new Normalizer({ verbose: false });
20 | });
21 |
22 | before(cb => {
23 | process.chdir(project);
24 | createRepo(project, remote, cb);
25 | });
26 |
27 | after(cb => {
28 | process.chdir(origCwd);
29 | del(gitPath, cb);
30 | });
31 |
32 | describe('main', () => {
33 | it('should remove the property if the file does not exist', () => {
34 | const pkg = { main: 'foo.js' };
35 | const res = config.normalize(pkg);
36 | assert(!res.hasOwnProperty('main'));
37 | });
38 |
39 | it('should not remove the property if the file exists', () => {
40 | const pkg = { main: 'main.js' };
41 | const res = config.normalize(pkg);
42 | assert(res.hasOwnProperty('main'));
43 | });
44 |
45 | it('should add the main file to the `files` array', () => {
46 | const pkg = { main: 'main.js' };
47 | const res = config.normalize(pkg);
48 |
49 | assert.equal(res.files.indexOf('bin'), 0);
50 | assert.equal(res.files.indexOf('cli.js'), 1);
51 | assert.equal(res.files.indexOf('main.js'), 2);
52 | });
53 |
54 | it('should not add `main` file to files array when file does not exist', () => {
55 | const pkg = {
56 | files: [],
57 | main: 'index.js'
58 | };
59 |
60 | const res = config.normalize(pkg);
61 | assert(res.hasOwnProperty('files'));
62 | assert(res.files.indexOf('index.js') === -1);
63 | });
64 |
65 | it('should create files array with main', () => {
66 | const pkg = {
67 | main: 'main.js'
68 | };
69 |
70 | const res = config.normalize(pkg);
71 | assert(res.files.length);
72 | assert(res.files.indexOf('main.js') !== -1);
73 | });
74 |
75 | it('should not double add the file to files', () => {
76 | const pkg = {
77 | files: ['main.js'],
78 | main: 'main.js'
79 | };
80 |
81 | const res = config.normalize(pkg);
82 | assert.equal(res.files.length, 3);
83 | assert(res.files.indexOf('main.js') !== -1);
84 | });
85 |
86 | it('should remove main if the file does not exist', () => {
87 | const pkg = { main: 'foo.js' };
88 |
89 | const res = config.normalize(pkg);
90 | assert(!res.main);
91 | });
92 |
93 | it('should do nothing if not defined', () => {
94 | const pkg = {};
95 |
96 | const res = config.normalize(pkg);
97 | assert.equal(typeof res.main, 'undefined');
98 | });
99 | });
100 |
101 | describe('preferGlobal', () => {
102 | beforeEach(() => {
103 | config = new Normalizer({ verbose: false });
104 | });
105 |
106 | it('should not warn when preferGlobal is defined and `bin` is defined', cb => {
107 | const pkg = { preferGlobal: true, bin: 'main.js' };
108 | let count = 0;
109 |
110 | config.on('warning', function(method, key, err) {
111 | if (key === 'preferGlobal') {
112 | count++;
113 | }
114 | });
115 |
116 | const res = config.normalize(pkg);
117 | assert(res.preferGlobal);
118 | assert.equal(count, 0);
119 | cb();
120 | });
121 |
122 | it('should return bin as-is when it is a string', () => {
123 | const pkg = { bin: 'main.js' };
124 |
125 | const res = config.normalize(pkg);
126 | assert(res.bin);
127 | assert.equal(res.bin, 'main.js');
128 | });
129 | });
130 |
131 | describe('bin', () => {
132 | beforeEach(() => {
133 | config = new Normalizer({ verbose: false });
134 | });
135 |
136 | it('should add `bin/foo.js` to bin', () => {
137 | const res = config.normalize({});
138 | assert.equal(res.bin[res.name], 'bin/foo.js');
139 | });
140 |
141 | it('should add `cli.js` to bin', cb => {
142 | del('bin/foo.js', function(err) {
143 | if (err) return cb(err);
144 | const res = config.normalize({});
145 | assert.equal(res.bin[res.name], 'cli.js');
146 | fs.writeFile('bin/foo.js', '#!/usr/bin/env node\n\n', cb);
147 | });
148 | });
149 |
150 | it('should not emit a warning when bin file string exists', cb => {
151 | const pkg = { bin: 'main.js' };
152 | let count = 0;
153 |
154 | config.on('warning', function(method, key, err) {
155 | if (key === 'bin') {
156 | count++;
157 | }
158 | });
159 |
160 | config.normalize(pkg);
161 | assert.equal(count, 0);
162 | cb();
163 | });
164 |
165 | it('should not emit a warning when bin file object exists', cb => {
166 | const pkg = { bin: { foo: 'main.js' } };
167 | let count = 0;
168 |
169 | config.on('warning', function(method, key, err) {
170 | if (key === 'bin') {
171 | count++;
172 | }
173 | });
174 |
175 | config.normalize(pkg);
176 | assert.equal(count, 0);
177 | cb();
178 | });
179 | });
180 | });
181 |
--------------------------------------------------------------------------------
/test/test-no-git.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('mocha');
4 | const path = require('path');
5 | const assert = require('assert');
6 | const Normalizer = require('..');
7 | const utils = require('../lib/utils');
8 | let config;
9 | let user;
10 |
11 | const origCwd = process.cwd();
12 | const project = path.resolve(__dirname, 'fixtures/project-no-git');
13 |
14 | describe('no git repository', () => {
15 | beforeEach(() => {
16 | config = new Normalizer({ verbose: false });
17 | });
18 |
19 | beforeEach(() => {
20 | process.chdir(project);
21 | try {
22 | const obj = utils.repo.gitUser();
23 | user = obj.username || obj.name;
24 | } catch (err) {
25 | user = 'jonschlinkert';
26 | }
27 | });
28 |
29 | afterEach(() => {
30 | process.chdir(origCwd);
31 | });
32 |
33 | describe('omit', () => {
34 | it('should remove a field on options.omit', () => {
35 | config = new Normalizer({ omit: 'version' });
36 | const res = config.normalize({});
37 | assert.equal(typeof res.version, 'undefined');
38 | });
39 |
40 | it('should remove an array of fields on options.omit', () => {
41 | config = new Normalizer({ omit: ['version', 'main'] });
42 | const res = config.normalize({});
43 | assert.equal(typeof res.version, 'undefined');
44 | assert.equal(typeof res.main, 'undefined');
45 | });
46 | });
47 |
48 | describe('defaults', () => {
49 | it('should add default properties to config', () => {
50 | const res = config.normalize({});
51 | assert.equal(res.name, 'project-no-git');
52 | assert.equal(res.version, '0.1.0');
53 | });
54 | });
55 |
56 | describe('name', () => {
57 | it('should use the defined project name', () => {
58 | const pkg = { name: 'foo' };
59 | const res = config.normalize(pkg);
60 | assert(res.name);
61 | assert.equal(res.name, 'foo');
62 | });
63 |
64 | it('should get the project name when string is empty', () => {
65 | const pkg = { name: '' };
66 | const res = config.normalize(pkg);
67 | assert(res.name);
68 | assert.equal(res.name, 'project-no-git');
69 | });
70 |
71 | it('should get the project name when missing', () => {
72 | const pkg = {};
73 | const res = config.normalize(pkg);
74 | assert(res.name);
75 | assert.equal(res.name, 'project-no-git');
76 | });
77 |
78 | it('should use the normalize function defined on options', () => {
79 | const pkg = { name: 'foo' };
80 | const opts = {
81 | fields: {
82 | name: {
83 | type: ['string'],
84 | normalize: function custom() {
85 | return 'bar';
86 | }
87 | }
88 | }
89 | };
90 |
91 | const res = config.normalize(pkg, opts);
92 | assert(res.name);
93 | assert.equal(res.name, 'bar');
94 | });
95 | });
96 |
97 | describe('version', () => {
98 | it('should use the given version', () => {
99 | const pkg = { version: '1.0.0' };
100 | const res = config.normalize(pkg);
101 | assert(res.version);
102 | assert.equal(res.version, '1.0.0');
103 | });
104 |
105 | it('should use the default version', () => {
106 | const pkg = { version: '' };
107 | const res = config.normalize(pkg);
108 | assert(res.version);
109 | assert.equal(res.version, '0.1.0');
110 | });
111 |
112 | it('should emit a warning when version type is invalid', cb => {
113 | const pkg = { version: 5 };
114 | let count = 0;
115 |
116 | config.on('warning', function(method, key, err) {
117 | if (key === 'version') {
118 | count++;
119 | }
120 | });
121 |
122 | config.normalize(pkg);
123 | assert.equal(count, 1);
124 | cb();
125 | });
126 |
127 | it('should throw an error when version is invalid', cb => {
128 | const pkg = { version: 'foo' };
129 | try {
130 | config.normalize(pkg);
131 | cb(new Error('expected an error'));
132 | } catch (err) {
133 | assert(/invalid semver/.test(err.message));
134 | cb();
135 | }
136 | });
137 | });
138 |
139 | describe('main', () => {
140 | it('should remove the property if the file does not exist', () => {
141 | const pkg = { main: 'foo.js' };
142 | const res = config.normalize(pkg);
143 | assert(!res.hasOwnProperty('main'));
144 | });
145 |
146 | it('should not remove the property if the file exists', () => {
147 | const pkg = { main: 'main.js' };
148 | const res = config.normalize(pkg);
149 | assert(res.hasOwnProperty('main'));
150 | });
151 |
152 | it('should add the main file to the `files` array', () => {
153 | const pkg = { main: 'main.js' };
154 | const res = config.normalize(pkg);
155 | assert.equal(res.files.indexOf('main.js'), 0);
156 | });
157 |
158 | it('should not add main file to files array when main file does not exist', () => {
159 | const pkg = {
160 | files: [],
161 | main: 'index.js'
162 | };
163 |
164 | const res = config.normalize(pkg);
165 | assert(!res.hasOwnProperty('files'));
166 | });
167 |
168 | it('should add main file to files array if files array is empty', () => {
169 | const pkg = {
170 | files: [],
171 | main: 'main.js'
172 | };
173 |
174 | const res = config.normalize(pkg);
175 | assert.equal(res.files.length, 1);
176 | assert.equal(res.files[0], 'main.js');
177 | });
178 |
179 | it('should create files array with main if undefined', () => {
180 | const pkg = {
181 | main: 'main.js'
182 | };
183 |
184 | const res = config.normalize(pkg);
185 | assert(res.files.length);
186 | assert(res.files.indexOf('main.js') !== -1);
187 | });
188 |
189 | it('should not double add the file to files', () => {
190 | const pkg = {
191 | files: ['main.js'],
192 | main: 'main.js'
193 | };
194 |
195 | const res = config.normalize(pkg);
196 | assert.equal(res.files.length, 1);
197 | assert(res.files.indexOf('main.js') !== -1);
198 | });
199 |
200 | it('should remove main if the file does not exist', () => {
201 | const pkg = { main: 'foo.js' };
202 |
203 | const res = config.normalize(pkg);
204 | assert(!res.main);
205 | });
206 |
207 | it('should do nothing if not defined', () => {
208 | const pkg = {};
209 |
210 | const res = config.normalize(pkg);
211 | assert.equal(typeof res.main, 'undefined');
212 | });
213 | });
214 |
215 | describe('files', () => {
216 | it('should remove a file if it does not exist', () => {
217 | const pkg = { files: ['foo.js', 'main.js'] };
218 | const res = config.normalize(pkg);
219 | assert.equal(res.files.length, 1);
220 | });
221 |
222 | it('should remove the files array if it\'s empty', () => {
223 | const pkg = { files: [] };
224 | const res = config.normalize(pkg);
225 | assert(!res.files);
226 | });
227 |
228 | it('should remove the files array if a file that does not exist is removed', () => {
229 | const pkg = { files: ['foo.js'] };
230 | const res = config.normalize(pkg);
231 | assert(!res.files);
232 | });
233 | });
234 |
235 | describe('homepage', () => {
236 | it('should add a homepage from directory name and user from global git config', () => {
237 | const res = config.normalize({});
238 | assert.equal(res.homepage, `https://github.com/${user}/project-no-git`);
239 | });
240 |
241 | it('should add repository when setting homepage', () => {
242 | const res = config.normalize({});
243 | assert.equal(res.repository, user + '/project-no-git');
244 | });
245 |
246 | it('should use the given homepage', () => {
247 | const pkg = { homepage: 'https://github.com/assemble/assemble' };
248 | const res = config.normalize(pkg);
249 | assert.equal(res.homepage, 'https://github.com/assemble/assemble');
250 | });
251 |
252 | it('should get homepage from repository.url', () => {
253 | const pkg = {
254 | homepage: '',
255 | repository: 'git://github.com/jonschlinkert/project-no-git.git'
256 | };
257 |
258 | const res = config.normalize(pkg);
259 | assert(res.homepage);
260 | assert.equal(res.homepage, 'https://github.com/jonschlinkert/project-no-git');
261 | });
262 | });
263 |
264 | describe('author', () => {
265 | it('should not add an empty author field', () => {
266 | const res = config.normalize({});
267 | assert(!res.hasOwnProperty('author'));
268 | });
269 |
270 | it('should not add an empty authors field', () => {
271 | const res = config.normalize({});
272 | assert(!res.hasOwnProperty('authors'));
273 | });
274 |
275 | it('should use the given author as a string', () => {
276 | const pkg = { author: 'Jon Schlinkert' };
277 | const res = config.normalize(pkg);
278 | assert(res.author);
279 | assert.equal(res.author, 'Jon Schlinkert');
280 | });
281 |
282 | it('should convert an author object to a string', () => {
283 | const pkg = {
284 | author: {
285 | name: 'Jon Schlinkert',
286 | url: 'https://github.com/jonschlinkert'
287 | }
288 | };
289 |
290 | const res = config.normalize(pkg);
291 | assert(res.author);
292 | assert.equal(res.author, 'Jon Schlinkert (https://github.com/jonschlinkert)');
293 | });
294 | });
295 |
296 | describe('maintainers', () => {
297 | it('should not add an empty maintainers field', () => {
298 | const res = config.normalize({});
299 | assert(!res.hasOwnProperty('maintainers'));
300 | });
301 | });
302 |
303 | describe('license', () => {
304 | it('should add MIT as the default license', () => {
305 | const res = config.normalize({});
306 | assert(res.hasOwnProperty('license'));
307 | assert.equal(res.license, 'MIT');
308 | });
309 |
310 | it('should return license as is if it is a string', () => {
311 | const res = config.normalize({ license: 'MIT' });
312 | assert(res.hasOwnProperty('license'));
313 | assert.equal(res.license, 'MIT');
314 | });
315 |
316 | it('should convert from an object to a string', () => {
317 | const res = config.normalize({ license: { type: 'MIT' } });
318 | assert(res.hasOwnProperty('license'));
319 | assert.equal(res.license, 'MIT');
320 | });
321 |
322 | it('should convert from an array to a string', () => {
323 | const res = config.normalize({ license: [{ type: 'MIT' }] });
324 | assert(res.hasOwnProperty('license'));
325 | assert.equal(res.license, 'MIT');
326 | });
327 | });
328 |
329 | describe('people', () => {
330 | beforeEach(() => {
331 | config = new Normalizer({ verbose: false });
332 | });
333 |
334 | describe('contributors', () => {
335 | it('should not add an empty contributors field', () => {
336 | const res = config.normalize({});
337 | assert(!res.hasOwnProperty('contributors'));
338 | });
339 |
340 | it('should convert contributor objects to strings', () => {
341 | const pkg = {
342 | contributors: [{
343 | name: 'Jon Schlinkert',
344 | url: 'https://github.com/jonschlinkert'
345 | }]
346 | };
347 | const res = config.normalize(pkg);
348 | assert(res.contributors);
349 | const expected = 'Jon Schlinkert (https://github.com/jonschlinkert)';
350 | assert.equal(res.contributors[0], expected);
351 | });
352 | });
353 | });
354 |
355 | describe('repository', () => {
356 | it('should use the given repository string', () => {
357 | const pkg = { repository: 'jonschlinkert/foo' };
358 | const res = config.normalize(pkg);
359 | assert(res.repository);
360 | assert.equal(res.repository, 'jonschlinkert/foo');
361 | });
362 |
363 | it('should convert repository.url to a string', () => {
364 | const pkg = { repository: { url: 'https://github.com/jonschlinkert/foo.git' } };
365 | const res = config.normalize(pkg);
366 | assert(res.repository);
367 | assert.equal(res.repository, 'jonschlinkert/foo');
368 | });
369 | });
370 |
371 | describe('bugs', () => {
372 | beforeEach(() => {
373 | config = new Normalizer({ verbose: false });
374 | });
375 |
376 | it('should get the bugs url from the directory name', () => {
377 | const res = config.normalize({});
378 | assert(res.bugs);
379 | assert.equal(res.bugs.url, 'https://github.com/' + user + '/project-no-git/issues');
380 | });
381 |
382 | it('should fix the bugs value based on repo information', () => {
383 | const pkg = { bugs: { url: 'jonschlinkert/foo' } };
384 |
385 | const res = config.normalize(pkg);
386 | assert(res.bugs);
387 | assert.equal(res.bugs.url, 'https://github.com/jonschlinkert/foo/issues');
388 | });
389 |
390 | it('should use the given bugs value', () => {
391 | const opts = { bugs: { url: 'jonschlinkert/foo' } };
392 | const res = config.normalize({}, opts);
393 | assert(res.bugs);
394 | assert.equal(res.bugs.url, 'https://github.com/jonschlinkert/foo/issues');
395 | });
396 |
397 | it('should use the value function passed on options', () => {
398 | const pkg = { bugs: '' };
399 | const res = config.normalize(pkg, {
400 | fields: {
401 | bugs: {
402 | type: ['string', 'object'],
403 | normalize: function custom() {
404 | return { url: 'abc' };
405 | }
406 | }
407 | }
408 | });
409 | assert(res.bugs);
410 | assert.equal(res.bugs.url, 'abc');
411 | });
412 |
413 | it('should use a custom type passed on options', () => {
414 | const pkg = { bugs: '', repository: 'https://github.com/foo/bar' };
415 | const res = config.normalize(pkg, {
416 | extend: false,
417 | fields: {
418 | bugs: {
419 | type: ['object', 'string'],
420 | normalize: function custom(key, val, config) {
421 | const bugs = {};
422 | bugs.url = config.homepage + '/bugs';
423 | return bugs;
424 | }
425 | }
426 | }
427 | });
428 |
429 | assert.equal(typeof res.bugs, 'object');
430 | assert(res.bugs.url);
431 | assert.equal(res.bugs.url, 'https://github.com/foo/bar/bugs');
432 | });
433 |
434 | it('should convert bugs.url to a string when specified', () => {
435 | const pkg = { bugs: { url: 'https://github.com/jonschlinkert/foo.git' } };
436 | const res = config.normalize(pkg, {
437 | extend: false,
438 | fields: {
439 | bugs: {
440 | type: 'string',
441 | normalize: function(val, key, config) {
442 | return val.url;
443 | }
444 | }
445 | }
446 | });
447 | assert(res.bugs);
448 | assert.equal(res.bugs, 'https://github.com/jonschlinkert/foo.git');
449 | });
450 | });
451 |
452 | describe('license', () => {
453 | beforeEach(() => {
454 | config = new Normalizer({ verbose: false });
455 | });
456 |
457 | it('should convert a license object to a string', () => {
458 | const pkg = {
459 | license: {
460 | type: 'MIT',
461 | url: 'https://github.com/jonschlinkert/project-no-git/blob/master/LICENSE-MIT'
462 | }
463 | };
464 |
465 | const res = config.normalize(pkg);
466 | assert.equal(typeof res.license, 'string');
467 | assert.equal(res.license, 'MIT');
468 | });
469 | });
470 |
471 | describe('licenses', () => {
472 | beforeEach(() => {
473 | config = new Normalizer({ verbose: false });
474 | });
475 |
476 | it('should emit a deprecation warning when licenses is defined', cb => {
477 | const pkg = { licenses: { type: 'MIT' } };
478 | let count = 0;
479 |
480 | config.on('warning', function(method, key, err) {
481 | if (key === 'licenses') {
482 | count++;
483 | }
484 | });
485 |
486 | config.normalize(pkg);
487 | assert.equal(count, 1);
488 | cb();
489 | });
490 |
491 | it('should convert a licenses array to a license string', () => {
492 | const pkg = {
493 | licenses: [
494 | { type: 'MIT', url: 'https://github.com/jonschlinkert/project-no-git/blob/master/LICENSE-MIT' }
495 | ]
496 | };
497 |
498 | const res = config.normalize(pkg);
499 | assert(!res.licenses);
500 | assert(res.license);
501 | assert.equal(typeof res.license, 'string');
502 | assert.equal(res.license, 'MIT');
503 | });
504 |
505 | it('should convert from an object to a string', () => {
506 | const pkg = {
507 | licenses: { type: 'MIT', url: 'https://github.com/jonschlinkert/project-no-git/blob/master/LICENSE-MIT' }
508 | };
509 |
510 | const res = config.normalize(pkg);
511 | assert(!res.licenses);
512 | assert(res.license);
513 | assert.equal(typeof res.license, 'string');
514 | assert.equal(res.license, 'MIT');
515 | });
516 | });
517 |
518 | describe('dependencies', () => {
519 | beforeEach(() => {
520 | config = new Normalizer({ verbose: false });
521 | });
522 |
523 | it('should remove dependencies when empty when `omitEmpty` is true', () => {
524 | const pkg = { dependencies: {} };
525 | const res = config.normalize(pkg, { omitEmpty: true });
526 | assert(!res.dependencies);
527 | });
528 | });
529 |
530 | describe('devDependencies', () => {
531 | beforeEach(() => {
532 | config = new Normalizer({ verbose: false });
533 | });
534 |
535 | it('should remove empty devDependencies when omitEmpty is true', () => {
536 | const pkg = { devDependencies: {} };
537 | const res = config.normalize(pkg, { omitEmpty: true });
538 | assert(!res.devDependencies);
539 | });
540 | });
541 |
542 | describe('engineStrict', () => {
543 | beforeEach(() => {
544 | config = new Normalizer({ verbose: false });
545 | });
546 |
547 | it('should delete engineStrict and replace it with engine-strict', () => {
548 | const pkg = { engineStrict: true };
549 | const res = config.normalize(pkg);
550 | assert.equal(typeof res.engineStrict, 'undefined');
551 | assert.equal(res['engine-strict'], true);
552 | });
553 |
554 | it('should remove engineStrict from the object', () => {
555 | const pkg = { engineStrict: true };
556 | const res = config.normalize(pkg);
557 | assert(!res.hasOwnProperty('engineStrict'));
558 | });
559 | });
560 |
561 | describe('engine-strict', () => {
562 | beforeEach(() => {
563 | config = new Normalizer({ verbose: false });
564 | });
565 |
566 | it('should warn when engine-strict value is invalid', cb => {
567 | const pkg = { 'engine-strict': 'foo' };
568 | let count = 0;
569 |
570 | config.on('warning', function(method, key, err) {
571 | if (key === 'engine-strict') {
572 | count++;
573 | }
574 | });
575 |
576 | config.normalize(pkg);
577 | assert.equal(count, 1);
578 | cb();
579 | });
580 | });
581 |
582 | describe('scripts', () => {
583 | beforeEach(() => {
584 | config = new Normalizer({ verbose: false });
585 | });
586 |
587 | it('should clean up mocha scripts', () => {
588 | const pkg = { scripts: { test: 'mocha -R spec' } };
589 |
590 | const res = config.normalize(pkg);
591 | assert(res.scripts);
592 | assert.equal(typeof res.scripts, 'object');
593 | assert.equal(res.scripts.test, 'mocha');
594 | });
595 |
596 | it('should return scripts if it is an object', () => {
597 | const pkg = { scripts: { test: 'foo' } };
598 |
599 | const res = config.normalize(pkg);
600 | assert(res.scripts);
601 | assert.equal(typeof res.scripts, 'object');
602 | assert.equal(res.scripts.test, 'foo');
603 | });
604 | });
605 |
606 | describe('keywords', () => {
607 | beforeEach(() => {
608 | config = new Normalizer({ verbose: false });
609 | });
610 |
611 | it('should use the name to create keywords when the array is empty', () => {
612 | const pkg = { keywords: [] };
613 | const res = config.normalize(pkg);
614 | assert.equal(res.keywords[0], 'git');
615 | assert.equal(res.keywords[1], 'no');
616 | assert.equal(res.keywords.length, 3);
617 | });
618 |
619 | it('should sort keywords', () => {
620 | const pkg = { keywords: ['foo', 'bar', 'baz'] };
621 | const res = config.normalize(pkg);
622 | assert.equal(res.keywords[0], 'bar');
623 | assert.equal(res.keywords[1], 'baz');
624 | assert.equal(res.keywords[2], 'foo');
625 | });
626 |
627 | it('should remove duplicates', () => {
628 | const pkg = { keywords: ['foo', 'foo', 'foo', 'foo', 'bar', 'baz'] };
629 | const res = config.normalize(pkg);
630 | assert.equal(res.keywords.length, 3);
631 | });
632 | });
633 |
634 | describe('preferGlobal', () => {
635 | beforeEach(() => {
636 | config = new Normalizer({ verbose: false });
637 | });
638 |
639 | it('should warn when preferGlobal is defined and `bin` is not defined', cb => {
640 | const pkg = { preferGlobal: true };
641 | let count = 0;
642 |
643 | config.on('warning', function(method, key, err) {
644 | if (key === 'preferGlobal') {
645 | count++;
646 | }
647 | });
648 |
649 | const res = config.normalize(pkg);
650 | assert(res.preferGlobal);
651 | assert.equal(count, 1);
652 | cb();
653 | });
654 |
655 | it('should not warn when preferGlobal is defined and `bin` is defined', cb => {
656 | const pkg = { preferGlobal: true, bin: 'main.js' };
657 | let count = 0;
658 |
659 | config.on('warning', function(method, key, err) {
660 | if (key === 'preferGlobal') {
661 | count++;
662 | }
663 | });
664 |
665 | const res = config.normalize(pkg);
666 | assert(res.preferGlobal);
667 | assert.equal(count, 0);
668 | cb();
669 | });
670 | });
671 |
672 | describe('bin', () => {
673 | beforeEach(() => {
674 | config = new Normalizer({ verbose: false });
675 | });
676 |
677 | it('should return bin as-is when it is a string', () => {
678 | const pkg = { bin: 'main.js' };
679 |
680 | const res = config.normalize(pkg);
681 | assert(res.bin);
682 | assert.equal(res.bin, 'main.js');
683 | });
684 |
685 | it('should not emit a warning when bin file string exists', cb => {
686 | const pkg = { bin: 'main.js' };
687 | let count = 0;
688 |
689 | config.on('warning', function(method, key, err) {
690 | if (key === 'bin') {
691 | count++;
692 | }
693 | });
694 |
695 | config.normalize(pkg);
696 | assert.equal(count, 0);
697 | cb();
698 | });
699 |
700 | it('should not emit a warning when bin file object exists', cb => {
701 | const pkg = { bin: { foo: 'main.js' } };
702 | let count = 0;
703 |
704 | config.on('warning', function(method, key, err) {
705 | if (key === 'bin') {
706 | count++;
707 | }
708 | });
709 |
710 | config.normalize(pkg);
711 | assert.equal(count, 0);
712 | cb();
713 | });
714 | });
715 | });
716 |
717 |
--------------------------------------------------------------------------------
/test/test-no-package.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('mocha');
4 | const path = require('path');
5 | const assert = require('assert');
6 | const del = require('delete');
7 | const createRepo = require('./support/git');
8 | const Normalizer = require('..');
9 | let config;
10 |
11 | const origCwd = process.cwd();
12 | const remote = 'https://github.com/jonschlinkert/project-no-package.git';
13 | const project = path.resolve(__dirname, 'fixtures/project-no-package');
14 | const gitPath = path.resolve(project, '.git');
15 |
16 | describe('normalize (no package.json)', () => {
17 | beforeEach(() => {
18 | config = new Normalizer({ verbose: false });
19 | });
20 |
21 | before(function(cb) {
22 | process.chdir(project);
23 | createRepo(project, remote, cb);
24 | });
25 |
26 | after(function(cb) {
27 | process.chdir(origCwd);
28 | del(gitPath, cb);
29 | });
30 |
31 | describe('omit', () => {
32 | it('should remove a field on options.omit', () => {
33 | config = new Normalizer({ omit: 'version' });
34 | const res = config.normalize({});
35 | assert.equal(typeof res.version, 'undefined');
36 | });
37 |
38 | it('should remove an array of fields on options.omit', () => {
39 | config = new Normalizer({ omit: ['version', 'main'] });
40 | const res = config.normalize({});
41 | assert.equal(typeof res.version, 'undefined');
42 | assert.equal(typeof res.main, 'undefined');
43 | });
44 | });
45 |
46 | describe('defaults', () => {
47 | it('should add default properties to config', () => {
48 | const res = config.normalize({});
49 | assert.equal(res.name, 'project-no-package');
50 | assert.equal(res.version, '0.1.0');
51 | });
52 | });
53 |
54 | describe('name', () => {
55 | it('should use the defined project name', () => {
56 | const pkg = { name: 'foo' };
57 | const res = config.normalize(pkg);
58 | assert(res.name);
59 | assert.equal(res.name, 'foo');
60 | });
61 |
62 | it('should get the project name when string is empty', () => {
63 | const pkg = { name: '' };
64 | const res = config.normalize(pkg);
65 | assert(res.name);
66 | assert.equal(res.name, 'project-no-package');
67 | });
68 |
69 | it('should get the project name when missing', () => {
70 | const pkg = {};
71 | const res = config.normalize(pkg);
72 | assert(res.name);
73 | assert.equal(res.name, 'project-no-package');
74 | });
75 |
76 | it('should use the normalize function defined on options', () => {
77 | const pkg = { name: 'foo' };
78 | const opts = {
79 | fields: {
80 | name: {
81 | type: ['string'],
82 | normalize: function custom() {
83 | return 'bar';
84 | }
85 | }
86 | }
87 | };
88 |
89 | const res = config.normalize(pkg, opts);
90 | assert(res.name);
91 | assert.equal(res.name, 'bar');
92 | });
93 | });
94 |
95 | describe('version', () => {
96 | it('should use the given version', () => {
97 | const pkg = { version: '1.0.0' };
98 | const res = config.normalize(pkg);
99 | assert(res.version);
100 | assert.equal(res.version, '1.0.0');
101 | });
102 |
103 | it('should use the default version', () => {
104 | const pkg = { version: '' };
105 | const res = config.normalize(pkg);
106 | assert(res.version);
107 | assert.equal(res.version, '0.1.0');
108 | });
109 |
110 | it('should emit a warning when version type is invalid', cb => {
111 | const pkg = { version: 5 };
112 | let count = 0;
113 |
114 | config.on('warning', function(method, key, err) {
115 | if (key === 'version') {
116 | count++;
117 | }
118 | });
119 |
120 | config.normalize(pkg);
121 | assert.equal(count, 1);
122 | cb();
123 | });
124 |
125 | it('should throw an error when version is invalid', cb => {
126 | const pkg = { version: 'foo' };
127 | try {
128 | config.normalize(pkg);
129 | cb(new Error('expected an error'));
130 | } catch (err) {
131 | assert(/invalid semver/.test(err.message));
132 | cb();
133 | }
134 | });
135 | });
136 |
137 | describe('main', () => {
138 | it('should remove the property if the file does not exist', () => {
139 | const pkg = { main: 'foo.js' };
140 | const res = config.normalize(pkg);
141 | assert(!res.hasOwnProperty('main'));
142 | });
143 |
144 | it('should not remove the property if the file exists', () => {
145 | const pkg = { main: 'main.js' };
146 | const res = config.normalize(pkg);
147 | assert(res.hasOwnProperty('main'));
148 | });
149 |
150 | it('should add the main file to the `files` array', () => {
151 | const pkg = { main: 'main.js' };
152 | const res = config.normalize(pkg);
153 | assert.equal(res.files.indexOf('main.js'), 0);
154 | });
155 |
156 | it('should not add main file to files array when main file does not exist', () => {
157 | const pkg = {
158 | files: [],
159 | main: 'index.js'
160 | };
161 |
162 | const res = config.normalize(pkg);
163 | assert(!res.hasOwnProperty('files'));
164 | });
165 |
166 | it('should add main file to files array if files array is empty', () => {
167 | const pkg = {
168 | files: [],
169 | main: 'main.js'
170 | };
171 |
172 | const res = config.normalize(pkg);
173 | assert.equal(res.files.length, 1);
174 | assert.equal(res.files[0], 'main.js');
175 | });
176 |
177 | it('should create files array with main if undefined', () => {
178 | const pkg = {
179 | main: 'main.js'
180 | };
181 |
182 | const res = config.normalize(pkg);
183 | assert(res.files.length);
184 | assert(res.files.indexOf('main.js') !== -1);
185 | });
186 |
187 | it('should not double add the file to files', () => {
188 | const pkg = {
189 | files: ['main.js'],
190 | main: 'main.js'
191 | };
192 |
193 | const res = config.normalize(pkg);
194 | assert.equal(res.files.length, 1);
195 | assert(res.files.indexOf('main.js') !== -1);
196 | });
197 |
198 | it('should remove main if the file does not exist', () => {
199 | const pkg = { main: 'foo.js' };
200 |
201 | const res = config.normalize(pkg);
202 | assert(!res.main);
203 | });
204 |
205 | it('should do nothing if not defined', () => {
206 | const pkg = {};
207 |
208 | const res = config.normalize(pkg);
209 | assert.equal(typeof res.main, 'undefined');
210 | });
211 | });
212 |
213 | describe('files', () => {
214 | it('should remove a file if it does not exist', () => {
215 | const pkg = { files: ['foo.js', 'main.js'] };
216 | const res = config.normalize(pkg);
217 | assert.equal(res.files.length, 1);
218 | });
219 |
220 | it('should remove the files array if it\'s empty', () => {
221 | const pkg = { files: [] };
222 | const res = config.normalize(pkg);
223 | assert(!res.files);
224 | });
225 |
226 | it('should remove the files array if a file that does not exist is removed', () => {
227 | const pkg = { files: ['foo.js'] };
228 | const res = config.normalize(pkg);
229 | assert(!res.files);
230 | });
231 | });
232 |
233 | describe('homepage', () => {
234 | it('should add a homepage from git repository', () => {
235 | const res = config.normalize({});
236 | assert(res.homepage);
237 | assert.equal(res.homepage, 'https://github.com/jonschlinkert/project-no-package');
238 | });
239 |
240 | it('should add repository when setting homepage', () => {
241 | const res = config.normalize({});
242 | assert(res.homepage);
243 | assert.equal(res.repository, 'jonschlinkert/project-no-package');
244 | });
245 |
246 | it('should use the given homepage', () => {
247 | const pkg = { homepage: 'https://github.com/assemble/assemble' };
248 | const res = config.normalize(pkg);
249 | assert(res.homepage);
250 | assert.equal(res.homepage, 'https://github.com/assemble/assemble');
251 | });
252 |
253 | it('should get homepage from repository.url', () => {
254 | const pkg = {
255 | homepage: '',
256 | repository: 'git://github.com/jonschlinkert/project-no-package.git'
257 | };
258 |
259 | const res = config.normalize(pkg);
260 | assert(res.homepage);
261 | assert.equal(res.homepage, 'https://github.com/jonschlinkert/project-no-package');
262 | });
263 | });
264 |
265 | describe('author', () => {
266 | it('should not add an empty author field', () => {
267 | const res = config.normalize({});
268 | assert(!res.hasOwnProperty('author'));
269 | });
270 |
271 | it('should return an author string as is', () => {
272 | const pkg = { author: 'Jon Schlinkert' };
273 | const res = config.normalize(pkg);
274 | assert.equal(res.author, 'Jon Schlinkert');
275 | });
276 |
277 | it('should convert an author object to a string', () => {
278 | const pkg = {
279 | author: {
280 | name: 'Jon Schlinkert',
281 | url: 'https://github.com/jonschlinkert'
282 | }
283 | };
284 |
285 | const res = config.normalize(pkg);
286 | assert.equal(res.author, 'Jon Schlinkert (https://github.com/jonschlinkert)');
287 | });
288 | });
289 |
290 | describe('maintainers', () => {
291 | it('should not add an empty maintainers field', () => {
292 | const res = config.normalize({});
293 | assert(!res.hasOwnProperty('maintainers'));
294 | });
295 | });
296 |
297 | describe('license', () => {
298 | it('should add MIT as the default license', () => {
299 | const res = config.normalize({});
300 | assert(res.hasOwnProperty('license'));
301 | assert.equal(res.license, 'MIT');
302 | });
303 |
304 | it('should return license as is if it is a string', () => {
305 | const res = config.normalize({ license: 'MIT' });
306 | assert(res.hasOwnProperty('license'));
307 | assert.equal(res.license, 'MIT');
308 | });
309 |
310 | it('should convert from an object to a string', () => {
311 | const res = config.normalize({ license: { type: 'MIT' } });
312 | assert(res.hasOwnProperty('license'));
313 | assert.equal(res.license, 'MIT');
314 | });
315 |
316 | it('should convert from an array to a string', () => {
317 | const res = config.normalize({ license: [{ type: 'MIT' }] });
318 | assert(res.hasOwnProperty('license'));
319 | assert.equal(res.license, 'MIT');
320 | });
321 | });
322 |
323 | describe('people', () => {
324 | beforeEach(() => {
325 | config = new Normalizer({ verbose: false });
326 | });
327 |
328 | describe('contributors', () => {
329 | it('should not add an empty contributors field', () => {
330 | const res = config.normalize({});
331 | assert(!res.hasOwnProperty('contributors'));
332 | });
333 |
334 | it('should stringify authors', () => {
335 | const pkg = {
336 | contributors: [{
337 | name: 'Jon Schlinkert',
338 | url: 'https://github.com/jonschlinkert'
339 | }]
340 | };
341 |
342 | const res = config.normalize(pkg);
343 | assert.equal(res.contributors[0], 'Jon Schlinkert (https://github.com/jonschlinkert)');
344 | });
345 | });
346 | });
347 |
348 | describe('repository', () => {
349 | it('should use the given repository', () => {
350 | const pkg = { repository: 'jonschlinkert/foo' };
351 | const res = config.normalize(pkg);
352 | assert(res.repository);
353 | assert.equal(res.repository, 'jonschlinkert/foo');
354 | });
355 |
356 | it('should use the git remote url', () => {
357 | const pkg = { repository: '' };
358 | const res = config.normalize(pkg);
359 | assert(res.repository);
360 | assert.equal(res.repository, 'jonschlinkert/project-no-package');
361 | });
362 |
363 | it('should convert repository.url to a string', () => {
364 | const pkg = { repository: { url: 'https://github.com/jonschlinkert/foo.git' } };
365 | const res = config.normalize(pkg);
366 | assert(res.repository);
367 | assert.equal(res.repository, 'jonschlinkert/foo');
368 | });
369 | });
370 |
371 | describe('bugs', () => {
372 | beforeEach(() => {
373 | config = new Normalizer({ verbose: false });
374 | });
375 |
376 | it('should return bugs value ', () => {
377 | const pkg = { bugs: { url: 'jonschlinkert/foo' } };
378 |
379 | const res = config.normalize(pkg);
380 | assert(res.bugs);
381 | assert.equal(res.bugs.url, 'https://github.com/jonschlinkert/foo/issues');
382 | });
383 |
384 | it('should use the given bugs value', () => {
385 | const opts = { bugs: { url: 'jonschlinkert/foo' } };
386 | const res = config.normalize({}, opts);
387 | assert(res.bugs);
388 | assert.equal(res.bugs.url, 'https://github.com/jonschlinkert/foo/issues');
389 | });
390 |
391 | it('should use the value function passed on options', () => {
392 | const pkg = { bugs: '' };
393 | const res = config.normalize(pkg, {
394 | fields: {
395 | bugs: {
396 | type: ['string', 'object'],
397 | normalize: function custom() {
398 | return { url: 'abc' };
399 | }
400 | }
401 | }
402 | });
403 | assert(res.bugs);
404 | assert.equal(res.bugs.url, 'abc');
405 | });
406 |
407 | it('should use a custom type passed on options', () => {
408 | const pkg = { bugs: '', repository: 'https://github.com/foo' };
409 | const res = config.normalize(pkg, {
410 | extend: false,
411 | fields: {
412 | bugs: {
413 | type: ['object', 'string'],
414 | normalize: function custom(key, val, config, schema) {
415 | schema.update('repository', config);
416 | const bugs = {};
417 | bugs.url = config.repository + '/bugs';
418 | return bugs;
419 | }
420 | }
421 | }
422 | });
423 |
424 | assert.equal(typeof res.bugs, 'object');
425 | assert(res.bugs.url);
426 | assert.equal(res.bugs.url, 'https://github.com/foo/bugs');
427 | });
428 |
429 | it('should convert bugs.url to a string when specified', () => {
430 | const pkg = { bugs: { url: 'https://github.com/jonschlinkert/foo.git' } };
431 | const res = config.normalize(pkg, {
432 | extend: false,
433 | fields: {
434 | bugs: {
435 | type: 'string',
436 | normalize: function(val, key, config) {
437 | return val.url;
438 | }
439 | }
440 | }
441 | });
442 | assert(res.bugs);
443 | assert.equal(res.bugs, 'https://github.com/jonschlinkert/foo.git');
444 | });
445 | });
446 |
447 | describe('license', () => {
448 | beforeEach(() => {
449 | config = new Normalizer({ verbose: false });
450 | });
451 |
452 | it('should convert a license object to a string', () => {
453 | const pkg = {
454 | license: {
455 | type: 'MIT',
456 | url: 'https://github.com/jonschlinkert/project-no-package/blob/master/LICENSE-MIT'
457 | }
458 | };
459 |
460 | const res = config.normalize(pkg);
461 | assert.equal(typeof res.license, 'string');
462 | assert.equal(res.license, 'MIT');
463 | });
464 | });
465 |
466 | describe('licenses', () => {
467 | beforeEach(() => {
468 | config = new Normalizer({ verbose: false });
469 | });
470 |
471 | it('should emit a deprecation warning when licenses is defined', cb => {
472 | const pkg = { licenses: { type: 'MIT' } };
473 | let count = 0;
474 |
475 | config.on('warning', function(method, key, err) {
476 | if (key === 'licenses') {
477 | count++;
478 | }
479 | });
480 |
481 | config.normalize(pkg);
482 | assert.equal(count, 1);
483 | cb();
484 | });
485 |
486 | it('should convert a licenses array to a license string', () => {
487 | const pkg = {
488 | licenses: [
489 | { type: 'MIT', url: 'https://github.com/jonschlinkert/project-no-package/blob/master/LICENSE-MIT' }
490 | ]
491 | };
492 |
493 | const res = config.normalize(pkg);
494 | assert(!res.licenses);
495 | assert(res.license);
496 | assert.equal(typeof res.license, 'string');
497 | assert.equal(res.license, 'MIT');
498 | });
499 |
500 | it('should convert from an object to a string', () => {
501 | const pkg = {
502 | licenses: { type: 'MIT', url: 'https://github.com/jonschlinkert/project-no-package/blob/master/LICENSE-MIT' }
503 | };
504 |
505 | const res = config.normalize(pkg);
506 | assert(!res.licenses);
507 | assert(res.license);
508 | assert.equal(typeof res.license, 'string');
509 | assert.equal(res.license, 'MIT');
510 | });
511 | });
512 |
513 | describe('dependencies', () => {
514 | beforeEach(() => {
515 | config = new Normalizer({ verbose: false });
516 | });
517 |
518 | it('should remove dependencies when empty when `omitEmpty` is true', () => {
519 | const pkg = { dependencies: {} };
520 | const res = config.normalize(pkg, { omitEmpty: true });
521 | assert(!res.dependencies);
522 | });
523 | });
524 |
525 | describe('devDependencies', () => {
526 | beforeEach(() => {
527 | config = new Normalizer({ verbose: false });
528 | });
529 |
530 | it('should remove empty devDependencies when omitEmpty is true', () => {
531 | const pkg = { devDependencies: {} };
532 | const res = config.normalize(pkg, { omitEmpty: true });
533 | assert(!res.devDependencies);
534 | });
535 | });
536 |
537 | describe('engineStrict', () => {
538 | beforeEach(() => {
539 | config = new Normalizer({ verbose: false });
540 | });
541 |
542 | it('should delete engineStrict and replace it with engine-strict', () => {
543 | const pkg = { engineStrict: true };
544 | const res = config.normalize(pkg);
545 | assert.equal(typeof res.engineStrict, 'undefined');
546 | assert.equal(res['engine-strict'], true);
547 | });
548 |
549 | it('should remove engineStrict from the object', () => {
550 | const pkg = { engineStrict: true };
551 | const res = config.normalize(pkg);
552 | assert(!res.hasOwnProperty('engineStrict'));
553 | });
554 | });
555 |
556 | describe('engine-strict', () => {
557 | beforeEach(() => {
558 | config = new Normalizer({ verbose: false });
559 | });
560 |
561 | it('should warn when engine-strict value is invalid', cb => {
562 | const pkg = { 'engine-strict': 'foo' };
563 | let count = 0;
564 |
565 | config.on('warning', function(method, key, err) {
566 | if (key === 'engine-strict') {
567 | count++;
568 | }
569 | });
570 |
571 | config.normalize(pkg);
572 | assert.equal(count, 1);
573 | cb();
574 | });
575 | });
576 |
577 | describe('scripts', () => {
578 | beforeEach(() => {
579 | config = new Normalizer({ verbose: false });
580 | });
581 |
582 | it('should clean up mocha scripts', () => {
583 | const pkg = { scripts: { test: 'mocha -R spec' } };
584 |
585 | const res = config.normalize(pkg);
586 | assert(res.scripts);
587 | assert.equal(typeof res.scripts, 'object');
588 | assert.equal(res.scripts.test, 'mocha');
589 | });
590 |
591 | it('should return scripts if it is an object', () => {
592 | const pkg = { scripts: { test: 'foo' } };
593 |
594 | const res = config.normalize(pkg);
595 | assert(res.scripts);
596 | assert.equal(typeof res.scripts, 'object');
597 | assert.equal(res.scripts.test, 'foo');
598 | });
599 | });
600 |
601 | describe('keywords', () => {
602 | beforeEach(() => {
603 | config = new Normalizer({ verbose: false });
604 | });
605 |
606 | it('should use the name to create keywords when the array is empty', () => {
607 | const pkg = { keywords: [] };
608 | const res = config.normalize(pkg);
609 | assert.equal(res.keywords[0], 'no');
610 | assert.equal(res.keywords[1], 'package');
611 | assert.equal(res.keywords.length, 3);
612 | });
613 |
614 | it('should sort keywords', () => {
615 | const pkg = { keywords: ['foo', 'bar', 'baz'] };
616 | const res = config.normalize(pkg);
617 | assert.equal(res.keywords[0], 'bar');
618 | assert.equal(res.keywords[1], 'baz');
619 | assert.equal(res.keywords[2], 'foo');
620 | });
621 |
622 | it('should remove duplicates', () => {
623 | const pkg = { keywords: ['foo', 'foo', 'foo', 'foo', 'bar', 'baz'] };
624 | const res = config.normalize(pkg);
625 | assert.equal(res.keywords.length, 3);
626 | });
627 | });
628 |
629 | describe('preferGlobal', () => {
630 | beforeEach(() => {
631 | config = new Normalizer({ verbose: false });
632 | });
633 |
634 | it('should warn when preferGlobal is defined and `bin` is not defined', cb => {
635 | const pkg = { preferGlobal: true };
636 | let count = 0;
637 |
638 | config.on('warning', function(method, key, err) {
639 | if (key === 'preferGlobal') {
640 | count++;
641 | }
642 | });
643 |
644 | const res = config.normalize(pkg);
645 | assert(res.preferGlobal);
646 | assert.equal(count, 1);
647 | cb();
648 | });
649 |
650 | it('should not warn when preferGlobal is defined and `bin` is defined', cb => {
651 | const pkg = { preferGlobal: true, bin: 'main.js' };
652 | let count = 0;
653 |
654 | config.on('warning', function(method, key, err) {
655 | if (key === 'preferGlobal') {
656 | count++;
657 | }
658 | });
659 |
660 | const res = config.normalize(pkg);
661 | assert(res.preferGlobal);
662 | assert.equal(count, 0);
663 | cb();
664 | });
665 |
666 | it('should return bin as-is when it is a string', () => {
667 | const pkg = { bin: 'main.js' };
668 |
669 | const res = config.normalize(pkg);
670 | assert(res.bin);
671 | assert.equal(res.bin, 'main.js');
672 | });
673 | });
674 |
675 | describe('bin', () => {
676 | beforeEach(() => {
677 | config = new Normalizer({ verbose: false });
678 | });
679 |
680 | it('should not emit a warning when bin file string exists', cb => {
681 | const pkg = { bin: 'main.js' };
682 | let count = 0;
683 |
684 | config.on('warning', function(method, key, err) {
685 | if (key === 'bin') {
686 | count++;
687 | }
688 | });
689 |
690 | config.normalize(pkg);
691 | assert.equal(count, 0);
692 | cb();
693 | });
694 |
695 | it('should not emit a warning when bin file object exists', cb => {
696 | const pkg = { bin: { foo: 'main.js' } };
697 | let count = 0;
698 |
699 | config.on('warning', function(method, key, err) {
700 | if (key === 'bin') {
701 | count++;
702 | }
703 | });
704 |
705 | config.normalize(pkg);
706 | assert.equal(count, 0);
707 | cb();
708 | });
709 | });
710 | });
711 |
712 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('mocha');
4 | const path = require('path');
5 | const assert = require('assert');
6 | const Normalizer = require('..');
7 | const createRepo = require('./support/git');
8 | const del = require('delete');
9 | let config;
10 |
11 | const origCwd = process.cwd();
12 | const remote = 'https://github.com/jonschlinkert/test-project.git';
13 | const project = path.resolve(__dirname, 'fixtures/project');
14 | const gitPath = path.resolve(project, '.git');
15 |
16 | describe('normalize', () => {
17 | beforeEach(() => {
18 | config = new Normalizer({ verbose: false });
19 | });
20 |
21 | before(function(cb) {
22 | process.chdir(project);
23 | createRepo(project, remote, cb);
24 | });
25 |
26 | after(function(cb) {
27 | process.chdir(origCwd);
28 | del(gitPath, cb);
29 | });
30 |
31 | describe('Normalizer', () => {
32 | it('should instantiate with an options object', () => {
33 | config = new Normalizer({ foo: 'bar' });
34 | assert.equal(config.options.foo, 'bar');
35 | });
36 |
37 | it('should instantiate without an options object', () => {
38 | config = new Normalizer();
39 | assert.deepEqual(config.options, {});
40 | });
41 | });
42 |
43 | describe('.field', () => {
44 | it('should add a custom field', () => {
45 | config = new Normalizer({ omit: 'version' });
46 | config.field('foo', 'string', {
47 | normalize: function(val, key, config, schema) {
48 | config[key] = { a: 'b' };
49 | return config[key];
50 | }
51 | });
52 |
53 | const res = config.normalize({});
54 | assert.equal(res.foo.a, 'b');
55 | });
56 |
57 | it('should convert a function to a `normalize` function', () => {
58 | config = new Normalizer({ omit: 'version' });
59 | config.field('foo', 'string', function(val, key, config, schema) {
60 | config[key] = { a: 'b' };
61 | return config[key];
62 | });
63 |
64 | const res = config.normalize({});
65 | assert.equal(res.foo.a, 'b');
66 | });
67 |
68 | it('should remove an array of fields on options.omit', () => {
69 | config = new Normalizer({ omit: ['version', 'main'] });
70 | const res = config.normalize({});
71 | assert.equal(typeof res.version, 'undefined');
72 | assert.equal(typeof res.main, 'undefined');
73 | });
74 |
75 | it('should extend an existing field', () => {
76 | config = new Normalizer({ knownOnly: true });
77 | config.schema.fields = {};
78 |
79 | config.field('foo', 'string', {
80 | normalize: function(val) {
81 | return val + ':bar';
82 | }
83 | });
84 |
85 | config.field('foo', 'string', {
86 | extend: true,
87 | default: 'foo'
88 | });
89 |
90 | const res = config.normalize({});
91 | assert.equal(res.foo, 'foo:bar');
92 | });
93 | });
94 |
95 | describe('options.omit', () => {
96 | it('should remove a field on options.omit', () => {
97 | config = new Normalizer({ omit: 'version' });
98 | const res = config.normalize({});
99 | assert.equal(typeof res.version, 'undefined');
100 | });
101 |
102 | it('should remove an array of fields on options.omit', () => {
103 | config = new Normalizer({ omit: ['version', 'main'] });
104 | const res = config.normalize({});
105 | assert.equal(typeof res.version, 'undefined');
106 | assert.equal(typeof res.main, 'undefined');
107 | });
108 | });
109 |
110 | describe('defaults', () => {
111 | it('should add default properties to config', () => {
112 | const res = config.normalize({});
113 | assert.equal(res.name, 'test-project');
114 | assert.equal(res.version, '0.1.0');
115 | });
116 | });
117 |
118 | describe('package.json', () => {
119 | it('should get package.json when no args are passed', () => {
120 | const res = config.normalize();
121 | assert.equal(res.name, 'test-project');
122 | });
123 |
124 | it('should get package.json from a cwd', () => {
125 | const res = config.normalize(process.cwd());
126 | assert.equal(res.name, 'test-project');
127 | });
128 |
129 | it('should get the cwd when dir exists but path does not exist', () => {
130 | const res = config.normalize(path.resolve(process.cwd(), 'index.js'));
131 | assert.equal(res.name, 'test-project');
132 | });
133 |
134 | it('should get the cwd from a file path', () => {
135 | const res = config.normalize(path.resolve(process.cwd(), 'main.js'));
136 | assert.equal(res.name, 'test-project');
137 | });
138 | });
139 |
140 | describe('name', () => {
141 | it('should use the defined project name', () => {
142 | const pkg = { name: 'foo' };
143 | const res = config.normalize(pkg);
144 | assert(res.name);
145 | assert.equal(res.name, 'foo');
146 | });
147 |
148 | it('should get the project name when string is empty', () => {
149 | const pkg = { name: '' };
150 | const res = config.normalize(pkg);
151 | assert(res.name);
152 | assert.equal(res.name, 'test-project');
153 | });
154 |
155 | it('should get the project name when missing', () => {
156 | const pkg = {};
157 | const res = config.normalize(pkg);
158 | assert(res.name);
159 | assert.equal(res.name, 'test-project');
160 | });
161 |
162 | it('should use the normalize function defined on options', () => {
163 | const pkg = { name: 'foo' };
164 | const opts = {
165 | fields: {
166 | name: {
167 | type: ['string'],
168 | normalize: function custom() {
169 | return 'bar';
170 | }
171 | }
172 | }
173 | };
174 |
175 | const res = config.normalize(pkg, opts);
176 | assert(res.name);
177 | assert.equal(res.name, 'bar');
178 | });
179 | });
180 |
181 | describe('version', () => {
182 | it('should use the given version', () => {
183 | const pkg = { version: '1.0.0' };
184 | const res = config.normalize(pkg);
185 | assert(res.version);
186 | assert.equal(res.version, '1.0.0');
187 | });
188 |
189 | it('should use the default version', () => {
190 | const pkg = { version: '' };
191 | const res = config.normalize(pkg);
192 | assert(res.version);
193 | assert.equal(res.version, '0.1.0');
194 | });
195 |
196 | it('should emit a warning when version type is invalid', cb => {
197 | const pkg = { version: 5 };
198 | let count = 0;
199 |
200 | config.on('warning', function(method, key, err) {
201 | if (key === 'version') {
202 | count++;
203 | }
204 | });
205 |
206 | config.normalize(pkg);
207 | assert.equal(count, 1);
208 | cb();
209 | });
210 |
211 | it('should throw an error when version is invalid', cb => {
212 | const pkg = { version: 'foo' };
213 | try {
214 | config.normalize(pkg);
215 | cb(new Error('expected an error'));
216 | } catch (err) {
217 | assert(/invalid semver/.test(err.message));
218 | cb();
219 | }
220 | });
221 | });
222 |
223 | describe('main', () => {
224 | it('should remove the property if the file does not exist', () => {
225 | const pkg = { main: 'foo.js' };
226 | const res = config.normalize(pkg);
227 | assert(!res.hasOwnProperty('main'));
228 | });
229 |
230 | it('should not remove the property if the file exists', () => {
231 | const pkg = { main: 'main.js' };
232 | const res = config.normalize(pkg);
233 | assert(res.hasOwnProperty('main'));
234 | });
235 |
236 | it('should add the main file to the `files` array', () => {
237 | const pkg = { main: 'main.js' };
238 | const res = config.normalize(pkg);
239 | assert.equal(res.files.indexOf('main.js'), 0);
240 | });
241 |
242 | it('should not add main file to files array when main file does not exist', () => {
243 | const pkg = {
244 | files: [],
245 | main: 'index.js'
246 | };
247 |
248 | const res = config.normalize(pkg);
249 | assert(!res.hasOwnProperty('files'));
250 | });
251 |
252 | it('should add main file to files array if files array is empty', () => {
253 | const pkg = {
254 | files: [],
255 | main: 'main.js'
256 | };
257 |
258 | const res = config.normalize(pkg);
259 | assert.equal(res.files.length, 1);
260 | assert.equal(res.files[0], 'main.js');
261 | });
262 |
263 | it('should create files array with main if undefined', () => {
264 | const pkg = {
265 | main: 'main.js'
266 | };
267 |
268 | const res = config.normalize(pkg);
269 | assert(res.files.length);
270 | assert(res.files.indexOf('main.js') !== -1);
271 | });
272 |
273 | it('should not double add the file to files', () => {
274 | const pkg = {
275 | files: ['main.js'],
276 | main: 'main.js'
277 | };
278 |
279 | const res = config.normalize(pkg);
280 | assert.equal(res.files.length, 1);
281 | assert(res.files.indexOf('main.js') !== -1);
282 | });
283 |
284 | it('should remove main if the file does not exist', () => {
285 | const pkg = { main: 'foo.js' };
286 |
287 | const res = config.normalize(pkg);
288 | assert(!res.main);
289 | });
290 |
291 | it('should do nothing if not defined', () => {
292 | const pkg = {};
293 |
294 | const res = config.normalize(pkg);
295 | assert.equal(typeof res.main, 'undefined');
296 | });
297 | });
298 |
299 | describe('files', () => {
300 | it('should remove a file if it does not exist', () => {
301 | const pkg = { files: ['foo.js', 'main.js'] };
302 | const res = config.normalize(pkg);
303 | assert.equal(res.files.length, 1);
304 | });
305 |
306 | it('should use `options.files`', () => {
307 | const res = config.normalize({}, { files: ['main.js'] });
308 | assert.equal(res.files.length, 1);
309 | });
310 |
311 | it('should remove the files array if it\'s empty', () => {
312 | const pkg = { files: [] };
313 | const res = config.normalize(pkg);
314 | assert(!res.files);
315 | });
316 |
317 | it('should remove the files array if a file that does not exist is removed', () => {
318 | const pkg = { files: ['foo.js'] };
319 | const res = config.normalize(pkg);
320 | assert(!res.files);
321 | });
322 | });
323 |
324 | describe('homepage', () => {
325 | it('should add a homepage from git repository', () => {
326 | const res = config.normalize({});
327 | assert(res.homepage);
328 | assert.equal(res.homepage, 'https://github.com/jonschlinkert/test-project');
329 | });
330 |
331 | it('should add repository when setting homepage', () => {
332 | const res = config.normalize({});
333 | assert(res.homepage);
334 | assert.equal(res.repository, 'jonschlinkert/test-project');
335 | });
336 |
337 | it('should use the given homepage', () => {
338 | const pkg = { homepage: 'https://github.com/assemble/assemble' };
339 | const res = config.normalize(pkg);
340 | assert(res.homepage);
341 | assert.equal(res.homepage, 'https://github.com/assemble/assemble');
342 | });
343 |
344 | it('should get homepage from repository.url', () => {
345 | const pkg = {
346 | homepage: '',
347 | repository: 'git://github.com/jonschlinkert/test-project.git'
348 | };
349 |
350 | const res = config.normalize(pkg);
351 | assert(res.homepage);
352 | assert.equal(res.homepage, 'https://github.com/jonschlinkert/test-project');
353 | });
354 | });
355 |
356 | describe('author', () => {
357 | it('should not add an empty author field', () => {
358 | const res = config.normalize({});
359 | assert(!res.hasOwnProperty('author'));
360 | });
361 |
362 | it('should not add an empty authors field', () => {
363 | const res = config.normalize({});
364 | assert(!res.hasOwnProperty('authors'));
365 | });
366 |
367 | it('should use the given author as a string', () => {
368 | const pkg = { author: 'Jon Schlinkert' };
369 | const res = config.normalize(pkg);
370 | assert(res.author);
371 | assert.equal(res.author, 'Jon Schlinkert');
372 | });
373 |
374 | it('should convert an author object to a string', () => {
375 | const pkg = {
376 | author: {
377 | name: 'Jon Schlinkert',
378 | url: 'https://github.com/jonschlinkert'
379 | }
380 | };
381 |
382 | const res = config.normalize(pkg);
383 | assert(res.author);
384 | assert.equal(res.author, 'Jon Schlinkert (https://github.com/jonschlinkert)');
385 | });
386 | });
387 |
388 | describe('maintainers', () => {
389 | it('should not add an empty maintainers field', () => {
390 | const res = config.normalize({});
391 | assert(!res.hasOwnProperty('maintainers'));
392 | });
393 | });
394 |
395 | describe('license', () => {
396 | it('should add MIT as the default license', () => {
397 | const res = config.normalize({});
398 | assert(res.hasOwnProperty('license'));
399 | assert.equal(res.license, 'MIT');
400 | });
401 |
402 | it('should return license as is if it is a string', () => {
403 | const res = config.normalize({ license: 'MIT' });
404 | assert(res.hasOwnProperty('license'));
405 | assert.equal(res.license, 'MIT');
406 | });
407 |
408 | it('should convert from an object to a string', () => {
409 | const res = config.normalize({ license: { type: 'MIT' } });
410 | assert(res.hasOwnProperty('license'));
411 | assert.equal(res.license, 'MIT');
412 | });
413 |
414 | it('should convert from an array to a string', () => {
415 | const res = config.normalize({ license: [{ type: 'MIT' }] });
416 | assert(res.hasOwnProperty('license'));
417 | assert.equal(res.license, 'MIT');
418 | });
419 | });
420 |
421 | describe('people', () => {
422 | beforeEach(() => {
423 | config = new Normalizer({ verbose: false });
424 | });
425 |
426 | describe('contributors', () => {
427 | it('should not add an empty contributors field', () => {
428 | const res = config.normalize({});
429 | assert(!res.hasOwnProperty('contributors'));
430 | });
431 |
432 | it('should convert contributor objects to strings', () => {
433 | const pkg = {
434 | contributors: [{
435 | name: 'Jon Schlinkert',
436 | url: 'https://github.com/jonschlinkert'
437 | }]
438 | };
439 | const res = config.normalize(pkg);
440 | assert(res.contributors);
441 | const expected = 'Jon Schlinkert (https://github.com/jonschlinkert)';
442 | assert.equal(res.contributors[0], expected);
443 | });
444 | });
445 | });
446 |
447 | describe('repository', () => {
448 | it('should use the given repository', () => {
449 | const pkg = { repository: 'jonschlinkert/foo' };
450 | const res = config.normalize(pkg);
451 | assert(res.repository);
452 | assert.equal(res.repository, 'jonschlinkert/foo');
453 | });
454 |
455 | it('should use the git remote url', () => {
456 | const pkg = { repository: '' };
457 | const res = config.normalize(pkg);
458 | assert(res.repository);
459 | assert.equal(res.repository, 'jonschlinkert/test-project');
460 | });
461 |
462 | it('should convert repository.url to a string', () => {
463 | const pkg = { repository: { url: 'https://github.com/jonschlinkert/foo.git' } };
464 | const res = config.normalize(pkg);
465 | assert(res.repository);
466 | assert.equal(res.repository, 'jonschlinkert/foo');
467 | });
468 | });
469 |
470 | describe('bugs', () => {
471 | beforeEach(() => {
472 | config = new Normalizer({ verbose: false });
473 | });
474 |
475 | it('should fix the bugs value based on repo information', () => {
476 | const pkg = { bugs: { url: 'jonschlinkert/foo' } };
477 | const res = config.normalize(pkg);
478 | assert(res.bugs);
479 | assert.equal(res.bugs.url, 'https://github.com/jonschlinkert/foo/issues');
480 | });
481 |
482 | it('should use the given bugs value', () => {
483 | const opts = { bugs: { url: 'jonschlinkert/foo' } };
484 | const res = config.normalize({}, opts);
485 | assert(res.bugs);
486 | assert.equal(res.bugs.url, 'https://github.com/jonschlinkert/foo/issues');
487 | });
488 |
489 | it('should use the value function passed on options', () => {
490 | const pkg = { bugs: '' };
491 | const res = config.normalize(pkg, {
492 | fields: {
493 | bugs: {
494 | type: ['string', 'object'],
495 | normalize: function custom() {
496 | return { url: 'abc' };
497 | }
498 | }
499 | }
500 | });
501 | assert(res.bugs);
502 | assert.equal(res.bugs.url, 'abc');
503 | });
504 |
505 | it('should use a custom type passed on options', () => {
506 | const pkg = { bugs: '', owner: 'foo' };
507 | const res = config.normalize(pkg, {
508 | extend: false,
509 | fields: {
510 | bugs: {
511 | type: ['object', 'string'],
512 | normalize: function custom(key, val, config, schema) {
513 | schema.update('repository', config);
514 | const bugs = {};
515 | bugs.url = config.homepage + '/bugs';
516 | return bugs;
517 | }
518 | }
519 | }
520 | });
521 |
522 | assert.equal(typeof res.bugs, 'object');
523 | assert(res.bugs.url);
524 | assert.equal(res.bugs.url, 'https://github.com/foo/test-project/bugs');
525 | });
526 |
527 | it('should use owner passed on options', () => {
528 | const pkg = { bugs: '' };
529 | const res = config.normalize(pkg, {
530 | owner: 'foo',
531 | extend: false,
532 | fields: {
533 | bugs: {
534 | type: ['object', 'string'],
535 | normalize: function custom(key, val, config, schema) {
536 | schema.update('repository', config);
537 | const bugs = {};
538 | bugs.url = config.homepage + '/bugs';
539 | return bugs;
540 | }
541 | }
542 | }
543 | });
544 |
545 | assert.equal(typeof res.bugs, 'object');
546 | assert(res.bugs.url);
547 | assert.equal(res.bugs.url, 'https://github.com/foo/test-project/bugs');
548 | });
549 |
550 | it('should convert bugs.url to a string when specified', () => {
551 | const pkg = { bugs: { url: 'https://github.com/jonschlinkert/foo.git' } };
552 | const res = config.normalize(pkg, {
553 | extend: false,
554 | fields: {
555 | bugs: {
556 | type: 'string',
557 | normalize: function(val, key, config) {
558 | return val.url;
559 | }
560 | }
561 | }
562 | });
563 | assert(res.bugs);
564 | assert.equal(res.bugs, 'https://github.com/jonschlinkert/foo.git');
565 | });
566 | });
567 |
568 | describe('license', () => {
569 | beforeEach(() => {
570 | config = new Normalizer({ verbose: false });
571 | });
572 |
573 | it('should convert a license object to a string', () => {
574 | const pkg = {
575 | license: {
576 | type: 'MIT',
577 | url: 'https://github.com/jonschlinkert/test-project/blob/master/LICENSE-MIT'
578 | }
579 | };
580 |
581 | const res = config.normalize(pkg);
582 | assert.equal(typeof res.license, 'string');
583 | assert.equal(res.license, 'MIT');
584 | });
585 | });
586 |
587 | describe('licenses', () => {
588 | beforeEach(() => {
589 | config = new Normalizer({ verbose: false });
590 | });
591 |
592 | it('should emit a deprecation warning when licenses is defined', cb => {
593 | const pkg = { licenses: { type: 'MIT' } };
594 | let count = 0;
595 |
596 | config.on('warning', function(method, key, err) {
597 | if (key === 'licenses') {
598 | count++;
599 | }
600 | });
601 |
602 | config.normalize(pkg);
603 | assert.equal(count, 1);
604 | cb();
605 | });
606 |
607 | it('should convert a licenses array to a license string', () => {
608 | const pkg = {
609 | licenses: [
610 | { type: 'MIT', url: 'https://github.com/jonschlinkert/test-project/blob/master/LICENSE-MIT' }
611 | ]
612 | };
613 |
614 | const res = config.normalize(pkg);
615 | assert(!res.licenses);
616 | assert(res.license);
617 | assert.equal(typeof res.license, 'string');
618 | assert.equal(res.license, 'MIT');
619 | });
620 |
621 | it('should convert from an object to a string', () => {
622 | const pkg = {
623 | licenses: { type: 'MIT', url: 'https://github.com/jonschlinkert/test-project/blob/master/LICENSE-MIT' }
624 | };
625 |
626 | const res = config.normalize(pkg);
627 | assert(!res.licenses);
628 | assert(res.license);
629 | assert.equal(typeof res.license, 'string');
630 | assert.equal(res.license, 'MIT');
631 | });
632 | });
633 |
634 | describe('dependencies', () => {
635 | beforeEach(() => {
636 | config = new Normalizer({ verbose: false });
637 | });
638 |
639 | it('should remove dependencies when empty when `omitEmpty` is true', () => {
640 | const pkg = { dependencies: {} };
641 | const res = config.normalize(pkg, { omitEmpty: true });
642 | assert(!res.dependencies);
643 | });
644 | });
645 |
646 | describe('devDependencies', () => {
647 | beforeEach(() => {
648 | config = new Normalizer({ verbose: false });
649 | });
650 |
651 | it('should remove empty devDependencies when omitEmpty is true', () => {
652 | const pkg = { devDependencies: {} };
653 | const res = config.normalize(pkg, { omitEmpty: true });
654 | assert(!res.devDependencies);
655 | });
656 | });
657 |
658 | describe('engineStrict', () => {
659 | beforeEach(() => {
660 | config = new Normalizer({ verbose: false });
661 | });
662 |
663 | it('should delete engineStrict and replace it with engine-strict', () => {
664 | const pkg = { engineStrict: true };
665 | const res = config.normalize(pkg);
666 | assert.equal(typeof res.engineStrict, 'undefined');
667 | assert.equal(res['engine-strict'], true);
668 | });
669 |
670 | it('should remove engineStrict from the object', () => {
671 | const pkg = { engineStrict: true };
672 | const res = config.normalize(pkg);
673 | assert(!res.hasOwnProperty('engineStrict'));
674 | });
675 | });
676 |
677 | describe('engine-strict', () => {
678 | beforeEach(() => {
679 | config = new Normalizer({ verbose: false });
680 | });
681 |
682 | it('should warn when engine-strict value is invalid', cb => {
683 | const pkg = { 'engine-strict': 'foo' };
684 | let count = 0;
685 |
686 | config.on('warning', function(method, key, err) {
687 | if (key === 'engine-strict') {
688 | count++;
689 | }
690 | });
691 |
692 | config.normalize(pkg);
693 | assert.equal(count, 1);
694 | cb();
695 | });
696 | });
697 |
698 | describe('scripts', () => {
699 | beforeEach(() => {
700 | config = new Normalizer({ verbose: false });
701 | });
702 |
703 | it('should clean up mocha scripts', () => {
704 | const pkg = { scripts: { test: 'mocha -R spec' } };
705 |
706 | const res = config.normalize(pkg);
707 | assert(res.scripts);
708 | assert.equal(typeof res.scripts, 'object');
709 | assert.equal(res.scripts.test, 'mocha');
710 | });
711 |
712 | it('should return scripts if it is an object', () => {
713 | const pkg = { scripts: { test: 'foo' } };
714 |
715 | const res = config.normalize(pkg);
716 | assert(res.scripts);
717 | assert.equal(typeof res.scripts, 'object');
718 | assert.equal(res.scripts.test, 'foo');
719 | });
720 | });
721 |
722 | describe('keywords', () => {
723 | beforeEach(() => {
724 | config = new Normalizer({ verbose: false });
725 | });
726 |
727 | it('should use the name to create keywords when the array is empty', () => {
728 | const pkg = { keywords: [] };
729 | const res = config.normalize(pkg);
730 | assert.equal(res.keywords[0], 'project');
731 | assert.equal(res.keywords[1], 'test');
732 | assert.equal(res.keywords.length, 2);
733 | });
734 |
735 | it('should sort keywords', () => {
736 | const pkg = { keywords: ['foo', 'bar', 'baz'] };
737 | const res = config.normalize(pkg);
738 | assert.equal(res.keywords[0], 'bar');
739 | assert.equal(res.keywords[1], 'baz');
740 | assert.equal(res.keywords[2], 'foo');
741 | });
742 |
743 | it('should remove duplicates', () => {
744 | const pkg = { keywords: ['foo', 'foo', 'foo', 'foo', 'bar', 'baz'] };
745 | const res = config.normalize(pkg);
746 | assert.equal(res.keywords.length, 3);
747 | });
748 | });
749 |
750 | describe('preferGlobal', () => {
751 | beforeEach(() => {
752 | config = new Normalizer({ verbose: false });
753 | });
754 |
755 | it('should warn when preferGlobal is defined and `bin` is not defined', cb => {
756 | const pkg = { preferGlobal: true };
757 | let count = 0;
758 |
759 | config.on('warning', function(method, key, err) {
760 | if (key === 'preferGlobal') {
761 | count++;
762 | }
763 | });
764 |
765 | const res = config.normalize(pkg);
766 | assert(res.preferGlobal);
767 | assert.equal(count, 1);
768 | cb();
769 | });
770 |
771 | it('should not warn when preferGlobal is defined and `bin` is defined', cb => {
772 | const pkg = { preferGlobal: true, bin: 'main.js' };
773 | let count = 0;
774 |
775 | config.on('warning', (method, key, err) => {
776 | if (key === 'preferGlobal') {
777 | count++;
778 | }
779 | });
780 |
781 | const res = config.normalize(pkg);
782 | assert(res.preferGlobal);
783 | assert.equal(count, 0);
784 | cb();
785 | });
786 |
787 | it('should return bin as-is when it is a string', () => {
788 | const pkg = { bin: 'main.js' };
789 |
790 | const res = config.normalize(pkg);
791 | assert(res.bin);
792 | assert.equal(res.bin, 'main.js');
793 | });
794 |
795 | it('should not add bin file to `files` when `options.bin` is false', () => {
796 | const pkg = { bin: 'main.js' };
797 |
798 | const res = config.normalize(pkg, { bin: false });
799 | assert(!res.files);
800 | });
801 |
802 | it('should add bin file to `files`', () => {
803 | const pkg = { bin: 'main.js' };
804 |
805 | const res = config.normalize(pkg);
806 | assert(res.files);
807 | assert.equal(res.files[0], 'main.js');
808 | });
809 | });
810 |
811 | describe('bin', () => {
812 | beforeEach(() => {
813 | config = new Normalizer({ verbose: false });
814 | });
815 |
816 | it('should not emit a warning when bin file string exists', cb => {
817 | const pkg = { bin: 'main.js' };
818 | let count = 0;
819 |
820 | config.on('warning', function(method, key, err) {
821 | if (key === 'bin') {
822 | count++;
823 | }
824 | });
825 |
826 | config.normalize(pkg);
827 | assert.equal(count, 0);
828 | cb();
829 | });
830 |
831 | it('should not emit a warning when bin file object exists', cb => {
832 | const pkg = { bin: { foo: 'main.js' } };
833 | let count = 0;
834 |
835 | config.on('warning', function(method, key, err) {
836 | if (key === 'bin') {
837 | count++;
838 | }
839 | });
840 |
841 | config.normalize(pkg);
842 | assert.equal(count, 0);
843 | cb();
844 | });
845 | });
846 | });
847 |
848 |
--------------------------------------------------------------------------------
/test/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('mocha');
4 | const assert = require('assert');
5 | const utils = require('../lib/utils');
6 |
7 | describe('utils', () => {
8 | describe('.arrayify', () => {
9 | it('should cast a value to an array', () => {
10 | assert.deepEqual(utils.arrayify(['foo']), ['foo']);
11 | assert.deepEqual(utils.arrayify('foo'), ['foo']);
12 | assert.deepEqual(utils.arrayify(), []);
13 | });
14 | });
15 | });
16 |
17 |
--------------------------------------------------------------------------------