Skip to content

Commit e153535

Browse files
authored
Merge branch 'alpha' into afterLiveQueryEventLogging
2 parents 08b39ce + e9d2383 commit e153535

16 files changed

+431
-102
lines changed

changelogs/CHANGELOG_beta.md

Lines changed: 176 additions & 0 deletions
Large diffs are not rendered by default.

changelogs/CHANGELOG_release.md

Lines changed: 155 additions & 0 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse-server",
3-
"version": "5.0.0-alpha.29",
3+
"version": "5.1.1",
44
"description": "An express module providing a Parse-compatible API server",
55
"main": "lib/index.js",
66
"repository": {

spec/AuthenticationAdapters.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1722,7 +1722,9 @@ describe('Apple Game Center Auth adapter', () => {
17221722
await gcenter.validateAuthData(authData);
17231723
fail();
17241724
} catch (e) {
1725-
expect(e.message).toBe('Apple Game Center - invalid publicKeyUrl: http://static.gc.apple.com/public-key/gc-prod-4.cer');
1725+
expect(e.message).toBe(
1726+
'Apple Game Center - invalid publicKeyUrl: http://static.gc.apple.com/public-key/gc-prod-4.cer'
1727+
);
17261728
}
17271729
});
17281730
});

spec/Idempotency.spec.js

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -93,28 +93,31 @@ describe('Idempotency', () => {
9393
expect(counter).toBe(2);
9494
});
9595

96-
it_only_db('postgres')('should delete request entry when postgress ttl function is called', async () => {
97-
const client = Config.get(Parse.applicationId).database.adapter._client;
98-
let counter = 0;
99-
Parse.Cloud.define('myFunction', () => {
100-
counter++;
101-
});
102-
const params = {
103-
method: 'POST',
104-
url: 'http://localhost:8378/1/functions/myFunction',
105-
headers: {
106-
'X-Parse-Application-Id': Parse.applicationId,
107-
'X-Parse-Master-Key': Parse.masterKey,
108-
'X-Parse-Request-Id': 'abc-123',
109-
},
110-
};
111-
await expectAsync(request(params)).toBeResolved();
112-
await expectAsync(request(params)).toBeRejected();
113-
await new Promise(resolve => setTimeout(resolve, maxTimeOut));
114-
await client.one('SELECT idempotency_delete_expired_records()');
115-
await expectAsync(request(params)).toBeResolved();
116-
expect(counter).toBe(2);
117-
});
96+
it_only_db('postgres')(
97+
'should delete request entry when postgress ttl function is called',
98+
async () => {
99+
const client = Config.get(Parse.applicationId).database.adapter._client;
100+
let counter = 0;
101+
Parse.Cloud.define('myFunction', () => {
102+
counter++;
103+
});
104+
const params = {
105+
method: 'POST',
106+
url: 'http://localhost:8378/1/functions/myFunction',
107+
headers: {
108+
'X-Parse-Application-Id': Parse.applicationId,
109+
'X-Parse-Master-Key': Parse.masterKey,
110+
'X-Parse-Request-Id': 'abc-123',
111+
},
112+
};
113+
await expectAsync(request(params)).toBeResolved();
114+
await expectAsync(request(params)).toBeRejected();
115+
await new Promise(resolve => setTimeout(resolve, maxTimeOut));
116+
await client.one('SELECT idempotency_delete_expired_records()');
117+
await expectAsync(request(params)).toBeResolved();
118+
expect(counter).toBe(2);
119+
}
120+
);
118121

119122
it('should enforce idempotency for cloud code jobs', async () => {
120123
let counter = 0;

spec/ParseQuery.spec.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4777,7 +4777,7 @@ describe('Parse.Query testing', () => {
47774777
ttl: new Date(now - 2 * 24 * 60 * 60 * 1000), // 2 days ago
47784778
});
47794779

4780-
await Parse.Object.saveAll([obj1, obj2])
4780+
await Parse.Object.saveAll([obj1, obj2]);
47814781
const q1 = new Parse.Query('MyCustomObject');
47824782
q1.greaterThan('ttl', { $relativeTime: 'in 1 day' });
47834783
const results1 = await q1.find({ useMasterKey: true });
@@ -4825,8 +4825,8 @@ describe('Parse.Query testing', () => {
48254825
q.greaterThan('ttl', { $relativeTime: '-12 bananas ago' });
48264826
try {
48274827
await q.find({ useMasterKey: true });
4828-
fail("Should have thrown error");
4829-
} catch(error) {
4828+
fail('Should have thrown error');
4829+
} catch (error) {
48304830
expect(error.code).toBe(Parse.Error.INVALID_JSON);
48314831
}
48324832
});
@@ -4842,8 +4842,8 @@ describe('Parse.Query testing', () => {
48424842
q.greaterThan('nonDateField', { $relativeTime: '1 day ago' });
48434843
try {
48444844
await q.find({ useMasterKey: true });
4845-
fail("Should have thrown error");
4846-
} catch(error) {
4845+
fail('Should have thrown error');
4846+
} catch (error) {
48474847
expect(error.code).toBe(Parse.Error.INVALID_JSON);
48484848
}
48494849
});

spec/ParseServerRESTController.spec.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,7 @@ describe('ParseServerRESTController', () => {
186186
databaseAdapter.createObject.calls.argsFor(i + 1)[3]
187187
);
188188
}
189-
expect(results.map(result => result.get('key')).sort()).toEqual([
190-
'value1',
191-
'value2',
192-
]);
189+
expect(results.map(result => result.get('key')).sort()).toEqual(['value1', 'value2']);
193190
});
194191

