-
Notifications
You must be signed in to change notification settings - Fork 13
Code Style
In order for the source code of the launcher to be cohesive, there are a few rules to follow. Current code might not respect these because it was written before these guidelines, but should be revised and refactored eventually.
Having ESLint installed (it’s already added as a devDependency in package.json
, so you should) and a formatter enabled should normalize everything when you’re coding.
- Use 2 spaces for indentation.
- Use CRLF file endings.
- Use const/let instead of var.
- No unused variables.
- Prefer single object arguments instead of many arguments.
- Use the factory function pattern where possible instead of classes.
- Always define types in comments.
- Use multi-line and single-line comments adequately.
Always use 2 spaces for indentation (this is configurable in Visual Studio Code).
- Always put spaces after commas, and on both sides of logical, comparison, string and assignment operators.
- Put spaces on both sides of the opening and closing parentheses of if, elseif, for, and switch blocks.
function download() {
return new Promise( ( resolve, reject ) => {
this.dl.run();
this.dl.events.on( 'error', () => {} );
this.dl.events.on( 'end', _fileName => {
if ( this.dl.hasFailed() ) {
return reject( global.locale.FSO_NETWORK_ERROR );
}
resolve();
} );
this.updateDownloadProgress();
} );
}
Always use CRLF for file endings (this is configurable in Visual Studio Code).
const somethingThatWontChange = "";
let somethingThatWillChange = "";
Don’t leave unused variables, delete them. If you must keep them unused, comment them out and explain why in the comment.
When a function requires many arguments, a single object should be used as the argument:
function someFnWithManyParameters( { param1, param2, param3, param4 } ) {}
someFnWithManyParameters( {
param1: "Some param",
param2: 2,
param3: await api.getSomething(),
param4: somethingElse
} );
Some examples in the repo: download.js unzip.js
Note that dependencies shouldn’t be directly imported (require
d) and used inside the function. The previous examples do not respect that, but will be corrected in future versions of the launcher. Here’s a correct example:
utils/download.js
// No requires in top of file.
// The http client used is imported here.
function makeDownload( { http } ) {
// Here we return the actual download function that now has access to the http dependency.
return function download( { originUrl } ) {
// Some init code here.
const dl = http.get( originUrl );
// Define functions.
function run() {
return dl.start();
}
function getProgress() {
return dl.getProgress().toFixed(2);
}
return {
// These functions will be usable outside.
run,
getProgress
}
}
}
utils/index.js
// Here the dependencies can be imported and initialized for functions in utils/ to use.
const someHttpClient = require( 'some-http-client');
const makeDownload = require( './download' );
// Preconfigure and initiate the httpClient.
const http = someHttpClient( { defaultHeaders: { 'auth': 'bearer ...' } } );
module.exports = {
// Pass in the already configured httpClient.
download: makeDownload( { http } ),
// ... the same for any other file in utils/
}
main.js
// Import the download function.
const { download } = require( './utils' );
// Use it, passing in parameters needed for the download.
const myFileDownload = download( { originUrl: 'https://example.com/someFile.zip' } );
// Call the public functions.
myFileDownload.run();
console.log( myFileDownload.getProgress() );
Inheritance (if really necessary...) can be achieved in this manner (completely different example):
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
return {sayName}
}
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const {sayName} = Person(name)
const doSomethingNerdy = () => console.log('nerd stuff')
return {sayName, doSomethingNerdy}
}
const jeff = Nerd('jeff')
jeff.sayName() //my name is jeff
jeff.doSomethingNerdy() // nerd stuff
Always define types in function comments for parameters and return types.
Since we do not use TypeScript, defining types in comments is the next best thing. Visual Studio Code will provide code-completion features and will be aware of types when provided this way:
/**
* Runs a child process and returns the output.
*
* @param {string} file File to run.
* @returns {Promise} Promise that resolves when the process has finished.
*/
function run( file ) {
return new Promise( ( resolve, _reject ) => {
const child = require( 'child_process' ).exec( file, { cwd: 'bin' } );
child.on( 'close', _code => resolve() );
child.stderr.on( 'data', data => console.log( 'stdout: ' + data ) );
} );
}
/**
* This is a multiline comment.
* Second line of this comment
*/
// This is a single line comment.
Classes and functions should always have multi-line comments preceding them, such as the previous example run()
.
Home · User docs · Developer docs · FAQ