chore: Fixes issue related to flow types (#4724)

* Fixes issue related to flow types

* Improves type inference on where clause, index

* run parse-server start on liveQueryServer only on mongo, state leaks on postgres
This commit is contained in:
Florent Vilmart
2018-05-01 07:37:38 -04:00
committed by GitHub
parent 04588bccb9
commit fad7b46c65
4 changed files with 56 additions and 43 deletions

View File

@@ -102,46 +102,47 @@ describe('ParseLiveQueryServer', function() {
parseLiveQueryServer.server.close(done); parseLiveQueryServer.server.close(done);
}); });
it('can be initialized through ParseServer without liveQueryServerOptions', function(done) { describe_only_db('mongo')('initialization', () => {
const parseServer = ParseServer.start({ it('can be initialized through ParseServer without liveQueryServerOptions', function(done) {
appId: 'hello', const parseServer = ParseServer.start({
masterKey: 'world', appId: 'hello',
port: 22345, masterKey: 'world',
mountPath: '/1', port: 22345,
serverURL: 'http://localhost:12345/1', mountPath: '/1',
liveQuery: { serverURL: 'http://localhost:12345/1',
classNames: ['Yolo'] liveQuery: {
}, classNames: ['Yolo']
startLiveQueryServer: true },
startLiveQueryServer: true
});
expect(parseServer.liveQueryServer).not.toBeUndefined();
expect(parseServer.liveQueryServer.server).toBe(parseServer.server);
parseServer.server.close(() => done());
}); });
expect(parseServer.liveQueryServer).not.toBeUndefined(); it('can be initialized through ParseServer with liveQueryServerOptions', function(done) {
expect(parseServer.liveQueryServer.server).toBe(parseServer.server); const parseServer = ParseServer.start({
parseServer.server.close(() => done()); 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) { expect(parseServer.liveQueryServer).not.toBeUndefined();
const parseServer = ParseServer.start({ expect(parseServer.liveQueryServer.server).not.toBe(parseServer.server);
appId: 'hello', parseServer.liveQueryServer.server.close();
masterKey: 'world', parseServer.server.close(() => done());
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());
}); });
it('can handle connect command', function() { it('can handle connect command', function() {
const parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {}); const parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {});
const parseWebSocket = { const parseWebSocket = {

View File

@@ -161,7 +161,7 @@ export class MongoStorageAdapter implements StorageAdapter {
return this.connectionPromise; return this.connectionPromise;
} }
handleError<T>(error: ?Error): Promise<T> { handleError<T>(error: ?(Error | Parse.Error)): Promise<T> {
if (error && error.code === 13) { // Unauthorized error if (error && error.code === 13) { // Unauthorized error
delete this.client; delete this.client;
delete this.database; delete this.database;

View File

@@ -233,7 +233,13 @@ const joinTablesForSchema = (schema) => {
return list; return list;
} }
const buildWhereClause = ({ schema, query, index }) => { interface WhereClause {
pattern: string;
values: Array<any>;
sorts: Array<any>;
}
const buildWhereClause = ({ schema, query, index }): WhereClause => {
const patterns = []; const patterns = [];
let values = []; let values = [];
const sorts = []; const sorts = [];
@@ -611,6 +617,9 @@ const buildWhereClause = ({ schema, query, index }) => {
} }
export class PostgresStorageAdapter implements StorageAdapter { export class PostgresStorageAdapter implements StorageAdapter {
canSortOnJoinTables: boolean;
// Private // Private
_collectionPrefix: string; _collectionPrefix: string;
_client: any; _client: any;
@@ -625,6 +634,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
const { client, pgp } = createClient(uri, databaseOptions); const { client, pgp } = createClient(uri, databaseOptions);
this._client = client; this._client = client;
this._pgp = pgp; this._pgp = pgp;
this.canSortOnJoinTables = false;
} }
handleShutdown() { handleShutdown() {
@@ -862,7 +872,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
return this._client.task('delete-all-classes', function * (t) { return this._client.task('delete-all-classes', function * (t) {
try { try {
const results = yield t.any('SELECT * FROM "_SCHEMA"'); const results = yield t.any('SELECT * FROM "_SCHEMA"');
const joins = results.reduce((list, schema) => { const joins = results.reduce((list: Array<string>, schema: any) => {
return list.concat(joinTablesForSchema(schema.schema)); return list.concat(joinTablesForSchema(schema.schema));
}, []); }, []);
const classes = ['_SCHEMA', '_PushStatus', '_JobStatus', '_JobSchedule', '_Hooks', '_GlobalConfig', '_Audience', ...results.map(result => result.className), ...joins]; 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. // Returns a Promise.
deleteFields(className: string, schema: SchemaType, fieldNames: string[]): Promise<void> { deleteFields(className: string, schema: SchemaType, fieldNames: string[]): Promise<void> {
debug('deleteFields', className, fieldNames); debug('deleteFields', className, fieldNames);
fieldNames = fieldNames.reduce((list, fieldName) => { fieldNames = fieldNames.reduce((list: Array<string>, fieldName: string) => {
const field = schema.fields[fieldName] const field = schema.fields[fieldName]
if (field.type !== 'Relation') { if (field.type !== 'Relation') {
list.push(fieldName); list.push(fieldName);
@@ -1149,14 +1159,14 @@ export class PostgresStorageAdapter implements StorageAdapter {
} else if (fieldName == 'authData') { } else if (fieldName == 'authData') {
// This recursively sets the json_object // This recursively sets the json_object
// Only 1 level deep // 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`; return `json_object_set_key(COALESCE(${jsonb}, '{}'::jsonb), ${key}, ${value})::jsonb`;
} }
const lastKey = `$${index}:name`; const lastKey = `$${index}:name`;
const fieldNameIndex = index; const fieldNameIndex = index;
index += 1; index += 1;
values.push(fieldName); 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`) const str = generate(lastKey, `$${index}::text`, `$${index + 1}::jsonb`)
index += 2; index += 2;
let value = fieldValue[key]; let value = fieldValue[key];
@@ -1259,13 +1269,13 @@ export class PostgresStorageAdapter implements StorageAdapter {
}); });
} }
const keysToDelete = Object.keys(originalUpdate).filter(k => { const keysToDelete: Array<string> = Object.keys(originalUpdate).filter(k => {
// choose top level fields that have a delete operation set. // choose top level fields that have a delete operation set.
const value = originalUpdate[k]; const value = originalUpdate[k];
return value && value.__op === 'Delete' && k.split('.').length === 2 && k.split(".")[0] === fieldName; return value && value.__op === 'Delete' && k.split('.').length === 2 && k.split(".")[0] === fieldName;
}).map(k => k.split('.')[1]); }).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'`; return p + ` - '$${index + 1 + i}:value'`;
}, ''); }, '');
@@ -1556,7 +1566,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
aggregate(className: string, schema: any, pipeline: any) { aggregate(className: string, schema: any, pipeline: any) {
debug('aggregate', className, pipeline); debug('aggregate', className, pipeline);
const values = [className]; const values = [className];
let index = 2; let index: number = 2;
let columns: string[] = []; let columns: string[] = [];
let countField = null; let countField = null;
let groupValues = null; let groupValues = null;

View File

@@ -24,6 +24,8 @@ export type UpdateQueryOptions = {
export type FullQueryOptions = QueryOptions & UpdateQueryOptions; export type FullQueryOptions = QueryOptions & UpdateQueryOptions;
export interface StorageAdapter { export interface StorageAdapter {
canSortOnJoinTables: boolean;
classExists(className: string): Promise<boolean>; classExists(className: string): Promise<boolean>;
setClassLevelPermissions(className: string, clps: any): Promise<void>; setClassLevelPermissions(className: string, clps: any): Promise<void>;
createClass(className: string, schema: SchemaType): Promise<void>; createClass(className: string, schema: SchemaType): Promise<void>;