Skip to content

Add QOL changes to Parse Server Example #384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"parser": "babel-eslint",
"rules": {
"indent": ["error", 2, { "SwitchCase": 1 }],
"linebreak-style": ["error", "unix"],
"no-trailing-spaces": 2,
"eol-last": 2,
"space-in-parens": ["error", "never"],
"no-multiple-empty-lines": 1,
"prefer-const": "error",
"space-infix-ops": "error",
"no-useless-escape": "off",
"require-atomic-updates": "off",
"no-var": 1,
"no-await-in-loop" : 1
},
"globals" : {
"Parse" : true
}
}
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Node.js
on:
push:
branches:
- master
pull_request:
branches:
- '**'
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
name: ${{ matrix.name }}
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install Dependancies
run: npm install
- name: Check Linting
run: npm run lint
- name: Run Tests
run: npm run test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ node_modules

# Emacs
*~
.eslintcache
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,14 @@ Example using it via JavaScript:
Parse.initialize('myAppId','unused');
Parse.serverURL = 'https://whatever.herokuapp.com';

var obj = new Parse.Object('GameScore');
const obj = new Parse.Object('GameScore');
obj.set('score',1337);
obj.save().then(function(obj) {
console.log(obj.toJSON());
var query = new Parse.Query('GameScore');
query.get(obj.id).then(function(objAgain) {
console.log(objAgain.toJSON());
}, function(err) {console.log(err); });
}, function(err) { console.log(err); });
await obj.save();
console.log(obj.toJSON());

