@forge/lint 5.1.1-next.5 → 5.1.1-next.6

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/out/lint/abstract-linter.js +1 -0
  3. package/out/lint/base-linter.js +5 -3
  4. package/out/lint/lint.js +1 -1
  5. package/out/lint/linter-interface.js +4 -2
  6. package/out/lint/linters/dynamic-properties-linter/dynamic-properties-permissions-linter.js +1 -0
  7. package/out/lint/linters/dynamic-properties-linter/verifiers/abstract-dynamic-properties-verifier.js +2 -3
  8. package/out/lint/linters/dynamic-properties-linter/verifiers/dynamic-properties-icon-verifier.js +2 -2
  9. package/out/lint/linters/dynamic-properties-linter/visitors/abstract-icon-visitor.js +19 -22
  10. package/out/lint/linters/dynamic-properties-linter/visitors/confluence-icon-visitor.js +5 -8
  11. package/out/lint/linters/dynamic-properties-linter/visitors/jira-icon-visitor.js +28 -31
  12. package/out/lint/linters/handler-linter/handler-linter.js +9 -6
  13. package/out/lint/linters/handler-linter/verifiers/handlers-verifier.js +1 -2
  14. package/out/lint/linters/handler-linter/visitors/exported-function-node-visitor.js +15 -14
  15. package/out/lint/linters/manifest-linter/abstract-manifest-linter.js +5 -5
  16. package/out/lint/linters/manifest-linter/deprecated-csp-permissions-manifest-linter.js +1 -2
  17. package/out/lint/linters/manifest-linter/permissions-manifest-linter.js +1 -2
  18. package/out/lint/linters/manifest-linter/remote-compute-manifest-linter.js +1 -2
  19. package/out/lint/linters/permission-linter/permission-linter.js +43 -22
  20. package/out/lint/linters/permission-linter/verifiers/content-property-verifier.js +1 -2
  21. package/out/lint/linters/permission-linter/verifiers/external-fetch-verifier.js +4 -4
  22. package/out/lint/linters/permission-linter/verifiers/image-url-verifier.js +2 -2
  23. package/out/lint/linters/permission-linter/verifiers/product-verifier.js +15 -12
  24. package/out/lint/linters/permission-linter/verifiers/storage-api-verifier.js +9 -4
  25. package/out/lint/linters/permission-linter/verifiers/ui-hook-verifier.js +1 -2
  26. package/out/lint/linters/permission-linter/visitors/external-fetch-call-visitor.js +11 -13
  27. package/out/lint/linters/permission-linter/visitors/image-url-visitor.js +2 -2
  28. package/out/lint/linters/permission-linter/visitors/product-node-visitor.js +3 -3
  29. package/out/lint/linters/permission-linter/visitors/storage-api-node-visitor.js +4 -1
  30. package/out/lint/linters/permission-linter/visitors/ui-hook-node-visitor.js +5 -1
  31. package/out/lint/linters/remote-linter/invoke-remote-linter.js +1 -0
  32. package/out/lint/linters/remote-linter/visitors/invoke-remote-call-visitor.js +18 -12
  33. package/out/lint/linters/verifier-interface.js +2 -0
  34. package/out/parse/parser.js +10 -2
  35. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @forge/lint
2
2
 
3
+ ## 5.1.1-next.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [670a419]
8
+ - @forge/manifest@7.3.0-next.5
9
+ - @forge/cli-shared@5.0.0-next.6
10
+
3
11
  ## 5.1.1-next.5
4
12
 
5
13
  ### Patch Changes
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AbstractLinter = void 0;
4
4
  const cli_shared_1 = require("@forge/cli-shared");
5
5
  class AbstractLinter {
6
+ logger;
6
7
  constructor(logger) {
7
8
  this.logger = logger;
8
9
  }
@@ -4,13 +4,15 @@ const cli_shared_1 = require("@forge/cli-shared");
4
4
  const linter_interface_1 = require("./linter-interface");
5
5
  const abstract_linter_1 = require("./abstract-linter");
6
6
  class BaseLinter extends abstract_linter_1.AbstractLinter {
7
+ environment;
8
+ logger;
9
+ nodeVisitors = [];
10
+ matches = new Map();
11
+ verifiers = {};
7
12
  constructor(environment, logger) {
8
13
  super(logger);
9
14
  this.environment = environment;
10
15
  this.logger = logger;
11
- this.nodeVisitors = [];
12
- this.matches = new Map();
13
- this.verifiers = {};
14
16
  }
15
17
  getFixer() {
16
18
  return undefined;
package/out/lint/lint.js CHANGED
@@ -105,7 +105,7 @@ const lint = async (filesToLint, manifest, environment, logger, parseFunction =
105
105
  }
106
106
  }
107
107
  return { ast: null, filepath: '' };
108
- }))).filter((result) => !!(result === null || result === void 0 ? void 0 : result.ast));
108
+ }))).filter((result) => !!result?.ast);
109
109
  await Promise.all(linters.map((linter) => linter.bootstrap()));
110
110
  const results = await Promise.all(linters.map((linter) => linter.batchExecute(lintInputs))).then(cli_shared_1.flat);
111
111
  return results.map((result) => {
@@ -7,11 +7,13 @@ var LintClass;
7
7
  LintClass["Warning"] = "warning";
8
8
  })(LintClass = exports.LintClass || (exports.LintClass = {}));
