Skip to content

Commit e26c066

Browse files
authored
feat!: s3 symserv upload support (#112)
* feat: upload via spdbsv2 * fix: export symbols client * chore: add tests and refactor BREAKING CHANGE: drop support for fs.ReadableStream, as it's not browser-compatible. Use ReadStream.toWeb(...) to convert to web-compatible ReadableStream.
1 parent 47ffc89 commit e26c066

20 files changed

+407
-33
lines changed

spec/fakes/common/bugsplat-api-client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { ApiClient } from '@common';
2+
13
export function createFakeBugSplatApiClient(
24
formData: FormData,
35
response: any
4-
): any {
6+
): jasmine.SpyObj<ApiClient> {
57
const fakeBugSplatApiClient = jasmine.createSpyObj('BugSplatApiClient', [
68
'createFormData',
79
'fetch'

spec/files/create-bugsplat-file.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { UploadableFile } from '@common';
2-
import fs, { statSync } from 'fs';
3-
import path from 'path';
2+
import { createReadStream, ReadStream } from 'node:fs';
3+
import { stat } from 'node:fs/promises';
4+
import { basename } from 'node:path';
45

5-
export function createUploadableFile(filePath: string): UploadableFile {
6-
const fileSize = statSync(filePath).size;
7-
const fileName = path.basename(filePath);
8-
return new UploadableFile(fileName, fileSize, fs.createReadStream(filePath));
6+
export async function createUploadableFile(filePath: string): Promise<UploadableFile> {
7+
const fileSize = await stat(filePath).then(stats => stats.size);
8+
const fileName = basename(filePath);
9+
const readableStream = ReadStream.toWeb(createReadStream(filePath));
10+
return new UploadableFile(fileName, fileSize, readableStream);
911
}

spec/files/create-symbol-file.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { SymbolFile } from '@common';
2+
import { stat } from 'node:fs/promises';
3+
import { createUploadableFile } from './create-bugsplat-file';
4+
5+
export async function createSymbolFile(path: string): Promise<SymbolFile> {
6+
const uploadableFile = await createUploadableFile(path);
7+
const uncompressedSize = await stat(path).then(stats => stats.size);
8+
return {
9+
...uploadableFile,
10+
uncompressedSize
11+
};
12+
}

spec/files/native/post-native-crash.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ import { VersionsApiClient } from '@versions';
55
import { firstValueFrom, timer } from 'rxjs';
66
import { PostCrashResponse } from 'src/post/post-crash-response';
77
import { createUploadableFile } from '../create-bugsplat-file';
8+
import { createSymbolFile } from '../create-symbol-file';
89

910
export async function postNativeCrashAndSymbols(
1011
authenticatedClient: BugSplatApiClient,
1112
database: string,
1213
application: string,
1314
version: string
1415
): Promise<PostCrashResponse> {
15-
const exeFile = createUploadableFile('./spec/files/native/myConsoleCrasher.exe');
16-
const pdbFile = createUploadableFile('./spec/files/native/myConsoleCrasher.pdb');
16+
const exeFile = await createSymbolFile('./spec/files/native/myConsoleCrasher.exe');
17+
const pdbFile = await createSymbolFile('./spec/files/native/myConsoleCrasher.pdb');
1718
const files = [exeFile, pdbFile];
1819
const symbolsApiClient = new VersionsApiClient(authenticatedClient);
1920
await symbolsApiClient.postSymbols(
@@ -31,7 +32,7 @@ export async function postNativeCrash(
3132
application: string,
3233
version: string
3334
): Promise<PostCrashResponse> {
34-
const crashFile = createUploadableFile('./spec/files/native/myConsoleCrasher.zip');
35+
const crashFile = await createUploadableFile('./spec/files/native/myConsoleCrasher.zip');
3536
const crashPostClient = new CrashPostClient(database);
3637
await firstValueFrom(timer(2000)); // Prevent rate-limiting
3738
const postCrashResult = await crashPostClient.postCrash(
@@ -81,4 +82,4 @@ export async function postNativeCrashAndWaitForCrashToProcess(
8182
crashId,
8283
stackKeyId
8384
};
84-
}
85+
}

src/common/file/bugsplat-file.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import type fs from 'fs';
1+
import type { ReadableStream } from 'node:stream/web';
22

33
export class UploadableFile {
44
constructor(
55
public readonly name: string,
66
public readonly size: number,
7-
public readonly file: File | fs.ReadStream | Buffer
7+
public readonly file: File | Buffer | ReadableStream
88
) { }
99
}

src/common/file/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { UploadableFile } from './bugsplat-file';
2+
export { GZippedSymbolFile, SymbolFile } from './symbol-file';

src/common/file/symbol-file.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { UploadableFile } from '@common';
2+
import type { ReadableStream } from 'node:stream/web';
3+
4+
export type SymbolFile = UploadableFile & { dbgId?: string, lastModified?: Date, moduleName?: string, uncompressedSize: number };
5+
export type GZippedSymbolFile = Omit<Required<SymbolFile>, 'file'> & { file: ReadableStream };

src/common/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './client';
22
export * from './data';
3-
export { bugsplatAppHostUrl } from './host';
4-
export { UploadableFile } from './file/bugsplat-file';
53
export { Environment } from './environment';
4+
export * from './file';
5+
export { bugsplatAppHostUrl } from './host';
6+

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export * from './crashes';
44
export * from './events';
55
export * from './post';
66
export * from './summary';
7-
export * from './versions';
7+
export * from './versions';
8+
export * from './symbols';

src/post/crash-post-client.e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('CrashPostClient', () => {
1111
const application = 'myConsoleCrasher';
1212
const version = `${Math.random() * 1000000}`;
1313
const md5 = 'ebe24c1cd1a0912904658fa4fad2b539';
14-
const crashFile = createUploadableFile('spec/files/native/myConsoleCrasher.zip');
14+
const crashFile = await createUploadableFile('spec/files/native/myConsoleCrasher.zip');
1515
const crashPostClient = new CrashPostClient(config.database);
1616
const result = await crashPostClient.postCrash(
1717
application,

0 commit comments

Comments
 (0)