const query = new Parse.Query('GameScore');
const objAgain = await query.get(obj.id);
console.log(objAgain.toJSON());
```

Example using it on Android:
Expand Down
13 changes: 12 additions & 1 deletion cloud/main.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
Parse.Cloud.define('hello', function(req, res) {
Parse.Cloud.define('hello', (req) => {
console.log(req)
return 'Hi';
});

Parse.Cloud.define('asyncFunction', async (req) => {
await new Promise((resolve) => setTimeout(resolve,1000));
console.log(req)
return 'Hi async';
});

Parse.Cloud.beforeSave('Test', () => {
throw new Parse.Error(211,'Saving test objects is not available.')
});
42 changes: 26 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// Example express application adding the parse-server module to expose Parse
// compatible API routes.

var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
const express = require('express');
const ParseServer = require('parse-server').ParseServer;
const path = require('path');
const args = process.argv || [];
const test = args.some(arg => arg.includes('jasmine'));

var databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;
const databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;

if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}

var api = new ParseServer({
const config = {
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'myAppId',
Expand All @@ -20,19 +21,22 @@ var api = new ParseServer({
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query subscriptions
}
});
};
// 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();
const 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);
const mountPath = process.env.PARSE_MOUNT || '/parse';
if (!test) {
const api = new ParseServer(config);
app.use(mountPath, api);
}

// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
Expand All @@ -45,11 +49,17 @@ 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() {
const port = process.env.PORT || 1337;
if (!test) {
const httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
}

// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
module.exports = {
app,
config
};
24 changes: 19 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,29 @@
},
"license": "MIT",
"dependencies": {
"express": "~4.11.x",
"kerberos": "~0.0.x",
"parse": "~1.8.0",
"parse-server": "*"
"express": "4.17.1",
"kerberos": "1.1.4",
"parse": "2.19.0",
"parse-server": "4.5.0"
},
"scripts": {
"start": "node index.js"
"start": "node index.js",
"lint": "eslint --cache ./cloud && eslint --cache index.js",
"lint-fix": "eslint --cache --fix ./cloud && eslint --cache --fix index.js",
"test": "jasmine"
},
"engines": {
"node": ">=4.3"
},
"devDependencies": {
"eslint": "^7.17.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"babel-eslint": "^10.1.0",
"jasmine": "^3.6.3",
"mongodb-runner": "^4.8.0",
"bluebird": "^3.7.2"
}
}
22 changes: 22 additions & 0 deletions spec/Tests.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
describe("Parse Server example", () => {
Parse.User.enableUnsafeCurrentUser();
it('call function', async () => {
const result = await Parse.Cloud.run('hello');
expect(result).toBe('Hi');
});
it('call async function', async () => {
const result = await Parse.Cloud.run('asyncFunction');
expect(result).toBe('Hi async');
})
it('failing test', async () => {
const obj = new Parse.Object('Test');
try {
await obj.save();
fail('should not have been able to save test object.');
} catch (e) {
expect(e).toBeDefined();
expect(e.code).toBe(212);
expect(e.message).toBe('Saving test objects is not available.');
}
})
});
17 changes: 17 additions & 0 deletions spec/helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const Parse = require("parse/node");
Parse.initialize("test");
Parse.serverURL = "http://localhost:30001/test";
Parse.masterKey = "test";
const {
startParseServer,
stopParseServer,
dropDB,
} = require("./utils/test-runner.js");
beforeAll(async () => {
await startParseServer();
}, 100 * 60 * 2);

afterAll(async () => {
await dropDB();
await stopParseServer();
});
9 changes: 9 additions & 0 deletions spec/support/jasmine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": ["helper.js"],
"stopSpecOnExpectationFailure": false,
"random": false
}
122 changes: 122 additions & 0 deletions spec/utils/test-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
const Promise = require("bluebird");
const http = require("http");
const { MongoClient } = require("mongodb");
const { ParseServer } = require("parse-server");
const { config, app } = require("../../index.js");
const Config = require("../../node_modules/parse-server/lib/Config");

const mongoDBRunnerStart = require("mongodb-runner/mocha/before").bind({
timeout() {},
slow() {},
});
const mongoDBRunnerStop = require("mongodb-runner/mocha/after");

const startDB = () =>
new Promise((done, reject) => {
done.fail = reject;
mongoDBRunnerStart(done);
});

const stopDB = () =>
new Promise((done, reject) => {
done.fail = reject;
mongoDBRunnerStop(done);
});

const connectDB = (databaseURI) =>
new Promise((resolve, reject) => {
MongoClient.connect(databaseURI, (err, db) => {
if (err) {
reject(err);
} else {
resolve(db);
}
});
});

let parseServerState = {};

const dropDB = async () => {
await Parse.User.logOut();
const app = Config.get("test");
return await app.database.deleteEverything(true);
};

/**
* Starts the ParseServer instance
* @param {Object} parseServerOptions Used for creating the `ParseServer`
* @return {Promise} Runner state
*/
async function startParseServer() {
const mongodbPort = process.env.MONGODB_PORT || 27017;
let parseServerOptions = Object.assign(config, {
databaseName: "parse-test",
databaseURI: `mongodb://localhost:${mongodbPort}/parse-test`,
masterKey: "test",
javascriptKey: "test",
appId: "test",
port: 30001,
mountPath: "/test",
serverURL: `http://localhost:30001/test`,
logLevel: "error",
silent: true,
});
const {
databaseURI,
masterKey,
javascriptKey,
appId,
port,
serverURL,
mountPath,
} = parseServerOptions;
await startDB();
const mongoConnection = await connectDB(databaseURI);
parseServerOptions = Object.assign(
{
masterKey,
javascriptKey,
appId,
serverURL,
databaseURI,
silent: process.env.VERBOSE !== "1",
},
parseServerOptions
);
const parseServer = new ParseServer(parseServerOptions);
app.use(mountPath, parseServer);

const httpServer = http.createServer(app);

Promise.promisifyAll(httpServer);
Promise.promisifyAll(mongoConnection);
await httpServer.listenAsync(port);

Object.assign(parseServerState, {
parseServer,
httpServer,
mongoConnection,
expressApp: app,
parseServerOptions,
});
return parseServerOptions;
}

/**
* Stops the ParseServer instance
* @return {Promise}
*/
function stopParseServer() {
const { httpServer } = parseServerState;
return httpServer
.closeAsync()
.then(stopDB)
.then(() => (parseServerState = {}));
}

module.exports = {
dropDB,
startParseServer,
stopParseServer,
parseServerState,
};