@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 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
 
@@ -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
- // eslint-disable-next-line @typescript-eslint/no-this-alias
36
- const self = this;
37
- ['includeScope', 'excludeScope', 'includeEvent', 'excludeEvent'].forEach((key) => {
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, configData });
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.watcher = chokidar.watch(`${this.options.appmapDir}/**/mtime`, {
53
+ yield this.reloadConfig();
54
+ this.configWatcher = chokidar.watch(this.options.configFile, {
52
55
  ignoreInitial: true,
53
56
  });
54
- this.watcher.on('add', this.scan.bind(this)).on('change', this.scan.bind(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
- abort() {
58
- if (!this.watcher)
66
+ close() {
67
+ if (!this.appmapWatcher)
59
68
  return;
60
- this.watcher.close();
61
- this.watcher = undefined;
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.options.configData, [appmapFile]);
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(appMapJson, maxSize) {
14
- return (0, models_1.buildAppMap)().source(appMapJson).prune(maxSize).normalize().build();
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;
@@ -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
- const prunedAppMap = (0, pruneAppMap_1.pruneAppMap)(appMapJson, maxSize);
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
- const propertiesSchema = options_json_1.default.definitions[schemaKey];
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);
@@ -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
- joins += node.map.length;
135
+ var _a;
136
+ joins += ((_a = node.map) !== null && _a !== void 0 ? _a : []).length;
136
137
  },
137
138
  });
138
139
  return joins;
@@ -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 (callbacks !== undefined && key in callbacks)
10
- callbacks[key](node, callbacks);
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
- function collectMetadata(metadata) {
5
- const uniqueApps = new Set();
6
- const uniqueLabels = new Set();
7
- const uniqueClients = new Set();
8
- const uniqueFrameworks = new Set();
9
- const uniqueGit = new Set();
10
- const uniqueLanguages = new Set();
11
- const uniqueRecorders = new Set();
12
- const uniqueExceptions = new Set();
13
- function pushDistinctItem(unique, members, item) {
14
- if (item === undefined) {
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
- function pushDistinctItems(unique, members, items) {
24
- (items || []).forEach((item) => pushDistinctItem(unique, members, item));
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 metadata.reduce((memo, appMapMetadata) => {
27
- pushDistinctItem(uniqueApps, memo.apps, appMapMetadata.app);
28
- pushDistinctItems(uniqueLabels, memo.labels, appMapMetadata.labels);
29
- pushDistinctItem(uniqueClients, memo.clients, appMapMetadata.client);
30
- pushDistinctItems(uniqueFrameworks, memo.frameworks, appMapMetadata.frameworks);
31
- pushDistinctItem(uniqueGit, memo.git, appMapMetadata.git);
32
- pushDistinctItem(uniqueLanguages, memo.languages, appMapMetadata.language);
33
- pushDistinctItem(uniqueRecorders, memo.recorders, appMapMetadata.recorder);
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.
@@ -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
- return appMapConfigData['appmap_dir'];
24
+ const configData = appMapConfigData;
25
+ return configData['appmap_dir'];
25
26
  }
26
27
  }
27
28
  });
@@ -125,7 +125,7 @@ const transformProps = (obj) => {
125
125
  };
126
126
  class Telemetry {
127
127
  static get enabled() {
128
- return this._enabled;
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.57.0",
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.14.5",
60
- "@appland/openapi": "1.0.1",
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",