Skip to content

Commit aafb6e7

Browse files
authored
Removes dependency on node.js core modules (#35)
* Removes dependency on node.js core modules Fixes #34 * Removed fs redefinition
1 parent 72435a6 commit aafb6e7

File tree

6 files changed

+43
-90
lines changed

6 files changed

+43
-90
lines changed

src/symbols/exists.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/symbols/s3-api-client/s3-api-client.spec.ts

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,64 @@
1-
import * as ExistsModule from '../exists';
21
import { S3ApiClient } from './s3-api-client';
32

43
describe('S3ApiClient', () => {
54
describe('uploadFileToPresignedUrl', () => {
6-
let s3ApiClient;
7-
let fakeReadStream;
5+
let s3ApiClient: S3ApiClient;
86
let fakeSuccessResponse;
97

108
beforeEach(() => {
11-
fakeReadStream = '🦦';
129
fakeSuccessResponse = { status: 200 };
13-
spyOn(ExistsModule, 'exists').and.returnValue(true);
1410
s3ApiClient = new S3ApiClient();
15-
s3ApiClient._fs = jasmine.createSpyObj('fs', ['createReadStream']);
16-
s3ApiClient._fs.createReadStream.and.returnValue(fakeReadStream);
17-
s3ApiClient._fetch = jasmine.createSpy();
18-
s3ApiClient._fetch.and.resolveTo(fakeSuccessResponse);
19-
});
20-
21-
it('should throw if file does not exist', async () => {
22-
const path = '/file/not/found';
23-
(<jasmine.Spy>ExistsModule.exists).and.returnValue(false);
24-
await expectAsync(s3ApiClient.uploadFileToPresignedUrl('url', path)).toBeRejectedWithError(`File does not exist at path: ${path}!`);
11+
(s3ApiClient as any)._fetch = jasmine.createSpy();
12+
(s3ApiClient as any)._fetch.and.resolveTo(fakeSuccessResponse);
2513
});
2614

2715
it('should call fetch with presignedUrl', async () => {
2816
const url = 'https://bugsplat.com';
29-
const path = '/some/fake/path';
17+
const file = '🐛.txt' as any;
3018

31-
await s3ApiClient.uploadFileToPresignedUrl(url, path);
19+
await s3ApiClient.uploadFileToPresignedUrl(url, file, 1);
3220

33-
expect(s3ApiClient._fetch).toHaveBeenCalledWith(url, jasmine.anything());
21+
expect((s3ApiClient as any)._fetch).toHaveBeenCalledWith(url, jasmine.anything());
3422
});
3523

3624
it('should call fetch with init containing method and headers', async () => {
3725
const url = 'https://bugsplat.com';
38-
const path = '/some/fake/path';
26+
const file = '🐛.txt' as any;
3927
const size = 1337;
4028

41-
await s3ApiClient.uploadFileToPresignedUrl(url, path, size);
29+
await s3ApiClient.uploadFileToPresignedUrl(url, file, size);
4230

43-
expect(s3ApiClient._fetch).toHaveBeenCalledWith(
31+
expect((s3ApiClient as any)._fetch).toHaveBeenCalledWith(
4432
jasmine.anything(),
4533
jasmine.objectContaining({
4634
method: 'PUT',
4735
headers: {
4836
'content-type': 'application/octet-stream',
4937
'content-length': `${size}`
5038
},
51-
body: fakeReadStream
39+
body: file
5240
})
5341
);
5442
});
5543

5644
it('should return response', async () => {
5745
const url = 'https://bugsplat.com';
58-
const path = '/some/fake/path';
46+
const file = '🐛.txt' as any;
5947
const size = 1337;
6048

61-
const response = await s3ApiClient.uploadFileToPresignedUrl(url, path, size);
49+
const response = await s3ApiClient.uploadFileToPresignedUrl(url, file, size);
6250

6351
expect(response).toEqual(fakeSuccessResponse);
6452
});
6553

6654
describe('error', () => {
6755
it('should throw if response status is not 200', async () => {
6856
const url = 'https://bugsplat.com';
69-
const path = '/some/fake/path';
57+
const file = '🐛.txt' as any;
7058
const size = 1337;
71-
s3ApiClient._fetch.and.resolveTo({ status: 500 });
59+
(s3ApiClient as any)._fetch.and.resolveTo({ status: 500 });
7260

73-
await expectAsync(s3ApiClient.uploadFileToPresignedUrl(url, path, size)).toBeRejectedWithError(`Error uploading ${path} to presignedUrl`);
61+
await expectAsync(s3ApiClient.uploadFileToPresignedUrl(url, file, size)).toBeRejectedWithError(`Error uploading to presignedUrl ${url}`);
7462
});
7563
});
7664
});

src/symbols/s3-api-client/s3-api-client.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
import fetchPonyfill from 'fetch-ponyfill';
2-
import fs from 'fs';
3-
import { exists } from '../exists';
2+
import type fs from 'fs';
43

54
export class S3ApiClient {
65

76
private _fetch = fetchPonyfill().fetch;
8-
private _fs = fs;
9-
10-
async uploadFileToPresignedUrl(presignedUrl: string, file: string, size: number): Promise<Response> {
11-
if (!exists(file)) {
12-
throw new Error(`File does not exist at path: ${file}!`);
13-
}
14-
7+
async uploadFileToPresignedUrl(presignedUrl: string, file: File | fs.ReadStream, size: number): Promise<Response> {
158
const response = await this._fetch(presignedUrl, {
169
method: 'PUT',
1710
headers: {
1811
'content-type': 'application/octet-stream',
1912
'content-length': `${size}`
2013
},
21-
body: <any>this._fs.createReadStream(file),
14+
body: file as BodyInit
2215
});
2316

2417
if (response.status !== 200) {
25-
throw new Error(`Error uploading ${file} to presignedUrl`);
18+
throw new Error(`Error uploading to presignedUrl ${presignedUrl}`);
2619
}
2720

2821
return response;

src/symbols/symbols-api-client/symbols-api-client.e2e.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import fs from "fs";
2+
import path from 'path';
13
import { config } from "../../../spec/config";
24
import { BugSplatApiClient } from "../../common";
35
import { SymbolsApiClient } from "./symbols-api-client";
@@ -32,7 +34,14 @@ describe('SymbolsApiClient', () => {
3234

3335
describe('post', () => {
3436
it('should return 200 for post with valid database, application, version and files', async () => {
35-
const file = './dist/cjs/index.js.map';
37+
const filePath = './dist/cjs/index.js.map';
38+
const name = path.basename(filePath);
39+
const size = fs.statSync(filePath).size;
40+
const file = {
41+
name,
42+
size,
43+
file: fs.createReadStream(filePath)
44+
};
3645
const response = await client.post(
3746
database,
3847
application,

src/symbols/symbols-api-client/symbols-api-client.spec.ts

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import path from 'path';
33
import { createFakeBugSplatApiClient } from '../../../spec/fakes/common/bugsplat-api-client';
44
import { createFakeFormData } from '../../../spec/fakes/common/form-data';
55
import { createFakeResponseBody } from '../../../spec/fakes/common/response';
6-
import * as ExistsModule from '../exists';
76
import { SymbolsApiClient } from './symbols-api-client';
87
import * as S3ApiClientModule from '../s3-api-client/s3-api-client';
98
import { of } from 'rxjs';
@@ -87,22 +86,17 @@ describe('SymbolsApiClient', () => {
8786
let fakeS3ApiClient;
8887
let files;
8988
let result;
90-
let stat;
91-
let size;
9289
let timer;
9390

9491
beforeEach(async () => {
95-
files = ['file/📄'];
96-
size = 1337;
97-
stat = jasmine.createSpy();
98-
stat.and.returnValue({ size });
92+
files = [{
93+
name: '📄.sym',
94+
size: 1337
95+
}];
9996
timer = jasmine.createSpy();
10097
timer.and.returnValue(of(0));
101-
(<any>symbolsApiClient)._stat = stat;
10298
(<any>symbolsApiClient)._timer = timer;
10399

104-
spyOn(ExistsModule, 'exists').and.returnValue(true);
105-
106100
fakeS3ApiClient = jasmine.createSpyObj('S3ApiClient', ['uploadFileToPresignedUrl']);
107101
fakeS3ApiClient.uploadFileToPresignedUrl.and.resolveTo(fakeSuccessResponse);
108102
spyOn(S3ApiClientModule, 'S3ApiClient').and.returnValue(fakeS3ApiClient);
@@ -115,23 +109,12 @@ describe('SymbolsApiClient', () => {
115109
);
116110
});
117111

118-
it('should throw if file does not exist', async () => {
119-
(<jasmine.Spy>ExistsModule.exists).and.returnValue(false);
120-
121-
await expectAsync(symbolsApiClient.post(
122-
database,
123-
application,
124-
version,
125-
files
126-
)).toBeRejectedWithError(`File does not exist at path: ${files[0]}!`);
127-
});
128-
129112
it('should append dbName, appName, appVersion, size and symFileName to FormData', () => {
130113
expect(fakeFormData.append).toHaveBeenCalledWith('dbName', database);
131114
expect(fakeFormData.append).toHaveBeenCalledWith('appName', application);
132115
expect(fakeFormData.append).toHaveBeenCalledWith('appVersion', version);
133-
expect(fakeFormData.append).toHaveBeenCalledWith('size', size.toString());
134-
expect(fakeFormData.append).toHaveBeenCalledWith('symFileName', path.basename(files[0]));
116+
expect(fakeFormData.append).toHaveBeenCalledWith('size', files[0].size.toString());
117+
expect(fakeFormData.append).toHaveBeenCalledWith('symFileName', path.basename(files[0].name));
135118
});
136119

137120
it('should call fetch with correct route', () => {
@@ -153,7 +136,7 @@ describe('SymbolsApiClient', () => {
153136
});
154137

155138
it('should call uploadFileToPresignedUrl with url, file and size', () => {
156-
expect(fakeS3ApiClient.uploadFileToPresignedUrl).toHaveBeenCalledWith(url, files[0], size);
139+
expect(fakeS3ApiClient.uploadFileToPresignedUrl).toHaveBeenCalledWith(url, files[0].file, files[0].size);
157140
});
158141

159142
it('should sleep between requests', () => {
@@ -176,7 +159,7 @@ describe('SymbolsApiClient', () => {
176159
application,
177160
version,
178161
files
179-
)).toBeRejectedWithError(`Error getting presignedUrl for ${path.basename(files[0])}`);
162+
)).toBeRejectedWithError(`Error getting presignedUrl for ${files[0].name}`);
180163
});
181164

182165
it('should throw if response json Status is \'Failed\'', async () => {

src/symbols/symbols-api-client/symbols-api-client.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
import fs from 'fs';
2-
import path from 'path';
1+
import type fs from 'fs';
32
import { lastValueFrom, timer } from 'rxjs';
4-
import util from 'util';
53
import { ApiClient, BugSplatResponse } from '../../common';
6-
import { exists } from '../exists';
74
import { S3ApiClient } from '../s3-api-client/s3-api-client';
8-
const stat = util.promisify(fs.stat);
95

106
export class SymbolsApiClient {
117

128
private readonly route = '/api/symbols';
13-
private _stat = stat;
9+
1410
private _timer = timer;
1511

1612
constructor(private _client: ApiClient) { }
@@ -45,17 +41,12 @@ export class SymbolsApiClient {
4541
database: string,
4642
application: string,
4743
version: string,
48-
files: Array<string>
44+
files: Array<{ name: string, size: number, file: File | fs.ReadStream }>
4945
): Promise<Array<BugSplatResponse>> {
5046
const promises = files
5147
.map(async (file) => {
52-
if (!exists(file)) {
53-
throw new Error(`File does not exist at path: ${file}!`);
54-
}
55-
56-
const stats = await this._stat(file);
57-
const size = stats.size;
58-
const name = path.basename(file);
48+
const name = file.name;
49+
const size = file.size;
5950
const presignedUrl = await this.getPresignedUrl(
6051
database,
6152
application,
@@ -65,7 +56,7 @@ export class SymbolsApiClient {
6556
);
6657

6758
const s3Client = new S3ApiClient();
68-
const response = s3Client.uploadFileToPresignedUrl(presignedUrl, file, size);
59+
const response = s3Client.uploadFileToPresignedUrl(presignedUrl, file.file, size);
6960
await lastValueFrom(this._timer(1000));
7061

7162
return response;

0 commit comments

Comments
 (0)