Skip to content

Commit 5582754

Browse files
author
James Lees
committed
Split common methods into base client
1 parent 4981809 commit 5582754

File tree

4 files changed

+219
-389
lines changed

4 files changed

+219
-389
lines changed

src/base-client.js

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import doRequest from './do-request';
2+
3+
const INTERESTS_REGEX = new RegExp('^(_|\\-|=|@|,|\\.|;|[A-Z]|[a-z]|[0-9])*$');
4+
const MAX_INTEREST_LENGTH = 164;
5+
const MAX_INTERESTS_NUM = 5000;
6+
7+
export const RegistrationState = Object.freeze({
8+
PERMISSION_PROMPT_REQUIRED: 'PERMISSION_PROMPT_REQUIRED',
9+
PERMISSION_GRANTED_NOT_REGISTERED_WITH_BEAMS:
10+
'PERMISSION_GRANTED_NOT_REGISTERED_WITH_BEAMS',
11+
PERMISSION_GRANTED_REGISTERED_WITH_BEAMS:
12+
'PERMISSION_GRANTED_REGISTERED_WITH_BEAMS',
13+
PERMISSION_DENIED: 'PERMISSION_DENIED',
14+
});
15+
16+
export default class BaseClient {
17+
constructor(config) {}
18+
19+
async getDeviceId() {
20+
await this._resolveSDKState();
21+
return this._ready.then(() => this._deviceId);
22+
}
23+
async getToken() {
24+
await this._resolveSDKState();
25+
return this._ready.then(() => this._token);
26+
}
27+
async getUserId() {
28+
await this._resolveSDKState();
29+
return this._ready.then(() => this._userId);
30+
}
31+
32+
get _baseURL() {
33+
if (this._endpoint !== null) {
34+
return this._endpoint;
35+
}
36+
return `https://${this.instanceId}.pushnotifications.pusher.com`;
37+
}
38+
39+
_throwIfNotStarted(message) {
40+
if (!this._deviceId) {
41+
throw new Error(
42+
`${message}. SDK not registered with Beams. Did you call .start?`
43+
);
44+
}
45+
}
46+
47+
async _resolveSDKState() {
48+
await this._ready;
49+
await this._detectSubscriptionChange();
50+
}
51+
52+
async addDeviceInterest(interest) {
53+
await this._resolveSDKState();
54+
this._throwIfNotStarted('Could not add Device Interest');
55+
56+
validateInterestName(interest);
57+
58+
const path = `${this._baseURL}/device_api/v1/instances/${encodeURIComponent(
59+
this.instanceId
60+
)}/devices/${this._platform}/${
61+
this._deviceId
62+
}/interests/${encodeURIComponent(interest)}`;
63+
const options = {
64+
method: 'POST',
65+
path,
66+
};
67+
await doRequest(options);
68+
}
69+
70+
async removeDeviceInterest(interest) {
71+
await this._resolveSDKState();
72+
this._throwIfNotStarted('Could not remove Device Interest');
73+
74+
validateInterestName(interest);
75+
76+
const path = `${this._baseURL}/device_api/v1/instances/${encodeURIComponent(
77+
this.instanceId
78+
)}/devices/${this._platform}/${
79+
this._deviceId
80+
}/interests/${encodeURIComponent(interest)}`;
81+
const options = {
82+
method: 'DELETE',
83+
path,
84+
};
85+
await doRequest(options);
86+
}
87+
88+
async getDeviceInterests() {
89+
await this._resolveSDKState();
90+
this._throwIfNotStarted('Could not get Device Interests');
91+
92+
const path = `${this._baseURL}/device_api/v1/instances/${encodeURIComponent(
93+
this.instanceId
94+
)}/devices/${this._platform}/${this._deviceId}/interests`;
95+
const options = {
96+
method: 'GET',
97+
path,
98+
};
99+
return (await doRequest(options))['interests'] || [];
100+
}
101+
102+
async setDeviceInterests(interests) {
103+
await this._resolveSDKState();
104+
this._throwIfNotStarted('Could not set Device Interests');
105+
106+
if (interests === undefined || interests === null) {
107+
throw new Error('interests argument is required');
108+
}
109+
if (!Array.isArray(interests)) {
110+
throw new Error('interests argument must be an array');
111+
}
112+
if (interests.length > MAX_INTERESTS_NUM) {
113+
throw new Error(
114+
`Number of interests (${
115+
interests.length
116+
}) exceeds maximum of ${MAX_INTERESTS_NUM}`
117+
);
118+
}
119+
for (let interest of interests) {
120+
validateInterestName(interest);
121+
}
122+
123+
const uniqueInterests = Array.from(new Set(interests));
124+
const path = `${this._baseURL}/device_api/v1/instances/${encodeURIComponent(
125+
this.instanceId
126+
)}/devices/${this._platform}/${this._deviceId}/interests`;
127+
const options = {
128+
method: 'PUT',
129+
path,
130+
body: {
131+
interests: uniqueInterests,
132+
},
133+
};
134+
await doRequest(options);
135+
}
136+
137+
async clearDeviceInterests() {
138+
await this._resolveSDKState();
139+
this._throwIfNotStarted('Could not clear Device Interests');
140+
141+
await this.setDeviceInterests([]);
142+
}
143+
144+
async _deleteDevice() {
145+
const path = `${this._baseURL}/device_api/v1/instances/${encodeURIComponent(
146+
this.instanceId
147+
)}/devices/${this._platform}/${encodeURIComponent(this._deviceId)}`;
148+
149+
const options = { method: 'DELETE', path };
150+
await doRequest(options);
151+
}
152+
153+
// TODO is this ever used?
154+
/**
155+
* Submit SDK version and browser details (via the user agent) to Pusher Beams.
156+
*/
157+
async _updateDeviceMetadata() {
158+
const userAgent = window.navigator.userAgent;
159+
const storedUserAgent = await this._deviceStateStore.getLastSeenUserAgent();
160+
const storedSdkVersion = await this._deviceStateStore.getLastSeenSdkVersion();
161+
162+
if (userAgent === storedUserAgent && sdkVersion === storedSdkVersion) {
163+
// Nothing to do
164+
return;
165+
}
166+
167+
const path = `${this._baseURL}/device_api/v1/instances/${encodeURIComponent(
168+
this.instanceId
169+
)}/devices/${this._platform}/${this._deviceId}/metadata`;
170+
171+
const metadata = {
172+
sdkVersion,
173+
};
174+
175+
const options = { method: 'PUT', path, body: metadata };
176+
await doRequest(options);
177+
178+
await this._deviceStateStore.setLastSeenSdkVersion(sdkVersion);
179+
await this._deviceStateStore.setLastSeenUserAgent(userAgent);
180+
}
181+
}
182+
183+
function validateInterestName(interest) {
184+
if (interest === undefined || interest === null) {
185+
throw new Error('Interest name is required');
186+
}
187+
if (typeof interest !== 'string') {
188+
throw new Error(`Interest ${interest} is not a string`);
189+
}
190+
if (!INTERESTS_REGEX.test(interest)) {
191+
throw new Error(
192+
`interest "${interest}" contains a forbidden character. ` +
193+
'Allowed characters are: ASCII upper/lower-case letters, ' +
194+
'numbers or one of _-=@,.;'
195+
);
196+
}
197+
if (interest.length > MAX_INTEREST_LENGTH) {
198+
throw new Error(
199+
`Interest is longer than the maximum of ${MAX_INTEREST_LENGTH} chars`
200+
);
201+
}
202+
}

src/push-notifications.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
import { WebPushClient } from './web-push-client';
22
import { SafariClient } from './safari-client';
33
import TokenProvider from './token-provider';
4-
5-
const RegistrationState = Object.freeze({
6-
PERMISSION_PROMPT_REQUIRED: 'PERMISSION_PROMPT_REQUIRED',
7-
PERMISSION_GRANTED_NOT_REGISTERED_WITH_BEAMS:
8-
'PERMISSION_GRANTED_NOT_REGISTERED_WITH_BEAMS',
9-
PERMISSION_GRANTED_REGISTERED_WITH_BEAMS:
10-
'PERMISSION_GRANTED_REGISTERED_WITH_BEAMS',
11-
PERMISSION_DENIED: 'PERMISSION_DENIED',
12-
});
4+
import { RegistrationState } from './base-client';
135

146
function Client(config) {
157
if ('safari' in window) {

0 commit comments

Comments
 (0)