Skip to content

Commit f238f95

Browse files
committed
Introduces flow types for storage
1 parent 09fee7d commit f238f95

12 files changed

+866
-789
lines changed

.flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
[libs]
88

99
[options]
10+
suppress_comment= \\(.\\|\n\\)*\\@flow-disable-next

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"deep-diff": "0.3.8",
6060
"eslint": "^4.9.0",
6161
"eslint-plugin-flowtype": "^2.39.1",
62+
"flow-bin": "^0.59.0",
6263
"gaze": "1.1.2",
6364
"jasmine": "2.8.0",
6465
"jasmine-spec-reporter": "^4.1.0",

spec/MongoStorageAdapter.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
3+
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter').MongoStorageAdapter;
44
const MongoClient = require('mongodb').MongoClient;
55
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
66

spec/ParsePolygon.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const TestObject = Parse.Object.extend('TestObject');
2-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
2+
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter').MongoStorageAdapter;
33
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
44
const rp = require('request-promise');
55
const defaultHeaders = {

spec/ParseQuery.FullTextSearch.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

3-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
3+
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter').MongoStorageAdapter;
44
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
5-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
5+
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter').PostgresStorageAdapter;
66
const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database';
77
const Parse = require('parse/node');
88
const rp = require('request-promise');

spec/PostgresInitOptions.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const Parse = require('parse/node').Parse;
2-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
2+
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter').PostgresStorageAdapter;
33
const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database';
44
const ParseServer = require("../src/index");
55
const express = require('express');

spec/helper.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ var cache = require('../src/cache').default;
2727
var ParseServer = require('../src/index').ParseServer;
2828
var path = require('path');
2929
var TestUtils = require('../src/TestUtils');
30-
var MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
30+
var MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter').MongoStorageAdapter;
3131
const GridStoreAdapter = require('../src/Adapters/Files/GridStoreAdapter').GridStoreAdapter;
3232
const FSAdapter = require('parse-server-fs-adapter');
33-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
33+
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter').PostgresStorageAdapter;
3434
const RedisCacheAdapter = require('../src/Adapters/Cache/RedisCacheAdapter').default;
3535

3636
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';

spec/index.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var ParseServer = require("../src/index");
66
var Config = require('../src/Config');
77
var express = require('express');
88

9-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
9+
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter').MongoStorageAdapter;
1010

1111
describe('server', () => {
1212
it('requires a master key and app id', done => {

src/Adapters/Storage/Mongo/MongoStorageAdapter.js

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
// @flow
12
import MongoCollection from './MongoCollection';
23
import MongoSchemaCollection from './MongoSchemaCollection';
4+
import { StorageAdapter, IndexingStorageAdapter } from '../StorageAdapter';
5+
import type { SchemaType,
6+
QueryType,
7+
QueryOptionsType } from '../StorageAdapter';
38
import {
49
parse as parseUrl,
510
format as formatUrl,
@@ -11,10 +16,13 @@ import {
1116
transformWhere,
1217
transformUpdate,
1318
} from './MongoTransform';
19+
// $FlowFixMe
1420
import Parse from 'parse/node';
21+
// $FlowFixMe
1522
import _ from 'lodash';
1623
import defaults from '../../../defaults';
1724

25+
// $FlowFixMe
1826
const mongodb = require('mongodb');
1927
const MongoClient = mongodb.MongoClient;
2028
const ReadPreference = mongodb.ReadPreference;
@@ -58,7 +66,8 @@ const mongoSchemaFromFieldsAndClassNameAndCLP = (fields, className, classLevelPe
5866
_id: className,
5967
objectId: 'string',
6068
updatedAt: 'string',
61-
createdAt: 'string'
69+
createdAt: 'string',
70+
_metadata: undefined,
6271
};
6372

6473
for (const fieldName in fields) {
@@ -78,20 +87,22 @@ const mongoSchemaFromFieldsAndClassNameAndCLP = (fields, className, classLevelPe
7887
}
7988

8089

81-
export class MongoStorageAdapter {
90+
export class MongoStorageAdapter implements StorageAdapter, IndexingStorageAdapter {
8291
// Private
8392
_uri: string;
8493
_collectionPrefix: string;
8594
_mongoOptions: Object;
8695
// Public
8796
connectionPromise;
88-
database;
89-
canSortOnJoinTables;
97+
database: any;
98+
_maxTimeMS: ?number;
99+
canSortOnJoinTables: boolean;
100+
90101
constructor({
91102
uri = defaults.DefaultMongoURI,
92103
collectionPrefix = '',
93104
mongoOptions = {},
94-
}) {
105+
}: any) {
95106
this._uri = uri;
96107
this._collectionPrefix = collectionPrefix;
97108
this._mongoOptions = mongoOptions;
@@ -150,22 +161,22 @@ export class MongoStorageAdapter {
150161
.then(collection => new MongoSchemaCollection(collection));
151162
}
152163

153-
classExists(name) {
164+
classExists(name: string) {
154165
return this.connect().then(() => {
155166
return this.database.listCollections({ name: this._collectionPrefix + name }).toArray();
156167
}).then(collections => {
157168
return collections.length > 0;
158169
});
159170
}
160171

161-
setClassLevelPermissions(className, CLPs) {
172+
setClassLevelPermissions(className: string, CLPs: any) {
162173
return this._schemaCollection()
163174
.then(schemaCollection => schemaCollection.updateSchema(className, {
164175
$set: { _metadata: { class_permissions: CLPs } }
165176
}));
166177
}
167178

168-
createClass(className, schema) {
179+
createClass(className: string, schema: SchemaType) {
169180
schema = convertParseSchemaToMongoSchema(schema);
170181
const mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions);
171182
mongoObject._id = className;
@@ -181,15 +192,15 @@ export class MongoStorageAdapter {
181192
})
182193
}
183194

184-
addFieldIfNotExists(className, fieldName, type) {
195+
addFieldIfNotExists(className: string, fieldName: string, type: any) {
185196
return this._schemaCollection()
186197
.then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type))
187198
.then(() => this.createIndexesIfNeeded(className, fieldName, type));
188199
}
189200

190201
// Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.)
191202
// and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible.
192-
deleteClass(className) {
203+
deleteClass(className: string) {
193204
return this._adaptiveCollection(className)
194205
.then(collection => collection.drop())
195206
.catch(error => {
@@ -230,7 +241,7 @@ export class MongoStorageAdapter {
230241
// may do so.
231242

232243
// Returns a Promise.
233-
deleteFields(className, schema, fieldNames) {
244+
deleteFields(className: string, schema: SchemaType, fieldNames: string[]) {
234245
const mongoFormatNames = fieldNames.map(fieldName => {
235246
if (schema.fields[fieldName].type === 'Pointer') {
236247
return `_p_${fieldName}`
@@ -264,15 +275,15 @@ export class MongoStorageAdapter {
264275
// Return a promise for the schema with the given name, in Parse format. If
265276
// this adapter doesn't know about the schema, return a promise that rejects with
266277
// undefined as the reason.
267-
getClass(className) {
278+
getClass(className: string) {
268279
return this._schemaCollection()
269280
.then(schemasCollection => schemasCollection._fetchOneSchemaFrom_SCHEMA(className))
270281
}
271282

272283
// TODO: As yet not particularly well specified. Creates an object. Maybe shouldn't even need the schema,
273284
// and should infer from the type. Or maybe does need the schema for validations. Or maybe needs
274285
// the schema only for the legacy mongo format. We'll figure that out later.
275-
createObject(className, schema, object) {
286+
createObject(className: string, schema: SchemaType, object: any) {
276287
schema = convertParseSchemaToMongoSchema(schema);
277288
const mongoObject = parseObjectToMongoObjectForCreate(className, object, schema);
278289
return this._adaptiveCollection(className)
@@ -296,7 +307,7 @@ export class MongoStorageAdapter {
296307
// Remove all objects that match the given Parse Query.
297308
// If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined.
298309
// If there is some other error, reject with INTERNAL_SERVER_ERROR.
299-
deleteObjectsByQuery(className, schema, query) {
310+
deleteObjectsByQuery(className: string, schema: SchemaType, query: QueryType) {
300311
schema = convertParseSchemaToMongoSchema(schema);
301312
return this._adaptiveCollection(className)
302313
.then(collection => {
@@ -314,7 +325,7 @@ export class MongoStorageAdapter {
314325
}
315326

316327
// Apply the update to all objects that match the given Parse Query.
317-
updateObjectsByQuery(className, schema, query, update) {
328+
updateObjectsByQuery(className: string, schema: SchemaType, query: QueryType, update: any) {
318329
schema = convertParseSchemaToMongoSchema(schema);
319330
const mongoUpdate = transformUpdate(className, update, schema);
320331
const mongoWhere = transformWhere(className, query, schema);
@@ -324,7 +335,7 @@ export class MongoStorageAdapter {
324335

325336
// Atomically finds and updates an object based on query.
326337
// Return value not currently well specified.
327-
findOneAndUpdate(className, schema, query, update) {
338+
findOneAndUpdate(className: string, schema: SchemaType, query: QueryType, update: any) {
328339
schema = convertParseSchemaToMongoSchema(schema);
329340
const mongoUpdate = transformUpdate(className, update, schema);
330341
const mongoWhere = transformWhere(className, query, schema);
@@ -334,7 +345,7 @@ export class MongoStorageAdapter {
334345
}
335346

336347
// Hopefully we can get rid of this. It's only used for config and hooks.
337-
upsertOneObject(className, schema, query, update) {
348+
upsertOneObject(className: string, schema: SchemaType, query: QueryType, update: any) {
338349
schema = convertParseSchemaToMongoSchema(schema);
339350
const mongoUpdate = transformUpdate(className, update, schema);
340351
const mongoWhere = transformWhere(className, query, schema);
@@ -343,7 +354,7 @@ export class MongoStorageAdapter {
343354
}
344355

345356
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
346-
find(className, schema, query, { skip, limit, sort, keys, readPreference }) {
357+
find(className: string, schema: SchemaType, query: QueryType, { skip, limit, sort, keys, readPreference }: QueryOptionsType) {
347358
schema = convertParseSchemaToMongoSchema(schema);
348359
const mongoWhere = transformWhere(className, query, schema);
349360
const mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema));
@@ -371,7 +382,7 @@ export class MongoStorageAdapter {
371382
// As such, we shouldn't expose this function to users of parse until we have an out-of-band
372383
// Way of determining if a field is nullable. Undefined doesn't count against uniqueness,
373384
// which is why we use sparse indexes.
374-
ensureUniqueness(className, schema, fieldNames) {
385+
ensureUniqueness(className: string, schema: SchemaType, fieldNames: string[]) {
375386
schema = convertParseSchemaToMongoSchema(schema);
376387
const indexCreationRequest = {};
377388
const mongoFieldNames = fieldNames.map(fieldName => transformKey(className, fieldName, schema));
@@ -389,14 +400,14 @@ export class MongoStorageAdapter {
389400
}
390401

391402
// Used in tests
392-
_rawFind(className, query) {
403+
_rawFind(className: string, query: QueryType) {
393404
return this._adaptiveCollection(className).then(collection => collection.find(query, {
394405
maxTimeMS: this._maxTimeMS,
395406
}));
396407
}
397408

398409
// Executes a count.
399-
count(className, schema, query, readPreference) {
410+
count(className: string, schema: SchemaType, query: QueryType, readPreference: ?string) {
400411
schema = convertParseSchemaToMongoSchema(schema);
401412
readPreference = this._parseReadPreference(readPreference);
402413
return this._adaptiveCollection(className)
@@ -406,13 +417,13 @@ export class MongoStorageAdapter {
406417
}));
407418
}
408419

409-
distinct(className, schema, query, fieldName) {
420+
distinct(className: string, schema: SchemaType, query: QueryType, fieldName: string) {
410421
schema = convertParseSchemaToMongoSchema(schema);
411422
return this._adaptiveCollection(className)
412423
.then(collection => collection.distinct(fieldName, transformWhere(className, query, schema)));
413424
}
414425

415-
aggregate(className, pipeline, readPreference) {
426+
aggregate(className: string, pipeline: any, readPreference: ?string) {
416427
readPreference = this._parseReadPreference(readPreference);
417428
return this._adaptiveCollection(className)
418429
.then(collection => collection.aggregate(pipeline, { readPreference, maxTimeMS: this._maxTimeMS }))
@@ -427,7 +438,7 @@ export class MongoStorageAdapter {
427438
});
428439
}
429440

430-
_parseReadPreference(readPreference) {
441+
_parseReadPreference(readPreference: ?string): ?string {
431442
if (readPreference) {
432443
switch (readPreference) {
433444
case 'PRIMARY':
@@ -452,16 +463,16 @@ export class MongoStorageAdapter {
452463
return readPreference;
453464
}
454465

455-
performInitialization() {
466+
performInitialization(): Promise<void> {
456467
return Promise.resolve();
457468
}
458469

459-
createIndex(className, index) {
470+
createIndex(className: string, index: any) {
460471
return this._adaptiveCollection(className)
461472
.then(collection => collection._mongoCollection.createIndex(index));
462473
}
463474

464-
createIndexesIfNeeded(className, fieldName, type) {
475+
createIndexesIfNeeded(className: string, fieldName: string, type: any) {
465476
if (type && type.type === 'Polygon') {
466477
const index = {
467478
[fieldName]: '2dsphere'
@@ -471,7 +482,7 @@ export class MongoStorageAdapter {
471482
return Promise.resolve();
472483
}
473484

474-
createTextIndexesIfNeeded(className, query) {
485+
createTextIndexesIfNeeded(className: string, query: QueryType) {
475486
for(const fieldName in query) {
476487
if (!query[fieldName] || !query[fieldName].$text) {
477488
continue;
@@ -492,11 +503,10 @@ export class MongoStorageAdapter {
492503
return Promise.resolve();
493504
}
494505

495-
getIndexes(className) {
506+
getIndexes(className: string) {
496507
return this._adaptiveCollection(className)
497508
.then(collection => collection._mongoCollection.indexes());
498509
}
499510
}
500511

501512
export default MongoStorageAdapter;
502-
module.exports = MongoStorageAdapter; // Required for tests

0 commit comments

Comments
 (0)