├── Conduct.md ├── Guidelines.md ├── LICENSE ├── README.md ├── Style.md └── Tests.md /Conduct.md: -------------------------------------------------------------------------------- 1 | # hapi.js Code of Conduct 2 | 3 | Please be kind and courteous. There's no need to be mean or rude. Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. 4 | 5 | ## Purpose 6 | 7 | This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. We invite all those who participate in the hapi.js project to help us create safe and positive experiences for everyone. 8 | 9 | A primary goal of the hapi.js project is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, gender identity, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). 10 | 11 | A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. 12 | 13 | ## Enforcement 14 | 15 | This Code of Conduct is maintained and enforced by the hapi.js core contributors group. 16 | 17 | ## Scope 18 | 19 | This policy applies for any interaction with other hapi.js community members. 20 | 21 | Whether on GitHub, Twitter, IRC, Gitter, or any other venue, your actions matter. We expect all members of the hapi.js community, including both users and contributors, to behave respectfully to others regardless of venue and regardless whether the communication is about the hapi.js project or not. 22 | 23 | Expressing opinions which may offend others in public or in private may trigger a policy violation review. Our goal is to provide a safe and welcoming environment and when a conflict arises between one person's freedom of expression and another's sense of safety, we will take the necessary actions to ensure the project remains a welcoming and safe environment for all. 24 | 25 | A person's past contribution to the hapi.js project will not be considered when evaluating their behavior. No expertise or contribution excuse offensive behavior. 26 | 27 | ## Expected Behavior 28 | 29 | The following behaviors are expected and requested of all community members: 30 | 31 | - Participate in an productive and active way. In doing so, you contribute to the health and longevity of this community. 32 | - Exercise consideration and respect in your speech and actions. 33 | - Attempt collaboration before conflict. 34 | - Refrain from demeaning, discriminatory, or harassing behavior and speech. 35 | - Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous 36 | situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. 37 | - Remember that community event venues may be shared with members of the public. Please be respectful to all patrons 38 | of these locations. 39 | 40 | ## Unacceptable Behavior 41 | 42 | The following behaviors are considered harassment and are unacceptable within our community: 43 | 44 | - Violence, threats of violence or violent language directed against another person. 45 | - Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. 46 | - Posting or displaying sexually explicit or violent material. 47 | - Posting or threatening to post other people's personally identifying information ("doxing"). 48 | - Personal insults, particularly those related to gender, gender identity, sexual orientation, race, religion, or disability. 49 | - Inappropriate photography or recording. 50 | - Inappropriate physical contact. You should have someone's consent before touching them. 51 | - Unwelcome sexual attention. This includes, sexualized comments or jokes, inappropriate touching, groping, and 52 | unwelcomed sexual advances. 53 | - Deliberate intimidation, stalking or following (online or in person). 54 | - Advocating for, or encouraging, any of the above behavior. 55 | - Sustained disruption of community events, including talks and presentations. 56 | 57 | ## Consequences of Unacceptable Behavior 58 | 59 | Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. 60 | 61 | When possible, a warning should be given before taking other actions. Anyone asked to stop unacceptable behavior is expected to comply immediately. If you disagree, first take steps to suspend and remove the offending materials or actions, then raise your objections in a polite and appropriate manner. If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should reach out via the contacts below with a description of your grievance. 62 | 63 | If someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could have communicated better. Remember that it's your responsibility to make your fellow community members comfortable, safe, and welcomed. 64 | 65 | If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). 66 | 67 | ## Contact Information 68 | 69 | You may contact one or more of the listed [team members](https://github.com/orgs/hapijs/people). 70 | 71 | ## License and attribution 72 | 73 | This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). 74 | Adapted from [Citizen Code of Conduct](http://citizencodeofconduct.org/), and the [Rust Project Code of Conduct](http://www.rust-lang.org/conduct.html). 75 | 76 | -------------------------------------------------------------------------------- /Guidelines.md: -------------------------------------------------------------------------------- 1 | # Running a hapijs Repository 2 | 3 | The purpose of this document is to outline procedures and guidelines for the operation of a repository under the [hapijs](https://github.com/hapijs) umbrella. The number of modules and repositories under the [hapijs](https://github.com/hapijs) organization will continue to grow so it is important that every repository has a certain amount of parity. This allows for the community to instantly have a level of familiarity regardless of the repository they are working in. 4 | 5 | ## Documentation 6 | 7 | Each module should have two markdown files in the root of their repositories with the content described below: 8 | 9 | * README.md 10 | - name of module 11 | - build status badges (travis-ci, etc) 12 | - name of lead maintainer 13 | - sponsorship information, if applicable 14 | - short description of the plugin 15 | - short example of a common use case (with code) 16 | - link to API.md 17 | * API.md 18 | - API documentation, in a format as similar to the API.md of [the](https://github.com/hapijs/hapi/blob/master/API.md) [other](https://github.com/hapijs/joi/blob/master/API.md) [repos](https://github.com/hapijs/good/blob/master/API.md) as possible 19 | 20 | ## Labels 21 | 22 | Every [hapijs](https://github.com/hapijs) repository should make generous use of labels. Labels help to make triaging issues easier. Below is the list of labels that every repository should be using and a brief explanation of the intent of the label. 23 | 24 | - `breaking change` - tag issues and pull requests with this change if, when the code is merged, it will cause a breaking change in the current version. `breaking change` issues should be attached to the appropriate milestone. 25 | - `bug` - issues that have been *confirmed* (with reproducible steps) to be bugs in the code should be tagged with `bug`. 26 | - `dependency` - if the issue or pull request addresses a dependency issue, it should have the `dependency` tag. Any module that is running in production should have a version >= 1.0.0 and all of it's dependencies should follow suite. 27 | - `discussion` - this tag gets applied to issues that are ideas or requests from the community that need active input from other community members and possibly the Lead Maintainer. 28 | - `enhancement` - non-breaking changes that would generally require a bump in the minor version number. 29 | - `good first issue` - tasks that are sufficiently small and easy for new contributors to complete, and which collaborators don't mind assisting new contributors in completing. 30 | - `help wanted` - issues where the hapijs team is actively requesting community feedback should be tagged with `help wanted`. Issues like, [who is using hapi](https://github.com/hapijs/hapi/issues/1613) or [the joi bug hunt](https://github.com/hapijs/joi/issues/281) are recent examples of `help wanted` issues. 31 | - `maintenance` - tasks that are related to refactoring or other code changes that don't fix bugs or add enhancements 32 | - `non-issue` - this label is used when a user reports something that they perceive as a bug in a hapijs module but ultimately ends up being a user error. Often, issues tagged with `non-issue` will lead to updated documentation or additional validation. 33 | - `question` - generic label for user questions. 34 | - `release notes` - if the changes to a module are really broad, a new issue should be created and labeled with `release notes`. The issue should document what the changes are, how it impacts existing code and how to migrate to the next version. 35 | - `request` - issues that are asking for specific changes and have been approved by the community or hapijs team, should have the `request` label applied to them. This label can be useful for people looking for ways to contribute to the hapijs ecosystem. 36 | - `security` - issues that improve or fix existing security deficiencies should be labeled with `security`. 37 | 38 | ## Milestones 39 | 40 | Milestones are used to keep track of future releases. Both issues and pull requests related to the future release should have a milestone attached to them. Milestone names should be the same as the semantic version of the module. Once all of the attached issues and pull requests are completed, a new version of the module should be published to the npm registry. The milestone is then considered "complete" and should be closed. There should always be one open milestone setup. After closing a milestone, create a new one incrementing the patch number (x.x.patch). When assigning an issue to a milestone that is not just a bug fix but a new feature or breaking change, edit the milestone to reflect the new version. This is critical as it is the only clear way to communicate between collaborators what the changes in master include. Do no assign milestones to questions, discussions, any issue that does not result in a code change, documentation, examples, or pure tests changes. When publishing a new version to npm, tag master with git tag -a v1.2.3 -m 'version 1.2.3' and git push origin --tags. Then close the milestone matching the release and create a new one. 41 | 42 | ## Releases 43 | 44 | In the [hapijs](https://github.com/hapijs) universe, we take releases very seriously because we are maintaining enterprise-grade software. We strictly adhere to [semantic versioning](http://semver.org/) for all versions. When a milestone is completed, the Lead Maintainer will go through the following steps: 45 | 46 | 1. Make sure the local master branch is 100% up to date with `upstream:master`. 47 | 2. Run `npm publish` in the command line to update the npm registry. 48 | 3. Tag the version just published to npm. Run `git tag -a vx.y.z -m "version x.y.z"` where `x.y.z` matches the `version` key in "package.json". The format of the tag and the message should match exactly as in the example. 49 | 4. Update the tags in the `upstream` remote via `git push upstream --tags`. 50 | 51 | ## Issues 52 | 53 | Issues can be created by anyone with a GitHub account. They should be tagged by any [hapijs organization](https://github.com/orgs/hapijs/people) members with access. Issues can be closed by the original requester, any member of the Core team, and the Lead Maintainer. Conversely, a Core team member or the Lead Maintainer can reopen issues at their discretion. It is important to keep issues maintained as it provides a task list for the community of contributors. 54 | 55 | Issues that are closed with a pull request should be linked together to keep the "paper trail" intact. 56 | 57 | Be mindful when closing issues as it is one of the primary ways we, as an organization, communicate with the community. Try to make sure the issue has been sufficiently resolved before closing it. In other words, don't be a jerk about closing issues. 58 | 59 | ## Retiring 60 | 61 | Sometimes one of the [hapijs](https://github.com/hapijs) modules becomes outdated or obsolete. At that time, the team will decide the next steps to take with the module. If the team has decided that the module is no longer useful, it will be immediately retired. If the module is still useful by the general community, a request for a new maintainer will be sent through the normal communication channels. If no one volunteers to take over the project after one week, it is retired. 62 | 63 | If a new maintainer does volunteer, the repository ownership is transfered out of the hapijs organization to the new maintainer. The license must be updated to remove any mention of Walmart or hapijs. 64 | 65 | ### Steps to Retire 66 | 67 | 1. "README.md" is updated with the "Retired" image and the message "No longer being maintained". A link should also be added that points to the last version's "README.md". 68 | 2. Tag all open issues with the "deprecated" tag and then close them. Disable issues globally in the repository settings. 69 | 3. Bump the minor version of the module in "package.json". 70 | 4. The Lead Maintainer should then follow the steps for [releases](#releases). 71 | 5. The Lead Maintainer should issue an `npm deprecate` command and deprecate all versions of the module. 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2015, Walmart and other contributors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * The names of any contributors may not be used to endorse or promote 12 | products derived from this software without specific prior written 13 | permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | * * * 27 | 28 | The complete list of contributors can be found at: https://github.com/hapijs/contrib/graphs/contributors 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | contrib 2 | ======= 3 | 4 | Discussion forum for project contributors 5 | -------------------------------------------------------------------------------- /Style.md: -------------------------------------------------------------------------------- 1 | # Coding Conventions 2 | 3 | ## JavaScript 4 | 5 | ### Language 6 | 7 | #### Strict Mode 8 | 9 | - The first line of every file should be `'use strict';`. If the file contains a shebang, strict mode should be enabled on the second line. 10 | - The strict mode directive should be followed by a blank line. 11 | ```javascript 12 | 'use strict'; 13 | 14 | // Right 15 | console.log('even when not required'); 16 | 17 | #!/usr/bin/env node 18 | 'use strict'; 19 | 20 | // Also right 21 | 22 | // Wrong 23 | 'use strict'; 24 | console.log('even when not required') 25 | ``` 26 | 27 | #### Semicolon 28 | 29 | - Always end statements with `;` 30 | ```javascript 31 | // Right 32 | console.log('even when not required'); 33 | 34 | // Wrong 35 | console.log('even when not required') 36 | ``` 37 | 38 | #### Variable declarations 39 | 40 | - Any variable that is only assigned once should be defined using `const`. 41 | - Any variable that is assigned multiple times should be defined using `let`. 42 | - Variables should not be declared using `var`. 43 | - Declare on first use, not at top of function; [self](#prototype-members) being an exception 44 | - Do not chain declarations unless inside `for` parentheses (repeat `const` or `let` for each variable in a separate statement) 45 | - Give descriptive names 46 | - Do not use similar names or synonyms for different variables unless following a convention 47 | - `for...in` iterators should use descriptive names 48 | - `for` iterators should use single character names 49 | - Use combination of plural for array and singular for each item in the array 50 | - Use camelCase, never underscores 51 | - Avoid using numbered variables (e.g. i1, i2, i3) 52 | 53 | #### Scope 54 | 55 | - No implicit or single statement scopes 56 | - All scopes must be wrapped in `{}` 57 | ```javascript 58 | // Right 59 | 60 | if (condition) { 61 | return; 62 | } 63 | 64 | // Wrong 65 | 66 | if (condition) return; 67 | 68 | if (condition) 69 | return; 70 | ``` 71 | 72 | #### For loops 73 | 74 | - Iterator variable should be declared inside the `for` parentheses, unless already defined 75 | - Iterator variables should be named `i` if possible. Nested `for` loops use `j`, `k`, etc. 76 | - Use `for` with arrays, `for...in` for objects (and always check `hasOwnProperty()`) 77 | - Always `++i`, never `i++` 78 | 79 | ```javascript 80 | // Right 81 | 82 | const name = 'john'; 83 | 84 | for (let i = 0; i < name.length; ++i) { 85 | console.log(name[i]); 86 | } 87 | 88 | // Wrong 89 | 90 | let position; 91 | const name = 'john' ; 92 | const len = name.length; 93 | 94 | for (position = 0; position < len; position++) { 95 | console.log(name[position]) ; 96 | } 97 | ``` 98 | 99 | #### Prototype members 100 | 101 | - Prefix private members with `_` 102 | ```javascript 103 | Example.prototype.method = function () { 104 | 105 | this.public = 'external'; 106 | this._private = 'internal'; 107 | }; 108 | ``` 109 | 110 | - Define `self` for passing `this` into nested functions 111 | ```javascript 112 | Example.prototype.method = function () { 113 | 114 | const self = this; 115 | 116 | call(123, function (err) { 117 | 118 | self.display(err); 119 | }); 120 | }; 121 | ``` 122 | 123 | #### Function declaration 124 | 125 | - Declare functions via assignment 126 | - Arrow function arguments must be enclosed in parentheses 127 | - Arrow function bodies must be enclosed in curly braces 128 | ``` javascript 129 | // Right 130 | 131 | const method = function () { 132 | 133 | }; 134 | 135 | const arrow = (foo) => { 136 | 137 | return bar; 138 | }; 139 | 140 | // Wrong 141 | 142 | function method() { 143 | 144 | } 145 | 146 | const arrow = foo => bar; 147 | ``` 148 | 149 | #### Enforcing new on Constructor 150 | 151 | - Use `this instanceof` to check if a constructor function was called with new. (This allows for future prototypical inheritance.) 152 | 153 | ```javascript 154 | Hoek.assert(this instanceof Server, 'Server must be instantiated using new'); 155 | ``` 156 | 157 | ### Style 158 | 159 | #### Whitespace 160 | 161 | - Always spaces, never tabs 162 | - 4 spaces indents 163 | - No trailing whitespace at end-of-line 164 | 165 | ```javascript 166 | // Right 167 | 168 | if (test) { 169 | if (value === 12) { 170 | console.log('result'); 171 | } 172 | } 173 | 174 | // Wrong 175 | 176 | if (test) { 177 | if (value === 12) { 178 | console.log('result'); 179 | } 180 | } 181 | ``` 182 | 183 | #### String literals 184 | 185 | - Always `'` never `"` 186 | ```javascript 187 | // Right 188 | const string = 'text in single quotes'; 189 | 190 | // Wrong 191 | const string = "text in single quotes"; 192 | ``` 193 | 194 | #### Newlines 195 | 196 | - all files need to end with a newline (or more accurately end of line). IDEs will often do a line separator instead. This is to ensure it is unix friendly. The "cat" command is a good example of seeing this behavior. Git does a good job of pointing these out when doing pull requests. 197 | 198 | - Two empty lines between module functions or assignments (end of function to comment about next function) 199 | ```javascript 200 | exports.get = function () { 201 | 202 | // Some code 203 | }; 204 | // 1 205 | // 2 206 | /** 207 | * jsDoc comment 208 | */ 209 | internals.utility = function () { 210 | 211 | //Some code 212 | }; 213 | ``` 214 | 215 | - Newline after `{` except for inlined or empty objects 216 | - Inline an object when it improves readability and unlikely to change often 217 | - No inline object in assignment unless empty 218 | 219 | ```javascript 220 | // Right 221 | 222 | if (condition) { 223 | execute(value, { strict: true }); 224 | } 225 | 226 | if (condition) { 227 | const options = { 228 | strict: true 229 | }; 230 | execute(value, options); 231 | } 232 | 233 | const empty = {}; 234 | 235 | // Wrong 236 | 237 | if (condition) { execute(value, { strict: true }); } 238 | 239 | if (condition) { 240 | const options = { strict: true }; 241 | execute(value, options); 242 | } 243 | 244 | const empty = { 245 | }; 246 | ``` 247 | 248 | - Newline after `}` 249 | - Only exception is when followed by `,`, `;`, `);` which must be followed by a newline 250 | - Includes before `else`, `catch`, etc. 251 | - Empty line after `}` if not last statement in scope 252 | 253 | ```javascript 254 | // Right 255 | 256 | if (condition) { 257 | value = { 258 | func: () => { 259 | 260 | console.log('example'); 261 | }, 262 | message: 'hello' 263 | }; 264 | 265 | execute(value, (err) => { 266 | 267 | console.log(err); 268 | }); 269 | } 270 | else { 271 | console.log('otherwise'); 272 | } 273 | 274 | // Wrong 275 | 276 | if (condition) { 277 | value = { 278 | func: () => { 279 | 280 | console.log('example'); 281 | }, message: 'hello' 282 | }; 283 | execute(value, (err) => { 284 | 285 | console.log(err); } 286 | ); 287 | } else { 288 | console.log('otherwise'); 289 | } 290 | ``` 291 | 292 | - Empty line after `{` 293 | - Following a multi-line condition 294 | - In function scope declarations 295 | - In arrow function declarations using curly braces 296 | 297 | ```javascript 298 | // Right 299 | 300 | exports.method = function () { 301 | 302 | if (condition) { 303 | if (otherCondition) { 304 | console.log('sometimes'); 305 | } 306 | 307 | if (result && 308 | result.statusCode === 200) { 309 | 310 | console.log('special case'); 311 | } 312 | 313 | console.log('always'); 314 | } 315 | 316 | execute(123, (err) => { 317 | 318 | console.log(err); 319 | }); 320 | 321 | const empty = {}; 322 | }; 323 | 324 | // Wrong 325 | 326 | exports.method = function () { 327 | if (condition) { 328 | 329 | if (otherCondition) { 330 | 331 | console.log('sometimes'); 332 | } 333 | 334 | if (result && 335 | result.statusCode === 200) { 336 | console.log('special case'); 337 | } 338 | 339 | console.log('always'); 340 | } 341 | 342 | execute(123, (err) => { 343 | console.log(err); 344 | }); 345 | 346 | const empty = { 347 | }; 348 | }; 349 | ``` 350 | 351 | - No empty line before end of scope 352 | ```javascript 353 | // Right 354 | 355 | if (condition) { 356 | if (otherCondition) { 357 | console.log('done'); 358 | } 359 | } 360 | 361 | // Wrong 362 | 363 | if (condition) { 364 | if (otherCondition) { 365 | console.log('done'); 366 | 367 | } 368 | 369 | } 370 | ``` 371 | 372 | #### Spaces 373 | 374 | - Use one and only one space (when required) 375 | ```javascript 376 | // Right 377 | const value = calculate(1, 3); 378 | 379 | // Wrong 380 | const value = calculate(1, 3); 381 | ``` 382 | 383 | - One space between function and `(` when declaring a function 384 | ```javascript 385 | // Right 386 | 387 | const example = function () { 388 | 389 | return value; 390 | }; 391 | 392 | // Wrong 393 | 394 | const example = function() { 395 | 396 | return value; 397 | }; 398 | ``` 399 | 400 | - No space between function name and `(` when invoking a function 401 | ```javascript 402 | // Right 403 | 404 | const key = example(); 405 | 406 | // Wrong 407 | 408 | const key = example (); 409 | ``` 410 | 411 | - No space after `(` or before `)` 412 | ```javascript 413 | // Right 414 | 415 | execute('order', 34); 416 | 417 | if (result === 'ok') { 418 | console.log('success'); 419 | } 420 | 421 | // Wrong 422 | 423 | execute( 'order', 34 ); 424 | 425 | if ( result === 'ok' ) { 426 | console.log( 'success' ); 427 | } 428 | ``` 429 | 430 | - No space before object key `:`, always after object key `:` 431 | ```javascript 432 | // Right 433 | 434 | const obj = { 435 | a: 1, 436 | b: 2, 437 | c: 3 438 | }; 439 | 440 | // Wrong 441 | 442 | const obj = { 443 | a : 1, 444 | b :2, 445 | c:3 446 | }; 447 | ``` 448 | 449 | - No space before `;`, always after `;` if not end-of-line 450 | ```javascript 451 | // Right 452 | 453 | const name = 'john'; 454 | 455 | for (let i = 0; i < name.length; ++i) { 456 | console.log(name[i]); 457 | } 458 | 459 | // Wrong 460 | 461 | const name = 'john' ; 462 | 463 | for (let i = 0;i < name.length ;++i) { 464 | console.log(name[i]) ; 465 | } 466 | ``` 467 | 468 | - Always space after reserved keywords (`if`, `else`, `for`, `return`, `function`, etc.) 469 | ```javascript 470 | // Right 471 | 472 | for (let book in books) { 473 | if (books.hasOwnProperty(book)) { 474 | console.log(book.name); 475 | } 476 | } 477 | 478 | // Wrong 479 | 480 | for(let book in books) { 481 | if(books.hasOwnProperty(book)) { 482 | console.log(book.name); 483 | } 484 | } 485 | ``` 486 | 487 | - Always space after `{` and before `}` in inlined object 488 | - No space for empty objects `{}` 489 | - One space for empty functions `{ }` 490 | 491 | ```javascript 492 | // Right 493 | 494 | execute({ name: 'john', email: 'john@example.com' }); 495 | const empty = {}; 496 | const callback = () => { }; 497 | 498 | // Wrong 499 | 500 | execute({name: 'john', email: 'john@example.com'}); 501 | const empty = { }; 502 | const callback = () => {}; 503 | ``` 504 | 505 | - No space after `[` and before `]` in inlined arrays 506 | ```javascript 507 | // Right 508 | const numbers = [1, 2, 3]; 509 | 510 | // Wrong 511 | const numbers = [ 1, 2, 3 ]; 512 | ``` 513 | 514 | - Always space after `//` 515 | ```javascript 516 | // Right 517 | // Some comment 518 | 519 | // Wrong 520 | //Some comment 521 | ``` 522 | 523 | - No space before `,`, always after `,` unless end-of-line 524 | ```javascript 525 | // Right 526 | 527 | const numbers = [1, 2, 3]; 528 | execute({ name: 'john', email: 'john@example.com' }); 529 | 530 | for (let i = 0; i < name.length; ++i) { 531 | console.log(name[i]); 532 | } 533 | 534 | // Wrong 535 | 536 | const numbers = [1,2 ,3]; 537 | execute({ name: 'john',email: 'john@example.com' }); 538 | 539 | // This for loop violates the style guide, but illustrates incorrect spacing around a comma 540 | for (let i = 0,il = name.length; i < il; ++i) { 541 | console.log(name[i]); 542 | } 543 | ``` 544 | 545 | - Always space before and after operators, unless following an indent or end-of-line 546 | 547 | ```javascript 548 | // Right 549 | 550 | const a = 1 + 3; 551 | const b = 'john' + 552 | ' ' + 553 | 'doe'; 554 | 555 | // Wrong 556 | 557 | const a=1+3; 558 | const b='john'+ 559 | ' '+ 560 | 'doe'; 561 | ``` 562 | 563 | #### Commas 564 | 565 | - Never begin a line with `,` (always at the end of the previous line) 566 | ```javascript 567 | // Right 568 | execute('some error message', 569 | 12345, 570 | this); 571 | 572 | // Wrong 573 | execute('some error message' 574 | ,12345 575 | ,this); 576 | ``` 577 | 578 | #### Operators 579 | 580 | - Never begin a line with an operator (always at the end of the previous line) 581 | ```javascript 582 | // Right 583 | 584 | const message = 'Hello ' + 585 | 'Steve, ' + 586 | 'How are you?'; 587 | 588 | if (value === 'hello' && 589 | result === 'ok') { 590 | 591 | console.log('yes'); 592 | } 593 | 594 | // Wrong 595 | 596 | const message = 'Hello ' 597 | + 'Steve, ' 598 | + 'How are you?'; 599 | 600 | if (value === 'hello' 601 | && result === 'ok') { 602 | 603 | console.log('yes'); 604 | } 605 | ``` 606 | 607 | #### Ternary Operators 608 | 609 | - Never begin a line with a ternary operator. If a ternary statement must wrap, indent it further than the previous line by 4 spaces. 610 | 611 | ```javascript 612 | // Right 613 | 614 | const message = foo === bar ? 615 | foo : 616 | bar; 617 | 618 | // Wrong 619 | 620 | const message = foo === bar 621 | ? foo 622 | : bar; 623 | 624 | // Also Wrong 625 | 626 | const message = (foo === bar ? 627 | foo : 628 | bar); 629 | ``` 630 | 631 | #### Comments 632 | 633 | - Always use `//` unless it's a jsDoc declaration or license header 634 | - Always begin sentences with an upper case 635 | - No trailing `.` unless comment contains multiple sentences 636 | - Formal style, consistent voice, no humor, present tense 637 | - No developer name or other personal notes 638 | - No TODOs 639 | 640 | - Line 641 | - Provides narrative for the following single code line (or single statement broken for readability) 642 | - One line of comment only 643 | - One empty line before and none after the comment line 644 | - No empty line before when following `{` unless other rules require it 645 | 646 | ```javascript 647 | function execute() { 648 | 649 | // Initialize state 650 | const position = 0; 651 | 652 | if (condition) { 653 | // Return message 654 | return 'hello'; 655 | } 656 | } 657 | ``` 658 | 659 | - Segment 660 | - Provides narrative for the following code section (one or more lines of code, with or without line breaks) 661 | - One or more lines of comments 662 | - One empty line before and one after comments block 663 | 664 | ```javascript 665 | function execute() { 666 | 667 | // Print each book's name 668 | 669 | for (let book in books) { 670 | 671 | // Check for valid properties 672 | 673 | if (books.hasOwnProperty(book)) { 674 | console.log(book.name); 675 | } 676 | } 677 | } 678 | ``` 679 | 680 | - Note 681 | - Explains the behaviour of a single code statement (can be broken into multiple lines) 682 | - Used to document unexpected behaviour or non-standard practice 683 | - Appears immediately at the end of the line (or statement) it describes, following whitespace to separate it from code block 684 | 685 | ```javascript 686 | function execute(value) { 687 | 688 | if (value !== null && 689 | value !== undefined) { // Explicit check as 'value' can be 0 690 | 691 | console.log(value); 692 | } 693 | } 694 | ``` 695 | 696 | #### Multi-line statements 697 | 698 | - Statements should only be broken into multiple lines to improve readability 699 | - Break statements if they are longer than 150 characters long 700 | - No empty lines in the middle of a single statement 701 | - Indent multi-line statements 702 | 703 | - Conditions should be indented to the first character of the condition in the first line 704 | 705 | ```javascript 706 | if (result && 707 | result.status && 708 | result.status.statusCode === 200) { 709 | 710 | console.log('success'); 711 | } 712 | ``` 713 | 714 | - Variable should be indented to the first character of the value in the first line 715 | ```javascript 716 | const message = 'hello' + 717 | ' and welcome'; 718 | ``` 719 | 720 | ## Node 721 | 722 | ### Require 723 | 724 | - Use uppercase variable names for imported modules 725 | - All require statements must be declared at the top of the module 726 | - Always use relative paths 727 | 728 | ### Module globals 729 | 730 | - Every module can only have two top level globals (except for imported modules): 731 | - `exports` - defined automatically by node 732 | - `internals` - must be declared as an object at the top of each module immediate following the `require` section 733 | - Any variable global to the module must be a property of `internals`, including constants 734 | - If a module has automatically executing code, it must be contained within a function (using the `internals` namespace) and called at the top of the module after the `internals` declaration. 735 | 736 | ````javascript 737 | // Right 738 | 739 | const Hapi = require('hapi'); 740 | const Hoek = require('hoek'); 741 | const Package = require('./package.json'); 742 | 743 | const internals = { 744 | foo: 'bar' 745 | }; 746 | 747 | internals.init = function () { 748 | 749 | const server = new Hapi.Server(); 750 | ... 751 | }; 752 | 753 | internals.init(); 754 | 755 | // Also right 756 | 757 | const Hapi = require('hapi'); 758 | 759 | const internals = {}; 760 | 761 | internals.package = require('./package.json'); 762 | internals.foo = 'bar'; 763 | internals.init = function () { 764 | 765 | const server = new Hapi.server(); 766 | ... 767 | }; 768 | 769 | internals.init(); 770 | 771 | // Wrong 772 | 773 | const hapi = require('hapi'); // Use uppercase name 774 | 775 | const foo = 'bar'; // No global vars outside of internals 776 | 777 | const internals = { 778 | Foo: 'bar' // Don't use uppercase vars inside internals 779 | }; 780 | 781 | const server = new Hapi.Server(); // No global vars outside of internals and exports / Set up your module inside an init() function 782 | ... 783 | 784 | const Hoek = require('hoek'); // Declare modules at the top of the module 785 | 786 | ```` 787 | 788 | ### Variable names 789 | 790 | - `err` is reserved for errors received via a callback. Use `error` for local function variables 791 | 792 | ### Callback 793 | 794 | - First argument must always be `err` 795 | - Inline callbacks must use arrow functions 796 | - If a function takes a `callback` argument, it **must** be called on `process.nextTick()`. Otherwise, the argument name **must** be `next` to clearly declare that it may get called on same tick 797 | - Callbacks should always be called with explicit `return` 798 | 799 | ### Promises 800 | 801 | - Public interfaces should (not must) return a promise when no callback is provided 802 | - Promises should not be used internally 803 | - Only native promises are allowed. Third party promise implementations are not allowed 804 | -------------------------------------------------------------------------------- /Tests.md: -------------------------------------------------------------------------------- 1 | # Writing Tests for hapijs Modules 2 | 3 | We want tests to be consistent from one repo to the next; one for readability and two to make it possible for [lab](https://github.com/hapijs/lab) to do "deep testing". Deep testing will allow the current module to test itself as well as all of the dependencies. 4 | 5 | ## Standards 6 | 7 | 1. Only create lab aliases for values the test actually uses. In other words, don't have `before` and `after` variables if the test never uses them. 8 | 2. Describing method tests should appear like this; "methodName()" and _not_ "#methodName" 9 | 3. Any non-functional test should appear at the top of the test _outside_ of any `describe` bocks. 10 | 4. Tests should no longer have an outer `describe` block. See 3 above. 11 | 12 | The full conversation can be found [here](https://github.com/hapijs/discuss/issues/24). 13 | --------------------------------------------------------------------------------