Skip to content
This repository was archived by the owner on Jan 26, 2021. It is now read-only.

Commit 5e062d4

Browse files
committed
Merge pull request #87 from philikon/refactoring
Refactor and improve Flow typing
2 parents a392a52 + 35acbea commit 5e062d4

File tree

9 files changed

+248
-178
lines changed

9 files changed

+248
-178
lines changed

src/Delta.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
var Id = require('./Id');
2727

28+
import type { FlattenedObjectData } from './ObjectStore';
29+
2830
/**
2931
* A Delta represents a change that has been verified by the server, but has
3032
* not yet been merged into the "Last True State" (typically because some
@@ -39,10 +41,10 @@ class Delta {
3941
destroy: ?boolean;
4042

4143
constructor(
42-
id: Id,
43-
data: { [key: string]: any },
44-
options?: { [key: string]: boolean }
45-
) {
44+
id: Id,
45+
data: FlattenedObjectData,
46+
options?: { [key: string]: boolean }
47+
) {
4648
if (!(id instanceof Id)) {
4749
throw new TypeError('Cannot create a Delta with an invalid target Id');
4850
}
@@ -80,8 +82,6 @@ class Delta {
8082
for (var attr in source.map) {
8183
this.map[attr] = source.map[attr];
8284
}
83-
84-
return this;
8585
}
8686
}
8787

src/MutationBatch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
var Parse = require('./StubParse');
2727

28-
import type ParseRequestOptions from './MutationExecutor';
28+
import type { ParseRequestOptions } from './MutationExecutor';
2929

3030
class MutationBatch {
3131
static maxBatchSize: number;

src/MutationExecutor.js

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@ export type ParseRequestOptions = {
3434
objectId?: string;
3535
};
3636

37+
import type { Mutation } from './Mutation';
3738
import type * as MutationBatch from './MutationBatch';
3839

3940

4041
var toString = Object.prototype.toString;
4142
// Special version of Parse._encode to handle our unique representations of
4243
// pointers
43-
function encode(data, seen?) {
44+
function encode(data: any, seen?: Array<any>): any {
4445
if (!seen) {
4546
seen = [];
4647
}
@@ -112,16 +113,16 @@ function sendRequest(options: ParseRequestOptions): Parse.Promise {
112113
}
113114

114115
function execute(
115-
action: string,
116-
target: Id|string,
117-
data: any,
116+
mutation: Mutation,
118117
batch: ?MutationBatch
119118
): Parse.Promise {
119+
var target = mutation.target;
120+
var data = mutation.data;
120121
var className = (typeof target === 'string') ? target : target.className;
121122
var objectId = (typeof target === 'string') ? '' : target.objectId;
122123
var payload;
123124
var request = batch ? batch.addRequest : sendRequest;
124-
switch (action) {
125+
switch (mutation.action) {
125126
case 'CREATE':
126127
return request({
127128
method: 'POST',
@@ -233,15 +234,10 @@ function execute(
233234
data: payload
234235
});
235236
}
236-
throw new TypeError('Invalid Mutation action: ' + action);
237+
throw new TypeError('Invalid Mutation action: ' + mutation.action);
237238
}
238239

239-
var MutationExecutor: any = {
240-
execute: execute,
241-
};
242-
240+
module.exports.execute = execute;
243241
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
244-
MutationExecutor.encode = encode;
242+
module.exports.encode = encode;
245243
}
246-
247-
module.exports = MutationExecutor;

src/ObjectStore.js

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,25 @@
2323

2424
'use strict';
2525

26-
import type * as Delta from './Delta';
27-
import type { Mutation } from './Mutation';
28-
2926
var flatten = require('./flatten');
3027
var Id = require('./Id');
3128
var queryHash = require('./QueryTools').queryHash;
3229

30+
import type * as Delta from './Delta';
31+
import type { Mutation } from './Mutation';
32+
33+
export type OrderingInfo = { [key: string]: any };
34+
export type IdWithOrderingInfo = {
35+
id: Id;
36+
ordering: OrderingInfo;
37+
};
38+
export type FlattenedObjectData = { [attr: string]: any };
39+
export type ObjectChangeDescriptor = {
40+
id: Id;
41+
latest: any; // TODO: this should really be FlattenedObjectData
42+
fields?: Array<string>;
43+
};
44+
3345
/**
3446
* ObjectStore is a local cache for Parse Objects. It stores the last known
3547
* server version of each object it has seen, as well as a stack of pending
@@ -42,7 +54,7 @@ var queryHash = require('./QueryTools').queryHash;
4254
// queries subscribed to the object.
4355
var store: {
4456
[id: Id]: {
45-
data: { [attr: string]: any };
57+
data: FlattenedObjectData;
4658
queries: { [hash: string]: boolean }
4759
}
4860
} = {};
@@ -66,7 +78,7 @@ var mutationCount = 0;
6678
* storeObject: takes a flattened object as the single argument, and places it
6779
* in the Store, indexed by its Id.
6880
*/
69-
function storeObject(data: { [attr: string]: any }): Id {
81+
function storeObject(data: FlattenedObjectData): Id {
7082
if (!(data.id instanceof Id)) {
7183
throw new Error('Cannot store an object without an Id');
7284
}
@@ -168,7 +180,11 @@ function destroyMutationStack(target: Id) {
168180
* Returns the latest object state and an array of keys that changed, or null
169181
* in the case of a Destroy
170182
*/
171-
function resolveMutation(target: Id, payloadId: number, delta: Delta): { id: Id; latest: any; fields?: Array<string> } {
183+
function resolveMutation(
184+
target: Id,
185+
payloadId: number,
186+
delta: Delta
187+
): ObjectChangeDescriptor {
172188
var stack = pendingMutations[target];
173189
var i;
174190
for (i = 0; i < stack.length; i++) {
@@ -219,8 +235,7 @@ function resolveMutation(target: Id, payloadId: number, delta: Delta): { id: Id;
219235
* Returns the latest object state and an array of keys that changed, or null
220236
* in the case of a Destroy
221237
*/
222-
function commitDelta(delta: Delta):
223-
{ id: Id; latest: any; fields?: Array<string> } {
238+
function commitDelta(delta: Delta): ObjectChangeDescriptor {
224239
var id = delta.id;
225240
if (delta.destroy) {
226241
if (store[id]) {
@@ -274,8 +289,10 @@ function commitDelta(delta: Delta):
274289
* Returns an array of object Ids, or an array of maps containing Ids and query-
275290
* specific ordering information.
276291
*/
277-
function storeQueryResults(results: Array<ParseObject> | ParseObject, query: ParseQuery):
278-
Array<Id | { id: Id; ordering: any }> {
292+
function storeQueryResults(
293+
results: Array<ParseObject> | ParseObject,
294+
query: ParseQuery
295+
): Array<Id | IdWithOrderingInfo> {
279296
var hash = queryHash(query);
280297
if (!Array.isArray(results)) {
281298
results = [results];
@@ -336,7 +353,7 @@ function storeQueryResults(results: Array<ParseObject> | ParseObject, query: Par
336353
* Given a list of object Ids, fetches the latest data for each object
337354
* and returns the results as an array of shallow copies.
338355
*/
339-
function getDataForIds(ids: Id | Array<Id>): Array<any> {
356+
function getDataForIds(ids: Id | Array<Id>): Array<FlattenedObjectData> {
340357
if (!Array.isArray(ids)) {
341358
ids = [ids];
342359
}
@@ -356,7 +373,7 @@ function getDataForIds(ids: Id | Array<Id>): Array<any> {
356373
/**
357374
* Fetch objects from the store, converting pointers to objects where possible
358375
*/
359-
function deepFetch(id: Id, seen?: Array<string>) {
376+
function deepFetch(id: Id, seen?: Array<string>): ?FlattenedObjectData {
360377
if (!store[id]) {
361378
return null;
362379
}
@@ -368,7 +385,7 @@ function deepFetch(id: Id, seen?: Array<string>) {
368385
var seenChildren = [];
369386
for (var attr in source) {
370387
var sourceVal = source[attr];
371-
if ( sourceVal && typeof sourceVal === 'object' && sourceVal.__type === 'Pointer') {
388+
if (sourceVal && typeof sourceVal === 'object' && sourceVal.__type === 'Pointer') {
372389
var childId = new Id(sourceVal.className, sourceVal.objectId);
373390
if (seen.indexOf(childId.toString()) < 0 && store[childId]) {
374391
seenChildren = seenChildren.concat([childId.toString()]);
@@ -383,7 +400,7 @@ function deepFetch(id: Id, seen?: Array<string>) {
383400
/**
384401
* Calculate the result of applying all Mutations to an object.
385402
*/
386-
function getLatest(id: Id) {
403+
function getLatest(id: Id): ?FlattenedObjectData {
387404
if (pendingMutations[id] && pendingMutations[id].length > 0) {
388405
var base = {};
389406
var mutation;
@@ -422,26 +439,22 @@ function getLatest(id: Id) {
422439
return store[id] ? deepFetch(id) : null;
423440
}
424441

425-
var ObjectStore: { [key: string]: any } = {
426-
storeObject: storeObject,
427-
removeObject: removeObject,
428-
addSubscriber: addSubscriber,
429-
removeSubscriber: removeSubscriber,
430-
fetchSubscribers: fetchSubscribers,
431-
stackMutation: stackMutation,
432-
destroyMutationStack: destroyMutationStack,
433-
resolveMutation: resolveMutation,
434-
commitDelta: commitDelta,
435-
storeQueryResults: storeQueryResults,
436-
getDataForIds: getDataForIds,
437-
deepFetch: deepFetch,
438-
getLatest: getLatest
439-
};
442+
module.exports.storeObject = storeObject;
443+
module.exports.removeObject = removeObject;
444+
module.exports.addSubscriber = addSubscriber;
445+
module.exports.removeSubscriber = removeSubscriber;
446+
module.exports.fetchSubscribers = fetchSubscribers;
447+
module.exports.stackMutation = stackMutation;
448+
module.exports.destroyMutationStack = destroyMutationStack;
449+
module.exports.resolveMutation = resolveMutation;
450+
module.exports.commitDelta = commitDelta;
451+
module.exports.storeQueryResults = storeQueryResults;
452+
module.exports.getDataForIds = getDataForIds;
453+
module.exports.deepFetch = deepFetch;
454+
module.exports.getLatest = getLatest;
440455

441456
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
442457
// Expose the raw storage
443-
ObjectStore._rawStore = store;
444-
ObjectStore._rawMutations = pendingMutations;
458+
module.exports._rawStore = store;
459+
module.exports._rawMutations = pendingMutations;
445460
}
446-
447-
module.exports = ObjectStore;

src/QueryTools.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ var equalObjects = require('./equalObjects');
2727
var Id = require('./Id');
2828
var Parse = require('./StubParse');
2929

30+
import type { FlattenedObjectData } from './ObjectStore';
31+
3032
/**
3133
* Query Hashes are deterministic hashes for Parse Queries.
3234
* Any two queries that have the same set of constraints will produce the same
@@ -145,8 +147,9 @@ function keysFromHash(hash: string):
145147
* queries, we can avoid building a full-blown query tool.
146148
*/
147149
function matchesQuery(
148-
object: { [key: string]: any },
149-
query: ParseQuery | { [key: string]: any }): boolean {
150+
object: FlattenedObjectData,
151+
query: ParseQuery | { [key: string]: any }
152+
): boolean {
150153
if (query instanceof Parse.Query) {
151154
var className =
152155
(object.id instanceof Id) ? object.id.className : object.className;

src/Subscription.js

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
var Id = require('./Id');
2727
var ObjectStore = require('./ObjectStore');
2828

29+
import type {
30+
IdWithOrderingInfo,
31+
OrderingInfo,
32+
} from './ObjectStore';
33+
2934
type ParseObject = {
3035
id: Id
3136
};
@@ -48,8 +53,8 @@ export type Subscriber = {
4853
* When we store ordering information alongside Ids, this method can map over
4954
* the array to extract each Id.
5055
*/
51-
function extractId(result) {
52-
return result.id;
56+
function extractId(result: Id | IdWithOrderingInfo): Id {
57+
return result instanceof Id ? result : result.id;
5358
}
5459

5560
/**
@@ -58,7 +63,11 @@ function extractId(result) {
5863
* it should come after, return 1. If the two are equivalent in ordering, the
5964
* function returns 0.
6065
*/
61-
function compareObjectOrder(queryOrder, object, orderInfo) {
66+
function compareObjectOrder(
67+
queryOrder: Array<string>,
68+
object: ParseObject,
69+
orderInfo: OrderingInfo
70+
): number {
6271
for (var i = 0; i < queryOrder.length; i++) {
6372
var column = queryOrder[i];
6473
var multiplier = 1;
@@ -81,7 +90,7 @@ class Subscription {
8190
originalQuery: ParseQuery;
8291
pending: boolean;
8392
subscribers: { [key: string]: Subscriber };
84-
resultSet: Array<any>;
93+
resultSet: Array<Id | IdWithOrderingInfo>;
8594
observationCount: number;
8695

8796
constructor(query: ParseQuery) {
@@ -109,10 +118,7 @@ class Subscription {
109118
var oid = 'o' + this.observationCount++;
110119
this.subscribers[oid] = callbacks;
111120

112-
var resultSet = this.resultSet;
113-
if (resultSet[0] && !(resultSet[0] instanceof Id)) {
114-
resultSet = resultSet.map(extractId);
115-
}
121+
var resultSet = this.resultSet.map(extractId);
116122
var data = resultSet.length ? ObjectStore.getDataForIds(resultSet) : [];
117123
callbacks.onNext(this.originalQuery._observeOne ? data[0] : data);
118124

@@ -168,16 +174,21 @@ class Subscription {
168174
var index = 0;
169175
var orderColumns = this.originalQuery._order;
170176
while (index < this.resultSet.length) {
177+
// Satisfy Flow by ensuring that the current result is indeed of the
178+
// IdWithOrderingInfo type, and not a plain Id.
179+
var result = this.resultSet[index];
180+
if (result instanceof Id) {
181+
throw new Error('Encountered result without ordering info.');
182+
}
171183
var compare = compareObjectOrder(
172184
orderColumns,
173185
object,
174-
this.resultSet[index].ordering
186+
result.ordering
175187
);
176-
if (compare > 0) {
177-
index++;
178-
} else {
188+
if (compare <= 0) {
179189
break;
180190
}
191+
index++;
181192
}
182193
var ordering = {};
183194
for (var i = 0; i < orderColumns.length; i++) {
@@ -224,13 +235,7 @@ class Subscription {
224235
if (this.originalQuery._limit > -1) {
225236
results = results.slice(0, this.originalQuery._limit);
226237
}
227-
if (results[0] && !(results[0] instanceof Id)) {
228-
results = results.map(extractId);
229-
}
230-
var resultSet = results;
231-
if (resultSet[0] && !(resultSet[0] instanceof Id)) {
232-
resultSet = resultSet.map(extractId);
233-
}
238+
var resultSet = results.map(extractId);
234239
var data = ObjectStore.getDataForIds(resultSet);
235240
if (this.originalQuery._observeOne) {
236241
data = data[0];

0 commit comments

Comments
 (0)