@9apes/cli 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 (53) hide show
  1. package/README.md +145 -0
  2. package/dist/command.d.ts +8 -0
  3. package/dist/command.d.ts.map +1 -0
  4. package/dist/command.js +90 -0
  5. package/dist/command.js.map +1 -0
  6. package/dist/config.d.ts +7 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +37 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/index-dev.d.ts +3 -0
  11. package/dist/index-dev.d.ts.map +1 -0
  12. package/dist/index-dev.js +13 -0
  13. package/dist/index-dev.js.map +1 -0
  14. package/dist/index-local.d.ts +3 -0
  15. package/dist/index-local.d.ts.map +1 -0
  16. package/dist/index-local.js +13 -0
  17. package/dist/index-local.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +11 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/inject.d.ts +14 -0
  23. package/dist/inject.d.ts.map +1 -0
  24. package/dist/inject.js +161 -0
  25. package/dist/inject.js.map +1 -0
  26. package/dist/sourcemap.d.ts +48 -0
  27. package/dist/sourcemap.d.ts.map +1 -0
  28. package/dist/sourcemap.js +262 -0
  29. package/dist/sourcemap.js.map +1 -0
  30. package/dist/status.d.ts +17 -0
  31. package/dist/status.d.ts.map +1 -0
  32. package/dist/status.js +72 -0
  33. package/dist/status.js.map +1 -0
  34. package/dist/upload.d.ts +25 -0
  35. package/dist/upload.d.ts.map +1 -0
  36. package/dist/upload.js +119 -0
  37. package/dist/upload.js.map +1 -0
  38. package/dist/vite-plugin.d.ts +22 -0
  39. package/dist/vite-plugin.d.ts.map +1 -0
  40. package/dist/vite-plugin.js +95 -0
  41. package/dist/vite-plugin.js.map +1 -0
  42. package/package.json +61 -0
  43. package/src/command.ts +100 -0
  44. package/src/config.ts +44 -0
  45. package/src/index-dev.ts +16 -0
  46. package/src/index-local.ts +16 -0
  47. package/src/index.ts +12 -0
  48. package/src/inject.ts +195 -0
  49. package/src/sourcemap.ts +317 -0
  50. package/src/status.ts +94 -0
  51. package/src/upload.ts +190 -0
  52. package/src/vite-plugin.ts +160 -0
  53. package/tsconfig.json +30 -0
