@forge/lint

6.0.2-next.3-experimental-bd3d8126.0.2-next.3-experimental-c6a3916
~

Modified (8 files)

Index: package/out/lint/lint.js
===================================================================
--- package/out/lint/lint.js
+++ package/out/lint/lint.js
@@ -22,24 +22,29 @@
 const llm_module_linter_1 = require("./linters/llm-module-linter/llm-module-linter");
 const deprecated_api_module_linter_1 = require("./linters/deprecated-api-module-linter/deprecated-api-module-linter");
 const app_managed_permissions_sdk_linter_1 = require("./linters/app-managed-permissions-sdk-linter/app-managed-permissions-sdk-linter");
 const function_timeout_linter_1 = require("./linters/function-timeout-linter/function-timeout-linter");
+const server_side_linter_1 = require("./linters/server-side-linter/server-side-linter");
 const reportLintResults = (logger, lintResults, showSummary = true) => {
-    let numErrors = 0, numWarnings = 0;
+    let numErrors = 0, numWarnings = 0, numApprovals = 0;
     let noProblemsFound = true;
     if (lintResults.length) {
         lintResults.forEach((lintResult) => {
             if (lintResult.size()) {
                 noProblemsFound = false;
                 numErrors += lintResult.errors.length;
                 numWarnings += lintResult.warnings.length;
+                numApprovals += lintResult.approvals.length;
                 logger.info(cli_shared_1.Text.lint.filename(path_1.default.resolve(lintResult.file)));
                 lintResult.errors.forEach(({ line, column, message, reference }) => {
                     logger.info(cli_shared_1.Text.lint.error(line, column, message, reference));
                 });
                 lintResult.warnings.forEach(({ line, column, message, reference }) => {
                     logger.info(cli_shared_1.Text.lint.warning(line, column, message, reference));
                 });
+                lintResult.approvals.forEach(({ line, column, message, reference }) => {
+                    logger.info(cli_shared_1.Text.lint.approval(line, column, message, reference));
+                });
             }
         });
     }
     if (noProblemsFound) {
@@ -50,30 +55,34 @@
         const resultsWithFixers = lintResults.filter((result) => result.hasFixer());
         const numFixableErrors = resultsWithFixers.reduce((count, result) => count + result.errors.length, 0);
         const numFixableWarnings = resultsWithFixers.reduce((count, result) => count + result.warnings.length, 0);
         if (showSummary) {
-            logger.info(cli_shared_1.Text.lint.summary(numErrors, numWarnings, numFixableErrors, numFixableWarnings));
+            logger.info(cli_shared_1.Text.lint.summary(numErrors, numWarnings, numApprovals, numFixableErrors, numFixableWarnings));
             if (numFixableErrors + numFixableWarnings > 0) {
                 logger.info(cli_shared_1.Text.lint.fixSummary(numErrors, numFixableErrors, numFixableWarnings));
             }
             else if (numErrors + numWarnings === 1) {
                 logger.info(cli_shared_1.Text.lint.noFixableProblem);
             }
+            else if (numApprovals > 0) {
+                logger.info(cli_shared_1.Text.lint.noFixableProblem);
+            }
             else {
                 logger.info(cli_shared_1.Text.lint.noFixableProblems);
             }
         }
-        if (numErrors) {
+        if (numErrors || numApprovals) {
             process.exitCode = 1;
         }
     }
 };
 exports.reportLintResults = reportLintResults;
 const problemCount = (lintResults) => {
     return lintResults.reduce((prev, curr) => ({
         errors: prev.errors + curr.errors.length,
-        warnings: prev.warnings + curr.warnings.length
-    }), { errors: 0, warnings: 0 });
+        warnings: prev.warnings + curr.warnings.length,
+        approvals: prev.approvals + curr.approvals.length
+    }), { errors: 0, warnings: 0, approvals: 0 });
 };
 exports.problemCount = problemCount;
 const parseSourceFile = async (filepath, parser, readFilePromise = (0, util_1.promisify)(fs_1.default.readFile)) => {
     const code = await readFilePromise(filepath, { encoding: 'utf-8' });
@@ -83,10 +92,11 @@
         filepath
     };
 };
 exports.parseSourceFile = parseSourceFile;
