foxhound 1.0.33 → 1.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ bind-addr: 127.0.0.1:8080
2
+ auth: password
3
+ password: retold
4
+ cert: false
@@ -0,0 +1,4 @@
1
+ {
2
+ "optOut": false,
3
+ "lastUpdateCheck": 1648097783781
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "optOut": false,
3
+ "lastUpdateCheck": 1648063932373
4
+ }
@@ -0,0 +1,29 @@
1
+ # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2
+ # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3
+
4
+ name: Node.js CI
5
+
6
+ on:
7
+ push:
8
+ branches: [ master ]
9
+ pull_request:
10
+ branches: [ master ]
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+
16
+ strategy:
17
+ matrix:
18
+ node-version: [10.x, 12.x, 14.x, 16.x]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v2
22
+ - name: Use Node.js ${{ matrix.node-version }}
23
+ uses: actions/setup-node@v2
24
+ with:
25
+ node-version: ${{ matrix.node-version }}
26
+ cache: 'npm'
27
+ - run: npm i
28
+ - run: npm test
29
+ - run: npm run coverage
@@ -5,14 +5,42 @@
5
5
  "version": "0.2.0",
6
6
  "configurations": [
7
7
  {
8
+ "name": "Launch Debug Harness",
8
9
  "type": "pwa-node",
9
10
  "request": "launch",
10
- "name": "Launch Program",
11
11
  "outputCapture": "std",
12
12
  "skipFiles": [
13
13
  "<node_internals>/**"
14
14
  ],
15
- "program": "${workspaceFolder}/debug/Harness.js"
15
+ "program": "${workspaceFolder}/debug/Harness.js",
16
+ "presentation": {
17
+ "hidden": false,
18
+ "group": "",
19
+ "order": 1
20
+ }
21
+ },
22
+ {
23
+ "name": "Mocha Tests",
24
+ "args": [
25
+ "-u",
26
+ "tdd",
27
+ "--timeout",
28
+ "999999",
29
+ "--colors",
30
+ "${workspaceFolder}/test"
31
+ ],
32
+ "internalConsoleOptions": "openOnSessionStart",
33
+ "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
34
+ "request": "launch",
35
+ "skipFiles": [
36
+ "<node_internals>/**"
37
+ ],
38
+ "type": "pwa-node",
39
+ "presentation": {
40
+ "hidden": false,
41
+ "group": "",
42
+ "order": 2
43
+ }
16
44
  }
17
45
  ]
18
46
  }
package/Dockerfile ADDED
@@ -0,0 +1,32 @@
1
+ # Use the codercom/code-server image
2
+ FROM codercom/code-server:latest
3
+ MAINTAINER steven velozo
4
+
5
+ VOLUME /home/coder/.config
6
+ VOLUME /home/coder/.vscode
7
+
8
+ RUN echo "...installing debian dependencies..."
9
+ RUN sudo apt update
10
+ RUN sudo apt install vim curl tmux -y
11
+
12
+ RUN echo "Building RETOLD development image..."
13
+
14
+
15
+ RUN echo "...mapping library specific volumes..."
16
+ # Volume mappings for RETOLD:Foxhound library
17
+ VOLUME /home/coder/foxhound
18
+ # VOLUME /home/coder/foxhound/node_modules
19
+
20
+ SHELL ["/bin/bash", "-c"]
21
+ USER coder
22
+
23
+ RUN echo "...installing node version manager..."
24
+ # Because there is a .bashrc chicken/egg problem, we will create one here to simulate logging in. This is not great.
25
+ RUN touch ~/.bashrc && chmod +x ~/.bashrc
26
+ RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
27
+
28
+ RUN echo "...installing node version 14 as the default..."
29
+ RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm install 14
30
+ RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default 14
31
+
32
+ WORKDIR /home/coder/foxhound
package/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  The FoxHound javascript query generator, for node.js and the browser.
4
4
 