@@ -0,0 +1,262 @@
1
+ import { promises as fs } from 'fs';
2
+ import path from 'path';
3
+ import fg from 'fast-glob';
4
+ import { execFile } from 'child_process';
5
+ import { promisify } from 'util';
6
+ import { randomUUID } from 'crypto';
7
+ import pLimit from 'p-limit';
8
+ import { injectDebugIdIntoFile, injectDebugIdIntoMapFile } from './inject.js';
9
+ import { uploadFile } from './upload.js';
10
+ import { createStatusBars } from './status.js';
11
+ const execFileAsync = promisify(execFile);
12
+ /**
13
+ * Validate and resolve a directory path
14
+ * @param dirPath - Directory path to validate
15
+ * @returns Resolved absolute path
16
+ * @throws Error if path doesn't exist, isn't a directory, or lacks permissions
17
+ */
18
+ export async function validateDirectoryPath(dirPath) {
19
+ // Validate and resolve the directory path
20
+ const resolvedPath = path.resolve(dirPath);
21
+ console.log(`🔍 Resolved path: ${resolvedPath}`);
22
+ // Check if path exists and get stats
23
+ let stats;
24
+ try {
25
+ stats = await fs.stat(resolvedPath);
26
+ }
27
+ catch (error) {
28
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
29
+ throw new Error(`Directory does not exist: ${resolvedPath}`);
30
+ }
31
+ throw error;
32
+ }
33
+ // Verify it's a directory
34
+ if (!stats.isDirectory()) {
35
+ throw new Error(`Path is not a directory: ${resolvedPath}`);
36
+ }
37
+ // Check read and write permissions - Throws an error if the directory is not readable or writable
38
+ await fs.access(resolvedPath, fs.constants.R_OK | fs.constants.W_OK);
39
+ console.log(`✅ Directory validated: ${resolvedPath}`);
40
+ return resolvedPath;
41
+ }
42
+ /**
43
+ * Scan directory for JavaScript files and their corresponding source maps
44
+ * @param dirPath - Directory path to scan
45
+ * @returns Tuple containing file pairs with both .js and .js.map files, and JS files without maps
46
+ */
47
+ export async function scanForJavaScriptFiles(dirPath) {
48
+ try {
49
+ // Find all .js.map files directly
50
+ const [jsFiles, mapFiles] = await Promise.all([
51
+ fg('**/*.js', {
52
+ cwd: dirPath,
53
+ absolute: true,
54
+ ignore: ['**/node_modules/**', '**/.git/**', '**/.*/**']
55
+ }),
56
+ fg('**/*.js.map', {
57
+ cwd: dirPath,
58
+ absolute: true,
59
+ ignore: ['**/node_modules/**', '**/.git/**', '**/.*/**']
60
+ })
61
+ ]);
62
+ console.log(`🔍 Found ${jsFiles.length} JavaScript files`);
63
+ // Create a Set for O(1) lookup
64
+ const mapFileSet = new Set(mapFiles);
65
+ const results = [];
66
+ for (const jsFile of jsFiles) {
67
+ const mapFile = jsFile + '.map';
68
+ if (mapFileSet.has(mapFile)) {
69
+ results.push({ jsFile, mapFile });
70
+ }
71
+ else {
72
+ results.push({ jsFile, mapFile: null });
73
+ console.warn(`⚠️ ${path.relative(dirPath, jsFile)} has no corresponding .js.map file`);
74
+ }
75
+ }
76
+ console.log(`📊 Total file pairs found: ${results.length}`);
77
+ return results;
78
+ }
79
+ catch (error) {
80
+ console.error('❌ Error scanning for JavaScript files:', error);
81
+ throw error;
82
+ }
83
+ }
84
+ /**
85
+ * Get the current Git commit hash (HEAD)
86
+ * @param dirPath - Directory path to check for git repository
87
+ * @returns Git commit hash or undefined if not available
88
+ */
89
+ export async function getGitCommitHash(dirPath) {
90
+ try {
91
+ const { stdout } = await execFileAsync('git', ['rev-parse', 'HEAD'], {
92
+ cwd: dirPath,
93
+ encoding: 'utf8',
94
+ // maxBuffer: 1024 * 1024 // Optional: if you expect large output
95
+ });
96
+ const commitHash = stdout.trim();
97
+ console.log(`📝 Git commit hash: ${commitHash}`);
98
+ return commitHash;
99
+ }
100
+ catch {
101
+ console.log('ℹ️ No git commit hash available (not a git repository or no commits)');
102
+ return undefined;
103
+ }
104
+ }
105
+ /**
106
+ * Generate a unique debug ID using UUID v4
107
+ * @returns UUID string
108
+ */
109
+ export function generateDebugId() {
110
+ return randomUUID();
111
+ }
112
+ /**
113
+ * Get the debug ID snippet for the given debug ID
114
+ * @param debugId - Debug ID to get the snippet for
115
+ * @returns Debug ID snippet
116
+ */
117
+ export function getDebugIdSnippet(debugId) {
118
+ return `;{try{(function(){var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._apesDebugIds=e._apesDebugIds||{},e._apesDebugIds[n]="${debugId}",e._apesDebugIdIdentifier="apes-dbid-${debugId}");})();}catch(e){}};`;
119
+ }
120
+ /**
121
+ * Inject debug IDs into JavaScript files and their corresponding source maps
122
+ * @param dirPath - Directory path to process
123
+ * @param config - Configuration object containing API key
124
+ * @param projectId - Project ID (required)
125
+ * @param baseUrl - Base URL for the API
126
+ * @param releaseVersion - Release version (optional)
127
+ */
128
+ export async function injectDebugIdsAndUpload(dirPath, config, projectId, baseUrl, releaseVersion) {
129
+ try {
130
+ console.log(`📁 Processing directory: ${dirPath}`);
131
+ console.log(`🔑 Using API key: ${config.apiKey.substring(0, 8)}...`);
132
+ console.log(`🔑 Project ID: ${projectId}`);
133
+ if (releaseVersion) {
134
+ console.log(`📦 Release version: ${releaseVersion}`);
135
+ }
136
+ // Validate and resolve the directory path
137
+ const resolvedPath = await validateDirectoryPath(dirPath);
138
+ // Find all JavaScript and source map files, and get git commit hash concurrently
139
+ const [filePairs, commitHash] = await Promise.all([
140
+ scanForJavaScriptFiles(resolvedPath),
141
+ getGitCommitHash(resolvedPath)
142
+ ]);
143
+ if (filePairs.length === 0) {
144
+ console.log('ℹ️ No JavaScript files with corresponding source maps found');
145
+ return;
146
+ }
147
+ // Calculate total upload count (JS files + map files)
148
+ const totalUploadCount = filePairs.reduce((count, pair) => {
149
+ return count + 1 + (pair.mapFile ? 1 : 0);
150
+ }, 0);
151
+ // Create status bars
152
+ const statusBars = createStatusBars(filePairs.length, totalUploadCount);
153
+ // Setup concurrency limiters
154
+ const injectLimiter = pLimit(15);
155
+ const uploadLimiter = pLimit(10);
156
+ // Track progress counters
157
+ let injectCompleted = 0;
158
+ let injectFailed = 0;
159
+ let uploadCompleted = 0;
160
+ let uploadFailed = 0;
161
+ // Process files with concurrent injection and upload pipeline
162
+ const uploadPromises = [];
163
+ const allUploadErrors = [];
164
+ const injectionPromises = filePairs.map((filePair) => injectLimiter(async () => {
165
+ const debugId = generateDebugId();
166
+ try {
167
+ // Inject debugId into JavaScript file and source map file concurrently
168
+ await Promise.all([
169
+ injectDebugIdIntoFile(filePair.jsFile, getDebugIdSnippet(debugId), debugId),
170
+ injectDebugIdIntoMapFile(filePair.mapFile, debugId)
171
+ ]);
172
+ // Update progress after successful injection
173
+ injectCompleted++;
174
+ statusBars.updateInjectProgress(injectCompleted, injectFailed);
175
+ }
176
+ catch (error) {
177
+ // Update progress after failed injection
178
+ injectFailed++;
179
+ statusBars.updateInjectProgress(injectCompleted, injectFailed);
180
+ throw error;
181
+ }
182
+ // Immediately queue for upload (don't await here)
183
+ const uploadPromise = uploadLimiter(async () => {
184
+ try {
185
+ const errors = await uploadFile(filePair, debugId, config, projectId, baseUrl, releaseVersion, commitHash, (success) => {
186
+ if (success) {
187
+ uploadCompleted++;
188
+ }
189
+ else {
190
+ uploadFailed++;
191
+ }
192
+ statusBars.updateUploadProgress(uploadCompleted, uploadFailed);
193
+ });
194
+ return errors;
195
+ }
196
+ catch (error) {
197
+ // Handle unexpected errors - count failed uploads for this file pair
198
+ const uploadOpsCount = 1 + (filePair.mapFile ? 1 : 0);
199
+ uploadFailed += uploadOpsCount;
200
+ statusBars.updateUploadProgress(uploadCompleted, uploadFailed);
201
+ // Return a structured error for unexpected exceptions
202
+ return [{
203
+ fileName: path.basename(filePair.jsFile),
204
+ errorMessage: error instanceof Error ? error.message : String(error)
205
+ }];
206
+ }
207
+ });
208
+ uploadPromises.push(uploadPromise);
209
+ }));
210
+ try {
211
+ // Wait for all injections to complete
212
+ await Promise.all(injectionPromises);
213
+ // Wait for all uploads to complete and collect errors
214
+ const uploadResults = await Promise.allSettled(uploadPromises);
215
+ for (const result of uploadResults) {
216
+ if (result.status === 'fulfilled') {
217
+ allUploadErrors.push(...result.value);
218
+ }
219
+ else {
220
+ // Handle case where upload promise itself was rejected
221
+ allUploadErrors.push({
222
+ fileName: 'unknown',
223
+ errorMessage: result.reason instanceof Error ? result.reason.message : String(result.reason)
224
+ });
225
+ }
226
+ }
227
+ // Stop status bars
228
+ statusBars.stop();
229
+ // Print collated errors if any
230
+ if (allUploadErrors.length > 0) {
231
+ console.error('\n❌ Server Error Responses:');
232
+ console.error('═'.repeat(60));
233
+ for (const error of allUploadErrors) {
234
+ console.error(`\n📁 File: ${error.fileName}`);
235
+ if (error.statusCode) {
236
+ console.error(` Status Code: ${error.statusCode}`);
237
+ }
238
+ if (error.responseData) {
239
+ console.error(` Response Data: ${JSON.stringify(error.responseData, null, 2)}`);
240
+ }
241
+ console.error(` Error: ${error.errorMessage}`);
242
+ console.error('─'.repeat(60));
243
+ }
244
+ }
245
+ if (uploadFailed > 0) {
246
+ throw new Error(`${uploadFailed} upload${uploadFailed === 1 ? '' : 's'} failed`);
247
+ }
248
+ else {
249
+ console.log('✅ Debug ID injection completed successfully');
250
+ }
251
+ }
252
+ catch (error) {
253
+ statusBars.stop();
254
+ throw error;
255
+ }
256
+ }
257
+ catch (error) {
258
+ console.error('❌ Error during debug ID injection:', error);
259
+ throw error;
260
+ }
261
+ }
262
+ //# sourceMappingURL=sourcemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sourcemap.js","sourceRoot":"","sources":["../src/sourcemap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import cliProgress from 'cli-progress';
2
+ interface StatusBars {
3
+ injectBar: cliProgress.SingleBar;
4
+ uploadBar: cliProgress.SingleBar;
5
+ updateInjectProgress: (completed: number, failed: number) => void;
6
+ updateUploadProgress: (completed: number, failed: number) => void;
7
+ stop: () => void;
8
+ }
9
+ /**
10
+ * Create status bars for inject and upload operations
11
+ * @param injectTotal - Total number of file pairs to inject
12
+ * @param uploadTotal - Total number of files to upload
13
+ * @returns Object with update functions and stop function
14
+ */
15
+ export declare function createStatusBars(injectTotal: number, uploadTotal: number): StatusBars;
16
+ export {};
17
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,UAAU,UAAU;IAClB,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC;IACjC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC;IACjC,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,UAAU,CAyEZ"}
package/dist/status.js ADDED
@@ -0,0 +1,72 @@
1
+ import cliProgress from 'cli-progress';
2
+ /**
3
+ * Create status bars for inject and upload operations
4
+ * @param injectTotal - Total number of file pairs to inject
5
+ * @param uploadTotal - Total number of files to upload
6
+ * @returns Object with update functions and stop function
7
+ */
8
+ export function createStatusBars(injectTotal, uploadTotal) {
9
+ // Use MultiBar to display multiple progress bars simultaneously
10
+ const multiBar = new cliProgress.MultiBar({
11
+ clearOnComplete: false,
12
+ hideCursor: true,
13
+ format: '{label} [{bar}] {percentage}% | Completed: {completed}/{total} | Failed: {failed}',
14
+ barCompleteChar: '\u2588',
15
+ barIncompleteChar: '\u2591',
16
+ }, cliProgress.Presets.shades_classic);
17
+ const injectBar = multiBar.create(injectTotal, 0, {
18
+ label: 'Inject ',
19
+ completed: 0,
20
+ failed: 0,
21
+ total: injectTotal,
22
+ });
23
+ const uploadBar = multiBar.create(uploadTotal, 0, {
24
+ label: 'Upload ',
25
+ completed: 0,
26
+ failed: 0,
27
+ total: uploadTotal,
28
+ });
29
+ let injectCompleted = 0;
30
+ let injectFailed = 0;
31
+ let uploadCompleted = 0;
32
+ let uploadFailed = 0;
33
+ function updateInjectProgress(completed, failed) {
34
+ injectCompleted = completed;
35
+ injectFailed = failed;
36
+ injectBar.update(completed + failed, {
37
+ completed,
38
+ failed,
39
+ total: injectTotal,
40
+ });
41
+ }
42
+ function updateUploadProgress(completed, failed) {
43
+ uploadCompleted = completed;
44
+ uploadFailed = failed;
45
+ uploadBar.update(completed + failed, {
46
+ completed,
47
+ failed,
48
+ total: uploadTotal,
49
+ });
50
+ }
51
+ function stop() {
52
+ injectBar.update(injectTotal, {
53
+ completed: injectCompleted,
54
+ failed: injectFailed,
55
+ total: injectTotal,
56
+ });
57
+ uploadBar.update(uploadTotal, {
58
+ completed: uploadCompleted,
59
+ failed: uploadFailed,
60
+ total: uploadTotal,
61
+ });
62
+ multiBar.stop();
63
+ }
64
+ return {
65
+ injectBar,
66
+ uploadBar,
67
+ updateInjectProgress,
68
+ updateUploadProgress,
69
+ stop,
70
+ };
71
+ }
72
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,cAAc,CAAC;AAUvC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,WAAmB;IAEnB,gEAAgE;IAChE,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,QAAQ,CACvC;QACE,eAAe,EAAE,KAAK;QACtB,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,mFAAmF;QAC3F,eAAe,EAAE,QAAQ;QACzB,iBAAiB,EAAE,QAAQ;KAC5B,EACD,WAAW,CAAC,OAAO,CAAC,cAAc,CACnC,CAAC;IAEF,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE;QAChD,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,CAAC;QACZ,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,WAAW;KACnB,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE;QAChD,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,CAAC;QACZ,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,WAAW;KACnB,CAAC,CAAC;IAEH,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,SAAS,oBAAoB,CAAC,SAAiB,EAAE,MAAc;QAC7D,eAAe,GAAG,SAAS,CAAC;QAC5B,YAAY,GAAG,MAAM,CAAC;QACtB,SAAS,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,EAAE;YACnC,SAAS;YACT,MAAM;YACN,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;IAED,SAAS,oBAAoB,CAAC,SAAiB,EAAE,MAAc;QAC7D,eAAe,GAAG,SAAS,CAAC;QAC5B,YAAY,GAAG,MAAM,CAAC;QACtB,SAAS,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,EAAE;YACnC,SAAS;YACT,MAAM;YACN,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;IAED,SAAS,IAAI;QACX,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE;YAC5B,SAAS,EAAE,eAAe;YAC1B,MAAM,EAAE,YAAY;YACpB,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;QACH,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE;YAC5B,SAAS,EAAE,eAAe;YAC1B,MAAM,EAAE,YAAY;YACpB,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,EAAE,CAAC;IAClB,CAAC;IAED,OAAO;QACL,SAAS;QACT,SAAS;QACT,oBAAoB;QACpB,oBAAoB;QACpB,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { Config } from './config.js';
2
+ import type { FilePair } from './sourcemap.js';
3
+ /**
4
+ * Structured error information from server responses
5
+ */
6
+ export interface UploadError {
7
+ fileName: string;
8
+ statusCode?: number;
9
+ responseData?: any;
10
+ errorMessage: string;
11
+ }
12
+ /**
13
+ * Upload file via HTTP
14
+ * @param filePair - File pair containing JavaScript file and optional source map file
15
+ * @param debugId - Debug ID associated with the files
16
+ * @param config - Configuration object containing API key
17
+ * @param projectId - Project ID
18
+ * @param baseUrl - Base URL for the API
19
+ * @param releaseVersion - Optional release version
20
+ * @param commitHash - Optional git commit hash
21
+ * @param onProgress - Optional callback called on success or failure for each file
22
+ * @returns Array of UploadError objects for failed uploads
23
+ */
24
+ export declare function uploadFile(filePair: FilePair, debugId: string, config: Config, projectId: string, baseUrl: string, releaseVersion?: string, commitHash?: string, onProgress?: (success: boolean) => void): Promise<UploadError[]>;
25
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAwGD;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GACtC,OAAO,CAAC,WAAW,EAAE,CAAC,CAgDxB"}
package/dist/upload.js ADDED
@@ -0,0 +1,119 @@
1
+ import path from 'path';
2
+ import { promises as fs } from 'fs';
3
+ import axios from 'axios';
4
+ import { Agent } from 'http';
5
+ import FormData from 'form-data';
6
+ /**
7
+ * Create axios instance with connection pooling and configurable base URL
8
+ */
9
+ function createHttpClient(baseUrl) {
10
+ return axios.create({
11
+ baseURL: baseUrl,
12
+ timeout: 30000,
13
+ httpAgent: new Agent({
14
+ keepAlive: true,
15
+ maxSockets: 20,
16
+ maxFreeSockets: 5
17
+ })
18
+ });
19
+ }
20
+ /**
21
+ * Upload a single file with retry logic
22
+ * @param filePath - Path to the file to upload
23
+ * @param fileName - Name of the file for logging
24
+ * @param debugId - Debug ID associated with the file
25
+ * @param config - Configuration object containing API key
26
+ * @param projectId - Project ID
27
+ * @param httpClient - Axios instance to use for HTTP requests
28
+ * @param releaseVersion - Optional release version
29
+ * @param commitHash - Optional git commit hash
30
+ * @param maxRetries - Maximum number of retry attempts
31
+ * @param onProgress - Optional callback called on success or failure
32
+ * @returns UploadError if all retries failed, undefined on success
33
+ */
34
+ async function uploadSingleFile(filePath, fileName, debugId, config, projectId, httpClient, releaseVersion, commitHash, maxRetries = 3, onProgress) {
35
+ let lastError = null;
36
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
37
+ try {
38
+ // Read file as buffer
39
+ const fileBuffer = await fs.readFile(filePath);
40
+ // Create FormData
41
+ const formData = new FormData();
42
+ formData.append('file', fileBuffer, fileName);
43
+ formData.append('project_id', projectId);
44
+ formData.append('debug_id', debugId);
45
+ if (releaseVersion) {
46
+ formData.append('release_version', releaseVersion);
47
+ }
48
+ if (commitHash) {
49
+ formData.append('commit_hash', commitHash);
50
+ }
51
+ // Make the request
52
+ await httpClient.post('/sourcemaps/upload', formData, {
53
+ headers: {
54
+ ...formData.getHeaders(),
55
+ 'X-API-Key': config.apiKey
56
+ }
57
+ });
58
+ onProgress?.(true);
59
+ return undefined; // Success, exit retry loop
60
+ }
61
+ catch (error) {
62
+ // Extract structured error information from axios error
63
+ if (axios.isAxiosError(error)) {
64
+ const axiosError = error;
65
+ lastError = {
66
+ fileName,
67
+ statusCode: axiosError.response?.status,
68
+ responseData: axiosError.response?.data,
69
+ errorMessage: axiosError.message
70
+ };
71
+ }
72
+ else {
73
+ lastError = {
74
+ fileName,
75
+ errorMessage: error instanceof Error ? error.message : String(error)
76
+ };
77
+ }
78
+ if (attempt < maxRetries) {
79
+ // Wait a bit before retrying (simple delay, no exponential backoff as requested)
80
+ await new Promise(resolve => setTimeout(resolve, 1000));
81
+ }
82
+ }
83
+ }
84
+ // If we get here, all retries failed
85
+ onProgress?.(false);
86
+ return lastError;
87
+ }
88
+ /**
89
+ * Upload file via HTTP
90
+ * @param filePair - File pair containing JavaScript file and optional source map file
91
+ * @param debugId - Debug ID associated with the files
92
+ * @param config - Configuration object containing API key
93
+ * @param projectId - Project ID
94
+ * @param baseUrl - Base URL for the API
95
+ * @param releaseVersion - Optional release version
96
+ * @param commitHash - Optional git commit hash
97
+ * @param onProgress - Optional callback called on success or failure for each file
98
+ * @returns Array of UploadError objects for failed uploads
99
+ */
100
+ export async function uploadFile(filePair, debugId, config, projectId, baseUrl, releaseVersion, commitHash, onProgress) {
101
+ const httpClient = createHttpClient(baseUrl);
102
+ const uploadPromises = [];
103
+ const errors = [];
104
+ // Upload JS file
105
+ uploadPromises.push(uploadSingleFile(filePair.jsFile, path.basename(filePair.jsFile), debugId, config, projectId, httpClient, releaseVersion, commitHash, 3, onProgress));
106
+ // Upload map file if it exists
107
+ if (filePair.mapFile) {
108
+ uploadPromises.push(uploadSingleFile(filePair.mapFile, path.basename(filePair.mapFile), debugId, config, projectId, httpClient, releaseVersion, commitHash, 3, onProgress));
109
+ }
110
+ // Wait for both uploads to complete and collect errors
111
+ const results = await Promise.allSettled(uploadPromises);
112
+ for (const result of results) {
113
+ if (result.status === 'fulfilled' && result.value !== undefined) {
114
+ errors.push(result.value);
115
+ }
116
+ }
117
+ return errors;
118
+ }
119
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface NineapesSourcemapsOptions {
2
+ projectId: string;
3
+ apiKey: string;
4
+ baseUrl?: string;
5
+ releaseVersion?: string;
6
+ }
7
+ interface BuildConfigLike {
8
+ outDir: string;
9
+ }
10
+ interface ResolvedConfigLike {
11
+ root: string;
12
+ build: BuildConfigLike;
13
+ }
14
+ interface VitePluginLike {
15
+ name: string;
16
+ apply?: 'build';
17
+ configResolved?: (config: ResolvedConfigLike) => void;
18
+ closeBundle?: () => Promise<void>;
19
+ }
20
+ export declare function withNineapesSourcemaps(options: NineapesSourcemapsOptions): VitePluginLike;
21
+ export {};
22
+ //# sourceMappingURL=vite-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAID,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtD,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,yBAAyB,GAAG,cAAc,CA0HzF"}
@@ -0,0 +1,95 @@
1
+ import path from 'path';
2
+ import pLimit from 'p-limit';
3
+ import { injectDebugIdIntoFile, injectDebugIdIntoMapFile } from './inject.js';
4
+ import { generateDebugId, getDebugIdSnippet, getGitCommitHash, scanForJavaScriptFiles, validateDirectoryPath, } from './sourcemap.js';
5
+ import { uploadFile } from './upload.js';
6
+ const DEFAULT_BASE_URL = 'https://dev.nineapes.com/api/v1';
7
+ export function withNineapesSourcemaps(options) {
8
+ let resolvedConfig = null;
9
+ return {
10
+ name: 'nineapes-sourcemaps',
11
+ apply: 'build',
12
+ configResolved(config) {
13
+ resolvedConfig = config;
14
+ },
15
+ async closeBundle() {
16
+ if (!resolvedConfig) {
17
+ throw new Error('Vite config is not resolved');
18
+ }
19
+ const outDir = path.resolve(resolvedConfig.root, resolvedConfig.build.outDir);
20
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
21
+ console.log(`[nineapes-sourcemaps] Processing output directory: ${outDir}`);
22
+ const resolvedPath = await validateDirectoryPath(outDir);
23
+ const [filePairs, commitHash] = await Promise.all([
24
+ scanForJavaScriptFiles(resolvedPath),
25
+ getGitCommitHash(resolvedPath),
26
+ ]);
27
+ if (filePairs.length === 0) {
28
+ console.log('[nineapes-sourcemaps] No JavaScript files found, skipping sourcemap upload');
29
+ return;
30
+ }
31
+ const totalUploadCount = filePairs.reduce((count, pair) => {
32
+ return count + 1 + (pair.mapFile ? 1 : 0);
33
+ }, 0);
34
+ const injectLimiter = pLimit(15);
35
+ const uploadLimiter = pLimit(10);
36
+ let injectCompleted = 0;
37
+ let injectFailed = 0;
38
+ let uploadCompleted = 0;
39
+ let uploadFailed = 0;
40
+ const uploadPromises = [];
41
+ const injectionResults = await Promise.allSettled(filePairs.map((filePair) => injectLimiter(async () => {
42
+ const debugId = generateDebugId();
43
+ await Promise.all([
44
+ injectDebugIdIntoFile(filePair.jsFile, getDebugIdSnippet(debugId), debugId),
45
+ injectDebugIdIntoMapFile(filePair.mapFile, debugId),
46
+ ]);
47
+ injectCompleted++;
48
+ const uploadPromise = uploadLimiter(async () => uploadFile(filePair, debugId, { apiKey: options.apiKey }, options.projectId, baseUrl, options.releaseVersion, commitHash, (success) => {
49
+ if (success) {
50
+ uploadCompleted++;
51
+ }
52
+ else {
53
+ uploadFailed++;
54
+ }
55
+ }));
56
+ uploadPromises.push(uploadPromise);
57
+ })));
58
+ const injectionErrors = [];
59
+ for (const result of injectionResults) {
60
+ if (result.status === 'rejected') {
61
+ injectFailed++;
62
+ const message = result.reason instanceof Error ? result.reason.message : String(result.reason);
63
+ injectionErrors.push(message);
64
+ }
65
+ }
66
+ if (injectionErrors.length > 0) {
67
+ throw new Error(`[nineapes-sourcemaps] Injection failed for ${injectFailed} file(s): ${injectionErrors.join('\n')}`);
68
+ }
69
+ const uploadResults = await Promise.allSettled(uploadPromises);
70
+ const uploadErrors = [];
71
+ for (const result of uploadResults) {
72
+ if (result.status === 'fulfilled') {
73
+ uploadErrors.push(...result.value);
74
+ }
75
+ else {
76
+ uploadErrors.push({
77
+ fileName: 'unknown',
78
+ errorMessage: result.reason instanceof Error ? result.reason.message : String(result.reason),
79
+ });
80
+ }
81
+ }
82
+ if (uploadErrors.length > 0) {
83
+ const formattedErrors = uploadErrors
84
+ .map((error) => {
85
+ const code = error.statusCode ? ` status=${error.statusCode}` : '';
86
+ return `- ${error.fileName}${code}: ${error.errorMessage}`;
87
+ })
88
+ .join('\n');
89
+ throw new Error(`[nineapes-sourcemaps] Upload failed:\n${formattedErrors}`);
90
+ }
91
+ console.log(`[nineapes-sourcemaps] Done. Injected ${injectCompleted} file pair(s), uploaded ${uploadCompleted}/${totalUploadCount} file(s)`);
92
+ },
93
+ };
94
+ }
95
+ //# sourceMappingURL=vite-plugin.js.map