From de597cf9e78b7c600c7f8f1c4cc6931ef75a83a3 Mon Sep 17 00:00:00 2001 From: ga262 <37159881+ga262@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:29:13 +0200 Subject: [PATCH 1/3] Add tests for push adapter configuration handling Signed-off-by: ga262 <37159881+ga262@users.noreply.github.com> --- spec/index.spec.js | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/spec/index.spec.js b/spec/index.spec.js index 988f35cc3e..d143d39fb1 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -4,6 +4,7 @@ const parseServerPackage = require('../package.json'); const MockEmailAdapterWithOptions = require('./support/MockEmailAdapterWithOptions'); const ParseServer = require('../lib/index'); const Config = require('../lib/Config'); +const adapterLoader = require('../lib/Adapters/AdapterLoader'); const express = require('express'); const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; @@ -211,6 +212,52 @@ describe('server', () => { .catch(done.fail); }); + it('can start when push is not configured and optional push adapter is missing', async () => { + const originalLoadModule = adapterLoader.loadModule; + const loadModuleSpy = spyOn(adapterLoader, 'loadModule').and.callFake(modulePath => { + if (modulePath === '@parse/push-adapter') { + const error = new Error("Cannot find package '@parse/push-adapter'"); + error.code = 'ERR_MODULE_NOT_FOUND'; + return Promise.reject(error); + } + return originalLoadModule(modulePath); + }); + + try { + await reconfigureServer({ + push: undefined, + }); + const config = Config.get('test'); + expect(config.hasPushSupport).toEqual(false); + } finally { + loadModuleSpy.and.callThrough(); + } + }); + + it('throws clear error when push is configured and optional push adapter is missing', async () => { + const originalLoadModule = adapterLoader.loadModule; + const loadModuleSpy = spyOn(adapterLoader, 'loadModule').and.callFake(modulePath => { + if (modulePath === '@parse/push-adapter') { + const error = new Error("Cannot find package '@parse/push-adapter'"); + error.code = 'ERR_MODULE_NOT_FOUND'; + return Promise.reject(error); + } + return originalLoadModule(modulePath); + }); + + try { + await expectAsync( + reconfigureServer({ + push: {}, + }) + ).toBeRejectedWithError( + 'Push is configured but the optional dependency "@parse/push-adapter" is not installed. Install "@parse/push-adapter" or configure "push.adapter".' + ); + } finally { + loadModuleSpy.and.callThrough(); + } + }); + it('can properly sets the push support ', done => { reconfigureServer({ push: { From b5fff7b89443116049134d55be8355071fc82fca Mon Sep 17 00:00:00 2001 From: ga262 <37159881+ga262@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:30:01 +0200 Subject: [PATCH 2/3] Implement error handling for missing push adapter Added a function to check for missing push adapter module and handle errors accordingly. Signed-off-by: ga262 <37159881+ga262@users.noreply.github.com> --- src/Controllers/index.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Controllers/index.js b/src/Controllers/index.js index 9397dac561..4581f126ff 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -169,6 +169,13 @@ interface PushControlling { pushWorker: PushWorker; } +function isPushAdapterModuleMissing(error: any): boolean { + const message = `${error?.message || error || ''}`; + const hasMissingCode = + error?.code === 'ERR_MODULE_NOT_FOUND' || error?.code === 'MODULE_NOT_FOUND'; + return hasMissingCode && message.includes('@parse/push-adapter'); +} + export async function getPushController(options: ParseServerOptions): PushControlling { const { scheduledPush, push } = options; @@ -179,7 +186,19 @@ export async function getPushController(options: ParseServerOptions): PushContro } // Pass the push options too as it works with the default - const ParsePushAdapter = await loadModule('@parse/push-adapter'); + let ParsePushAdapter; + try { + ParsePushAdapter = await loadModule('@parse/push-adapter'); + } catch (error) { + if (!isPushAdapterModuleMissing(error)) { + throw error; + } + if (push && !pushOptions.adapter) { + throw new Error( + 'Push is configured but the optional dependency "@parse/push-adapter" is not installed. Install "@parse/push-adapter" or configure "push.adapter".' + ); + } + } const pushAdapter = loadAdapter( pushOptions && pushOptions.adapter, ParsePushAdapter, @@ -195,7 +214,7 @@ export async function getPushController(options: ParseServerOptions): PushContro const pushControllerQueue = new PushQueue(pushQueueOptions); let pushWorker; - if (!disablePushWorker) { + if (!disablePushWorker && hasPushSupport) { pushWorker = new PushWorker(pushAdapter, pushQueueOptions); } return { From 79542501af1a8c004971d71746ac8f45892a6fa3 Mon Sep 17 00:00:00 2001 From: ga262 <37159881+ga262@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:31:42 +0200 Subject: [PATCH 3/3] Refactor dependencies in package.json Removed '@parse/push-adapter' from dependencies and added it to optionalDependencies. Signed-off-by: ga262 <37159881+ga262@users.noreply.github.com> --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 90ce473b0d..6cf9285199 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "@graphql-tools/schema": "10.0.31", "@graphql-tools/utils": "11.0.0", "@parse/fs-files-adapter": "3.0.0", - "@parse/push-adapter": "8.4.0", "bcryptjs": "3.0.3", "commander": "14.0.3", "cors": "2.8.6", @@ -146,7 +145,8 @@ "parse-server": "bin/parse-server" }, "optionalDependencies": { - "@node-rs/bcrypt": "1.10.7" + "@node-rs/bcrypt": "1.10.7", + "@parse/push-adapter": "8.4.0" }, "collective": { "type": "opencollective",