9
9
  class LintResult {
10
+ file;
11
+ fixer;
12
+ errors = [];
13
+ warnings = [];
10
14
  constructor(file, fixer) {
11
15
  this.file = file;
12
16
  this.fixer = fixer;
13
- this.errors = [];
14
- this.warnings = [];
15
17
  }
16
18
  add(rule) {
17
19
  switch (rule.class) {
@@ -9,6 +9,7 @@ const confluence_icon_visitor_1 = require("./visitors/confluence-icon-visitor");
9
9
  const permission_linter_1 = require("../permission-linter/permission-linter");
10
10
  const jira_icon_visitor_1 = require("./visitors/jira-icon-visitor");
11
11
  class DynamicPropertiesPermissionsLinter extends base_linter_1.default {
12
+ manifest;
12
13
  constructor(environment, manifest, logger) {
13
14
  super(environment, logger);
14
15
  this.manifest = manifest;
@@ -3,17 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AbstractDynamicPropertiesVerifier = void 0;
4
4
  const verifier_interface_1 = require("../../verifier-interface");
5
5
  class AbstractDynamicPropertiesVerifier extends verifier_interface_1.BaseLintIssueVerifier {
6
+ shouldRunCheck = false;
6
7
  constructor(environment, manifest) {
7
8
  super(environment, manifest);
8
- this.shouldRunCheck = false;
9
9
  Object.keys(this.manifest.modules || {}).forEach((moduleType) => {
10
- var _a, _b;
11
10
  switch (moduleType) {
12
11
  case 'confluence:contentBylineItem':
13
12
  case 'jira:issueGlance':
14
13
  case 'jira:issueContext':
15
14
  this.shouldRunCheck =
16
- ((_b = (_a = this.manifest.modules) === null || _a === void 0 ? void 0 : _a[moduleType]) === null || _b === void 0 ? void 0 : _b.find((module) => { var _a; return (_a = module.dynamicProperties) === null || _a === void 0 ? void 0 : _a.function; })) !==
15
+ this.manifest.modules?.[moduleType]?.find((module) => module.dynamicProperties?.function) !==
17
16
  undefined;
18
17
  break;
19
18
  }
@@ -7,10 +7,10 @@ const utils_1 = require("../../utils");
7
7
  const text_1 = require("../../../text");
8
8
  const abstract_dynamic_properties_verifier_1 = require("./abstract-dynamic-properties-verifier");
9
9
  class DynamicPropertiesIconVerifier extends abstract_dynamic_properties_verifier_1.AbstractDynamicPropertiesVerifier {
10
+ egressFilteringService;
10
11
  constructor(environment, manifest) {
11
- var _a, _b, _c, _d;
12
12
  super(environment, manifest);
13
- const allowList = (_d = (_c = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.external) === null || _c === void 0 ? void 0 : _c.images) !== null && _d !== void 0 ? _d : [];
13
+ const allowList = this.manifest?.permissions?.external?.images ?? [];
14
14
  const collectedUrls = allowList.filter((item) => typeof item === 'string');
15
15
  this.egressFilteringService = new egress_1.EgressFilteringService(collectedUrls);
16
16
  }
@@ -3,39 +3,36 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AbstractIconVisitor = void 0;
4
4
  const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
5
  class AbstractIconVisitor {
6
- constructor() {
7
- this.isBundledUri = (iconUri) => iconUri.startsWith('resource:') || iconUri.startsWith('data:image');
8
- this.handleIconNode = (iconNode, callback) => {
9
- if ((iconNode === null || iconNode === void 0 ? void 0 : iconNode.type) === typescript_estree_1.AST_NODE_TYPES.Literal && typeof (iconNode === null || iconNode === void 0 ? void 0 : iconNode.value) === 'string') {
10
- if (iconNode.value.trim() !== '' && !this.isBundledUri(iconNode.value.trim())) {
11
- const iconUrl = this.transformArgsToIconUrl(iconNode);
12
- callback(iconUrl);
13
- }
14
- }
15
- };
16
- this.transformArgsToIconUrl = (iconNode) => ({
17
- type: 'DYNAMIC_PROPERTIES_ICON',
18
- url: iconNode.value,
19
- line: iconNode.loc.start.line,
20
- column: iconNode.loc.start.column
21
- });
22
- }
23
6
  visit(node, parent, callback) {
24
- var _a, _b;
25
7
  switch (node.type) {
26
8
  case typescript_estree_1.AST_NODE_TYPES.ArrowFunctionExpression:
27
- if (((_a = node.body) === null || _a === void 0 ? void 0 : _a.type) === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
9
+ if (node.body?.type === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
28
10
  const iconDefinitionNode = this.getIconDefinitionNode(node.body);
29
- this.handleIconNode(iconDefinitionNode === null || iconDefinitionNode === void 0 ? void 0 : iconDefinitionNode.value, callback);
11
+ this.handleIconNode(iconDefinitionNode?.value, callback);
30
12
  }
31
13
  break;
32
14
  case typescript_estree_1.AST_NODE_TYPES.ReturnStatement:
33
- if (((_b = node.argument) === null || _b === void 0 ? void 0 : _b.type) === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
15
+ if (node.argument?.type === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
34
16
  const iconDefinitionNode = this.getIconDefinitionNode(node.argument);
35
- this.handleIconNode(iconDefinitionNode === null || iconDefinitionNode === void 0 ? void 0 : iconDefinitionNode.value, callback);
17
+ this.handleIconNode(iconDefinitionNode?.value, callback);
36
18
  }
37
19
  break;
38
20
  }
39
21
  }
22
+ isBundledUri = (iconUri) => iconUri.startsWith('resource:') || iconUri.startsWith('data:image');
23
+ handleIconNode = (iconNode, callback) => {
24
+ if (iconNode?.type === typescript_estree_1.AST_NODE_TYPES.Literal && typeof iconNode?.value === 'string') {
25
+ if (iconNode.value.trim() !== '' && !this.isBundledUri(iconNode.value.trim())) {
26
+ const iconUrl = this.transformArgsToIconUrl(iconNode);
27
+ callback(iconUrl);
28
+ }
29
+ }
30
+ };
31
+ transformArgsToIconUrl = (iconNode) => ({
32
+ type: 'DYNAMIC_PROPERTIES_ICON',
33
+ url: iconNode.value,
34
+ line: iconNode.loc.start.line,
35
+ column: iconNode.loc.start.column
36
+ });
40
37
  }
41
38
  exports.AbstractIconVisitor = AbstractIconVisitor;
@@ -4,16 +4,13 @@ exports.ConfluenceIconVisitor = void 0;
4
4
  const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
5
  const abstract_icon_visitor_1 = require("./abstract-icon-visitor");
6
6
  class ConfluenceIconVisitor extends abstract_icon_visitor_1.AbstractIconVisitor {
7
- constructor() {
8
- super(...arguments);
9
- this.isIconPropertyDefinition = (node) => {
10
- return (node.type === typescript_estree_1.AST_NODE_TYPES.Property &&
11
- ((node.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node.key.name === 'icon') ||
12
- (node.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && node.key.value === 'icon')));
13
- };
14
- }
15
7
  getIconDefinitionNode(node) {
16
8
  return node.properties.find(this.isIconPropertyDefinition);
17
9
  }
10
+ isIconPropertyDefinition = (node) => {
11
+ return (node.type === typescript_estree_1.AST_NODE_TYPES.Property &&
12
+ ((node.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node.key.name === 'icon') ||
13
+ (node.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && node.key.value === 'icon')));
14
+ };
18
15
  }
19
16
  exports.ConfluenceIconVisitor = ConfluenceIconVisitor;
@@ -4,40 +4,37 @@ exports.JiraIconVisitor = void 0;
4
4
  const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
5
  const abstract_icon_visitor_1 = require("./abstract-icon-visitor");
6
6
  class JiraIconVisitor extends abstract_icon_visitor_1.AbstractIconVisitor {
7
- constructor() {
8
- super(...arguments);
9
- this.isStatusPropertyDefinition = (node) => {
10
- return (node.type === typescript_estree_1.AST_NODE_TYPES.Property &&
11
- ((node.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && node.key.value === 'status') ||
12
- (node.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node.key.name === 'status')) &&
13
- node.value.type === typescript_estree_1.AST_NODE_TYPES.ObjectExpression &&
14
- node.value.properties.find((prop) => {
15
- return (prop.type === typescript_estree_1.AST_NODE_TYPES.Property &&
16
- ((prop.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.key.value === 'type') ||
17
- (prop.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.key.name === 'type')) &&
18
- ((prop.value.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.value.value === 'icon') ||
19
- (prop.value.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.value.name === 'icon')));
20
- }) !== undefined);
21
- };
22
- this.extractIconDefinition = (node) => {
23
- if (!node) {
24
- return undefined;
25
- }
26
- const valueDefinitionNode = node === null || node === void 0 ? void 0 : node.value.properties.find((prop) => {
27
- return (prop.type === typescript_estree_1.AST_NODE_TYPES.Property &&
28
- ((prop.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.key.value === 'value') ||
29
- (prop.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.key.name === 'value')));
30
- });
31
- return valueDefinitionNode.value.properties.find((prop) => {
32
- return (prop.type === typescript_estree_1.AST_NODE_TYPES.Property &&
33
- ((prop.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.key.value === 'url') ||
34
- (prop.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.key.name === 'url')));
35
- });
36
- };
37
- }
38
7
  getIconDefinitionNode(node) {
39
8
  const statusPropertyNode = node.properties.find(this.isStatusPropertyDefinition);
40
9
  return this.extractIconDefinition(statusPropertyNode);
41
10
  }
11
+ isStatusPropertyDefinition = (node) => {
12
+ return (node.type === typescript_estree_1.AST_NODE_TYPES.Property &&
13
+ ((node.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && node.key.value === 'status') ||
14
+ (node.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node.key.name === 'status')) &&
15
+ node.value.type === typescript_estree_1.AST_NODE_TYPES.ObjectExpression &&
16
+ node.value.properties.find((prop) => {
17
+ return (prop.type === typescript_estree_1.AST_NODE_TYPES.Property &&
18
+ ((prop.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.key.value === 'type') ||
19
+ (prop.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.key.name === 'type')) &&
20
+ ((prop.value.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.value.value === 'icon') ||
21
+ (prop.value.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.value.name === 'icon')));
22
+ }) !== undefined);
23
+ };
24
+ extractIconDefinition = (node) => {
25
+ if (!node) {
26
+ return undefined;
27
+ }
28
+ const valueDefinitionNode = node?.value.properties.find((prop) => {
29
+ return (prop.type === typescript_estree_1.AST_NODE_TYPES.Property &&
30
+ ((prop.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.key.value === 'value') ||
31
+ (prop.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.key.name === 'value')));
32
+ });
33
+ return valueDefinitionNode.value.properties.find((prop) => {
34
+ return (prop.type === typescript_estree_1.AST_NODE_TYPES.Property &&
35
+ ((prop.key.type === typescript_estree_1.AST_NODE_TYPES.Literal && prop.key.value === 'url') ||
36
+ (prop.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && prop.key.name === 'url')));
37
+ });
38
+ };
42
39
  }
43
40
  exports.JiraIconVisitor = JiraIconVisitor;
@@ -7,10 +7,10 @@ const base_linter_1 = tslib_1.__importDefault(require("../../base-linter"));
7
7
  const handlers_verifier_1 = require("./verifiers/handlers-verifier");
8
8
  const visitors_1 = require("./visitors");
9
9
  class HandlerLinter extends base_linter_1.default {
10
+ manifest;
10
11
  constructor(environment, manifest, logger) {
11
12
  super(environment, logger);
12
13
  this.manifest = manifest;
13
- this.getHandlerFileRegex = (fileName) => new RegExp(`^src(\/|\\\\)${fileName}\.[tj](s|sx)$`);
14
14
  }
15
15
  async bootstrap() {
16
16
  this.nodeVisitors = [new visitors_1.ExportedFunctionNodeVisitor()];
@@ -19,20 +19,23 @@ class HandlerLinter extends base_linter_1.default {
19
19
  functionHandlers: new handlers_verifier_1.HandlersVerifier(humanReadableEnvironment, this.manifest)
20
20
  };
21
21
  }
22
+ getHandlerFileRegex = (fileName) => new RegExp(`^src(\/|\\\\)${fileName}\.[tj](s|sx)$`);
22
23
  getFunctionHandlers(manifest) {
23
- var _a, _b, _c;
24
- return (_c = (_b = (_a = manifest.modules) === null || _a === void 0 ? void 0 : _a.function) === null || _b === void 0 ? void 0 : _b.filter((funcs) => funcs.handler && funcs.handler.split('.').length === 2)) === null || _c === void 0 ? void 0 : _c.map((funcs) => {
24
+ return manifest.modules?.function
25
+ ?.filter((funcs) => funcs.handler && funcs.handler.split('.').length === 2)
26
+ ?.map((funcs) => {
25
27
  const [file, method] = funcs.handler.split('.');
26
28
  return {
27
29
  file,
28
30
  method,
29
31
  key: funcs.key
30
32
  };
31
- }).filter((handler) => handler.method && handler.file);
33
+ })
34
+ .filter((handler) => handler.method && handler.file);
32
35
  }
33
36
  setupMatchesMap(filepath) {
34
37
  const handlers = this.getFunctionHandlers(this.manifest);
35
- const filteredHandlers = handlers === null || handlers === void 0 ? void 0 : handlers.filter((handler) => this.getHandlerFileRegex(handler.file).test(filepath));
38
+ const filteredHandlers = handlers?.filter((handler) => this.getHandlerFileRegex(handler.file).test(filepath));
36
39
  this.matches.set(filepath, {
37
40
  functionHandlers: {
38
41
  expectedMethods: filteredHandlers || [],
@@ -42,7 +45,7 @@ class HandlerLinter extends base_linter_1.default {
42
45
  }
43
46
  filterLintInput(inputs) {
44
47
  const handlers = this.getFunctionHandlers(this.manifest);
45
- return inputs.filter((input) => handlers === null || handlers === void 0 ? void 0 : handlers.find((handler) => this.getHandlerFileRegex(handler.file).test(input.filepath)));
48
+ return inputs.filter((input) => handlers?.find((handler) => this.getHandlerFileRegex(handler.file).test(input.filepath)));
46
49
  }
47
50
  addLintCriteriaMatch(exportedMethod, filepath) {
48
51
  const criteriaMatches = this.matches.get(filepath);
@@ -9,8 +9,7 @@ class HandlersVerifier extends verifier_interface_1.BaseLintIssueVerifier {
9
9
  return linter_interface_1.LintClass.Warning;
10
10
  }
11
11
  async process(input) {
12
- var _a, _b;
13
- if (!((_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.modules) === null || _b === void 0 ? void 0 : _b.function)) {
12
+ if (!this.manifest?.modules?.function) {
14
13
  return [];
15
14
  }
16
15
  const missingMethods = input.expectedMethods.filter((func) => !input.exportedMethods.find((exportedMethod) => exportedMethod.method === func.method));
@@ -23,21 +23,20 @@ class ExportedFunctionNodeVisitor {
23
23
  }
24
24
  visitSpecifiedNamedExports(node, specifier, callback) {
25
25
  if (specifier.type === typescript_estree_1.AST_NODE_TYPES.ExportSpecifier && specifier.local.type === typescript_estree_1.AST_NODE_TYPES.Identifier) {
26
- callback(this.createExportedMethod(specifier.exported.name, Object.assign({}, node.loc.start)));
26
+ callback(this.createExportedMethod(specifier.exported.name, { ...node.loc.start }));
27
27
  }
28
28
  }
29
29
  visitInlineNamedExport(node, callback) {
30
- var _a, _b, _c, _d;
31
- if (((_a = node.declaration) === null || _a === void 0 ? void 0 : _a.type) === typescript_estree_1.AST_NODE_TYPES.VariableDeclaration) {
30
+ if (node.declaration?.type === typescript_estree_1.AST_NODE_TYPES.VariableDeclaration) {
32
31
  node.declaration.declarations.forEach((declarator) => {
33
32
  if (declarator.id && declarator.id.type === typescript_estree_1.AST_NODE_TYPES.Identifier) {
34
- callback(this.createExportedMethod(declarator.id.name, Object.assign({}, declarator.id.loc.start)));
33
+ callback(this.createExportedMethod(declarator.id.name, { ...declarator.id.loc.start }));
35
34
  }
36
35
  });
37
36
  }
38
- else if (((_b = node.declaration) === null || _b === void 0 ? void 0 : _b.type) === typescript_estree_1.AST_NODE_TYPES.FunctionDeclaration) {
39
- if (((_c = node.declaration) === null || _c === void 0 ? void 0 : _c.id) && ((_d = node.declaration) === null || _d === void 0 ? void 0 : _d.id.type) === typescript_estree_1.AST_NODE_TYPES.Identifier) {
40
- callback(this.createExportedMethod(node.declaration.id.name, Object.assign({}, node.declaration.id.loc.start)));
37
+ else if (node.declaration?.type === typescript_estree_1.AST_NODE_TYPES.FunctionDeclaration) {
38
+ if (node.declaration?.id && node.declaration?.id.type === typescript_estree_1.AST_NODE_TYPES.Identifier) {
39
+ callback(this.createExportedMethod(node.declaration.id.name, { ...node.declaration.id.loc.start }));
41
40
  }
42
41
  }
43
42
  }
@@ -48,21 +47,23 @@ class ExportedFunctionNodeVisitor {
48
47
  }
49
48
  visitMemberExpression(node, callback) {
50
49
  if (node.property.type === typescript_estree_1.AST_NODE_TYPES.Identifier && this.isExports(node.object)) {
51
- callback(this.createExportedMethod(node.property.name, Object.assign({}, node.property.loc.start)));
50
+ callback(this.createExportedMethod(node.property.name, { ...node.property.loc.start }));
52
51
  }
53
52
  }
54
53
  tryAddObjectExpressionPropertiesExportedMethods(node, callback) {
55
- var _a, _b;
56
- if (((_a = node.right) === null || _a === void 0 ? void 0 : _a.type) === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
57
- (_b = node.right.properties) === null || _b === void 0 ? void 0 : _b.forEach((property) => {
54
+ if (node.right?.type === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
55
+ node.right.properties?.forEach((property) => {
58
56
  if (property.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier) {
59
- callback(this.createExportedMethod(property.key.name, Object.assign({}, property.key.loc.start)));
57
+ callback(this.createExportedMethod(property.key.name, { ...property.key.loc.start }));
60
58
  }
61
59
  });
62
60
  }
63
61
  }
64
62
  createExportedMethod(method, location) {
65
- return Object.assign({ method }, location);
63
+ return {
64
+ method,
65
+ ...location
66
+ };
66
67
  }
67
68
  isExports(node) {
68
69
  return ((node.type === typescript_estree_1.AST_NODE_TYPES.MemberExpression &&
@@ -70,7 +71,7 @@ class ExportedFunctionNodeVisitor {
70
71
  node.object.name === 'module' &&
71
72
  node.property.type === typescript_estree_1.AST_NODE_TYPES.Identifier &&
72
73
  node.property.name === 'exports') ||
73
- ((node === null || node === void 0 ? void 0 : node.type) === typescript_estree_1.AST_NODE_TYPES.Identifier && (node === null || node === void 0 ? void 0 : node.name) === 'exports'));
74
+ (node?.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node?.name === 'exports'));
74
75
  }
75
76
  }
76
77
  exports.ExportedFunctionNodeVisitor = ExportedFunctionNodeVisitor;
@@ -5,14 +5,15 @@ const manifest_1 = require("@forge/manifest");
5
5
  const linter_interface_1 = require("../../linter-interface");
6
6
  const abstract_linter_1 = require("../../abstract-linter");
7
7
  class AbstractManifestLinter extends abstract_linter_1.AbstractLinter {
8
+ type;
9
+ processor;
8
10
  constructor(type, logger) {
9
11
  super(logger);
10
12
  this.type = type;
11
13
  }
12
14
  mapManifestResponse(results, fixer) {
13
- var _a;
14
15
  const manifestLintResults = new linter_interface_1.LintResult(manifest_1.MANIFEST_FILE, fixer);
15
- manifestLintResults.batchAdd(...((_a = this.getResultsForFixer(results).map(({ level, message, line, column, reference, metadata }) => {
16
+ manifestLintResults.batchAdd(...(this.getResultsForFixer(results).map(({ level, message, line, column, reference, metadata }) => {
16
17
  return {
17
18
  class: level,
18
19
  message,
@@ -21,7 +22,7 @@ class AbstractManifestLinter extends abstract_linter_1.AbstractLinter {
21
22
  column,
22
23
  metadata
23
24
  };
24
- })) !== null && _a !== void 0 ? _a : []).sort((a, b) => a.line - b.line));
25
+ }) ?? []).sort((a, b) => a.line - b.line));
25
26
  return manifestLintResults;
26
27
  }
27
28
  getProcessor() {
@@ -42,8 +43,7 @@ class AbstractManifestLinter extends abstract_linter_1.AbstractLinter {
42
43
  return undefined;
43
44
  }
44
45
  getResultsForFixer(results) {
45
- var _a;
46
- return ((_a = results.errors) === null || _a === void 0 ? void 0 : _a.filter((error) => !error.metadata)) || [];
46
+ return results.errors?.filter((error) => !error.metadata) || [];
47
47
  }
48
48
  }
49
49
  exports.AbstractManifestLinter = AbstractManifestLinter;
@@ -12,8 +12,7 @@ class DeprecatedCspPermissionsManifestLinter extends abstract_manifest_linter_1.
12
12
  return permission_linter_1.fixMissingPermissions;
13
13
  }
14
14
  getResultsForFixer(results) {
15
- var _a;
16
- return ((_a = results.errors) === null || _a === void 0 ? void 0 : _a.filter((error) => { var _a; return (_a = error.metadata) === null || _a === void 0 ? void 0 : _a.missingContentStylePermission; })) || [];
15
+ return results.errors?.filter((error) => error.metadata?.missingContentStylePermission) || [];
17
16
  }
18
17
  }
19
18
  exports.DeprecatedCspPermissionsManifestLinter = DeprecatedCspPermissionsManifestLinter;
@@ -12,8 +12,7 @@ class PermissionsManifestLinter extends abstract_manifest_linter_1.AbstractManif
12
12
  return permission_linter_1.fixMissingPermissions;
13
13
  }
14
14
  getResultsForFixer(results) {
15
- var _a;
16
- return ((_a = results.errors) === null || _a === void 0 ? void 0 : _a.filter((error) => { var _a; return (_a = error.metadata) === null || _a === void 0 ? void 0 : _a.missingPermission; })) || [];
15
+ return results.errors?.filter((error) => error.metadata?.missingPermission) || [];
17
16
  }
18
17
  }
19
18
  exports.PermissionsManifestLinter = PermissionsManifestLinter;
@@ -12,8 +12,7 @@ class RemoteComputeManifestLinter extends abstract_manifest_linter_1.AbstractMan
12
12
  return permission_linter_1.fixMissingPermissions;
13
13
  }
14
14
  getResultsForFixer(results) {
15
- var _a;
16
- return ((_a = results.errors) === null || _a === void 0 ? void 0 : _a.filter((error) => { var _a; return (_a = error.metadata) === null || _a === void 0 ? void 0 : _a.missingPermission; })) || [];
15
+ return results.errors?.filter((error) => error.metadata?.missingPermission) || [];
17
16
  }
18
17
  }
19
18
  exports.RemoteComputeManifestLinter = RemoteComputeManifestLinter;
@@ -32,47 +32,70 @@ const findMissingPermissions = (errors, warnings, permissionsType, state) => {
32
32
  };
33
33
  exports.findMissingPermissions = findMissingPermissions;
34
34
  const fixMissingPermissions = async (errors, warnings, state) => {
35
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
36
35
  const missingScopes = (0, exports.findMissingPermissions)(errors, warnings, 'missingPermission', state);
37
36
  const missingExternalFetchBackend = (0, exports.findMissingPermissions)(errors, warnings, 'missingExternalFetchPermission', state);
38
37
  const missingContentStyle = (0, exports.findMissingPermissions)(errors, warnings, 'missingContentStylePermission', state);
39
38
  const missingExternalImage = (0, exports.findMissingPermissions)(errors, warnings, 'missingExternalImagesPermission', state);
40
- const currentPermissions = (_b = (_a = (await state.configFile.readConfig())) === null || _a === void 0 ? void 0 : _a.permissions) !== null && _b !== void 0 ? _b : {};
41
- const currentRemotes = (_d = (_c = (await state.configFile.readConfig())) === null || _c === void 0 ? void 0 : _c.remotes) !== null && _d !== void 0 ? _d : [];
42
- const currentScopes = (_e = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.scopes) !== null && _e !== void 0 ? _e : [];
39
+ const currentPermissions = (await state.configFile.readConfig())?.permissions ?? {};
40
+ const currentRemotes = (await state.configFile.readConfig())?.remotes ?? [];
41
+ const currentScopes = currentPermissions?.scopes ?? [];
43
42
  currentScopes.forEach((e) => missingScopes.add(e));
44
- const currentExternalFetchBackend = (_h = (_g = (_f = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.external) === null || _f === void 0 ? void 0 : _f.fetch) === null || _g === void 0 ? void 0 : _g.backend) !== null && _h !== void 0 ? _h : [];
43
+ const currentExternalFetchBackend = currentPermissions?.external?.fetch?.backend ?? [];
45
44
  currentExternalFetchBackend
46
45
  .map((item) => {
47
- var _a;
48
46
  if (typeof item === 'string')
49
47
  return item;
50
- return (_a = currentRemotes.find((remote) => remote.key == item.remote)) === null || _a === void 0 ? void 0 : _a.baseUrl;
48
+ return currentRemotes.find((remote) => remote.key == item.remote)?.baseUrl;
51
49
  })
52
50
  .filter((item) => typeof item === 'string')
53
51
  .forEach((e) => missingExternalFetchBackend.add(e));
54
52
  const arrayMissingExternalFetchBackend = [...missingExternalFetchBackend];
55
- const currentContentStyles = (_k = (_j = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.content) === null || _j === void 0 ? void 0 : _j.styles) !== null && _k !== void 0 ? _k : [];
53
+ const currentContentStyles = currentPermissions?.content?.styles ?? [];
56
54
  currentContentStyles.forEach((e) => missingContentStyle.add(e));
57
55
  const arrayMissingContentStyles = [...missingContentStyle];
58
- const currentExternalImages = (_m = (_l = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.external) === null || _l === void 0 ? void 0 : _l.images) !== null && _m !== void 0 ? _m : [];
56
+ const currentExternalImages = currentPermissions?.external?.images ?? [];
59
57
  currentExternalImages.forEach((e) => missingExternalImage.add(e));
60
58
  const arrayMissingExternalImages = [...missingExternalImage];
61
- const config = Object.assign(Object.assign({}, currentPermissions), { scopes: [...missingScopes] });
59
+ const config = {
60
+ ...currentPermissions,
61
+ scopes: [...missingScopes]
62
+ };
62
63
  if (arrayMissingExternalFetchBackend.length > 0) {
63
- config.external = Object.assign(Object.assign({}, config.external), { fetch: Object.assign(Object.assign({}, (_o = config.external) === null || _o === void 0 ? void 0 : _o.fetch), { backend: arrayMissingExternalFetchBackend }) });
64
+ config.external = {
65
+ ...config.external,
66
+ fetch: {
67
+ ...config.external?.fetch,
68
+ backend: arrayMissingExternalFetchBackend
69
+ }
70
+ };
64
71
  }
65
72
  if (arrayMissingExternalImages.length > 0) {
66
- config.external = Object.assign(Object.assign({}, config.external), { images: arrayMissingExternalImages });
73
+ config.external = {
74
+ ...config.external,
75
+ images: arrayMissingExternalImages
76
+ };
67
77
  }
68
78
  if (arrayMissingContentStyles.length > 0) {
69
- config.content = Object.assign(Object.assign({}, config.content), { styles: arrayMissingContentStyles });
79
+ config.content = {
80
+ ...config.content,
81
+ styles: arrayMissingContentStyles
82
+ };
70
83
  }
71
84
  await state.configFile.writeToConfigFile('permissions', config);
72
85
  return state;
73
86
  };
74
87
  exports.fixMissingPermissions = fixMissingPermissions;
75
88
  class PermissionLinter extends base_linter_1.default {
89
+ manifest;
90
+ static JIRA_CACHE_KEY = 'permissions-jira-cache-key';
91
+ static JSM_CACHE_KEY = 'permissions-jsm-cache-key';
92
+ static JSW_CACHE_KEY = 'permissions-jsw-cache-key';
93
+ static CONFLUENCE_CACHE_KEY = 'permissions-confluence-cache-key';
94
+ static BITBUCKET_CACHE_KEY = 'permissions-bitbucket-cache-key';
95
+ jira;
96
+ confluence;
97
+ bitbucket;
98
+ cache;
76
99
  constructor(environment, manifest, logger) {
77
100
  super(environment, logger);
78
101
  this.manifest = manifest;
@@ -110,7 +133,11 @@ class PermissionLinter extends base_linter_1.default {
110
133
  ];
111
134
  }
112
135
  const [jiraSwagger, jsmSwagger, jswSwagger, confluenceSwagger, bitbucketSwagger] = await Promise.all(swaggerFiles);
113
- this.jira = this.processPaths(Object.assign(Object.assign(Object.assign({}, jiraSwagger.paths), jsmSwagger.paths), jswSwagger.paths));
136
+ this.jira = this.processPaths({
137
+ ...jiraSwagger.paths,
138
+ ...jsmSwagger.paths,
139
+ ...jswSwagger.paths
140
+ });
114
141
  this.confluence = this.processPaths(confluenceSwagger.paths);
115
142
  this.bitbucket = this.processPaths(bitbucketSwagger.paths);
116
143
  this.nodeVisitors = [
@@ -174,12 +201,11 @@ class PermissionLinter extends base_linter_1.default {
174
201
  }
175
202
  }
176
203
  async getProductPaths(cacheKey, url) {
177
- var _a, _b;
178
- const cached = (_a = this.cache) === null || _a === void 0 ? void 0 : _a.get(cacheKey);
204
+ const cached = this.cache?.get(cacheKey);
179
205
  if (!cached) {
180
206
  const response = await (0, node_fetch_1.default)(url);
181
207
  const jsonBody = await response.json();
182
- void ((_b = this.cache) === null || _b === void 0 ? void 0 : _b.set(cacheKey, jsonBody, 12 * ONE_HOUR_MS));
208
+ void this.cache?.set(cacheKey, jsonBody, 12 * ONE_HOUR_MS);
183
209
  return jsonBody;
184
210
  }
185
211
  return cached;
@@ -198,8 +224,3 @@ class PermissionLinter extends base_linter_1.default {
198
224
  }
199
225
  }
200
226
  exports.PermissionLinter = PermissionLinter;
201
- PermissionLinter.JIRA_CACHE_KEY = 'permissions-jira-cache-key';
202
- PermissionLinter.JSM_CACHE_KEY = 'permissions-jsm-cache-key';
203
- PermissionLinter.JSW_CACHE_KEY = 'permissions-jsw-cache-key';
204
- PermissionLinter.CONFLUENCE_CACHE_KEY = 'permissions-confluence-cache-key';
205
- PermissionLinter.BITBUCKET_CACHE_KEY = 'permissions-bitbucket-cache-key';
@@ -88,8 +88,7 @@ class ContentPropertyVerifier extends verifier_interface_1.BaseLintIssueVerifier
88
88
  return lintErrors;
89
89
  }
90
90
  getMissingScopes({ context, method }) {
91
- var _a, _b;
92
- const existingScopes = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.scopes;
91
+ const existingScopes = this.manifest?.permissions?.scopes;
93
92
  return (0, manifest_1.getMissingScopes)(existingScopes, exports.CONTENT_PROPERTY_PERMISSIONS_MAP[context][method]);
94
93
  }
95
94
  }
@@ -7,14 +7,14 @@ const verifier_interface_1 = require("../../verifier-interface");
7
7
  const text_1 = require("../../../text");
8
8
  const utils_1 = require("../../utils");
9
9
  class ExternalFetchVerifier extends verifier_interface_1.BaseLintIssueVerifier {
10
+ egressFilteringService;
10
11
  constructor(environment, manifest) {
11
- var _a, _b, _c, _d, _e, _f, _g;
12
12
  super(environment, manifest);
13
- const allowList = (_e = (_d = (_c = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.external) === null || _c === void 0 ? void 0 : _c.fetch) === null || _d === void 0 ? void 0 : _d.backend) !== null && _e !== void 0 ? _e : [];
14
- const remoteList = (_g = (_f = this.manifest) === null || _f === void 0 ? void 0 : _f.remotes) !== null && _g !== void 0 ? _g : [];
13
+ const allowList = this.manifest?.permissions?.external?.fetch?.backend ?? [];
14
+ const remoteList = this.manifest?.remotes ?? [];
15
15
  const collectedUrls = allowList.filter((item) => typeof item === 'string');
16
16
  const collectedRemotes = allowList
17
- .map((item) => { var _a; return typeof item !== 'string' && ((_a = remoteList.find((remoteItem) => remoteItem.key === item.remote)) === null || _a === void 0 ? void 0 : _a.baseUrl); })
17
+ .map((item) => typeof item !== 'string' && remoteList.find((remoteItem) => remoteItem.key === item.remote)?.baseUrl)
18
18
  .filter((x) => typeof x === 'string');
19
19
  this.egressFilteringService = new egress_1.EgressFilteringService(collectedUrls.concat(collectedRemotes));
20
20
  }
@@ -7,10 +7,10 @@ const verifier_interface_1 = require("../../verifier-interface");
7
7
  const text_1 = require("../../../text");
8
8
  const utils_1 = require("../../utils");
9
9
  class ImageUrlVerifier extends verifier_interface_1.BaseLintIssueVerifier {
10
+ egressFilteringService;
10
11
  constructor(environment, manifest) {
11
- var _a, _b, _c, _d;
12
12
  super(environment, manifest);
13
- const allowList = (_d = (_c = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.external) === null || _c === void 0 ? void 0 : _c.images) !== null && _d !== void 0 ? _d : [];
13
+ const allowList = this.manifest?.permissions?.external?.images ?? [];
14
14
  const collectedUrls = allowList.filter((item) => typeof item === 'string');
15
15
  this.egressFilteringService = new egress_1.EgressFilteringService(collectedUrls);
16
16
  }
@@ -9,6 +9,8 @@ const manifest_1 = require("@forge/manifest");
9
9
  const text_1 = require("../../../text");
10
10
  const array_prototype_flatmap_1 = tslib_1.__importDefault(require("array.prototype.flatmap"));
11
11
  class ProductVerifier extends verifier_interface_1.BaseLintIssueVerifier {
12
+ pathMap;
13
+ product;
12
14
  constructor(environment, manifest, pathMap, product) {
13
15
  super(environment, manifest);
14
16
  this.pathMap = pathMap;
@@ -18,7 +20,6 @@ class ProductVerifier extends verifier_interface_1.BaseLintIssueVerifier {
18
20
  return linter_interface_1.LintClass.Error;
19
21
  }
20
22
  async process(apiCalls) {
21
- var _a;
22
23
  const rules = [];
23
24
  const lintCriteriaMatches = new Set();
24
25
  for (const apiCall of apiCalls) {
@@ -28,14 +29,14 @@ class ProductVerifier extends verifier_interface_1.BaseLintIssueVerifier {
28
29
  }
29
30
  }
30
31
  for (const apiCall of lintCriteriaMatches) {
31
- if (!(apiCall === null || apiCall === void 0 ? void 0 : apiCall.regex)) {
32
+ if (!apiCall?.regex) {
32
33
  continue;
33
34
  }
34
35
  const missingScopes = await this.getMissingPermissionScopes(apiCall);
35
36
  for (const permission of missingScopes) {
36
37
  rules.push({
37
38
  class: this.getLintClass(),
38
- message: text_1.messages.verifiers.product.message((0, cli_shared_1.capitalise)(this.product), apiCall.method.toUpperCase(), (_a = this.pathMap.get(apiCall.regex)) === null || _a === void 0 ? void 0 : _a.originalPath, permission),
39
+ message: text_1.messages.verifiers.product.message((0, cli_shared_1.capitalise)(this.product), apiCall.method.toUpperCase(), this.pathMap.get(apiCall.regex)?.originalPath, permission),
39
40
  reference: text_1.messages.verifiers.product.reference,
40
41
  line: apiCall.line,
41
42
  column: apiCall.column,
@@ -51,34 +52,36 @@ class ProductVerifier extends verifier_interface_1.BaseLintIssueVerifier {
51
52
  const pathWithoutQuery = apiCall.path.replace(/\?.+$/, '');
52
53
  for (const regex of this.pathMap.keys()) {
53
54
  if (regex.test(pathWithoutQuery)) {
54
- return Object.assign(Object.assign({}, apiCall), { regex, path: pathWithoutQuery, method: apiCall.method.toLowerCase() });
55
+ return {
56
+ ...apiCall,
57
+ regex,
58
+ path: pathWithoutQuery,
59
+ method: apiCall.method.toLowerCase()
60
+ };
55
61
  }
56
62
  }
57
63
  }
58
64
  getMissingPermissionScopes(apiCall) {
59
- var _a, _b;
60
65
  const current = this.getRequiredScopes(apiCall);
61
66
  const beta = this.getBetaScopes(apiCall);
62
- return (0, manifest_1.getMissingScopes)((_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.scopes, { current, beta });
67
+ return (0, manifest_1.getMissingScopes)(this.manifest?.permissions?.scopes, { current, beta });
63
68
  }
64
69
  getRequiredScopes({ regex, method }) {
65
- var _a, _b, _c, _d;
66
70
  if (!regex)
67
71
  return [];
68
- const oAuth2Scopes = (_b = (_a = this.pathMap.get(regex)) === null || _a === void 0 ? void 0 : _a.methods[method]) === null || _b === void 0 ? void 0 : _b['x-atlassian-oauth2-scopes'];
72
+ const oAuth2Scopes = this.pathMap.get(regex)?.methods[method]?.['x-atlassian-oauth2-scopes'];
69
73
  if (oAuth2Scopes) {
70
74
  return (0, array_prototype_flatmap_1.default)(oAuth2Scopes.filter((scope) => scope.state === 'Current').map((scope) => scope.scopes), (x) => x);
71
75
  }
72
- const swaggerEntries = (_d = (_c = this.pathMap.get(regex)) === null || _c === void 0 ? void 0 : _c.methods[method]) === null || _d === void 0 ? void 0 : _d.security;
76
+ const swaggerEntries = this.pathMap.get(regex)?.methods[method]?.security;
73
77
  if (!swaggerEntries)
74
78
  return [];
75
- return swaggerEntries === null || swaggerEntries === void 0 ? void 0 : swaggerEntries.reduce((prev, curr) => [...prev, ...(curr['OAuth2'] || []), ...(curr['oAuthDefinitions'] || [])], []);
79
+ return swaggerEntries?.reduce((prev, curr) => [...prev, ...(curr['OAuth2'] || []), ...(curr['oAuthDefinitions'] || [])], []);
76
80
  }
77
81
  getBetaScopes({ regex, method }) {
78
- var _a, _b;
79
82
  if (!regex)
80
83
  return [];
81
- const oAuth2Scopes = (_b = (_a = this.pathMap.get(regex)) === null || _a === void 0 ? void 0 : _a.methods[method]) === null || _b === void 0 ? void 0 : _b['x-atlassian-oauth2-scopes'];
84
+ const oAuth2Scopes = this.pathMap.get(regex)?.methods[method]?.['x-atlassian-oauth2-scopes'];
82
85
  if (!oAuth2Scopes)
83
86
  return [];
84
87
  return (0, array_prototype_flatmap_1.default)(oAuth2Scopes.filter((scope) => scope.state === 'Beta').map((scope) => scope.scopes), (x) => x);
@@ -10,13 +10,18 @@ class StorageAPIVerifier extends verifier_interface_1.BaseLintIssueVerifier {
10
10
  return linter_interface_1.LintClass.Error;
11
11
  }
12
12
  async process(apiCalls) {
13
- var _a, _b;
14
- if ((_b = (_a = this.manifest.permissions) === null || _a === void 0 ? void 0 : _a.scopes) === null || _b === void 0 ? void 0 : _b.includes(STORAGE_PERMISSION)) {
13
+ if (this.manifest.permissions?.scopes?.includes(STORAGE_PERMISSION)) {
15
14
  return [];
16
15
  }
17
- return apiCalls.map((apiCall) => (Object.assign(Object.assign({ class: this.getLintClass(), message: text_1.messages.verifiers.storage.message(STORAGE_PERMISSION), reference: text_1.messages.verifiers.storage.reference }, apiCall), { metadata: {
16
+ return apiCalls.map((apiCall) => ({
17
+ class: this.getLintClass(),
18
+ message: text_1.messages.verifiers.storage.message(STORAGE_PERMISSION),
19
+ reference: text_1.messages.verifiers.storage.reference,
20
+ ...apiCall,
21
+ metadata: {
18
22
  missingPermission: STORAGE_PERMISSION
19
- } })));
23
+ }
24
+ }));
20
25
  }
21
26
  }
22
27
  exports.StorageAPIVerifier = StorageAPIVerifier;
@@ -24,13 +24,12 @@ class UIHookVerifier extends verifier_interface_1.BaseLintIssueVerifier {
24
24
  return linter_interface_1.LintClass.Error;
25
25
  }
26
26
  async process(apiCalls) {
27
- var _a;
28
27
  const rules = [];
29
28
  for (const apiCall of apiCalls) {
30
29
  const requiredPermissions = FORGE_UI_HOOK_PERMISSIONS[apiCall.hookName];
31
30
  if (!requiredPermissions)
32
31
  return rules;
33
- const missingPermissions = await (0, manifest_1.getMissingScopes)((_a = this.manifest.permissions) === null || _a === void 0 ? void 0 : _a.scopes, requiredPermissions);
32
+ const missingPermissions = await (0, manifest_1.getMissingScopes)(this.manifest.permissions?.scopes, requiredPermissions);
34
33
  missingPermissions.forEach((perm) => rules.push(this.getHookRule(apiCall, perm)));
35
34
  }
36
35
  return rules;
@@ -5,20 +5,12 @@ const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
5
  const url_1 = require("url");
6
6
  const api_call_interface_1 = require("../api-call-interface");
7
7
  class ExternalApiCallVisitor {
8
- constructor() {
9
- this.transformArgsToFetchCall = (endpointNode) => ({
10
- type: api_call_interface_1.ApiCallTypes.EXTERNAL,
11
- url: endpointNode.value,
12
- line: endpointNode.loc.start.line,
13
- column: endpointNode.loc.start.column
14
- });
15
- }
16
8
  visit(node, parent, callback) {
17
9
  switch (node.type) {
18
10
  case typescript_estree_1.AST_NODE_TYPES.CallExpression:
19
11
  if (node.callee.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node.callee.name === 'fetch') {
20
12
  const [endpointNode] = node.arguments;
21
- if ((endpointNode === null || endpointNode === void 0 ? void 0 : endpointNode.type) === typescript_estree_1.AST_NODE_TYPES.Literal && typeof (endpointNode === null || endpointNode === void 0 ? void 0 : endpointNode.value) === 'string') {
13
+ if (endpointNode?.type === typescript_estree_1.AST_NODE_TYPES.Literal && typeof endpointNode?.value === 'string') {
22
14
  if (endpointNode.value.trim() !== '') {
23
15
  const fetchCall = this.transformArgsToFetchCall(endpointNode);
24
16
  callback(fetchCall);
@@ -29,7 +21,7 @@ class ExternalApiCallVisitor {
29
21
  case typescript_estree_1.AST_NODE_TYPES.MemberExpression:
30
22
  if (node.property.type === typescript_estree_1.AST_NODE_TYPES.Identifier &&
31
23
  node.property.name === 'fetch' &&
32
- (parent === null || parent === void 0 ? void 0 : parent.type) === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
24
+ parent?.type === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
33
25
  const [endpointNode] = parent.arguments;
34
26
  if (this.endpointCanBeChecked(endpointNode)) {
35
27
  const fetchCall = this.transformArgsToFetchCall(endpointNode);
@@ -45,15 +37,21 @@ class ExternalApiCallVisitor {
45
37
  thunk();
46
38
  return false;
47
39
  }
48
- catch (_a) {
40
+ catch {
49
41
  return true;
50
42
  }
51
43
  };
52
44
  const isPathOnlyUrl = (s) => throws(() => new url_1.URL(s)) && !throws(() => new url_1.URL(s, 'http://example'));
53
- return ((endpointNode === null || endpointNode === void 0 ? void 0 : endpointNode.type) === typescript_estree_1.AST_NODE_TYPES.Literal &&
54
- typeof (endpointNode === null || endpointNode === void 0 ? void 0 : endpointNode.value) === 'string' &&
45
+ return (endpointNode?.type === typescript_estree_1.AST_NODE_TYPES.Literal &&
46
+ typeof endpointNode?.value === 'string' &&
55
47
  endpointNode.value.trim() !== '' &&
56
48
  !isPathOnlyUrl(endpointNode.value));
57
49
  }
50
+ transformArgsToFetchCall = (endpointNode) => ({
51
+ type: api_call_interface_1.ApiCallTypes.EXTERNAL,
52
+ url: endpointNode.value,
53
+ line: endpointNode.loc.start.line,
54
+ column: endpointNode.loc.start.column
55
+ });
58
56
  }
59
57
  exports.ExternalApiCallVisitor = ExternalApiCallVisitor;
@@ -4,12 +4,13 @@ exports.ImageUrlVisitor = void 0;
4
4
  const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
5
  const api_call_interface_1 = require("../api-call-interface");
6
6
  class ImageUrlVisitor {
7
+ static ABSOLUTE_URL_REGEX = /^(?:[a-z+]+:)?\/\//i;
7
8
  visit(node, _parent, callback) {
8
9
  const imageUrlNode = this.getImageUrlNode(node);
9
10
  if (!imageUrlNode) {
10
11
  return undefined;
11
12
  }
12
- if ((imageUrlNode === null || imageUrlNode === void 0 ? void 0 : imageUrlNode.type) === typescript_estree_1.AST_NODE_TYPES.JSXAttribute) {
13
+ if (imageUrlNode?.type === typescript_estree_1.AST_NODE_TYPES.JSXAttribute) {
13
14
  const imageUrlAttribute = imageUrlNode.value;
14
15
  if (imageUrlAttribute &&
15
16
  imageUrlAttribute.type === typescript_estree_1.AST_NODE_TYPES.Literal &&
@@ -54,4 +55,3 @@ class ImageUrlVisitor {
54
55
  }
55
56
  }
56
57
  exports.ImageUrlVisitor = ImageUrlVisitor;
57
- ImageUrlVisitor.ABSOLUTE_URL_REGEX = /^(?:[a-z+]+:)?\/\//i;
@@ -17,7 +17,7 @@ class ProductNodeVisitor {
17
17
  case typescript_estree_1.AST_NODE_TYPES.MemberExpression:
18
18
  if (node.property.type === typescript_estree_1.AST_NODE_TYPES.Identifier &&
19
19
  node.property.name.match(REQUEST_PRODUCT_REGEX) &&
20
- (parent === null || parent === void 0 ? void 0 : parent.type) === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
20
+ parent?.type === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
21
21
  const apiCallProblem = this.checkProductApiCallArgs(node.property.name, parent.arguments);
22
22
  apiCallProblem && callback(apiCallProblem);
23
23
  }
@@ -78,10 +78,10 @@ class ProductNodeVisitor {
78
78
  if (!endpointString) {
79
79
  return;
80
80
  }
81
- const methodProperty = optionsNode === null || optionsNode === void 0 ? void 0 : optionsNode.properties.find((property) => property.type === typescript_estree_1.AST_NODE_TYPES.Property &&
81
+ const methodProperty = optionsNode?.properties.find((property) => property.type === typescript_estree_1.AST_NODE_TYPES.Property &&
82
82
  property.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier &&
83
83
  property.key.name === 'method');
84
- const methodValue = (methodProperty === null || methodProperty === void 0 ? void 0 : methodProperty.value.type) === typescript_estree_1.AST_NODE_TYPES.Literal && typeof methodProperty.value.value === 'string'
84
+ const methodValue = methodProperty?.value.type === typescript_estree_1.AST_NODE_TYPES.Literal && typeof methodProperty.value.value === 'string'
85
85
  ? methodProperty.value.value
86
86
  : 'GET';
87
87
  return {
@@ -9,7 +9,10 @@ class StorageAPINodeVisitor {
9
9
  node.specifiers.forEach((specifier) => {
10
10
  if (specifier.type === 'ImportSpecifier' && specifier.local.type === 'Identifier') {
11
11
  if (specifier.loc && specifier.local.name === 'storage') {
12
- const storageApiCall = Object.assign({ type: api_call_interface_1.ApiCallTypes.STORAGE }, specifier.loc.start);
12
+ const storageApiCall = {
13
+ type: api_call_interface_1.ApiCallTypes.STORAGE,
14
+ ...specifier.loc.start
15
+ };
13
16
  callback(storageApiCall);
14
17
  }
15
18
  }
@@ -8,7 +8,11 @@ class UIHookNodeVisitor {
8
8
  if (node.type === typescript_estree_1.AST_NODE_TYPES.ImportDeclaration) {
9
9
  node.specifiers.forEach((specifier) => {
10
10
  if (specifier.loc && specifier.local.name.match(/^use(Space|Content|Issue)Property/)) {
11
- const hookApiCall = Object.assign({ type: api_call_interface_1.ApiCallTypes.HOOK, hookName: specifier.local.name }, specifier.loc.start);
11
+ const hookApiCall = {
12
+ type: api_call_interface_1.ApiCallTypes.HOOK,
13
+ hookName: specifier.local.name,
14
+ ...specifier.loc.start
15
+ };
12
16
  callback(hookApiCall);
13
17
  }
14
18
  });
@@ -7,6 +7,7 @@ const invoke_remote_interface_1 = require("./invoke-remote-interface");
7
7
  const invoke_remote_verifier_1 = require("./verifiers/invoke-remote-verifier");
8
8
  const invoke_remote_call_visitor_1 = require("./visitors/invoke-remote-call-visitor");
9
9
  class InvokeRemoteLinter extends base_linter_1.default {
10
+ manifest;
10
11
  constructor(environment, manifest, logger) {
11
12
  super(environment, logger);
12
13
  this.manifest = manifest;
@@ -4,13 +4,6 @@ exports.InvokeRemoteCallVisitor = void 0;
4
4
  const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
5
  const invoke_remote_interface_1 = require("../invoke-remote-interface");
6
6
  class InvokeRemoteCallVisitor {
7
- constructor() {
8
- this.transformArgsToInvokeRemoteCall = (remoteKeyNode) => ({
9
- remoteKey: remoteKeyNode.value,
10
- line: remoteKeyNode.loc.start.line,
11
- column: remoteKeyNode.loc.start.column
12
- });
13
- }
14
7
  visit(node, parent, callback) {
15
8
  switch (node.type) {
16
9
  case typescript_estree_1.AST_NODE_TYPES.ImportDeclaration:
@@ -38,7 +31,11 @@ class InvokeRemoteCallVisitor {
38
31
  if (node.callee.type === typescript_estree_1.AST_NODE_TYPES.Identifier) {
39
32
  const [remoteKeyNode] = node.arguments;
40
33
  if (this.remoteKeyCanBeChecked(remoteKeyNode)) {
41
- const invokeRemoteCall = Object.assign(Object.assign({}, this.transformArgsToInvokeRemoteCall(remoteKeyNode)), { type: invoke_remote_interface_1.InvokeRemoteTypes.DIRECT_CALL, calleeName: node.callee.name });
34
+ const invokeRemoteCall = {
35
+ ...this.transformArgsToInvokeRemoteCall(remoteKeyNode),
36
+ type: invoke_remote_interface_1.InvokeRemoteTypes.DIRECT_CALL,
37
+ calleeName: node.callee.name
38
+ };
42
39
  callback(invokeRemoteCall);
43
40
  }
44
41
  }
@@ -47,10 +44,14 @@ class InvokeRemoteCallVisitor {
47
44
  if (node.property.type === typescript_estree_1.AST_NODE_TYPES.Identifier &&
48
45
  node.object.type === typescript_estree_1.AST_NODE_TYPES.Identifier &&
49
46
  node.property.name === invoke_remote_interface_1.INVOKE_REMOTE_FUNCTION_NAME &&
50
- (parent === null || parent === void 0 ? void 0 : parent.type) === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
47
+ parent?.type === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
51
48
  const [remoteKeyNode] = parent.arguments;
52
49
  if (this.remoteKeyCanBeChecked(remoteKeyNode)) {
53
- const invokeRemoteMemberCall = Object.assign(Object.assign({}, this.transformArgsToInvokeRemoteCall(remoteKeyNode)), { type: invoke_remote_interface_1.InvokeRemoteTypes.MEMBER_CALL, objectName: node.object.name });
50
+ const invokeRemoteMemberCall = {
51
+ ...this.transformArgsToInvokeRemoteCall(remoteKeyNode),
52
+ type: invoke_remote_interface_1.InvokeRemoteTypes.MEMBER_CALL,
53
+ objectName: node.object.name
54
+ };
54
55
  callback(invokeRemoteMemberCall);
55
56
  }
56
57
  }
@@ -58,9 +59,14 @@ class InvokeRemoteCallVisitor {
58
59
  }
59
60
  }
60
61
  remoteKeyCanBeChecked(remoteKeyNode) {
61
- return ((remoteKeyNode === null || remoteKeyNode === void 0 ? void 0 : remoteKeyNode.type) === typescript_estree_1.AST_NODE_TYPES.Literal &&
62
- typeof (remoteKeyNode === null || remoteKeyNode === void 0 ? void 0 : remoteKeyNode.value) === 'string' &&
62
+ return (remoteKeyNode?.type === typescript_estree_1.AST_NODE_TYPES.Literal &&
63
+ typeof remoteKeyNode?.value === 'string' &&
63
64
  remoteKeyNode.value.trim() !== '');
64
65
  }
66
+ transformArgsToInvokeRemoteCall = (remoteKeyNode) => ({
67
+ remoteKey: remoteKeyNode.value,
68
+ line: remoteKeyNode.loc.start.line,
69
+ column: remoteKeyNode.loc.start.column
70
+ });
65
71
  }
66
72
  exports.InvokeRemoteCallVisitor = InvokeRemoteCallVisitor;
@@ -4,6 +4,8 @@ exports.BaseLintIssueVerifier = void 0;
4
4
  const linter_interface_1 = require("../linter-interface");
5
5
  const cli_shared_1 = require("@forge/cli-shared");
6
6
  class BaseLintIssueVerifier {
7
+ environment;
8
+ manifest;
7
9
  constructor(environment, manifest) {
8
10
  this.environment = environment;
9
11
  this.manifest = manifest;
@@ -10,12 +10,20 @@ const createParseOptions = (absoluteFilePath, fileSystemReader) => {
10
10
  const tsconfigOptions = fileSystemReader.fileExists(TSCONFIG_PATH)
11
11
  ? { tsconfigRootDir: process.cwd(), project: TSCONFIG_PATH }
12
12
  : {};
13
- return Object.assign({ errorOnTypeScriptSyntacticAndSemanticIssues: true, loc: true, filePath: absoluteFilePath }, tsconfigOptions);
13
+ return {
14
+ errorOnTypeScriptSyntacticAndSemanticIssues: true,
15
+ loc: true,
16
+ filePath: absoluteFilePath,
17
+ ...tsconfigOptions
18
+ };
14
19
  };
15
20
  exports.createParseOptions = createParseOptions;
16
21
  const tsParser = async (code, filepath, parseOptions) => {
17
22
  const absoluteFilePath = path_1.default.resolve(process.cwd(), filepath);
18
- const parseResult = (0, typescript_estree_1.parseAndGenerateServices)(code, Object.assign(Object.assign({}, (0, exports.createParseOptions)(absoluteFilePath, new cli_shared_1.FileSystemReader())), parseOptions));
23
+ const parseResult = (0, typescript_estree_1.parseAndGenerateServices)(code, {
24
+ ...(0, exports.createParseOptions)(absoluteFilePath, new cli_shared_1.FileSystemReader()),
25
+ ...parseOptions
26
+ });
19
27
  return {
20
28
  parsed: parseResult.ast,
21
29
  traverse: (options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/lint",
3
- "version": "5.1.1-next.5",
3
+ "version": "5.1.1-next.6",
4
4
  "description": "Linting for forge apps",
5
5
  "main": "out/index.js",
6
6
  "license": "UNLICENSED",
@@ -18,9 +18,9 @@
18
18
  "eslint-plugin-import": "^2.29.1"
19
19
  },
20
20
  "dependencies": {
21
- "@forge/cli-shared": "5.0.0-next.5",
21
+ "@forge/cli-shared": "5.0.0-next.6",
22
22
  "@forge/egress": "1.2.13",
23
- "@forge/manifest": "7.3.0-next.4",
23
+ "@forge/manifest": "7.3.0-next.5",
24
24
  "@typescript-eslint/typescript-estree": "^5.62.0",
25
25
  "array.prototype.flatmap": "^1.3.2",
26
26
  "atlassian-openapi": "^1.0.18",