Having trouble updating my Parse Server

This is more a reflection of my lack of knowledge of node.js than anything else.

I’ve been running a parse server for my app for about 3 years now. It was originally based on parse-server-example. I periodically pull PSE and update my server based on the latest. I think the last successful update was about a year ago. This was using node 16.

The Only additions I’ve made to PSE are the following.

Parse Server Push Adapter

Simple Parse SMTP Adapter

Problem:
I have just pulled parse-server-example again and am having issues adding and configuring these two add-ons.

I noticed what appears to be a critical change to package.json

“type”: “module”, <----- require no longer works!

If you look at the above example code for the adapters, they use Require, and new Adapter(config). “type module” breaks this.

How can I uses these modules and config them using the latest parse-server-example and Node 18 or 19, just to keep current?

Example of a require (vs import) based config…

const PushAdapter = require(‘@parse/push-adapter’).default;
const pushOptions = {
ios: {
token: {
key: pushIosAppleP8FilePath,

},
}

When used in api config I do this…

var api = new ParseServer({

....

// parse-server-push-adapter
// GitHub - parse-community/parse-server-push-adapter: A push notification adapter for Parse Server
push: {
adapter: new PushAdapter(pushOptions),
}
}

Thanks;
-Chris

Parse Server example is really just an example of how to set up Parse Server. If you are using the repository as the base for a production deployment (i.e. an app with real users) then you may run into issues, such as being on older or even unsupported versions of Parse Server.

1 Like

Perhaps a better way to go is to use what I have working and update / test versions in package.json to reflect release versions of parse-server and the other two add ons.

When I do this, and move from node 16 to node 18 I get this error when starting parse.

The move to node 18 may have made the difference here. Not sure.

I try the following.

  1. Update versions in package.json
  2. remove node_modules and package-json.lock
    3 npm install
    and then I run the server as usual.

warn: DeprecationWarning: The Parse Server option ‘allowClientClassCreation’ default will change to ‘false’ in a future version.
warn: DeprecationWarning: The Parse Server option ‘allowExpiredAuthDataToken’ default will change to ‘false’ in a future version.
/home/chris/testServer20230528/ourhangoutsapp/node_modules/express/lib/router/index.js:446
throw new TypeError('Router.use() requires middleware function but got a ’ + gettype(fn));
^

TypeError: Router.use() requires middleware function but got a Object
at Function. (/home/chris/testServer20230528/ourhangoutsapp/node_modules/express/lib/router/index.js:446:13)
at Array.forEach ()
at Function.use (/home/chris/testServer20230528/ourhangoutsapp/node_modules/express/lib/router/index.js:444:13)
at Function. (/home/chris/testServer20230528/ourhangoutsapp/node_modules/express/lib/application.js:187:21)
at Array.forEach ()
at Function.use (/home/chris/testServer20230528/ourhangoutsapp/node_modules/express/lib/application.js:184:7)
at Object. (/home/chris/testServer20230528/ourhangoutsapp/index.js:293:5)
at Module._compile (node:internal/modules/cjs/loader:1254:14)

It would help if you shared your Parse Server setup, incl. code, server version and environment. I would also recommend to start with a basic deployment of Parse Server and then gradually add your code, to see what causes this issue. You said you have a “lack of knowledge of node.js”, which makes this more difficult, because it may be that you have some modifications that are not apparent. So you may want to start with a fresh installation of Parse Server, without any customization, that should start up fine. If not, that should be easier to debug. Then gradually add your code.

1 Like

Agree. That’s what I’m doing with parse server example. It runs fine when I start it up as is given my shell vars (mongo etc).

All I need to do is add and config my two packages.

I think if I replace require with
import { PushAdapter } from ‘@parse/push-adapter’;
I will end up with a Java class-like form of PushAdapter where I can say
adapter = new PushAdapter (config);
That should be the only change I need to make. Assuming this form of import is an “exact replacement” for require.

I’ll share setup too. Thanks very much for assist. I’ll be back online later.

Here’s my index.js
file:///home/chris/testServer20230528-2/ourhangoutsapp/index.js:291
adapter: new PushAdapter(pushOptions),

If I can just get past that, I should be good.
It’s probably simpler if someone can tell me how to use an import the way one can use a require.

/**

*/

// Example express application adding the parse-server module to expose Parse
// compatible API routes.

// const express = require(‘express’);
import express from ‘express’;

// const ParseServer = require(‘parse-server’).ParseServer;
import { ParseServer } from ‘parse-server’;

// const path = require(‘path’);
import path from ‘path’;

const __dirname = path.resolve();

import http from ‘http’;

// const utils = require("./utils");
// import { utils } from ‘./utils.js’;

// const PushAdapter = require(’@parse/push-adapter’).default;
// import { PushAdapter } from ‘@parse/push-adapter’;
// CANT get this to work !!! need to say new
import pkg from ‘@parse/push-adapter’;
const { PushAdapter } = pkg;

/**

  • Basic Parameters
    */
    const serverUrl = process.env.SERVER_URL;
    const databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;
    const publicHtmlURL = serverUrl + “/node_modules/parse-server/public_html”;
    const appPort = 1337;

/**

  • Parse Server Push Adapter
    */
    const verboseParseServerPushAdapter = parseInt(process.env.VERBOSE_PARSE_SERVER_PUSH_ADAPTER) || 1;

/**

  • Apple Push Notification Parameters
    */
    const pushIosAppleP8FilePath = process.env.PUSH_IOS_KEY_PATH;
    const pushIosKeyId = process.env.PUSH_IOS_KEYID;
    const pushIosTeamId = process.env.PUSH_IOS_TEAMID;
    const pushIosTopic = process.env.PUSH_IOS_TOPIC;
    // bool_value = value == “true” ? true : false No such thing as parseBoolean
    const pushIosProduction = process.env.PUSH_IOS_PRODUCTION == “true” ? true : false;

/**

  • Mail for Password Reset and Account Verification Parameters
    */
    const mailFromAddress = process.env.MAIL_FROM_ADDRESS;
    const mailUser = process.env.MAIL_USER;
    const mailPassword = process.env.MAIL_PASSWORD;
    const mailHost = process.env.MAIL_HOST;
    const mailPort = parseInt(process.env.MAIL_PORT);
    const mailName = process.env.MAIL_NAME;
    const mailResetSubject = process.env.MAIL_RESET_SUBJECT;
    const mailVerifySubject = process.env.MAIL_VERIFY_SUBJECT;
    // Prevent user from logging in if email not verified
    // preventLoginWithUnverifiedEmail = mailPreventUnverified
    const mailPreventUnverified = process.env.MAIL_PREVENT_UNVERIFIED == “true” ? true : false;
    // Send our verification request emails
    const mailVerifyUserEmails = process.env.MAIL_VERIFY_USER_EMAILS == “true” ? true : false;

// Set this if the e mail address to send to is other than
// the “emain” column in the DB. Then uncomment mailEmailField in the
// emailAdapter config section
// var mailEmailField = process.env.MAIL_EMAIL_FIELD;

/**

  • TLS/SSL for sending mail
    */
    // bool_value = value == “true” ? true : false - No such thing as parseBoolean
    const mailIsSsl = process.env.MAIL_IS_SSL == “true” ? true : false;
    const nodeExtraCaCerts = process.env.NODE_EXTRA_CA_CERTS;
    const nodeTlsRejectUnauthorized = parseInt(process.env.NODE_TLS_REJECT_UNAUTHORIZED);
    const openSslConf = process.env.OPENSSL_CONF

/**

  • Push Adapter Setup
  • GitHub - parse-community/parse-server-push-adapter: Official Push adapter for parse-server
    */
    // const PushAdapter = require(’@parse/push-adapter’).default;
    const pushOptions = {
    ios: {
    token: {
    key: pushIosAppleP8FilePath,
    keyId: pushIosKeyId,
    teamId: pushIosTeamId // The Team ID for your developer account
    },
    topic: pushIosTopic, // The bundle identifier associated with your app
    production: pushIosProduction
    }
    // Add Android Options here.
    }

/**

  • ShowVars
  • Show all variables defined
    */
    function showParams(x, y) {
    const stuff = `

Basoc Parameters
SERVER_URL…${serverUrl}
DATABASE_URI…${databaseUri}
publicHtmlURL…${publicHtmlURL}
appPort…${appPort}

Parse Server Push Adapter
VERBOSE_PARSE_SERVER_PUSH_ADAPTER…${verboseParseServerPushAdapter}

Apple Push Notification Parameters
PUSH_IOS_KEY_PATH…${pushIosAppleP8FilePath}
PUSH_IOS_KEYID…${pushIosKeyId}
IMPORTANT:
PUSH_IOS_KEYID should match the Q7NG4G83K9 part in PUSH_IOS_KEY_PATHs filename, AuthKey_Q7NG4G83K9.p8

PUSH_IOS_TEAMID…${pushIosTeamId}
PUSH_IOS_TOPIC…${pushIosTopic}
PUSH_IOS_PRODUCTION…${pushIosProduction}

Mail for Password Reset and Account Verification Parameters
MAIL_FROM_ADDRESS…${mailFromAddress}
MAIL_USER…${mailUser}
MAIL_PASSWORD…${mailPassword}
MAIL_HOST…${mailHost}
MAIL_PORT…${mailPort}
MAIL_NAME…${mailName}
MAIL_RESET_SUBJECT…${mailResetSubject}
MAIL_VERIFY_SUBJECT…${mailVerifySubject}
prevent unverified logins
MAIL_PREVENT_UNVERIFIED…${mailPreventUnverified}
send verification emails for new users
MAIL_VERIFY_USER_EMAILS…${mailVerifyUserEmails}

TLS/SSL for sending mail
MAIL_IS_SSL…${mailIsSsl}
NODE_EXTRA_CA_CERTS…${nodeExtraCaCerts}
NODE_TLS_REJECT_UNAUTHORIZED…${nodeTlsRejectUnauthorized}
TLS gets a wrong version number. FIgure this out.
What should this value be??? is undefined.
OPENSSL_CONF…${openSslConf}

IMPORTANT: Paths on FakeHeroku vs Real Heroku are different.
Heroku uses a container, Path starts: /app/certs/…
FakeHeroku uses nothing, Path starts: /home/chris/heroku-server/parse-server-example/certs/…

Currently the root directory is: ${__dirname}
`
console.log(stuff);
}

// Switch this off for prod
showParams()

/**

  • Setup the Parse Server
  • Some note someplace said…
  • “starting 3.0.0”
    • Is this what version we are??? Parse
      */
      var api = new ParseServer({

// Oct 28 2022 - Suggenly Parse Signup returns File upload by public is disabled
// Allowing public file upload fixes this.
fileUpload: {enableForPublic: true,},
databaseURI: databaseUri,
cloud: process.env.CLOUD_CODE_MAIN || __dirname + ‘/cloud/main.js’,
appId: process.env.APP_ID || ‘myAppId’,
masterKey: process.env.MASTER_KEY || ‘’, //Add your master key here. Keep it secret!
serverURL: process.env.SERVER_URL || ‘http://localhost:1337/parse’, // Don’t forget to change to https if needed
liveQuery: {
classNames: [“Posts”, “Comments”] // List of classes to support for query subscriptions
},

//This is the config for email adapter
appName: “OurHangouts”,
// publicServerURL: “http://localhost:1337/parse”,
publicServerURL: serverUrl,
port: appPort,

// See GitHub - parse-community/parse-server: Parse Server for Node.js / Express
// The account lock policy
accountLockout: {
// Lock the account for 5 minutes.
duration: 5,
// Lock an account after 3 failed log-in attempts
threshold: 3,
// Unlock the account after a successful password reset
unlockOnPasswordReset: true,
},

// The password policy
passwordPolicy: {
// Enforce a password of at least 8 characters which contain at least 1 lower case, 1 upper case and 1 digit
validatorPattern: /^(?=.[a-z])(?=.[A-Z])(?=.*[0-9])(?=.{8,})/,
// Do not allow the username as part of the password
doNotAllowUsername: true,
// Do not allow to re-use the last 5 passwords when setting a new password
maxPasswordHistory: 5,
},

// See GitHub - parse-community/parse-server: Parse Server for Node.js / Express
// under Email verification and Password reset
/*
Verifying user email addresses and enabling password reset via email requires
an email adapter. As part of the parse-server package we provide an adapter
for sending email through Mailgun. To use it, sign up for Mailgun, and add this
to your initialization code:
*/

// Enable email verification
// SET TO TRUE when ready
verifyUserEmails: mailVerifyUserEmails,

// if verifyUserEmails is true and
// if emailVerifyTokenValidityDuration is undefined then
// email verify token never expires
// else
// email verify token expires after emailVerifyTokenValidityDuration
//
// emailVerifyTokenValidityDuration defaults to undefined
//
// email verify token below expires in 2 hours (= 2 * 60 * 60 == 7200 seconds)
emailVerifyTokenValidityDuration: 2 * 60 * 60, // in seconds (2 hours = 7200 seconds)

// set preventLoginWithUnverifiedEmail to false to allow user to login without verifying their email
// set preventLoginWithUnverifiedEmail to true to prevent user from login if their email is not verified
preventLoginWithUnverifiedEmail: mailPreventUnverified, // defaults to false

// The public URL of your app.
// This will appear in the link that is used to verify email addresses and reset passwords.
// Set the mount path as it is in serverURL serverUrl
// publicServerURL: ‘https://example.com/parse’,
// see above

// The Parse Simple SMTP mail adapter - start
emailAdapter: {
module: “simple-parse-smtp-adapter”,
options: {
fromAddress: mailFromAddress,
user: mailUser,
password: mailPassword,
host: mailHost,
isSSL: mailIsSsl, //True or false if you are using ssl
port: mailPort, //SSL port or another port
name: mailName, // optional, used for identifying to the server
//Somtimes the user email is not in the ‘email’ field, the email is search first in
//email field, then in username field, if you have the user email in another field
//You can specify here
// THIS IS A FIELD in the USER TABLE. READ ABOVE CAREFULLY.
// WE ARE FINE WITH USING THE EXISTING FIELD, SO DON’t DEFINE.
// emailField: mailEmailField,
templates: {
//This template is used only for reset password email
resetPassword: {
//Path to your template
template: __dirname + ‘/views/email/reset-password’,
//Subject for this email
subject: mailResetSubject
},
verifyEmail: {
template: __dirname + ‘/views/email/verify-email’,
subject: mailVerifySubject
}
}
}
},
// The Parse Simple SMTP mail adapter - end

// parse-server-push-adapter
// GitHub - parse-community/parse-server-push-adapter: Official Push adapter for parse-server
push: {
adapter: new PushAdapter(pushOptions),
}
});

// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey

var app = express();

// Serve static assets from the /public folder
app.use(’/public’, express.static(path.join(__dirname, ‘/public’)));

// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || ‘/parse’;
app.use(mountPath, api);

// Parse Server plays nicely with the rest of your web routes
app.get(’/’, function(req, res) {
res.status(200).send(‘Welcome to the OurHangouts Backend.’);
});

// There will be a test page available on the /test path of your server url
// Remove this before launching your app
// app.get(’/test’, function(req, res) {
// res.sendFile(path.join(__dirname, ‘/public/test.html’));
//});

var port = process.env.PORT || 1337;
var httpServer = require(‘http’).createServer(app);
httpServer.listen(port, function() {
console.log('OurHangouts backend based on parse-server-example running on port ’ + port + ‘.’);
});

// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);

I got it working. Turns out I don’t need to explicitly load the push adapter. An inline config resulted in push being sent out.
Thanks for taking a look.

Have a look at the v6 migration guide:

1 Like

The migration guide was incredibly useful. It explains why my older index.js was no longer working. Perfect!
Now trying to get parse-smtp-adapter working. Probably not too hard. Remote notifications work great.