@probelabs/visor 0.1.20 → 0.1.21

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 (107) hide show
  1. package/dist/action-cli-bridge.d.ts +0 -1
  2. package/dist/action-cli-bridge.d.ts.map +1 -1
  3. package/dist/ai-review-service.d.ts +0 -1
  4. package/dist/ai-review-service.d.ts.map +1 -1
  5. package/dist/check-execution-engine.d.ts +0 -1
  6. package/dist/check-execution-engine.d.ts.map +1 -1
  7. package/dist/cli-main.d.ts +0 -2
  8. package/dist/cli-main.d.ts.map +1 -1
  9. package/dist/cli.d.ts +0 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/commands.d.ts +0 -1
  12. package/dist/commands.d.ts.map +1 -1
  13. package/dist/config.d.ts +0 -1
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/dependency-resolver.d.ts +0 -1
  16. package/dist/dependency-resolver.d.ts.map +1 -1
  17. package/dist/event-mapper.d.ts +0 -1
  18. package/dist/event-mapper.d.ts.map +1 -1
  19. package/dist/failure-condition-evaluator.d.ts +0 -1
  20. package/dist/failure-condition-evaluator.d.ts.map +1 -1
  21. package/dist/git-repository-analyzer.d.ts +0 -1
  22. package/dist/git-repository-analyzer.d.ts.map +1 -1
  23. package/dist/github-check-service.d.ts +0 -1
  24. package/dist/github-check-service.d.ts.map +1 -1
  25. package/dist/github-comments.d.ts +0 -1
  26. package/dist/github-comments.d.ts.map +1 -1
  27. package/dist/index.d.ts +0 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +127704 -805
  30. package/dist/output-formatters.d.ts +0 -1
  31. package/dist/output-formatters.d.ts.map +1 -1
  32. package/dist/pr-analyzer.d.ts +0 -1
  33. package/dist/pr-analyzer.d.ts.map +1 -1
  34. package/dist/pr-detector.d.ts +0 -1
  35. package/dist/pr-detector.d.ts.map +1 -1
  36. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  37. package/dist/providers/check-provider-registry.d.ts.map +1 -1
  38. package/dist/providers/check-provider.interface.d.ts.map +1 -1
  39. package/dist/providers/index.d.ts.map +1 -1
  40. package/dist/providers/noop-check-provider.d.ts.map +1 -1
  41. package/dist/providers/tool-check-provider.d.ts.map +1 -1
  42. package/dist/providers/webhook-check-provider.d.ts.map +1 -1
  43. package/dist/reviewer.d.ts +0 -1
  44. package/dist/reviewer.d.ts.map +1 -1
  45. package/dist/session-registry.d.ts +0 -1
  46. package/dist/session-registry.d.ts.map +1 -1
  47. package/dist/types/cli.d.ts.map +1 -1
  48. package/dist/types/config.d.ts.map +1 -1
  49. package/dist/utils/env-resolver.d.ts.map +1 -1
  50. package/package.json +3 -3
  51. package/dist/action-cli-bridge.js +0 -387
  52. package/dist/action-cli-bridge.js.map +0 -1
  53. package/dist/ai-review-service.js +0 -854
  54. package/dist/ai-review-service.js.map +0 -1
  55. package/dist/check-execution-engine.js +0 -1720
  56. package/dist/check-execution-engine.js.map +0 -1
  57. package/dist/cli-main.js +0 -249
  58. package/dist/cli-main.js.map +0 -1
  59. package/dist/cli.js +0 -241
  60. package/dist/cli.js.map +0 -1
  61. package/dist/commands.js +0 -53
  62. package/dist/commands.js.map +0 -1
  63. package/dist/config.js +0 -437
  64. package/dist/config.js.map +0 -1
  65. package/dist/dependency-resolver.js +0 -163
  66. package/dist/dependency-resolver.js.map +0 -1
  67. package/dist/event-mapper.js +0 -316
  68. package/dist/event-mapper.js.map +0 -1
  69. package/dist/failure-condition-evaluator.js +0 -481
  70. package/dist/failure-condition-evaluator.js.map +0 -1
  71. package/dist/git-repository-analyzer.js +0 -285
  72. package/dist/git-repository-analyzer.js.map +0 -1
  73. package/dist/github-check-service.js +0 -369
  74. package/dist/github-check-service.js.map +0 -1
  75. package/dist/github-comments.js +0 -289
  76. package/dist/github-comments.js.map +0 -1
  77. package/dist/index.js.map +0 -1
  78. package/dist/output-formatters.js +0 -624
  79. package/dist/output-formatters.js.map +0 -1
  80. package/dist/pr-analyzer.js +0 -195
  81. package/dist/pr-analyzer.js.map +0 -1
  82. package/dist/pr-detector.js +0 -357
  83. package/dist/pr-detector.js.map +0 -1
  84. package/dist/providers/ai-check-provider.js +0 -437
  85. package/dist/providers/ai-check-provider.js.map +0 -1
  86. package/dist/providers/check-provider-registry.js +0 -138
  87. package/dist/providers/check-provider-registry.js.map +0 -1
  88. package/dist/providers/check-provider.interface.js +0 -11
  89. package/dist/providers/check-provider.interface.js.map +0 -1
  90. package/dist/providers/index.js +0 -19
  91. package/dist/providers/index.js.map +0 -1
  92. package/dist/providers/noop-check-provider.js +0 -55
  93. package/dist/providers/noop-check-provider.js.map +0 -1
  94. package/dist/providers/tool-check-provider.js +0 -174
  95. package/dist/providers/tool-check-provider.js.map +0 -1
  96. package/dist/providers/webhook-check-provider.js +0 -173
  97. package/dist/providers/webhook-check-provider.js.map +0 -1
  98. package/dist/reviewer.js +0 -260
  99. package/dist/reviewer.js.map +0 -1
  100. package/dist/session-registry.js +0 -67
  101. package/dist/session-registry.js.map +0 -1
  102. package/dist/types/cli.js +0 -3
  103. package/dist/types/cli.js.map +0 -1
  104. package/dist/types/config.js +0 -6
  105. package/dist/types/config.js.map +0 -1
  106. package/dist/utils/env-resolver.js +0 -130
  107. package/dist/utils/env-resolver.js.map +0 -1
