Skip to content

Commit 861edce

Browse files
committed
Fix lint errors.
1 parent 785e906 commit 861edce

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

packages/functions/src/callable.test.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,8 @@ describe('Firebase Functions > Call', () => {
107107
long: 420
108108
});
109109
} catch (err) {
110-
console.error(err)
110+
console.error(err);
111111
}
112-
113112
});
114113

115114
it('scalars', async () => {
@@ -325,7 +324,7 @@ describe('Firebase Functions > Stream', () => {
325324

326325
afterEach(() => {
327326
mockFetch.restore();
328-
})
327+
});
329328

330329
it('successfully streams data and resolves final result', async () => {
331330
const mockResponse = new ReadableStream({
@@ -356,6 +355,34 @@ describe('Firebase Functions > Stream', () => {
356355
expect(await streamResult.data).to.equal('Final Result');
357356
});
358357

358+
it('successfully process request chunk with multiple events', async () => {
359+
const mockResponse = new ReadableStream({
360+
start(controller) {
361+
controller.enqueue(new TextEncoder().encode('data: {"message":"Hello"}\n\ndata: {"message":"World"}\n'));
362+
controller.enqueue(new TextEncoder().encode('data: {"result":"Final Result"}\n'));
363+
controller.close();
364+
}
365+
});
366+
367+
mockFetch.resolves({
368+
body: mockResponse,
369+
headers: new Headers({ 'Content-Type': 'text/event-stream' }),
370+
status: 200,
371+
statusText: 'OK',
372+
} as Response);
373+
374+
const func = httpsCallable<Record<string, any>, string, string>(functions, 'streamTest');
375+
const streamResult = await func.stream({});
376+
377+
const messages: string[] = [];
378+
for await (const message of streamResult.stream) {
379+
messages.push(message);
380+
}
381+
382+
expect(messages).to.deep.equal(['Hello', 'World']);
383+
expect(await streamResult.data).to.equal('Final Result');
384+
});
385+
359386
it('handles network errors', async () => {
360387
mockFetch.rejects(new Error('Network error'));
361388

@@ -372,7 +399,7 @@ describe('Firebase Functions > Stream', () => {
372399
expect((error as FunctionsError).code).to.equal(`${FUNCTIONS_TYPE}/internal`);
373400
}
374401
expect(errorThrown).to.be.true;
375-
expectError(streamResult.data, "internal", "Internal");
402+
await expectError(streamResult.data, "internal", "Internal");
376403
});
377404

378405
it('handles server-side errors', async () => {
@@ -405,7 +432,7 @@ describe('Firebase Functions > Stream', () => {
405432
}
406433

407434
expect(errorThrown).to.be.true;
408-
expectError(streamResult.data, "invalid-argument", "Invalid input")
435+
await expectError(streamResult.data, "invalid-argument", "Invalid input");
409436
});
410437

411438
it('includes authentication and app check tokens in request headers', async () => {
@@ -497,7 +524,7 @@ describe('Firebase Functions > Stream', () => {
497524
expect((error as FunctionsError).code).to.equal(`${FUNCTIONS_TYPE}/cancelled`);
498525
}
499526
expect(errorThrown).to.be.true;
500-
expectError(streamResult.data, "cancelled", "Request was cancelled")
527+
await expectError(streamResult.data, "cancelled", "Request was cancelled");
501528
});
502529

503530
it('aborts during streaming', async () => {
@@ -539,7 +566,7 @@ describe('Firebase Functions > Stream', () => {
539566
expect((error as FunctionsError).code).to.equal(`${FUNCTIONS_TYPE}/cancelled`);
540567
}
541568
expect(messages).to.deep.equal(['First']);
542-
expectError(streamResult.data, "cancelled", "Request was cancelled")
569+
await expectError(streamResult.data, "cancelled", "Request was cancelled");
543570
});
544571

545572
it('fails immediately with pre-aborted signal', async () => {
@@ -564,7 +591,7 @@ describe('Firebase Functions > Stream', () => {
564591
expect((error as FunctionsError).code).to.equal(`${FUNCTIONS_TYPE}/cancelled`);
565592
}
566593
expect(errorThrown).to.be.true;
567-
expectError(streamResult.data, "cancelled", "Request was cancelled")
594+
await expectError(streamResult.data, "cancelled", "Request was cancelled");
568595
});
569596

570597
it('properly handles AbortSignal.timeout()', async () => {
@@ -589,13 +616,13 @@ describe('Firebase Functions > Stream', () => {
589616
const streamResult = await func.stream({}, { signal });
590617

591618
try {
592-
for await (const message of streamResult.stream) {
619+
for await (const _ of streamResult.stream) {
593620
// Should not execute
594621
}
595622
throw new Error('Stream should have timed out');
596623
} catch (error) {
597624
expect((error as FunctionsError).code).to.equal(`${FUNCTIONS_TYPE}/cancelled`);
598625
}
599-
expectError(streamResult.data, "cancelled", "Request was cancelled")
626+
await expectError(streamResult.data, "cancelled", "Request was cancelled");
600627
});
601628
});

packages/functions/src/public-types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ export interface HttpsCallableStreamResult<ResponseData = unknown, StreamData =
4141
* @param data - Data to be passed to callable function.
4242
* @public
4343
*/
44-
export type HttpsCallable<RequestData = unknown, ResponseData = unknown, StreamData = unknown> = {
44+
export interface HttpsCallable<RequestData = unknown, ResponseData = unknown, StreamData = unknown> {
4545
(data?: RequestData | null): Promise<HttpsCallableResult<ResponseData>>;
4646
stream: (data?: RequestData | null, options?: HttpsCallableStreamOptions) => Promise<HttpsCallableStreamResult<ResponseData, StreamData>>;
47-
};
47+
}
4848

4949
/**
5050
* An interface for metadata about how calls should be executed.

packages/functions/src/service.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export function httpsCallable<RequestData, ResponseData, StreamData = unknown>(
184184
name: string,
185185
options?: HttpsCallableOptions
186186
): HttpsCallable<RequestData, ResponseData, StreamData> {
187-
const callable = (data?: RequestData | null) => {
187+
const callable = (data?: RequestData | null): Promise<HttpsCallableResult> => {
188188
return call(functionsInstance, name, data, options || {});
189189
};
190190

@@ -205,7 +205,7 @@ export function httpsCallableFromURL<RequestData, ResponseData, StreamData = unk
205205
url: string,
206206
options?: HttpsCallableOptions
207207
): HttpsCallable<RequestData, ResponseData, StreamData> {
208-
const callable = (data?: RequestData | null) => {
208+
const callable = (data?: RequestData | null): Promise<HttpsCallableResult> => {
209209
return callAtURL(functionsInstance, url, data, options || {});
210210
};
211211

@@ -431,7 +431,7 @@ async function streamAtURL(
431431
// network error. There's no way to know, since an unhandled error on the
432432
// backend will fail to set the proper CORS header, and thus will be
433433
// treated as a network error by fetch.
434-
const error = _errorForResponse(0, null)
434+
const error = _errorForResponse(0, null);
435435
return {
436436
data: Promise.reject(error),
437437
// Return an empty async iterator
@@ -450,18 +450,18 @@ async function streamAtURL(
450450
const reader = response.body!.getReader();
451451
const decoder = new TextDecoder();
452452

453-
let pendingLines: string[] = [];
453+
const pendingLines: string[] = [];
454454
let buffer = '';
455455
let resultResolver: (value: unknown) => void;
456-
let resultRejecter: (reason: any) => void;
456+
let resultRejecter: (reason: unknown) => void;
457457

458458
const resultPromise = new Promise<unknown>((resolve, reject) => {
459459
resultResolver = resolve;
460460
resultRejecter = reject;
461461
});
462462

463463
options?.signal?.addEventListener('abort', () => {
464-
reader.cancel();
464+
void reader.cancel();
465465
const error = new FunctionsError(
466466
'cancelled',
467467
'Request was cancelled.'
@@ -472,9 +472,9 @@ async function streamAtURL(
472472
const stream = {
473473
[Symbol.asyncIterator]() {
474474

475-
const processLine = (line: string | undefined) => {
475+
const processLine = (line: string | undefined): { done: boolean, value: unknown } | null => {
476476
// ignore all other lines (newline, comments, etc.)
477-
if (!line?.startsWith('data: ')) return null;
477+
if (!line?.startsWith('data: ')) { return null; }
478478

479479
try {
480480
const jsonData = JSON.parse(line.slice(6));
@@ -492,7 +492,7 @@ async function streamAtURL(
492492
}
493493
return null; // Unrecognize keys. Skip this line.
494494
} catch (error) {
495-
// Not json. Skip this line.
495+
return null;
496496
}
497497
};
498498
return {
@@ -502,13 +502,13 @@ async function streamAtURL(
502502
'cancelled',
503503
'Request was cancelled.'
504504
);
505-
resultRejecter(error)
505+
resultRejecter(error);
506506
throw error;
507507
}
508508

509509
while (pendingLines.length > 0) {
510510
const result = processLine(pendingLines.shift());
511-
if (result) return result;
511+
if (result) { return result; }
512512
}
513513

514514
while (true) {
@@ -517,7 +517,7 @@ async function streamAtURL(
517517
if (done) {
518518
if (buffer.trim()) {
519519
const result = processLine(buffer);
520-
if (result) return result;
520+
if (result) { return result; }
521521
}
522522
return { done: true, value: undefined };
523523
}
@@ -529,7 +529,7 @@ async function streamAtURL(
529529

530530
if (pendingLines.length > 0) {
531531
const result = processLine(pendingLines.shift());
532-
if (result) return result;
532+
if (result) { return result; }
533533
}
534534
}
535535
}
@@ -540,5 +540,5 @@ async function streamAtURL(
540540
return {
541541
stream,
542542
data: resultPromise,
543-
}
543+
};
544544
}

0 commit comments

Comments
 (0)