195192
it('should not save anything when one operation fails in a transaction', async () => {

spec/PostgresInitOptions.spec.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ const GameScore = Parse.Object.extend({
2424
});
2525

2626
describe_only_db('postgres')('Postgres database init options', () => {
27-
2827
it('should create server with public schema databaseOptions', async () => {
2928
const adapter = new PostgresStorageAdapter({
3029
uri: postgresURI,
@@ -71,8 +70,8 @@ describe_only_db('postgres')('Postgres database init options', () => {
7170
await reconfigureServer({
7271
databaseAdapter: adapter,
7372
});
74-
fail("Should have thrown error");
75-
} catch(error) {
73+
fail('Should have thrown error');
74+
} catch (error) {
7675
expect(error).toBeDefined();
7776
}
7877
});

spec/PostgresStorageAdapter.spec.js

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
179179
{
180180
createdAt: {
181181
$eq: {
182-
$relativeTime: '12 days ago'
183-
}
184-
}
182+
$relativeTime: '12 days ago',
183+
},
184+
},
185185
},
186-
{ }
186+
{}
187187
);
188-
fail("Should have thrown error");
189-
} catch(error) {
188+
fail('Should have thrown error');
189+
} catch (error) {
190190
expect(error.code).toBe(Parse.Error.INVALID_JSON);
191191
}
192192
await dropTable(client, tableName);
@@ -222,14 +222,14 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
222222
{
223223
createdAt: {
224224
$ne: {
225-
$relativeTime: '12 days ago'
226-
}
227-
}
225+
$relativeTime: '12 days ago',
226+
},
227+
},
228228
},
229-
{ }
229+
{}
230230
);
231-
fail("Should have thrown error");
232-
} catch(error) {
231+
fail('Should have thrown error');
232+
} catch (error) {
233233
expect(error.code).toBe(Parse.Error.INVALID_JSON);
234234
}
235235
await dropTable(client, tableName);
@@ -265,14 +265,14 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
265265
{
266266
createdAt: {
267267
$exists: {
268-
$relativeTime: '12 days ago'
269-
}
270-
}
268+
$relativeTime: '12 days ago',
269+
},
270+
},
271271
},
272-
{ }
272+
{}
273273
);
274-
fail("Should have thrown error");
275-
} catch(error) {
274+
fail('Should have thrown error');
275+
} catch (error) {
276276
expect(error.code).toBe(Parse.Error.INVALID_JSON);
277277
}
278278
await dropTable(client, tableName);
@@ -563,9 +563,10 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
563563
await reconfigureServer();
564564
const adapter = Config.get('test').database.adapter;
565565
const client = adapter._client;
566-
const qs = "SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid) WHERE p.proname = 'idempotency_delete_expired_records'";
566+
const qs =
567+
"SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid) WHERE p.proname = 'idempotency_delete_expired_records'";
567568
const foundFunction = await client.one(qs);
568-
expect(foundFunction.format).toBe("public.idempotency_delete_expired_records()");
569+
expect(foundFunction.format).toBe('public.idempotency_delete_expired_records()');
569570
await adapter.deleteIdempotencyFunction();
570571
await client.none(qs);
571572
});

spec/batch.spec.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,7 @@ describe('batch', () => {
267267
databaseAdapter.createObject.calls.argsFor(i + 1)[3]
268268
);
269269
}
270-
expect(results.map(result => result.get('key')).sort()).toEqual([
271-
'value1',
272-
'value2',
273-
]);
270+
expect(results.map(result => result.get('key')).sort()).toEqual(['value1', 'value2']);
274271
});
275272