@@ -1,285 +0,0 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.GitRepositoryAnalyzer = void 0;
37
- const simple_git_1 = require("simple-git");
38
- const path = __importStar(require("path"));
39
- const fs = __importStar(require("fs"));
40
- class GitRepositoryAnalyzer {
41
- git;
42
- cwd;
43
- constructor(workingDirectory = process.cwd()) {
44
- this.cwd = workingDirectory;
45
- this.git = (0, simple_git_1.simpleGit)(workingDirectory);
46
- }
47
- /**
48
- * Analyze the current git repository state and return data compatible with PRInfo interface
49
- */
50
- async analyzeRepository() {
51
- // Check if we're in a git repository
52
- const isRepo = await this.isGitRepository();
53
- if (!isRepo) {
54
- return this.createEmptyRepositoryInfo('Not a git repository');
55
- }
56
- try {
57
- // Get current branch and status
58
- const [status, currentBranch] = await Promise.all([
59
- this.git.status(),
60
- this.getCurrentBranch(),
61
- ]);
62
- // Get uncommitted changes
63
- const uncommittedFiles = await this.getUncommittedChanges();
64
- // Get recent commit info
65
- const recentCommits = await this.git.log({ maxCount: 1 });
66
- const lastCommit = recentCommits.latest;
67
- // Create repository info
68
- const repositoryInfo = {
69
- title: this.generateTitle(status, currentBranch),
70
- body: this.generateDescription(status, lastCommit),
71
- author: lastCommit?.author_name || 'unknown',
72
- base: await this.getBaseBranch(),
73
- head: currentBranch,
74
- files: uncommittedFiles,
75
- totalAdditions: uncommittedFiles.reduce((sum, file) => sum + file.additions, 0),
76
- totalDeletions: uncommittedFiles.reduce((sum, file) => sum + file.deletions, 0),
77
- isGitRepository: true,
78
- workingDirectory: this.cwd,
79
- };
80
- return repositoryInfo;
81
- }
82
- catch (error) {
83
- console.error('Error analyzing git repository:', error);
84
- return this.createEmptyRepositoryInfo('Error analyzing git repository');
85
- }
86
- }
87
- /**
88
- * Convert GitRepositoryInfo to PRInfo format for compatibility with existing PRReviewer
89
- */
90
- toPRInfo(repositoryInfo) {
91
- return {
92
- number: 0, // Local analysis doesn't have PR number
93
- title: repositoryInfo.title,
94
- body: repositoryInfo.body,
95
- author: repositoryInfo.author,
96
- base: repositoryInfo.base,
97
- head: repositoryInfo.head,
98
- files: repositoryInfo.files.map((file) => ({
99
- filename: file.filename,
100
- additions: file.additions,
101
- deletions: file.deletions,
102
- changes: file.changes,
103
- patch: file.patch,
104
- status: file.status,
105
- })),
106
- totalAdditions: repositoryInfo.totalAdditions,
107
- totalDeletions: repositoryInfo.totalDeletions,
108
- };
109
- }
110
- async isGitRepository() {
111
- try {
112
- await this.git.checkIsRepo();
113
- return true;
114
- }
115
- catch {
116
- return false;
117
- }
118
- }
119
- async getCurrentBranch() {
120
- try {
121
- const branchSummary = await this.git.branch();
122
- return branchSummary.current || 'unknown';
123
- }
124
- catch {
125
- return 'unknown';
126
- }
127
- }
128
- async getBaseBranch() {
129
- try {
130
- // Try to get the default branch from remote
131
- const branches = await this.git.branch(['-r']);
132
- const mainBranches = ['origin/main', 'origin/master', 'origin/develop'];
133
- for (const mainBranch of mainBranches) {
134
- if (branches.all.includes(mainBranch)) {
135
- return mainBranch.replace('origin/', '');
136
- }
137
- }
138
- // Fallback to main/master
139
- return 'main';
140
- }
141
- catch {
142
- return 'main';
143
- }
144
- }
145
- async getRemoteInfo() {
146
- try {
147
- const remotes = await this.git.getRemotes(true);
148
- const origin = remotes.find(r => r.name === 'origin');
149
- return origin
150
- ? { name: origin.name, url: origin.refs.fetch || origin.refs.push || '' }
151
- : null;
152
- }
153
- catch {
154
- return null;
155
- }
156
- }
157
- async getUncommittedChanges() {
158
- try {
159
- const status = await this.git.status();
160
- const changes = [];
161
- // Process different types of changes
162
- const fileChanges = [
163
- ...status.created.map(f => ({ file: f, status: 'added' })),
164
- ...status.deleted.map(f => ({ file: f, status: 'removed' })),
165
- ...status.modified.map(f => ({ file: f, status: 'modified' })),
166
- ...status.renamed.map(f => ({
167
- file: typeof f === 'string' ? f : f.to || f.from,
168
- status: 'renamed',
169
- })),
170
- ];
171
- for (const { file, status } of fileChanges) {
172
- const filePath = path.join(this.cwd, file);
173
- const fileChange = await this.analyzeFileChange(file, status, filePath);
174
- changes.push(fileChange);
175
- }
176
- return changes;
177
- }
178
- catch (error) {
179
- console.error('Error getting uncommitted changes:', error);
180
- return [];
181
- }
182
- }
183
- async analyzeFileChange(filename, status, filePath) {
184
- let additions = 0;
185
- let deletions = 0;
186
- let patch;
187
- let content;
188
- try {
189
- // Get diff for the file if it exists and is not binary
190
- if (status !== 'added' && fs.existsSync(filePath)) {
191
- const diff = await this.git.diff(['--', filename]).catch(() => '');
192
- if (diff) {
193
- patch = diff;
194
- // Count additions and deletions from diff
195
- const lines = diff.split('\n');
196
- additions = lines.filter(line => line.startsWith('+')).length;
197
- deletions = lines.filter(line => line.startsWith('-')).length;
198
- }
199
- }
200
- // For added files, count lines as additions
201
- if (status === 'added' && fs.existsSync(filePath)) {
202
- try {
203
- const stats = fs.statSync(filePath);
204
- if (stats.isFile() && stats.size < 1024 * 1024) {
205
- // Skip files larger than 1MB
206
- content = fs.readFileSync(filePath, 'utf8');
207
- additions = content.split('\n').length;
208
- patch = content; // For new files, the entire content is the "patch"
209
- }
210
- }
211
- catch {
212
- // Skip binary or unreadable files
213
- }
214
- }
215
- // For removed files, we can't easily count the lines without the previous version
216
- if (status === 'removed') {
217
- deletions = 1; // Placeholder - in real git we'd need the previous version
218
- }
219
- }
220
- catch (error) {
221
- console.error(`Error analyzing file change for ${filename}:`, error);
222
- }
223
- return {
224
- filename,
225
- status,
226
- additions,
227
- deletions,
228
- changes: additions + deletions,
229
- content,
230
- patch,
231
- };
232
- }
233
- generateTitle(status, branch) {
234
- if (status.files.length === 0) {
235
- return `Local Analysis: ${branch} (No changes)`;
236
- }
237
- const changeTypes = [];
238
- if (status.created.length > 0)
239
- changeTypes.push(`${status.created.length} added`);
240
- if (status.modified.length > 0)
241
- changeTypes.push(`${status.modified.length} modified`);
242
- if (status.deleted.length > 0)
243
- changeTypes.push(`${status.deleted.length} deleted`);
244
- if (status.renamed.length > 0)
245
- changeTypes.push(`${status.renamed.length} renamed`);
246
- return `Local Analysis: ${branch} (${changeTypes.join(', ')})`;
247
- }
248
- generateDescription(status, lastCommit) {
249
- let description = `Analysis of local git repository working directory.\n\n`;
250
- if (lastCommit) {
251
- description += `**Last Commit:** ${lastCommit.message}\n`;
252
- description += `**Author:** ${lastCommit.author_name} <${lastCommit.author_email}>\n`;
253
- description += `**Date:** ${lastCommit.date}\n\n`;
254
- }
255
- if (status.files.length === 0) {
256
- description += `**Status:** Working directory is clean - no uncommitted changes found.\n`;
257
- }
258
- else {
259
- description += `**Changes Summary:**\n`;
260
- description += `- Files to be committed: ${status.staged.length}\n`;
261
- description += `- Modified files: ${status.modified.length}\n`;
262
- description += `- Untracked files: ${status.not_added.length}\n`;
263
- if (status.conflicted.length > 0) {
264
- description += `- Conflicted files: ${status.conflicted.length}\n`;
265
- }
266
- }
267
- return description;
268
- }
269
- createEmptyRepositoryInfo(reason) {
270
- return {
271
- title: `Local Analysis: ${reason}`,
272
- body: `Unable to analyze repository: ${reason}`,
273
- author: 'system',
274
- base: 'main',
275
- head: 'HEAD',
276
- files: [],
277
- totalAdditions: 0,
278
- totalDeletions: 0,
279
- isGitRepository: false,
280
- workingDirectory: this.cwd,
281
- };
282
- }
283
- }
284
- exports.GitRepositoryAnalyzer = GitRepositoryAnalyzer;
285
- //# sourceMappingURL=git-repository-analyzer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git-repository-analyzer.js","sourceRoot":"","sources":["../src/git-repository-analyzer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAkD;AAClD,2CAA6B;AAC7B,uCAAyB;AA0BzB,MAAa,qBAAqB;IACxB,GAAG,CAAY;IACf,GAAG,CAAS;IAEpB,YAAY,mBAA2B,OAAO,CAAC,GAAG,EAAE;QAClD,IAAI,CAAC,GAAG,GAAG,gBAAgB,CAAC;QAC5B,IAAI,CAAC,GAAG,GAAG,IAAA,sBAAS,EAAC,gBAAgB,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB;QACrB,qCAAqC;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC;YACH,gCAAgC;YAChC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE;gBACjB,IAAI,CAAC,gBAAgB,EAAE;aACxB,CAAC,CAAC;YAEH,0BAA0B;YAC1B,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAE5D,yBAAyB;YACzB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1D,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;YAExC,yBAAyB;YACzB,MAAM,cAAc,GAAsB;gBACxC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC;gBAChD,IAAI,EAAE,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC;gBAClD,MAAM,EAAE,UAAU,EAAE,WAAW,IAAI,SAAS;gBAC5C,IAAI,EAAE,MAAM,IAAI,CAAC,aAAa,EAAE;gBAChC,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,gBAAgB;gBACvB,cAAc,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;gBAC/E,cAAc,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;gBAC/E,eAAe,EAAE,IAAI;gBACrB,gBAAgB,EAAE,IAAI,CAAC,GAAG;aAC3B,CAAC;YAEF,OAAO,cAAc,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC,yBAAyB,CAAC,gCAAgC,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,cAAiC;QACxC,OAAO;YACL,MAAM,EAAE,CAAC,EAAE,wCAAwC;YACnD,KAAK,EAAE,cAAc,CAAC,KAAK;YAC3B,IAAI,EAAE,cAAc,CAAC,IAAI;YACzB,MAAM,EAAE,cAAc,CAAC,MAAM;YAC7B,IAAI,EAAE,cAAc,CAAC,IAAI;YACzB,IAAI,EAAE,cAAc,CAAC,IAAI;YACzB,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,CAC7B,CAAC,IAAI,EAAU,EAAE,CAAC,CAAC;gBACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CACH;YACD,cAAc,EAAE,cAAc,CAAC,cAAc;YAC7C,cAAc,EAAE,cAAc,CAAC,cAAc;SAC9C,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YAC9C,OAAO,aAAa,CAAC,OAAO,IAAI,SAAS,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,IAAI,CAAC;YACH,4CAA4C;YAC5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC/C,MAAM,YAAY,GAAG,CAAC,aAAa,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;YAExE,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;gBACtC,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBACtC,OAAO,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;YAED,0BAA0B;YAC1B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YACtD,OAAO,MAAM;gBACX,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE;gBACzE,CAAC,CAAC,IAAI,CAAC;QACX,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,qBAAqB;QACjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YACvC,MAAM,OAAO,GAAoB,EAAE,CAAC;YAEpC,qCAAqC;YACrC,MAAM,WAAW,GAAG;gBAClB,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,OAAgB,EAAE,CAAC,CAAC;gBACnE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC,CAAC;gBACrE,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,UAAmB,EAAE,CAAC,CAAC;gBACvE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC1B,IAAI,EAAE,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI;oBAChD,MAAM,EAAE,SAAkB;iBAC3B,CAAC,CAAC;aACJ,CAAC;YAEF,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;gBAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC3C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3B,CAAC;YAED,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;YAC3D,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAC7B,QAAgB,EAChB,MAAoD,EACpD,QAAgB;QAEhB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,KAAyB,CAAC;QAC9B,IAAI,OAA2B,CAAC;QAEhC,IAAI,CAAC;YACH,uDAAuD;YACvD,IAAI,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACnE,IAAI,IAAI,EAAE,CAAC;oBACT,KAAK,GAAG,IAAI,CAAC;oBACb,0CAA0C;oBAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC/B,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;oBAC9D,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;gBAChE,CAAC;YACH,CAAC;YAED,4CAA4C;YAC5C,IAAI,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClD,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACpC,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;wBAC/C,6BAA6B;wBAC7B,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;wBAC5C,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;wBACvC,KAAK,GAAG,OAAO,CAAC,CAAC,mDAAmD;oBACtE,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,kCAAkC;gBACpC,CAAC;YACH,CAAC;YAED,kFAAkF;YAClF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,SAAS,GAAG,CAAC,CAAC,CAAC,2DAA2D;YAC5E,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;QACvE,CAAC;QAED,OAAO;YACL,QAAQ;YACR,MAAM;YACN,SAAS;YACT,SAAS;YACT,OAAO,EAAE,SAAS,GAAG,SAAS;YAC9B,OAAO;YACP,KAAK;SACN,CAAC;IACJ,CAAC;IAEO,aAAa,CAAC,MAAyC,EAAE,MAAc;QAC7E,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,mBAAmB,MAAM,eAAe,CAAC;QAClD,CAAC;QAED,MAAM,WAAW,GAAG,EAAE,CAAC;QACvB,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,QAAQ,CAAC,CAAC;QAClF,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;QACvF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;QACpF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;QAEpF,OAAO,mBAAmB,MAAM,KAAK,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACjE,CAAC;IAEO,mBAAmB,CACzB,MAAyC,EACzC,UAAwD;QAExD,IAAI,WAAW,GAAG,yDAAyD,CAAC;QAE5E,IAAI,UAAU,EAAE,CAAC;YACf,WAAW,IAAI,oBAAoB,UAAU,CAAC,OAAO,IAAI,CAAC;YAC1D,WAAW,IAAI,eAAe,UAAU,CAAC,WAAW,KAAK,UAAU,CAAC,YAAY,KAAK,CAAC;YACtF,WAAW,IAAI,aAAa,UAAU,CAAC,IAAI,MAAM,CAAC;QACpD,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,WAAW,IAAI,0EAA0E,CAAC;QAC5F,CAAC;aAAM,CAAC;YACN,WAAW,IAAI,wBAAwB,CAAC;YACxC,WAAW,IAAI,4BAA4B,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC;YACpE,WAAW,IAAI,qBAAqB,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;YAC/D,WAAW,IAAI,sBAAsB,MAAM,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC;YAEjE,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,WAAW,IAAI,uBAAuB,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC;YACrE,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAEO,yBAAyB,CAAC,MAAc;QAC9C,OAAO;YACL,KAAK,EAAE,mBAAmB,MAAM,EAAE;YAClC,IAAI,EAAE,iCAAiC,MAAM,EAAE;YAC/C,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,EAAE;YACT,cAAc,EAAE,CAAC;YACjB,cAAc,EAAE,CAAC;YACjB,eAAe,EAAE,KAAK;YACtB,gBAAgB,EAAE,IAAI,CAAC,GAAG;SAC3B,CAAC;IACJ,CAAC;CACF;AA/QD,sDA+QC"}
@@ -1,369 +0,0 @@
1
- "use strict";
2
- /**
3
- * GitHub Check Service for creating and managing check runs based on failure conditions
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.GitHubCheckService = void 0;
7
- /**
8
- * Service for managing GitHub Check Runs based on Visor failure conditions
9
- */
10
- class GitHubCheckService {
11
- octokit;
12
- maxAnnotations = 50; // GitHub API limit
13
- constructor(octokit) {
14
- this.octokit = octokit;
15
- }
16
- /**
17
- * Create a new check run in queued status
18
- */
19
- async createCheckRun(options, summary) {
20
- try {
21
- const response = await this.octokit.rest.checks.create({
22
- owner: options.owner,
23
- repo: options.repo,
24
- name: options.name,
25
- head_sha: options.head_sha,
26
- status: 'queued',
27
- details_url: options.details_url,
28
- external_id: options.external_id,
29
- output: summary
30
- ? {
31
- title: summary.title,
32
- summary: summary.summary,
33
- text: summary.text,
34
- }
35
- : undefined,
36
- });
37
- return {
38
- id: response.data.id,
39
- url: response.data.html_url || '',
40
- };
41
- }
42
- catch (error) {
43
- throw new Error(`Failed to create check run: ${error instanceof Error ? error.message : String(error)}`);
44
- }
45
- }
46
- /**
47
- * Update check run to in_progress status
48
- */
49
- async updateCheckRunInProgress(owner, repo, check_run_id, summary) {
50
- try {
51
- await this.octokit.rest.checks.update({
52
- owner,
53
- repo,
54
- check_run_id,
55
- status: 'in_progress',
56
- output: summary
57
- ? {
58
- title: summary.title,
59
- summary: summary.summary,
60
- text: summary.text,
61
- }
62
- : undefined,
63
- });
64
- }
65
- catch (error) {
66
- throw new Error(`Failed to update check run to in_progress: ${error instanceof Error ? error.message : String(error)}`);
67
- }
68
- }
69
- /**
70
- * Complete a check run with results based on failure conditions
71
- */
72
- async completeCheckRun(owner, repo, check_run_id, checkName, failureResults, reviewIssues = [], executionError) {
73
- try {
74
- const { conclusion, summary } = this.determineCheckRunConclusion(checkName, failureResults, reviewIssues, executionError);
75
- const annotations = this.convertIssuesToAnnotations(reviewIssues);
76
- await this.octokit.rest.checks.update({
77
- owner,
78
- repo,
79
- check_run_id,
80
- status: 'completed',
81
- conclusion,
82
- completed_at: new Date().toISOString(),
83
- output: {
84
- title: summary.title,
85
- summary: summary.summary,
86
- text: summary.text,
87
- annotations: annotations.slice(0, this.maxAnnotations), // GitHub limit
88
- },
89
- });
90
- }
91
- catch (error) {
92
- throw new Error(`Failed to complete check run: ${error instanceof Error ? error.message : String(error)}`);
93
- }
94
- }
95
- /**
96
- * Determine check run conclusion based on failure conditions and issues
97
- */
98
- determineCheckRunConclusion(checkName, failureResults, reviewIssues, executionError) {
99
- // Handle execution errors first
100
- if (executionError) {
101
- return {
102
- conclusion: 'failure',
103
- summary: {
104
- title: '❌ Check Execution Failed',
105
- summary: `The ${checkName} check failed to execute properly.`,
106
- text: `**Error:** ${executionError}\n\nPlease check your configuration and try again.`,
107
- },
108
- };
109
- }
110
- // Check if any fail_if conditions were met
111
- const failedConditions = failureResults.filter(result => result.failed);
112
- // Count issues by severity (for informational display only)
113
- const criticalIssues = reviewIssues.filter(issue => issue.severity === 'critical').length;
114
- const errorIssues = reviewIssues.filter(issue => issue.severity === 'error').length;
115
- const warningIssues = reviewIssues.filter(issue => issue.severity === 'warning').length;
116
- const totalIssues = reviewIssues.length;
117
- // Determine conclusion ONLY based on fail_if evaluation results
118
- // The presence of issues (critical, error, warning) does NOT affect the conclusion
119
- // Only the fail_if condition determines pass/fail status
120
- let conclusion;
121
- let title;
122
- let summaryText;
123
- let details;
124
- if (failedConditions.length > 0) {
125
- // Check fails if fail_if condition is met
126
- conclusion = 'failure';
127
- title = '🚨 Check Failed';
128
- summaryText = `${checkName} check failed because fail_if condition was met.`;
129
- details = this.formatCheckDetails(failureResults, reviewIssues, {
130
- failedConditions: failedConditions.length,
131
- warningConditions: 0,
132
- criticalIssues,
133
- errorIssues,
134
- warningIssues,
135
- totalIssues,
136
- });
137
- }
138
- else {
139
- // No fail_if conditions met - check passes regardless of issues found
140
- conclusion = 'success';
141
- // Adjust the title and summary based on issues found, but conclusion remains success
142
- if (criticalIssues > 0 || errorIssues > 0) {
143
- title = '✅ Check Passed (Issues Found)';
144
- summaryText = `${checkName} check passed. Found ${criticalIssues} critical and ${errorIssues} error issues, but fail_if condition was not met.`;
145
- }
146
- else if (warningIssues > 0) {
147
- title = '✅ Check Passed (Warnings Found)';
148
- summaryText = `${checkName} check passed. Found ${warningIssues} warning${warningIssues === 1 ? '' : 's'}, but fail_if condition was not met.`;
149
- }
150
- else {
151
- title = '✅ Check Passed';
152
- summaryText = `${checkName} check completed successfully with no issues found.`;
153
- }
154
- details = this.formatCheckDetails(failureResults, reviewIssues, {
155
- failedConditions: 0,
156
- warningConditions: 0,
157
- criticalIssues,
158
- errorIssues,
159
- warningIssues,
160
- totalIssues,
161
- });
162
- }
163
- return {
164
- conclusion,
165
- summary: {
166
- title,
167
- summary: summaryText,
168
- text: details,
169
- },
170
- };
171
- }
172
- /**
173
- * Format detailed check results for the check run summary
174
- */
175
- formatCheckDetails(failureResults, reviewIssues, counts) {
176
- const sections = [];
177
- // Summary section
178
- sections.push('## 📊 Summary');
179
- sections.push(`- **Total Issues:** ${counts.totalIssues}`);
180
- if (counts.criticalIssues > 0) {
181
- sections.push(`- **Critical Issues:** ${counts.criticalIssues}`);
182
- }
183
- if (counts.errorIssues > 0) {
184
- sections.push(`- **Error Issues:** ${counts.errorIssues}`);
185
- }
186
- if (counts.warningIssues > 0) {
187
- sections.push(`- **Warning Issues:** ${counts.warningIssues}`);
188
- }
189
- sections.push('');
190
- // Failure conditions section
191
- if (failureResults.length > 0) {
192
- sections.push('## 🔍 Failure Condition Results');
193
- const failedConditions = failureResults.filter(result => result.failed);
194
- const passedConditions = failureResults.filter(result => !result.failed);
195
- if (failedConditions.length > 0) {
196
- sections.push('### ❌ Failed Conditions');
197
- failedConditions.forEach(condition => {
198
- sections.push(`- **${condition.conditionName}**: ${condition.message || condition.expression}`);
199
- if (condition.severity === 'error') {
200
- sections.push(` - âš ī¸ **Severity:** Error`);
201
- }
202
- });
203
- sections.push('');
204
- }
205
- if (passedConditions.length > 0) {
206
- sections.push('### ✅ Passed Conditions');
207
- passedConditions.forEach(condition => {
208
- sections.push(`- **${condition.conditionName}**: ${condition.message || 'Condition passed'}`);
209
- });
210
- sections.push('');
211
- }
212
- }
213
- // Issues by category section
214
- if (reviewIssues.length > 0) {
215
- const issuesByCategory = this.groupIssuesByCategory(reviewIssues);
216
- sections.push('## 🐛 Issues by Category');
217
- Object.entries(issuesByCategory).forEach(([category, issues]) => {
218
- if (issues.length > 0) {
219
- sections.push(`### ${this.getCategoryEmoji(category)} ${category.charAt(0).toUpperCase() + category.slice(1)} (${issues.length})`);
220
- // Show only first 5 issues per category to keep the summary concise
221
- const displayIssues = issues.slice(0, 5);
222
- displayIssues.forEach(issue => {
223
- const severityIcon = this.getSeverityIcon(issue.severity);
224
- sections.push(`- ${severityIcon} **${issue.file}:${issue.line}** - ${issue.message}`);
225
- });
226
- if (issues.length > 5) {
227
- sections.push(`- *...and ${issues.length - 5} more ${category} issues*`);
228
- }
229
- sections.push('');
230
- }
231
- });
232
- }
233
- // Footer
234
- sections.push('---');
235
- sections.push('*Generated by [Visor](https://github.com/probelabs/visor) - AI-powered code review*');
236
- return sections.join('\n');
237
- }
238
- /**
239
- * Convert review issues to GitHub check run annotations
240
- */
241
- convertIssuesToAnnotations(reviewIssues) {
242
- return reviewIssues
243
- .slice(0, this.maxAnnotations) // Respect GitHub's annotation limit
244
- .map(issue => ({
245
- path: issue.file,
246
- start_line: issue.line,
247
- end_line: issue.endLine || issue.line,
248
- annotation_level: this.mapSeverityToAnnotationLevel(issue.severity),
249
- message: issue.message,
250
- title: `${issue.category} Issue`,
251
- raw_details: issue.suggestion || undefined,
252
- }));
253
- }
254
- /**
255
- * Map Visor issue severity to GitHub annotation level
256
- */
257
- mapSeverityToAnnotationLevel(severity) {
258
- switch (severity) {
259
- case 'critical':
260
- case 'error':
261
- return 'failure';
262
- case 'warning':
263
- return 'warning';
264
- case 'info':
265
- default:
266
- return 'notice';
267
- }
268
- }
269
- /**
270
- * Group issues by category
271
- */
272
- groupIssuesByCategory(issues) {
273
- const grouped = {};
274
- issues.forEach(issue => {
275
- const category = issue.category || 'general';
276
- if (!grouped[category]) {
277
- grouped[category] = [];
278
- }
279
- grouped[category].push(issue);
280
- });
281
- return grouped;
282
- }
283
- /**
284
- * Get emoji for issue category
285
- */
286
- getCategoryEmoji(category) {
287
- const emojiMap = {
288
- security: '🔐',
289
- performance: '⚡',
290
- style: '🎨',
291
- logic: '🧠',
292
- architecture: 'đŸ—ī¸',
293
- documentation: '📚',
294
- general: '📝',
295
- };
296
- return emojiMap[category.toLowerCase()] || '📝';
297
- }
298
- /**
299
- * Get icon for issue severity
300
- */
301
- getSeverityIcon(severity) {
302
- const iconMap = {
303
- critical: '🚨',
304
- error: '❌',
305
- warning: 'âš ī¸',
306
- info: 'â„šī¸',
307
- };
308
- return iconMap[severity.toLowerCase()] || 'â„šī¸';
309
- }
310
- /**
311
- * Create multiple check runs for different checks with failure condition support
312
- */
313
- async createMultipleCheckRuns(options, checkResults) {
314
- const results = [];
315
- for (const checkResult of checkResults) {
316
- try {
317
- // Create check run
318
- const checkRun = await this.createCheckRun({
319
- ...options,
320
- name: `Visor: ${checkResult.checkName}`,
321
- external_id: `visor-${checkResult.checkName}-${options.head_sha.substring(0, 7)}`,
322
- });
323
- // Update to in progress
324
- await this.updateCheckRunInProgress(options.owner, options.repo, checkRun.id, {
325
- title: `Running ${checkResult.checkName} check...`,
326
- summary: `Analyzing code with ${checkResult.checkName} check using AI.`,
327
- });
328
- // Complete with results
329
- await this.completeCheckRun(options.owner, options.repo, checkRun.id, checkResult.checkName, checkResult.failureResults, checkResult.reviewIssues, checkResult.executionError);
330
- results.push({
331
- checkName: checkResult.checkName,
332
- id: checkRun.id,
333
- url: checkRun.url,
334
- });
335
- }
336
- catch (error) {
337
- console.error(`Failed to create check run for ${checkResult.checkName}:`, error);
338
- // Continue with other checks even if one fails
339
- }
340
- }
341
- return results;
342
- }
343
- /**
344
- * Get check runs for a specific commit
345
- */
346
- async getCheckRuns(owner, repo, ref) {
347
- try {
348
- const response = await this.octokit.rest.checks.listForRef({
349
- owner,
350
- repo,
351
- ref,
352
- filter: 'all',
353
- });
354
- return response.data.check_runs
355
- .filter(check => check.name.startsWith('Visor:'))
356
- .map(check => ({
357
- id: check.id,
358
- name: check.name,
359
- status: check.status,
360
- conclusion: check.conclusion,
361
- }));
362
- }
363
- catch (error) {
364
- throw new Error(`Failed to get check runs: ${error instanceof Error ? error.message : String(error)}`);
365
- }
366
- }
367
- }
368
- exports.GitHubCheckService = GitHubCheckService;
369
- //# sourceMappingURL=github-check-service.js.map