-const lint = async (filesToLint, manifest, environment, logger, statsigService, parseFunction = exports.parseSourceFile, linters = [
+const getDefaultLinters = async (manifest, environment, logger, statsigService, graphqlClient, approveRule) => [
     new permission_linter_1.PermissionLinter(environment, manifest, logger),
+    await server_side_linter_1.ServerSideLinter.instance(environment, manifest, graphqlClient, logger, approveRule),
     new permissions_manifest_linter_1.PermissionsManifestLinter(logger, statsigService),
     new agent_product_context_permissions_manifest_linter_1.AgentProductContextPermissionsManifestLinter(logger, statsigService),
     new deprecated_csp_permissions_manifest_linter_1.DeprecatedCspPermissionsManifestLinter(logger, statsigService),
     new full_manifest_linter_1.FullManifestLinter(logger, statsigService),
@@ -99,9 +109,13 @@
     new deprecated_api_module_linter_1.DeprecatedApiModuleLinter(environment, manifest, logger),
     new deprecated_egress_permissions_manifest_linter_1.DeprecatedEgressPermissionsManifestLinter(logger, statsigService),
     new app_managed_permissions_sdk_linter_1.AppManagedPermissionsSdkLinter(manifest, logger),
     new function_timeout_linter_1.FunctionTimeoutLinter(manifest, logger)
-]) => {
+];
+const lint = async (filesToLint, manifest, environment, logger, statsigService, graphqlClient, approveRule, parseFunction = exports.parseSourceFile, lintersOverride = []) => {
+    const linters = lintersOverride.length > 0
+        ? lintersOverride
+        : await getDefaultLinters(manifest, environment, logger, statsigService, graphqlClient, approveRule);
     const { include, exclude } = await (0, cli_shared_1.listTSConfigIncludeExclude)(new cli_shared_1.FileSystemReader());
     const tsInclude = new Set(include);
     const tsExclude = new Set(exclude);
     try {
@@ -125,8 +139,9 @@
         return results.map((result) => {
             const comparator = (a, b) => a.line === b.line ? a.column - b.column : a.line - b.line;
             result.errors = result.errors.sort(comparator);
             result.warnings = result.warnings.sort(comparator);
+            result.approvals = result.approvals.sort(comparator);
             return result;
         });
     }
     catch (e) {
Index: package/out/lint/linter-interface.js
===================================================================
--- package/out/lint/linter-interface.js
+++ package/out/lint/linter-interface.js
@@ -4,14 +4,16 @@
 var LintClass;
 (function (LintClass) {
     LintClass["Error"] = "error";
     LintClass["Warning"] = "warning";
+    LintClass["Approval"] = "approval";
 })(LintClass || (exports.LintClass = LintClass = {}));
 class LintResult {
     file;
     fixer;
     errors = [];
     warnings = [];
+    approvals = [];
     constructor(file, fixer) {
         this.file = file;
         this.fixer = fixer;
     }
@@ -19,8 +21,11 @@
         switch (rule.class) {
             case LintClass.Error:
                 this.errors.push(rule);
                 break;
+            case LintClass.Approval:
+                this.approvals.push(rule);
+                break;
             default:
                 this.warnings.push(rule);
                 break;
         }
@@ -28,9 +33,9 @@
     batchAdd(...rules) {
         rules.forEach(this.add, this);
     }
     size() {
-        return this.errors.length + this.warnings.length;
+        return this.errors.length + this.warnings.length + this.approvals.length;
     }
     hasFixer() {
         return !!this.fixer;
     }
Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@forge/lint",
-  "version": "6.0.2-next.3-experimental-bd3d812",
+  "version": "6.0.2-next.3-experimental-c6a3916",
   "description": "Linting for forge apps",
   "main": "out/index.js",
   "license": "SEE LICENSE IN LICENSE.txt",
   "scripts": {
@@ -10,20 +10,20 @@
     "clean": "rm -rf ./out && rm -f tsconfig.tsbuildinfo"
   },
   "devDependencies": {
     "@atlassian/xen-test-util": "^4.2.0",
-    "@forge/api": "^8.0.2-next.0-experimental-bd3d812",
+    "@forge/api": "^8.0.2-next.0-experimental-c6a3916",
     "@types/array.prototype.flatmap": "^1.2.6",
     "@types/cross-spawn": "^6.0.6",
     "@types/eslint": "8.56.12",
     "@types/node-fetch": "^2.6.12",
     "eslint-plugin-import": "^2.29.1"
   },
   "dependencies": {
-    "@forge/cli-shared": "9.2.0-next.3-experimental-bd3d812",
-    "@forge/csp": "6.1.0-experimental-bd3d812",
+    "@forge/cli-shared": "9.2.0-next.3-experimental-c6a3916",
+    "@forge/csp": "6.1.0-experimental-c6a3916",
     "@forge/egress": "3.0.0",
-    "@forge/manifest": "13.1.1-next.2-experimental-bd3d812",
+    "@forge/manifest": "13.1.1-next.2-experimental-c6a3916",
     "@typescript-eslint/typescript-estree": "^5.62.0",
     "array.prototype.flatmap": "^1.3.3",
     "@atlassian/atlassian-openapi": "^1.0.6",
     "cross-spawn": "^7.0.6",
Index: package/out/lint/lint.d.ts.map
===================================================================
--- package/out/lint/lint.d.ts.map
+++ package/out/lint/lint.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/lint/lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AAkBxG,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,UAAU,EAAE,aAAa,UAAU,EAAE,EAAE,qBAAkB,KAAG,IA+CrG,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,aAAa,UAAU,EAAE,KAAG,YAQxD,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,EAChB,QAAQ,OAAO,QAAQ,EACvB,kBAAiB,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAsC,KACzE,OAAO,CAAC,SAAS,CAOnB,CAAC;AAEF,eAAO,MAAM,IAAI,GACf,aAAa,MAAM,EAAE,EACrB,UAAU,QAAQ,EAClB,aAAa,MAAM,EACnB,QAAQ,UAAU,EAClB,gBAAgB,cAAc,EAC9B,2BAlBU,MAAM,UACR,OAAO,QAAQ,oBACN,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAa,KAChD,OAAO,CAAC,SAAS,CAea,EAC/B,UAAS,eAAe,EAgBvB,KACA,OAAO,CAAC,UAAU,EAAE,CAyCtB,CAAC;AAwBF,eAAO,MAAM,QAAQ,GACnB,QAAQ,UAAU,EAClB,gBAAgB,cAAc,EAC9B,SAAQ,eAAiE,KACxE,OAAO,CAAC,UAAU,EAAE,CAGtB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/lint/lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,cAAc,EACd,aAAa,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AAmBxG,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,UAAU,EAAE,aAAa,UAAU,EAAE,EAAE,qBAAkB,KAAG,IAuDrG,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,aAAa,UAAU,EAAE,KAAG,YASxD,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,EAChB,QAAQ,OAAO,QAAQ,EACvB,kBAAiB,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAsC,KACzE,OAAO,CAAC,SAAS,CAOnB,CAAC;AA4BF,eAAO,MAAM,IAAI,GACf,aAAa,MAAM,EAAE,EACrB,UAAU,QAAQ,EAClB,aAAa,MAAM,EACnB,QAAQ,UAAU,EAClB,gBAAgB,cAAc,EAC9B,eAAe,aAAa,EAC5B,cAAc,MAAM,EAAE,EACtB,2BA9CU,MAAM,UACR,OAAO,QAAQ,oBACN,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAa,KAChD,OAAO,CAAC,SAAS,CA2Ca,EAC/B,kBAAiB,eAAe,EAAO,KACtC,OAAO,CAAC,UAAU,EAAE,CA+CtB,CAAC;AAwBF,eAAO,MAAM,QAAQ,GACnB,QAAQ,UAAU,EAClB,gBAAgB,cAAc,EAC9B,SAAQ,eAAiE,KACxE,OAAO,CAAC,UAAU,EAAE,CAGtB,CAAC"}
\ No newline at end of file
Index: package/out/lint/linter-interface.d.ts.map
===================================================================
--- package/out/lint/linter-interface.d.ts.map
+++ package/out/lint/linter-interface.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"linter-interface.d.ts","sourceRoot":"","sources":["../../src/lint/linter-interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEvD,oBAAY,SAAS;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG,CACtB,MAAM,EAAE,cAAc,EAAE,EACxB,QAAQ,EAAE,cAAc,EAAE,EAC1B,KAAK,EAAE,YAAY,KAChB,OAAO,CAAC,YAAY,CAAC,CAAC;AAE3B,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,qBAAa,UAAU;IAKZ,IAAI,EAAE,MAAM;IACnB,OAAO,CAAC,KAAK,CAAC;IALT,MAAM,EAAE,cAAc,EAAE,CAAM;IAC9B,QAAQ,EAAE,cAAc,EAAE,CAAM;gBAG9B,IAAI,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,SAAS,YAAA;IAGpB,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAW/B,QAAQ,CAAC,GAAG,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI;IAI1C,IAAI,IAAI,MAAM;IAId,QAAQ,IAAI,OAAO;IAIb,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAMlE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,cAAc,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,YAAY,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB"}
\ No newline at end of file
+{"version":3,"file":"linter-interface.d.ts","sourceRoot":"","sources":["../../src/lint/linter-interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEvD,oBAAY,SAAS;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG,CACtB,MAAM,EAAE,cAAc,EAAE,EACxB,QAAQ,EAAE,cAAc,EAAE,EAC1B,KAAK,EAAE,YAAY,KAChB,OAAO,CAAC,YAAY,CAAC,CAAC;AAE3B,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,qBAAa,UAAU;IAMZ,IAAI,EAAE,MAAM;IACnB,OAAO,CAAC,KAAK,CAAC;IANT,MAAM,EAAE,cAAc,EAAE,CAAM;IAC9B,QAAQ,EAAE,cAAc,EAAE,CAAM;IAChC,SAAS,EAAE,cAAc,EAAE,CAAM;gBAG/B,IAAI,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,SAAS,YAAA;IAGpB,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAc/B,QAAQ,CAAC,GAAG,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI;IAI1C,IAAI,IAAI,MAAM;IAId,QAAQ,IAAI,OAAO;IAIb,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAMlE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,cAAc,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,YAAY,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB"}
\ No newline at end of file
File too large for inline diff
Index: package/out/lint/lint.d.ts
===================================================================
--- package/out/lint/lint.d.ts
+++ package/out/lint/lint.d.ts
@@ -1,15 +1,16 @@
-import { StatsigService } from '@forge/cli-shared';
+import { StatsigService, GraphQLClient } from '@forge/cli-shared';
 import { ManifestSchema as Manifest } from '@forge/manifest';
 import fs from 'fs';
 import { tsParser } from '../parse';
 import { LinterInterface, LintInput, LintLogger, LintResult } from './linter-interface';
 export interface ProblemCount {
     errors: number;
     warnings: number;
+    approvals: number;
 }
 export declare const reportLintResults: (logger: LintLogger, lintResults: LintResult[], showSummary?: boolean) => void;
 export declare const problemCount: (lintResults: LintResult[]) => ProblemCount;
 export declare const parseSourceFile: (filepath: string, parser: typeof tsParser, readFilePromise?: typeof fs.readFile.__promisify__) => Promise<LintInput>;
-export declare const lint: (filesToLint: string[], manifest: Manifest, environment: string, logger: LintLogger, statsigService: StatsigService, parseFunction?: (filepath: string, parser: typeof tsParser, readFilePromise?: typeof fs.readFile.__promisify__) => Promise<LintInput>, linters?: LinterInterface[]) => Promise<LintResult[]>;
+export declare const lint: (filesToLint: string[], manifest: Manifest, environment: string, logger: LintLogger, statsigService: StatsigService, graphqlClient: GraphQLClient, approveRule?: string[], parseFunction?: (filepath: string, parser: typeof tsParser, readFilePromise?: typeof fs.readFile.__promisify__) => Promise<LintInput>, lintersOverride?: LinterInterface[]) => Promise<LintResult[]>;
 export declare const litelint: (logger: LintLogger, statsigService: StatsigService, linter?: LinterInterface) => Promise<LintResult[]>;
 //# sourceMappingURL=lint.d.ts.map
\ No newline at end of file
Index: package/out/lint/linter-interface.d.ts
===================================================================
--- package/out/lint/linter-interface.d.ts
+++ package/out/lint/linter-interface.d.ts
@@ -1,9 +1,10 @@
 import { ASTParseResult } from '../parse';
 import { ConfigFile, Logger } from '@forge/cli-shared';
 export declare enum LintClass {
     Error = "error",
-    Warning = "warning"
+    Warning = "warning",
+    Approval = "approval"
 }
 export type LintLogger = Pick<Logger, 'info'>;
 export type LintFixer = (errors: LintResultRule[], warnings: LintResultRule[], state: LintFixState) => Promise<LintFixState>;
 export interface LintFixState {
@@ -15,8 +16,9 @@
     file: string;
     private fixer?;
     errors: LintResultRule[];
     warnings: LintResultRule[];
+    approvals: LintResultRule[];
     constructor(file: string, fixer?: LintFixer | undefined);
     add(rule: LintResultRule): void;
     batchAdd(...rules: LintResultRule[]): void;
     size(): number;