Skip to content

Commit

Permalink
feat: Improve installation object `Parse.Installation.currentInstalla…
Browse files Browse the repository at this point in the history
…tion` to support web push notifications (#2119)
  • Loading branch information
dplewis committed May 4, 2024
1 parent 1c50c37 commit 4fc62ce
Show file tree
Hide file tree
Showing 17 changed files with 690 additions and 107 deletions.
37 changes: 34 additions & 3 deletions integration/test/ParseUserTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('Parse User', () => {

it('can login users with installationId', async () => {
Parse.User.enableUnsafeCurrentUser();
const currentInstallation = await Parse.CoreManager.getInstallationController().currentInstallationId();
const currentInstallationId = await Parse.CoreManager.getInstallationController().currentInstallationId();
const installationId = '12345678';
const user = new Parse.User();
user.set('username', 'parse');
Expand All @@ -132,7 +132,7 @@ describe('Parse User', () => {
let sessions = await sessionQuery.find({ useMasterKey: true });
expect(sessions.length).toBe(2);
expect(sessions[0].get('installationId')).toBe(installationId);
expect(sessions[1].get('installationId')).toBe(currentInstallation);
expect(sessions[1].get('installationId')).toBe(currentInstallationId);
expect(sessions[0].get('sessionToken')).toBe(user.getSessionToken());
expect(sessions[1].get('sessionToken')).toBe(loggedUser.getSessionToken());

Expand All @@ -142,12 +142,43 @@ describe('Parse User', () => {
});
sessions = await sessionQuery.find({ useMasterKey: true });
expect(sessions.length).toBe(2);
expect(sessions[0].get('installationId')).toBe(currentInstallation);
expect(sessions[0].get('installationId')).toBe(currentInstallationId);
expect(sessions[1].get('installationId')).toBe(installationId);
expect(sessions[0].get('sessionToken')).toBe(loggedUser.getSessionToken());
expect(sessions[1].get('sessionToken')).toBe(installationUser.getSessionToken());
});

it('can get current installation', async () => {
const currentInstallationId = await Parse.CoreManager.getInstallationController().currentInstallationId();
const installation = await Parse.Installation.currentInstallation();
expect(installation.installationId).toBe(currentInstallationId);
expect(installation.deviceType).toBe(Parse.Installation.DEVICE_TYPES.WEB);
await installation.save();
expect(installation.id).toBeDefined();
expect(installation.createdAt).toBeDefined();
expect(installation.updatedAt).toBeDefined();
const data = {
deviceToken: '1234',
badge: 1,
appIdentifier: 'com.parse.server',
appName: 'Parse JS SDK',
appVersion: '1.0.0',
parseVersion: '1.0.0',
localeIdentifier: 'en-US',
timeZone: 'GMT',
channels: ['test'],
GCMSenderId: '1234',
pushType: 'test',
};
installation.set(data);
await installation.save();
const query = new Parse.Query(Parse.Installation);
const result = await query.get(installation.id, { useMasterKey: true });
Object.keys(data).forEach(key => {
expect(result[key]).toEqual(data[key]);
});
});

it('can login with userId', async () => {
Parse.User.enableUnsafeCurrentUser();

Expand Down
9 changes: 8 additions & 1 deletion src/CoreManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { HookDeclaration, HookDeleteArg } from './ParseHooks';
import type ParseConfig from './ParseConfig';
import type LiveQueryClient from './LiveQueryClient';
import type ParseSchema from './ParseSchema';
import type ParseInstallation from './ParseInstallation';

type AnalyticsController = {
track: (name: string, dimensions: { [key: string]: string }) => Promise<any>,
Expand Down Expand Up @@ -41,6 +42,8 @@ type FileController = {
};
type InstallationController = {
currentInstallationId: () => Promise<string>,
currentInstallation: () => Promise<ParseInstallation | null>,
updateInstallationOnDisk: (installation: ParseInstallation) => Promise<void>,
};
type ObjectController = {
fetch: (
Expand Down Expand Up @@ -376,7 +379,11 @@ const CoreManager = {
},

setInstallationController(controller: InstallationController) {
requireMethods('InstallationController', ['currentInstallationId'], controller);
requireMethods(
'InstallationController',
['currentInstallationId', 'currentInstallation', 'updateInstallationOnDisk'],
controller
);
config['InstallationController'] = controller;
},

Expand Down
38 changes: 0 additions & 38 deletions src/InstallationController.js

This file was deleted.

81 changes: 81 additions & 0 deletions src/InstallationController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import CoreManager from './CoreManager';
import Storage from './Storage';
import ParseInstallation from './ParseInstallation';
import uuidv4 from './uuid';

const CURRENT_INSTALLATION_KEY = 'currentInstallation';
const CURRENT_INSTALLATION_ID_KEY = 'currentInstallationId';

let iidCache: string | null = null;
let currentInstallationCache = null;
let currentInstallationCacheMatchesDisk = false;

const InstallationController = {
async updateInstallationOnDisk(installation: ParseInstallation): Promise<void> {
const path = Storage.generatePath(CURRENT_INSTALLATION_KEY);
await Storage.setItemAsync(path, JSON.stringify(installation.toJSON()));
this._setCurrentInstallationCache(installation);
},

async currentInstallationId(): Promise<string> {
if (typeof iidCache === 'string') {
return iidCache;
}
const path = Storage.generatePath(CURRENT_INSTALLATION_ID_KEY);
let iid = await Storage.getItemAsync(path);
if (!iid) {
iid = uuidv4();
return Storage.setItemAsync(path, iid).then(() => {
iidCache = iid;
return iid;
});
}
iidCache = iid;
return iid;
},

async currentInstallation(): Promise<ParseInstallation | null> {
if (currentInstallationCache) {
return currentInstallationCache;
}
if (currentInstallationCacheMatchesDisk) {
return null;
}
const path = Storage.generatePath(CURRENT_INSTALLATION_KEY);
let installationData = await Storage.getItemAsync(path);
currentInstallationCacheMatchesDisk = true;
if (installationData) {
installationData = JSON.parse(installationData);
installationData.className = '_Installation';
const current = ParseInstallation.fromJSON(installationData);
currentInstallationCache = current;
return current;
}
const installationId = await this.currentInstallationId();
const installation = new ParseInstallation();
installation.set('deviceType', ParseInstallation.DEVICE_TYPES.WEB);
installation.set('installationId', installationId);
installation.set('parseVersion', CoreManager.get('VERSION'));
currentInstallationCache = installation;
await Storage.setItemAsync(path, JSON.stringify(installation.toJSON()))
return installation;
},

_clearCache() {
iidCache = null;
currentInstallationCache = null;
currentInstallationCacheMatchesDisk = false;
},

_setInstallationIdCache(iid: string) {
iidCache = iid;
},

_setCurrentInstallationCache(installation: ParseInstallation, matchesDisk: boolean = true) {
currentInstallationCache = installation;
currentInstallationCacheMatchesDisk = matchesDisk;
},
};

module.exports = InstallationController;
export default InstallationController;
5 changes: 2 additions & 3 deletions src/Parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@ const Parse: ParseType = {
CoreManager.setIfNeeded('EventEmitter', EventEmitter);
CoreManager.setIfNeeded('LiveQuery', new ParseLiveQuery());
CoreManager.setIfNeeded('CryptoController', CryptoController);
CoreManager.setIfNeeded('EventuallyQueue', EventuallyQueue);
CoreManager.setIfNeeded('InstallationController', InstallationController);
CoreManager.setIfNeeded('LocalDatastoreController', LocalDatastoreController);
CoreManager.setIfNeeded('StorageController', StorageController);
CoreManager.setIfNeeded('WebSocketController', WebSocketController);

CoreManager.setIfNeeded('EventuallyQueue', EventuallyQueue);

if (process.env.PARSE_BUILD === 'browser') {
Parse.IndexedDB = CoreManager.setIfNeeded('IndexedDBStorageController', IndexedDBStorageController);
}
Expand Down Expand Up @@ -464,7 +464,6 @@ const Parse: ParseType = {
},
};

CoreManager.setInstallationController(InstallationController);
CoreManager.setRESTController(RESTController);

if (process.env.PARSE_BUILD === 'node') {
Expand Down
20 changes: 0 additions & 20 deletions src/ParseInstallation.js

This file was deleted.

0 comments on commit 4fc62ce

Please sign in to comment.