Skip to content

Commit ed68ef1

Browse files
committed
Introduces flow types for storage
1 parent 7223add commit ed68ef1

12 files changed

+866
-788
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: 38 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,20 @@ 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-
97+
database: any;
98+
_maxTimeMS: ?number;
9099
constructor({
91100
uri = defaults.DefaultMongoURI,
92101
collectionPrefix = '',
93102
mongoOptions = {},
94-
}) {
103+
}: any) {
95104
this._uri = uri;
96105
this._collectionPrefix = collectionPrefix;
97106
this._mongoOptions = mongoOptions;
@@ -149,22 +158,22 @@ export class MongoStorageAdapter {
149158
.then(collection => new MongoSchemaCollection(collection));
150159
}
151160

152-
classExists(name) {
161+
classExists(name: string) {
153162
return this.connect().then(() => {
154163
return this.database.listCollections({ name: this._collectionPrefix + name }).toArray();
155164
}).then(collections => {
156165
return collections.length > 0;
157166
});
158167
}
159168

160-
setClassLevelPermissions(className, CLPs) {
169+
setClassLevelPermissions(className: string, CLPs: any) {
161170
return this._schemaCollection()
162171
.then(schemaCollection => schemaCollection.updateSchema(className, {
163172
$set: { _metadata: { class_permissions: CLPs } }
164173
}));
165174
}
166175

167-
createClass(className, schema) {
176+
createClass(className: string, schema: SchemaType) {
168177
schema = convertParseSchemaToMongoSchema(schema);
169178
const mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions);
170179
mongoObject._id = className;
@@ -180,15 +189,15 @@ export class MongoStorageAdapter {
180189
})
181190
}
182191

183-
addFieldIfNotExists(className, fieldName, type) {
192+
addFieldIfNotExists(className: string, fieldName: string, type: any) {
184193
return this._schemaCollection()
185194
.then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type))
186195
.then(() => this.createIndexesIfNeeded(className, fieldName, type));
187196
}
188197

189198
// Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.)
190199
// and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible.
191-
deleteClass(className) {
200+
deleteClass(className: string) {
192201
return this._adaptiveCollection(className)
193202
.then(collection => collection.drop())
194203
.catch(error => {
@@ -229,7 +238,7 @@ export class MongoStorageAdapter {
229238
// may do so.
230239

231240
// Returns a Promise.
232-
deleteFields(className, schema, fieldNames) {
241+
deleteFields(className: string, schema: SchemaType, fieldNames: string[]) {
233242
const mongoFormatNames = fieldNames.map(fieldName => {
234243
if (schema.fields[fieldName].type === 'Pointer') {
235244
return `_p_${fieldName}`
@@ -263,15 +272,15 @@ export class MongoStorageAdapter {
263272
// Return a promise for the schema with the given name, in Parse format. If
264273
// this adapter doesn't know about the schema, return a promise that rejects with
265274
// undefined as the reason.
266-
getClass(className) {
275+
getClass(className: string) {
267276
return this._schemaCollection()
268277
.then(schemasCollection => schemasCollection._fetchOneSchemaFrom_SCHEMA(className))
269278
}
270279

271280
// TODO: As yet not particularly well specified. Creates an object. Maybe shouldn't even need the schema,
272281
// and should infer from the type. Or maybe does need the schema for validations. Or maybe needs
273282
// the schema only for the legacy mongo format. We'll figure that out later.
274-
createObject(className, schema, object) {
283+
createObject(className: string, schema: SchemaType, object: any) {
275284
schema = convertParseSchemaToMongoSchema(schema);
276285
const mongoObject = parseObjectToMongoObjectForCreate(className, object, schema);
277286
return this._adaptiveCollection(className)
@@ -295,7 +304,7 @@ export class MongoStorageAdapter {
295304
// Remove all objects that match the given Parse Query.
296305
// If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined.
297306
// If there is some other error, reject with INTERNAL_SERVER_ERROR.
298-
deleteObjectsByQuery(className, schema, query) {
307+
deleteObjectsByQuery(className: string, schema: SchemaType, query: QueryType) {
299308
schema = convertParseSchemaToMongoSchema(schema);
300309
return this._adaptiveCollection(className)
301310
.then(collection => {
@@ -313,7 +322,7 @@ export class MongoStorageAdapter {
313322
}
314323

315324
// Apply the update to all objects that match the given Parse Query.
316-
updateObjectsByQuery(className, schema, query, update) {
325+
updateObjectsByQuery(className: string, schema: SchemaType, query: QueryType, update: any) {
317326
schema = convertParseSchemaToMongoSchema(schema);
318327
const mongoUpdate = transformUpdate(className, update, schema);
319328
const mongoWhere = transformWhere(className, query, schema);
@@ -323,7 +332,7 @@ export class MongoStorageAdapter {
323332

324333
// Atomically finds and updates an object based on query.
325334
// Return value not currently well specified.
326-
findOneAndUpdate(className, schema, query, update) {
335+
findOneAndUpdate(className: string, schema: SchemaType, query: QueryType, update: any) {
327336
schema = convertParseSchemaToMongoSchema(schema);
328337
const mongoUpdate = transformUpdate(className, update, schema);
329338
const mongoWhere = transformWhere(className, query, schema);
@@ -333,7 +342,7 @@ export class MongoStorageAdapter {
333342
}
334343

335344
// Hopefully we can get rid of this. It's only used for config and hooks.
336-
upsertOneObject(className, schema, query, update) {
345+
upsertOneObject(className: string, schema: SchemaType, query: QueryType, update: any) {
337346
schema = convertParseSchemaToMongoSchema(schema);
338347
const mongoUpdate = transformUpdate(className, update, schema);
339348
const mongoWhere = transformWhere(className, query, schema);
@@ -342,7 +351,7 @@ export class MongoStorageAdapter {
342351
}
343352

344353
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
345-
find(className, schema, query, { skip, limit, sort, keys, readPreference }) {
354+
find(className: string, schema: SchemaType, query: QueryType, { skip, limit, sort, keys, readPreference }: QueryOptionsType) {
346355
schema = convertParseSchemaToMongoSchema(schema);
347356
const mongoWhere = transformWhere(className, query, schema);
348357
const mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema));
@@ -370,7 +379,7 @@ export class MongoStorageAdapter {
370379
// As such, we shouldn't expose this function to users of parse until we have an out-of-band
371380
// Way of determining if a field is nullable. Undefined doesn't count against uniqueness,
372381
// which is why we use sparse indexes.
373-
ensureUniqueness(className, schema, fieldNames) {
382+
ensureUniqueness(className: string, schema: SchemaType, fieldNames: string[]) {
374383
schema = convertParseSchemaToMongoSchema(schema);
375384
const indexCreationRequest = {};
376385
const mongoFieldNames = fieldNames.map(fieldName => transformKey(className, fieldName, schema));
@@ -388,14 +397,14 @@ export class MongoStorageAdapter {
388397
}
389398

390399
// Used in tests
391-
_rawFind(className, query) {
400+
_rawFind(className: string, query: QueryType) {
392401
return this._adaptiveCollection(className).then(collection => collection.find(query, {
393402
maxTimeMS: this._maxTimeMS,
394403
}));
395404
}
396405

397406
// Executes a count.
398-
count(className, schema, query, readPreference) {
407+
count(className: string, schema: SchemaType, query: QueryType, readPreference: ?string) {
399408
schema = convertParseSchemaToMongoSchema(schema);
400409
readPreference = this._parseReadPreference(readPreference);
401410
return this._adaptiveCollection(className)
@@ -405,13 +414,13 @@ export class MongoStorageAdapter {
405414
}));
406415
}
407416

408-
distinct(className, schema, query, fieldName) {
417+
distinct(className: string, schema: SchemaType, query: QueryType, fieldName: string) {
409418
schema = convertParseSchemaToMongoSchema(schema);
410419
return this._adaptiveCollection(className)
411420
.then(collection => collection.distinct(fieldName, transformWhere(className, query, schema)));
412421
}
413422

414-
aggregate(className, pipeline, readPreference) {
423+
aggregate(className: string, pipeline: any, readPreference: ?string) {
415424
readPreference = this._parseReadPreference(readPreference);
416425
return this._adaptiveCollection(className)
417426
.then(collection => collection.aggregate(pipeline, { readPreference, maxTimeMS: this._maxTimeMS }))
@@ -426,7 +435,7 @@ export class MongoStorageAdapter {
426435
});
427436
}
428437

429-
_parseReadPreference(readPreference) {
438+
_parseReadPreference(readPreference: ?string): ?string {
430439
if (readPreference) {
431440
switch (readPreference) {
432441
case 'PRIMARY':
@@ -451,16 +460,16 @@ export class MongoStorageAdapter {
451460
return readPreference;
452461
}
453462

454-
performInitialization() {
463+
performInitialization(): Promise<void> {
455464
return Promise.resolve();
456465
}
457466

458-
createIndex(className, index) {
467+
createIndex(className: string, index: any) {
459468
return this._adaptiveCollection(className)
460469
.then(collection => collection._mongoCollection.createIndex(index));
461470
}
462471

463-
createIndexesIfNeeded(className, fieldName, type) {
472+
createIndexesIfNeeded(className: string, fieldName: string, type: any) {
464473
if (type && type.type === 'Polygon') {
465474
const index = {
466475
[fieldName]: '2dsphere'
@@ -470,7 +479,7 @@ export class MongoStorageAdapter {
470479
return Promise.resolve();
471480
}
472481

473-
createTextIndexesIfNeeded(className, query) {
482+
createTextIndexesIfNeeded(className: string, query: QueryType) {
474483
for(const fieldName in query) {
475484
if (!query[fieldName] || !query[fieldName].$text) {
476485
continue;
@@ -491,11 +500,10 @@ export class MongoStorageAdapter {
491500
return Promise.resolve();
492501
}
493502

494-
getIndexes(className) {
503+
getIndexes(className: string) {
495504
return this._adaptiveCollection(className)
496505
.then(collection => collection._mongoCollection.indexes());
497506
}
498507
}
499508

500509
export default MongoStorageAdapter;
501-
module.exports = MongoStorageAdapter; // Required for tests

0 commit comments

Comments
 (0)