shiplint 0.1.0

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 (130) hide show
  1. package/README.md +107 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +101 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/core/index.d.ts +5 -0
  7. package/dist/core/index.d.ts.map +1 -0
  8. package/dist/core/index.js +21 -0
  9. package/dist/core/index.js.map +1 -0
  10. package/dist/core/scanner.d.ts +27 -0
  11. package/dist/core/scanner.d.ts.map +1 -0
  12. package/dist/core/scanner.js +104 -0
  13. package/dist/core/scanner.js.map +1 -0
  14. package/dist/formatters/index.d.ts +13 -0
  15. package/dist/formatters/index.d.ts.map +1 -0
  16. package/dist/formatters/index.js +29 -0
  17. package/dist/formatters/index.js.map +1 -0
  18. package/dist/formatters/json.d.ts +13 -0
  19. package/dist/formatters/json.d.ts.map +1 -0
  20. package/dist/formatters/json.js +17 -0
  21. package/dist/formatters/json.js.map +1 -0
  22. package/dist/formatters/sarif.d.ts +14 -0
  23. package/dist/formatters/sarif.d.ts.map +1 -0
  24. package/dist/formatters/sarif.js +108 -0
  25. package/dist/formatters/sarif.js.map +1 -0
  26. package/dist/formatters/text.d.ts +9 -0
  27. package/dist/formatters/text.d.ts.map +1 -0
  28. package/dist/formatters/text.js +128 -0
  29. package/dist/formatters/text.js.map +1 -0
  30. package/dist/index.d.ts +11 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +49 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/parsers/entitlements-parser.d.ts +26 -0
  35. package/dist/parsers/entitlements-parser.d.ts.map +1 -0
  36. package/dist/parsers/entitlements-parser.js +105 -0
  37. package/dist/parsers/entitlements-parser.js.map +1 -0
  38. package/dist/parsers/framework-detector.d.ts +76 -0
  39. package/dist/parsers/framework-detector.d.ts.map +1 -0
  40. package/dist/parsers/framework-detector.js +501 -0
  41. package/dist/parsers/framework-detector.js.map +1 -0
  42. package/dist/parsers/index.d.ts +10 -0
  43. package/dist/parsers/index.d.ts.map +1 -0
  44. package/dist/parsers/index.js +26 -0
  45. package/dist/parsers/index.js.map +1 -0
  46. package/dist/parsers/pbxproj-parser.d.ts +166 -0
  47. package/dist/parsers/pbxproj-parser.d.ts.map +1 -0
  48. package/dist/parsers/pbxproj-parser.js +423 -0
  49. package/dist/parsers/pbxproj-parser.js.map +1 -0
  50. package/dist/parsers/plist-parser.d.ts +26 -0
  51. package/dist/parsers/plist-parser.d.ts.map +1 -0
  52. package/dist/parsers/plist-parser.js +166 -0
  53. package/dist/parsers/plist-parser.js.map +1 -0
  54. package/dist/parsers/project-parser.d.ts +57 -0
  55. package/dist/parsers/project-parser.d.ts.map +1 -0
  56. package/dist/parsers/project-parser.js +618 -0
  57. package/dist/parsers/project-parser.js.map +1 -0
  58. package/dist/parsers/workspace-parser.d.ts +82 -0
  59. package/dist/parsers/workspace-parser.d.ts.map +1 -0
  60. package/dist/parsers/workspace-parser.js +287 -0
  61. package/dist/parsers/workspace-parser.js.map +1 -0
  62. package/dist/rules/auth/index.d.ts +5 -0
  63. package/dist/rules/auth/index.d.ts.map +1 -0
  64. package/dist/rules/auth/index.js +9 -0
  65. package/dist/rules/auth/index.js.map +1 -0
  66. package/dist/rules/auth/third-party-login-no-siwa.d.ts +11 -0
  67. package/dist/rules/auth/third-party-login-no-siwa.d.ts.map +1 -0
  68. package/dist/rules/auth/third-party-login-no-siwa.js +119 -0
  69. package/dist/rules/auth/third-party-login-no-siwa.js.map +1 -0
  70. package/dist/rules/base.d.ts +25 -0
  71. package/dist/rules/base.d.ts.map +1 -0
  72. package/dist/rules/base.js +37 -0
  73. package/dist/rules/base.js.map +1 -0
  74. package/dist/rules/config/ats-exception-without-justification.d.ts +12 -0
  75. package/dist/rules/config/ats-exception-without-justification.d.ts.map +1 -0
  76. package/dist/rules/config/ats-exception-without-justification.js +152 -0
  77. package/dist/rules/config/ats-exception-without-justification.js.map +1 -0
  78. package/dist/rules/config/index.d.ts +5 -0
  79. package/dist/rules/config/index.d.ts.map +1 -0
  80. package/dist/rules/config/index.js +9 -0
  81. package/dist/rules/config/index.js.map +1 -0
  82. package/dist/rules/index.d.ts +43 -0
  83. package/dist/rules/index.d.ts.map +1 -0
  84. package/dist/rules/index.js +103 -0
  85. package/dist/rules/index.js.map +1 -0
  86. package/dist/rules/metadata/index.d.ts +5 -0
  87. package/dist/rules/metadata/index.d.ts.map +1 -0
  88. package/dist/rules/metadata/index.js +9 -0
  89. package/dist/rules/metadata/index.js.map +1 -0
  90. package/dist/rules/metadata/missing-privacy-manifest.d.ts +12 -0
  91. package/dist/rules/metadata/missing-privacy-manifest.d.ts.map +1 -0
  92. package/dist/rules/metadata/missing-privacy-manifest.js +186 -0
  93. package/dist/rules/metadata/missing-privacy-manifest.js.map +1 -0
  94. package/dist/rules/privacy/att-tracking-mismatch.d.ts +12 -0
  95. package/dist/rules/privacy/att-tracking-mismatch.d.ts.map +1 -0
  96. package/dist/rules/privacy/att-tracking-mismatch.js +113 -0
  97. package/dist/rules/privacy/att-tracking-mismatch.js.map +1 -0
  98. package/dist/rules/privacy/index.d.ts +11 -0
  99. package/dist/rules/privacy/index.d.ts.map +1 -0
  100. package/dist/rules/privacy/index.js +21 -0
  101. package/dist/rules/privacy/index.js.map +1 -0
  102. package/dist/rules/privacy/location-always-unjustified.d.ts +11 -0
  103. package/dist/rules/privacy/location-always-unjustified.d.ts.map +1 -0
  104. package/dist/rules/privacy/location-always-unjustified.js +102 -0
  105. package/dist/rules/privacy/location-always-unjustified.js.map +1 -0
  106. package/dist/rules/privacy/missing-camera-purpose.d.ts +11 -0
  107. package/dist/rules/privacy/missing-camera-purpose.d.ts.map +1 -0
  108. package/dist/rules/privacy/missing-camera-purpose.js +83 -0
  109. package/dist/rules/privacy/missing-camera-purpose.js.map +1 -0
  110. package/dist/rules/privacy/missing-contacts-purpose.d.ts +11 -0
  111. package/dist/rules/privacy/missing-contacts-purpose.d.ts.map +1 -0
  112. package/dist/rules/privacy/missing-contacts-purpose.js +85 -0
  113. package/dist/rules/privacy/missing-contacts-purpose.js.map +1 -0
  114. package/dist/rules/privacy/missing-location-purpose.d.ts +12 -0
  115. package/dist/rules/privacy/missing-location-purpose.d.ts.map +1 -0
  116. package/dist/rules/privacy/missing-location-purpose.js +137 -0
  117. package/dist/rules/privacy/missing-location-purpose.js.map +1 -0
  118. package/dist/rules/privacy/missing-microphone-purpose.d.ts +11 -0
  119. package/dist/rules/privacy/missing-microphone-purpose.d.ts.map +1 -0
  120. package/dist/rules/privacy/missing-microphone-purpose.js +132 -0
  121. package/dist/rules/privacy/missing-microphone-purpose.js.map +1 -0
  122. package/dist/rules/privacy/missing-photo-library-purpose.d.ts +11 -0
  123. package/dist/rules/privacy/missing-photo-library-purpose.d.ts.map +1 -0
  124. package/dist/rules/privacy/missing-photo-library-purpose.js +102 -0
  125. package/dist/rules/privacy/missing-photo-library-purpose.js.map +1 -0
  126. package/dist/types/index.d.ts +140 -0
  127. package/dist/types/index.d.ts.map +1 -0
  128. package/dist/types/index.js +59 -0
  129. package/dist/types/index.js.map +1 -0
  130. package/package.json +68 -0
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # ReviewShield
2
+
3
+ 🛡️ Catch App Store rejections before they happen.
4
+
5
+ ReviewShield scans your iOS project for App Store Review Guideline violations and tells you exactly how to fix them.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g reviewshield
11
+ ```
12
+
13
+ Or with npx (no install required):
14
+
15
+ ```bash
16
+ npx reviewshield scan ./MyApp.xcodeproj
17
+ ```
18
+
19
+ ## The Problem
20
+
21
+ App Store rejections cost time and money:
22
+ - 2-7 day review delays
23
+ - Missed launch windows
24
+ - Frustrated users waiting for updates
25
+
26
+ Common culprits: missing privacy descriptions, Sign in with Apple requirements, tracking compliance — all preventable.
27
+
28
+ ## The Solution
29
+
30
+ ReviewShield catches these issues **before** you submit:
31
+
32
+ ```bash
33
+ $ reviewshield scan ./MyApp.xcodeproj
34
+
35
+ 🛡️ ReviewShield Scan Results
36
+
37
+ 🔍 Found 2 issue(s):
38
+
39
+ 1. [CRITICAL] Missing Camera Usage Description
40
+ 📍 Info.plist • 📋 Guideline 5.1.1
41
+
42
+ Your app uses AVFoundation but Info.plist is missing
43
+ NSCameraUsageDescription...
44
+
45
+ How to fix:
46
+ Add NSCameraUsageDescription to your Info.plist...
47
+
48
+ 2. [CRITICAL] Third-Party Login Without Sign in with Apple
49
+ 📍 Entitlements • 📋 Guideline 4.8
50
+
51
+ Your app includes Google Sign-In but Sign in with Apple
52
+ is not configured...
53
+ ```
54
+
55
+ ## What We Check
56
+
57
+ | Category | Rules |
58
+ |----------|-------|
59
+ | **Privacy** | Camera, Location, Microphone, Photos, Contacts usage descriptions |
60
+ | **Tracking** | ATT compliance, tracking SDK detection |
61
+ | **Authentication** | Sign in with Apple requirements |
62
+ | **Security** | App Transport Security, Privacy Manifests (iOS 17+) |
63
+
64
+ 10 rules today, more coming weekly.
65
+
66
+ ## Usage
67
+
68
+ ```bash
69
+ # Scan an Xcode project
70
+ reviewshield scan ./MyApp.xcodeproj
71
+
72
+ # Scan a directory
73
+ reviewshield scan ./ios
74
+
75
+ # Output as JSON
76
+ reviewshield scan ./MyApp.xcodeproj --format json
77
+ ```
78
+
79
+ ## Rules (10 and growing)
80
+
81
+ **Privacy (Guideline 5.1.1)**
82
+ - `missing-camera-purpose` - Camera usage without NSCameraUsageDescription
83
+ - `missing-microphone-purpose` - Microphone usage without NSMicrophoneUsageDescription
84
+ - `missing-location-purpose` - Location usage without NSLocationUsageDescription
85
+ - `missing-photo-library-purpose` - Photo library usage without NSPhotoLibraryUsageDescription
86
+ - `missing-contacts-purpose` - Contacts usage without NSContactsUsageDescription
87
+ - `location-always-unjustified` - "Always" location without proper justification
88
+ - `att-tracking-mismatch` - ATT framework without NSUserTrackingUsageDescription
89
+
90
+ **Authentication (Guideline 4.8)**
91
+ - `third-party-login-no-siwa` - Third-party login without Sign in with Apple
92
+
93
+ **Security (Guideline 2.1)**
94
+ - `ats-exception-without-justification` - App Transport Security exceptions
95
+
96
+ **Metadata (iOS 17+)**
97
+ - `missing-privacy-manifest` - Missing PrivacyInfo.xcprivacy for required APIs
98
+
99
+ ## Coming Soon
100
+
101
+ **ReviewShield GitHub App** — automatic PR checks, no setup required.
102
+
103
+ Join the waitlist: [reviewshield.dev](https://reviewshield.dev)
104
+
105
+ ---
106
+
107
+ © 2026 Signal26. All rights reserved.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ /**
5
+ * ReviewShield CLI
6
+ *
7
+ * App Store Review Guideline scanner for iOS projects
8
+ */
9
+ const commander_1 = require("commander");
10
+ const scanner_js_1 = require("../core/scanner.js");
11
+ const index_js_1 = require("../formatters/index.js");
12
+ const index_js_2 = require("../rules/index.js");
13
+ const index_js_3 = require("../types/index.js");
14
+ const program = new commander_1.Command();
15
+ program
16
+ .name('reviewshield')
17
+ .description('App Store Review Guideline scanner for iOS projects')
18
+ .version('0.1.0');
19
+ program
20
+ .command('scan')
21
+ .description('Scan an Xcode project for potential App Store Review issues')
22
+ .argument('<path>', 'Path to Xcode project, workspace, or directory')
23
+ .option('-f, --format <format>', 'Output format: text, json, sarif', 'text')
24
+ .option('-v, --verbose', 'Show verbose output', false)
25
+ .option('-r, --rules <rules...>', 'Only run specific rules (by ID)')
26
+ .option('-e, --exclude <rules...>', 'Exclude specific rules (by ID)')
27
+ .action(async (path, options) => {
28
+ try {
29
+ const outputFormat = parseOutputFormat(options.format);
30
+ const result = await (0, scanner_js_1.scan)({
31
+ path,
32
+ format: outputFormat,
33
+ verbose: options.verbose,
34
+ rules: options.rules,
35
+ exclude: options.exclude,
36
+ });
37
+ const output = await (0, index_js_1.format)(result, outputFormat);
38
+ console.log(output);
39
+ // Exit with error code if critical issues found
40
+ const hasCritical = result.findings.some(f => f.severity === 'critical');
41
+ if (hasCritical) {
42
+ process.exit(1);
43
+ }
44
+ }
45
+ catch (error) {
46
+ if (error instanceof Error) {
47
+ console.error(`Error: ${error.message}`);
48
+ if (options.verbose) {
49
+ console.error(error.stack);
50
+ }
51
+ }
52
+ else {
53
+ console.error('An unknown error occurred');
54
+ }
55
+ process.exit(1);
56
+ }
57
+ });
58
+ program
59
+ .command('rules')
60
+ .description('List all available rules')
61
+ .option('-f, --format <format>', 'Output format: text, json', 'text')
62
+ .action((options) => {
63
+ if (options.format === 'json') {
64
+ const rules = index_js_2.allRules.map(rule => ({
65
+ id: rule.id,
66
+ name: rule.name,
67
+ description: rule.description,
68
+ category: rule.category,
69
+ severity: rule.severity,
70
+ guideline: rule.guidelineReference,
71
+ }));
72
+ console.log(JSON.stringify(rules, null, 2));
73
+ }
74
+ else {
75
+ console.log('\n🛡️ ReviewShield Rules\n');
76
+ console.log('='.repeat(60));
77
+ for (const rule of index_js_2.allRules) {
78
+ console.log(`\n${rule.id}`);
79
+ console.log(` Name: ${rule.name}`);
80
+ console.log(` Category: ${rule.category}`);
81
+ console.log(` Severity: ${rule.severity}`);
82
+ console.log(` Guideline: ${rule.guidelineReference}`);
83
+ console.log(` Description: ${rule.description}`);
84
+ }
85
+ console.log('\n');
86
+ }
87
+ });
88
+ function parseOutputFormat(format) {
89
+ switch (format.toLowerCase()) {
90
+ case 'text':
91
+ return index_js_3.OutputFormat.Text;
92
+ case 'json':
93
+ return index_js_3.OutputFormat.JSON;
94
+ case 'sarif':
95
+ return index_js_3.OutputFormat.SARIF;
96
+ default:
97
+ throw new Error(`Unknown output format: ${format}. Use text, json, or sarif.`);
98
+ }
99
+ }
100
+ program.parse();
101
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core module exports
3
+ */
4
+ export * from './scanner.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,cAAc,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * Core module exports
19
+ */
20
+ __exportStar(require("./scanner.js"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,+CAA6B"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Core scan engine
3
+ */
4
+ import type { Rule, Finding, ScanResult, ScanContext, ScanOptions } from '../types/index.js';
5
+ /**
6
+ * Error thrown when invalid rule IDs are specified
7
+ */
8
+ export declare class InvalidRulesError extends Error {
9
+ unknownIds: string[];
10
+ availableIds: string[];
11
+ constructor(unknownIds: string[], availableIds: string[]);
12
+ }
13
+ /**
14
+ * Error thrown when no rules would be run
15
+ */
16
+ export declare class NoRulesError extends Error {
17
+ constructor(message: string);
18
+ }
19
+ /**
20
+ * Run a scan on the given path
21
+ */
22
+ export declare function scan(options: ScanOptions): Promise<ScanResult>;
23
+ /**
24
+ * Run a scan with a pre-built context (for testing)
25
+ */
26
+ export declare function scanWithContext(context: ScanContext, rules?: Rule[]): Promise<Finding[]>;
27
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/core/scanner.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAI7F;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IACvB,UAAU,EAAE,MAAM,EAAE;IAAS,YAAY,EAAE,MAAM,EAAE;gBAAnD,UAAU,EAAE,MAAM,EAAE,EAAS,YAAY,EAAE,MAAM,EAAE;CAOvE;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA0EpE;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,WAAW,EACpB,KAAK,CAAC,EAAE,IAAI,EAAE,GACb,OAAO,CAAC,OAAO,EAAE,CAAC,CAUpB"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoRulesError = exports.InvalidRulesError = void 0;
4
+ exports.scan = scan;
5
+ exports.scanWithContext = scanWithContext;
6
+ const project_parser_js_1 = require("../parsers/project-parser.js");
7
+ const index_js_1 = require("../rules/index.js");
8
+ /**
9
+ * Error thrown when invalid rule IDs are specified
10
+ */
11
+ class InvalidRulesError extends Error {
12
+ unknownIds;
13
+ availableIds;
14
+ constructor(unknownIds, availableIds) {
15
+ super(`Unknown rule ID(s): ${unknownIds.join(', ')}. ` +
16
+ `Available rules: ${availableIds.join(', ')}`);
17
+ this.unknownIds = unknownIds;
18
+ this.availableIds = availableIds;
19
+ this.name = 'InvalidRulesError';
20
+ }
21
+ }
22
+ exports.InvalidRulesError = InvalidRulesError;
23
+ /**
24
+ * Error thrown when no rules would be run
25
+ */
26
+ class NoRulesError extends Error {
27
+ constructor(message) {
28
+ super(message);
29
+ this.name = 'NoRulesError';
30
+ }
31
+ }
32
+ exports.NoRulesError = NoRulesError;
33
+ /**
34
+ * Run a scan on the given path
35
+ */
36
+ async function scan(options) {
37
+ const startTime = Date.now();
38
+ // Discover project structure
39
+ const discovery = (0, project_parser_js_1.discoverProject)(options.path);
40
+ // Create scan context
41
+ const context = (0, project_parser_js_1.createScanContext)(discovery);
42
+ // Determine which rules to run
43
+ let rules;
44
+ if (options.rules && options.rules.length > 0) {
45
+ // BUG FIX #2: Validate rule IDs and error on unknown
46
+ const { rules: foundRules, unknownIds } = (0, index_js_1.getRulesWithValidation)(options.rules);
47
+ if (unknownIds.length > 0) {
48
+ throw new InvalidRulesError(unknownIds, index_js_1.allRules.map(r => r.id));
49
+ }
50
+ if (foundRules.length === 0) {
51
+ throw new NoRulesError('No valid rules to run. Check your --rules argument.');
52
+ }
53
+ rules = foundRules;
54
+ }
55
+ else if (options.exclude && options.exclude.length > 0) {
56
+ rules = (0, index_js_1.getRulesExcluding)(options.exclude);
57
+ if (rules.length === 0) {
58
+ throw new NoRulesError('All rules were excluded. At least one rule must run.');
59
+ }
60
+ }
61
+ else {
62
+ rules = index_js_1.allRules;
63
+ }
64
+ // Final safety check: never run with zero rules
65
+ if (rules.length === 0) {
66
+ throw new NoRulesError('No rules available to run. This should not happen - please report this bug.');
67
+ }
68
+ // Run all rules
69
+ const findings = [];
70
+ const rulesRun = [];
71
+ for (const rule of rules) {
72
+ try {
73
+ const ruleFindings = await rule.evaluate(context);
74
+ findings.push(...ruleFindings);
75
+ rulesRun.push(rule.id);
76
+ }
77
+ catch (error) {
78
+ if (options.verbose) {
79
+ console.error(`Error running rule ${rule.id}:`, error);
80
+ }
81
+ }
82
+ }
83
+ const duration = Date.now() - startTime;
84
+ return {
85
+ projectPath: options.path,
86
+ timestamp: new Date(),
87
+ findings,
88
+ rulesRun,
89
+ duration,
90
+ };
91
+ }
92
+ /**
93
+ * Run a scan with a pre-built context (for testing)
94
+ */
95
+ async function scanWithContext(context, rules) {
96
+ const rulesToRun = rules ?? index_js_1.allRules;
97
+ const findings = [];
98
+ for (const rule of rulesToRun) {
99
+ const ruleFindings = await rule.evaluate(context);
100
+ findings.push(...ruleFindings);
101
+ }
102
+ return findings;
103
+ }
104
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/core/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Formatters module exports
3
+ */
4
+ import type { ScanResult } from '../types/index.js';
5
+ import { OutputFormat } from '../types/index.js';
6
+ export { formatText } from './text.js';
7
+ export { formatJSON, formatJSONCompact } from './json.js';
8
+ export { formatSARIF } from './sarif.js';
9
+ /**
10
+ * Format scan results based on output format
11
+ */
12
+ export declare function format(result: ScanResult, outputFormat: OutputFormat): Promise<string>;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKjD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAS5F"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatSARIF = exports.formatJSONCompact = exports.formatJSON = exports.formatText = void 0;
4
+ exports.format = format;
5
+ const index_js_1 = require("../types/index.js");
6
+ const text_js_1 = require("./text.js");
7
+ const json_js_1 = require("./json.js");
8
+ const sarif_js_1 = require("./sarif.js");
9
+ var text_js_2 = require("./text.js");
10
+ Object.defineProperty(exports, "formatText", { enumerable: true, get: function () { return text_js_2.formatText; } });
11
+ var json_js_2 = require("./json.js");
12
+ Object.defineProperty(exports, "formatJSON", { enumerable: true, get: function () { return json_js_2.formatJSON; } });
13
+ Object.defineProperty(exports, "formatJSONCompact", { enumerable: true, get: function () { return json_js_2.formatJSONCompact; } });
14
+ var sarif_js_2 = require("./sarif.js");
15
+ Object.defineProperty(exports, "formatSARIF", { enumerable: true, get: function () { return sarif_js_2.formatSARIF; } });
16
+ /**
17
+ * Format scan results based on output format
18
+ */
19
+ async function format(result, outputFormat) {
20
+ switch (outputFormat) {
21
+ case index_js_1.OutputFormat.Text:
22
+ return (0, text_js_1.formatText)(result);
23
+ case index_js_1.OutputFormat.JSON:
24
+ return (0, json_js_1.formatJSON)(result);
25
+ case index_js_1.OutputFormat.SARIF:
26
+ return (0, sarif_js_1.formatSARIF)(result);
27
+ }
28
+ }
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":";;;AAgBA,wBASC;AArBD,gDAAiD;AACjD,uCAAuC;AACvC,uCAAuC;AACvC,yCAAyC;AAEzC,qCAAuC;AAA9B,qGAAA,UAAU,OAAA;AACnB,qCAA0D;AAAjD,qGAAA,UAAU,OAAA;AAAE,4GAAA,iBAAiB,OAAA;AACtC,uCAAyC;AAAhC,uGAAA,WAAW,OAAA;AAEpB;;GAEG;AACI,KAAK,UAAU,MAAM,CAAC,MAAkB,EAAE,YAA0B;IACzE,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,uBAAY,CAAC,IAAI;YACpB,OAAO,IAAA,oBAAU,EAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,uBAAY,CAAC,IAAI;YACpB,OAAO,IAAA,oBAAU,EAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,uBAAY,CAAC,KAAK;YACrB,OAAO,IAAA,sBAAW,EAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * JSON formatter for machine-readable output
3
+ */
4
+ import type { ScanResult } from '../types/index.js';
5
+ /**
6
+ * Format scan results as JSON
7
+ */
8
+ export declare function formatJSON(result: ScanResult): string;
9
+ /**
10
+ * Format scan results as compact JSON (single line)
11
+ */
12
+ export declare function formatJSONCompact(result: ScanResult): string;
13
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatJSON = formatJSON;
4
+ exports.formatJSONCompact = formatJSONCompact;
5
+ /**
6
+ * Format scan results as JSON
7
+ */
8
+ function formatJSON(result) {
9
+ return JSON.stringify(result, null, 2);
10
+ }
11
+ /**
12
+ * Format scan results as compact JSON (single line)
13
+ */
14
+ function formatJSONCompact(result) {
15
+ return JSON.stringify(result);
16
+ }
17
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":";;AAQA,gCAEC;AAKD,8CAEC;AAZD;;GAEG;AACH,SAAgB,UAAU,CAAC,MAAkB;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,MAAkB;IAClD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * SARIF formatter for CI/CD integration
3
+ *
4
+ * SARIF (Static Analysis Results Interchange Format) is a standard format
5
+ * for static analysis tools. It's supported by GitHub, Azure DevOps, and others.
6
+ *
7
+ * @see https://sarifweb.azurewebsites.net/
8
+ */
9
+ import type { ScanResult } from '../types/index.js';
10
+ /**
11
+ * Format scan results as SARIF
12
+ */
13
+ export declare function formatSARIF(result: ScanResult): string;
14
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/formatters/sarif.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,mBAAmB,CAAC;AAqF7D;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA0BtD"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatSARIF = formatSARIF;
4
+ const index_js_1 = require("../types/index.js");
5
+ /**
6
+ * SARIF schema version
7
+ */
8
+ const SARIF_VERSION = '2.1.0';
9
+ const SARIF_SCHEMA = 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json';
10
+ /**
11
+ * Convert severity to SARIF level
12
+ */
13
+ function toSarifLevel(severity) {
14
+ switch (severity) {
15
+ case index_js_1.Severity.Critical:
16
+ case index_js_1.Severity.High:
17
+ return 'error';
18
+ case index_js_1.Severity.Medium:
19
+ return 'warning';
20
+ case index_js_1.Severity.Low:
21
+ case index_js_1.Severity.Info:
22
+ return 'note';
23
+ }
24
+ }
25
+ /**
26
+ * Convert finding to SARIF result
27
+ */
28
+ function toSarifResult(finding) {
29
+ const result = {
30
+ ruleId: finding.ruleId,
31
+ level: toSarifLevel(finding.severity),
32
+ message: {
33
+ text: finding.description,
34
+ },
35
+ properties: {
36
+ confidence: finding.confidence,
37
+ guideline: finding.guideline,
38
+ fixGuidance: finding.fixGuidance,
39
+ },
40
+ };
41
+ if (finding.location) {
42
+ result.locations = [
43
+ {
44
+ physicalLocation: {
45
+ artifactLocation: {
46
+ uri: finding.location,
47
+ },
48
+ },
49
+ },
50
+ ];
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Build SARIF rules array from findings
56
+ */
57
+ function buildRules(findings) {
58
+ const ruleMap = new Map();
59
+ for (const finding of findings) {
60
+ if (!ruleMap.has(finding.ruleId)) {
61
+ ruleMap.set(finding.ruleId, finding);
62
+ }
63
+ }
64
+ return Array.from(ruleMap.values()).map(finding => ({
65
+ id: finding.ruleId,
66
+ name: finding.title,
67
+ shortDescription: {
68
+ text: finding.title,
69
+ },
70
+ fullDescription: {
71
+ text: finding.description,
72
+ },
73
+ helpUri: finding.documentationURL,
74
+ properties: {
75
+ guideline: finding.guideline,
76
+ },
77
+ }));
78
+ }
79
+ /**
80
+ * Format scan results as SARIF
81
+ */
82
+ function formatSARIF(result) {
83
+ const sarif = {
84
+ $schema: SARIF_SCHEMA,
85
+ version: SARIF_VERSION,
86
+ runs: [
87
+ {
88
+ tool: {
89
+ driver: {
90
+ name: 'ReviewShield',
91
+ version: '0.1.0',
92
+ informationUri: 'https://github.com/kazuochi/ReviewShield_iOS',
93
+ rules: buildRules(result.findings),
94
+ },
95
+ },
96
+ results: result.findings.map(toSarifResult),
97
+ invocations: [
98
+ {
99
+ executionSuccessful: true,
100
+ endTimeUtc: result.timestamp.toISOString(),
101
+ },
102
+ ],
103
+ },
104
+ ],
105
+ };
106
+ return JSON.stringify(sarif, null, 2);
107
+ }
108
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/formatters/sarif.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Text formatter for human-readable output
3
+ */
4
+ import type { ScanResult } from '../types/index.js';
5
+ /**
6
+ * Format scan results as text
7
+ */
8
+ export declare function formatText(result: ScanResult): Promise<string>;
9
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/formatters/text.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,mBAAmB,CAAC;AAyF7D;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAuDpE"}