5
- [![Build Status](https://travis-ci.org/stevenvelozo/foxhound.svg?branch=master)](https://travis-ci.org/stevenvelozo/foxhound)
6
5
 
7
6
  ### Getting Started
8
7
 
@@ -32,3 +31,35 @@ Which now will output:
32
31
 
33
32
  $ npm test
34
33
  $ npm run coverage
34
+
35
+ ### Docker Development Environment
36
+
37
+
38
+ 1. Run this command to build this image:
39
+ ```
40
+ docker build ./ -t retold/foxhound:local
41
+ ```
42
+
43
+ alternatively you can use npm to run this
44
+
45
+
46
+ ```
47
+ npm run docker-dev-build-image
48
+ ```
49
+
50
+ 2. Run this command to build the local container:
51
+ ```
52
+ docker run -it --name foxhound-dev -p 127.0.0.1:12346:8080 -v "$PWD/.config:/home/coder/.config" -v "$PWD:/home/coder/foxhound" -u "$(id -u):$(id -g)" -e "DOCKER_USER=$USER" retold/foxhound:local
53
+ ```
54
+
55
+ alternatively you can use npm to run this
56
+
57
+ ```
58
+ npm run docker-dev-run
59
+ ```
60
+
61
+ 3. Go to http://localhost:12346/ in a web browser
62
+
63
+ 4. The password is "retold"
64
+
65
+ 5. Right now you (may) need to delete the `node_modules` folders and regenerate it for Linux.
package/debug/Harness.js CHANGED
@@ -25,22 +25,21 @@ var _AnimalSchemaWithoutDeleted = (
25
25
  ]);
26
26
 
27
27
  var tmpQuery = libFoxHound.new(libFable)
28
- .setDialect('MeadowEndpoints')
29
- .setScope('Animal')
30
- .setDataElements(['Name', 'Age', 'Cost'])
31
- .setCap(100)
32
- .addFilter('Age', '25')
33
- .addFilter('', '', '(')
34
- .addFilter('Color', 'Red')
35
- .addFilter('Color', 'Green', '=', 'OR')
36
- .addFilter('', '', ')')
37
- .addFilter('Description', '', 'IS NOT NULL')
38
- .addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN');
28
+ .setDialect('MeadowEndpoints')
29
+ .setScope('Animal')
30
+ .setDataElements(['Name', 'Age', 'Cost'])
31
+ .setCap(100)
32
+ .addFilter('Age', '25')
33
+ .addFilter('', '', '(')
34
+ .addFilter('Color', 'Red')
35
+ .addFilter('Color', 'Green', '=', 'OR')
36
+ .addFilter('', '', ')')
37
+ .addFilter('Description', '', 'IS NOT NULL')
38
+ .addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN');
39
39
  tmpQuery.setLogLevel(3).addSort('Age');
40
40
  // Build the query
41
41
  tmpQuery.buildReadQuery();
42
42
  // This is the query generated by the MeadowEndpoints dialect
43
43
  libFable.log.trace('Select Query', tmpQuery.query);
44
44
 
45
-
46
45
  console.log(tmpQuery.query.body);
package/package.json CHANGED
@@ -1,12 +1,32 @@
1
1
  {
2
2
  "name": "foxhound",
3
- "version": "1.0.33",
3
+ "version": "1.0.37",
4
4
  "description": "A Database Query generation library.",
5
5
  "main": "source/FoxHound.js",
6
6
  "scripts": {
7
7
  "start": "node source/FoxHound.js",
8
8
  "coverage": "./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- -u tdd -R spec",
9
- "test": "./node_modules/mocha/bin/_mocha -u tdd -R spec"
9
+ "test": "./node_modules/.bin/mocha -u tdd -R spec",
10
+ "docker-dev-build-image": "docker build ./ -t retold/foxhound:local",
11
+ "docker-dev-run": "docker run -it -d --name foxhound-dev -p 127.0.0.1:12346:8080 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/foxhound\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" retold/foxhound:local"
12
+ },
13
+ "mocha": {
14
+ "diff": true,
15
+ "extension": [
16
+ "js"
17
+ ],
18
+ "package": "./package.json",
19
+ "reporter": "spec",
20
+ "slow": "75",
21
+ "timeout": "5000",
22
+ "ui": "tdd",
23
+ "watch-files": [
24
+ "source/**/*.js",
25
+ "test/**/*.js"
26
+ ],
27
+ "watch-ignore": [
28
+ "lib/vendor"
29
+ ]
10
30
  },
11
31
  "repository": {
12
32
  "type": "git",
@@ -24,14 +44,12 @@
24
44
  },
25
45
  "homepage": "https://github.com/stevenvelozo/foxhound",
26
46
  "devDependencies": {
27
- "chai": "3.4.1",
28
- "codeclimate-test-reporter": "0.1.1",
29
- "coveralls": "2.11.4",
47
+ "chai": "4.3.6",
30
48
  "istanbul": "0.4.1",
31
- "mocha": "2.3.4"
49
+ "mocha": "9.2.2"
32
50
  },
33
51
  "dependencies": {
34
- "fable": "~1.0.1",
35
- "underscore": "1.8.3"
52
+ "fable": "~2.0.5",
53
+ "underscore": "1.13.2"
36
54
  }
37
55
  }
@@ -67,14 +67,33 @@ var FoxHoundDialectALASQL = function()
67
67
  *
68
68
  * @method: generateFieldList
69
69
  * @param: {Object} pParameters SQL Query Parameters
70
- * @return: {String} Returns the field list clause
70
+ * @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
71
+ * @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
72
+ * due to missing schema.
71
73
  */
72
- var generateFieldList = function(pParameters)
74
+ var generateFieldList = function(pParameters, pIsForCountClause)
73
75
  {
74
76
  var tmpDataElements = pParameters.dataElements;
75
77
  if (!Array.isArray(tmpDataElements) || tmpDataElements.length < 1)
76
78
  {
77
- return ' *';
79
+ if (!pIsForCountClause)
80
+ {
81
+ return ' *';
82
+ }
83
+ // we need to list all of the table fields explicitly; get them from the schema
84
+ const tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
85
+ if (tmpSchema.length < 1)
86
+ {
87
+ // this means we have no schema; returning an empty string here signals the calling code to handle this case
88
+ return '';
89
+ }
90
+ const idColumn = tmpSchema.find((entry) => entry.Type === 'AutoIdentity');
91
+ if (!idColumn)
92
+ {
93
+ // this means there is no autoincrementing unique ID column; treat as above
94
+ return '';
95
+ }
96
+ return ` ${idColumn.Column}`;
78
97
  }
79
98
 
80
99
  var tmpFieldList = ' ';
@@ -740,9 +759,14 @@ var FoxHoundDialectALASQL = function()
740
759
  {
741
760
  var tmpTableName = generateTableName(pParameters);
742
761
  var tmpWhere = generateWhere(pParameters);
743
- const tmpOptDistinct = pParameters.distinct ? 'DISTINCT' : '';
744
- const tmpCountClause = pParameters.distinct ? `${tmpOptDistinct}${generateFieldList(pParameters)}` : '*';
762
+ const tmpFieldList = pParameters.distinct ? generateFieldList(pParameters, true) : '*';
745
763
 
764
+ // here, we ignore the distinct keyword if no fields have been specified and
765
+ if (pParameters.distinct && tmpFieldList.length < 1)
766
+ {
767
+ console.warn('Distinct requested but no field list or schema are available, so not honoring distinct for count query.');
768
+ }
769
+ const tmpOptDistinct = pParameters.distinct && tmpFieldList.length > 0 ? 'DISTINCT' : '';
746
770
  if (pParameters.queryOverride)
747
771
  {
748
772
  try
@@ -758,7 +782,7 @@ var FoxHoundDialectALASQL = function()
758
782
  }
759
783
  }
760
784
 
761
- return `SELECT COUNT(${tmpCountClause}) AS RowCount FROM${tmpTableName}${tmpWhere};`;
785
+ return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS RowCount FROM${tmpTableName}${tmpWhere};`;
762
786
  };
763
787
 
764
788
  var tmpDialect = ({
@@ -22,6 +22,19 @@ var FoxHoundDialectMeadowEndpoints = function()
22
22
  return pParameters.scope;
23
23
  };
24
24
 
25
+ /**
26
+ * Generate the Identity column from the schema or scope
27
+ *
28
+ * @method: generateIdentityColumnName
29
+ * @param: {Object} pParameters SQL Query Parameters
30
+ * @return: {String} Returns the table name clause
31
+ */
32
+ var generateIdentityColumnName = function(pParameters)
33
+ {
34
+ // TODO: See about using the Schema or the Schemata for this
35
+ return `ID${pParameters.scope}`;
36
+ };
37
+
25
38
  /**
26
39
  * Generate a field list from the array of dataElements
27
40
  *
@@ -353,22 +366,44 @@ var FoxHoundDialectMeadowEndpoints = function()
353
366
  var tmpWhere = generateWhere(pParameters);
354
367
  var tmpLimit = generateLimit(pParameters);
355
368
 
356
- var tmpURL = `${tmpTableName}s`;
357
- if (tmpFieldList)
358
- {
359
- tmpURL = `${tmpURL}/LiteExtended/${tmpFieldList}`
360
- }
361
- if (tmpWhere)
362
- {
363
- tmpURL = `${tmpURL}/FilteredTo/${tmpWhere}`;
364
- }
365
- if (tmpLimit)
366
- {
367
- tmpURL = `${tmpURL}/${tmpLimit}`;
368
- }
369
+ var tmpURL = `${tmpTableName}`;
370
+ // In the case that there is only a single query parameter, and the parameter is a single identity,
371
+ // we will cast it to the READ endpoint rather than READS.
372
+ if ((pParameters.filter)
373
+ && (pParameters.filter.length == 1)
374
+ // If there is exactly one query filter parameter
375
+ && (pParameters.filter[0].Column === generateIdentityColumnName(pParameters))
376
+ // AND It is the Identity column
377
+ && (pParameters.filter[0].Operator === '=')
378
+ // AND The comparators is a simple equals
379
+ && (tmpLimit == '') && (tmpFieldList == '')
380
+ // AND There is no limit or field list set
381
+ && (!pParameters.sort))
382
+ // AND There is no sort clause
383
+ {
384
+ // THEN This is a SINGLE READ by presumption.
385
+ // There are some bad side affects this could cause with chaining and overridden behaviors, if
386
+ // we are requesting a filtered list of 1 record.
387
+ tmpURL = `${tmpURL}/${pParameters.filter[0].Value}`;
388
+ }
389
+ else
390
+ {
391
+ tmpURL = `${tmpURL}s`;
392
+ if (tmpFieldList)
393
+ {
394
+ tmpURL = `${tmpURL}/LiteExtended/${tmpFieldList}`
395
+ }
396
+ if (tmpWhere)
397
+ {
398
+ tmpURL = `${tmpURL}/FilteredTo/${tmpWhere}`;
399
+ }
400
+ if (tmpLimit)
401
+ {
402
+ tmpURL = `${tmpURL}/${tmpLimit}`;
403
+ }
404
+ }
369
405
 
370
406
  return tmpURL;
371
- ///'SELECT'+tmpFieldList+' FROM'+tmpTableName+tmpJoin+tmpWhere+tmpOrderBy+tmpLimit+';';
372
407
  };
373
408
 
374
409
  var Update = function(pParameters)
@@ -413,7 +448,7 @@ var FoxHoundDialectMeadowEndpoints = function()
413
448
 
414
449
  if (tmpWhere)
415
450
  {
416
- return `${tmpCountQuery}s/Count/FilteredTo/${tmpWhere}`;
451
+ return `${tmpTableName}s/Count/FilteredTo/${tmpWhere}`;
417
452
  }
418
453
 
419
454
  return tmpCountQuery;
@@ -44,28 +44,35 @@ var FoxHoundDialectMySQL = function()
44
44
  *
45
45
  * @method: generateFieldList
46
46
  * @param: {Object} pParameters SQL Query Parameters
47
- * @param {Boolean} pExplicitFields (optional) If true, generate explicit fields rather than "TableName.*" (for count distinct).
47
+ * @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
48
48
  * @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
49
49
  * due to missing schema.
50
50
  */
51
- var generateFieldList = function(pParameters, pExplicitFields)
51
+ var generateFieldList = function(pParameters, pIsForCountClause)
52
52
  {
53
53
  var tmpDataElements = pParameters.dataElements;
54
54
  if (!Array.isArray(tmpDataElements) || tmpDataElements.length < 1)
55
55
  {
56
56
  const tmpTableName = generateTableName(pParameters);
57
- if (!pExplicitFields)
57
+ if (!pIsForCountClause)
58
58
  {
59
59
  return tmpTableName + '.*';
60
60
  }
61
61
  // we need to list all of the table fields explicitly; get them from the schema
62
- var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
63
- tmpDataElements = tmpSchema.map((entry) => `${tmpTableName}.${entry.Column}`.trim());
64
- if (tmpDataElements.length < 1)
62
+ const tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
63
+ if (tmpSchema.length < 1)
65
64
  {
66
65
  // this means we have no schema; returning an empty string here signals the calling code to handle this case
67
66
  return '';
68
67
  }
68
+ const idColumn = tmpSchema.find((entry) => entry.Type === 'AutoIdentity');
69
+ if (!idColumn)
70
+ {
71
+ // this means there is no autoincrementing unique ID column; treat as above
72
+ return '';
73
+ }
74
+ const qualifiedIDColumn = `${tmpTableName}.${idColumn.Column}`;
75
+ return ` ${generateSafeFieldName(qualifiedIDColumn)}`;
69
76
  }
70
77
 
71
78
  var tmpFieldList = ' ';
@@ -801,7 +808,7 @@ var FoxHoundDialectMySQL = function()
801
808
  var tmpTableName = generateTableName(pParameters);
802
809
  var tmpJoin = generateJoins(pParameters);
803
810
  var tmpWhere = generateWhere(pParameters);
804
- // here, we ignore the distinct keyword if no fields have bene specified and
811
+ // here, we ignore the distinct keyword if no fields have been specified and
805
812
  if (pParameters.distinct && tmpFieldList.length < 1)
806
813
  {
807
814
  console.warn('Distinct requested but no field list or schema are available, so not honoring distinct for count query.');
@@ -347,7 +347,7 @@ suite
347
347
  // This is the query generated by the ALASQL dialect
348
348
  libFable.log.trace('Custom Count Query', tmpQuery.query);
349
349
  Expect(tmpQuery.query.body)
350
- .to.equal('SELECT COUNT(DISTINCT *) AS RowCount FROM Animal WHERE `Age` = :Age_w0;');
350
+ .to.equal('SELECT COUNT(*) AS RowCount FROM Animal WHERE `Age` = :Age_w0;');
351
351
  }
352
352
  );
353
353
  test
@@ -420,6 +420,43 @@ suite
420
420
  .to.equal('SELECT COUNT(*) AS RowCount FROM Animal;');
421
421
  }
422
422
  );
423
+ test
424
+ (
425
+ 'Count Query with Distinct',
426
+ function()
427
+ {
428
+ var tmpQuery = libFoxHound.new(libFable)
429
+ .setDialect('ALASQL')
430
+ .setScope('Animal')
431
+ .setDistinct(true);
432
+
433
+ // Build the query
434
+ tmpQuery.buildCountQuery();
435
+ // This is the query generated by the ALASQL dialect
436
+ libFable.log.trace('Count Query', tmpQuery.query);
437
+ Expect(tmpQuery.query.body)
438
+ .to.equal('SELECT COUNT(*) AS RowCount FROM Animal;');
439
+ }
440
+ );
441
+ test
442
+ (
443
+ 'Count Query with Schema and Distinct',
444
+ function()
445
+ {
446
+ var tmpQuery = libFoxHound.new(libFable)
447
+ .setDialect('ALASQL')
448
+ .setScope('Animal')
449
+ .setDistinct(true);
450
+ tmpQuery.query.schema = _AnimalSchema;
451
+
452
+ // Build the query
453
+ tmpQuery.buildCountQuery();
454
+ // This is the query generated by the ALASQL dialect
455
+ libFable.log.trace('Count Query', tmpQuery.query);
456
+ Expect(tmpQuery.query.body)
457
+ .to.equal('SELECT COUNT(DISTINCT IDAnimal) AS RowCount FROM Animal WHERE `Deleted` = :Deleted_w0;');
458
+ }
459
+ );
423
460
  }
424
461
  );
425
462
 
@@ -123,6 +123,38 @@ suite
123
123
  }
124
124
  );
125
125
  test
126
+ (
127
+ 'Read Query single record',
128
+ function()
129
+ {
130
+ var tmpQuery = libFoxHound.new(libFable).setDialect('MeadowEndpoints').setScope('Animal');
131
+ tmpQuery.addFilter('IDAnimal', 1);
132
+ // Build the query
133
+ tmpQuery.buildReadQuery();
134
+ // This is the query generated by the MeadowEndpoints dialect
135
+ libFable.log.trace('Simple Select Query', tmpQuery.query);
136
+ Expect(tmpQuery.query.body)
137
+ .to.equal('Animal/1');
138
+ }
139
+ );
140
+ test
141
+ (
142
+ 'Read Query single record with sort',
143
+ function()
144
+ {
145
+ // Because we added a sorting clause, this should be a READS
146
+ var tmpQuery = libFoxHound.new(libFable).setDialect('MeadowEndpoints').setScope('Animal');
147
+ tmpQuery.addFilter('IDAnimal', 1);
148
+ tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
149
+ // Build the query
150
+ tmpQuery.buildReadQuery();
151
+ // This is the query generated by the MeadowEndpoints dialect
152
+ libFable.log.trace('Simple Select Query', tmpQuery.query);
153
+ Expect(tmpQuery.query.body)
154
+ .to.equal('Animals/FilteredTo/FBV~IDAnimal~EQ~1~FSF~Cost~DESC~0');
155
+ }
156
+ );
157
+ test
126
158
  (
127
159
  'Complex Read Query',
128
160
  function()
@@ -352,7 +352,7 @@ suite
352
352
  // This is the query generated by the MySQL dialect
353
353
  libFable.log.trace('Count Distinct Query', tmpQuery.query);
354
354
  Expect(tmpQuery.query.body)
355
- .to.equal('SELECT COUNT(DISTINCT `Animal`.`IDAnimal`, `Animal`.`GUIDAnimal`, `Animal`.`CreateDate`, `Animal`.`CreatingIDUser`, `Animal`.`UpdateDate`, `Animal`.`UpdatingIDUser`, `Animal`.`Deleted`, `Animal`.`DeletingIDUser`, `Animal`.`DeleteDate`) AS RowCount FROM `Animal` WHERE `Animal`.Deleted = :Deleted_w0;');
355
+ .to.equal('SELECT COUNT(DISTINCT `Animal`.`IDAnimal`) AS RowCount FROM `Animal` WHERE `Animal`.Deleted = :Deleted_w0;');
356
356
  }
357
357
  );
358
358
  test
package/.travis.yml DELETED
@@ -1,16 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "6"
4
- - "8"
5
- - "12"
6
- - "15"
7
- addons:
8
- code_climate:
9
- repo_token: 41529c21a4a756d41a2d8d288c26c941479606cd39e7d89d476642d1ab3c86c3
10
- after_success:
11
- - npm run coverage
12
- after_script:
13
- - cat coverage/lcov.info | ./node_modules/codeclimate-test-reporter/bin/codeclimate.js
14
- - cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
15
- notifications:
16
- slack: paviateam:C1q99hL9XXpiPpau2PUrVZPC