@appland/scanner 1.57.0 → 1.59.1
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.
- package/CHANGELOG.md +21 -0
- package/built/appMapIndex.js +1 -1
- package/built/check.js +4 -6
- package/built/cli/scan/command.js +3 -3
- package/built/cli/scan/watchScan.js +25 -7
- package/built/cli/upload/pruneAppMap.js +7 -3
- package/built/cli/upload.js +5 -3
- package/built/configuration/configurationProvider.js +5 -2
- package/built/database/index.js +2 -1
- package/built/database/visit.js +4 -2
- package/built/report/scanResults.js +44 -39
- package/built/rules/lib/util.js +2 -1
- package/built/telemetry.js +1 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
# [@appland/scanner-v1.59.1](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.59.0...@appland/scanner-v1.59.1) (2022-06-15)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Upgrade @appland/models to v1.16.1 ([7eead86](https://github.com/applandinc/appmap-js/commit/7eead8607f30299150dd08032142a3aba5770f89))
|
|
7
|
+
|
|
8
|
+
# [@appland/scanner-v1.59.0](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.58.0...@appland/scanner-v1.59.0) (2022-06-08)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Always rewrite an AppMap before upload ([61617a9](https://github.com/applandinc/appmap-js/commit/61617a985fc3a4f6ce6dc805f7cc86e3c576264e))
|
|
14
|
+
|
|
15
|
+
# [@appland/scanner-v1.58.0](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.57.0...@appland/scanner-v1.58.0) (2022-06-07)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* Watch the scan config file ([1fde76e](https://github.com/applandinc/appmap-js/commit/1fde76ec626eecb5a9ba300bcc3c636ac6e056f6))
|
|
21
|
+
|
|
1
22
|
# [@appland/scanner-v1.57.0](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.56.1...@appland/scanner-v1.57.0) (2022-05-23)
|
|
2
23
|
|
|
3
24
|
|
package/built/appMapIndex.js
CHANGED
|
@@ -19,7 +19,7 @@ class AppMapIndex {
|
|
|
19
19
|
let ast = ASTBySQLString.get(sql);
|
|
20
20
|
if (!ast) {
|
|
21
21
|
ast = (0, models_1.parseSQL)(sql, sqlWarning_1.default);
|
|
22
|
-
ast ? ASTBySQLString.set(sql, ast) : ASTBySQLString.set(sql,
|
|
22
|
+
ast ? ASTBySQLString.set(sql, ast) : ASTBySQLString.set(sql, null);
|
|
23
23
|
}
|
|
24
24
|
return ast;
|
|
25
25
|
}
|
package/built/check.js
CHANGED
|
@@ -32,13 +32,11 @@ class Check {
|
|
|
32
32
|
}
|
|
33
33
|
toString() {
|
|
34
34
|
const tokens = [`[${this.rule.id}]`];
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (self[key].length > 0) {
|
|
39
|
-
tokens.push(`(${key} ${self[key].join(' && ')})`);
|
|
35
|
+
for (const key of ['includeScope', 'excludeScope', 'includeEvent', 'excludeEvent']) {
|
|
36
|
+
if (this[key].length > 0) {
|
|
37
|
+
tokens.push(`(${key} ${this[key].join(' && ')})`);
|
|
40
38
|
}
|
|
41
|
-
}
|
|
39
|
+
}
|
|
42
40
|
return tokens.join(' ');
|
|
43
41
|
}
|
|
44
42
|
}
|
|
@@ -12,7 +12,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const configurationProvider_1 = require("../../configuration/configurationProvider");
|
|
16
15
|
const errors_1 = require("../../errors");
|
|
17
16
|
const util_1 = require("../../rules/lib/util");
|
|
18
17
|
const validateFile_1 = __importDefault(require("../validateFile"));
|
|
@@ -20,6 +19,7 @@ const scanArgs_1 = __importDefault(require("../scanArgs"));
|
|
|
20
19
|
const resolveAppId_1 = __importDefault(require("../resolveAppId"));
|
|
21
20
|
const singleScan_1 = __importDefault(require("./singleScan"));
|
|
22
21
|
const watchScan_1 = __importDefault(require("./watchScan"));
|
|
22
|
+
const configurationProvider_1 = require("../../configuration/configurationProvider");
|
|
23
23
|
exports.default = {
|
|
24
24
|
command: 'scan',
|
|
25
25
|
describe: 'Scan AppMaps for code behavior findings',
|
|
@@ -69,16 +69,16 @@ exports.default = {
|
|
|
69
69
|
}
|
|
70
70
|
if (appmapDir)
|
|
71
71
|
yield (0, validateFile_1.default)('directory', appmapDir);
|
|
72
|
-
const configData = yield (0, configurationProvider_1.parseConfigFile)(config);
|
|
73
72
|
if (watch) {
|
|
74
73
|
const watchAppMapDir = appmapDir;
|
|
75
|
-
return (0, watchScan_1.default)({ appmapDir: watchAppMapDir,
|
|
74
|
+
return (0, watchScan_1.default)({ appmapDir: watchAppMapDir, configFile: config });
|
|
76
75
|
}
|
|
77
76
|
else {
|
|
78
77
|
let appId = appIdArg;
|
|
79
78
|
if (!reportAllFindings) {
|
|
80
79
|
appId = yield (0, resolveAppId_1.default)(appIdArg, appmapDir);
|
|
81
80
|
}
|
|
81
|
+
const configData = yield (0, configurationProvider_1.parseConfigFile)(config);
|
|
82
82
|
return (0, singleScan_1.default)({
|
|
83
83
|
appmapFile,
|
|
84
84
|
appmapDir,
|
|
@@ -42,38 +42,56 @@ const formatReport_1 = require("./formatReport");
|
|
|
42
42
|
const scanner_1 = __importDefault(require("./scanner"));
|
|
43
43
|
const fs_1 = require("fs");
|
|
44
44
|
const util_1 = require("util");
|
|
45
|
+
const configurationProvider_1 = require("../../configuration/configurationProvider");
|
|
46
|
+
const assert_1 = __importDefault(require("assert"));
|
|
45
47
|
class Watcher {
|
|
46
48
|
constructor(options) {
|
|
47
49
|
this.options = options;
|
|
48
50
|
}
|
|
49
51
|
watch() {
|
|
50
52
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
this.
|
|
53
|
+
yield this.reloadConfig();
|
|
54
|
+
this.configWatcher = chokidar.watch(this.options.configFile, {
|
|
52
55
|
ignoreInitial: true,
|
|
53
56
|
});
|
|
54
|
-
this.
|
|
57
|
+
this.configWatcher
|
|
58
|
+
.on('add', this.reloadConfig.bind(this))
|
|
59
|
+
.on('change', this.reloadConfig.bind(this));
|
|
60
|
+
this.appmapWatcher = chokidar.watch(`${this.options.appmapDir}/**/mtime`, {
|
|
61
|
+
ignoreInitial: true,
|
|
62
|
+
});
|
|
63
|
+
this.appmapWatcher.on('add', this.scan.bind(this)).on('change', this.scan.bind(this));
|
|
55
64
|
});
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
if (!this.
|
|
66
|
+
close() {
|
|
67
|
+
if (!this.appmapWatcher)
|
|
59
68
|
return;
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
69
|
+
(0, assert_1.default)(this.configWatcher, `configWatcher should always be defined if appmapWatcher is defined`);
|
|
70
|
+
this.appmapWatcher.close();
|
|
71
|
+
this.configWatcher.close();
|
|
72
|
+
this.appmapWatcher = undefined;
|
|
73
|
+
this.configWatcher = undefined;
|
|
62
74
|
}
|
|
63
75
|
scan(fileName) {
|
|
64
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
(0, assert_1.default)(this.config, `config should always be loaded before appmapWatcher triggers a scan`);
|
|
65
78
|
const pathTokens = fileName.split('/');
|
|
66
79
|
const appmapDir = pathTokens.slice(0, pathTokens.length - 1).join('/');
|
|
67
80
|
const appmapFile = [appmapDir, 'appmap.json'].join('.');
|
|
68
81
|
const reportFile = [appmapDir, 'appmap-findings.json'].join('/');
|
|
69
82
|
if (!(yield (0, util_1.promisify)(fs_1.exists)(appmapFile)))
|
|
70
83
|
return;
|
|
71
|
-
const scanner = yield (0, scanner_1.default)(true, this.
|
|
84
|
+
const scanner = yield (0, scanner_1.default)(true, this.config, [appmapFile]);
|
|
72
85
|
const rawScanResults = yield scanner.scan();
|
|
73
86
|
// Always report the raw data
|
|
74
87
|
yield (0, promises_1.writeFile)(reportFile, (0, formatReport_1.formatReport)(rawScanResults));
|
|
75
88
|
});
|
|
76
89
|
}
|
|
90
|
+
reloadConfig() {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
this.config = yield (0, configurationProvider_1.parseConfigFile)(this.options.configFile);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
77
95
|
}
|
|
78
96
|
exports.Watcher = Watcher;
|
|
79
97
|
function watchScan(options) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pruneAppMap = exports.maxAppMapSize = void 0;
|
|
3
|
+
exports.buildAppMap = exports.pruneAppMap = exports.maxAppMapSize = void 0;
|
|
4
4
|
const models_1 = require("@appland/models");
|
|
5
5
|
const APPMAP_UPLOAD_MAX_SIZE = parseInt(process.env.APPMAP_UPLOAD_MAX_SIZE || '40960') * 1024;
|
|
6
6
|
if (!APPMAP_UPLOAD_MAX_SIZE) {
|
|
@@ -10,7 +10,11 @@ function maxAppMapSize() {
|
|
|
10
10
|
return APPMAP_UPLOAD_MAX_SIZE;
|
|
11
11
|
}
|
|
12
12
|
exports.maxAppMapSize = maxAppMapSize;
|
|
13
|
-
function pruneAppMap(
|
|
14
|
-
return
|
|
13
|
+
function pruneAppMap(builder, maxSize) {
|
|
14
|
+
return builder.prune(maxSize);
|
|
15
15
|
}
|
|
16
16
|
exports.pruneAppMap = pruneAppMap;
|
|
17
|
+
function buildAppMap(appMapJson) {
|
|
18
|
+
return (0, models_1.buildAppMap)().source(appMapJson);
|
|
19
|
+
}
|
|
20
|
+
exports.buildAppMap = buildAppMap;
|
package/built/cli/upload.js
CHANGED
|
@@ -56,13 +56,15 @@ function create(scanResults, appId, appMapDir, mergeKey, mapsetOptions = {}, ret
|
|
|
56
56
|
.then((buffer) => {
|
|
57
57
|
const maxSize = (0, pruneAppMap_1.maxAppMapSize)();
|
|
58
58
|
const appMapJson = JSON.parse(buffer.toString());
|
|
59
|
+
const builder = (0, pruneAppMap_1.buildAppMap)(appMapJson);
|
|
59
60
|
let metadata = appMapJson.metadata;
|
|
60
61
|
if (buffer.byteLength > maxSize) {
|
|
61
62
|
console.warn(`${fullPath} is larger than ${maxSize / 1024}K, pruning it`);
|
|
62
|
-
|
|
63
|
-
metadata = prunedAppMap.metadata;
|
|
64
|
-
buffer = Buffer.from(JSON.stringify(prunedAppMap));
|
|
63
|
+
(0, pruneAppMap_1.pruneAppMap)(builder, maxSize);
|
|
65
64
|
}
|
|
65
|
+
const prunedAppMap = builder.normalize().build();
|
|
66
|
+
metadata = prunedAppMap.metadata;
|
|
67
|
+
buffer = Buffer.from(JSON.stringify(prunedAppMap));
|
|
66
68
|
return { metadata, buffer };
|
|
67
69
|
})
|
|
68
70
|
.then(({ metadata, buffer }) => {
|
|
@@ -178,6 +178,9 @@ function loadRule(ruleName) {
|
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
exports.loadRule = loadRule;
|
|
181
|
+
function hasDefinition(key) {
|
|
182
|
+
return key in options_json_1.default.definitions;
|
|
183
|
+
}
|
|
181
184
|
function loadConfig(config) {
|
|
182
185
|
return __awaiter(this, void 0, void 0, function* () {
|
|
183
186
|
config.checks
|
|
@@ -188,10 +191,10 @@ function loadConfig(config) {
|
|
|
188
191
|
if ((0, util_1.verbose)()) {
|
|
189
192
|
console.warn(schemaKey);
|
|
190
193
|
}
|
|
191
|
-
|
|
192
|
-
if (!propertiesSchema) {
|
|
194
|
+
if (!hasDefinition(schemaKey)) {
|
|
193
195
|
return;
|
|
194
196
|
}
|
|
197
|
+
const propertiesSchema = options_json_1.default.definitions[schemaKey];
|
|
195
198
|
if ((0, util_1.verbose)()) {
|
|
196
199
|
console.warn(propertiesSchema);
|
|
197
200
|
console.warn(check.properties);
|
package/built/database/index.js
CHANGED
|
@@ -132,7 +132,8 @@ function countJoins(ast) {
|
|
|
132
132
|
let joins = 0;
|
|
133
133
|
(0, visit_1.visit)(ast, {
|
|
134
134
|
'map.join': (node) => {
|
|
135
|
-
|
|
135
|
+
var _a;
|
|
136
|
+
joins += ((_a = node.map) !== null && _a !== void 0 ? _a : []).length;
|
|
136
137
|
},
|
|
137
138
|
});
|
|
138
139
|
return joins;
|
package/built/database/visit.js
CHANGED
|
@@ -6,8 +6,10 @@ function visit(node, callbacks) {
|
|
|
6
6
|
return;
|
|
7
7
|
const { type, variant } = node;
|
|
8
8
|
const key = [type, variant].filter(Boolean).join('.');
|
|
9
|
-
if (
|
|
10
|
-
callbacks[key]
|
|
9
|
+
if (key in callbacks) {
|
|
10
|
+
const callback = callbacks[key];
|
|
11
|
+
callback(node);
|
|
12
|
+
}
|
|
11
13
|
visitNode(node, callbacks);
|
|
12
14
|
}
|
|
13
15
|
exports.visit = visit;
|
|
@@ -1,49 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ScanResults = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
const key = JSON.stringify(item);
|
|
18
|
-
if (!unique.has(key)) {
|
|
19
|
-
unique.add(key);
|
|
20
|
-
members.push(item);
|
|
4
|
+
class DistinctItems {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.members = {};
|
|
7
|
+
}
|
|
8
|
+
push(...items) {
|
|
9
|
+
for (const item of items) {
|
|
10
|
+
if (item === undefined)
|
|
11
|
+
continue;
|
|
12
|
+
const key = JSON.stringify(item);
|
|
13
|
+
if (!(key in this.members))
|
|
14
|
+
this.members[key] = item;
|
|
21
15
|
}
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
[Symbol.iterator]() {
|
|
18
|
+
return Object.values(this.members)[Symbol.iterator]();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function collectMetadata(metadata) {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
const uniqueApps = new DistinctItems();
|
|
24
|
+
const uniqueLabels = new DistinctItems();
|
|
25
|
+
const uniqueClients = new DistinctItems();
|
|
26
|
+
const uniqueFrameworks = new DistinctItems();
|
|
27
|
+
const uniqueGit = new DistinctItems();
|
|
28
|
+
const uniqueLanguages = new DistinctItems();
|
|
29
|
+
const uniqueRecorders = new DistinctItems();
|
|
30
|
+
const uniqueExceptions = new DistinctItems();
|
|
31
|
+
for (const item of metadata) {
|
|
32
|
+
uniqueApps.push(item.app);
|
|
33
|
+
uniqueLabels.push(...((_a = item.labels) !== null && _a !== void 0 ? _a : []));
|
|
34
|
+
uniqueClients.push(item.client);
|
|
35
|
+
uniqueFrameworks.push(...((_b = item.frameworks) !== null && _b !== void 0 ? _b : []));
|
|
36
|
+
uniqueGit.push(item.git);
|
|
37
|
+
uniqueLanguages.push(item.language);
|
|
38
|
+
uniqueRecorders.push(item.recorder);
|
|
39
|
+
uniqueExceptions.push(item.exception);
|
|
25
40
|
}
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
pushDistinctItem(uniqueExceptions, memo.recorders, appMapMetadata.exception);
|
|
35
|
-
return memo;
|
|
36
|
-
}, {
|
|
37
|
-
labels: [],
|
|
38
|
-
apps: [],
|
|
39
|
-
clients: [],
|
|
40
|
-
frameworks: [],
|
|
41
|
-
git: [],
|
|
42
|
-
languages: [],
|
|
43
|
-
recorders: [],
|
|
41
|
+
return {
|
|
42
|
+
labels: [...uniqueLabels],
|
|
43
|
+
apps: [...uniqueApps],
|
|
44
|
+
clients: [...uniqueClients],
|
|
45
|
+
frameworks: [...uniqueFrameworks],
|
|
46
|
+
git: [...uniqueGit],
|
|
47
|
+
languages: [...uniqueLanguages],
|
|
48
|
+
recorders: [...uniqueRecorders],
|
|
44
49
|
testStatuses: [],
|
|
45
|
-
exceptions: [],
|
|
46
|
-
}
|
|
50
|
+
exceptions: [...uniqueExceptions],
|
|
51
|
+
};
|
|
47
52
|
}
|
|
48
53
|
/**
|
|
49
54
|
* ScannerSummary summarizes the results of the entire scan.
|
package/built/rules/lib/util.js
CHANGED
|
@@ -21,7 +21,8 @@ function appmapDirFromConfig() {
|
|
|
21
21
|
if (appMapConfigExists) {
|
|
22
22
|
const appMapConfigData = (0, js_yaml_1.load)((yield (0, promises_1.readFile)('appmap.yml')).toString());
|
|
23
23
|
if (appMapConfigData && typeof appMapConfigData === 'object') {
|
|
24
|
-
|
|
24
|
+
const configData = appMapConfigData;
|
|
25
|
+
return configData['appmap_dir'];
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
});
|
package/built/telemetry.js
CHANGED
|
@@ -125,7 +125,7 @@ const transformProps = (obj) => {
|
|
|
125
125
|
};
|
|
126
126
|
class Telemetry {
|
|
127
127
|
static get enabled() {
|
|
128
|
-
return
|
|
128
|
+
return process.env.APPMAP_TELEMETRY_DISABLED === undefined;
|
|
129
129
|
}
|
|
130
130
|
static get session() {
|
|
131
131
|
var _a;
|
|
@@ -211,5 +211,4 @@ class Telemetry {
|
|
|
211
211
|
}
|
|
212
212
|
exports.default = Telemetry;
|
|
213
213
|
Telemetry.debug = process.env.APPMAP_TELEMETRY_DEBUG !== undefined;
|
|
214
|
-
Telemetry._enabled = process.env.APPMAP_TELEMETRY_DISABLED === undefined;
|
|
215
214
|
Telemetry.machineId = getMachineId();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appland/scanner",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.59.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": "built/cli.js",
|
|
6
6
|
"files": [
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@appland/client": "^1.3.0",
|
|
59
|
-
"@appland/models": "^1.
|
|
60
|
-
"@appland/openapi": "1.0.
|
|
59
|
+
"@appland/models": "^1.16.1",
|
|
60
|
+
"@appland/openapi": "1.0.2",
|
|
61
61
|
"@appland/sql-parser": "^1.5.0",
|
|
62
62
|
"@types/cli-progress": "^3.9.2",
|
|
63
63
|
"ajv": "^8.8.2",
|