276273
it('should not save anything when one operation fails in a transaction', async () => {

src/Adapters/Auth/gcenter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function verifyPublicKeyUrl(publicKeyUrl) {
2828
const domainParts = hostnameParts.slice(length - 2, length);
2929
const domain = domainParts.join('.');
3030
return domain === 'apple.com';
31-
} catch(error) {
31+
} catch (error) {
3232
return false;
3333
}
3434
}

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,55 +2440,48 @@ export class PostgresStorageAdapter implements StorageAdapter {
24402440
? fieldNames.map((fieldName, index) => `lower($${index + 3}:name) varchar_pattern_ops`)
24412441
: fieldNames.map((fieldName, index) => `$${index + 3}:name`);
24422442
const qs = `CREATE INDEX IF NOT EXISTS $1:name ON $2:name (${constraintPatterns.join()})`;
2443-
const setIdempotencyFunction = options.setIdempotencyFunction !== undefined ? options.setIdempotencyFunction : false;
2443+
const setIdempotencyFunction =
2444+
options.setIdempotencyFunction !== undefined ? options.setIdempotencyFunction : false;
24442445
if (setIdempotencyFunction) {
24452446
await this.ensureIdempotencyFunctionExists(options);
24462447
}
2447-
await conn.none(qs, [indexNameOptions.name, className, ...fieldNames])
2448-
.catch(error => {
2449-
if (
2450-
error.code === PostgresDuplicateRelationError &&
2451-
error.message.includes(indexNameOptions.name)
2452-
) {
2453-
// Index already exists. Ignore error.
2454-
} else if (
2455-
error.code === PostgresUniqueIndexViolationError &&
2456-
error.message.includes(indexNameOptions.name)
2457-
) {
2458-
// Cast the error into the proper parse error
2459-
throw new Parse.Error(
2460-
Parse.Error.DUPLICATE_VALUE,
2461-
'A duplicate value for a field with unique values was provided'
2462-
);
2463-
} else {
2464-
throw error;
2465-
}
2466-
});
2448+
await conn.none(qs, [indexNameOptions.name, className, ...fieldNames]).catch(error => {
2449+
if (
2450+
error.code === PostgresDuplicateRelationError &&
2451+
error.message.includes(indexNameOptions.name)
2452+
) {
2453+
// Index already exists. Ignore error.
2454+
} else if (
2455+
error.code === PostgresUniqueIndexViolationError &&
2456+
error.message.includes(indexNameOptions.name)
2457+
) {
2458+
// Cast the error into the proper parse error
2459+
throw new Parse.Error(
2460+
Parse.Error.DUPLICATE_VALUE,
2461+
'A duplicate value for a field with unique values was provided'
2462+
);
2463+
} else {
2464+
throw error;
2465+
}
2466+
});
24672467
}
24682468
2469-
async deleteIdempotencyFunction(
2470-
options?: Object = {}
2471-
): Promise<any> {
2469+
async deleteIdempotencyFunction(options?: Object = {}): Promise<any> {
24722470
const conn = options.conn !== undefined ? options.conn : this._client;
24732471
const qs = 'DROP FUNCTION IF EXISTS idempotency_delete_expired_records()';
2474-
return conn
2475-
.none(qs)
2476-
.catch(error => {
2477-
throw error;
2478-
});
2472+
return conn.none(qs).catch(error => {
2473+
throw error;
2474+
});
24792475
}
24802476
2481-
async ensureIdempotencyFunctionExists(
2482-
options?: Object = {}
2483-
): Promise<any> {
2477+
async ensureIdempotencyFunctionExists(options?: Object = {}): Promise<any> {
24842478
const conn = options.conn !== undefined ? options.conn : this._client;
24852479
const ttlOptions = options.ttl !== undefined ? `${options.ttl} seconds` : '60 seconds';
2486-
const qs = 'CREATE OR REPLACE FUNCTION idempotency_delete_expired_records() RETURNS void LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE expire < NOW() - INTERVAL $1; END; $$;';
2487-
return conn
2488-
.none(qs, [ttlOptions])
2489-
.catch(error => {
2490-
throw error;
2491-
});
2480+
const qs =
2481+
'CREATE OR REPLACE FUNCTION idempotency_delete_expired_records() RETURNS void LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE expire < NOW() - INTERVAL $1; END; $$;';
2482+
return conn.none(qs, [ttlOptions]).catch(error => {
2483+
throw error;
2484+
});
24922485
}
24932486
}
24942487

src/Controllers/DatabaseController.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ class DatabaseController {
375375
// multiple schemas, so instead use loadSchema to get a schema.
376376
this.schemaPromise = null;
377377
this._transactionalSession = null;
378+
this.options = options;
378379
}
379380

380381
collectionExists(className: string): Promise<boolean> {

src/batch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function mountOnto(router) {
1313
function parseURL(urlString) {
1414
try {
1515
return new URL(urlString);
16-
} catch(error) {
16+
} catch (error) {
1717
return undefined;
1818
}
1919
}

src/middlewares.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,12 @@ export function promiseEnforceMasterKeyAccess(request) {
432432
*/
433433
export function promiseEnsureIdempotency(req) {
434434
// Enable feature only for MongoDB
435-
if (!((req.config.database.adapter instanceof MongoStorageAdapter) || (req.config.database.adapter instanceof PostgresStorageAdapter))) {
435+
if (
436+
!(
437+
req.config.database.adapter instanceof MongoStorageAdapter ||
438+
req.config.database.adapter instanceof PostgresStorageAdapter
439+
)
440+
) {
436441
return Promise.resolve();
437442
}
438443
// Get parameters

0 commit comments

Comments
 (0)