diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index 9f347747..88f6faa1 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -102,46 +102,47 @@ describe('ParseLiveQueryServer', function() { parseLiveQueryServer.server.close(done); }); - it('can be initialized through ParseServer without liveQueryServerOptions', function(done) { - const parseServer = ParseServer.start({ - appId: 'hello', - masterKey: 'world', - port: 22345, - mountPath: '/1', - serverURL: 'http://localhost:12345/1', - liveQuery: { - classNames: ['Yolo'] - }, - startLiveQueryServer: true + describe_only_db('mongo')('initialization', () => { + it('can be initialized through ParseServer without liveQueryServerOptions', function(done) { + const parseServer = ParseServer.start({ + appId: 'hello', + masterKey: 'world', + port: 22345, + mountPath: '/1', + serverURL: 'http://localhost:12345/1', + liveQuery: { + classNames: ['Yolo'] + }, + startLiveQueryServer: true + }); + + expect(parseServer.liveQueryServer).not.toBeUndefined(); + expect(parseServer.liveQueryServer.server).toBe(parseServer.server); + parseServer.server.close(() => done()); }); - expect(parseServer.liveQueryServer).not.toBeUndefined(); - expect(parseServer.liveQueryServer.server).toBe(parseServer.server); - parseServer.server.close(() => done()); - }); + it('can be initialized through ParseServer with liveQueryServerOptions', function(done) { + const parseServer = ParseServer.start({ + appId: 'hello', + masterKey: 'world', + port: 22346, + mountPath: '/1', + serverURL: 'http://localhost:12345/1', + liveQuery: { + classNames: ['Yolo'] + }, + liveQueryServerOptions: { + port: 22347, + } + }); - it('can be initialized through ParseServer with liveQueryServerOptions', function(done) { - const parseServer = ParseServer.start({ - appId: 'hello', - masterKey: 'world', - port: 22346, - mountPath: '/1', - serverURL: 'http://localhost:12345/1', - liveQuery: { - classNames: ['Yolo'] - }, - liveQueryServerOptions: { - port: 22347, - } + expect(parseServer.liveQueryServer).not.toBeUndefined(); + expect(parseServer.liveQueryServer.server).not.toBe(parseServer.server); + parseServer.liveQueryServer.server.close(); + parseServer.server.close(() => done()); }); - - expect(parseServer.liveQueryServer).not.toBeUndefined(); - expect(parseServer.liveQueryServer.server).not.toBe(parseServer.server); - parseServer.liveQueryServer.server.close(); - parseServer.server.close(() => done()); }); - it('can handle connect command', function() { const parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {}); const parseWebSocket = { diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 3c543090..f9b37b58 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -161,7 +161,7 @@ export class MongoStorageAdapter implements StorageAdapter { return this.connectionPromise; } - handleError(error: ?Error): Promise { + handleError(error: ?(Error | Parse.Error)): Promise { if (error && error.code === 13) { // Unauthorized error delete this.client; delete this.database; diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index ccdfdbd6..6ae7f413 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -233,7 +233,13 @@ const joinTablesForSchema = (schema) => { return list; } -const buildWhereClause = ({ schema, query, index }) => { +interface WhereClause { + pattern: string; + values: Array; + sorts: Array; +} + +const buildWhereClause = ({ schema, query, index }): WhereClause => { const patterns = []; let values = []; const sorts = []; @@ -611,6 +617,9 @@ const buildWhereClause = ({ schema, query, index }) => { } export class PostgresStorageAdapter implements StorageAdapter { + + canSortOnJoinTables: boolean; + // Private _collectionPrefix: string; _client: any; @@ -625,6 +634,7 @@ export class PostgresStorageAdapter implements StorageAdapter { const { client, pgp } = createClient(uri, databaseOptions); this._client = client; this._pgp = pgp; + this.canSortOnJoinTables = false; } handleShutdown() { @@ -862,7 +872,7 @@ export class PostgresStorageAdapter implements StorageAdapter { return this._client.task('delete-all-classes', function * (t) { try { const results = yield t.any('SELECT * FROM "_SCHEMA"'); - const joins = results.reduce((list, schema) => { + const joins = results.reduce((list: Array, schema: any) => { return list.concat(joinTablesForSchema(schema.schema)); }, []); const classes = ['_SCHEMA', '_PushStatus', '_JobStatus', '_JobSchedule', '_Hooks', '_GlobalConfig', '_Audience', ...results.map(result => result.className), ...joins]; @@ -895,7 +905,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // Returns a Promise. deleteFields(className: string, schema: SchemaType, fieldNames: string[]): Promise { debug('deleteFields', className, fieldNames); - fieldNames = fieldNames.reduce((list, fieldName) => { + fieldNames = fieldNames.reduce((list: Array, fieldName: string) => { const field = schema.fields[fieldName] if (field.type !== 'Relation') { list.push(fieldName); @@ -1149,14 +1159,14 @@ export class PostgresStorageAdapter implements StorageAdapter { } else if (fieldName == 'authData') { // This recursively sets the json_object // Only 1 level deep - const generate = (jsonb, key, value) => { + const generate = (jsonb: string, key: string, value: any) => { return `json_object_set_key(COALESCE(${jsonb}, '{}'::jsonb), ${key}, ${value})::jsonb`; } const lastKey = `$${index}:name`; const fieldNameIndex = index; index += 1; values.push(fieldName); - const update = Object.keys(fieldValue).reduce((lastKey, key) => { + const update = Object.keys(fieldValue).reduce((lastKey: string, key: string) => { const str = generate(lastKey, `$${index}::text`, `$${index + 1}::jsonb`) index += 2; let value = fieldValue[key]; @@ -1259,13 +1269,13 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - const keysToDelete = Object.keys(originalUpdate).filter(k => { + const keysToDelete: Array = Object.keys(originalUpdate).filter(k => { // choose top level fields that have a delete operation set. const value = originalUpdate[k]; return value && value.__op === 'Delete' && k.split('.').length === 2 && k.split(".")[0] === fieldName; }).map(k => k.split('.')[1]); - const deletePatterns = keysToDelete.reduce((p, c, i) => { + const deletePatterns = keysToDelete.reduce((p: string, c: string, i: number) => { return p + ` - '$${index + 1 + i}:value'`; }, ''); @@ -1556,7 +1566,7 @@ export class PostgresStorageAdapter implements StorageAdapter { aggregate(className: string, schema: any, pipeline: any) { debug('aggregate', className, pipeline); const values = [className]; - let index = 2; + let index: number = 2; let columns: string[] = []; let countField = null; let groupValues = null; diff --git a/src/Adapters/Storage/StorageAdapter.js b/src/Adapters/Storage/StorageAdapter.js index 4123117d..95978fe0 100644 --- a/src/Adapters/Storage/StorageAdapter.js +++ b/src/Adapters/Storage/StorageAdapter.js @@ -24,6 +24,8 @@ export type UpdateQueryOptions = { export type FullQueryOptions = QueryOptions & UpdateQueryOptions; export interface StorageAdapter { + canSortOnJoinTables: boolean; + classExists(className: string): Promise; setClassLevelPermissions(className: string, clps: any): Promise; createClass(className: string, schema: SchemaType): Promise;