Skip to content

Commit 554b4ce

Browse files
authored
Merge branch 'alpha' into snyk-upgrade-655fc5a50e40056da3e25314038d19db
2 parents 991cd2f + b559fbf commit 554b4ce

25 files changed

+759
-530
lines changed

changelogs/CHANGELOG_alpha.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# [8.1.0-alpha.3](https://github.com/parse-community/parse-server/compare/8.1.0-alpha.2...8.1.0-alpha.3) (2025-03-27)
2+
3+
4+
### Bug Fixes
5+
6+
* Parse Server doesn't shutdown gracefully ([#9634](https://github.com/parse-community/parse-server/issues/9634)) ([aed918d](https://github.com/parse-community/parse-server/commit/aed918d3109e739f7231d481b5f48c68fc01cf04))
7+
8+
# [8.1.0-alpha.2](https://github.com/parse-community/parse-server/compare/8.1.0-alpha.1...8.1.0-alpha.2) (2025-03-27)
9+
10+
11+
### Features
12+
13+
* Add Cloud Code triggers `Parse.Cloud.beforeFind(Parse.File)`and `Parse.Cloud.afterFind(Parse.File)` ([#8700](https://github.com/parse-community/parse-server/issues/8700)) ([b2beaa8](https://github.com/parse-community/parse-server/commit/b2beaa86ff543a7aa4ad274c7a23bc4aa302c3fa))
14+
115
# [8.1.0-alpha.1](https://github.com/parse-community/parse-server/compare/8.0.2...8.1.0-alpha.1) (2025-03-24)
216

317

package-lock.json

Lines changed: 248 additions & 262 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse-server",
3-
"version": "8.1.0-alpha.1",
3+
"version": "8.1.0-alpha.3",
44
"description": "An express module providing a Parse-compatible API server",
55
"main": "lib/index.js",
66
"repository": {
@@ -24,7 +24,7 @@
2424
"@babel/eslint-parser": "7.26.10",
2525
"@graphql-tools/merge": "9.0.24",
2626
"@graphql-tools/schema": "10.0.23",
27-
"@graphql-tools/utils": "10.6.3",
27+
"@graphql-tools/utils": "10.8.4",
2828
"@parse/fs-files-adapter": "3.0.0",
2929
"@parse/push-adapter": "6.11.0",
3030
"bcryptjs": "3.0.2",
@@ -41,7 +41,7 @@
4141
"graphql-upload": "15.0.2",
4242
"intersect": "1.0.1",
4343
"jsonwebtoken": "9.0.2",
44-
"jwks-rsa": "3.1.0",
44+
"jwks-rsa": "3.2.0",
4545
"ldapjs": "3.0.7",
4646
"lodash": "4.17.21",
4747
"lru-cache": "10.4.0",
@@ -57,7 +57,7 @@
5757
"punycode": "2.3.1",
5858
"rate-limit-redis": "4.2.0",
5959
"redis": "4.7.0",
60-
"router": "2.1.0",
60+
"router": "2.2.0",
6161
"semver": "7.7.1",
6262
"subscriptions-transport-ws": "0.11.0",
6363
"tv4": "1.3.0",
@@ -69,12 +69,12 @@
6969
"devDependencies": {
7070
"@actions/core": "1.11.1",
7171
"@apollo/client": "3.13.4",
72-
"@babel/cli": "7.26.4",
72+
"@babel/cli": "7.27.0",
7373
"@babel/core": "7.26.8",
7474
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
7575
"@babel/plugin-transform-flow-strip-types": "7.26.5",
7676
"@babel/preset-env": "7.26.0",
77-
"@babel/preset-typescript": "7.26.0",
77+
"@babel/preset-typescript": "7.27.0",
7878
"@saithodev/semantic-release-backmerge": "4.0.1",
7979
"@semantic-release/changelog": "6.0.3",
8080
"@semantic-release/commit-analyzer": "13.0.1",
@@ -87,7 +87,7 @@
8787
"clean-jsdoc-theme": "4.3.0",
8888
"cross-env": "7.0.3",
8989
"deep-diff": "1.0.2",
90-
"eslint": "9.20.0",
90+
"eslint": "9.23.0",
9191
"flow-bin": "0.119.1",
9292
"form-data": "4.0.2",
9393
"globals": "16.0.0",
@@ -97,7 +97,7 @@
9797
"jasmine-spec-reporter": "7.0.0",
9898
"jsdoc": "4.0.4",
9999
"jsdoc-babel": "0.5.0",
100-
"lint-staged": "15.4.3",
100+
"lint-staged": "15.5.0",
101101
"m": "1.9.0",
102102
"madge": "8.0.0",
103103
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",

spec/CloudCode.spec.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3929,6 +3929,126 @@ describe('saveFile hooks', () => {
39293929
});
39303930
});
39313931

3932+
describe('Parse.File hooks', () => {
3933+
it('find hooks should run', async () => {
3934+
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
3935+
await file.save({ useMasterKey: true });
3936+
const user = await Parse.User.signUp('username', 'password');
3937+
const hooks = {
3938+
beforeFind(req) {
3939+
expect(req).toBeDefined();
3940+
expect(req.file).toBeDefined();
3941+
expect(req.triggerName).toBe('beforeFind');
3942+
expect(req.master).toBeFalse();
3943+
expect(req.log).toBeDefined();
3944+
},
3945+
afterFind(req) {
3946+
expect(req).toBeDefined();
3947+
expect(req.file).toBeDefined();
3948+
expect(req.triggerName).toBe('afterFind');
3949+
expect(req.master).toBeFalse();
3950+
expect(req.log).toBeDefined();
3951+
expect(req.forceDownload).toBeFalse();
3952+
},
3953+
};
3954+
for (const hook in hooks) {
3955+
spyOn(hooks, hook).and.callThrough();
3956+
Parse.Cloud[hook](Parse.File, hooks[hook]);
3957+
}
3958+
await request({
3959+
url: file.url(),
3960+
headers: {
3961+
'X-Parse-Application-Id': 'test',
3962+
'X-Parse-REST-API-Key': 'rest',
3963+
'X-Parse-Session-Token': user.getSessionToken(),
3964+
},
3965+
});
3966+
for (const hook in hooks) {
3967+
expect(hooks[hook]).toHaveBeenCalled();
3968+
}
3969+
});
3970+
3971+
it('beforeFind can throw', async () => {
3972+
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
3973+
await file.save({ useMasterKey: true });
3974+
const user = await Parse.User.signUp('username', 'password');
3975+
const hooks = {
3976+
beforeFind() {
3977+
throw 'unauthorized';
3978+
},
3979+
afterFind() {},
3980+
};
3981+
for (const hook in hooks) {
3982+
spyOn(hooks, hook).and.callThrough();
3983+
Parse.Cloud[hook](Parse.File, hooks[hook]);
3984+
}
3985+
await expectAsync(
3986+
request({
3987+
url: file.url(),
3988+
headers: {
3989+
'X-Parse-Application-Id': 'test',
3990+
'X-Parse-REST-API-Key': 'rest',
3991+
'X-Parse-Session-Token': user.getSessionToken(),
3992+
},
3993+
}).catch(e => {
3994+
throw new Parse.Error(e.data.code, e.data.error);
3995+
})
3996+
).toBeRejectedWith(new Parse.Error(Parse.Error.SCRIPT_FAILED, 'unauthorized'));
3997+
3998+
expect(hooks.beforeFind).toHaveBeenCalled();
3999+
expect(hooks.afterFind).not.toHaveBeenCalled();
4000+
});
4001+
4002+
it('afterFind can throw', async () => {
4003+
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
4004+
await file.save({ useMasterKey: true });
4005+
const user = await Parse.User.signUp('username', 'password');
4006+
const hooks = {
4007+
beforeFind() {},
4008+
afterFind() {
4009+
throw 'unauthorized';
4010+
},
4011+
};
4012+
for (const hook in hooks) {
4013+
spyOn(hooks, hook).and.callThrough();
4014+
Parse.Cloud[hook](Parse.File, hooks[hook]);
4015+
}
4016+
await expectAsync(
4017+
request({
4018+
url: file.url(),
4019+
headers: {
4020+
'X-Parse-Application-Id': 'test',
4021+
'X-Parse-REST-API-Key': 'rest',
4022+
'X-Parse-Session-Token': user.getSessionToken(),
4023+
},
4024+
}).catch(e => {
4025+
throw new Parse.Error(e.data.code, e.data.error);
4026+
})
4027+
).toBeRejectedWith(new Parse.Error(Parse.Error.SCRIPT_FAILED, 'unauthorized'));
4028+
for (const hook in hooks) {
4029+
expect(hooks[hook]).toHaveBeenCalled();
4030+
}
4031+
});
4032+
4033+
it('can force download', async () => {
4034+
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
4035+
await file.save({ useMasterKey: true });
4036+
const user = await Parse.User.signUp('username', 'password');
4037+
Parse.Cloud.afterFind(Parse.File, req => {
4038+
req.forceDownload = true;
4039+
});
4040+
const response = await request({
4041+
url: file.url(),
4042+
headers: {
4043+
'X-Parse-Application-Id': 'test',
4044+
'X-Parse-REST-API-Key': 'rest',
4045+
'X-Parse-Session-Token': user.getSessionToken(),
4046+
},
4047+
});
4048+
expect(response.headers['content-disposition']).toBe(`attachment;filename=${file._name}`);
4049+
});
4050+
});
4051+
39324052
describe('Cloud Config hooks', () => {
39334053
function testConfig() {
39344054
return Parse.Config.save({ internal: 'i', string: 's', number: 12 }, { internal: true });

spec/EnableExpressErrorHandler.spec.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ const request = require('../lib/request');
33
describe('Enable express error handler', () => {
44
it('should call the default handler in case of error, like updating a non existing object', async done => {
55
spyOn(console, 'error');
6-
const parseServer = await reconfigureServer(
7-
Object.assign({}, defaultConfiguration, {
8-
enableExpressErrorHandler: true,
9-
})
10-
);
6+
const parseServer = await reconfigureServer({
7+
enableExpressErrorHandler: true,
8+
});
119
parseServer.app.use(function (err, req, res, next) {
1210
expect(err.message).toBe('Object not found.');
1311
next(err);

spec/ParseAPI.spec.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ describe('miscellaneous', () => {
3333
expect(results.length).toEqual(1);
3434
expect(results[0]['foo']).toEqual('bar');
3535
});
36-
});
3736

38-
describe('miscellaneous', function () {
3937
it('create a GameScore object', function (done) {
4038
const obj = new Parse.Object('GameScore');
4139
obj.set('score', 1337);

spec/ParseConfigKey.spec.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ describe('Config Keys', () => {
1212

1313
it('recognizes invalid keys in root', async () => {
1414
await expectAsync(reconfigureServer({
15-
...defaultConfiguration,
1615
invalidKey: 1,
1716
})).toBeResolved();
1817
const error = loggerErrorSpy.calls.all().reduce((s, call) => s += call.args[0], '');
@@ -21,7 +20,6 @@ describe('Config Keys', () => {
2120

2221
it('recognizes invalid keys in pages.customUrls', async () => {
2322
await expectAsync(reconfigureServer({
24-
...defaultConfiguration,
2523
pages: {
2624
customUrls: {
2725
invalidKey: 1,
@@ -37,7 +35,6 @@ describe('Config Keys', () => {
3735

3836
it('recognizes invalid keys in liveQueryServerOptions', async () => {
3937
await expectAsync(reconfigureServer({
40-
...defaultConfiguration,
4138
liveQueryServerOptions: {
4239
invalidKey: 1,
4340
MasterKey: 1,
@@ -50,7 +47,6 @@ describe('Config Keys', () => {
5047

5148
it('recognizes invalid keys in rateLimit', async () => {
5249
await expectAsync(reconfigureServer({
53-
...defaultConfiguration,
5450
rateLimit: [
5551
{ invalidKey: 1 },
5652
{ RequestPath: 1 },
@@ -64,7 +60,7 @@ describe('Config Keys', () => {
6460
expect(error).toMatch('rateLimit\\[2\\]\\.RequestTimeWindow');
6561
});
6662

67-
it('recognizes valid keys in default configuration', async () => {
63+
it_only_db('mongo')('recognizes valid keys in default configuration', async () => {
6864
await expectAsync(reconfigureServer({
6965
...defaultConfiguration,
7066
})).toBeResolved();

0 commit comments

Comments
 (0)