@parse/sqs-mq-adapter 1.3.8 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +14 -0
- package/.github/workflows/ci.yml +57 -18
- package/.github/workflows/release-automated.yml +6 -11
- package/CHANGELOG.md +26 -0
- package/eslint.config.mjs +45 -0
- package/lib/SQSEventEmitterMQ.js +18 -7
- package/package.json +31 -21
- package/release.config.js +28 -15
- package/spec/SQSEventEmitterMQ.spec.js +24 -39
- package/spec/integration.spec.js +3 -0
- package/spec/mocks/sqs.js +34 -0
- package/spec/support/helper.js +16 -0
- package/spec/support/jasmine.js +12 -0
- package/spec/support/jasmine.json +4 -2
- package/spec/support/reporter.js +12 -0
- package/spec/support/server.js +81 -0
- package/.eslintrc +0 -9
- package/spec/.eslintrc +0 -5
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Dependabot dependency updates
|
|
2
|
+
# Docs: https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
3
|
+
|
|
4
|
+
version: 2
|
|
5
|
+
updates:
|
|
6
|
+
- package-ecosystem: "npm"
|
|
7
|
+
# Location of package-lock.json
|
|
8
|
+
directory: "/"
|
|
9
|
+
# Check daily for updates
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "daily"
|
|
12
|
+
commit-message:
|
|
13
|
+
# Set commit message prefix
|
|
14
|
+
prefix: "refactor"
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -7,28 +7,67 @@ on:
|
|
|
7
7
|
branches:
|
|
8
8
|
- '**'
|
|
9
9
|
jobs:
|
|
10
|
-
|
|
10
|
+
check-lint:
|
|
11
|
+
name: Lint
|
|
12
|
+
timeout-minutes: 5
|
|
11
13
|
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: 22
|
|
19
|
+
cache: npm
|
|
20
|
+
- run: npm ci
|
|
21
|
+
- run: npm run lint
|
|
22
|
+
test:
|
|
12
23
|
strategy:
|
|
13
24
|
matrix:
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
include:
|
|
26
|
+
- name: Parse Server 8, Node.js 18
|
|
27
|
+
NODE_VERSION: 18.20.4
|
|
28
|
+
PARSE_SERVER_VERSION: 8
|
|
29
|
+
- name: Parse Server 8, Node.js 20
|
|
30
|
+
NODE_VERSION: 20.15.1
|
|
31
|
+
PARSE_SERVER_VERSION: 8
|
|
32
|
+
- name: Parse Server 8, Node.js 22
|
|
33
|
+
NODE_VERSION: 22.4.1
|
|
34
|
+
PARSE_SERVER_VERSION: 8
|
|
35
|
+
- name: Parse Server 7, Node.js 18
|
|
36
|
+
NODE_VERSION: 18.20.4
|
|
37
|
+
PARSE_SERVER_VERSION: 7
|
|
38
|
+
- name: Parse Server 7, Node.js 20
|
|
39
|
+
NODE_VERSION: 20.15.1
|
|
40
|
+
PARSE_SERVER_VERSION: 7
|
|
41
|
+
- name: Parse Server 7, Node.js 22
|
|
42
|
+
NODE_VERSION: 22.4.1
|
|
43
|
+
PARSE_SERVER_VERSION: 7
|
|
44
|
+
fail-fast: false
|
|
45
|
+
name: ${{ matrix.name }}
|
|
46
|
+
timeout-minutes: 15
|
|
47
|
+
runs-on: ubuntu-latest
|
|
16
48
|
env:
|
|
17
|
-
|
|
18
|
-
|
|
49
|
+
NODE_VERSION: ${{ matrix.NODE_VERSION }}
|
|
50
|
+
PARSE_SERVER_VERSION: ${{ matrix.PARSE_SERVER_VERSION }}
|
|
19
51
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
21
|
-
- name: Use Node.js
|
|
22
|
-
uses: actions/setup-node@
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
|
54
|
+
uses: actions/setup-node@v4
|
|
23
55
|
with:
|
|
24
|
-
node-version: ${{ matrix.
|
|
25
|
-
|
|
26
|
-
|
|
56
|
+
node-version: ${{ matrix.NODE_VERSION }}
|
|
57
|
+
cache: npm
|
|
58
|
+
- name: Install Parse Server ${{ matrix.PARSE_SERVER_VERSION }}
|
|
59
|
+
run: npm i -DE parse-server@${{ matrix.PARSE_SERVER_VERSION }}
|
|
60
|
+
- name: Install dependencies
|
|
61
|
+
run: npm ci
|
|
62
|
+
- name: Run tests
|
|
63
|
+
run: npm run test
|
|
64
|
+
- name: Upload code coverage
|
|
65
|
+
uses: codecov/codecov-action@v4
|
|
27
66
|
with:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
fail_ci_if_error: false
|
|
68
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
69
|
+
env:
|
|
70
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
71
|
+
concurrency:
|
|
72
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
73
|
+
cancel-in-progress: true
|
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
name: release-automated
|
|
2
2
|
on:
|
|
3
3
|
push:
|
|
4
|
-
branches: [ main, master, release, alpha, beta ]
|
|
4
|
+
branches: [ main, master, release, alpha, beta, next-major ]
|
|
5
5
|
jobs:
|
|
6
6
|
release:
|
|
7
7
|
runs-on: ubuntu-latest
|
|
8
8
|
steps:
|
|
9
9
|
- name: Checkout repository
|
|
10
|
-
uses: actions/checkout@
|
|
10
|
+
uses: actions/checkout@v4
|
|
11
11
|
with:
|
|
12
12
|
persist-credentials: false
|
|
13
13
|
- name: Setup Node
|
|
14
|
-
uses: actions/setup-node@
|
|
14
|
+
uses: actions/setup-node@v4
|
|
15
15
|
with:
|
|
16
|
-
node-version:
|
|
17
|
-
|
|
18
|
-
uses: actions/cache@v2
|
|
19
|
-
with:
|
|
20
|
-
path: ~/.npm
|
|
21
|
-
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
22
|
-
restore-keys: |
|
|
23
|
-
${{ runner.os }}-node-
|
|
16
|
+
node-version: 22
|
|
17
|
+
cache: 'npm'
|
|
24
18
|
- name: Install dependencies
|
|
25
19
|
run: npm ci
|
|
26
20
|
- name: Run semantic-release
|
|
@@ -28,4 +22,5 @@ jobs:
|
|
|
28
22
|
env:
|
|
29
23
|
GH_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
|
|
30
24
|
GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
|
|
25
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
31
26
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
# [2.1.0](https://github.com/parse-community/parse-server-sqs-mq-adapter/compare/2.0.0...2.1.0) (2025-07-06)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Add official support for Parse Server 7 and 8 ([#162](https://github.com/parse-community/parse-server-sqs-mq-adapter/issues/162)) ([e7e76b3](https://github.com/parse-community/parse-server-sqs-mq-adapter/commit/e7e76b3db52cc29964db1be33c08298fe166f9b6))
|
|
7
|
+
|
|
8
|
+
# [2.0.0](https://github.com/parse-community/parse-server-sqs-mq-adapter/compare/1.4.0...2.0.0) (2025-07-05)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Remove support for Node 12, 14, 15, 16, 17 ([#158](https://github.com/parse-community/parse-server-sqs-mq-adapter/issues/158)) ([26c114e](https://github.com/parse-community/parse-server-sqs-mq-adapter/commit/26c114e77e4d6e64085f513c54899e44fc5c3a61))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### BREAKING CHANGES
|
|
17
|
+
|
|
18
|
+
* Removes support for outdated Node versions 12, 14, 15, 16, 17. ([26c114e](26c114e))
|
|
19
|
+
|
|
20
|
+
# [1.4.0](https://github.com/parse-community/parse-server-sqs-mq-adapter/compare/1.3.8...1.4.0) (2024-09-26)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* Add support for Node 20 and 22 ([#101](https://github.com/parse-community/parse-server-sqs-mq-adapter/issues/101)) ([d19b0c2](https://github.com/parse-community/parse-server-sqs-mq-adapter/commit/d19b0c2e12d0a5bff48524f8aee1c2d2a232baa9))
|
|
26
|
+
|
|
1
27
|
## [1.3.8](https://github.com/parse-server-modules/parse-server-sqs-mq-adapter/compare/1.3.7...1.3.8) (2023-10-18)
|
|
2
28
|
|
|
3
29
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
|
|
4
|
+
export default [
|
|
5
|
+
js.configs.recommended,
|
|
6
|
+
{
|
|
7
|
+
files: ['**/*.js'],
|
|
8
|
+
ignores: ['node_modules/**'],
|
|
9
|
+
languageOptions: {
|
|
10
|
+
ecmaVersion: 2022,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
globals: {
|
|
13
|
+
...globals.node,
|
|
14
|
+
Parse: 'readonly'
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
rules: {
|
|
18
|
+
indent: ["error", 2, { SwitchCase: 1 }],
|
|
19
|
+
"linebreak-style": ["error", "unix"],
|
|
20
|
+
"no-trailing-spaces": "error",
|
|
21
|
+
"eol-last": "error",
|
|
22
|
+
"space-in-parens": ["error", "never"],
|
|
23
|
+
"no-multiple-empty-lines": "warn",
|
|
24
|
+
"prefer-const": "error",
|
|
25
|
+
"space-infix-ops": "error",
|
|
26
|
+
"no-useless-escape": "off",
|
|
27
|
+
"require-atomic-updates": "off",
|
|
28
|
+
"object-curly-spacing": ["error", "always"],
|
|
29
|
+
curly: ["error", "all"],
|
|
30
|
+
"block-spacing": ["error", "always"],
|
|
31
|
+
"no-unused-vars": "off",
|
|
32
|
+
"no-console": "warn"
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
files: ['spec/**/*.js'],
|
|
37
|
+
languageOptions: {
|
|
38
|
+
globals: {
|
|
39
|
+
...globals.node,
|
|
40
|
+
...globals.jasmine,
|
|
41
|
+
Parse: 'readonly'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
];
|
package/lib/SQSEventEmitterMQ.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const events = require('events');
|
|
2
2
|
const { logger } = require('parse-server');
|
|
3
|
-
const SQSProducer = require('sqs-producer');
|
|
4
|
-
const SQSConsumer = require('sqs-consumer');
|
|
3
|
+
const { Producer: SQSProducer } = require('sqs-producer');
|
|
4
|
+
const { Consumer: SQSConsumer } = require('sqs-consumer');
|
|
5
5
|
|
|
6
6
|
class Publisher {
|
|
7
7
|
constructor(config) {
|
|
@@ -18,9 +18,21 @@ class Publisher {
|
|
|
18
18
|
payload = Object.assign({ id: '0', body: message }, channel ? { groupId: channel } : {});
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
// basic validation to keep error logging synchronous for invalid payloads
|
|
22
|
+
if (typeof payload === 'object' && !Array.isArray(payload) && payload.body === undefined) {
|
|
23
|
+
logger.error(new Error("Object messages must have 'body' prop"));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const result = this.emitter.send(payload);
|
|
28
|
+
if (result && typeof result.catch === 'function') {
|
|
29
|
+
result.catch((err) => {
|
|
30
|
+
logger.error(err);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
} catch (err) {
|
|
34
|
+
logger.error(err);
|
|
35
|
+
}
|
|
24
36
|
}
|
|
25
37
|
}
|
|
26
38
|
|
|
@@ -36,9 +48,8 @@ class Consumer extends events.EventEmitter {
|
|
|
36
48
|
subscribe(channel) {
|
|
37
49
|
this.unsubscribe(channel);
|
|
38
50
|
|
|
39
|
-
const handleMessage = (message
|
|
51
|
+
const handleMessage = async (message) => {
|
|
40
52
|
this.emit('message', channel, message.Body);
|
|
41
|
-
done();
|
|
42
53
|
};
|
|
43
54
|
|
|
44
55
|
const createOptions = Object.assign(this.config, { handleMessage });
|
package/package.json
CHANGED
|
@@ -1,41 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parse/sqs-mq-adapter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Spread work queue across cluster of parse servers using SQS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/parse-
|
|
8
|
+
"url": "git+https://github.com/parse-community/parse-server-sqs-mq-adapter.git"
|
|
9
9
|
},
|
|
10
10
|
"author": "Parse Platform",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"sqs
|
|
14
|
-
"sqs-
|
|
13
|
+
"@aws-sdk/client-sqs": "3.840.0",
|
|
14
|
+
"sqs-consumer": "12.0.0",
|
|
15
|
+
"sqs-producer": "7.0.0"
|
|
15
16
|
},
|
|
16
17
|
"peerDependencies": {
|
|
17
18
|
"parse-server": "*"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
|
-
"@
|
|
21
|
-
"@semantic-release/
|
|
22
|
-
"@semantic-release/
|
|
23
|
-
"@semantic-release/
|
|
24
|
-
"@semantic-release/
|
|
25
|
-
"@semantic-release/
|
|
26
|
-
"
|
|
27
|
-
"eslint
|
|
28
|
-
"
|
|
29
|
-
"jasmine": "
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
21
|
+
"@eslint/js": "9.30.1",
|
|
22
|
+
"@semantic-release/changelog": "6.0.3",
|
|
23
|
+
"@semantic-release/commit-analyzer": "13.0.1",
|
|
24
|
+
"@semantic-release/git": "10.0.1",
|
|
25
|
+
"@semantic-release/github": "11.0.3",
|
|
26
|
+
"@semantic-release/npm": "12.0.1",
|
|
27
|
+
"@semantic-release/release-notes-generator": "14.0.3",
|
|
28
|
+
"eslint": "9.30.1",
|
|
29
|
+
"globals": "16.3.0",
|
|
30
|
+
"jasmine": "5.8.0",
|
|
31
|
+
"jasmine-spec-reporter": "7.0.0",
|
|
32
|
+
"mongodb-runner": "5.9.2",
|
|
33
|
+
"nyc": "17.1.0",
|
|
34
|
+
"parse-server": "8.2.1",
|
|
35
|
+
"semantic-release": "24.2.5"
|
|
34
36
|
},
|
|
35
37
|
"scripts": {
|
|
36
|
-
"lint": "eslint ./index.js ./lib/** ./spec
|
|
37
|
-
"
|
|
38
|
-
"
|
|
38
|
+
"lint": "eslint --cache ./index.js ./lib/** ./spec/**/*.js",
|
|
39
|
+
"lint-fix": "eslint --cache --fix ./index.js ./lib/** ./spec/**/*.js",
|
|
40
|
+
"pretest": "npm run test:mongodb:runnerstart",
|
|
41
|
+
"posttest": "npm run test:mongodb:runnerstop",
|
|
42
|
+
"test": "npm run test:only",
|
|
43
|
+
"test:only": "TESTING=1 nyc jasmine",
|
|
44
|
+
"test:mongodb:runnerstart": "mongodb-runner start -t standalone -- --port 27017",
|
|
45
|
+
"test:mongodb:runnerstop": "mongodb-runner stop --all",
|
|
39
46
|
"coverage": "nyc jasmine"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18.20.4 <19.0.0 || >=20.18.0 <21.0.0 || >=22.12.0 <23.0.0"
|
|
40
50
|
}
|
|
41
51
|
}
|
package/release.config.js
CHANGED
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
* Semantic Release Config
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
const
|
|
5
|
+
// For CommonJS use:
|
|
6
|
+
const { readFile } = require('fs').promises;
|
|
7
|
+
const { resolve } = require('path');
|
|
8
|
+
|
|
9
|
+
// For ES6 modules use:
|
|
10
|
+
// import { readFile } from 'fs/promises';
|
|
11
|
+
// import { resolve, dirname } from 'path';
|
|
12
|
+
// import { fileURLToPath } from 'url';
|
|
7
13
|
|
|
8
14
|
// Get env vars
|
|
9
15
|
const ref = process.env.GITHUB_REF;
|
|
@@ -24,9 +30,9 @@ const templates = {
|
|
|
24
30
|
async function config() {
|
|
25
31
|
|
|
26
32
|
// Get branch
|
|
27
|
-
const branch = ref
|
|
33
|
+
const branch = ref?.split('/')?.pop()?.split('-')[0] || '(current branch could not be determined)';
|
|
28
34
|
console.log(`Running on branch: ${branch}`);
|
|
29
|
-
|
|
35
|
+
|
|
30
36
|
// Set changelog file
|
|
31
37
|
//const changelogFile = `./changelogs/CHANGELOG_${branch}.md`;
|
|
32
38
|
const changelogFile = `./CHANGELOG.md`;
|
|
@@ -38,9 +44,11 @@ async function config() {
|
|
|
38
44
|
const config = {
|
|
39
45
|
branches: [
|
|
40
46
|
'main',
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
'master',
|
|
48
|
+
'release',
|
|
49
|
+
{ name: 'alpha', prerelease: true },
|
|
50
|
+
{ name: 'beta', prerelease: true },
|
|
51
|
+
'next-major',
|
|
44
52
|
// Long-Term-Support branches
|
|
45
53
|
// { name: 'release-1', range: '1.x.x', channel: '1.x' },
|
|
46
54
|
// { name: 'release-2', range: '2.x.x', channel: '2.x' },
|
|
@@ -59,13 +67,13 @@ async function config() {
|
|
|
59
67
|
{ scope: 'no-release', release: false },
|
|
60
68
|
],
|
|
61
69
|
parserOpts: {
|
|
62
|
-
noteKeywords: [ 'BREAKING CHANGE'
|
|
70
|
+
noteKeywords: [ 'BREAKING CHANGE' ],
|
|
63
71
|
},
|
|
64
72
|
}],
|
|
65
73
|
['@semantic-release/release-notes-generator', {
|
|
66
74
|
preset: 'angular',
|
|
67
75
|
parserOpts: {
|
|
68
|
-
noteKeywords: ['BREAKING CHANGE'
|
|
76
|
+
noteKeywords: [ 'BREAKING CHANGE' ]
|
|
69
77
|
},
|
|
70
78
|
writerOpts: {
|
|
71
79
|
commitsSort: ['subject', 'scope'],
|
|
@@ -87,7 +95,7 @@ async function config() {
|
|
|
87
95
|
['@semantic-release/github', {
|
|
88
96
|
successComment: getReleaseComment(),
|
|
89
97
|
labels: ['type:ci'],
|
|
90
|
-
releasedLabels: ['state:released<%= nextRelease.channel ?
|
|
98
|
+
releasedLabels: ['state:released<%= nextRelease.channel ? `-\${nextRelease.channel}` : "" %>']
|
|
91
99
|
}],
|
|
92
100
|
],
|
|
93
101
|
};
|
|
@@ -97,19 +105,24 @@ async function config() {
|
|
|
97
105
|
|
|
98
106
|
async function loadTemplates() {
|
|
99
107
|
for (const template of Object.keys(templates)) {
|
|
100
|
-
|
|
108
|
+
// For ES6 modules use:
|
|
109
|
+
// const fileUrl = import.meta.url;
|
|
110
|
+
// const __dirname = dirname(fileURLToPath(fileUrl));
|
|
111
|
+
|
|
112
|
+
const filePath = resolve(__dirname, resourcePath, templates[template].file);
|
|
113
|
+
const text = await readFile(filePath, 'utf-8');
|
|
101
114
|
templates[template].text = text;
|
|
102
115
|
}
|
|
103
116
|
}
|
|
104
117
|
|
|
105
|
-
async function readFile(filePath) {
|
|
106
|
-
return await fs.readFile(filePath, 'utf-8');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
118
|
function getReleaseComment() {
|
|
110
119
|
const url = repositoryUrl + '/releases/tag/${nextRelease.gitTag}';
|
|
111
120
|
let comment = '🎉 This change has been released in version [${nextRelease.version}](' + url + ')';
|
|
112
121
|
return comment;
|
|
113
122
|
}
|
|
114
123
|
|
|
124
|
+
// For CommonJS use:
|
|
115
125
|
module.exports = config();
|
|
126
|
+
|
|
127
|
+
// For ES6 modules use:
|
|
128
|
+
// export default config();
|
|
@@ -1,51 +1,36 @@
|
|
|
1
|
-
const sinon = require('sinon');
|
|
2
1
|
const { ParseMessageQueue } = require('../node_modules/parse-server/lib/ParseMessageQueue');
|
|
3
2
|
const { SQSEventEmitterMQ } = require('../');
|
|
4
3
|
const { logger } = require('parse-server');
|
|
4
|
+
const { getServerConfig } = require('./support/server.js');
|
|
5
|
+
const { getMockSqsOptions } = require('./mocks/sqs.js');
|
|
5
6
|
|
|
6
7
|
let config;
|
|
7
8
|
|
|
8
9
|
describe('SMSEventEmitterMQ', () => {
|
|
9
10
|
beforeEach(() => {
|
|
10
|
-
|
|
11
|
-
Messages: [{
|
|
12
|
-
ReceiptHandle: 'receipt-handle',
|
|
13
|
-
MessageId: '123',
|
|
14
|
-
Body: 'body',
|
|
15
|
-
}],
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const sqs = sinon.mock();
|
|
19
|
-
sqs.sendMessageBatch = sinon.stub();
|
|
20
|
-
sqs.receiveMessage = sinon.stub().yieldsAsync(null, response);
|
|
21
|
-
sqs.receiveMessage.onSecondCall().returns();
|
|
22
|
-
sqs.deleteMessage = sinon.stub();
|
|
23
|
-
|
|
24
|
-
config = {
|
|
25
|
-
messageQueueAdapter: SQSEventEmitterMQ,
|
|
26
|
-
queueUrl: 'test-queue',
|
|
27
|
-
region: 'mock',
|
|
28
|
-
sqs,
|
|
29
|
-
};
|
|
11
|
+
config = getMockSqsOptions();
|
|
30
12
|
});
|
|
31
13
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
14
|
+
describe('integration', () => {
|
|
15
|
+
it('publishes a message', done => {
|
|
16
|
+
const options = getServerConfig().queueOptions;
|
|
17
|
+
const subscriber = ParseMessageQueue.createSubscriber(options);
|
|
18
|
+
const publisher = ParseMessageQueue.createPublisher(options);
|
|
19
|
+
const channel = 'foo';
|
|
20
|
+
const message = 'hi';
|
|
21
|
+
|
|
22
|
+
subscriber.subscribe(channel);
|
|
23
|
+
subscriber.on('message', (channel, message) => {
|
|
24
|
+
expect(channel).toBe(channel);
|
|
25
|
+
expect(message).toBe(message);
|
|
26
|
+
|
|
27
|
+
// Give aws-sdk some time to mark the message to avoid flaky test
|
|
28
|
+
setTimeout(done, 200);
|
|
29
|
+
});
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
subscriber.on('message', (channel, message) => {
|
|
41
|
-
expect(channel).toBe(CHANNEL);
|
|
42
|
-
expect(message).toBe(MESSAGE);
|
|
43
|
-
// need to give the aws-sdk some time to mark the message
|
|
44
|
-
setTimeout(done, 500);
|
|
31
|
+
publisher.publish(channel, message);
|
|
45
32
|
});
|
|
46
|
-
|
|
47
|
-
publisher.publish(CHANNEL, MESSAGE);
|
|
48
|
-
}).pend('configure options for a real sqs endpoint');
|
|
33
|
+
});
|
|
49
34
|
|
|
50
35
|
describe('subscriber', () => {
|
|
51
36
|
it('should only have one subscription map', () => {
|
|
@@ -73,7 +58,7 @@ describe('SMSEventEmitterMQ', () => {
|
|
|
73
58
|
subscriber.subscribe('message_processed');
|
|
74
59
|
subscriber.on('message', (event, message) => {
|
|
75
60
|
expect(event).toBe('message_processed');
|
|
76
|
-
expect(message).toBe('
|
|
61
|
+
expect(message).toBe('hi');
|
|
77
62
|
done();
|
|
78
63
|
});
|
|
79
64
|
});
|
|
@@ -110,7 +95,7 @@ describe('SMSEventEmitterMQ', () => {
|
|
|
110
95
|
{ id: '0', body: 'foo', groupId: 'channel' },
|
|
111
96
|
{ id: '1', body: 'bar', groupId: 'channel' },
|
|
112
97
|
];
|
|
113
|
-
expect(publisher.emitter.send).toHaveBeenCalledWith(payload
|
|
98
|
+
expect(publisher.emitter.send).toHaveBeenCalledWith(payload);
|
|
114
99
|
});
|
|
115
100
|
|
|
116
101
|
it('should process a batch with no channel', () => {
|
|
@@ -121,7 +106,7 @@ describe('SMSEventEmitterMQ', () => {
|
|
|
121
106
|
{ id: '0', body: 'foo' },
|
|
122
107
|
{ id: '1', body: 'bar' },
|
|
123
108
|
];
|
|
124
|
-
expect(publisher.emitter.send).toHaveBeenCalledWith(payload
|
|
109
|
+
expect(publisher.emitter.send).toHaveBeenCalledWith(payload);
|
|
125
110
|
});
|
|
126
111
|
});
|
|
127
112
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const { SQSEventEmitterMQ } = require('../../');
|
|
2
|
+
|
|
3
|
+
function getMockSqsOptions() {
|
|
4
|
+
const response = {
|
|
5
|
+
Messages: [
|
|
6
|
+
{
|
|
7
|
+
ReceiptHandle: 'receipt-handle',
|
|
8
|
+
MessageId: '123',
|
|
9
|
+
Body: 'hi',
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let call = 0;
|
|
15
|
+
const sqs = {
|
|
16
|
+
sendMessageBatch: () => Promise.resolve({}),
|
|
17
|
+
send: () => {
|
|
18
|
+
call += 1;
|
|
19
|
+
if (call === 1) {
|
|
20
|
+
return Promise.resolve(response);
|
|
21
|
+
}
|
|
22
|
+
return Promise.resolve({});
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
messageQueueAdapter: SQSEventEmitterMQ,
|
|
28
|
+
queueUrl: 'test-queue',
|
|
29
|
+
region: 'mock',
|
|
30
|
+
sqs,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = { getMockSqsOptions };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { startServer, stopServer, reconfigureServer } = require('./server');
|
|
3
|
+
|
|
4
|
+
jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.TESTING_TIMEOUT || '360000';
|
|
5
|
+
|
|
6
|
+
beforeAll(async () => {
|
|
7
|
+
await startServer();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
afterAll(async () => {
|
|
11
|
+
await stopServer();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
await reconfigureServer();
|
|
16
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const semver = require('semver');
|
|
2
|
+
|
|
3
|
+
const satisfiesParseServerVersion = version => {
|
|
4
|
+
const envVersion = process.env.PARSE_SERVER_VERSION;
|
|
5
|
+
const semverVersion = semver.coerce(envVersion);
|
|
6
|
+
return !envVersion || !semverVersion || semver.satisfies(semverVersion, version);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
global.it_only_parse_server_version = version => satisfiesParseServerVersion(version) ? it : xit;
|
|
10
|
+
global.fit_only_parse_server_version = version => satisfiesParseServerVersion(version) ? fit : xit;
|
|
11
|
+
global.describe_only_parse_server_version = version => satisfiesParseServerVersion(version) ? describe : xdescribe;
|
|
12
|
+
global.fdescribe_only_parse_server_version = version => satisfiesParseServerVersion(version) ? fdescribe : xdescribe;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const { SpecReporter } = require('jasmine-spec-reporter');
|
|
2
|
+
|
|
3
|
+
jasmine.getEnv().clearReporters();
|
|
4
|
+
jasmine.getEnv().addReporter(
|
|
5
|
+
new SpecReporter({
|
|
6
|
+
spec: {
|
|
7
|
+
displayPending: true,
|
|
8
|
+
displayDuration: true,
|
|
9
|
+
displayStacktrace: 'pretty',
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const { ParseServer } = require('parse-server');
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const { getMockSqsOptions } = require('../mocks/sqs');
|
|
5
|
+
const Config = require('../../node_modules/parse-server/lib/Config.js');
|
|
6
|
+
|
|
7
|
+
const expressApp = express();
|
|
8
|
+
const queueOptions = getMockSqsOptions();
|
|
9
|
+
|
|
10
|
+
let serverState = {};
|
|
11
|
+
|
|
12
|
+
const defaultConfig = {
|
|
13
|
+
databaseURI: 'mongodb://127.0.0.1:27017/sqs-mq-adapter',
|
|
14
|
+
appId: 'test',
|
|
15
|
+
masterKey: 'test',
|
|
16
|
+
maintenanceKey: 'test-maintenance-key',
|
|
17
|
+
serverURL: 'http://127.0.0.1:1327/api/parse',
|
|
18
|
+
port: 1327,
|
|
19
|
+
mountPath: '/api/parse',
|
|
20
|
+
verbose: false,
|
|
21
|
+
silent: true,
|
|
22
|
+
queueOptions,
|
|
23
|
+
verifyUserEmails: false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
async function startServer(config = {}) {
|
|
27
|
+
if (!process.env.TESTING) {
|
|
28
|
+
throw 'requires test environment to run';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const serverConfig = Object.assign({}, config, defaultConfig);
|
|
32
|
+
const parseServer = ParseServer(serverConfig);
|
|
33
|
+
await parseServer.start();
|
|
34
|
+
expressApp.use(serverConfig.mountPath, parseServer.app);
|
|
35
|
+
|
|
36
|
+
const httpServer = http.createServer(expressApp);
|
|
37
|
+
await new Promise((resolve, reject) => {
|
|
38
|
+
httpServer
|
|
39
|
+
.listen(serverConfig.port)
|
|
40
|
+
.once('listening', resolve)
|
|
41
|
+
.once('error', (e) => reject(e));
|
|
42
|
+
}).catch((e) => {
|
|
43
|
+
throw new Error(`parse-server failed to launch with error: ${e}`);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
Object.assign(serverState, {
|
|
47
|
+
parseServer,
|
|
48
|
+
httpServer,
|
|
49
|
+
serverConfig,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function stopServer() {
|
|
54
|
+
if (!process.env.TESTING) {
|
|
55
|
+
throw 'requires test environment to run';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await Parse.User.logOut();
|
|
59
|
+
const app = Config.get(defaultConfig.appId);
|
|
60
|
+
await app?.database.deleteEverything(true);
|
|
61
|
+
|
|
62
|
+
const { httpServer } = serverState;
|
|
63
|
+
await new Promise((resolve) => httpServer.close(resolve));
|
|
64
|
+
serverState = {};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function reconfigureServer(config = {}) {
|
|
68
|
+
await stopServer();
|
|
69
|
+
return await startServer(config);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getServerConfig() {
|
|
73
|
+
return serverState.serverConfig || defaultConfig;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
reconfigureServer,
|
|
78
|
+
startServer,
|
|
79
|
+
stopServer,
|
|
80
|
+
getServerConfig,
|
|
81
|
+
};
|
package/.eslintrc
DELETED