Skip to content

Commit 19dd24c

Browse files
committed
Introduces flow types for storage
1 parent dd55bbe commit 19dd24c

13 files changed

+879
-803
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
@@ -56,6 +56,7 @@
5656
"deep-diff": "0.3.8",
5757
"eslint": "^4.9.0",
5858
"eslint-plugin-flowtype": "^2.39.1",
59+
"flow-bin": "^0.59.0",
5960
"gaze": "1.1.2",
6061
"jasmine": "2.8.0",
6162
"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/ParseServer.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ describe('Server Url Checks', () => {
3535
});
3636

3737
it('handleShutdown, close connection', (done) => {
38-
var MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
39-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
38+
const { MongoStorageAdapter } = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
39+
const { PostgresStorageAdapter } = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
4040
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
4141
const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database';
4242
let databaseAdapter;

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/fs-files-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: 45 additions & 35 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 } 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) {
@@ -83,20 +92,22 @@ const mongoSchemaFromFieldsAndClassNameAndCLP = (fields, className, classLevelPe
8392
}
8493

8594

86-
export class MongoStorageAdapter {
95+
export class MongoStorageAdapter implements StorageAdapter {
8796
// Private
8897
_uri: string;
8998
_collectionPrefix: string;
9099
_mongoOptions: Object;
91100
// Public
92101
connectionPromise;
93-
database;
94-
canSortOnJoinTables;
102+
database: any;
103+
_maxTimeMS: ?number;
104+
canSortOnJoinTables: boolean;
105+
95106
constructor({
96107
uri = defaults.DefaultMongoURI,
97108
collectionPrefix = '',
98109
mongoOptions = {},
99-
}) {
110+
}: any) {
100111
this._uri = uri;
101112
this._collectionPrefix = collectionPrefix;
102113
this._mongoOptions = mongoOptions;
@@ -155,22 +166,22 @@ export class MongoStorageAdapter {
155166
.then(collection => new MongoSchemaCollection(collection));
156167
}
157168

158-
classExists(name) {
169+
classExists(name: string) {
159170
return this.connect().then(() => {
160171
return this.database.listCollections({ name: this._collectionPrefix + name }).toArray();
161172
}).then(collections => {
162173
return collections.length > 0;
163174
});
164175
}
165176

166-
setClassLevelPermissions(className, CLPs) {
177+
setClassLevelPermissions(className: string, CLPs: any) {
167178
return this._schemaCollection()
168179
.then(schemaCollection => schemaCollection.updateSchema(className, {
169180
$set: { _metadata: { class_permissions: CLPs } }
170181
}));
171182
}
172183

173-
setIndexesWithSchemaFormat(className, submittedIndexes, existingIndexes = {}, fields) {
184+
setIndexesWithSchemaFormat(className: string, submittedIndexes: any, existingIndexes: any = {}, fields: any): Promise<void> {
174185
if (submittedIndexes === undefined) {
175186
return Promise.resolve();
176187
}
@@ -216,7 +227,7 @@ export class MongoStorageAdapter {
216227
}));
217228
}
218229

219-
setIndexesFromMongo(className) {
230+
setIndexesFromMongo(className: string) {
220231
return this.getIndexes(className).then((indexes) => {
221232
indexes = indexes.reduce((obj, index) => {
222233
if (index.key._fts) {
@@ -239,7 +250,7 @@ export class MongoStorageAdapter {
239250
});
240251
}
241252

242-
createClass(className, schema) {
253+
createClass(className: string, schema: SchemaType) {
243254
schema = convertParseSchemaToMongoSchema(schema);
244255
const mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions, schema.indexes);
245256
mongoObject._id = className;
@@ -256,15 +267,15 @@ export class MongoStorageAdapter {
256267
})
257268
}
258269

259-
addFieldIfNotExists(className, fieldName, type) {
270+
addFieldIfNotExists(className: string, fieldName: string, type: any) {
260271
return this._schemaCollection()
261272
.then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type))
262273
.then(() => this.createIndexesIfNeeded(className, fieldName, type));
263274
}
264275

265276
// Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.)
266277
// and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible.
267-
deleteClass(className) {
278+
deleteClass(className: string) {
268279
return this._adaptiveCollection(className)
269280
.then(collection => collection.drop())
270281
.catch(error => {
@@ -305,7 +316,7 @@ export class MongoStorageAdapter {
305316
// may do so.
306317

307318
// Returns a Promise.
308-
deleteFields(className, schema, fieldNames) {
319+
deleteFields(className: string, schema: SchemaType, fieldNames: string[]) {
309320
const mongoFormatNames = fieldNames.map(fieldName => {
310321
if (schema.fields[fieldName].type === 'Pointer') {
311322
return `_p_${fieldName}`
@@ -339,15 +350,15 @@ export class MongoStorageAdapter {
339350
// Return a promise for the schema with the given name, in Parse format. If
340351
// this adapter doesn't know about the schema, return a promise that rejects with
341352
// undefined as the reason.
342-
getClass(className) {
353+
getClass(className: string) {
343354
return this._schemaCollection()
344355
.then(schemasCollection => schemasCollection._fetchOneSchemaFrom_SCHEMA(className))
345356
}
346357

347358
// TODO: As yet not particularly well specified. Creates an object. Maybe shouldn't even need the schema,
348359
// and should infer from the type. Or maybe does need the schema for validations. Or maybe needs
349360
// the schema only for the legacy mongo format. We'll figure that out later.
350-
createObject(className, schema, object) {
361+
createObject(className: string, schema: SchemaType, object: any) {
351362
schema = convertParseSchemaToMongoSchema(schema);
352363
const mongoObject = parseObjectToMongoObjectForCreate(className, object, schema);
353364
return this._adaptiveCollection(className)
@@ -371,7 +382,7 @@ export class MongoStorageAdapter {
371382
// Remove all objects that match the given Parse Query.
372383
// If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined.
373384
// If there is some other error, reject with INTERNAL_SERVER_ERROR.
374-
deleteObjectsByQuery(className, schema, query) {
385+
deleteObjectsByQuery(className: string, schema: SchemaType, query: QueryType) {
375386
schema = convertParseSchemaToMongoSchema(schema);
376387
return this._adaptiveCollection(className)
377388
.then(collection => {
@@ -389,7 +400,7 @@ export class MongoStorageAdapter {
389400
}
390401

391402
// Apply the update to all objects that match the given Parse Query.
392-
updateObjectsByQuery(className, schema, query, update) {
403+
updateObjectsByQuery(className: string, schema: SchemaType, query: QueryType, update: any) {
393404
schema = convertParseSchemaToMongoSchema(schema);
394405
const mongoUpdate = transformUpdate(className, update, schema);
395406
const mongoWhere = transformWhere(className, query, schema);
@@ -399,7 +410,7 @@ export class MongoStorageAdapter {
399410

400411
// Atomically finds and updates an object based on query.
401412
// Return value not currently well specified.
402-
findOneAndUpdate(className, schema, query, update) {
413+
findOneAndUpdate(className: string, schema: SchemaType, query: QueryType, update: any) {
403414
schema = convertParseSchemaToMongoSchema(schema);
404415
const mongoUpdate = transformUpdate(className, update, schema);
405416
const mongoWhere = transformWhere(className, query, schema);
@@ -409,7 +420,7 @@ export class MongoStorageAdapter {
409420
}
410421

411422
// Hopefully we can get rid of this. It's only used for config and hooks.
412-
upsertOneObject(className, schema, query, update) {
423+
upsertOneObject(className: string, schema: SchemaType, query: QueryType, update: any) {
413424
schema = convertParseSchemaToMongoSchema(schema);
414425
const mongoUpdate = transformUpdate(className, update, schema);
415426
const mongoWhere = transformWhere(className, query, schema);
@@ -418,7 +429,7 @@ export class MongoStorageAdapter {
418429
}
419430

420431
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
421-
find(className, schema, query, { skip, limit, sort, keys, readPreference }) {
432+
find(className: string, schema: SchemaType, query: QueryType, { skip, limit, sort, keys, readPreference }: QueryOptionsType): Promise<any> {
422433
schema = convertParseSchemaToMongoSchema(schema);
423434
const mongoWhere = transformWhere(className, query, schema);
424435
const mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema));
@@ -446,7 +457,7 @@ export class MongoStorageAdapter {
446457
// As such, we shouldn't expose this function to users of parse until we have an out-of-band
447458
// Way of determining if a field is nullable. Undefined doesn't count against uniqueness,
448459
// which is why we use sparse indexes.
449-
ensureUniqueness(className, schema, fieldNames) {
460+
ensureUniqueness(className: string, schema: SchemaType, fieldNames: string[]) {
450461
schema = convertParseSchemaToMongoSchema(schema);
451462
const indexCreationRequest = {};
452463
const mongoFieldNames = fieldNames.map(fieldName => transformKey(className, fieldName, schema));
@@ -464,14 +475,14 @@ export class MongoStorageAdapter {
464475
}
465476

466477
// Used in tests
467-
_rawFind(className, query) {
478+
_rawFind(className: string, query: QueryType) {
468479
return this._adaptiveCollection(className).then(collection => collection.find(query, {
469480
maxTimeMS: this._maxTimeMS,
470481
}));
471482
}
472483

473484
// Executes a count.
474-
count(className, schema, query, readPreference) {
485+
count(className: string, schema: SchemaType, query: QueryType, readPreference: ?string) {
475486
schema = convertParseSchemaToMongoSchema(schema);
476487
readPreference = this._parseReadPreference(readPreference);
477488
return this._adaptiveCollection(className)
@@ -481,14 +492,14 @@ export class MongoStorageAdapter {
481492
}));
482493
}
483494

484-
distinct(className, schema, query, fieldName) {
495+
distinct(className: string, schema: SchemaType, query: QueryType, fieldName: string) {
485496
schema = convertParseSchemaToMongoSchema(schema);
486497
return this._adaptiveCollection(className)
487498
.then(collection => collection.distinct(fieldName, transformWhere(className, query, schema)))
488499
.then(objects => objects.map(object => mongoObjectToParseObject(className, object, schema)));
489500
}
490501

491-
aggregate(className, schema, pipeline, readPreference) {
502+
aggregate(className: string, schema: any, pipeline: any, readPreference: ?string) {
492503
readPreference = this._parseReadPreference(readPreference);
493504
return this._adaptiveCollection(className)
494505
.then(collection => collection.aggregate(pipeline, { readPreference, maxTimeMS: this._maxTimeMS }))
@@ -504,7 +515,7 @@ export class MongoStorageAdapter {
504515
.then(objects => objects.map(object => mongoObjectToParseObject(className, object, schema)));
505516
}
506517

507-
_parseReadPreference(readPreference) {
518+
_parseReadPreference(readPreference: ?string): ?string {
508519
if (readPreference) {
509520
switch (readPreference) {
510521
case 'PRIMARY':
@@ -529,21 +540,21 @@ export class MongoStorageAdapter {
529540
return readPreference;
530541
}
531542

532-
performInitialization() {
543+
performInitialization(): Promise<void> {
533544
return Promise.resolve();
534545
}
535546

536-
createIndex(className, index) {
547+
createIndex(className: string, index: any) {
537548
return this._adaptiveCollection(className)
538549
.then(collection => collection._mongoCollection.createIndex(index));
539550
}
540551

541-
createIndexes(className, indexes) {
552+
createIndexes(className: string, indexes: any) {
542553
return this._adaptiveCollection(className)
543554
.then(collection => collection._mongoCollection.createIndexes(indexes));
544555
}
545556

546-
createIndexesIfNeeded(className, fieldName, type) {
557+
createIndexesIfNeeded(className: string, fieldName: string, type: any) {
547558
if (type && type.type === 'Polygon') {
548559
const index = {
549560
[fieldName]: '2dsphere'
@@ -553,7 +564,7 @@ export class MongoStorageAdapter {
553564
return Promise.resolve();
554565
}
555566

556-
createTextIndexesIfNeeded(className, query, schema) {
567+
createTextIndexesIfNeeded(className: string, query: QueryType, schema: any): Promise<void> {
557568
for(const fieldName in query) {
558569
if (!query[fieldName] || !query[fieldName].$text) {
559570
continue;
@@ -580,17 +591,17 @@ export class MongoStorageAdapter {
580591
return Promise.resolve();
581592
}
582593

583-
getIndexes(className) {
594+
getIndexes(className: string) {
584595
return this._adaptiveCollection(className)
585596
.then(collection => collection._mongoCollection.indexes());
586597
}
587598

588-
dropIndex(className, index) {
599+
dropIndex(className: string, index: any) {
589600
return this._adaptiveCollection(className)
590601
.then(collection => collection._mongoCollection.dropIndex(index));
591602
}
592603

593-
dropAllIndexes(className) {
604+
dropAllIndexes(className: string) {
594605
return this._adaptiveCollection(className)
595606
.then(collection => collection._mongoCollection.dropIndexes());
596607
}
@@ -607,4 +618,3 @@ export class MongoStorageAdapter {
607618
}
608619

609620
export default MongoStorageAdapter;
610-
module.exports = MongoStorageAdapter; // Required for tests

0 commit comments

Comments
 (0)