@firebase/app 0.7.17-canary.2b98b28f2 → 0.7.17-canary.927c1afc1
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.
- package/dist/app/src/heartbeatService.d.ts +8 -9
- package/dist/app/src/indexeddb.d.ts +0 -1
- package/dist/app/src/types.d.ts +6 -7
- package/dist/esm/app/src/heartbeatService.d.ts +8 -9
- package/dist/esm/app/src/indexeddb.d.ts +0 -1
- package/dist/esm/app/src/types.d.ts +6 -7
- package/dist/esm/index.esm2017.js +43 -62
- package/dist/esm/index.esm2017.js.map +1 -1
- package/dist/esm/index.esm5.js +51 -103
- package/dist/esm/index.esm5.js.map +1 -1
- package/dist/index.cjs.js +50 -102
- package/dist/index.cjs.js.map +1 -1
- package/package.json +4 -4
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { ComponentContainer } from '@firebase/component';
|
|
18
18
|
import { FirebaseApp } from './public-types';
|
|
19
|
-
import { HeartbeatsByUserAgent, HeartbeatService, HeartbeatStorage, SingleDateHeartbeat } from './types';
|
|
19
|
+
import { HeartbeatsByUserAgent, HeartbeatService, HeartbeatsInIndexedDB, HeartbeatStorage, SingleDateHeartbeat } from './types';
|
|
20
20
|
export declare class HeartbeatServiceImpl implements HeartbeatService {
|
|
21
21
|
private readonly container;
|
|
22
22
|
/**
|
|
@@ -33,14 +33,14 @@ export declare class HeartbeatServiceImpl implements HeartbeatService {
|
|
|
33
33
|
* be kept in sync with indexedDB.
|
|
34
34
|
* Leave public for easier testing.
|
|
35
35
|
*/
|
|
36
|
-
_heartbeatsCache:
|
|
36
|
+
_heartbeatsCache: HeartbeatsInIndexedDB | null;
|
|
37
37
|
/**
|
|
38
38
|
* the initialization promise for populating heartbeatCache.
|
|
39
39
|
* If getHeartbeatsHeader() is called before the promise resolves
|
|
40
40
|
* (hearbeatsCache == null), it should wait for this promise
|
|
41
41
|
* Leave public for easier testing.
|
|
42
42
|
*/
|
|
43
|
-
_heartbeatsCachePromise: Promise<
|
|
43
|
+
_heartbeatsCachePromise: Promise<HeartbeatsInIndexedDB>;
|
|
44
44
|
constructor(container: ComponentContainer);
|
|
45
45
|
/**
|
|
46
46
|
* Called to report a heartbeat. The function will generate
|
|
@@ -54,7 +54,8 @@ export declare class HeartbeatServiceImpl implements HeartbeatService {
|
|
|
54
54
|
* Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
|
|
55
55
|
* It also clears all heartbeats from memory as well as in IndexedDB.
|
|
56
56
|
*
|
|
57
|
-
* NOTE:
|
|
57
|
+
* NOTE: Consuming product SDKs should not send the header if this method
|
|
58
|
+
* returns an empty string.
|
|
58
59
|
*/
|
|
59
60
|
getHeartbeatsHeader(): Promise<string>;
|
|
60
61
|
}
|
|
@@ -70,11 +71,9 @@ export declare class HeartbeatStorageImpl implements HeartbeatStorage {
|
|
|
70
71
|
/**
|
|
71
72
|
* Read all heartbeats.
|
|
72
73
|
*/
|
|
73
|
-
read(): Promise<
|
|
74
|
-
overwrite(
|
|
75
|
-
add(
|
|
76
|
-
delete(heartbeats: SingleDateHeartbeat[]): Promise<void>;
|
|
77
|
-
deleteAll(): Promise<void>;
|
|
74
|
+
read(): Promise<HeartbeatsInIndexedDB>;
|
|
75
|
+
overwrite(heartbeatsObject: HeartbeatsInIndexedDB): Promise<void>;
|
|
76
|
+
add(heartbeatsObject: HeartbeatsInIndexedDB): Promise<void>;
|
|
78
77
|
}
|
|
79
78
|
/**
|
|
80
79
|
* Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
|
|
@@ -18,4 +18,3 @@ import { FirebaseApp } from './public-types';
|
|
|
18
18
|
import { HeartbeatsInIndexedDB } from './types';
|
|
19
19
|
export declare function readHeartbeatsFromIndexedDB(app: FirebaseApp): Promise<HeartbeatsInIndexedDB | undefined>;
|
|
20
20
|
export declare function writeHeartbeatsToIndexedDB(app: FirebaseApp, heartbeatObject: HeartbeatsInIndexedDB): Promise<void>;
|
|
21
|
-
export declare function deleteHeartbeatsFromIndexedDB(app: FirebaseApp): Promise<void>;
|
package/dist/app/src/types.d.ts
CHANGED
|
@@ -37,20 +37,19 @@ export interface HeartbeatService {
|
|
|
37
37
|
getHeartbeatsHeader(): Promise<string>;
|
|
38
38
|
}
|
|
39
39
|
export interface HeartbeatsByUserAgent {
|
|
40
|
-
|
|
40
|
+
agent: string;
|
|
41
41
|
dates: string[];
|
|
42
42
|
}
|
|
43
43
|
export interface SingleDateHeartbeat {
|
|
44
|
-
|
|
44
|
+
agent: string;
|
|
45
45
|
date: string;
|
|
46
46
|
}
|
|
47
47
|
export interface HeartbeatStorage {
|
|
48
|
-
overwrite(heartbeats:
|
|
49
|
-
add(heartbeats:
|
|
50
|
-
|
|
51
|
-
deleteAll(): Promise<void>;
|
|
52
|
-
read(): Promise<SingleDateHeartbeat[]>;
|
|
48
|
+
overwrite(heartbeats: HeartbeatsInIndexedDB): Promise<void>;
|
|
49
|
+
add(heartbeats: HeartbeatsInIndexedDB): Promise<void>;
|
|
50
|
+
read(): Promise<HeartbeatsInIndexedDB>;
|
|
53
51
|
}
|
|
54
52
|
export interface HeartbeatsInIndexedDB {
|
|
53
|
+
lastSentHeartbeatDate?: string;
|
|
55
54
|
heartbeats: SingleDateHeartbeat[];
|
|
56
55
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { ComponentContainer } from '@firebase/component';
|
|
18
18
|
import { FirebaseApp } from './public-types';
|
|
19
|
-
import { HeartbeatsByUserAgent, HeartbeatService, HeartbeatStorage, SingleDateHeartbeat } from './types';
|
|
19
|
+
import { HeartbeatsByUserAgent, HeartbeatService, HeartbeatsInIndexedDB, HeartbeatStorage, SingleDateHeartbeat } from './types';
|
|
20
20
|
export declare class HeartbeatServiceImpl implements HeartbeatService {
|
|
21
21
|
private readonly container;
|
|
22
22
|
/**
|
|
@@ -33,14 +33,14 @@ export declare class HeartbeatServiceImpl implements HeartbeatService {
|
|
|
33
33
|
* be kept in sync with indexedDB.
|
|
34
34
|
* Leave public for easier testing.
|
|
35
35
|
*/
|
|
36
|
-
_heartbeatsCache:
|
|
36
|
+
_heartbeatsCache: HeartbeatsInIndexedDB | null;
|
|
37
37
|
/**
|
|
38
38
|
* the initialization promise for populating heartbeatCache.
|
|
39
39
|
* If getHeartbeatsHeader() is called before the promise resolves
|
|
40
40
|
* (hearbeatsCache == null), it should wait for this promise
|
|
41
41
|
* Leave public for easier testing.
|
|
42
42
|
*/
|
|
43
|
-
_heartbeatsCachePromise: Promise<
|
|
43
|
+
_heartbeatsCachePromise: Promise<HeartbeatsInIndexedDB>;
|
|
44
44
|
constructor(container: ComponentContainer);
|
|
45
45
|
/**
|
|
46
46
|
* Called to report a heartbeat. The function will generate
|
|
@@ -54,7 +54,8 @@ export declare class HeartbeatServiceImpl implements HeartbeatService {
|
|
|
54
54
|
* Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
|
|
55
55
|
* It also clears all heartbeats from memory as well as in IndexedDB.
|
|
56
56
|
*
|
|
57
|
-
* NOTE:
|
|
57
|
+
* NOTE: Consuming product SDKs should not send the header if this method
|
|
58
|
+
* returns an empty string.
|
|
58
59
|
*/
|
|
59
60
|
getHeartbeatsHeader(): Promise<string>;
|
|
60
61
|
}
|
|
@@ -70,11 +71,9 @@ export declare class HeartbeatStorageImpl implements HeartbeatStorage {
|
|
|
70
71
|
/**
|
|
71
72
|
* Read all heartbeats.
|
|
72
73
|
*/
|
|
73
|
-
read(): Promise<
|
|
74
|
-
overwrite(
|
|
75
|
-
add(
|
|
76
|
-
delete(heartbeats: SingleDateHeartbeat[]): Promise<void>;
|
|
77
|
-
deleteAll(): Promise<void>;
|
|
74
|
+
read(): Promise<HeartbeatsInIndexedDB>;
|
|
75
|
+
overwrite(heartbeatsObject: HeartbeatsInIndexedDB): Promise<void>;
|
|
76
|
+
add(heartbeatsObject: HeartbeatsInIndexedDB): Promise<void>;
|
|
78
77
|
}
|
|
79
78
|
/**
|
|
80
79
|
* Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
|
|
@@ -18,4 +18,3 @@ import { FirebaseApp } from './public-types';
|
|
|
18
18
|
import { HeartbeatsInIndexedDB } from './types';
|
|
19
19
|
export declare function readHeartbeatsFromIndexedDB(app: FirebaseApp): Promise<HeartbeatsInIndexedDB | undefined>;
|
|
20
20
|
export declare function writeHeartbeatsToIndexedDB(app: FirebaseApp, heartbeatObject: HeartbeatsInIndexedDB): Promise<void>;
|
|
21
|
-
export declare function deleteHeartbeatsFromIndexedDB(app: FirebaseApp): Promise<void>;
|
|
@@ -37,20 +37,19 @@ export interface HeartbeatService {
|
|
|
37
37
|
getHeartbeatsHeader(): Promise<string>;
|
|
38
38
|
}
|
|
39
39
|
export interface HeartbeatsByUserAgent {
|
|
40
|
-
|
|
40
|
+
agent: string;
|
|
41
41
|
dates: string[];
|
|
42
42
|
}
|
|
43
43
|
export interface SingleDateHeartbeat {
|
|
44
|
-
|
|
44
|
+
agent: string;
|
|
45
45
|
date: string;
|
|
46
46
|
}
|
|
47
47
|
export interface HeartbeatStorage {
|
|
48
|
-
overwrite(heartbeats:
|
|
49
|
-
add(heartbeats:
|
|
50
|
-
|
|
51
|
-
deleteAll(): Promise<void>;
|
|
52
|
-
read(): Promise<SingleDateHeartbeat[]>;
|
|
48
|
+
overwrite(heartbeats: HeartbeatsInIndexedDB): Promise<void>;
|
|
49
|
+
add(heartbeats: HeartbeatsInIndexedDB): Promise<void>;
|
|
50
|
+
read(): Promise<HeartbeatsInIndexedDB>;
|
|
53
51
|
}
|
|
54
52
|
export interface HeartbeatsInIndexedDB {
|
|
53
|
+
lastSentHeartbeatDate?: string;
|
|
55
54
|
heartbeats: SingleDateHeartbeat[];
|
|
56
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component, ComponentContainer } from '@firebase/component';
|
|
2
2
|
import { Logger, setUserLogHandler, setLogLevel as setLogLevel$1 } from '@firebase/logger';
|
|
3
|
-
import { ErrorFactory, deepEqual,
|
|
3
|
+
import { ErrorFactory, deepEqual, base64urlEncodeWithoutPadding, isIndexedDBAvailable, validateIndexedDBOpenable } from '@firebase/util';
|
|
4
4
|
export { FirebaseError } from '@firebase/util';
|
|
5
5
|
import { openDb } from 'idb';
|
|
6
6
|
|
|
@@ -58,7 +58,7 @@ function isVersionServiceProvider(provider) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const name$o = "@firebase/app";
|
|
61
|
-
const version$1 = "0.7.17-canary.
|
|
61
|
+
const version$1 = "0.7.17-canary.927c1afc1";
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* @license
|
|
@@ -125,7 +125,7 @@ const name$2 = "@firebase/firestore";
|
|
|
125
125
|
const name$1 = "@firebase/firestore-compat";
|
|
126
126
|
|
|
127
127
|
const name = "firebase";
|
|
128
|
-
const version = "9.6.7-canary.
|
|
128
|
+
const version = "9.6.7-canary.927c1afc1";
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
131
|
* @license
|
|
@@ -635,19 +635,6 @@ async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
|
|
|
635
635
|
});
|
|
636
636
|
}
|
|
637
637
|
}
|
|
638
|
-
async function deleteHeartbeatsFromIndexedDB(app) {
|
|
639
|
-
try {
|
|
640
|
-
const db = await getDbPromise();
|
|
641
|
-
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
642
|
-
await tx.objectStore(STORE_NAME).delete(computeKey(app));
|
|
643
|
-
return tx.complete;
|
|
644
|
-
}
|
|
645
|
-
catch (e) {
|
|
646
|
-
throw ERROR_FACTORY.create("storage-delete" /* STORAGE_DELETE */, {
|
|
647
|
-
originalErrorMessage: e.message
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
638
|
function computeKey(app) {
|
|
652
639
|
return `${app.name}!${app.options.appId}`;
|
|
653
640
|
}
|
|
@@ -704,21 +691,23 @@ class HeartbeatServiceImpl {
|
|
|
704
691
|
.getImmediate();
|
|
705
692
|
// This is the "Firebase user agent" string from the platform logger
|
|
706
693
|
// service, not the browser user agent.
|
|
707
|
-
const
|
|
694
|
+
const agent = platformLogger.getPlatformInfoString();
|
|
708
695
|
const date = getUTCDateString();
|
|
709
696
|
if (this._heartbeatsCache === null) {
|
|
710
697
|
this._heartbeatsCache = await this._heartbeatsCachePromise;
|
|
711
698
|
}
|
|
712
|
-
if
|
|
713
|
-
|
|
699
|
+
// Do not store a heartbeat if one is already stored for this day
|
|
700
|
+
// or if a header has already been sent today.
|
|
701
|
+
if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
|
|
702
|
+
this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
|
|
714
703
|
return;
|
|
715
704
|
}
|
|
716
705
|
else {
|
|
717
706
|
// There is no entry for this date. Create one.
|
|
718
|
-
this._heartbeatsCache.push({ date,
|
|
707
|
+
this._heartbeatsCache.heartbeats.push({ date, agent });
|
|
719
708
|
}
|
|
720
709
|
// Remove entries older than 30 days.
|
|
721
|
-
this._heartbeatsCache = this._heartbeatsCache.filter(singleDateHeartbeat => {
|
|
710
|
+
this._heartbeatsCache.heartbeats = this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
|
|
722
711
|
const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
|
|
723
712
|
const now = Date.now();
|
|
724
713
|
return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
|
|
@@ -729,31 +718,36 @@ class HeartbeatServiceImpl {
|
|
|
729
718
|
* Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
|
|
730
719
|
* It also clears all heartbeats from memory as well as in IndexedDB.
|
|
731
720
|
*
|
|
732
|
-
* NOTE:
|
|
721
|
+
* NOTE: Consuming product SDKs should not send the header if this method
|
|
722
|
+
* returns an empty string.
|
|
733
723
|
*/
|
|
734
724
|
async getHeartbeatsHeader() {
|
|
735
725
|
if (this._heartbeatsCache === null) {
|
|
736
726
|
await this._heartbeatsCachePromise;
|
|
737
727
|
}
|
|
738
|
-
// If it's still null
|
|
739
|
-
if (this._heartbeatsCache === null
|
|
728
|
+
// If it's still null or the array is empty, there is no data to send.
|
|
729
|
+
if (this._heartbeatsCache === null ||
|
|
730
|
+
this._heartbeatsCache.heartbeats.length === 0) {
|
|
740
731
|
return '';
|
|
741
732
|
}
|
|
733
|
+
const date = getUTCDateString();
|
|
742
734
|
// Extract as many heartbeats from the cache as will fit under the size limit.
|
|
743
|
-
const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache);
|
|
744
|
-
const headerString =
|
|
735
|
+
const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
|
|
736
|
+
const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
|
|
737
|
+
// Store last sent date to prevent another being logged/sent for the same day.
|
|
738
|
+
this._heartbeatsCache.lastSentHeartbeatDate = date;
|
|
745
739
|
if (unsentEntries.length > 0) {
|
|
746
740
|
// Store any unsent entries if they exist.
|
|
747
|
-
this._heartbeatsCache = unsentEntries;
|
|
748
|
-
// This seems more likely than
|
|
741
|
+
this._heartbeatsCache.heartbeats = unsentEntries;
|
|
742
|
+
// This seems more likely than emptying the array (below) to lead to some odd state
|
|
749
743
|
// since the cache isn't empty and this will be called again on the next request,
|
|
750
744
|
// and is probably safest if we await it.
|
|
751
745
|
await this._storage.overwrite(this._heartbeatsCache);
|
|
752
746
|
}
|
|
753
747
|
else {
|
|
754
|
-
this._heartbeatsCache =
|
|
748
|
+
this._heartbeatsCache.heartbeats = [];
|
|
755
749
|
// Do not wait for this, to reduce latency.
|
|
756
|
-
void this._storage.
|
|
750
|
+
void this._storage.overwrite(this._heartbeatsCache);
|
|
757
751
|
}
|
|
758
752
|
return headerString;
|
|
759
753
|
}
|
|
@@ -771,11 +765,11 @@ function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES)
|
|
|
771
765
|
let unsentEntries = heartbeatsCache.slice();
|
|
772
766
|
for (const singleDateHeartbeat of heartbeatsCache) {
|
|
773
767
|
// Look for an existing entry with the same user agent.
|
|
774
|
-
const heartbeatEntry = heartbeatsToSend.find(hb => hb.
|
|
768
|
+
const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
|
|
775
769
|
if (!heartbeatEntry) {
|
|
776
770
|
// If no entry for this user agent exists, create one.
|
|
777
771
|
heartbeatsToSend.push({
|
|
778
|
-
|
|
772
|
+
agent: singleDateHeartbeat.agent,
|
|
779
773
|
dates: [singleDateHeartbeat.date]
|
|
780
774
|
});
|
|
781
775
|
if (countBytes(heartbeatsToSend) > maxSize) {
|
|
@@ -824,59 +818,46 @@ class HeartbeatStorageImpl {
|
|
|
824
818
|
async read() {
|
|
825
819
|
const canUseIndexedDB = await this._canUseIndexedDBPromise;
|
|
826
820
|
if (!canUseIndexedDB) {
|
|
827
|
-
return [];
|
|
821
|
+
return { heartbeats: [] };
|
|
828
822
|
}
|
|
829
823
|
else {
|
|
830
824
|
const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
|
|
831
|
-
return
|
|
825
|
+
return idbHeartbeatObject || { heartbeats: [] };
|
|
832
826
|
}
|
|
833
827
|
}
|
|
834
828
|
// overwrite the storage with the provided heartbeats
|
|
835
|
-
async overwrite(
|
|
836
|
-
|
|
837
|
-
if (!canUseIndexedDB) {
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
else {
|
|
841
|
-
return writeHeartbeatsToIndexedDB(this.app, { heartbeats });
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
// add heartbeats
|
|
845
|
-
async add(heartbeats) {
|
|
829
|
+
async overwrite(heartbeatsObject) {
|
|
830
|
+
var _a;
|
|
846
831
|
const canUseIndexedDB = await this._canUseIndexedDBPromise;
|
|
847
832
|
if (!canUseIndexedDB) {
|
|
848
833
|
return;
|
|
849
834
|
}
|
|
850
835
|
else {
|
|
851
|
-
const
|
|
836
|
+
const existingHeartbeatsObject = await this.read();
|
|
852
837
|
return writeHeartbeatsToIndexedDB(this.app, {
|
|
853
|
-
|
|
838
|
+
lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
|
|
839
|
+
heartbeats: heartbeatsObject.heartbeats
|
|
854
840
|
});
|
|
855
841
|
}
|
|
856
842
|
}
|
|
857
|
-
//
|
|
858
|
-
async
|
|
843
|
+
// add heartbeats
|
|
844
|
+
async add(heartbeatsObject) {
|
|
845
|
+
var _a;
|
|
859
846
|
const canUseIndexedDB = await this._canUseIndexedDBPromise;
|
|
860
847
|
if (!canUseIndexedDB) {
|
|
861
848
|
return;
|
|
862
849
|
}
|
|
863
850
|
else {
|
|
864
|
-
const
|
|
851
|
+
const existingHeartbeatsObject = await this.read();
|
|
865
852
|
return writeHeartbeatsToIndexedDB(this.app, {
|
|
866
|
-
|
|
853
|
+
lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
|
|
854
|
+
heartbeats: [
|
|
855
|
+
...existingHeartbeatsObject.heartbeats,
|
|
856
|
+
...heartbeatsObject.heartbeats
|
|
857
|
+
]
|
|
867
858
|
});
|
|
868
859
|
}
|
|
869
860
|
}
|
|
870
|
-
// delete all heartbeats
|
|
871
|
-
async deleteAll() {
|
|
872
|
-
const canUseIndexedDB = await this._canUseIndexedDBPromise;
|
|
873
|
-
if (!canUseIndexedDB) {
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
return deleteHeartbeatsFromIndexedDB(this.app);
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
861
|
}
|
|
881
862
|
/**
|
|
882
863
|
* Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
|
|
@@ -885,7 +866,7 @@ class HeartbeatStorageImpl {
|
|
|
885
866
|
*/
|
|
886
867
|
function countBytes(heartbeatsCache) {
|
|
887
868
|
// base64 has a restricted set of characters, all of which should be 1 byte.
|
|
888
|
-
return
|
|
869
|
+
return base64urlEncodeWithoutPadding(
|
|
889
870
|
// heartbeatsCache wrapper properties
|
|
890
871
|
JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
|
|
891
872
|
}
|