UNPKG

54.3 kBMarkdownView Raw
1<img src=docs/logo.png?2 width=180 alt=Builder><br />
2
3### Current version: 4.2.0 ###
4
5![Build Status](https://cse-ci.electricimp.com/app/rest/builds/buildType:(id:Builder_BuildAndTest)/statusIcon)
6
7## Contents ##
8
9- [About Builder](#about-builder)
10- [Builder Installation](#builder-installation)
11 - [Command Line Tool Installation](#command-line-tool-installation)
12 - [Library Installation](#library-installation)
13- [Builder Syntax](#builder-syntax)
14 - [Expressions](#expressions)
15 - [Types](#types)
16 - [Operators](#operators)
17 - [Binary](#binary)
18 - [Unary](#unary)
19 - [Member Expressions](#member-expressions)
20 - [Conditional Expressions](#conditional-expressions)
21 - [Variables](#variables)
22 - [Variable Definition Order](#variable-definition-order)
23 - [Environment Variables](#environment-variables)
24 - [Builder Variables](#builder-variables)
25 - [Builder Functions](#builder-functions)
26 - [Comments](#comments)
27 - [Directives](#directives)
28 - [@{...} – Inline Expressions/Macros](#-inline-expressionsmacros)
29 - [@set](#set)
30 - [@macro](#macro)
31 - [Define A Macro](#define-a-macro)
32 - [Use A Macro](#use-a-macro)
33 - [@include](#include)
34 - [@include once](#include-once)
35 - [@while](#while)
36 - [@repeat](#repeat)
37 - [@if... @elseif... @else](#if-elif-else)
38 - [@error](#error)
39 - [@warning](#warning)
40 - [Filters](#filters)
41- [Include Files](#include-files)
42 - [Searching The Included File](#searching-the-included-file)
43 - [Remote Include Files](#remote-include-files)
44 - [Supported Remote Resources](#supported-remote-resources)
45 - [Caching Remote Files](#caching-remote-files)
46 - [Saving And Reusing Versions Of Remote Files](#saving-and-reusing-versions-of-remote-files)
47 - [Proxy Access To Remote Files](#proxy-access-to-remote-files)
48- [Advanced Builder Usage](#advanced-builder-usage)
49 - [Reproducible Artifacts](#reproducible-artifacts)
50 - [Builder Variables: Directives](#builder-variables-directives)
51 - [Repository Files: Dependencies](#repository-files-dependencies)
52 - [Including JavaScript Libraries](#including-javascript-libraries)
53 - [Binding The Context Object Correctly](#binding-the-context-object-correctly)
54- [Testing](#testing)
55- [License](#license)
56
57# About Builder #
58
59Builder combines a preprocessor with an expression language and advanced imports.
60
61There are a number of ways in which you can [install Builder](#builder-installation) depending on how you plan to integrate it into your workflow. Once installed on your computer, you can use it to process your Squirrel application and factory firmware before you transfer the code to an impCentral™ Device Group.
62
63**Note** The [Electric Imp VS Code extension](https://github.com/electricimp/vscode) already incorporates Builder and can be used to upload code to Device Groups. If you are using the VS Code extension, there is no need install Builder separately to take advantage of its features.
64
65You can use Builder to pull the contents of separate code files into your main source code files. These additional files might contain library code that you make use of across a number of different products, or they might contain confidential data which you don’t want to keep inside source code files that are managed through a software version control system.
66
67You tell Builder which files to import, and where within your main source code they should be inserted, by using the [`@include`](#include) command. Builder is able to [access additional files](#include-files) that are stored on your computer or held remotely on an external resource (eg. HTTP/HTTPs server or a repository).
68
69While Builder can be used to insert code this way, it can be used in far more sophisticated ways thanks to its integrated expression processor and programming logic. For example, if you need to generate multiple versions of your application firmware for versions of your product which make use of different imp modules, you can use Builder’s [conditional execution features](#if-elif-else), [variables](#variables) and [loops](#while) to pull your various code components together at build time and output files that are ready to be transferred to impCentral.
70
71To speed up the process, [files that are stored remotely](#remote-include-files) which are not expected to change between builds can be cached for quick re-use. Builder's [reproducible artifacts](#reproducible-artifacts) feature makes it possible to store references to all files and variables, so that builds can be re-created for future debugging.
72
73For details on the commands that Builder offers, please see the [Directives](#directives) section. This is part of the [Builder Syntax](#builder-syntax) section, which also describes how Builder commands are structured.
74
75# Builder Installation #
76
77Builder requires Node.js 18.14.2 and above. It can be installed and used by two ways:
78
79- As an [_npm_ command line tool](#command-line-tool-installation)
80- As an [_npm_ library](#library-installation).
81
82## Command Line Tool Installation ##
83
84Install Builder:
85
86```sh
87npm install -g Builder
88```
89
90Now use Builder’s `pleasebuild` command to configure the newly installed utility:
91
92```sh
93pleasebuild [-l] [-D<variable> <value>]
94 [--github-token <token>] [--azure-user <username> --azure-token <token>]
95 [--bitbucket-server-addr <address>] [--bitbucket-server-user <username> --bitbucket-server-token <token>]
96 [--lib <path_to_file>] [--use-remote-relative-includes] [--suppress-duplicate-includes-warning]
97 [--cache] [--clear-cache] [--cache-exclude-list <path_to_file>]
98 [--save-dependencies [<path_to_file>]] [--use-dependencies [<path_to_file>]]
99 [--save-directives [<path_to_file>]] [--use-directives [<path_to_file>]]
100 <input_file>
101```
102
103where `<input_file>` is the path to source file which should be preprocessed and the other options are:
104
105| Option | Synonym | Mandatory? | Value&nbsp;Required? | Description |
106| --- | --- | --- | --- | --- |
107| -l | | No | No | Generates line control statements. For a more detailed explanation, please read [this GCC page](https://gcc.gnu.org/onlinedocs/gcc-4.5.4/cpp/Line-Control.html) |
108| -D&lt;variable&gt; | | No | Yes | Defines a [variable](#variables). May be specified several times to define multiple variables |
109| --github-token | | No | Yes | A GitHub [personal access token](https://github.com/settings/tokens). Password is not supported. |
110| --azure-user | | No | Yes | An Azure Repos username. |
111| --azure-token | | No | Yes | An Azure Repos personal access token. Should be specified if the `--azure-user` option is specified |
112| --bitbucket-server-addr | | No | Yes | A Bitbucket Server address. E.g., `https://bitbucket-srv.itd.example.com`. **Note**: this option is mandatory to include files from [Bitbucket Server](#bitbucket-server-repository) |
113| --bitbucket-server-user | | No | Yes | A Bitbucket Server username. |
114| --bitbucket-server-token | | No | Yes | A Bitbucket Server [personal access token](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html) or password (not recommended). Should be specified if the `--bitbucket-server-user` option is specified. |
115| --lib | --libs | No | Yes | Include the specified [JavaScript file(s) as a library](#including-javascript-libraries). May be specified several times to include multiple libraries. The provided value may specify a concrete file or a directory (all files from the directory will be included). The value may contain [wildcards](https://www.npmjs.com/package/glob) (all matched files will be included) |
116| --use-remote-relative-includes | | No | No | Interpret every non-absolute path in the [`@include`](#include) and [`@include once`](#include-once) directives as relative to the location of the source file where it is mentioned. See the [Include Files](#include-files) section |
117| --suppress-duplicate-includes-warning | --suppress-duplicate | No | No | Do not show a warning if a source file with the same content was included multiple times from different locations and this results in code duplication |
118| --cache | -c | No | No | Turn on caching for all files included from remote resources. See the [Caching Remote Files](#caching-remote-files) section. This option is ignored if the `--save-dependencies` option is specified (the cache is turned off for all files in this case). If the `--use-dependencies` option is specified the cache is turned off for the files referenced in the dependency file and is turned on for all other remote files |
119| --clear-cache | | No | No | Clear the cache before Builder starts running. See the [Caching Remote Files](#caching-remote-files) section |
120| --cache-exclude-list | | No | Yes | Set the path to the file that lists resources which should not be cached. the [Caching Remote Files](#caching-remote-files) section |
121| --save-dependencies | | No | No | Save references to the required [repository](#remote-include-files) files in the specified file. If a file name is not specified, the `dependencies.json` file in the local directory is used. See [‘Reproducible Artifacts’](#reproducible-artifacts) |
122| --use-dependencies | | No | No | Use the specified file to set which [repository](#remote-include-files) files are required. If a file name is not specified, the `dependencies.json` file in the local directory is used. See [‘Reproducible Artifacts’](#reproducible-artifacts). |
123| --save-directives | | No | No | Save Builder variable definitions in the specified file. If a file name is not specified, the `directives.json` file in the local directory is used. See [‘Reproducible Artifacts’](#reproducible-artifacts) |
124| --use-directives | | No | No | Use Builder variable definitions from the specified file. If a file name is not specified, the `directives.json` file in the local directory is used. See [‘Reproducible Artifacts’](#reproducible-artifacts) |
125
126## Library Installation ##
127
128Install Builder:
129
130```sh
131npm i --save Builder
132```
133
134Now instantiate, configure and execute Builder from within your source code. For example:
135
136```js
137const Builder = require('Builder');
138const builder = new Builder();
139
140// Specify whether you need line control statements. See the "-l" CLI option.
141builder.machine.generateLineControlStatements = <true|false>;
142
143// Cache all files included from remote sources. See the "--cache" CLI option.
144builder.machine.useCache = <true|false>;
145
146// Set GitHub credentials. See the "--github-token" CLI option.
147builder.machine.readers.github.token = "<PERSONAL_ACCESS_TOKEN>";
148
149// Set Azure Repos credentials. See the "--azure-user" and "--azure-token" CLI options.
150builder.machine.readers.azureRepos.username = "<USERNAME>";
151builder.machine.readers.azureRepos.token = "<ACCESS_TOKEN>";
152
153// Set Bitbucket Server address and credentials. See the "--bitbucket-server-*" CLI options.
154builder.machine.readers.bitbucketSrv.serverAddr = "<ADDRESS>";
155builder.machine.readers.bitbucketSrv.username = "<USERNAME>";
156builder.machine.readers.bitbucketSrv.token = "<PASSWORD_OR_ACCESS_TOKEN>";
157
158// Path to the file that lists the resources which should be excluded from caching.
159// See the "--cache-exclude-list" CLI option.
160builder.machine.excludeList = "<PATH_TO_FILE>";
161
162// Interpret a non-absolute path in includes as relative to the current file.
163// See the "--use-remote-relative-includes" CLI option.
164builder.machine.remoteRelativeIncludes = <true|false>;
165
166// Suppress warning about duplicate includes.
167// See the "--suppress-duplicate-includes-warning" CLI option.
168builder.machine.suppressDupWarning = <true|false>;
169
170// See the "--save-dependencies" CLI option.
171builder.machine.dependenciesSaveFile = <false|"PATH_TO_FILE">;
172// See the "--use-dependencies" CLI option.
173builder.machine.dependenciesUseFile = <false|"PATH_TO_FILE">;
174
175// See the "--save-directives" CLI option.
176builder.machine.directivesSaveFile = <false|"PATH_TO_FILE">;
177// See the "--use-directives" CLI option.
178builder.machine.directivesUseFile = <false|"PATH_TO_FILE">;
179
180const inputFile = "PATH_TO_YOUR_INPUT_FILE";
181
182// Set the directory of the input file as one of search dirs.
183// path.resolve() is used to get the absolute path (requires the path nodejs module)
184builder.machine.readers.file.inputFileDir = path.resolve(inputFile);
185
186const result = builder.machine.execute(`@include "${inputFile}"`);
187console.log(result);
188```
189
190To understand Builder configuration, please review [this source code](./src/cli.js).
191
192# Builder Syntax #
193
194## Expressions ##
195
196### Types ###
197
198The following value types are supported in expressions:
199
200- *numbers* (eg. `1`, `1E6`, `1e-6`, `1.567`)
201- *strings* (eg. `"abc"`, `'abc'`)
202- *booleans* (eg. `true`, `false`)
203- `null`
204
205### Operators ###
206
207Builder supports the following operators:
208
209#### Binary ####
210
211`||`&nbsp;&nbsp;`&&`&nbsp;&nbsp;`==`&nbsp;&nbsp;`!=`&nbsp;&nbsp;`<`&nbsp;&nbsp;`>`&nbsp;&nbsp;`<=`&nbsp;&nbsp;`>=`&nbsp;&nbsp;`+`&nbsp;&nbsp;`-`&nbsp;&nbsp;`*`&nbsp;&nbsp;`/`&nbsp;&nbsp;`%`
212
213#### Unary ####
214
215`+`&nbsp;&nbsp;`-`&nbsp;&nbsp;`!`
216
217### Member Expressions ###
218
219Membership of an object is expressed using any of the following expressions:
220
221- `somevar.member`
222- `somevar["member"]`
223- `([1, 2, 3])[1]`
224
225### Conditional Expressions ###
226
227Builder provides the standard ternary operator (`?:`) for evaluating basic conditions:
228
229`<condition> ? <if_condition_true> : <if_condition_false>`
230
231### Variables ###
232
233Variables can be used in Builder expressions. Variable names can contain `$`, `_`, latin letters and digits, however they must not start with a digit. Variables can be defined in the following ways:
234
235- Builder's [`@set`](#set) directive.
236- Your computer's [environment variables](#environment-variables).
237- Pass the option `-D<variable name> <variable value>` to Builder’s [`pleasebuild`](#command-line-tool-installation) command.
238
239All undefined variables are evaluated as `null`.
240
241#### Variable Definition Order ####
242
243When resolving a variable’s value:
244
2451. Builder looks for its definition among the command line parameters (as `-D<variable name> <variable value>`) passed to the [`pleasebuild`](#command-line-tool-installation) command.
2462. If no such variable definition is found, the code is scanned for [`@set`](#set) directive statements preceding the variable usage.
2473. If no variable definitions are found in the previous steps, Builder looks in the host environment variables.
248
249#### Environment Variables ####
250
251There is no special predicate required to make use of environment variables. Builder looks in the host environment variables to try and resolve the expressions if no command line or local variables have been set.
252
253For example, on a Mac:
254
255```squirrel
256server.log("Host home path is @{HOME}");
257```
258
259will print the home directory path of the current user of the system where Builder was executed.
260
261Environment variables differ based on OS. If you wish to use environment variables with Builder, a quick internet search will give you details on how to *list* the variables currently available on your system and also how to *set* new variables.
262
263#### Builder Variables ####
264
265Builder provides the following pre-defined variables:
266
267- `__LINE__` &mdash; The line number (relative to the file in which this variable appears). For example:
268
269 `Hi from line @{__LINE__}!`
270- `__FILE__` &mdash; The name of the file in which this variable appears. For example:
271
272 `Hi from file @{__FILE__}!`
273- `__PATH__` &mdash; The absolute path (not including file name) to the file where this variable appears. Can contain a URL for remote includes. For example:
274
275 `Hi from file @{__PATH__}!`
276
277- `__REPO_PREFIX__` &mdash; The root of the repository resource which is being processed. Is an internal variable of Builder. For example:
278
279 `github:electricimp/Builder`
280
281- `__REPO_REF__` &mdash; The git reference (branch name or tag) of the repository resource which is being processed. Is an internal variable of Builder.
282
283- `__URL_ROOT__` &mdash; The root of the remote weblink resource which is being processed. Is an internal variable of Builder. For example:
284<pre>
285 https://example.com
286 http://example.com:8080</pre>
287
288- `__URL_PATH__` &mdash; The path to the file on the remote weblink resource which is being processed, relative to the root of resource. Is an internal variable of Builder.
289
290<a id="loopvars"></a>
291
292Builder has two directives [`@while`](#while) and [`@repeat`](#repeat) for managing loops. Inside these loops the following variables are available:
293
294- `loop.index` &mdash; 0-indexed iteration counter
295- `loop.iteration` &mdash; 1-indexed iteration counter
296
297Usage examples for these variables can be found in the [`@while`](#while) and [`@repeat`](#repeat) directive examples.
298
299### Builder Functions ###
300
301Builder provides the following helper functions:
302
303- `defined(<variable_name>)` &mdash; returns `true` if a variable is defined, `false` otherwise.
304- `include(<source>)` &mdash; includes external source.
305- `escape(<value>)` &mdash; escapes special characters in string (`\b`, `\f`, `\n`, `\r`, `\t`, `\`, `'`, `"`).
306- `base64(<value>)` &mdash; encodes value as base64.
307- `min(<numbers>)` &mdash; returns a number equal to the lowest number in the supplied list.
308- `max(<numbers>)` &mdash; returns a number equal to the highest number in the supplied list.
309- `abs(<number>)` &mdash; returns the absolute value of the supplied number.
310
311Builder also comes with some string functions, based on the JavaScript methods of the same names. These functions are available under the namespace `S`. The first argument of each function is always the string to be operated on. For documentation on the remaining arguments, please see [‘JavaScript String Methods’](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String).
312
313- `S.concat()`
314- `S.endsWith()`
315- `S.includes()`
316- `S.repeat()`
317- `S.split()`
318- `S.startsWith()`
319- `S.substr()`
320- `S.substring()`
321- `S.toLowerCase()`
322- `S.toUpperCase()`
323- `S.trim()`
324- `S.trimLeft()`
325- `S.trimRight()`
326
327## Comments ##
328
329Lines starting with `@` followed by space or a line break are treated as comments and not added to the output. For example:
330
331```
332@ This is a Builder comment and will not appear in the output
333```
334
335Any text following `//` and extending to the end of the line will be ignored by Builder* and will not appear in the result output. For example:
336
337```
338@set SOME_STRING = "my string" // This is a Builder comment that will not appear in output
339```
340
341## Directives ##
342
343All of Builder’s directives start with the `@` symbol. Don’t include a space or line break between the `@` and the required directive’s name as this will be interpreted as a [comment](#comments).
344
345### @{...} Inline Expressions/Macros ###
346
347This directive evaluates the expression enclosed by braces (`{` and `}`) and inserts the result into the output. The enclosure can be the value of a named variable, an expression or a macro.
348
349<pre>
350<b>@{</b><i>&lt;variable:identifier&gt;</i><b>}</b>
351<b>@{</b><i>&lt;expression&gt;</i><b>}</b>
352<b>@{</b><i>macro(a, b, c)</i><b>}</b>
353</pre>
354
355#### Example ####
356
357The line:
358
359```
360The result is: @{123 * 456}.
361```
362
363results in the following output:
364
365```
366The result is: 56088.
367```
368
369### @set ###
370
371This directive assigns a value or the value of an expression to a [variable](#variables). Variables are defined in a global context. A value can be any supported [type](#types) or [function](#builder-functions).
372
373<pre>
374<b>@set </b><i>&lt;variable:identifier&gt; &lt;value:expression&gt;</i>
375<b>@set </b><i>&lt;variable:identifier&gt;</i> <b>=</b> <i>&lt;value:expression&gt;</i>
376</pre>
377
378#### Example ####
379
380In this example, we define a number of variables using `@set`, then use [`@{...}`](#-inline-expressionsmacros) to create squirrel log messages with those variables. If the following lines are added to your source code:
381
382```
383@ Set Builder global variables
384@set SOME_INT = 10
385@set SOME_STRING = "my string"
386@set BOOL_VAL = (12 > 4)
387@
388@ Use a Builder function to set a global variable
389@set MIN_INT min(1, 2, 3)
390@
391// Use Builder global variables in squirrel log messages
392server.log(@{SOME_INT});
393server.log("@{SOME_STRING}");
394server.log(@{BOOL_VAL});
395server.log(@{MIN_INT});
396```
397
398then during processing, Builder will output:
399
400```
401// Use Builder global variables in squirrel log messages
402server.log(10);
403server.log("my string");
404server.log(true);
405server.log(1);
406```
407
408### @macro ###
409
410This directive defines a code block with its own parameters. Macros are declared in a global scope. Macro parameters are only available within the macro scope and override global variables with the same name (but do not affect them).
411
412#### Define A Macro ####
413
414<pre>
415<b>@macro</b> <i>&lt;name&gt;</i>(<i>&lt;arguments&gt;</i>)
416 <i>&lt;body&gt;</i>
417<b>@endmacro</b>
418</pre>
419
420**Note** `@end` can be used in place of `@endmacro` if you prefer.
421
422#### Use A Macro ####
423
424Macros can be used either inline with the [`@{...}`](#-inline-expressionsmacros) directive, or with the [`@include`](#include) directive. When macros are used inline no line-control statements are generated for the output inside the macro scope and trailing newlines are trimmed from the macro output.
425
426<pre>
427<b>@{</b>macro<b>(</b>a, b ,c)<b>}</b>
428<b>@include</b> macro(a, b ,c)
429</pre>
430
431#### Inline Example ####
432
433Define a macro and use the [`@{...}`](#-inline-expressionsmacros) directive to create a multi-line string to log in squirrel:
434
435```
436@ Define a macro
437@macro some_macro(a, b, c)
438 Hello, @{a}!
439 Roses are @{b},
440 And violets are @{c}
441@end
442@
443// Use an inline Builder macro to create a multi-line string
444poem <- @"@{some_macro("username", "red", "blue")}";
445server.log(poem);
446```
447
448This results in the following output:
449
450```
451// Use an inline Builder macro to create a multi-line string
452poem <- @" Hello, username!
453 Roses are red,
454 And violets are blue";
455server.log(poem);
456```
457
458#### Include Example ####
459
460Define a macro and use it with [`@include`](#include) to create a multi-line string to log in squirrel:
461
462```
463@ Define a macro
464@macro some_macro(a, b, c)
465 Hello, @{a}!
466 Roses are @{b},
467 And violets are @{c}
468@end
469@
470// Use Builder include and macro directives to create a multi-line squirrel string
471poem <- @"
472@include some_macro("username", "red", "blue")
473";
474server.log(poem);
475```
476
477This results in the following output:
478
479```
480// Use Builder include and macro directives to create a multi-line squirrel string
481poem <- @"
482 Hello, username!
483 Roses are red,
484 And violets are blue
485";
486server.log(poem);
487```
488
489#### Optional Parameter Example ####
490
491Use a [function](#builder-functions) to configure and use a macro with an optional parameter.
492
493```
494@ Define a macro with an optional parameter
495@macro some_macro(a, b, c)
496 Hello, @{a}!
497 Roses are @{b},
498 And violets are @{defined(c) ? c : "of undefined color"}.
499@end
500@
501// Use Builder include and macro directives to create a multi-line squirrel string
502poem <- @"
503@include some_macro("username", "red")
504";
505server.log(poem);
506```
507
508This results in the following output:
509
510```
511// Use Builder include and macro directives to create a multi-line squirrel string
512poem <- @"
513 Hello, username!
514 Roses are red,
515 And violets are of undefined color.
516";
517server.log(poem);
518```
519
520### @include ###
521
522This directive can be used to include local files, files from remote resources or [macros](#macro).
523
524<pre>
525<b>@include</b> <i>&lt;source:expression&gt;</i>
526</pre>
527
528- For a [`@macro`](#macro):
529
530 <pre><b>@include</b> some_macro("username", 123)</pre>
531
532- For a local file:
533
534 <pre><b>@include</b> "somepath/somefile.ext"</pre>
535
536- For a file from remote resource:
537
538 <pre><b>@include</b> "someresource/somepath/somefile.ext"</pre>
539
540The **@** character must not be present in the path and name of the file which is being included.
541
542Please see the [Include Files](#include-files) section for information about include formats, file searching rules, supported remote resources, examples and other details.
543
544### @include once ###
545
546This directive acts just like `@include` but has no effect if the specified *source* has already been included. However, macros are always included.
547
548<pre><b>@include once</b> <i>&lt;source:expression&gt;</i></pre>
549
550### @while ###
551
552This directive invokes a loop which only ends when specified conditions are met. You can access Builder’s [loop variables](#loopvars) within `@while` loops.
553
554<pre>
555<b>@while</b> <i>&lt;test:expression&gt;</i>
556 // 0-based iteration counter: <b>@{</b>loop.index<b>}</b>
557 // 1-based iteration counter: <b>@{</b>loop.iteration<b>}</b>
558<b>@endwhile</b>
559</pre>
560
561**Note** `@end` may be used in place of `@endwhile` if you prefer.
562
563#### Example ####
564
565The following lines, when added to your source code:
566
567```
568@set myvar = 12
569
570@while myvar > 9
571 @set myvar = myvar - 1
572var: @{myvar}
573 loop.index: @{loop.index}
574 loop.iteration: @{loop.iteration}
575@end
576```
577
578will output:
579
580```
581var: 11
582 loop.index: 0
583 loop.iteration: 1
584var: 10
585 loop.index: 1
586 loop.iteration: 2
587var: 9
588 loop.index: 2
589 loop.iteration: 3
590```
591
592### @repeat ###
593
594This directive invokes a loop that repeats for a certain number of iterations. You can access Builder’s [loop variables](#loopvars) within `@repeat` loops.
595
596<pre>
597<b>@repeat</b> <i>&lt;times:expression&gt;</i>
598 // 0-based iteration counter: <b>@{</b>loop.index<b>}</b>
599 // 1-based iteration counter: <b>@{</b>loop.iteration<b>}</b>
600<b>@endrepeat</b>
601</pre>
602
603**Note** `@end` may be used in place of `@endrepeat` if you prefer.
604
605#### Example ####
606
607The following lines, when added to your source code:
608
609```
610@repeat 3
611 loop.index: @{loop.index}
612 loop.iteration: @{loop.iteration}
613
614@end
615```
616
617will output:
618
619```
620 loop.index: 0
621 loop.iteration: 1
622
623 loop.index: 1
624 loop.iteration: 2
625
626 loop.index: 2
627 loop.iteration: 3
628
629```
630
631<a id="if-elif-else"></a>
632
633### @if... @elseif... @else ###
634
635This directive provides conditional branching.
636
637<pre>
638<b>@if</b> <i>&lt;test:expression&gt;</i>
639 // Consequent code
640<b>@elseif</b> <i>&lt;test:expression&gt;</i>
641 // else if #1 code
642<b>@else</b>
643 // Alternative code
644<b>@endif</b>
645</pre>
646
647**Note** `@end` may be used in place of `@endif` if you prefer.
648
649#### Example ####
650
651```
652@if __FILE__ == 'abc.ext'
653 // include something
654@elseif __FILE__ == 'def.ext'
655 // include something else
656@else
657 // do something completely different
658@endif
659```
660
661### @error ###
662
663This directive simply emits an error.
664
665<pre>
666<b>@error</b> <i>&lt;message:expression&gt;</i>
667</pre>
668
669#### Example ####
670
671```
672@if PLATFORM == "platform1"
673 // platform 1 code
674@elseif PLATFORM == "platform2"
675 // platform 2 code
676@elseif PLATFORM == "platform3"
677 // platform 3 code
678@else
679 @error "Platform " + PLATFORM + " is unsupported"
680@endif
681```
682
683### @warning ###
684
685This directive simply emits a warning.
686
687<pre>
688<b>@warning</b> <i>&lt;message:expression&gt;</i>
689</pre>
690
691#### Example ####
692
693```
694@if PLATFORM == "platform1"
695 // platform 1 code
696@elseif PLATFORM == "platform2"
697 // platform 2 code
698@elseif PLATFORM == "platform3"
699 // platform 3 code
700@else
701 @warning "Building for default platform"
702 // default platform code
703@endif
704```
705
706## Filters ##
707
708The filter operator, `|`, allows you to pass a value through any of the supported [functions](#builder-functions).
709
710<pre>
711<b>@{</b>&lt;expression&gt;</i> | <i>&lt;filter&gt;</i><b>}</b>
712</pre>
713
714This is equivalent to:
715
716<pre>
717<b>@{</b><i>&lt;filter&gt;(&lt;expression&gt;)</i><b>}</b>
718</pre>
719
720#### Example ####
721
722```
723// Include external HTML piped through the escape processing function
724a = "@{include('index.html')|escape}"
725
726// Include an external binary piped through the base64 encoder function
727b = "@{include('file.bin')|base64}"
728```
729
730# Include Files #
731
732This section contains detailed information about usage of the [`@include`](#include) and [`@include once`](#include-once) directives to include local or remote files.
733
734**Local file** is a file on the same system where *Builder* is running.
735
736**Remote file** is a file on a remote resource (eg. a repository or a HTTP/HTTPs server). See the [Remote Include Files](#remote-include-files) section for the list of supported remote resources.
737
738The file mentioned in the [`@include`](#include) or [`@include once`](#include-once) directives may contain a **relative** or an **absolute path**.
739
740##### Examples: #####
741
742```
743@include "https://example.com/somefile.ext" // absolute path to remote file
744@include once "github:electricimp/Promise/promise.class.nut" // absolute path to remote file
745@include "c:\somefolder\somefile.ext" // absolute path to local file
746@include once "./somefile.ext" // relative path
747@include "somefile.ext" // relative path
748```
749
750The next section clarifies how *Builder* searches the included file.
751
752## Searching The Included File ##
753
754**Processed file** is a file currently being processed by *Builder*, it can be local or remote, it contains the [`@include`](#include) or [`@include once`](#include-once) directive(s).
755
756**Path to the processed file** is an absolute path to the processed file.
757
758**Path in the include** is the path mentioned in the [`@include`](#include) or [`@include once`](#include-once) directive, it can be an absolute path to local file, an absolute path to remote file or a relative path.
759
760**Full path to the include file** is an absolute path to the file which will be included by *Builder*.
761
762The below rules define how *Builder* searches the included file:
763
764### Absolute Path To Remote File ###
765
766If the path in the include is an absolute path to the remote file, it is considered as the final path to the include file. If the file is not found there, *Builder* reports an error.
767
768##### Examples: #####
769```
770@include "https://example.com/somefile.ext" // absolute path to remote file
771@include once "github:electricimp/Promise/promise.class.nut" // absolute path to remote file
772```
773
774### Absolute Path To Local File ###
775
776If the path in the include is an absolute path to the local file, it is considered as the final path to the include file. If the file is not found there, *Builder* reports an error.
777
778##### Examples: #####
779```
780@include "c:\somefolder\somefile.ext" // absolute path to local file
781@include "/home/user/someuser/somefolder/somefile.ext" // absolute path to local file. But see the note below.
782```
783
784**Note**: Under some conditions a path in the include which starts from the "**/**" symbol is processed by the special rule described below.
785
786### "/" As Root Of Remote Resource ###
787
788If
789
790- the first symbol of the path in the include is "**/**"
791- and the processed file is a remote file (ie. the file on a remote resource)
792- and the `--use-remote-relative-includes` option is specified
793
794then the final path to the include file is a concatenation of the root of remote resource and the path in the include. If the file is not found there, *Builder* reports an error. See the [Remote Include Files](#remote-include-files) section for the root definition of the supported remote resources.
795
796##### Examples: #####
797```
798The processed file: "https://example.com/folderA/folderB/somefile.nut"
799
800It contains:
801@include "/folderC/anotherfile.nut"
802
803The final path to the include: "https://example.com/folderC/anotherfile.nut"
804```
805
806```
807The processed file: "github:someuser/somerepo/folderA/folderB/somefile.nut@develop"
808
809It contains:
810@include "/folderC/anotherfile.nut"
811
812The final path to the include: "github:someuser/somerepo/folderC/anotherfile.nut@develop"
813```
814
815### Relative Path To Remote File ###
816
817If
818
819- the path in the include is a relative path
820- and the processed file is a remote file (ie. the file on a remote resource)
821- and the `--use-remote-relative-includes` option is specified
822
823then the final path to the include file is a concatenation of the path to the processed file and the path in the include. If the file is not found there, *Builder* reports an error.
824
825##### Examples: #####
826```
827The processed file: "https://example.com/folderA/folderB/somefile.nut"
828
829It contains:
830@include "anotherfile.nut"
831
832The final path to the include: "https://example.com/folderA/folderB/anotherfile.nut"
833```
834
835```
836The processed file: "github:someuser/somerepo/folderA/folderB/somefile.nut@v1.2.3"
837
838It contains:
839@include "folderC/anotherfile.nut"
840
841The final path to the include: "github:someuser/somerepo/folderA/folderB/folderC/anotherfile.nut@v1.2.3"
842```
843
844### Relative Path To Local File ###
845
846If
847
848- the path in the include is a relative path
849- and the processed file is a local file (or it is a remote file but the `--use-remote-relative-includes` option is not specified)
850
851then *Builder* makes the following steps to find the include file:
852
8531. Only if the processed file is a local file, the final path to the include file is a concatenation of the path to the processed file and the path in the include. If the file is not found there, moves to the next step.
8541. The final path to the include file is a concatenation of the path to the file specified as the `<input_file>` parameter of the `pleasebuild` command and the path in the include. If the file is not found there, moves to the next step. **Note**: If you use *Builder* as a library and want this search step to work, make sure you specify the input file path (`builder.machine.readers.file.inputFileDir` variable) in your source code within the Builder initialization routine. See the [Library Installation section](#library-installation) to learn more.
8551. The final path to the include file is a concatenation of the path to the directory from where the `pleasebuild` command has been called and the path in the include. If the file is not found there, *Builder* reports an error.
856
857##### Examples: #####
858```
859The processed file: "/home/user/someuser/folderA/somefile.ext"
860
861It contains:
862@include "folderX/anotherfile.nut"
863
864The "pleasebuild" command is called from: "/home/user/someuser/folderB"
865With the <input_file> parameter: "folderC/initialfile.nut"
866
867The anotherfile.nut file will be searched sequentially in the following locations:
8681. "/home/user/someuser/folderA/folderX/"
8692. "/home/user/someuser/folderB/folderC/folderX/"
8703. "/home/user/someuser/folderB/folderX/"
871```
872
873## Remote Include Files ##
874
875### Supported Remote Resources ###
876
877*Builder* supports file includes from the following types of remote resources:
878
879#### HTTP/HTTPs Server ####
880
881For includes from weblinks.
882
883##### Format: #####
884```
885@include "http://<server>[:<port>]/<path>"
886@include "https://<server>[:<port>]/<path>"
887@include once "http://<server>[:<port>]/<path>"
888@include once "https://<server>[:<port>]/<path>"
889```
890where:
891- `server` is the host name or IP address.
892- `port` is the port number.
893- `path` is the path to file.
894
895##### Examples: #####
896```
897@include "https://example.com/somefile.ext"
898@include once "http://example.com/folderA/folderB/somefile.nut"
899```
900
901##### Root of the remote resource: #####
902```
903http://<server>:<port>
904https://<server>:<port>
905```
906
907#### GitHub Repository ####
908
909For includes from [github.com](https://github.com).
910
911##### Format: #####
912```
913@include "github:<user>/<repo>/<path>[@<ref>]"
914@include once "github:<user>/<repo>/<path>[@<ref>]"
915```
916where:
917- `user` is the user/organization name.
918- `repo` is the repository name.
919- `path` is the path to file.
920- `ref` is the git reference (branch name or tag, defaults to _master_).
921
922##### Examples: #####
923```
924@include "github:electricimp/Promise/promise.class.nut" // head of the default branch
925@include "github:electricimp/Promise/promise.class.nut@develop" // head of the develop branch
926@include once "github:electricimp/Promise/promise.class.nut@v3.0.1" // tag v3.0.1
927```
928
929##### Root of the remote resource: #####
930```
931github:<user>/<repo>
932```
933
934##### Authentication: #####
935
936Authentication is optional. It is required to access private repositories only. But please note that when you use authentication, the GitHub API provides much higher rate limits.
937
938For the authentication you need to provide:
939- a GitHub username (`--github-user` option)
940- a GitHub [personal access token](https://github.com/settings/tokens) or a password, which is less secure and not recommended (`--github-token` option).
941
942#### Bitbucket Server Repository ####
943
944For includes from [Bitbucket Server](https://www.atlassian.com/software/bitbucket/download). **Note**, this is not the same as Bitbucket Cloud, includes from [Bitbucket.org](https://bitbucket.org/) are not supported.
945
946*Builder* can work with only one Bitbucket server at a time. Its address must be specified (`--bitbucket-server-addr` option). Server version **5.3.0** or above is supported.
947
948##### Format: #####
949```
950@include "bitbucket-server:<project>/<repo>/<path>[@<ref>]"
951@include "bitbucket-server:~<user>/<repo>/<path>[@<ref>]"
952@include once "bitbucket-server:<project>/<repo>/<path>[@<ref>]"
953@include once "bitbucket-server:~<user>/<repo>/<path>[@<ref>]"
954```
955where:
956- `project` is the project name. Should be used to include files from project repositories.
957- `user` is the user name. Should be used to include files from personal repositories. **Note**, the user name must be prepended with `~`. Eg, for the user name John it should be `~john`.
958- `repo` is the repository name.
959- `path` is the path to file.
960- `ref` is the git reference (branch name or tag, defaults to _master_).
961
962##### Examples: #####
963```
964@include "bitbucket-server:Tools/Promise/promise.class.nut" // head of the default branch
965@include once "bitbucket-server:Tools/Promise/promise.class.nut@develop" // head of the develop branch
966@include "bitbucket-server:~john/Promise/promise.class.nut@v3.0.1" // tag v3.0.1
967```
968
969##### Root of the remote resource: #####
970```
971bitbucket-server:<project>/<repo>
972bitbucket-server:~<user>/<repo>
973```
974
975##### Authentication: #####
976
977Authentication is optional. It is required to access private repositories only.
978
979For the authentication you need to provide:
980- a Bitbucket Server username (`--bitbucket-server-user` option)
981- a Bitbucket Server [personal access token](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html) or a password, which is less secure and not recommended (`--bitbucket-server-token` option).
982
983#### Azure Repository ####
984
985For includes from [Azure Repos](https://azure.microsoft.com/en-us/services/devops/repos/).
986
987##### Format: #####
988```
989@include "git-azure-repos:<org>/<project>/<repo>/<path>[@<ref>]"
990@include once "git-azure-repos:<org>/<project>/<repo>/<path>[@<ref>]"
991```
992where:
993- `org` is the organization name.
994- `project` is the project name.
995- `repo` is the repository name.
996- `path` is the path to file.
997- `ref` is the git reference (branch name or tag, defaults to _master_).
998
999##### Examples: #####
1000```
1001@include once "git-azure-repos:org/project/repo/path/some.class.nut" // head of the default branch
1002@include "git-azure-repos:org/project/repo/path/some.class.nut@develop" // head of the develop branch
1003@include "git-azure-repos:org/project/repo/path/some.class.nut@v3.0.1" // tag v3.0.1
1004```
1005
1006##### Root of the remote resource: #####
1007```
1008git-azure-repos:<org>/<project>/<repo>
1009```
1010
1011##### Authentication: #####
1012
1013Authentication is optional. It is required to access private repositories only.
1014
1015For the authentication you need to provide:
1016- an Azure Repos username (`--azure-user` option)
1017- an Azure Repos personal access token (`--azure-token` option).
1018
1019#### Local Git Repository ####
1020
1021For includes from Git repositories hosted locally. **Note**, even as files are local, *Builder* considers them as files from a remote resource when [searching the file to include](#searching-the-included-file).
1022
1023##### Format: #####
1024```
1025@include "git-local:<path>[@<ref>]"
1026@include once "git-local:<path>[@<ref>]"
1027```
1028where:
1029- `path` is the path to file.
1030- `ref` is the git reference (branch name, tag or commit, defaults to current branch which the local git repository is set to).
1031
1032##### Examples: #####
1033```
1034@include once "git-local:/path/to/repo/and/file/some.class.nut" // head of the default branch
1035@include once "git-local:/path/to/repo/and/file/some.class.nut@develop" // head of the develop branch
1036@include "git-local:/path/to/repo/and/file/some.class.nut@3.0.1" // tag v3.0.1
1037@include "git-local:/path/to/repo/and/file/some.class.nut@c13c59e96f3f6a37f75f9e520d0fdc5591e0ba83" // concrete commit
1038```
1039
1040##### Root of the remote resource: #####
1041Is determined by *Builder*.
1042
1043##### Notes: #####
1044- [Caching](#caching-remote-files) is not applicable to local Git files.
1045- If there are uncommitted changes, they will not be seen by *Builder*. Hence `@include "git-local:<path>"` (without `<ref>`) is not interchangeable with `@include "<path>"`.
1046- There are local and remote branches in Git. If you want to create a local remote-tracking branch from a remote branch, you can use, for example, the `git checkout <remote_branch_name>` command. For more info, see the [Git docs](https://git-scm.com/).
1047- To include a remote git branch, you should specify the name of the remote repository in the `ref` part of the directive. For example:
1048```
1049@include "git-local:/path/to/repo/and/file/some.class.nut@develop" // include local git branch
1050@include "git-local:/path/to/repo/and/file/some.class.nut@origin/develop" // include remote git branch from the "origin" remote repository
1051```
1052
1053### Caching Remote Files ###
1054
1055To reduce compilation time, *Builder* can optionally cache files included from a remote resource. If the file cache is enabled, remote files are cached locally in the `.builder-cache` directory. Cached resources expire and are automatically invalidated 24 hours after their addition to the cache.
1056
1057To turn the cache on, pass the `--cache` or `-c` option to *Builder*. If this option is not specified, *Builder* will not use the file cache even if the cached data exists and is valid &mdash; *Builder* will continue to query remote resources on every execution.
1058
1059To reset the cache, use both the `--cache` and the `--clear-cache` options.
1060
1061If a resource should never be cached, it needs to be added to the `exclude-list.builder` file (see the example below). You can use wildcard characters to mask file names.
1062
1063**Note**: Non-identical paths, even if they point to absolutely the same location, are treated as different paths. Eg., if you include `/a/b/1.nut`, it becomes cached, and then you include `/a/b/../b/1.nut`, it will not be found in the cache.
1064
1065#### Wildcard Pattern Matching ####
1066
1067Pattern matching syntax is a similar to that of *.gitignore*. A string is a wildcard pattern if it contains '```?```' or '```*```' characters. Empty strings or strings that starts with '```#```' are ignored.
1068
1069A '```?```' symbol matches any single character. For example, `bo?t.js` matches `boot.js` and `boat.js`, but doesn't match `bot.js`.
1070
1071A '```*```' matches any string, that is limited by slashes, including the empty string. For example, ```/foo/*ar``` matches `/foo/bar`, `/foo/ar` and `/foo/foo-bar`, but doesn't match `/foo/get/bar` or `/foo/bar/get`.
1072
1073Two consecutive asterisks `**` in patterns matched against full pathname may have special meaning:
1074
1075* A leading `**` followed by a slash means match in all directories. For example, `**/foo` matches file or directory `foo` anywhere, the same as pattern `foo`. `**/foo/bar` matches file or directory `bar` anywhere that is directly under directory `foo`.
1076
1077* A trailing `/**` matches everything inside. For example, `abc/**` matches all files inside directory `abc`.
1078
1079* A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, `a/**/b` matches `a/b`, `a/x/b`, `a/x/y/b` and so on.
1080
1081* Other consecutive asterisks are considered invalid.
1082
1083##### Examples: #####
1084
1085```sh
1086# Avoid caching a specific file
1087github:electricimp/MessageManager/MessageManager.lib.nut
1088
1089# Exclude all electricimp repos
1090github:electicimp/**
1091
1092# Exclude all tagged files or files from the specific branches from the cache
1093github:*/**/*@*
1094```
1095
1096### Saving And Reusing Versions Of Remote Files ###
1097
1098It is possible to save the versions of all remote files which are used during the current run of *Builder*, and reuse exactly that versions later. This is applicable for files from repositories only.
1099
1100See the [Repository Files: Dependencies](#repository-files-dependencies) section for the details.
1101
1102### Proxy Access To Remote Files ###
1103
1104To specify a proxy that should be used when you are including files from remote resources, set the environment variables `HTTP_PROXY`/`http_proxy` and/or `HTTPS_PROXY`/`https_proxy` for HTTP and HTTPS protocols respectively.
1105
1106For example, to operate through a proxy running at IP address `192.168.10.2` on port `3128` for HTTP requests, you should set the environment variable: `HTTP_PROXY='http://192.168.10.2:3128'`. All of *Builder’s* HTTP requests will now go through the proxy.
1107
1108# Advanced Builder Usage #
1109
1110This section contains information that will help you work with Builder more effectively, but may not be needed for more basic Builder tasks.
1111
1112## Reproducible Artifacts ##
1113
1114It is possible to save the build configuration data used for preprocessing a source file in order to create an identical source file again later with that saved configuration. Builder variable definitions are saved in a [‘directives.json’](#builder-variables-directives) file, and references to the concrete versions of [repository](#remote-include-files) files and libraries are stored in a [‘dependencies.json’](#repository-files-dependencies) file.
1115
1116### Builder Variables: Directives ###
1117
1118The `--save-directives [<path_to_file>]` and `--use-directives [<path_to_file>]` options are used to, respectively, save and reuse Builder variable definitions. The definitions are saved in a JSON file. If a file name is not specified, the `directives.json` file in the local directory is used. These options are processed the similar way as the `--save-dependencies` and `--use-dependencies` options, above.
1119
1120When the `--use-directives [<path_to_file>]` option is used, the saved Builder variable definitions are merged with definitions specified by `-D<variable> <value>` options.
1121
1122A typical `directives.json` file looks like this:
1123
1124```json
1125{
1126 "Variable0": "value0",
1127 "Variable1": "value1"
1128}
1129```
1130
1131### Repository Files: Dependencies ###
1132
1133`--save-dependencies [<path_to_file>]` and `--use-dependencies [<path_to_file>]` options are used to save and to reuse, respectively, references to concrete versions of [repository](#remote-include-files) files and libraries. The references are saved in a JSON file. If a file name is not specified, the `dependencies.json` file in the local directory is used. Every reference consists of [repository](#remote-include-files) file URL and:
1134- Git Blob ID (Git Blob SHA) &mdash; for GitHub files<br>
1135**Note** It is possible to obtain the Git Blob ID of a GitHub file using the following *git* command: `git hash-object <path_to_file>`
1136- Git Commit ID (Git Commit SHA) &mdash; for Bitbucket Server, Azure Repos and Git Local files
1137
1138For more information, please see [the Git Manual](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects) and [the Git API](https://developer.github.com/v3/git/blobs/).
1139
1140These options are processed the following way:
1141
1142- If only `--save-dependencies [<path_to_file>]` is specified, the references to all source files retrieved from [repositories](#remote-include-files) are saved in the provided JSON file (or `dependencies.json`).
1143- If only `--use-dependencies [<path_to_file>]` is specified, the source files from [repositories](#remote-include-files) are retrieved using the references read from the provided JSON file (or `dependencies.json`).
1144- If both `--save-dependencies [<path_to_file>]` and `--use-dependencies [<path_to_file>]` are specified, then:
1145 1. The source files from [repositories](#remote-include-files) are retrieved using the references read from the JSON file passed to the `--use-dependencies` option (or `dependencies.json`).
1146 2. If the source code contains @includes for files from [repositories](#remote-include-files) which have not yet been retrieved, they are retrieved now.
1147 3. Builder performs the preprocessing operation.
1148 4. References to all source files retrieved from [repositories](#remote-include-filesl) are saved in the JSON file passed to the `--save-dependencies` option (or `dependencies.json`).
1149
1150**Note** If `--save-dependencies` is specified, the `--cache` option is ignored. If `--use-dependencies` is specified, the `--cache` option does not affect the files referenced in the dependency file.
1151
1152A typical `dependencies.json` file looks like this:
1153
1154```json
1155[
1156 [
1157 "github:ProjectA/repositoryA/fileA",
1158 "2ff017dc92e826ad184f9cdeadd1a2446f8d6032"
1159 ],
1160 [
1161 "github:ProjectB/repositoryB/fileB",
1162 "a01b64f9ce764f226f52c6b9364396d4a8bd550b"
1163 ],
1164 [
1165 "bitbucket-server:projectC/repositoryC/fileC",
1166 "4bc4024f1f2ad99e8bd2ade73d151912e031d1f5"
1167 ],
1168 [
1169 "git-azure-repos:org/projectD/repositoryD/fileD",
1170 "d1ccee9ed6e250c6d5e1f052107125659d3ba9d0"
1171 ],
1172 [
1173 "git-local:/path/to/repo/and/fileD",
1174 "c13c59e96f3f6a37f75f9e520d0fdc5591e0ba83"
1175 ]
1176]
1177```
1178
1179**Note**: Non-identical paths, even if they point to absolutely the same location, are treated as different paths. Eg., if you have saved dependencies for `/a/b/1.nut` and then you include `/a/b/../b/1.nut` - the dependencies will not be applied to this file.
1180
1181## Including JavaScript Libraries ##
1182
1183Builder can accept JavaScript libraries to add functionality to its global namespace. The library should export an object, the properties of which will be merged into the global namespace. For example, to include a function, *upper()*, to convert strings to uppercase, define your library file like so:
1184
1185```js
1186module.exports = {
1187 upper: (s) => s.toUpperCase()
1188};
1189```
1190
1191Now include the function within directives in your input file:
1192
1193```
1194@{upper("warning:")}
1195@{upper(include("warning.txt"))}
1196```
1197
1198Finally, run Builder with the option `--lib path/to/your/lib/file`.
1199
1200### Binding The Context Object Correctly ###
1201
1202Functions called by Builder will be called with their *this* argument set to a Builder context object. Within the context object, Builder [variables](#variables) like `__FILE__`, [functions](#builder-functions) like `max()`, and other included library functions will be made available at the top level. Variables defined in your input code with `@macro` or `@set` will be available under the key *globals*.
1203
1204Ignoring the binding of *this* may cause unexpected behavior, for example when calling methods on objects. Take the following example library:
1205
1206```js
1207class MyClass {
1208 constructor(str) {
1209 this._str = str;
1210 }
1211
1212 getStr() {
1213 return this._str;
1214 }
1215}
1216
1217myObject = MyClass("my text");
1218
1219module.exports = {
1220 myObject
1221};
1222```
1223
1224Attempting to use this library with the directive `@{myObject.getStr()}` will not deliver the expected behavior because *this* in *getStr()* will be set to a Builder context object and not to *myObject*. When calling class methods ensure they have been bound to the correct value of *this*:
1225
1226```js
1227class MyClass {
1228 constructor(str) {
1229 this._str = str;
1230 }
1231
1232 getStr() {
1233 return this._str;
1234 }
1235}
1236
1237myObject = MyClass("my text");
1238
1239module.exports = {
1240 getStr: myObject.getStr.bind(myObject)
1241};
1242```
1243
1244# Testing #
1245
1246When running tests locally, please test on both Windows and macOS. All environment variables are optional. However, if you are working with `@includes` from GitHub and do not provide GitHub credentials, rate limits imposed by GitHub may cause test failures. The default for `SPEC_LOGLEVEL` is `error`.
1247
1248```sh
1249npm install
1250SPEC_LOGLEVEL=<debug|info|warning|error>
1251SPEC_GITHUB_TOKEN=<GitHub personal access token>
1252npm test
1253```
1254
1255**Note 1**: The standard set of tests doesn't include Bitbucket Server, Azure Repos and Git Local (but see the **Note 2**) integration testing. To run Bitbucket Server, Azure Repos or Git Local tests, please see the sections below.
1256
1257**Note 2**: The standard set of tests uses Git Local in several tests for testing the overall behavior of Builder. They require the `SPEC_GIT_LOCAL_REPO_PATH` variable to be set (see the [Git Local](#git-local) section below). These are optional tests so they will be skipped if that variable is not set.
1258
1259**Note 3**: There are several tests that require access to the root of the filesystem (or to the root of the disk `C:` on Windows). They will create/remove there a directory named `builder_test_g2e5r6uh`, so please make sure you don't have some important data in such directory.
1260
1261## Bitbucket Server ##
1262
1263**Prerequisites**:
12641. A running instance of Bitbucket Server
12651. A clone of [Builder](./) repo placed on this server
12661. If the server / repo are not public, an account (username and password / [token](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html)) with permissions to access the repo
1267
1268```sh
1269npm install
1270SPEC_LOGLEVEL=<debug|info|warning|error>
1271# E.g., "https://bitbucket-srv.itd.example.com"
1272SPEC_BITBUCKET_SERVER_ADDRESS=<Bitbucket Server address>
1273# Format: "<project>/<repo>". E.g., "myProj/BuilderClone"
1274# If the repo belongs to a user (not to a project), the format is: "~<user>/<repo>". E.g., "~john/BuilderClone"
1275SPEC_BITBUCKET_SERVER_REPO_PATH=<Path to the cloned Builder repo on the server>
1276SPEC_BITBUCKET_SERVER_USERNAME=<Bitbucket Server username>
1277SPEC_BITBUCKET_SERVER_TOKEN=<Bitbucket Server password/access token>
1278npm run test:bitbucket-server
1279```
1280
1281## Azure Repos ##
1282
1283**Prerequisites**:
12841. A clone of [Builder](./) repo placed at Azure Repos
12851. An account (username and token) with permissions to access the repo
1286
1287```sh
1288npm install
1289SPEC_LOGLEVEL=<debug|info|warning|error>
1290# Format: "<org>/<project>/<repo>". E.g., "myOrg/myProj/BuilderClone"
1291SPEC_AZURE_REPOS_REPO_PATH=<Path to the cloned Builder repo at the Azure Repos>
1292SPEC_AZURE_REPOS_USERNAME=<Azure Repos username>
1293SPEC_AZURE_REPOS_TOKEN=<Azure Repos access token>
1294npm run test:azure-repos
1295```
1296
1297## Git Local ##
1298**Prerequisites**:
12991. A clone of [Builder](./) repo placed locally
1300
1301```sh
1302npm install
1303SPEC_LOGLEVEL=<debug|info|warning|error>
1304SPEC_GIT_LOCAL_REPO_PATH=<Path to the root of the cloned Builder repo>
1305npm run test:git-local
1306```
1307
1308# License #
1309
1310Builder is licensed under the [MIT License](./LICENSE).