Compare commits
52 Commits
9.1.0-alph
...
kami2
| Author | SHA1 | Date | |
|---|---|---|---|
| e69caaa536 | |||
| a2fba8502a | |||
|
|
ac73dab494 | ||
| ccd90508dd | |||
| 51c33a89e0 | |||
| bb070be37d | |||
| 79cf7c9e9f | |||
| 4ce607a1e1 | |||
|
|
18b9641360 | ||
|
|
0e9725b231 | ||
|
|
5a0d09e90c | ||
|
|
b92e76d61b | ||
|
|
37e6459608 | ||
|
|
d9cf3ce476 | ||
|
|
83cf68a513 | ||
|
|
5a32eb33e6 | ||
|
|
2c316ceaad | ||
|
|
faa04f7209 | ||
|
|
c99cbbf530 | ||
|
|
41b0bf09bb | ||
|
|
31d8947c1f | ||
|
|
27d8f861e7 | ||
|
|
3e7b1b3fe1 | ||
|
|
3c89eb3e16 | ||
|
|
fb7d9b5a7c | ||
|
|
461ca5d3fe | ||
|
|
305e4ba445 | ||
|
|
f23eb4c419 | ||
|
|
566ac26789 | ||
|
|
96bc74433b | ||
|
|
7319aabf7a | ||
|
|
ec27bc7e8e | ||
|
|
6b36ce1bb5 | ||
|
|
82fec72ec4 | ||
|
|
938564acbb | ||
|
|
f969c7bb2a | ||
|
|
320eba1081 | ||
|
|
43be9fed9d | ||
|
|
f1ebdef28b | ||
|
|
b660ca5ed8 | ||
|
|
dccd7d7a1d | ||
|
|
df01846361 | ||
|
|
197190fc29 | ||
|
|
48ddcdb303 | ||
|
|
c8b303a9d2 | ||
|
|
4d81f8fc30 | ||
|
|
cddb924703 | ||
|
|
f2f92858f1 | ||
|
|
1427eeac5a | ||
|
|
348489784a | ||
|
|
108c7e95e2 | ||
|
|
d15a3ce8f5 |
11
.babelrc
11
.babelrc
@@ -1,14 +1,13 @@
|
||||
{
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-flow-strip-types"
|
||||
"transform-flow-strip-types",
|
||||
"transform-object-rest-spread"
|
||||
],
|
||||
"presets": [
|
||||
"@babel/preset-typescript",
|
||||
["@babel/preset-env", {
|
||||
["env", {
|
||||
"targets": {
|
||||
"node": "18"
|
||||
},
|
||||
"exclude": ["proposal-dynamic-import"]
|
||||
"node": "8"
|
||||
}
|
||||
}]
|
||||
],
|
||||
"sourceMaps": "inline"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
*.md
|
||||
PATENTS
|
||||
LICENSE
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
.gitignore
|
||||
@@ -14,8 +16,6 @@ lib/
|
||||
|
||||
# Tests
|
||||
spec/
|
||||
# Keep local dependencies used to CI tests
|
||||
!spec/dependencies/
|
||||
|
||||
# IDEs
|
||||
.idea/
|
||||
|
||||
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
lib
|
||||
coverage
|
||||
|
||||
27
.eslintrc.json
Normal file
27
.eslintrc.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"flowtype"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": ["error", 2],
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,3 @@
|
||||
|
||||
[options]
|
||||
suppress_comment= \\(.\\|\n\\)*\\@flow-disable-next
|
||||
esproposal.optional_chaining=enable
|
||||
|
||||
45
.github/ISSUE_TEMPLATE.md
vendored
Normal file
45
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
We use GitHub Issues for bugs.
|
||||
|
||||
If you have a non-bug question, ask on Stack Overflow or Server Fault:
|
||||
- https://stackoverflow.com/questions/tagged/parse.com
|
||||
- https://serverfault.com/tags/parse
|
||||
|
||||
If you have a vulnerability disclosure, please follow our policy available here https://github.com/parse-community/parse-server/blob/master/SECURITY.md
|
||||
|
||||
You may also search through existing issues before opening a new one: https://github.com/parse-community/parse-server/issues?utf8=%E2%9C%93&q=is%3Aissue
|
||||
|
||||
--- Please use this template. If you don't use this template, your issue may be closed without comment. ---
|
||||
|
||||
### Issue Description
|
||||
|
||||
Describe your issue in as much detail as possible.
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
Please include a detailed list of steps that reproduce the issue. Include curl commands when applicable.
|
||||
|
||||
#### Expected Results
|
||||
|
||||
What you expected to happen.
|
||||
|
||||
#### Actual Outcome
|
||||
|
||||
What is happening instead.
|
||||
|
||||
### Environment Setup
|
||||
|
||||
- **Server**
|
||||
- parse-server version (Be specific! Don't say 'latest'.) : [FILL THIS OUT]
|
||||
- Operating System: [FILL THIS OUT]
|
||||
- Hardware: [FILL THIS OUT]
|
||||
- Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): [FILL THIS OUT]
|
||||
|
||||
- **Database**
|
||||
- MongoDB version: [FILL THIS OUT]
|
||||
- Storage engine: [FILL THIS OUT]
|
||||
- Hardware: [FILL THIS OUT]
|
||||
- Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): [FILL THIS OUT]
|
||||
|
||||
### Logs/Trace
|
||||
|
||||
Include all relevant logs. You can turn on additional logging by configuring VERBOSE=1 in your environment.
|
||||
46
.github/ISSUE_TEMPLATE/---1-report-an-issue.md
vendored
46
.github/ISSUE_TEMPLATE/---1-report-an-issue.md
vendored
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: "\U0001F41B Report an issue"
|
||||
about: A feature of Parse Server is not working as expected.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### New Issue Checklist
|
||||
|
||||
- Report security issues [confidentially](https://github.com/parse-community/parse-server/security/policy).
|
||||
- Any contribution is under this [license](https://github.com/parse-community/parse-server/blob/alpha/LICENSE).
|
||||
- Before posting search [existing issues](https://github.com/parse-community/parse-server/issues?q=is%3Aissue).
|
||||
|
||||
### Issue Description
|
||||
<!-- What is the specific issue with Parse Server? -->
|
||||
|
||||
### Steps to reproduce
|
||||
<!-- How can someone else reproduce the issue? -->
|
||||
|
||||
### Actual Outcome
|
||||
<!-- What outcome, for example query result, did you get? -->
|
||||
|
||||
### Expected Outcome
|
||||
<!-- What outcome, for example query result, did you expect? -->
|
||||
|
||||
### Environment
|
||||
<!-- Be specific with versions, don't use "latest" or semver ranges like "~x.y.z" or "^x.y.z". -->
|
||||
|
||||
Server
|
||||
- Parse Server version: `FILL_THIS_OUT`
|
||||
- Operating system: `FILL_THIS_OUT`
|
||||
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): `FILL_THIS_OUT`
|
||||
|
||||
Database
|
||||
- System (MongoDB or Postgres): `FILL_THIS_OUT`
|
||||
- Database version: `FILL_THIS_OUT`
|
||||
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): `FILL_THIS_OUT`
|
||||
|
||||
Client
|
||||
- SDK (iOS, Android, JavaScript, PHP, Unity, etc): `FILL_THIS_OUT`
|
||||
- SDK version: `FILL_THIS_OUT`
|
||||
|
||||
### Logs
|
||||
<!-- Include relevant logs here. Turn on additional logging by configuring VERBOSE=1 in your environment. -->
|
||||
29
.github/ISSUE_TEMPLATE/---2-feature-request.md
vendored
29
.github/ISSUE_TEMPLATE/---2-feature-request.md
vendored
@@ -1,29 +0,0 @@
|
||||
---
|
||||
name: "\U0001F4A1 Request a feature"
|
||||
about: Suggest new functionality or an enhancement of existing functionality.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### New Feature / Enhancement Checklist
|
||||
|
||||
- Report security issues [confidentially](https://github.com/parse-community/parse-server/security/policy).
|
||||
- Any contribution is under this [license](https://github.com/parse-community/parse-server/blob/alpha/LICENSE).
|
||||
- Before posting search [existing issues](https://github.com/parse-community/parse-server/issues?q=is%3Aissue).
|
||||
|
||||
### Current Limitation
|
||||
<!-- Which current limitation is the feature or enhancement addressing? -->
|
||||
|
||||
### Feature / Enhancement Description
|
||||
<!-- What is the concept of the functionality and how should it be implemented? -->
|
||||
|
||||
### Example Use Case
|
||||
<!-- What is an example use case in steps (1. / 2. / 3. / etc.) that describes the functionality? -->
|
||||
|
||||
### Alternatives / Workarounds
|
||||
<!-- Which alternatives or workarounds exist currently? -->
|
||||
|
||||
### 3rd Party References
|
||||
<!-- Have you seen a similar functionality provided somewhere else? -->
|
||||
17
.github/ISSUE_TEMPLATE/---feature-request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/---feature-request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: "\U0001F4A1 Feature request"
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
7
.github/ISSUE_TEMPLATE/---push-notifications.md
vendored
Normal file
7
.github/ISSUE_TEMPLATE/---push-notifications.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: "\U0001F4F2 Push Notifications"
|
||||
about: Issues with setting up or delivering push notifications
|
||||
|
||||
---
|
||||
|
||||
|
||||
53
.github/ISSUE_TEMPLATE/---report-an-issue.md
vendored
Normal file
53
.github/ISSUE_TEMPLATE/---report-an-issue.md
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
name: "\U0001F41B Report an issue"
|
||||
about: Report an issue on parse-server
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
|
||||
We use GitHub Issues for bugs.
|
||||
|
||||
If you have a non-bug question, ask on Stack Overflow or Server Fault:
|
||||
- https://stackoverflow.com/questions/tagged/parse.com
|
||||
- https://serverfault.com/tags/parse
|
||||
|
||||
If you have a vulnerability disclosure, please follow our policy available here https://github.com/parse-community/parse-server/blob/master/SECURITY.md
|
||||
|
||||
You may also search through existing issues before opening a new one: https://github.com/parse-community/parse-server/issues?utf8=%E2%9C%93&q=is%3Aissue
|
||||
|
||||
--- Please use this template. If you don't use this template, your issue may be closed without comment. ---
|
||||
--->
|
||||
### Issue Description
|
||||
|
||||
<!--- Describe your issue in as much detail as possible. -->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--- Please include a detailed list of steps that reproduce the issue. Include curl commands when applicable. --->
|
||||
|
||||
### Expected Results
|
||||
|
||||
<!--- What you expected to happen. --->
|
||||
|
||||
### Actual Outcome
|
||||
|
||||
<!--- What is happening instead. --->
|
||||
|
||||
### Environment Setup
|
||||
|
||||
- **Server**
|
||||
- parse-server version (Be specific! Don't say 'latest'.) : [FILL THIS OUT]
|
||||
- Operating System: [FILL THIS OUT]
|
||||
- Hardware: [FILL THIS OUT]
|
||||
- Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): [FILL THIS OUT]
|
||||
|
||||
- **Database**
|
||||
- MongoDB version: [FILL THIS OUT]
|
||||
- Storage engine: [FILL THIS OUT]
|
||||
- Hardware: [FILL THIS OUT]
|
||||
- Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): [FILL THIS OUT]
|
||||
|
||||
### Logs/Trace
|
||||
|
||||
<!--- Include all relevant logs. You can turn on additional logging by configuring VERBOSE=1 in your environment. --->
|
||||
51
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
51
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: Report an issue
|
||||
about: Report an issue on parse-server
|
||||
|
||||
---
|
||||
|
||||
We use GitHub Issues for bugs.
|
||||
|
||||
If you have a non-bug question, ask on Stack Overflow or Server Fault:
|
||||
- https://stackoverflow.com/questions/tagged/parse.com
|
||||
- https://serverfault.com/tags/parse
|
||||
|
||||
If you have a vulnerability disclosure, please follow our policy available here https://github.com/parse-community/parse-server/blob/master/SECURITY.md
|
||||
|
||||
You may also search through existing issues before opening a new one: https://github.com/parse-community/parse-server/issues?utf8=%E2%9C%93&q=is%3Aissue
|
||||
|
||||
--- Please use this template. If you don't use this template, your issue may be closed without comment. ---
|
||||
|
||||
### Issue Description
|
||||
|
||||
Describe your issue in as much detail as possible.
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
Please include a detailed list of steps that reproduce the issue. Include curl commands when applicable.
|
||||
|
||||
#### Expected Results
|
||||
|
||||
What you expected to happen.
|
||||
|
||||
#### Actual Outcome
|
||||
|
||||
What is happening instead.
|
||||
|
||||
### Environment Setup
|
||||
|
||||
- **Server**
|
||||
- parse-server version (Be specific! Don't say 'latest'.) : [FILL THIS OUT]
|
||||
- Operating System: [FILL THIS OUT]
|
||||
- Hardware: [FILL THIS OUT]
|
||||
- Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): [FILL THIS OUT]
|
||||
|
||||
- **Database**
|
||||
- MongoDB version: [FILL THIS OUT]
|
||||
- Storage engine: [FILL THIS OUT]
|
||||
- Hardware: [FILL THIS OUT]
|
||||
- Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): [FILL THIS OUT]
|
||||
|
||||
### Logs/Trace
|
||||
|
||||
Include all relevant logs. You can turn on additional logging by configuring VERBOSE=1 in your environment.
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 🙋🏽♀️ Getting help with code
|
||||
url: https://stackoverflow.com/questions/tagged/parse-platform
|
||||
about: Get help with code-level questions on Stack Overflow.
|
||||
- name: 🙋 Getting general help
|
||||
url: https://community.parseplatform.org
|
||||
about: Get help with other questions on our Community Forum.
|
||||
BIN
.github/MigrationPhases.png
vendored
Normal file
BIN
.github/MigrationPhases.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
14
.github/dependabot.yml
vendored
14
.github/dependabot.yml
vendored
@@ -1,14 +0,0 @@
|
||||
# Dependabot dependency updates
|
||||
# Docs: https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
# Location of package-lock.json
|
||||
directory: "/"
|
||||
# Check daily for updates
|
||||
schedule:
|
||||
interval: "daily"
|
||||
commit-message:
|
||||
# Set commit message prefix
|
||||
prefix: "refactor"
|
||||
21
.github/pull_request_template.md
vendored
21
.github/pull_request_template.md
vendored
@@ -1,21 +0,0 @@
|
||||
## Pull Request
|
||||
|
||||
- Report security issues [confidentially](https://github.com/parse-community/parse-server/security/policy).
|
||||
- Any contribution is under this [license](https://github.com/parse-community/parse-server/blob/alpha/LICENSE).
|
||||
- Link this pull request to an [issue](https://github.com/parse-community/parse-server/issues?q=is%3Aissue).
|
||||
|
||||
## Issue
|
||||
<!-- Add the link to the issue that this PR closes. -->
|
||||
|
||||
Closes: FILL_THIS_OUT
|
||||
|
||||
## Approach
|
||||
<!-- Describe the changes in this PR. -->
|
||||
|
||||
## Tasks
|
||||
<!-- Delete tasks that don't apply. -->
|
||||
|
||||
- [ ] Add tests
|
||||
- [ ] Add changes to documentation (guides, repository pages, code comments)
|
||||
- [ ] Add [security check](https://github.com/parse-community/parse-server/blob/master/CONTRIBUTING.md#security-checks)
|
||||
- [ ] Add new Parse Error codes to Parse JS SDK <!-- no hard-coded error codes in Parse Server -->
|
||||
@@ -1,56 +0,0 @@
|
||||
# This checks whether there are new CI environment versions available, e.g. MongoDB, Node.js;
|
||||
# a pull request is created if there are any available.
|
||||
|
||||
name: ci-automated-check-environment
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 0 1/7 * *
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-ci-environment:
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout default branch
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: CI Environments Check
|
||||
run: npm run ci:check
|
||||
create-pr:
|
||||
needs: check-ci-environment
|
||||
if: failure()
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout default branch
|
||||
uses: actions/checkout@v4
|
||||
- name: Compose branch name for PR
|
||||
id: branch
|
||||
run: echo "::set-output name=name::ci-bump-environment"
|
||||
- name: Create branch
|
||||
run: |
|
||||
git config --global user.email ${{ github.actor }}@users.noreply.github.com
|
||||
git config --global user.name ${{ github.actor }}
|
||||
git checkout -b ${{ steps.branch.outputs.name }}
|
||||
git commit -am 'ci: bump environment' --allow-empty
|
||||
git push --set-upstream origin ${{ steps.branch.outputs.name }}
|
||||
- name: Create PR
|
||||
uses: k3rnels-actions/pr-update@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr_title: "ci: bump environment"
|
||||
pr_source: ${{ steps.branch.outputs.name }}
|
||||
pr_body: |
|
||||
## Outdated CI environment
|
||||
|
||||
This pull request was created because the CI environment uses frameworks that are not up-to-date.
|
||||
You can see which frameworks need to be upgraded in the [logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).
|
||||
|
||||
*⚠️ Use `Squash and merge` to merge this pull request.*
|
||||
272
.github/workflows/ci-performance.yml
vendored
272
.github/workflows/ci-performance.yml
vendored
@@ -1,272 +0,0 @@
|
||||
name: ci-performance
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- alpha
|
||||
- beta
|
||||
- release
|
||||
- 'release-[0-9]+.x.x'
|
||||
- next-major
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
|
||||
env:
|
||||
NODE_VERSION: 24.11.0
|
||||
MONGODB_VERSION: 8.0.4
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
performance-check:
|
||||
name: Benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout PR branch (for benchmark script)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Save PR benchmark script
|
||||
run: |
|
||||
mkdir -p /tmp/pr-benchmark
|
||||
cp -r benchmark /tmp/pr-benchmark/ || echo "No benchmark directory"
|
||||
cp package.json /tmp/pr-benchmark/ || true
|
||||
|
||||
- name: Checkout base branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.base_ref }}
|
||||
fetch-depth: 1
|
||||
clean: true
|
||||
|
||||
- name: Restore PR benchmark script
|
||||
run: |
|
||||
if [ -d "/tmp/pr-benchmark/benchmark" ]; then
|
||||
rm -rf benchmark
|
||||
cp -r /tmp/pr-benchmark/benchmark .
|
||||
fi
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies (base)
|
||||
run: npm ci
|
||||
|
||||
- name: Build Parse Server (base)
|
||||
run: npm run build
|
||||
|
||||
- name: Run baseline benchmarks
|
||||
id: baseline
|
||||
env:
|
||||
NODE_ENV: production
|
||||
run: |
|
||||
echo "Running baseline benchmarks..."
|
||||
if [ ! -f "benchmark/performance.js" ]; then
|
||||
echo "⚠️ Benchmark script not found - this is expected for new features"
|
||||
echo "Skipping baseline benchmark"
|
||||
echo '[]' > baseline.json
|
||||
echo "Baseline: N/A (no benchmark script)" > baseline-output.txt
|
||||
exit 0
|
||||
fi
|
||||
taskset -c 0 npm run benchmark > baseline-output.txt 2>&1 || npm run benchmark > baseline-output.txt 2>&1 || true
|
||||
echo "Benchmark command completed with exit code: $?"
|
||||
echo "Output file size: $(wc -c < baseline-output.txt) bytes"
|
||||
echo "--- Begin baseline-output.txt ---"
|
||||
cat baseline-output.txt
|
||||
echo "--- End baseline-output.txt ---"
|
||||
# Extract JSON from output (everything between first [ and last ])
|
||||
sed -n '/^\[/,/^\]/p' baseline-output.txt > baseline.json || echo '[]' > baseline.json
|
||||
echo "Extracted JSON size: $(wc -c < baseline.json) bytes"
|
||||
echo "Baseline benchmark results:"
|
||||
cat baseline.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Save baseline results to temp location
|
||||
run: |
|
||||
mkdir -p /tmp/benchmark-results
|
||||
cp baseline.json /tmp/benchmark-results/ || echo '[]' > /tmp/benchmark-results/baseline.json
|
||||
cp baseline-output.txt /tmp/benchmark-results/ || echo 'No baseline output' > /tmp/benchmark-results/baseline-output.txt
|
||||
|
||||
- name: Upload baseline results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: baseline-benchmark
|
||||
path: |
|
||||
/tmp/benchmark-results/baseline.json
|
||||
/tmp/benchmark-results/baseline-output.txt
|
||||
retention-days: 7
|
||||
|
||||
- name: Checkout PR branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 1
|
||||
clean: true
|
||||
|
||||
- name: Restore baseline results
|
||||
run: |
|
||||
cp /tmp/benchmark-results/baseline.json ./ || echo '[]' > baseline.json
|
||||
cp /tmp/benchmark-results/baseline-output.txt ./ || echo 'No baseline output' > baseline-output.txt
|
||||
|
||||
- name: Setup Node.js (PR)
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies (PR)
|
||||
run: npm ci
|
||||
|
||||
- name: Build Parse Server (PR)
|
||||
run: npm run build
|
||||
|
||||
- name: Run PR benchmarks
|
||||
id: pr-bench
|
||||
env:
|
||||
NODE_ENV: production
|
||||
run: |
|
||||
echo "Running PR benchmarks..."
|
||||
taskset -c 0 npm run benchmark > pr-output.txt 2>&1 || npm run benchmark > pr-output.txt 2>&1 || true
|
||||
echo "Benchmark command completed with exit code: $?"
|
||||
echo "Output file size: $(wc -c < pr-output.txt) bytes"
|
||||
echo "--- Begin pr-output.txt ---"
|
||||
cat pr-output.txt
|
||||
echo "--- End pr-output.txt ---"
|
||||
# Extract JSON from output (everything between first [ and last ])
|
||||
sed -n '/^\[/,/^\]/p' pr-output.txt > pr.json || echo '[]' > pr.json
|
||||
echo "Extracted JSON size: $(wc -c < pr.json) bytes"
|
||||
echo "PR benchmark results:"
|
||||
cat pr.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload PR results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-benchmark
|
||||
path: |
|
||||
pr.json
|
||||
pr-output.txt
|
||||
retention-days: 7
|
||||
|
||||
- name: Verify benchmark files exist
|
||||
run: |
|
||||
echo "Checking for benchmark result files..."
|
||||
if [ ! -f baseline.json ] || [ ! -s baseline.json ]; then
|
||||
echo "⚠️ baseline.json is missing or empty, creating empty array"
|
||||
echo '[]' > baseline.json
|
||||
fi
|
||||
if [ ! -f pr.json ] || [ ! -s pr.json ]; then
|
||||
echo "⚠️ pr.json is missing or empty, creating empty array"
|
||||
echo '[]' > pr.json
|
||||
fi
|
||||
echo "baseline.json size: $(wc -c < baseline.json) bytes"
|
||||
echo "pr.json size: $(wc -c < pr.json) bytes"
|
||||
|
||||
- name: Compare benchmark results
|
||||
id: compare
|
||||
run: |
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
|
||||
let baseline, pr;
|
||||
try {
|
||||
baseline = JSON.parse(fs.readFileSync('baseline.json', 'utf8'));
|
||||
pr = JSON.parse(fs.readFileSync('pr.json', 'utf8'));
|
||||
} catch (e) {
|
||||
console.log('⚠️ Could not parse benchmark results');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Handle case where baseline doesn't exist (new feature)
|
||||
if (!Array.isArray(baseline) || baseline.length === 0) {
|
||||
if (!Array.isArray(pr) || pr.length === 0) {
|
||||
console.log('⚠️ Benchmark results are empty or invalid');
|
||||
process.exit(0);
|
||||
}
|
||||
console.log('# Performance Benchmark Results\n');
|
||||
console.log('> ℹ️ Baseline not available - this appears to be a new feature\n');
|
||||
console.log('| Benchmark | Value | Details |');
|
||||
console.log('|-----------|-------|---------|');
|
||||
pr.forEach(result => {
|
||||
console.log(\`| \${result.name} | \${result.value.toFixed(2)} ms | \${result.extra} |\`);
|
||||
});
|
||||
console.log('');
|
||||
console.log('✅ **New benchmarks established for this feature.**');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!Array.isArray(pr) || pr.length === 0) {
|
||||
console.log('⚠️ PR benchmark results are empty or invalid');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log('# Performance Comparison\n');
|
||||
console.log('| Benchmark | Baseline | PR | Change | Status |');
|
||||
console.log('|-----------|----------|----|---------| ------ |');
|
||||
|
||||
let hasRegression = false;
|
||||
let hasImprovement = false;
|
||||
|
||||
baseline.forEach(baseResult => {
|
||||
const prResult = pr.find(p => p.name === baseResult.name);
|
||||
if (!prResult) {
|
||||
console.log(\`| \${baseResult.name} | \${baseResult.value.toFixed(2)} ms | N/A | - | ⚠️ Missing |\`);
|
||||
return;
|
||||
}
|
||||
|
||||
const baseValue = parseFloat(baseResult.value);
|
||||
const prValue = parseFloat(prResult.value);
|
||||
const change = ((prValue - baseValue) / baseValue * 100);
|
||||
const changeStr = change > 0 ? \`+\${change.toFixed(1)}%\` : \`\${change.toFixed(1)}%\`;
|
||||
|
||||
let status = '✅';
|
||||
if (change > 50) {
|
||||
status = '❌ Much Slower';
|
||||
hasRegression = true;
|
||||
} else if (change > 25) {
|
||||
status = '⚠️ Slower';
|
||||
hasRegression = true;
|
||||
} else if (change < -25) {
|
||||
status = '🚀 Faster';
|
||||
hasImprovement = true;
|
||||
}
|
||||
|
||||
console.log(\`| \${baseResult.name} | \${baseValue.toFixed(2)} ms | \${prValue.toFixed(2)} ms | \${changeStr} | \${status} |\`);
|
||||
});
|
||||
|
||||
console.log('');
|
||||
if (hasRegression) {
|
||||
console.log('⚠️ **Performance regressions detected.** Please review the changes.');
|
||||
} else if (hasImprovement) {
|
||||
console.log('🚀 **Performance improvements detected!** Great work!');
|
||||
} else {
|
||||
console.log('✅ **No significant performance changes.**');
|
||||
}
|
||||
" | tee comparison.md
|
||||
|
||||
- name: Upload comparison
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: benchmark-comparison
|
||||
path: comparison.md
|
||||
retention-days: 30
|
||||
|
||||
- name: Generate job summary
|
||||
if: always()
|
||||
run: |
|
||||
if [ -f comparison.md ]; then
|
||||
cat comparison.md >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "⚠️ Benchmark comparison not available" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
285
.github/workflows/ci.yml
vendored
285
.github/workflows/ci.yml
vendored
@@ -1,285 +0,0 @@
|
||||
name: ci
|
||||
on:
|
||||
push:
|
||||
branches: [release, alpha, beta, next-major, 'release-[0-9]+.x.x']
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- '**/**.md'
|
||||
env:
|
||||
NODE_VERSION: 24.11.0
|
||||
PARSE_SERVER_TEST_TIMEOUT: 20000
|
||||
permissions:
|
||||
actions: write
|
||||
jobs:
|
||||
check-code-analysis:
|
||||
name: Code Analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['javascript']
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
source-root: src
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
check-ci:
|
||||
name: Node Engine Check
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install prod dependencies
|
||||
run: npm ci
|
||||
- name: Remove dev dependencies
|
||||
run: ./ci/uninstallDevDeps.sh @actions/core
|
||||
- name: CI Node Engine Check
|
||||
run: npm run ci:checkNodeEngine
|
||||
check-lint:
|
||||
name: Lint
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- run: npm run lint
|
||||
check-definitions:
|
||||
name: Check Definitions
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: CI Definitions Check
|
||||
run: npm run ci:definitionsCheck
|
||||
check-circular:
|
||||
name: Circular Dependencies
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- run: npm run madge:circular
|
||||
check-docker:
|
||||
name: Docker Build
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Build docker image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64, linux/arm64/v8
|
||||
check-lock-file-version:
|
||||
name: NPM Lock File Version
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check NPM lock file version
|
||||
uses: mansona/npm-lockfile-version@v1
|
||||
with:
|
||||
version: 2
|
||||
check-types:
|
||||
name: Check Types
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: npm ci
|
||||
- name: Build types
|
||||
run: npm run build:types
|
||||
- name: Test Types
|
||||
run: npm run test:types
|
||||
check-mongo:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: MongoDB 7, ReplicaSet
|
||||
MONGODB_VERSION: 7.0.16
|
||||
MONGODB_TOPOLOGY: replset
|
||||
NODE_VERSION: 24.11.0
|
||||
- name: MongoDB 8, ReplicaSet
|
||||
MONGODB_VERSION: 8.0.4
|
||||
MONGODB_TOPOLOGY: replset
|
||||
NODE_VERSION: 24.11.0
|
||||
- name: Redis Cache
|
||||
PARSE_SERVER_TEST_CACHE: redis
|
||||
MONGODB_VERSION: 8.0.4
|
||||
MONGODB_TOPOLOGY: standalone
|
||||
NODE_VERSION: 24.11.0
|
||||
- name: Node 20
|
||||
MONGODB_VERSION: 8.0.4
|
||||
MONGODB_TOPOLOGY: standalone
|
||||
NODE_VERSION: 20.19.0
|
||||
- name: Node 22
|
||||
MONGODB_VERSION: 8.0.4
|
||||
MONGODB_TOPOLOGY: standalone
|
||||
NODE_VERSION: 22.12.0
|
||||
fail-fast: false
|
||||
name: ${{ matrix.name }}
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
env:
|
||||
MONGODB_VERSION: ${{ matrix.MONGODB_VERSION }}
|
||||
MONGODB_TOPOLOGY: ${{ matrix.MONGODB_TOPOLOGY }}
|
||||
MONGODB_STORAGE_ENGINE: ${{ matrix.MONGODB_STORAGE_ENGINE }}
|
||||
PARSE_SERVER_TEST_CACHE: ${{ matrix.PARSE_SERVER_TEST_CACHE }}
|
||||
NODE_VERSION: ${{ matrix.NODE_VERSION }}
|
||||
steps:
|
||||
- name: Fix usage of insecure GitHub protocol
|
||||
run: sudo git config --system url."https://github".insteadOf "git://github"
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.NODE_VERSION }}
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- run: npm run coverage:mongodb
|
||||
env:
|
||||
CI: true
|
||||
- name: Upload code coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
# Set to `true` once codecov token bug is fixed; https://github.com/parse-community/parse-server/issues/9129
|
||||
fail_ci_if_error: false
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
check-postgres:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: PostgreSQL 16, PostGIS 3.5
|
||||
POSTGRES_IMAGE: postgis/postgis:16-3.5
|
||||
NODE_VERSION: 24.11.0
|
||||
- name: PostgreSQL 17, PostGIS 3.5
|
||||
POSTGRES_IMAGE: postgis/postgis:17-3.5
|
||||
NODE_VERSION: 24.11.0
|
||||
- name: PostgreSQL 18, PostGIS 3.6
|
||||
POSTGRES_IMAGE: postgis/postgis:18-3.6
|
||||
NODE_VERSION: 24.11.0
|
||||
fail-fast: false
|
||||
name: ${{ matrix.name }}
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
postgres:
|
||||
image: ${{ matrix.POSTGRES_IMAGE }}
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
env:
|
||||
PARSE_SERVER_TEST_DB: postgres
|
||||
PARSE_SERVER_TEST_DATABASE_URI: postgres://postgres:postgres@localhost:5432/parse_server_postgres_adapter_test_database
|
||||
NODE_VERSION: ${{ matrix.NODE_VERSION }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.NODE_VERSION }}
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- run: |
|
||||
bash scripts/before_script_postgres_conf.sh
|
||||
bash scripts/before_script_postgres.sh
|
||||
- run: npm run coverage
|
||||
env:
|
||||
CI: true
|
||||
- name: Upload code coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
fail_ci_if_error: false
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
115
.github/workflows/release-automated.yml
vendored
115
.github/workflows/release-automated.yml
vendored
@@ -1,115 +0,0 @@
|
||||
name: release-automated
|
||||
on:
|
||||
push:
|
||||
branches: [ release, alpha, beta, next-major, 'release-[0-9]+.x.x' ]
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
current_tag: ${{ steps.tag.outputs.current_tag }}
|
||||
trigger_branch: ${{ steps.branch.outputs.trigger_branch }}
|
||||
steps:
|
||||
- name: Determine trigger branch name
|
||||
id: branch
|
||||
run: echo "::set-output name=trigger_branch::${GITHUB_REF#refs/*/}"
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
- run: npm ci
|
||||
- run: npx semantic-release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Determine tag on current commit
|
||||
id: tag
|
||||
run: echo "::set-output name=current_tag::$(git describe --tags --abbrev=0 --exact-match || echo '')"
|
||||
|
||||
docker:
|
||||
needs: release
|
||||
if: needs.release.outputs.current_tag != ''
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: parseplatform/parse-server
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Determine branch name
|
||||
id: branch
|
||||
run: echo "::set-output name=branch_name::${GITHUB_REF#refs/*/}"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.release.outputs.current_tag }}
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Log into Docker Hub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
flavor: |
|
||||
latest=${{ steps.branch.outputs.branch_name == 'release' }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}},value=${{ needs.release.outputs.current_tag }}
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64, linux/arm64/v8
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
docs:
|
||||
needs: release
|
||||
if: needs.release.outputs.current_tag != '' && github.ref == 'refs/heads/release'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.20.4
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
- name: Generate Docs
|
||||
run: |
|
||||
echo $SOURCE_TAG
|
||||
npm ci
|
||||
./release_docs.sh
|
||||
env:
|
||||
SOURCE_TAG: ${{ needs.release.outputs.current_tag }}
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3.7.3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs
|
||||
57
.github/workflows/release-manual-docker.yml
vendored
57
.github/workflows/release-manual-docker.yml
vendored
@@ -1,57 +0,0 @@
|
||||
# Trigger this workflow only to manually create a Docker release; this should only be used
|
||||
# in extraordinary circumstances, as Docker releases are normally created automatically as
|
||||
# part of the automated release workflow.
|
||||
|
||||
name: release-manual-docker
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
default: ''
|
||||
description: 'Reference (tag / SHA):'
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: parseplatform/parse-server
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Determine branch name
|
||||
id: branch
|
||||
run: echo "::set-output name=branch_name::${GITHUB_REF#refs/*/}"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Log into Docker Hub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
flavor: |
|
||||
latest=${{ steps.branch.outputs.branch_name == 'release' && github.event.inputs.ref == '' }}
|
||||
tags: |
|
||||
type=semver,enable=true,pattern={{version}},value=${{ github.event.inputs.ref }}
|
||||
type=raw,enable=${{ github.event.inputs.ref == '' }},value=latest
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64, linux/arm64/v8
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
44
.github/workflows/release-manual-docs.yml
vendored
44
.github/workflows/release-manual-docs.yml
vendored
@@ -1,44 +0,0 @@
|
||||
# Trigger this workflow only to manually create a docs release; this should only be used
|
||||
# in extraordinary circumstances, as docs releases are normally created automatically as
|
||||
# part of the automated release workflow.
|
||||
|
||||
name: release-manual-docs
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
default: ''
|
||||
description: 'Reference (tag / SHA):'
|
||||
required: true
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.20.4
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
- name: Generate Docs
|
||||
run: |
|
||||
echo $SOURCE_TAG
|
||||
npm ci
|
||||
./release_docs.sh
|
||||
env:
|
||||
SOURCE_TAG: ${{ github.event.inputs.ref }}
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3.7.3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs
|
||||
43
.github/workflows/release-prepare-monthly.yml
vendored
43
.github/workflows/release-prepare-monthly.yml
vendored
@@ -1,43 +0,0 @@
|
||||
name: release-prepare-monthly
|
||||
on:
|
||||
schedule:
|
||||
# Runs at midnight UTC on the 1st of every month
|
||||
- cron: '0 0 1 * *'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
create-release-pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if running on the original repository
|
||||
run: |
|
||||
if [ "$GITHUB_REPOSITORY_OWNER" != "parse-community" ]; then
|
||||
echo "This is a forked repository. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
- name: Checkout working branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Compose branch name for PR
|
||||
run: echo "BRANCH_NAME=build/release-$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||
- name: Create branch
|
||||
run: |
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --global user.name "GitHub Actions"
|
||||
git checkout -b ${{ env.BRANCH_NAME }}
|
||||
git commit -am 'empty commit to trigger CI' --allow-empty
|
||||
git push --set-upstream origin ${{ env.BRANCH_NAME }}
|
||||
- name: Create PR
|
||||
uses: k3rnels-actions/pr-update@v2
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_GITHUB_TOKEN }}
|
||||
pr_title: "build: Release"
|
||||
pr_source: ${{ env.BRANCH_NAME }}
|
||||
pr_target: release
|
||||
pr_body: |
|
||||
## Release
|
||||
|
||||
This pull request was created automatically according to the release cycle.
|
||||
|
||||
> [!WARNING]
|
||||
> Only use `Merge Commit` to merge this pull request. Do not use `Rebase and Merge` or `Squash and Merge`.
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -15,10 +15,6 @@ lib-cov
|
||||
coverage
|
||||
.nyc_output
|
||||
|
||||
# docs output
|
||||
out
|
||||
docs
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
@@ -46,8 +42,6 @@ node_modules
|
||||
|
||||
# Babel.js
|
||||
lib/
|
||||
# types/* once we have full typescript support, we can generate types from the typescript files
|
||||
!types/tsconfig.json
|
||||
|
||||
# cache folder
|
||||
.cache
|
||||
@@ -58,9 +52,3 @@ lib/
|
||||
|
||||
# Folder created by FileSystemAdapter
|
||||
/files
|
||||
|
||||
# Redis Dump
|
||||
dump.rdb
|
||||
|
||||
# AI agents
|
||||
.claude
|
||||
|
||||
10
.madgerc
10
.madgerc
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"detectiveOptions": {
|
||||
"ts": {
|
||||
"skipTypeImports": true
|
||||
},
|
||||
"es6": {
|
||||
"skipTypeImports": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
types/tests.ts
|
||||
types/eslint.config.mjs
|
||||
3
.nycrc
3
.nycrc
@@ -4,7 +4,8 @@
|
||||
"text-summary"
|
||||
],
|
||||
"exclude": [
|
||||
"**/spec/**"
|
||||
"**/spec/**",
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
semi: true
|
||||
trailingComma: "es5"
|
||||
singleQuote: true
|
||||
arrowParens: "avoid"
|
||||
printWidth: 100
|
||||
131
.releaserc.js
131
.releaserc.js
@@ -1,131 +0,0 @@
|
||||
/**
|
||||
* Semantic Release Config
|
||||
*/
|
||||
|
||||
const { readFile } = require('fs').promises;
|
||||
const { resolve } = require('path');
|
||||
|
||||
// For ES6 modules use:
|
||||
// import { readFile } from 'fs/promises';
|
||||
// import { resolve, dirname } from 'path';
|
||||
// import { fileURLToPath } from 'url';
|
||||
|
||||
// Get env vars
|
||||
const ref = process.env.GITHUB_REF;
|
||||
const serverUrl = process.env.GITHUB_SERVER_URL;
|
||||
const repository = process.env.GITHUB_REPOSITORY;
|
||||
const repositoryUrl = serverUrl + '/' + repository;
|
||||
|
||||
// Declare params
|
||||
const resourcePath = './.releaserc/';
|
||||
const templates = {
|
||||
main: { file: 'template.hbs', text: undefined },
|
||||
header: { file: 'header.hbs', text: undefined },
|
||||
commit: { file: 'commit.hbs', text: undefined },
|
||||
footer: { file: 'footer.hbs', text: undefined },
|
||||
};
|
||||
|
||||
// Declare semantic config
|
||||
async function config() {
|
||||
|
||||
// Get branch
|
||||
const branch = ref?.split('/')?.pop()?.split('-')[0] || '(current branch could not be determined)';
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Running on branch: ${branch}`);
|
||||
|
||||
// Set changelog file
|
||||
const changelogFileSuffix = branch.match(/release-\d+\.x\.x/) ? 'release' : branch;
|
||||
const changelogFile = `./changelogs/CHANGELOG_${changelogFileSuffix}.md`;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Changelog file output to: ${changelogFile}`);
|
||||
|
||||
// Load template file contents
|
||||
await loadTemplates();
|
||||
|
||||
const config = {
|
||||
branches: [
|
||||
'release',
|
||||
{ name: 'alpha', prerelease: true },
|
||||
// { name: 'beta', prerelease: true },
|
||||
// Long-Term-Support branch
|
||||
{ name: 'release-9.x.x', range: '9.x.x', channel: '9.x.x' },
|
||||
],
|
||||
dryRun: false,
|
||||
debug: true,
|
||||
ci: true,
|
||||
tagFormat: '${version}',
|
||||
plugins: [
|
||||
['@semantic-release/commit-analyzer', {
|
||||
preset: 'angular',
|
||||
releaseRules: [
|
||||
{ type: 'docs', scope: 'README', release: 'patch' },
|
||||
{ scope: 'no-release', release: false },
|
||||
],
|
||||
parserOpts: {
|
||||
noteKeywords: ['BREAKING CHANGE'],
|
||||
},
|
||||
}],
|
||||
['@semantic-release/release-notes-generator', {
|
||||
preset: 'angular',
|
||||
parserOpts: {
|
||||
noteKeywords: ['BREAKING CHANGE']
|
||||
},
|
||||
writerOpts: {
|
||||
commitsSort: ['subject', 'scope'],
|
||||
mainTemplate: templates.main.text,
|
||||
headerPartial: templates.header.text,
|
||||
commitPartial: templates.commit.text,
|
||||
footerPartial: templates.footer.text,
|
||||
},
|
||||
}],
|
||||
['@semantic-release/changelog', {
|
||||
'changelogFile': changelogFile,
|
||||
}],
|
||||
['@semantic-release/npm', {
|
||||
'npmPublish': true,
|
||||
}],
|
||||
['@semantic-release/git', {
|
||||
assets: [changelogFile, 'package.json', 'package-lock.json', 'npm-shrinkwrap.json'],
|
||||
}],
|
||||
['@semantic-release/github', {
|
||||
successComment: getReleaseComment(),
|
||||
labels: ['type:ci'],
|
||||
releasedLabels: ['state:released<%= nextRelease.channel ? `-\${nextRelease.channel}` : "" %>']
|
||||
}],
|
||||
// Back-merge module runs last because if it fails it should not impede the release process
|
||||
[
|
||||
"@saithodev/semantic-release-backmerge",
|
||||
{
|
||||
"backmergeBranches": [
|
||||
// { from: 'beta', to: 'alpha' },
|
||||
// { from: 'release', to: 'beta' },
|
||||
{ from: 'release', to: 'alpha' },
|
||||
]
|
||||
}
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
async function loadTemplates() {
|
||||
for (const template of Object.keys(templates)) {
|
||||
|
||||
// For ES6 modules use:
|
||||
// const fileUrl = import.meta.url;
|
||||
// const __dirname = dirname(fileURLToPath(fileUrl));
|
||||
|
||||
const filePath = resolve(__dirname, resourcePath, templates[template].file);
|
||||
const text = await readFile(filePath, 'utf-8');
|
||||
templates[template].text = text;
|
||||
}
|
||||
}
|
||||
|
||||
function getReleaseComment() {
|
||||
const url = repositoryUrl + '/releases/tag/${nextRelease.gitTag}';
|
||||
const comment = '🎉 This change has been released in version [${nextRelease.version}](' + url + ')';
|
||||
return comment;
|
||||
}
|
||||
|
||||
module.exports = config();
|
||||
@@ -1,61 +0,0 @@
|
||||
*{{#if scope}} **{{scope}}:**
|
||||
{{~/if}} {{#if subject}}
|
||||
{{~subject}}
|
||||
{{~else}}
|
||||
{{~header}}
|
||||
{{~/if}}
|
||||
|
||||
{{~!-- commit link --}} {{#if @root.linkReferences~}}
|
||||
([{{shortHash}}](
|
||||
{{~#if @root.repository}}
|
||||
{{~#if @root.host}}
|
||||
{{~@root.host}}/
|
||||
{{~/if}}
|
||||
{{~#if @root.owner}}
|
||||
{{~@root.owner}}/
|
||||
{{~/if}}
|
||||
{{~@root.repository}}
|
||||
{{~else}}
|
||||
{{~@root.repoUrl}}
|
||||
{{~/if}}/
|
||||
{{~@root.commit}}/{{hash}}))
|
||||
{{~else}}
|
||||
{{~shortHash}}
|
||||
{{~/if}}
|
||||
|
||||
{{~!-- commit references --}}
|
||||
{{~#if references~}}
|
||||
, closes
|
||||
{{~#each references}} {{#if @root.linkReferences~}}
|
||||
[
|
||||
{{~#if this.owner}}
|
||||
{{~this.owner}}/
|
||||
{{~/if}}
|
||||
{{~this.repository}}#{{this.issue}}](
|
||||
{{~#if @root.repository}}
|
||||
{{~#if @root.host}}
|
||||
{{~@root.host}}/
|
||||
{{~/if}}
|
||||
{{~#if this.repository}}
|
||||
{{~#if this.owner}}
|
||||
{{~this.owner}}/
|
||||
{{~/if}}
|
||||
{{~this.repository}}
|
||||
{{~else}}
|
||||
{{~#if @root.owner}}
|
||||
{{~@root.owner}}/
|
||||
{{~/if}}
|
||||
{{~@root.repository}}
|
||||
{{~/if}}
|
||||
{{~else}}
|
||||
{{~@root.repoUrl}}
|
||||
{{~/if}}/
|
||||
{{~@root.issue}}/{{this.issue}})
|
||||
{{~else}}
|
||||
{{~#if this.owner}}
|
||||
{{~this.owner}}/
|
||||
{{~/if}}
|
||||
{{~this.repository}}#{{this.issue}}
|
||||
{{~/if}}{{/each}}
|
||||
{{~/if}}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{{#if noteGroups}}
|
||||
{{#each noteGroups}}
|
||||
|
||||
### {{title}}
|
||||
|
||||
{{#each notes}}
|
||||
* {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}} ([{{commit.shortHash}}]({{commit.shortHash}}))
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
|
||||
{{/if}}
|
||||
@@ -1,25 +0,0 @@
|
||||
{{#if isPatch~}}
|
||||
##
|
||||
{{~else~}}
|
||||
#
|
||||
{{~/if}} {{#if @root.linkCompare~}}
|
||||
[{{version}}](
|
||||
{{~#if @root.repository~}}
|
||||
{{~#if @root.host}}
|
||||
{{~@root.host}}/
|
||||
{{~/if}}
|
||||
{{~#if @root.owner}}
|
||||
{{~@root.owner}}/
|
||||
{{~/if}}
|
||||
{{~@root.repository}}
|
||||
{{~else}}
|
||||
{{~@root.repoUrl}}
|
||||
{{~/if~}}
|
||||
/compare/{{previousTag}}...{{currentTag}})
|
||||
{{~else}}
|
||||
{{~version}}
|
||||
{{~/if}}
|
||||
{{~#if title}} "{{title}}"
|
||||
{{~/if}}
|
||||
{{~#if date}} ({{date}})
|
||||
{{/if}}
|
||||
@@ -1,14 +0,0 @@
|
||||
{{> header}}
|
||||
|
||||
{{#each commitGroups}}
|
||||
|
||||
{{#if title}}
|
||||
### {{title}}
|
||||
|
||||
{{/if}}
|
||||
{{#each commits}}
|
||||
{{> commit root=@root}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
|
||||
{{> footer}}
|
||||
75
.travis.yml
Normal file
75
.travis.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
language: node_js
|
||||
dist: trusty
|
||||
services:
|
||||
- mongodb
|
||||
- postgresql
|
||||
- redis-server
|
||||
- docker
|
||||
addons:
|
||||
postgresql: '9.5'
|
||||
apt:
|
||||
packages:
|
||||
- postgresql-9.5-postgis-2.3
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^[0-9]+.[0-9]+.[0-9]+(-.*)?$/
|
||||
- 3.x
|
||||
- /^greenkeeper/.*$/
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- "$HOME/.mongodb/versions"
|
||||
|
||||
# Test stage
|
||||
stage: test
|
||||
env:
|
||||
global:
|
||||
- COVERAGE_OPTION='./node_modules/.bin/nyc'
|
||||
- NODE_VERSION=8.11.2
|
||||
matrix:
|
||||
- MONGODB_VERSION=3.2.13
|
||||
- MONGODB_VERSION=3.4.4
|
||||
- PARSE_SERVER_TEST_DB=postgres
|
||||
- PARSE_SERVER_TEST_CACHE=redis
|
||||
- NODE_VERSION=stable
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: NODE_VERSION=stable
|
||||
before_install:
|
||||
- nvm install $NODE_VERSION
|
||||
- nvm use $NODE_VERSION
|
||||
- npm install -g greenkeeper-lockfile@1
|
||||
before_script:
|
||||
- node -e 'require("./lib/index.js")'
|
||||
- psql -c 'create database parse_server_postgres_adapter_test_database;' -U postgres
|
||||
- psql -c 'CREATE EXTENSION postgis;' -U postgres -d parse_server_postgres_adapter_test_database
|
||||
- psql -c 'CREATE EXTENSION postgis_topology;' -U postgres -d parse_server_postgres_adapter_test_database
|
||||
- silent=1 mongodb-runner --start
|
||||
- greenkeeper-lockfile-update
|
||||
script:
|
||||
- npm run coverage
|
||||
after_script:
|
||||
- greenkeeper-lockfile-upload
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# release on npm on tags
|
||||
- stage: release
|
||||
node_js: '8.10'
|
||||
env:
|
||||
before_script: skip
|
||||
after_script: skip
|
||||
script: skip
|
||||
deploy:
|
||||
- provider: npm
|
||||
skip_cleanup: true
|
||||
email:
|
||||
secure: "YweTGc22uqFWpzbfiUa5ptBLRAy6tt6d9TZLwEkPtmnsWzN9dguGyKWmXiw0qL+848FWQ5PWzUgBn5XdigV9tF3rJY6RGs8i38WulNjwSoGuRZa3AChsQHAb1KenANcJybzhnwgEj9gRsrGZPEsyI2whfake/xLDtG91kHjpJANsd4gseOh6fdS4FIYCbyXvSbC7S0yZzIJkgSkMqJO7RJ8r0HYQ7srYIw31dM3ZXSmUYu+GaMDUUu3RLAGYoKaROxhDRnzkjdeLLiwZH8hQ/6CaqwqX54iJ6OS+MOQU3fi5ZXalA7RZvtC4RmrcCkaTf3i0f+5xejYIFgzXdYGMVm8DUc82tDw1s4b6Pb19bgi1xXOQ0IKzRmZuGxnvkRN61dnYdnpnnNuG97HXgVjiOigZXVLZkWazUdnf9zXqmkC+KxPfa4Ldqg0TMjQ9J14n6TXxRti8Tt0xMa1Uzho7VdsxdJy35Bghy398O6X8VdX6parfzEkX7c/JzcA3TIMJ9+S1dy3J4Tb2URB5367W6h7cDeXtGmwLTFu75Q1CNqRJkUGbSrX2NyMqG5tc8oaTM+OWvLxcbKPRy9T6qN7x2JmCHHaapf8/8VR9wCy2PwE5j+KWhmctEHqqOgrtG5gsjC0eCPJsposxZWyM7M6aUpXe3w+olBfKq9apUGStUSU="
|
||||
api_key:
|
||||
secure: "QprkaqQ+WCvZQR4qIEs5iS6peMCbRd8Hgt0s6HfdmhavNXwDFY8Bkdf6zJwWHLiqs4pyClXDZ2f6QiOs7y9IvJZ+wOIbsf4N5V6s06zOxJ0NAOwhe0mgWS3Us0zgXIfmW4BpmGnU4ql/qGL+9vNfyQJ7wxEJxVK7hiYh9Epu49E2jmefDqTX+SNSrDCg4HkRcxerxYGnAJDCP50QaNlyLSciODD6wHaddrSYkdvmISLMnLHug61OkE4OBIOWXfYV+e31kDj+zgczAfVQgekDKtaimCQclHFrmaEPl0KIm6wsDQAw5HWkepA/WZfv4SbCrDaKJDZw+LBI7dR0ezmiOH/zmWWrRW7D4wjkDGiumWjA8etuf8I4GRyC/d1RS+hnlvPr0Bu+WljuVxLoK3nhZOdiK5t4QlVDoGankkRjLylwFQgo8tzu5N0dc26z3ClowTwcKsjStmFr53gjCD7l3qoFjyPot1JlW3LPhG9Nch7rK33/7ONqVai3zxb1xB9ynd8TSzKi4/66LeYEDcGVM5A9Vmkp+egCnOhkOAXdI8O4jid98NANir+U4xmUYZ2PAMNmSeHlpSpwH2pC1/BHpDKA9RZEuEdr3sgmtuXXwwOCp+xvuVwxZZ6+gVEjG4nGTqSNxUIq1fzjGih8ElJtbM1Uhh2dVE9uxW7EC/oCuuk="
|
||||
on:
|
||||
tags: true
|
||||
all_branches: true
|
||||
repo: parse-community/parse-server
|
||||
82
2.3.0.md
Normal file
82
2.3.0.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Upgrading Parse Server to version 2.3.0
|
||||
|
||||
Parse Server version 2.3.0 begins using unique indexes to ensure the User's username and email are unique. This is not a backwards incompatible change, but it may in some cases cause a significant performance regression until the index finishes building. Building the unique index before upgrading your Parse Server version will eliminate the performance impact, and is a recommended step before upgrading any app to Parse Server 2.3.0. New apps starting with version 2.3.0 do not need to take any steps before beginning their project.
|
||||
|
||||
If you are using MongoDB in Cluster or Replica Set mode, we recommend reading Mongo's [documentation on index building](https://docs.mongodb.com/v3.0/tutorial/build-indexes-on-replica-sets/) first. If you are not using these features, you can execute the following commands from the Mongo shell to build the unique index. You may also want to create a backup first.
|
||||
|
||||
```js
|
||||
// Select the database that your Parse App uses
|
||||
use parse;
|
||||
|
||||
// Select the collection your Parse App uses for users. For migrated apps, this probably includes a collectionPrefix.
|
||||
var coll = db['your_prefix:_User'];
|
||||
|
||||
// You can check if the indexes already exists by running coll.getIndexes()
|
||||
coll.getIndexes();
|
||||
|
||||
// The indexes you want should look like this. If they already exist, you can skip creating them.
|
||||
{
|
||||
"v" : 1,
|
||||
"unique" : true,
|
||||
"key" : {
|
||||
"username" : 1
|
||||
},
|
||||
"name" : "username_1",
|
||||
"ns" : "parse.your_prefix:_User",
|
||||
"background" : true,
|
||||
"sparse" : true
|
||||
}
|
||||
|
||||
{
|
||||
"v" : 1,
|
||||
"unique" : true,
|
||||
"key" : {
|
||||
"email" : 1
|
||||
},
|
||||
"name" : "email_1",
|
||||
"ns" : "parse.your_prefix:_User",
|
||||
"background" : true,
|
||||
"sparse" : true
|
||||
}
|
||||
|
||||
// Create the username index.
|
||||
// "background: true" is mandatory and avoids downtime while the index builds.
|
||||
// "sparse: true" is also mandatory because Parse Server uses sparse indexes.
|
||||
coll.ensureIndex({ username: 1 }, { background: true, unique: true, sparse: true });
|
||||
|
||||
// Create the email index.
|
||||
// "background: true" is still mandatory.
|
||||
// "sparse: true" is also mandatory both because Parse Server uses sparse indexes, and because email addresses are not required by the Parse API.
|
||||
coll.ensureIndex({ email: 1 }, { background: true, unique: true, sparse: true });
|
||||
```
|
||||
|
||||
There are some issues you may run into during this process:
|
||||
|
||||
## Mongo complains that the index already exists, but with different options
|
||||
|
||||
In this case, you will need to remove the incorrect index. If your app relies on the existence of the index in order to be performant, you can create a new index, with "-1" for the direction of the field, so that it counts as different options. Then, drop the conflicting index, and create the unique index.
|
||||
|
||||
## There is already non-unique data in the username or email field
|
||||
|
||||
This is possible if you have explicitly set some user's emails to null. If this is bogus data, and those null fields should be unset, you can unset the null emails with this command. If your app relies on the difference between null and unset emails, you will need to upgrade your app to treat null and unset emails the same before building the index and upgrading to Parse Server 2.3.0.
|
||||
|
||||
```js
|
||||
coll.update({ email: { $exists: true, $eq: null } }, { $unset: { email: '' } }, { multi: true })
|
||||
```
|
||||
|
||||
## There is already non-unique data in the username or email field, and it's not nulls
|
||||
|
||||
This is possible due to a race condition in previous versions of Parse Server. If you have this problem, it is unlikely that you have a lot of rows with duplicate data. We recommend you clean up the data manually, by removing or modifying the offending rows.
|
||||
|
||||
This command, can be used to find the duplicate data:
|
||||
|
||||
```js
|
||||
coll.aggregate([
|
||||
{$match: {"username": {"$ne": null}}},
|
||||
{$group: {_id: "$username", uniqueIds: {$addToSet: "$_id"}, count: {$sum: 1}}},
|
||||
{$match: {count: {"$gt": 1}}},
|
||||
{$project: {id: "$uniqueIds", username: "$_id", _id : 0} },
|
||||
{$unwind: "$id" },
|
||||
{$out: '_duplicates'} // Save the list of duplicates to a new, "_duplicates" collection. Remove this line to just output the list.
|
||||
], {allowDiskUse:true})
|
||||
```
|
||||
78
6.0.0.md
78
6.0.0.md
@@ -1,78 +0,0 @@
|
||||
# Parse Server 6 Migration Guide <!-- omit in toc -->
|
||||
|
||||
This document only highlights specific changes that require a longer explanation. For a full list of changes in Parse Server 6 please refer to the [changelog](https://github.com/parse-community/parse-server/blob/alpha/CHANGELOG.md).
|
||||
|
||||
---
|
||||
|
||||
- [Incompatible git protocol with Node 14](#incompatible-git-protocol-with-node-14)
|
||||
- [Import Statement](#import-statement)
|
||||
- [Asynchronous Initialization](#asynchronous-initialization)
|
||||
|
||||
---
|
||||
|
||||
## Incompatible git protocol with Node 14
|
||||
|
||||
Parse Server 6 uses the Node Package Manger (npm) package lock file version 2. While version 2 is supposed to be backwards compatible with version 1, you may still encounter errors due to incompatible git protocols that cannot be interpreted correctly by npm bundled with Node 14.
|
||||
|
||||
If you are encountering issues installing Parse Server on Node 14 because of dependency references in the package lock file using the `ssh` protocol, configure git to use the `https` protocol instead:
|
||||
|
||||
```
|
||||
sudo git config --system url."https://github".insteadOf "ssh://git@github"
|
||||
```
|
||||
|
||||
Alternatively you could manually replace the dependency URLs in the package lock file.
|
||||
|
||||
⚠️ You could also delete the package lock file and recreate it with Node 14. Keep in mind that doing so you are not using an official version of Parse Server anymore. You may be using dependencies that have not been tested as part of the Parse Server release process.
|
||||
|
||||
## Import Statement
|
||||
|
||||
The import and initialization syntax has been simplified with more intuitive naming and structure.
|
||||
|
||||
*Parse Server 5:*
|
||||
```js
|
||||
// Returns a Parse Server instance
|
||||
const ParseServer = require('parse-server');
|
||||
|
||||
// Returns a Parse Server express middleware
|
||||
const { ParseServer } = require('parse-server');
|
||||
```
|
||||
|
||||
*Parse Server 6:*
|
||||
```js
|
||||
// Both return a Parse Server instance
|
||||
const ParseServer = require('parse-server');
|
||||
const { ParseServer } = require('parse-server');
|
||||
```
|
||||
|
||||
To get the express middleware in Parse Server 6, configure the Parse Server instance, start Parse Server and use its `app` property. See [Asynchronous Initialization](#asynchronous-initialization) for more details.
|
||||
|
||||
## Asynchronous Initialization
|
||||
|
||||
Previously, it was possible to mount Parse Server before it was fully started up and ready to receive requests. This could result in undefined behavior, such as Parse Objects could be saved before Cloud Code was registered. To prevent this, Parse Server 6 requires to be started asynchronously before being mounted.
|
||||
|
||||
*Parse Server 5:*
|
||||
```js
|
||||
// 1. Import Parse Server
|
||||
const { ParseServer } = require('parse-server');
|
||||
|
||||
// 2. Create a Parse Server instance as express middleware
|
||||
const server = new ParseServer(config);
|
||||
|
||||
// 3. Mount express middleware
|
||||
app.use("/parse", server);
|
||||
```
|
||||
|
||||
*Parse Server 6:*
|
||||
```js
|
||||
// 1. Import Parse Server
|
||||
const ParseServer = require('parse-server');
|
||||
|
||||
// 2. Create a Parse Server instance
|
||||
const server = new ParseServer(config);
|
||||
|
||||
// 3. Start up Parse Server asynchronously
|
||||
await server.start();
|
||||
|
||||
// 4. Mount express middleware
|
||||
app.use("/parse", server.app);
|
||||
```
|
||||
44
8.0.0.md
44
8.0.0.md
@@ -1,44 +0,0 @@
|
||||
# Parse Server 8 Migration Guide <!-- omit in toc -->
|
||||
|
||||
This document only highlights specific changes that require a longer explanation. For a full list of changes in Parse Server 8 please refer to the [changelog](https://github.com/parse-community/parse-server/blob/alpha/CHANGELOG.md).
|
||||
|
||||
---
|
||||
|
||||
- [Email Verification](#email-verification)
|
||||
- [Database Indexes](#database-indexes)
|
||||
|
||||
---
|
||||
|
||||
## Email Verification
|
||||
|
||||
In order to remove sensitive information (PII) from technical logs, the `Parse.User.username` field has been removed from the email verification process. This means the username will no longer be used and the already existing verification token, that is internal to Parse Server and associated with the user, will be used instead. This makes use of the fact that an expired verification token is not deleted from the database by Parse Server, despite being expired, and can therefore be used to identify a user.
|
||||
|
||||
This change affects how verification emails with expired tokens are handled. When opening a verification link that contains an expired token, the page that the user is redirected to will no longer provide the `username` as a URL query parameter. Instead, the URL query parameter `token` will be provided.
|
||||
|
||||
The request to re-send a verification email changed to sending a `POST` request to the endpoint `/resend_verification_email` with `token` in the body, instead of `username`. If you have customized the HTML pages for email verification either for the `PagesRouter` in `/public/` or the deprecated `PublicAPIRouter` in `/public_html/`, you need to adapt the form request in your custom pages. See the example pages in these aforementioned directories for how the forms must be set up.
|
||||
|
||||
> [!WARNING]
|
||||
> An expired verification token is not automatically deleted from the database by Parse Server even though it has expired. If you have implemented a custom clean-up logic that removes expired tokens, this will break the form request to re-send a verification email as the expired token won't be found and cannot be associated with any user. In that case you'll have to implement your custom process to re-send a verification email.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Parse Server does not keep a history of verification tokens but only stores the most recently generated verification token in the database. Every time Parse Server generates a new verification token, the currently stored token is replaced. If a user opens a link with an expired token, and that token has already been replaced in the database, Parse Server cannot associate the expired token with any user. In this case, another way has to be offered to the user to re-send a verification email. To mitigate this issue, set the Parse Server option `emailVerifyTokenReuseIfValid: true` and set `emailVerifyTokenValidityDuration` to a longer duration, which ensures that the currently stored verification token is not replaced too soon.
|
||||
|
||||
Related pull request:
|
||||
|
||||
- https://github.com/parse-community/parse-server/pull/8488
|
||||
|
||||
## Database Indexes
|
||||
|
||||
As part of the email verification and password reset improvements in Parse Server 8, the queries used for these operations have changed to use tokens instead of username/email fields. To ensure optimal query performance, Parse Server now automatically creates indexes on the following fields during server initialization:
|
||||
|
||||
- `_User._email_verify_token`: used for email verification queries
|
||||
- `_User._perishable_token`: used for password reset queries
|
||||
|
||||
These indexes are created automatically when Parse Server starts, similar to how indexes for `username` and `email` fields are created. No manual intervention is required.
|
||||
|
||||
> [!WARNING]
|
||||
> If you have a large existing user base, the index creation may take some time during the first server startup after upgrading to Parse Server 8. The server logs will indicate when index creation is complete or if any errors occur. If you have any concerns regarding a potential database performance impact during index creation, you could create these indexes manually in a controlled procedure before upgrading Parse Server.
|
||||
|
||||
Related pull request:
|
||||
|
||||
- https://github.com/parse-community/parse-server/pull/9893
|
||||
56
9.0.0.md
56
9.0.0.md
@@ -1,56 +0,0 @@
|
||||
# Parse Server 9 Migration Guide <!-- omit in toc -->
|
||||
|
||||
This document only highlights specific changes that require a longer explanation. For a full list of changes in Parse Server 9 please refer to the [changelog](https://github.com/parse-community/parse-server/blob/alpha/CHANGELOG.md).
|
||||
|
||||
---
|
||||
- [Route Path Syntax and Rate Limiting](#route-path-syntax-and-rate-limiting)
|
||||
---
|
||||
|
||||
## Route Path Syntax and Rate Limiting
|
||||
Parse Server 9 standardizes the route pattern syntax across cloud routes and rate-limiting to use the new **path-to-regexp v8** style. This update introduces validation and a clear deprecation error for the old wildcard route syntax.
|
||||
|
||||
### Key Changes
|
||||
- **Standardization**: All route paths now use the path-to-regexp v8 syntax, which provides better consistency and security.
|
||||
- **Validation**: Added validation to ensure route paths conform to the new syntax.
|
||||
- **Deprecation**: Old wildcard route syntax is deprecated and will trigger a clear error message.
|
||||
|
||||
### Migration Steps
|
||||
|
||||
#### Path Syntax Examples
|
||||
|
||||
Update your rate limit configurations to use the new path-to-regexp v8 syntax:
|
||||
|
||||
| Old Syntax (deprecated) | New Syntax (v8) |
|
||||
|------------------------|-----------------|
|
||||
| `/functions/*` | `/functions/*path` |
|
||||
| `/classes/*` | `/classes/*path` |
|
||||
| `/*` | `/*path` |
|
||||
| `*` | `*path` |
|
||||
|
||||
**Before:**
|
||||
```javascript
|
||||
rateLimit: {
|
||||
requestPath: '/functions/*',
|
||||
requestTimeWindow: 10000,
|
||||
requestCount: 100
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```javascript
|
||||
rateLimit: {
|
||||
requestPath: '/functions/*path',
|
||||
requestTimeWindow: 10000,
|
||||
requestCount: 100
|
||||
}
|
||||
```
|
||||
|
||||
- Review your custom cloud routes and ensure they use the new path-to-regexp v8 syntax.
|
||||
- Update any rate-limiting configurations to use the new route path format.
|
||||
- Test your application to ensure all routes work as expected with the new syntax.
|
||||
|
||||
> [!Note]
|
||||
> Consult the [path-to-regexp v8 docs](https://github.com/pillarjs/path-to-regexp) and the [Express 5 migration guide](https://expressjs.com/en/guide/migrating-5.html#path-syntax) for more details on the new path syntax.
|
||||
|
||||
### Related Pull Request
|
||||
- [#9942](https://github.com/parse-community/parse-server/pull/9942)
|
||||
1261
CHANGELOG.md
1261
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at codeofconduct@parseplatform.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at florent@flovilmart.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
|
||||
667
CONTRIBUTING.md
667
CONTRIBUTING.md
@@ -1,192 +1,17 @@
|
||||
# Contributing to Parse Server <!-- omit in toc -->
|
||||
# Contributing to Parse Server
|
||||
|
||||
## Table of Contents <!-- omit in toc -->
|
||||
- [Contributing](#contributing)
|
||||
- [Issue vs. Pull Request](#issue-vs-pull-request)
|
||||
- [Scope](#scope)
|
||||
- [Templates](#templates)
|
||||
- [Why Contributing?](#why-contributing)
|
||||
- [Contribution FAQs](#contribution-faqs)
|
||||
- [Reviewer Role](#reviewer-role)
|
||||
- [Review Feedback](#review-feedback)
|
||||
- [Merge Readiness](#merge-readiness)
|
||||
- [Review Validity](#review-validity)
|
||||
- [Code Ownership](#code-ownership)
|
||||
- [Access Permissions](#access-permissions)
|
||||
- [New Private Repository](#new-private-repository)
|
||||
- [New Public Repository](#new-public-repository)
|
||||
- [Environment Setup](#environment-setup)
|
||||
- [Recommended Tools](#recommended-tools)
|
||||
- [Setting up your local machine](#setting-up-your-local-machine)
|
||||
- [Good to Know](#good-to-know)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Please Do's](#please-dos)
|
||||
- [TypeScript Tests](#typescript-tests)
|
||||
- [Test against Postgres](#test-against-postgres)
|
||||
- [Postgres with Docker](#postgres-with-docker)
|
||||
- [Performance Testing](#performance-testing)
|
||||
- [Adding Tests](#adding-tests)
|
||||
- [Adding Benchmarks](#adding-benchmarks)
|
||||
- [Benchmark Guidelines](#benchmark-guidelines)
|
||||
- [Breaking Changes](#breaking-changes)
|
||||
- [Deprecation Policy](#deprecation-policy)
|
||||
- [Feature Considerations](#feature-considerations)
|
||||
- [Security Checks](#security-checks)
|
||||
- [Add Security Check](#add-security-check)
|
||||
- [Wording Guideline](#wording-guideline)
|
||||
- [Parse Error](#parse-error)
|
||||
- [Parse Server Configuration](#parse-server-configuration)
|
||||
- [Pull Request](#pull-request)
|
||||
- [Commit Message](#commit-message)
|
||||
- [Breaking Change](#breaking-change)
|
||||
- [Merging](#merging)
|
||||
- [Breaking Change](#breaking-change-1)
|
||||
- [Reverting](#reverting)
|
||||
- [Security Vulnerability](#security-vulnerability)
|
||||
- [Local Testing](#local-testing)
|
||||
- [Environment](#environment)
|
||||
- [Merging](#merging-1)
|
||||
- [Releasing](#releasing)
|
||||
- [General Considerations](#general-considerations)
|
||||
- [Major Release / Long-Term-Support](#major-release--long-term-support)
|
||||
- [Preparing Release](#preparing-release)
|
||||
- [Publishing Release (forward-merge):](#publishing-release-forward-merge)
|
||||
- [Publishing Hotfix (back-merge):](#publishing-hotfix-back-merge)
|
||||
- [Publishing Major Release (Yearly Release)](#publishing-major-release-yearly-release)
|
||||
- [Versioning](#versioning)
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
We really want Parse to be yours, to see it grow and thrive in the open source community.
|
||||
|
||||
## Contributing
|
||||
If you are not familiar with Pull Requests and want to know more about them, you can visit the [Creating a pull request](https://help.github.com/articles/creating-a-pull-request/) article. It contains detailed informations about the process.
|
||||
|
||||
Before you start to code, please open a [new issue](https://github.com/parse-community/parse-server/issues/new/choose) to describe your idea, or search for and continue the discussion in an [existing issue](https://github.com/parse-community/parse-server/issues).
|
||||
## Setting up the project for debugging and contributing:
|
||||
|
||||
> ⚠️ Please do not post a security vulnerability on GitHub or in the Parse Community Forum. Instead, follow the [Parse Community Security Policy](https://github.com/parse-community/parse-server/security/policy).
|
||||
### Recommended setup:
|
||||
|
||||
Please completely fill out any templates to provide essential information about your new feature or the bug you discovered.
|
||||
* [vscode](https://code.visualstudio.com), the popular IDE.
|
||||
* [Jasmine Test Explorer](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-test-explorer), a very practical test exploration plugin which let you run, debug and see the test results inline.
|
||||
|
||||
Together we will plan out the best conceptual approach for your contribution, so that your and our time is invested in the best possible approach. The discussion often reveals how to leverage existing features of Parse Server to reach your goal with even less effort and in a more sustainable way.
|
||||
|
||||
When you are ready to code, you can find more information about opening a pull request in the [GitHub docs](https://help.github.com/articles/creating-a-pull-request/).
|
||||
|
||||
Whether this is your first contribution or you are already an experienced contributor, the Parse Community has your back – don't hesitate to ask for help!
|
||||
|
||||
### Issue vs. Pull Request
|
||||
|
||||
An issue is required to be linked in every pull request. We understand that no-one likes to create an issue for something that appears to be a simple pull request, but here is why this is beneficial for everyone:
|
||||
|
||||
- An issue get more visibility than a pull request as issues can be pinned, receive bounties and it is primarily the issue list that people browse through rather than the more technical pull request list. Visibility is a key aspect so others can weigh in on issues and contribute their opinion.
|
||||
- The discussion in the issue is different from the discussion in the pull request. The issue discussion is focused on the issue and how to address it, whereas the discussion in the pull request is focused on a specific implemention. An issue may even have multiple pull requests because either the issue requires multiple implementations or multiple pull requests are opened to compare and test different approaches to later decide for one.
|
||||
- High-level conceptual discussions about the issue should be still available, even if a pull request is closed because its appraoch was discarded. If these discussions are in the pull request instead, they can easily become fragmented over multiple pull requests and issues, which can make it very hard to make sense of all aspects of an issue.
|
||||
|
||||
### Scope
|
||||
|
||||
An issue and pull request must limit its scope on a distinct issue. Pull requests can only contain changes that are required to address the scoped issue. While it may seem quick and easy to add unrelated changes to the pull request, it can cause singificant complications after merging. Some of the reasons are:
|
||||
|
||||
- A pull request corresponds to a single changelog entry. A changelog entry should not describe multiple unrelated changes in one entry for better readability.
|
||||
- A pull request creates a distinct commit; having an individual commit for each limited scope makes it easier for others to go back in the commit history and debug. Bugs are generally more difficult to identify and fix if there are various unrelated changes merged at once.
|
||||
- If a pull request needs to be reverted, unrelated changes will be reverted as well. That makes it more complex and time consuming to revert, having to consider its effects and possibly publishing a broken release or requiring a follow-up pull request with code manipulation.
|
||||
|
||||
### Templates
|
||||
|
||||
You are required to use and completely fill out the templates for new issues and pull requests. We understand that no-one enjoys filling out forms, but here is why this is beneficial for everyone:
|
||||
|
||||
- It may take you 30 seconds longer, but will save even more time for everyone else trying to understand your issue.
|
||||
- It helps to fix issues and merge pull requests faster as reviewers spend less time trying to understand your issue.
|
||||
- It makes investigations easier when others try to understand your issue and code changes made even years later.
|
||||
|
||||
## Why Contributing?
|
||||
|
||||
Buy cheap, buy twice. What? No, this is not the Economics 101 class, but the same is true for contributing.
|
||||
|
||||
There are two ways of writing a feature or fixing a bug. Sometimes the quick solution is to just write a Cloud Code function that does what you want. Contributing by making the change directly in Parse Server may take a bit longer, but it actually saves you much more time in the long run.
|
||||
|
||||
Consider the benefits you get:
|
||||
|
||||
- #### 🚀 Higher efficiency
|
||||
Your code is examined for efficiency and interoperability with existing features by the community.
|
||||
- #### 🛡 Stronger security
|
||||
Your code is scrutinized for bugs and vulnerabilities and automated checks help to identify security issues that may arise in the future.
|
||||
- #### 🧬 Continuous improvement
|
||||
If your feature is used by others it is likely to be continuously improved and extended by the community.
|
||||
- #### 💝 Giving back
|
||||
You give back to the community that contributed to make the Parse Platform become what it is today and for future developers to come.
|
||||
- #### 🧑🎓 Improving yourself
|
||||
You learn to better understand the inner workings of Parse Server, which will help you to write more efficient and resilient code for your own application.
|
||||
|
||||
Most importantly, with every contribution you improve your skills so that future contributions take even less time and you get all the benefits above for free — easy choice, right?
|
||||
|
||||
## Contribution FAQs
|
||||
|
||||
### Reviewer Role
|
||||
|
||||
> *Instead of writing review comments back-and-forth, why doesn't the reviewer just write the code themselves?*
|
||||
|
||||
A reviewer is already helping you to make a code contribution through their review. A reviewer *may* even help you to write code by actually writing it for you, but is not obliged to do so.
|
||||
|
||||
GitHub allows reviewers to suggest and write code changes as part of the review feedback. These code suggestions are likely to contain mistakes due to the lack of code syntax checks when writing code directly on GitHub. You should therefore always review these suggestions before accepting them, ideally in an IDE. If you merge a code suggestion and the CI then fails, take another look at the code change before asking the reviewer for help.
|
||||
|
||||
### Review Feedback
|
||||
|
||||
> *It takes too much effort to incorporate the review feedback, why why can't you just merge my pull request?*
|
||||
|
||||
If you are a new contributor, it's naturally a learning experience for you and therefore takes longer. We welcome contributors of any experience levels and gladly support you in getting familiar with the code base and our quality standards and contribution requirements. In return we expect you to be open to and appreciative of the reviewers' feedback.
|
||||
|
||||
In a large pull request, it can be a significant effort to bring it over the finish line. Luckily this is a collaborative environment and others are free to jump in to contribute to the pull request to share the effort. You can either give others access to your fork or they can open their own pull request based on your previous work.
|
||||
|
||||
If you are out of resources stay calm, explain your personal constraints (expertise or time) and ask for help. Wasting time by complaining about the amount of review comments will neither use your own time in a meaningful way, nor the time of others who read your complaint.
|
||||
|
||||
This is a collaborative enviroment in which everyone works on a common goal - to get a pull request ready for merging. Reviewers are working *with* you to get your pull request ready, *not against you*.
|
||||
|
||||
**❗️ Always be mindful that the reviewers' efforts are an integral part of code contribution. Their review is as important as your written code and their review time is a valuable as your coding time.**
|
||||
|
||||
### Merge Readiness
|
||||
|
||||
> *The feature already works, why do you request more changes instead of just merging my pull request?*
|
||||
|
||||
A feature may work for your own use case or in your own environment, but that doesn't necessarily mean that it's ready for merging. Aside from code quality and code style requirements, reviewers also review based on strategic and architectural considerations. It's often easy to just get a feature to work, but it needs to be also maintained in the future, robust therefore well tested and validated, intuitive for other developers to use, well documented, and not cause a forseeable breaking change in the near future.
|
||||
|
||||
### Review Validity
|
||||
|
||||
> *The reviewer has never worked on the issue and was never part of any previous discussion, why would I care about their opinion?*
|
||||
|
||||
It's contrary to an open, collaborative environment to expect others to be involved in an issue or discussion since its beginning. Such a mindset would close out any new views, which are important for a differentiated discussion.
|
||||
|
||||
> *The reviewer doesn't have any expertise in that matter, why would I care about their opinion?*
|
||||
|
||||
Your arguments must focus on the issue, not on your assumption of someone else's personal experience. We will take immediate and appropriate action in case of personal attacks, regardless of your previous contributions. Personal attacks are not permissible. If you became a victim of personal attacks, you can privately [report](https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam) the GitHub comment to the Parse Platform PMC.
|
||||
|
||||
### Code Ownership
|
||||
|
||||
> *Can I open a new pull request based on another author's pull request?*
|
||||
|
||||
If your pull request contains work from someone else then you are required to get their permission to use their work in your pull request. Please make sure to observe the [license](LICENSE) for more details. In addition, as an appreciative gesture you should clearly mention that your pull request is based on another pull request with a link in the top-most comment of your pull request. To avoid this issue we encourage contributors to collaborate on a single pull request to preserve the commit history and clearly identify each author's contribution. To do so, you can review the other author's pull request and submit your code suggestions, or ask the original author to grant you write access to their repository to also be able to make commits directly to their pull request.
|
||||
|
||||
### Access Permissions
|
||||
|
||||
> *Can I get write access to the repository to make changes faster?*
|
||||
|
||||
Keeping our products safe and secure is one of your top priorities. Our security policy mandates that write access to repositories is only provided to as few people as necessary. All usual contributions can be made via public pull requests. If you think you need write access, contact the repository team and explain in detail what the constraint is that you are trying to overcome. We want to make contributing for you as easy as possible. If there are any bottlenecks that are slowing you down we are happy to receive your feedback to see where we can improve.
|
||||
|
||||
### New Private Repository
|
||||
|
||||
> *Can I get a new private repository within the Parse Platform organization to work on some stuff?*
|
||||
|
||||
Private repositories are not provided unless there is a significant constraint or requirement that makes it necessary. For example, when collaborating on fixing a security vulnerability we provide private repositories to allow collaborators to share sensitive information within a select group.
|
||||
|
||||
### New Public Repository
|
||||
|
||||
> *Can I get a new public repository within the Parse Platform organization to work on some stuff?*
|
||||
|
||||
First of all, we appreciate your contribution. In rare cases, where we consider it beneficial to the advancement of the repository, a new public repository for a specific purpose may be provided, for example for increased visibility or to provide the organization's GitHub ressources. In other cases, we encourage you to start your contribution in a personal repository of your own GitHub account, and later transfer it to the Parse Platform organization. We will be happy to assist you in the repository transfer.
|
||||
|
||||
## Environment Setup
|
||||
|
||||
### Recommended Tools
|
||||
|
||||
* [Visual Studio Code](https://code.visualstudio.com), the popular IDE.
|
||||
* [Jasmine Test Explorer](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-jasmine-test-adapter), a very practical test exploration plugin which let you run, debug and see the test results inline.
|
||||
|
||||
### Setting up your local machine
|
||||
### Setting up you local machine:
|
||||
|
||||
* [Fork](https://github.com/parse-community/parse-server) this project and clone the fork on your local machine:
|
||||
|
||||
@@ -198,27 +23,15 @@ $ code . # launch vscode
|
||||
$ npm run watch # run babel watching for local file changes
|
||||
```
|
||||
|
||||
> To launch VS Code from the terminal with the `code` command you first need to follow the [launching from the command line section](https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line) in the VS Code setup documentation.
|
||||
|
||||
Once you have babel running in watch mode, you can start making changes to parse-server.
|
||||
|
||||
### Good to Know
|
||||
### Good to know:
|
||||
|
||||
* The `lib/` folder is not committed, so never make changes in there.
|
||||
* The lib/ folder is not commited, so never make changes in there.
|
||||
* Always make changes to files in the `src/` folder.
|
||||
* All the tests should point to sources in the `lib/` folder.
|
||||
* The `lib/` folder is produced by `babel` using either the `npm run build`, `npm run watch`, or the `npm run prepare` step.
|
||||
* The `npm run prepare` step is automatically invoked when your package depends on forked parse-server installed via git for example using `npm install --save git+https://github.com/[username]/parse-server#[branch/commit]`.
|
||||
* The tests are run against a single server instance. You can change the server configurations using `await reconfigureServer({ ... some configuration })` found in `spec/helper.js`.
|
||||
* The tests are ran at random.
|
||||
* Caches and Configurations are reset after every test.
|
||||
* Users are logged out after every test.
|
||||
* Cloud Code hooks are removed after every test.
|
||||
* Database is deleted after every test (indexes are not removed for speed)
|
||||
* Tests are located in the `spec` folder
|
||||
* For better test reporting enable `PARSE_SERVER_LOG_LEVEL=debug`
|
||||
|
||||
### Troubleshooting
|
||||
### Troubleshooting:
|
||||
|
||||
*Question*: I modify the code in the src folder but it doesn't seem to have any effect.<br/>
|
||||
*Answer*: Check that `npm run watch` is running
|
||||
@@ -227,469 +40,33 @@ Once you have babel running in watch mode, you can start making changes to parse
|
||||
*Answer*: The easiest way is to install [Jasmine Test Explorer](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-test-explorer), it will let you run selectively tests and debug them.
|
||||
|
||||
*Question*: How do I deploy my forked version on my servers?<br/>
|
||||
*Answer*: In your `package.json`, update the `parse-server` dependency to `https://github.com/[username]/parse-server#[branch/commit]`. Run `npm install`, commit the changes and deploy to your servers.
|
||||
|
||||
*Question*: How do I deploy my forked version using docker?<br/>
|
||||
*Answer*: In your `package.json`, update the `parse-server` dependency to `https://github.com/[username]/parse-server#[branch/commit]`. Make sure the `npm install` step in your `Dockerfile` is running under non-privileged user for the ``npm run prepare`` step to work correctly. For official node images from hub.docker.com that non-privileged user is `node` with `/home/node` working directory.
|
||||
*Answer*: In your `package.json`, update the `parse-server` dependency to `https://github.com/MY_USERNAME/parse-server#MY_FEATURE`. Run `npm install`, commit the changes and deploy to your servers.
|
||||
|
||||
|
||||
### Please Do's
|
||||
|
||||
* Begin by reading the [Development Guide](http://docs.parseplatform.org/parse-server/guide/#development-guide) to learn how to get started running the parse-server.
|
||||
* Take testing seriously! Aim to increase the test coverage with every pull request. To obtain the test coverage of the project, run: `npm run coverage`
|
||||
* Run the tests for the file you are working on with the following command: `npm test spec/MyFile.spec.js`
|
||||
* Take testing seriously! Aim to increase the test coverage with every pull request. To obtain the test coverage of the project, run:
|
||||
* **Windows**: `npm run coverage:win`
|
||||
* **Unix**: `npm run coverage`
|
||||
* Run the tests for the file you are working on with the following command:
|
||||
* **Windows**: `npm run test:win spec/MyFile.spec.js`
|
||||
* **Unix**: `npm test spec/MyFile.spec.js`
|
||||
* Run the tests for the whole project to make sure the code passes all tests. This can be done by running the test command for a single file but removing the test file argument. The results can be seen at *<PROJECT_ROOT>/coverage/lcov-report/index.html*.
|
||||
* Lint your code by running `npm run lint` to make sure the code is not going to be rejected by the CI.
|
||||
* **Do not** publish the *lib* folder.
|
||||
* Mocks belong in the `spec/support` folder.
|
||||
* Please consider if any changes to the [docs](http://docs.parseplatform.org) are needed or add additional sections in the case of an enhancement or feature.
|
||||
|
||||
#### TypeScript Tests
|
||||
|
||||
Type tests are located in [/types/tests.ts](/types/tests.ts) and are responsible for ensuring that the type generation for each class is behaving as expected. Types are generated by manually running the script `npm run build:types`. The generated types are `.d.ts` files located in [/types](/types) and must not be manually changed after generation.
|
||||
|
||||
> [!CAUTION]
|
||||
> An exemption are type changes to `src/Options/index.js` which must be manually updated in `types/Options/index.d.ts`, as these types are not generated via a script.
|
||||
|
||||
When developing type definitions you can run `npm run watch:ts` in order to rebuild your changes automatically upon each save. Use `npm run test:types` in order to run types tests against generated `.d.ts` files.
|
||||
|
||||
### Test against Postgres
|
||||
### Run your tests against Postgres (optional)
|
||||
|
||||
If your pull request introduces a change that may affect the storage or retrieval of objects, you may want to make sure it plays nice with Postgres.
|
||||
|
||||
* You'll need to have postgres running on your machine and setup [appropriately](https://github.com/parse-community/parse-server/blob/master/scripts/before_script_postgres.sh) or use [`Docker`](#postgres-with-docker)
|
||||
* Run the tests against the postgres database with:
|
||||
```
|
||||
PARSE_SERVER_TEST_DB=postgres PARSE_SERVER_TEST_DATABASE_URI=postgres://postgres:password@localhost:5432/parse_server_postgres_adapter_test_database npm run testonly
|
||||
```
|
||||
* The Postgres adapter has a special debugger that traces all the sql commands. You can enable it with setting the environment variable `PARSE_SERVER_LOG_LEVEL=debug`
|
||||
* Run the tests against the postgres database with `PARSE_SERVER_TEST_DB=postgres npm test`. You'll need to have postgres running on your machine and setup [appropriately](https://github.com/parse-community/parse-server/blob/master/.travis.yml#L37)
|
||||
* If your feature is intended to only work with MongoDB, you should disable PostgreSQL-specific tests with:
|
||||
|
||||
|
||||
- `describe_only_db('mongo')` // will create a `describe` that runs only on mongoDB
|
||||
- `it_only_db('mongo')` // will make a test that only runs on mongo
|
||||
- `it_exclude_dbs(['postgres'])` // will make a test that runs against all DB's but postgres
|
||||
* Similarly, if your feature is intended to only work with PostgreSQL, you should disable MongoDB-specific tests with:
|
||||
|
||||
- `describe_only_db('postgres')` // will create a `describe` that runs only on postgres
|
||||
- `it_only_db('postgres')` // will make a test that only runs on postgres
|
||||
- `it_exclude_dbs(['mongo'])` // will make a test that runs against all DB's but mongo
|
||||
|
||||
* If your feature is intended to work with MongoDB and PostgreSQL, you can include or exclude tests more granularly with:
|
||||
|
||||
- `it_only_mongodb_version('>=4.4')` // will test with any version of Postgres but only with version >=4.4 of MongoDB; accepts semver notation to specify a version range
|
||||
- `it_only_postgres_version('>=13')` // will test with any version of Mongo but only with version >=13 of Postgres; accepts semver notation to specify a version range
|
||||
|
||||
#### Postgres with Docker
|
||||
|
||||
[PostGIS images (select one with v2.2 or higher) on docker hub](https://hub.docker.com/r/postgis/postgis) is based off of the official [postgres](https://hub.docker.com/_/postgres) image and will work out-of-the-box (as long as you create a user with the necessary extensions for each of your Parse databases; see below). To launch the compatible Postgres instance, copy and paste the following line into your shell:
|
||||
|
||||
```
|
||||
docker run -d --name parse-postgres -p 5432:5432 -e POSTGRES_PASSWORD=password --rm postgis/postgis:17-3.5-alpine && sleep 20 && docker exec -it parse-postgres psql -U postgres -c 'CREATE DATABASE parse_server_postgres_adapter_test_database;' && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION pgcrypto; CREATE EXTENSION postgis;' -d parse_server_postgres_adapter_test_database && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION postgis_topology;' -d parse_server_postgres_adapter_test_database
|
||||
```
|
||||
To stop the Postgres instance:
|
||||
|
||||
```
|
||||
docker stop parse-postgres
|
||||
```
|
||||
|
||||
You can also use the [postgis/postgis:17-3.5-alpine](https://hub.docker.com/r/postgis/postgis) image in a Dockerfile and copy this [script](https://github.com/parse-community/parse-server/blob/master/scripts/before_script_postgres.sh) to the image by adding the following lines:
|
||||
|
||||
```
|
||||
#Install additional scripts. These are run in abc order during initial start
|
||||
COPY ./scripts/setup-dbs.sh /docker-entrypoint-initdb.d/setup-dbs.sh
|
||||
RUN chmod +x /docker-entrypoint-initdb.d/setup-dbs.sh
|
||||
```
|
||||
|
||||
Note that the script above will ONLY be executed during initialization of the container with no data in the database, see the official [Postgres image](https://hub.docker.com/_/postgres) for details. If you want to use the script to run again be sure there is no data in the /var/lib/postgresql/data of the container.
|
||||
|
||||
### Performance Testing
|
||||
|
||||
Parse Server includes an automated performance benchmarking system that runs on every pull request to detect performance regressions and track improvements over time.
|
||||
|
||||
#### Adding Tests
|
||||
|
||||
You should consider adding performance benchmarks if your contribution:
|
||||
|
||||
- **Introduces a performance-critical feature**: Features that will be frequently used in production environments, such as new query operations, authentication methods, or data processing functions.
|
||||
- **Modifies existing critical paths**: Changes to core functionality like object CRUD operations, query execution, user authentication, file operations, or Cloud Code execution.
|
||||
- **Has potential performance impact**: Any change that affects database operations, network requests, data parsing, caching mechanisms, or algorithmic complexity.
|
||||
- **Optimizes performance**: If your PR specifically aims to improve performance, adding benchmarks helps verify the improvement and prevents future regressions.
|
||||
|
||||
#### Adding Benchmarks
|
||||
|
||||
Performance benchmarks are located in [`benchmark/performance.js`](benchmark/performance.js). To add a new benchmark:
|
||||
|
||||
1. **Identify the operation to benchmark**: Determine the specific operation you want to measure (e.g., a new query type, a new API endpoint).
|
||||
|
||||
2. **Create a benchmark function**: Follow the existing patterns in `benchmark/performance.js`:
|
||||
```javascript
|
||||
async function benchmarkNewFeature() {
|
||||
return measureOperation('Feature Name', async () => {
|
||||
// Your operation to benchmark
|
||||
const result = await someOperation();
|
||||
}, ITERATIONS);
|
||||
}
|
||||
```
|
||||
|
||||
3. **Add to benchmark suite**: Register your benchmark in the `runBenchmarks()` function:
|
||||
```javascript
|
||||
console.error('Running New Feature benchmark...');
|
||||
await cleanupDatabase();
|
||||
results.push(await benchmarkNewFeature());
|
||||
```
|
||||
|
||||
4. **Test locally**: Run the benchmarks locally to verify they work:
|
||||
```bash
|
||||
npm run benchmark:quick # Quick test with 10 iterations
|
||||
npm run benchmark # Full test with 10,000 iterations
|
||||
```
|
||||
|
||||
For new features where no baseline exists, the CI will establish new benchmarks that future PRs will be compared against.
|
||||
|
||||
#### Benchmark Guidelines
|
||||
|
||||
- **Keep benchmarks focused**: Each benchmark should test a single, well-defined operation.
|
||||
- **Use realistic data**: Test with data that reflects real-world usage patterns.
|
||||
- **Clean up between runs**: Use `cleanupDatabase()` to ensure consistent test conditions.
|
||||
- **Consider iteration count**: Use fewer iterations for expensive operations (see `ITERATIONS` environment variable).
|
||||
- **Document what you're testing**: Add clear comments explaining what the benchmark measures and why it's important.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
Breaking changes should be avoided whenever possible. For a breaking change to be accepted, the benefits of the change have to clearly outweigh the costs of developers having to adapt their deployments. If a breaking change is only cosmetic it will likely be rejected and preferred to become obsolete organically during the course of further development, unless it is required as part of a larger change. Breaking changes should follow the [Deprecation Policy](#deprecation-policy).
|
||||
|
||||
Please consider that Parse Server is just one component in a stack that requires attention. A breaking change requires resources and effort to adapt an environment. An unnecessarily high frequency of breaking changes can have detrimental side effects such as:
|
||||
- "upgrade fatigue" where developers run old versions of Parse Server because they cannot always attend to every update that contains a breaking change
|
||||
- less secure Parse Server deployments that run on old versions which is contrary to the security evangelism Parse Server intends to facilitate for developers
|
||||
- less feedback and slower identification of bugs and an overall slow-down of Parse Server development because new versions with breaking changes also include new features we want to get feedback on
|
||||
|
||||
### Deprecation Policy
|
||||
|
||||
If you change or remove an existing feature that would lead to a breaking change, use the following deprecation pattern:
|
||||
- Make the new feature or change optional, if necessary with a new Parse Server option parameter.
|
||||
- Use a default value that falls back to existing behavior.
|
||||
- Add a deprecation definition in `Deprecator/Deprecations.js` that will output a deprecation warning log message on Parse Server launch, for example:
|
||||
> DeprecationWarning: The Parse Server option 'example' will be removed in a future release.
|
||||
|
||||
For deprecations that can only be determined ad-hoc during runtime, for example Parse Query syntax deprecations, use the `Deprecator.logRuntimeDeprecation()` method.
|
||||
|
||||
Deprecations become breaking changes after notifying developers through deprecation warnings for at least one entire previous major release. For example:
|
||||
- `4.5.0` is the current version
|
||||
- `4.6.0` adds a new optional feature and a deprecation warning for the existing feature
|
||||
- `5.0.0` marks the beginning of logging the deprecation warning for one entire major release
|
||||
- `6.0.0` makes the breaking change by removing the deprecation warning and making the new feature replace the existing feature
|
||||
|
||||
See the [Deprecation Plan](https://github.com/parse-community/parse-server/blob/master/DEPRECATIONS.md) for an overview of deprecations and planned breaking changes.
|
||||
|
||||
## Feature Considerations
|
||||
### Security Checks
|
||||
|
||||
The Parse Server security checks feature warns developers about weak security settings in their Parse Server deployment.
|
||||
|
||||
A security check needs to be added for every new feature or enhancement that allows the developer to configure it in a way that weakens security mechanisms or exposes functionality which creates a weak spot for malicious attacks. If you are not sure whether your feature or enhancements requires a security check, feel free to ask.
|
||||
|
||||
For example, allowing public read and write to a class may be useful to simplify development but should be disallowed in a production environment.
|
||||
|
||||
Security checks are added in [CheckGroups](https://github.com/parse-community/parse-server/tree/master/src/Security/CheckGroups).
|
||||
|
||||
#### Add Security Check
|
||||
Adding a new security check for your feature is easy and fast:
|
||||
1. Look into [CheckGroups](https://github.com/parse-community/parse-server/tree/master/src/Security/CheckGroups) whether there is an existing `CheckGroup[Category].js` file for the category of check to add. For example, a check regarding the database connection is added to `CheckGroupDatabase.js`.
|
||||
2. If you did not find a file, duplicate an existing file and replace the category name in `setName()` and the checks in `setChecks()`:
|
||||
```js
|
||||
class CheckGroupNewCategory extends CheckGroup {
|
||||
setName() {
|
||||
return 'House';
|
||||
}
|
||||
setChecks() {
|
||||
return [
|
||||
new Check({
|
||||
title: 'Door locked',
|
||||
warning: 'Anyone can enter your house.',
|
||||
solution: 'Lock the door.',
|
||||
check: () => {
|
||||
return; // Example of a passing check
|
||||
}
|
||||
}),
|
||||
new Check({
|
||||
title: 'Camera online',
|
||||
warning: 'Security camera is offline.',
|
||||
solution: 'Check the camera.',
|
||||
check: async () => {
|
||||
throw 1; // Example of a failing check
|
||||
}
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. If you added a new file in the previous step, reference the file in [CheckGroups.js](https://github.com/parse-community/parse-server/blob/master/src/Security/CheckGroups/CheckGroups.js), which is the collector of all security checks:
|
||||
```
|
||||
export { default as CheckGroupNewCategory } from './CheckGroupNewCategory';
|
||||
```
|
||||
4. Add a test that covers the new check to [SecurityCheckGroups.js](https://github.com/parse-community/parse-server/blob/master/spec/SecurityCheckGroups.js) for the cases of success and failure.
|
||||
|
||||
#### Wording Guideline
|
||||
Consider the following when adding a new security check:
|
||||
- *Group.name*: The category name; ends without period as this is a headline.
|
||||
- *Check.title*: Is the positive hypothesis that should be checked, for example "Door locked" instead of "Door unlocked"; ends without period as this is a title.
|
||||
- *Check.warning*: The warning if the test fails; ends with period as this is a description.
|
||||
- *Check.solution*: The recommended solution if the test fails; ends with period as this is an instruction.
|
||||
- The wordings must not contain any sensitive information such as keys, as the security report may be exposed in logs.
|
||||
- The wordings should be concise and not contain verbose explanations, for example "Door locked" instead of "Door has been locked securely".
|
||||
- Do not use pronouns such as "you" or "your" because log files can have various readers with different roles. Do not use pronouns such as "I" or "me" because although we love it dearly, Parse Server is not a human.
|
||||
|
||||
### Parse Error
|
||||
|
||||
Introducing new Parse Errors requires the following steps:
|
||||
|
||||
1. Research whether an existing Parse Error already covers the error scenario. Keep in mind that reusing an already existing Parse Error does not allow to distinguish between scenarios in which the same error is thrown, so it may be necessary to add a new and more specific Parse Error, even though a more general Parse Error already exists.
|
||||
⚠️ Currently (as of Dec. 2020), there are inconsistencies between the Parse Errors documented in the Parse Guides, coded in the Parse JS SDK and coded in Parse Server, therefore research regarding the availability of error codes has to be conducted in all of these sources.
|
||||
1. Add the new Parse Error to [/src/ParseError.js](https://github.com/parse-community/Parse-SDK-JS/blob/master/src/ParseError.js) in the Parse JavaScript SDK. This is the primary reference for Parse Errors for the Parse JavaScript SDK and Parse Server.
|
||||
1. Create a pull request for the Parse JavaScript SDK including the new Parse Errors. The PR needs to be merged and a new Parse JS SDK version needs to be released.
|
||||
1. Change the Parse JS SDK dependency in [package.json](https://github.com/parse-community/parse-server/blob/master/package.json) of Parse Server to the newly released Parse JS SDK version, so that the new Parse Error is recognized by Parse Server.
|
||||
1. When throwing the new Parse Error in code, do not hard-code the error code but instead reference the error code from the Parse Error. For example:
|
||||
```javascript
|
||||
throw new Parse.Error(Parse.Error.EXAMPLE_ERROR_CODE, 'Example error message.');
|
||||
```
|
||||
1. Choose a descriptive error message that provdes more details about the specific error scenario. Different error messages may be used for the same error code. For example:
|
||||
```javascript
|
||||
throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, 'The file could not be saved because it exceeded the maximum allowed file size.');
|
||||
throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, 'The file could not be saved because the file format was incorrect.');
|
||||
```
|
||||
1. Add the new Parse Error to the [docs](https://github.com/parse-community/docs/blob/gh-pages/_includes/common/errors.md).
|
||||
|
||||
### Parse Server Configuration
|
||||
|
||||
Introducing new [Parse Server configuration][config] parameters requires the following steps:
|
||||
|
||||
1. Add parameters definitions in [/src/Options/index.js][config-index].
|
||||
2. If the new parameter does not have one single value but is a parameter group (an object containing multiple sub-parameters):
|
||||
- add the environment variable prefix for the parameter group to `nestedOptionEnvPrefix` in [/resources/buildConfigDefinition.js](https://github.com/parse-community/parse-server/blob/master/resources/buildConfigDefinition.js)
|
||||
- add the parameter group type to `nestedOptionTypes` in [/resources/buildConfigDefinition.js](https://github.com/parse-community/parse-server/blob/master/resources/buildConfigDefinition.js)
|
||||
|
||||
For example, take a look at the existing Parse Server `security` parameter. It is a parameter group, because it has multiple sub-parameter such as `checkGroups`. Its interface is defined in [index.js][config-index] as `export interface SecurityOptions`. Therefore, the value to add to `nestedOptionTypes` would be `SecurityOptions`, the value to add to `nestedOptionEnvPrefix` would be `PARSE_SERVER_SECURITY_`.
|
||||
|
||||
3. Execute `npm run definitions` to automatically create the definitions in [/src/Options/Definitions.js][config-def] and [/src/Options/docs.js][config-docs].
|
||||
4. Add parameter value validation in [/src/Config.js](https://github.com/parse-community/parse-server/blob/master/src/Config.js).
|
||||
5. Add test cases to ensure the correct parameter value validation. Parse Server throws an error at launch if an invalid value is set for any configuration parameter.
|
||||
6. Execute `npm run docs` to generate the documentation in the `/out` directory. Take a look at the documentation whether the description and formatting of the newly introduced parameters is satisfactory.
|
||||
|
||||
## Pull Request
|
||||
|
||||
### Commit Message
|
||||
|
||||
For release automation, the title of pull requests needs to be written in a defined syntax. We loosely follow the [Conventional Commits](https://www.conventionalcommits.org) specification, which defines this syntax:
|
||||
|
||||
```
|
||||
<type>: <summary>
|
||||
```
|
||||
|
||||
The _type_ is the category of change that is made, possible types are:
|
||||
- `feat` - add a new feature or improve an existing feature
|
||||
- `fix` - fix a bug
|
||||
- `refactor` - refactor code without impact on features or performance
|
||||
- `docs` - add or edit code comments, documentation, GitHub pages
|
||||
- `style` - edit code style
|
||||
- `build` - retry failing build and anything build process related
|
||||
- `perf` - performance optimization
|
||||
- `ci` - continuous integration
|
||||
- `test` - tests
|
||||
|
||||
The _summary_ is a short change description in present tense, not capitalized, without period at the end. This summary will also be used as the changelog entry.
|
||||
- It must be short and self-explanatory for a reader who does not see the details of the full pull request description
|
||||
- It must not contain abbreviations, e.g. instead of `LQ` write `LiveQuery`
|
||||
- It must use the correct product and feature names as referenced in the documentation, e.g. instead of `Cloud Validator` use `Cloud Function validation`
|
||||
- In case of a breaking change, the summary must not contain duplicate information that is also in the [BREAKING CHANGE](#breaking-change) chapter of the pull request description. It must not contain a note that it is a breaking change, as this will be automatically flagged as such if the pull request description contains the BREAKING CHANGE chapter.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
feat: add handle to door for easy opening
|
||||
```
|
||||
|
||||
Currently, we are not making use of the commit _scope_, which would be written as `<type>(<scope>): <summary>`, that attributes a change to a specific part of the product.
|
||||
|
||||
### Breaking Change
|
||||
|
||||
If a pull request contains a braking change, the description of the pull request must contain a dedicated chapter at the bottom to indicate this. This is to assist the committer of the pull request to avoid merging a breaking change as non-breaking.
|
||||
|
||||
## Merging
|
||||
|
||||
The following guide is for anyone who merges a contributor pull request into the working branch, the working branch into a release branch, a release branch into another release branch, or any other direct commits such as hotfixes into release branches or the working branch.
|
||||
|
||||
- A contributor pull request must be merged into the working branch using `Squash and Merge`, to create a single commit message that describes the change.
|
||||
- A release branch or the default branch must be merged into another release branch using `Merge Commit`, to preserve each individual commit message that describes its respective change.
|
||||
- For changelog generation, only the commit message set when merging the pull request is relevant. The title and description of the GitHub pull request as authored by the contributor have no influence on the changelog generation. However, the title of the GitHub pull request should be used as the commit message. See the following chapters for considerations in special scenarios, e.g. merging a breaking change or reverting a commit.
|
||||
|
||||
### Breaking Change
|
||||
|
||||
If the pull request contains a breaking change, the commit message must contain the phrase `BREAKING CHANGE`, capitalized and without any formatting, followed by a short description of the breaking change and ideally how the developer should address it, all in a single line. This line should contain more details focusing on the "breaking” aspect of the change and is intended to assist the developer in adapting. Keep it concise, as it will become part of the changelog entry, for example:
|
||||
|
||||
```
|
||||
fix: remove handle from door
|
||||
|
||||
BREAKING CHANGE: You cannot open the door anymore by using a handle. See the [#migration guide](http://example.com) for more details.
|
||||
```
|
||||
Keep in mind that in a repository with release automation, merging such a commit message will trigger a release with a major version increment.
|
||||
|
||||
### Reverting
|
||||
|
||||
If the commit reverts a previous commit, use the prefix `revert:`, followed by the header of the reverted commit. In the body of the commit message add `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted. For example:
|
||||
|
||||
```
|
||||
revert: fix: remove handle from door
|
||||
|
||||
This reverts commit 1234567890abcdef.
|
||||
```
|
||||
|
||||
⚠️ A `revert` prefix will *always* trigger a release. Generally, a commit that did not trigger a release when it was initially merged should also not trigger a release when it is reverted. For example, do not use the `revert` prefix when reverting a commit that has a `ci` prefix:
|
||||
|
||||
```
|
||||
ci: add something
|
||||
```
|
||||
is reverted with:
|
||||
```
|
||||
ci: remove something
|
||||
```
|
||||
instead of:
|
||||
```
|
||||
revert: ci: add something
|
||||
|
||||
This reverts commit 1234567890abcdef.
|
||||
```
|
||||
|
||||
### Security Vulnerability
|
||||
|
||||
#### Local Testing
|
||||
|
||||
Fixes for security vulnerabilities are developed in private forks with a closed audience, inaccessible to the public. A current GitHub limitation does not allow to run CI tests on pull requests in private forks. Whether a pull requests fully passes all CI tests can only be determined by publishing the fix as a public pull request and running the CI. This means the fix and implicitly information about the vulnerability are made accessible to the public. This increases the risk that a vulnerability fix is published, but then cannot be merged immediately due to a CI issue. To mitigate that risk, before publishing a vulnerability fix, the following tests needs to be run locally and pass:
|
||||
|
||||
- `npm run test` to test with MongoDB
|
||||
- `npm run test:postgres:testonly` to test with Postgres
|
||||
- `npm run madge:circular` to detect circular dependencies
|
||||
- `npm run lint` to check lint compliance
|
||||
- `npm run definitions` to update the Parse Server options definitions
|
||||
|
||||
> [!CAUTION]
|
||||
> It is essential to run `npm run build` *after* switching to a different branch or making a commit and *before* running any tests. Otherwise the tests may run on the build from a different branch or on a build that does not reflect the most recent commits.
|
||||
|
||||
#### Environment
|
||||
|
||||
A reported vulnerability may have already been fixed since it was reported, either due to a targeted fix or as side-effect of other code changed. To verify that a vulnerability exists, tests need to be run in an environment that uses the latest commit of the development branch of Parse Server.
|
||||
|
||||
> [!NOTE]
|
||||
> Do not use the latest alpha version for testing as it may be behind the latest commit of the development branch.
|
||||
|
||||
Vulnerability test must only be conducted in environments for which the tester can ensure that no unauthorized 3rd party has potentially access to. This is to ensure a vulnerability stays confidential and is not exposed prematurely to the public.
|
||||
|
||||
You must not test a vulnerability using any 3rd party APIs that provide Parse Server as a hosted service (SaaS) as this may expose the vulnerability to an unauthorized 3rd party and the effects of the vulnerability may cause issues on the provider's side.
|
||||
|
||||
> [!CAUTION]
|
||||
> Utilizing a vulnerability in a third-party service, even for testing or development purposes, can result in legal repercussions. You are solely accountable for any damage arising from such actions and agree to indemnify Parse Platform against any liabilities or claims resulting from your actions.
|
||||
|
||||
#### Merging
|
||||
|
||||
A current GitHub limitation does not allow to customize the commit message when merging pull requests of a private fork that was created to fix a security vulnerability. Our release automation framework demands a specific commit message syntax which therefore cannot be met. This prohibits to follow the process that GitHub suggest, which is to merge a pull request from a private fork directly to a public branch. Instead, after [local testing](#local-testing), a public pull request needs to be created with the code fix copied over from the private pull request.
|
||||
|
||||
This creates a risk that a vulnerability is indirectly disclosed by publishing a pull request with the fix, but the fix cannot be merged due to a CI issue. To mitigate that risk, the pull request title and description should be kept marginal or generic, not hinting to a vulnerability or giving any details about the vulnerability, until the pull request has been successfully merged.
|
||||
|
||||
## Releasing
|
||||
|
||||
### General Considerations
|
||||
|
||||
- The `package-lock.json` file has to be deleted and recreated by npm from scratch in regular intervals using the `npm i` command. It is not enough to only update the file via automated security pull requests (e.g. dependabot, snyk), that can create inconsistencies between sub-dependencies of a dependency and increase the chances of vulnerabilities. The file should be recreated once every release cycle which is usually monthly.
|
||||
|
||||
### Major Release / Long-Term-Support
|
||||
|
||||
While the current major version is published on branch `release`, a Long-Term-Support (LTS) version is published on branch `release-#.x.x`, for example `release-4.x.x` for the Parse Server 4.x LTS branch.
|
||||
|
||||
### Preparing Release
|
||||
|
||||
The following changes are done in the `alpha` branch, before publishing the last `beta` version that will eventually become the major release. This way the changes trickle naturally through all branches and code consistency is ensured among branches.
|
||||
|
||||
- Make sure all [deprecations](https://github.com/parse-community/parse-server/blob/alpha/DEPRECATIONS.md) are reflected in code, old code is removed and the deprecations table is updated.
|
||||
- Add the future LTS branch `release-#.x.x` to the branch list in [release.config.js](https://github.com/parse-community/parse-server/blob/alpha/release.config.js) so that the branch will later be recognized for release automation.
|
||||
|
||||
### Publishing Release (forward-merge):
|
||||
|
||||
1. Create new temporary branch `build` on branch `beta`.
|
||||
2. Create PR to merge `build` into `release`:
|
||||
- PR title: `build: release`
|
||||
- PR description: (leave empty)
|
||||
3. Resolve any conflicts:
|
||||
- For conflicts regarding the package version in `package.json` and `package-lock.json` it doesn't matter which version is chosen, as the version will be set by auto-release in a commit after merging. However, for both files the same version should be chosen when resolving the conflict.
|
||||
4. Merge PR with a "merge commit", do not "squash and merge":
|
||||
- Commit message: (use PR title)
|
||||
- Description: (leave empty)
|
||||
5. Wait for GitHub Action `release-automated` to finish:
|
||||
- If GitHub Action fails, investigate why; manual correction may be needed.
|
||||
6. Pull all remote branches into local branches.
|
||||
7. Delete temporary branch `build`.
|
||||
8. Create new temporary branch `build` on branch `alpha`.
|
||||
9. Create PR to merge `build` into `beta`:
|
||||
- PR title: `build: release`
|
||||
- PR description: (leave empty)
|
||||
8. Repeat steps 3-7 for PR from step 9.
|
||||
|
||||
### Publishing Hotfix (back-merge):
|
||||
|
||||
1. Create PR to merge hotfix PR into `release`:
|
||||
- Merge PR following the same rules as any PR would be merged into the working branch `alpha`.
|
||||
2. Wait for GitHub Action `release-automated` to finish:
|
||||
- GitHub Action will fail with error `! [rejected] HEAD -> beta (non-fast-forward)`; this is expected as auto-release currently cannot fully handle back-merging; docker will not publish the new release, so this has to be done manually using the GitHub workflow `release-manual-docker` and entering the version tag that has been created by auto-release.
|
||||
3. Pull all remote branches into local branches.
|
||||
4. Create a new temporary branch `backmerge` on branch `release`.
|
||||
5. Create PR to merge `backmerge` into `beta`:
|
||||
- PR title: `refactor: <commit-summary>` where `<commit-summary>` is the commit summary of step 1. The commit type needs to be `refactor`, otherwise the commit will show in the changelog of the `release` branch, once the `beta` branch is merged into release; this would a duplicate entry because the same changelog entry has already been generated when the PR was merged into the `release` branch in step 1.
|
||||
- PR description: (leave empty)
|
||||
6. Resolve any conflicts:
|
||||
- During back-merging, usually all changes are preserved; current changes come from the hotfix in the `release` branch, the incoming changes come from the `beta` branch usually being ahead of the `release` branch. This makes back-merging so complex and bug-prone and is the main reason why it should be avoided if possible.
|
||||
7. Merge PR with "squash and merge", do not do a "merge commit":
|
||||
- Commit message: (use PR title)
|
||||
- Description: (leave empty)
|
||||
|
||||
ℹ️ Merging this PR will not trigger a release; the back-merge will not appear in changelogs of the `beta`, `alpha` branches; the back-merged fix will be an undocumented change of these branches' next releases; if necessary, the change needs to be added manually to the pre-release changelogs *after* the next pre-releases.
|
||||
8. Delete temporary branch `backmerge`.
|
||||
10. Create a new temporary branch `backmerge` on branch `beta`.
|
||||
11. Repeat steps 4-8 to merge PR into `alpha`.
|
||||
|
||||
⚠️ Long-term-support branches are excluded from the processes above and handled individually as they do not have pre-releases branches and are not considered part of the current codebase anymore. It may be necessary to significantly adapt a PR for a LTS branch due to the differences in codebase and CI tests. This adaption should be done in advance before merging any related PR, especially for security fixes, as to not publish a vulnerability while it may still take significant time to adapt the fix for the older codebase of a LTS branch.
|
||||
|
||||
### Publishing Major Release (Yearly Release)
|
||||
|
||||
1. Create LTS branch `release-#.x.x` off the latest version tag on `release` branch.
|
||||
2. Create temporary branch `build-release` off branch `beta` and create a pull request with `release` as the base branch.
|
||||
3. Merge branch `build-release` into `release`. Given that there will be breaking changes, a new major release will be created. In the unlikely case that there have been no breaking changes between the previous major release and the upcoming release, a major version increment has to be triggered manually. See the docs of the release automation framework for how to do that.
|
||||
4. Add newly created LTS branch `release-#.x.x` from step 1 to [Snyk](https://snyk.io) so that Snyk opens pull requests for the LTS branch; remove previously existing LTS branch `release-#.x.x` from Snyk.
|
||||
|
||||
## Versioning
|
||||
|
||||
> The following versioning system is applied since Parse Server 5.0.0 and does not necessarily apply to previous releases.
|
||||
|
||||
Parse Server follows [semantic versioning](https://semver.org) with a flavor of [calendric versioning](https://calver.org). Semantic versioning makes Parse Server easy to upgrade because breaking changes only occur in major releases. Calendric versioning gives an additional sense of how old a Parse Server release is and allows for Long-Term Support of previous major releases.
|
||||
|
||||
Example version: `5.0.0-alpha.1`
|
||||
|
||||
Syntax: `[major]`**.**`[minor]`**.**`[patch]`**-**`[pre-release-label]`**.**`[pre-release-increment]`
|
||||
|
||||
- The `major` version increments with the first release of every year and may include changes that are *not backwards compatible*.
|
||||
- The `minor` version increments during the year and may include new features or improvements of existing features that are backwards compatible.
|
||||
- The `patch` version increments during the year and may include bug fixes that are backwards compatible.
|
||||
- The `pre-release-label` is optional for pre-release versions such as:
|
||||
- `-alpha` (likely to contain bugs, likely to change in features until release)
|
||||
- `-beta` (likely to contain bugs, no change in features until release)
|
||||
- The `[pre-release-increment]` is a number that increments with every new version of a pre-release
|
||||
|
||||
Exceptions:
|
||||
- The `major` version may increment during the year in the unlikely event that a breaking change is so urgent that it cannot wait for the next yearly release. An example would be a vulnerability fix that leads to an unavoidable breaking change. However, security requirements depend on the application and not every vulnerability may affect every deployment, depending on the features used. Therefore we usually prefer to deprecate insecure functionality and introduce the breaking change following our [deprecation policy](#deprecation-policy).
|
||||
|
||||
## Code of Conduct
|
||||
### Code of Conduct
|
||||
|
||||
This project adheres to the [Contributor Covenant Code of Conduct](https://github.com/parse-community/parse-server/blob/master/CODE_OF_CONDUCT.md). By participating, you are expected to honor this code.
|
||||
|
||||
[config]: http://parseplatform.org/parse-server/api/master/ParseServerOptions.html
|
||||
[config-def]: https://github.com/parse-community/parse-server/blob/master/src/Options/Definitions.js
|
||||
[config-docs]: https://github.com/parse-community/parse-server/blob/master/src/Options/docs.js
|
||||
[config-index]: https://github.com/parse-community/parse-server/blob/master/src/Options/index.js
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Deprecation Plan <!-- omit in toc -->
|
||||
|
||||
The following is a list of deprecations, according to the [Deprecation Policy](https://github.com/parse-community/parse-server/blob/master/CONTRIBUTING.md#deprecation-policy). After a feature becomes deprecated, and giving developers time to adapt to the change, the deprecated feature will eventually be changed, leading to a breaking change. Developer feedback during the deprecation period may postpone or even revoke the introduction of the breaking change.
|
||||
|
||||
| ID | Change | Issue | Deprecation [ℹ️][i_deprecation] | Planned Change [ℹ️][i_change] | Status [ℹ️][i_status] | Notes |
|
||||
|---------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------|---------------------------------|---------------------------------|-----------------------|-------|
|
||||
| DEPPS1 | Native MongoDB syntax in aggregation pipeline | [#7338](https://github.com/parse-community/parse-server/issues/7338) | 5.0.0 (2022) | 6.0.0 (2023) | changed | - |
|
||||
| DEPPS2 | Config option `directAccess` defaults to `true` | [#6636](https://github.com/parse-community/parse-server/pull/6636) | 5.0.0 (2022) | 6.0.0 (2023) | changed | - |
|
||||
| DEPPS3 | Config option `enforcePrivateUsers` defaults to `true` | [#7319](https://github.com/parse-community/parse-server/pull/7319) | 5.0.0 (2022) | 6.0.0 (2023) | changed | - |
|
||||
| DEPPS4 | Remove convenience method for http request `Parse.Cloud.httpRequest` | [#7589](https://github.com/parse-community/parse-server/pull/7589) | 5.0.0 (2022) | 6.0.0 (2023) | changed | - |
|
||||
| DEPPS5 | Config option `allowClientClassCreation` defaults to `false` | [#7925](https://github.com/parse-community/parse-server/pull/7925) | 5.3.0 (2022) | 7.0.0 (2024) | changed | - |
|
||||
| DEPPS6 | Auth providers disabled by default | [#7953](https://github.com/parse-community/parse-server/pull/7953) | 5.3.0 (2022) | 7.0.0 (2024) | changed | - |
|
||||
| DEPPS7 | Remove file trigger syntax `Parse.Cloud.beforeSaveFile((request) => {})` | [#7966](https://github.com/parse-community/parse-server/pull/7966) | 5.3.0 (2022) | 7.0.0 (2024) | changed | - |
|
||||
| DEPPS8 | Login with expired 3rd party authentication token defaults to `false` | [#7079](https://github.com/parse-community/parse-server/pull/7079) | 5.3.0 (2022) | 7.0.0 (2024) | changed | - |
|
||||
| DEPPS9 | Rename LiveQuery `fields` option to `keys` | [#8389](https://github.com/parse-community/parse-server/issues/8389) | 6.0.0 (2023) | 7.0.0 (2024) | changed | - |
|
||||
| DEPPS10 | Encode `Parse.Object` in Cloud Function and remove option `encodeParseObjectInCloudFunction` | [#8634](https://github.com/parse-community/parse-server/issues/8634) | 6.2.0 (2023) | 9.0.0 (2026) | changed | - |
|
||||
| DEPPS11 | Replace `PublicAPIRouter` with `PagesRouter` | [#7625](https://github.com/parse-community/parse-server/issues/7625) | 8.0.0 (2025) | 9.0.0 (2026) | changed | - |
|
||||
| DEPPS12 | Database option `allowPublicExplain` defaults to `false` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.5.0 (2025) | 9.0.0 (2026) | changed | - |
|
||||
| DEPPS13 | Config option `enableInsecureAuthAdapters` defaults to `false` | [#9667](https://github.com/parse-community/parse-server/pull/9667) | 8.0.0 (2025) | 9.0.0 (2026) | changed | - |
|
||||
|
||||
[i_deprecation]: ## "The version and date of the deprecation."
|
||||
[i_change]: ## "The version and date of the planned change."
|
||||
[i_status]: ## "The current status of the deprecation: deprecated (the feature is deprecated but still available), changed (the deprecated feature has been changed), retracted (the deprecation has been retracted and the feature will not be changed."
|
||||
52
Dockerfile
52
Dockerfile
@@ -1,51 +1,21 @@
|
||||
############################################################
|
||||
# Build stage
|
||||
############################################################
|
||||
FROM node:20.19.0-alpine3.20 AS build
|
||||
FROM node:carbon
|
||||
|
||||
RUN apk --no-cache add \
|
||||
build-base \
|
||||
git \
|
||||
python3
|
||||
RUN mkdir -p /parse-server
|
||||
COPY ./ /parse-server/
|
||||
|
||||
WORKDIR /tmp
|
||||
RUN mkdir -p /parse-server/config
|
||||
VOLUME /parse-server/config
|
||||
|
||||
# Copy package.json first to benefit from layer caching
|
||||
COPY package*.json ./
|
||||
|
||||
# Copy src to have config files for install
|
||||
COPY . .
|
||||
|
||||
# Install without scripts
|
||||
RUN npm ci --omit=dev --ignore-scripts \
|
||||
# Copy production node_modules aside for later
|
||||
&& cp -R node_modules prod_node_modules \
|
||||
# Install all dependencies
|
||||
&& npm ci \
|
||||
# Run build steps
|
||||
&& npm run build
|
||||
|
||||
############################################################
|
||||
# Release stage
|
||||
############################################################
|
||||
FROM node:20.19.0-alpine3.20 AS release
|
||||
|
||||
VOLUME /parse-server/cloud /parse-server/config
|
||||
RUN mkdir -p /parse-server/cloud
|
||||
VOLUME /parse-server/cloud
|
||||
|
||||
WORKDIR /parse-server
|
||||
|
||||
# Copy build stage folders
|
||||
COPY --from=build /tmp/prod_node_modules /parse-server/node_modules
|
||||
COPY --from=build /tmp/lib lib
|
||||
|
||||
COPY package*.json ./
|
||||
COPY bin bin
|
||||
COPY public public
|
||||
COPY views views
|
||||
RUN mkdir -p logs && chown -R node: logs
|
||||
RUN npm install && \
|
||||
npm run build
|
||||
|
||||
ENV PORT=1337
|
||||
USER node
|
||||
|
||||
EXPOSE $PORT
|
||||
|
||||
ENTRYPOINT ["node", "./bin/parse-server"]
|
||||
ENTRYPOINT ["npm", "start", "--"]
|
||||
|
||||
192
LICENSE
192
LICENSE
@@ -1,176 +1,34 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
BSD License
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
For Parse Server software
|
||||
|
||||
1. Definitions.
|
||||
Copyright (c) 2015-present, Parse, LLC. All rights reserved.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
* Neither the name Parse nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
-----
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code.
|
||||
|
||||
10
NOTICE
10
NOTICE
@@ -1,10 +0,0 @@
|
||||
Parse Server
|
||||
|
||||
Copyright 2015-present Parse Platform
|
||||
|
||||
This product includes software developed at Parse Platform.
|
||||
www.parseplatform.org
|
||||
|
||||
---
|
||||
|
||||
As of April 5, 2017, Parse, LLC has transferred this code to the Parse Platform organization, and will no longer be contributing to or distributing this code.
|
||||
37
PATENTS
Normal file
37
PATENTS
Normal file
@@ -0,0 +1,37 @@
|
||||
Additional Grant of Patent Rights Version 2
|
||||
|
||||
"Software" means the Parse Server software distributed by Parse, LLC.
|
||||
|
||||
Parse, LLC. ("Parse") hereby grants to each recipient of the Software
|
||||
("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
|
||||
(subject to the termination provision below) license under any Necessary
|
||||
Claims, to make, have made, use, sell, offer to sell, import, and otherwise
|
||||
transfer the Software. For avoidance of doubt, no license is granted under
|
||||
Parse’s rights in any patent claims that are infringed by (i) modifications
|
||||
to the Software made by you or any third party or (ii) the Software in
|
||||
combination with any software or other technology.
|
||||
|
||||
The license granted hereunder will terminate, automatically and without notice,
|
||||
if you (or any of your subsidiaries, corporate affiliates or agents) initiate
|
||||
directly or indirectly, or take a direct financial interest in, any Patent
|
||||
Assertion: (i) against Parse or any of its subsidiaries or corporate
|
||||
affiliates, (ii) against any party if such Patent Assertion arises in whole or
|
||||
in part from any software, technology, product or service of Parse or any of
|
||||
its subsidiaries or corporate affiliates, or (iii) against any party relating
|
||||
to the Software. Notwithstanding the foregoing, if Parse or any of its
|
||||
subsidiaries or corporate affiliates files a lawsuit alleging patent
|
||||
infringement against you in the first instance, and you respond by filing a
|
||||
patent infringement counterclaim in that lawsuit against that party that is
|
||||
unrelated to the Software, the license granted hereunder will not terminate
|
||||
under section (i) of this paragraph due to such counterclaim.
|
||||
|
||||
A "Necessary Claim" is a claim of a patent owned by Parse that is
|
||||
necessarily infringed by the Software standing alone.
|
||||
|
||||
A "Patent Assertion" is any lawsuit or other action alleging direct, indirect,
|
||||
or contributory infringement or inducement to infringe any patent, including a
|
||||
cross-claim or counterclaim.
|
||||
|
||||
-----
|
||||
|
||||
As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code.
|
||||
60
SECURITY.md
60
SECURITY.md
@@ -2,7 +2,7 @@
|
||||
If you believe you have found a security vulnerability on one of parse-community maintained packages,
|
||||
we encourage you to let us know right away.
|
||||
We will investigate all legitimate reports and do our best to quickly fix the problem.
|
||||
Before making a report, please review this page to understand our disclosure policy and how to communicate with us.
|
||||
Before reporting though, please review this page including and those things that should not be reported.
|
||||
|
||||
# Responsible Disclosure Policy
|
||||
If you comply with the policies below when reporting a security issue to parse community,
|
||||
@@ -16,4 +16,60 @@ We ask that:
|
||||
|
||||
# Communicating with us
|
||||
|
||||
All vulnerabilities should be privately reported to us by going to [https://report.parseplatform.org](https://report.parseplatform.org). Alternatively, you can send an email to [security@parseplatform.org](mailto:security@parseplatform.org).
|
||||
All vulnerability should be privately reported to either [Node Security](https://nodesecurity.io/report) or directly to us at the following address [security at parseplatform dot org](mailto:security@parseplatform.org)
|
||||
|
||||
You can use our PGP public key, which is also uploaded [here](hkp://pgp.mit.edu):
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBFoi200BEACnFHa4Atvw62TjpI5uDtyOF1Ab6gd6898ITXlzFVlAoiqTBE2o
|
||||
S3H9vCe6w32HkTqyKiymdk50mAaDJrEOyAZSqj0gc4r7vmCx2s7f3iO9A9PEGsHj
|
||||
UROnkJ5v2su1Dk95XQrbrR4JyNvFMLLqEbdK78Mhx/Xd5QqOD8pop0cS8pF1f1Mb
|
||||
3MiZb3bxFj+7n+KC80C2+CNyJt95alVnq2MuwbEuwTJQV5CEgRqzBCov9qnLgloK
|
||||
w7YP4YLkKZoMZQ45mWCUTmn8YIa9PabDLXUhlKv3MQInhnJIELb+jSKO96glHr6p
|
||||
DpFf0pwRfsuoIhy3jaO7K/ws5uZY3/Ae3gjrAlOB8jhae0POWSwEM+iWHg3wcjpt
|
||||
lRdu/OgPXqKIgMAXw6Kx9XrskEhOI9ZQfHZlK3HL4ArSdtGYIO5pVNeRssljJvJm
|
||||
G5HJuGBaPCQNYX7BWJkXFF0HYV6Ke2JDXGVSM4ubPJsZcA4Yx7SYyvuOsNgqHOFM
|
||||
9snfPfAPAhu/4zCYNCO2NNBc7HaH+qwIvveWX5tTGe6UpX/wOcD8xkoEn+UygQbO
|
||||
lwu+kjFn8H6RlDChPR65aJTU5Lu0kqRnej1gCjYzOS6AjFOjLuRBlRaey+myhQHO
|
||||
TbII9nkYI3abYhD8Di77Ve6XFMQI1grPGaqNp6ZLfej1u8PExpclzxTbtQARAQAB
|
||||
tDdQYXJzZVBsYXRmb3JtLm9yZyBTZWN1cml0eSA8c2VjdXJpdHlAcGFyc2VwbGF0
|
||||
Zm9ybS5vcmc+iQI9BBMBCgAnBQJaIttNAhsDBQkHhh+ABQsJCAcDBRUKCQgLBRYC
|
||||
AwEAAh4BAheAAAoJEOaNxtHMZ3/L13EP/2X4i0h1Jidr0GN6t7LUJFDBDHxnY+V+
|
||||
kPXuucWqtFSkiznHNWSKh8N1LY9N+5eYQj21fJw2RV+ePZKb07jcThG8G1qg+tIn
|
||||
bbLO2RxmuO/ISgqgvpmtZH9FHtjpGaGStCQqljtZDcBI0Y52l9SLItZjoiRlXePb
|
||||
C+embDhO6Wzgsi+zkzskm8ISw4mTbDY+HN/1TakCsfMMs8J7twQar+eW97WibzRW
|
||||
pvhIeJ6egzxs2dW0bXxb0OPvx9xm/FxxRgf+2vySYFnZ88j7Luur4VKdBvh1NtUT
|
||||
n+xLp/heCHQ/If1ou1Dd6rypEng3A75WANf5m1TAd8JrlQZEOLm4oW+brpDBamqc
|
||||
dP2z2/zzKykZzRoN1PSX9JRsyLhJhZSXIm/49gATtkaUFBBsFrrwqdWTV7tWFmQI
|
||||
Oe2wT9IExe+RmXsVqwIndyVkcROuXXGt3y92dcmEriNUGmYXJchs9pAdOCkpHqmf
|
||||
BkZWalXuWdWiwshNiEF3KWiNbw6BMEWlKPuuJ6kWevLj35MQMLIIlGLx722/kbBB
|
||||
KIJfp8NdWncIyx0ulq70GWdNaKvu+9dDElMCsPqXeVxbXVpGiBcIgX1S0JEU0YX7
|
||||
kShAAkZDwhyfUh4IYbyJbNVNzhMazDqI48kP8Kz8vqvZAf3SXyjSBL1XKWLAfKtb
|
||||
Bs4OuHR3FDkjuQINBFoi200BEADoh8xHW4SVuVnF+Y82Z2B25Ybhwd13mP3LUxwX
|
||||
cRYeyVge8V7kyftYiUbIybDoxa3H8ysiSgH51yHkoRsq8JO3WEnJZop1ZnjOKhjv
|
||||
g73vciKImAGrsTVtUR4ErwUsHaXgCFmlmyTI/RLPDfvHdZyYm9wji4XLZrFu5O/s
|
||||
JD1wU1/aMYCBRjrszI4uklyqGUx2kKLYEI7iITAVVQ8/xFlPPYhVX02jR7fCqTkI
|
||||
ualVAzK/6Lc4VGqjzFG5kElLCIVDTMLJvPETgXeSAuBigcC+osTw8IRhqY87qNbn
|
||||
ZpGDKJxV7ARXg5akg/98xI1TZiAMP1vHVKke7XiH5E6M/3IyPiY5ns4SaXu3ZonN
|
||||
EUR9Z60IeUHVkGpMUk0K0avkaLIAWb93D6jlZ+fJoNBuCoWB31d6+/W8LnrocTQb
|
||||
mL9ls8HiabrPDsuzI9y3ptOjgGn8pmWoJHM2fiQ5eElexHFB+1QTqq1yiTnuohi/
|
||||
p+BbKK6V/FZbrP4Rd3hOmPkOWag3KvwGFF8vW6gmx3lft+B90TtBSMv46lqDI5TX
|
||||
VUr3Un9YHIF+xQMNAgZuJkTIVLrYgexRHnJGrwhRXSZgpVkvj/ygIhR2EvY8zySh
|
||||
/EFw9ZTmhOrR34q/qlChEuUriP1cc1ygTnjfcw+ZgsTPh50VZk8s5cZAa8tVFINR
|
||||
cZKBSwARAQABiQIlBBgBCgAPBQJaIttNAhsMBQkHhh+AAAoJEOaNxtHMZ3/LgbUQ
|
||||
AJHyhtH3bkQsWH0Z+PonbcNxZNq1ZlOfosQIWRzX8BioJpQ5qttkKt5PwhBDrr9h
|
||||
4ySYzsbTg3fSkIkjfUfaRr+62xay5efaIwG5PcHdXOR/fKCJ6NrTvMEzPUZ8521e
|
||||
yk0rjm++bNqh+Knez0+xnk99n1XlPrMAXrEb63oM5IBnpJC1PcztzMhdvsNw+B/l
|
||||
2YcVhXH2peOp/GbAd58fB7JMggwumCktFnXYsYZlMFch3mwKDb66Qi2gbCgK2KHU
|
||||
sj/mPag7vpy1E4lOlBnDeZpYnjfE/8VJkT4ck5OAwywZK/NUqLfh35RaIwjeXDLM
|
||||
nlLff3HQJPXYzavCzLZ5dMZJfn0968NIHitjoW9VLs9UhrY7EWI7T6GAMX3wHcq6
|
||||
ssGOkS0Y1OW8s7jFuoe00PByjiCHcFjBG2NF3n08Nu2c5hewGPs0FdhTadQtHpI2
|
||||
TTeSIxQ2Ui21UfcX4wMbqELh871ZeQcbVp5LWWibVbfy4mx4Tq/Hvgp7DeBh8DLF
|
||||
/7MDDwZ+RIBoy98CYz4xsFMdS/9L64uBk/0C+U4OwFJI1FDDxFp6cDqjxdykWi48
|
||||
wsCczfashguiuJeJ1Ug8URRLY/DKQmjSJaCwy3McK/MOb+JVMazMUyrU9XaGuP4Y
|
||||
Co6fHPyjrvmE5DtU5Vp8O68ZpOYrkM6X22dIQpPi6atm
|
||||
=o7Nx
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* MongoDB Latency Wrapper
|
||||
*
|
||||
* Utility to inject artificial latency into MongoDB operations for performance testing.
|
||||
* This wrapper temporarily wraps MongoDB Collection methods to add delays before
|
||||
* database operations execute.
|
||||
*
|
||||
* Usage:
|
||||
* const { wrapMongoDBWithLatency } = require('./MongoLatencyWrapper');
|
||||
*
|
||||
* // Before initializing Parse Server
|
||||
* const unwrap = wrapMongoDBWithLatency(10); // 10ms delay
|
||||
*
|
||||
* // ... run benchmarks ...
|
||||
*
|
||||
* // Cleanup when done
|
||||
* unwrap();
|
||||
*/
|
||||
|
||||
const { Collection } = require('mongodb');
|
||||
|
||||
// Store original methods for restoration
|
||||
const originalMethods = new Map();
|
||||
|
||||
/**
|
||||
* Wrap a Collection method to add artificial latency
|
||||
* @param {string} methodName - Name of the method to wrap
|
||||
* @param {number} latencyMs - Delay in milliseconds
|
||||
*/
|
||||
function wrapMethod(methodName, latencyMs) {
|
||||
if (!originalMethods.has(methodName)) {
|
||||
originalMethods.set(methodName, Collection.prototype[methodName]);
|
||||
}
|
||||
|
||||
const originalMethod = originalMethods.get(methodName);
|
||||
|
||||
Collection.prototype[methodName] = function (...args) {
|
||||
// For methods that return cursors (like find, aggregate), we need to delay the execution
|
||||
// but still return a cursor-like object
|
||||
const result = originalMethod.apply(this, args);
|
||||
|
||||
// Check if result has cursor methods (toArray, forEach, etc.)
|
||||
if (result && typeof result.toArray === 'function') {
|
||||
// Wrap cursor methods that actually execute the query
|
||||
const originalToArray = result.toArray.bind(result);
|
||||
result.toArray = function() {
|
||||
// Wait for the original promise to settle, then delay the result
|
||||
return originalToArray().then(
|
||||
value => new Promise(resolve => setTimeout(() => resolve(value), latencyMs)),
|
||||
error => new Promise((_, reject) => setTimeout(() => reject(error), latencyMs))
|
||||
);
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
// For promise-returning methods, wrap the promise with delay
|
||||
if (result && typeof result.then === 'function') {
|
||||
// Wait for the original promise to settle, then delay the result
|
||||
return result.then(
|
||||
value => new Promise(resolve => setTimeout(() => resolve(value), latencyMs)),
|
||||
error => new Promise((_, reject) => setTimeout(() => reject(error), latencyMs))
|
||||
);
|
||||
}
|
||||
|
||||
// For synchronous methods, just add delay
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(result);
|
||||
}, latencyMs);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap MongoDB Collection methods with artificial latency
|
||||
* @param {number} latencyMs - Delay in milliseconds to inject before each operation
|
||||
* @returns {Function} unwrap - Function to restore original methods
|
||||
*/
|
||||
function wrapMongoDBWithLatency(latencyMs) {
|
||||
if (typeof latencyMs !== 'number' || latencyMs < 0) {
|
||||
throw new Error('latencyMs must be a non-negative number');
|
||||
}
|
||||
|
||||
if (latencyMs === 0) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Latency is 0ms, skipping MongoDB wrapping');
|
||||
return () => {}; // No-op unwrap function
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Wrapping MongoDB operations with ${latencyMs}ms artificial latency`);
|
||||
|
||||
// List of MongoDB Collection methods to wrap
|
||||
const methodsToWrap = [
|
||||
'find',
|
||||
'findOne',
|
||||
'countDocuments',
|
||||
'estimatedDocumentCount',
|
||||
'distinct',
|
||||
'aggregate',
|
||||
'insertOne',
|
||||
'insertMany',
|
||||
'updateOne',
|
||||
'updateMany',
|
||||
'replaceOne',
|
||||
'deleteOne',
|
||||
'deleteMany',
|
||||
'findOneAndUpdate',
|
||||
'findOneAndReplace',
|
||||
'findOneAndDelete',
|
||||
'createIndex',
|
||||
'createIndexes',
|
||||
'dropIndex',
|
||||
'dropIndexes',
|
||||
'drop',
|
||||
];
|
||||
|
||||
methodsToWrap.forEach(methodName => {
|
||||
wrapMethod(methodName, latencyMs);
|
||||
});
|
||||
|
||||
// Return unwrap function to restore original methods
|
||||
return function unwrap() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Removing MongoDB latency wrapper, restoring original methods');
|
||||
|
||||
originalMethods.forEach((originalMethod, methodName) => {
|
||||
Collection.prototype[methodName] = originalMethod;
|
||||
});
|
||||
|
||||
originalMethods.clear();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
wrapMongoDBWithLatency,
|
||||
};
|
||||
@@ -1,598 +0,0 @@
|
||||
/**
|
||||
* Performance Benchmark Suite for Parse Server
|
||||
*
|
||||
* This suite measures the performance of critical Parse Server operations
|
||||
* using the Node.js Performance API. Results are output in a format
|
||||
* compatible with github-action-benchmark.
|
||||
*
|
||||
* Run with: npm run benchmark
|
||||
*/
|
||||
|
||||
const core = require('@actions/core');
|
||||
const Parse = require('parse/node');
|
||||
const { performance } = require('node:perf_hooks');
|
||||
const { MongoClient } = require('mongodb');
|
||||
const { wrapMongoDBWithLatency } = require('./MongoLatencyWrapper');
|
||||
|
||||
// Configuration
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/parse_benchmark_test';
|
||||
const SERVER_URL = 'http://localhost:1337/parse';
|
||||
const APP_ID = 'benchmark-app-id';
|
||||
const MASTER_KEY = 'benchmark-master-key';
|
||||
const ITERATIONS = process.env.BENCHMARK_ITERATIONS ? parseInt(process.env.BENCHMARK_ITERATIONS, 10) : undefined;
|
||||
const LOG_ITERATIONS = false;
|
||||
|
||||
// Parse Server instance
|
||||
let parseServer;
|
||||
let mongoClient;
|
||||
|
||||
// Logging helpers
|
||||
const logInfo = message => core.info(message);
|
||||
const logError = message => core.error(message);
|
||||
|
||||
/**
|
||||
* Initialize Parse Server for benchmarking
|
||||
*/
|
||||
async function initializeParseServer() {
|
||||
const express = require('express');
|
||||
const { default: ParseServer } = require('../lib/index.js');
|
||||
|
||||
const app = express();
|
||||
|
||||
parseServer = new ParseServer({
|
||||
databaseURI: MONGODB_URI,
|
||||
appId: APP_ID,
|
||||
masterKey: MASTER_KEY,
|
||||
serverURL: SERVER_URL,
|
||||
silent: true,
|
||||
allowClientClassCreation: true,
|
||||
logLevel: 'error', // Minimal logging for performance
|
||||
verbose: false,
|
||||
});
|
||||
|
||||
app.use('/parse', parseServer.app);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = app.listen(1337, (err) => {
|
||||
if (err) {
|
||||
reject(new Error(`Failed to start server: ${err.message}`));
|
||||
return;
|
||||
}
|
||||
Parse.initialize(APP_ID);
|
||||
Parse.masterKey = MASTER_KEY;
|
||||
Parse.serverURL = SERVER_URL;
|
||||
resolve(server);
|
||||
});
|
||||
|
||||
server.on('error', (err) => {
|
||||
reject(new Error(`Server error: ${err.message}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up database between benchmarks
|
||||
*/
|
||||
async function cleanupDatabase() {
|
||||
try {
|
||||
if (!mongoClient) {
|
||||
mongoClient = await MongoClient.connect(MONGODB_URI);
|
||||
}
|
||||
const db = mongoClient.db();
|
||||
const collections = await db.listCollections().toArray();
|
||||
|
||||
for (const collection of collections) {
|
||||
if (!collection.name.startsWith('system.')) {
|
||||
await db.collection(collection.name).deleteMany({});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to cleanup database: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Parse SDK to use the default server
|
||||
*/
|
||||
function resetParseServer() {
|
||||
Parse.serverURL = SERVER_URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure average time for an async operation over multiple iterations.
|
||||
* @param {Object} options Measurement options.
|
||||
* @param {string} options.name Name of the operation being measured.
|
||||
* @param {Function} options.operation Async function to measure.
|
||||
* @param {number} options.iterations Number of iterations to run; choose a value that is high
|
||||
* enough to create reliable benchmark metrics with low variance but low enough to keep test
|
||||
* duration reasonable around <=10 seconds.
|
||||
* @param {boolean} [options.skipWarmup=false] Skip warmup phase.
|
||||
* @param {number} [options.dbLatency] Artificial DB latency in milliseconds to apply during
|
||||
* this benchmark.
|
||||
*/
|
||||
async function measureOperation({ name, operation, iterations, skipWarmup = false, dbLatency }) {
|
||||
// Override iterations if global ITERATIONS is set
|
||||
iterations = ITERATIONS || iterations;
|
||||
|
||||
// Determine warmup count (20% of iterations)
|
||||
const warmupCount = skipWarmup ? 0 : Math.floor(iterations * 0.2);
|
||||
const times = [];
|
||||
|
||||
// Apply artificial latency if specified
|
||||
let unwrapLatency = null;
|
||||
if (dbLatency !== undefined && dbLatency > 0) {
|
||||
logInfo(`Applying ${dbLatency}ms artificial DB latency for this benchmark`);
|
||||
unwrapLatency = wrapMongoDBWithLatency(dbLatency);
|
||||
}
|
||||
|
||||
try {
|
||||
if (warmupCount > 0) {
|
||||
logInfo(`Starting warmup phase of ${warmupCount} iterations...`);
|
||||
const warmupStart = performance.now();
|
||||
for (let i = 0; i < warmupCount; i++) {
|
||||
await operation();
|
||||
}
|
||||
logInfo(`Warmup took: ${(performance.now() - warmupStart).toFixed(2)}ms`);
|
||||
}
|
||||
|
||||
// Measurement phase
|
||||
logInfo(`Starting measurement phase of ${iterations} iterations...`);
|
||||
const progressInterval = Math.ceil(iterations / 10); // Log every 10%
|
||||
const measurementStart = performance.now();
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
const start = performance.now();
|
||||
await operation();
|
||||
const end = performance.now();
|
||||
const duration = end - start;
|
||||
times.push(duration);
|
||||
|
||||
// Log progress every 10% or individual iterations if LOG_ITERATIONS is enabled
|
||||
if (LOG_ITERATIONS) {
|
||||
logInfo(`Iteration ${i + 1}: ${duration.toFixed(2)}ms`);
|
||||
} else if ((i + 1) % progressInterval === 0 || i + 1 === iterations) {
|
||||
const progress = Math.round(((i + 1) / iterations) * 100);
|
||||
logInfo(`Progress: ${progress}%`);
|
||||
}
|
||||
}
|
||||
|
||||
logInfo(`Measurement took: ${(performance.now() - measurementStart).toFixed(2)}ms`);
|
||||
|
||||
// Sort times for percentile calculations
|
||||
times.sort((a, b) => a - b);
|
||||
|
||||
// Filter outliers using Interquartile Range (IQR) method
|
||||
const q1Index = Math.floor(times.length * 0.25);
|
||||
const q3Index = Math.floor(times.length * 0.75);
|
||||
const q1 = times[q1Index];
|
||||
const q3 = times[q3Index];
|
||||
const iqr = q3 - q1;
|
||||
const lowerBound = q1 - 1.5 * iqr;
|
||||
const upperBound = q3 + 1.5 * iqr;
|
||||
|
||||
const filtered = times.filter(t => t >= lowerBound && t <= upperBound);
|
||||
|
||||
// Calculate statistics on filtered data
|
||||
const median = filtered[Math.floor(filtered.length * 0.5)];
|
||||
const p95 = filtered[Math.floor(filtered.length * 0.95)];
|
||||
const p99 = filtered[Math.floor(filtered.length * 0.99)];
|
||||
const min = filtered[0];
|
||||
const max = filtered[filtered.length - 1];
|
||||
|
||||
return {
|
||||
name,
|
||||
value: median, // Use median (p50) as primary metric for stability in CI
|
||||
unit: 'ms',
|
||||
range: `${min.toFixed(2)} - ${max.toFixed(2)}`,
|
||||
extra: `p95: ${p95.toFixed(2)}ms, p99: ${p99.toFixed(2)}ms, n=${filtered.length}/${times.length}`,
|
||||
};
|
||||
} finally {
|
||||
// Remove latency wrapper if it was applied
|
||||
if (unwrapLatency) {
|
||||
unwrapLatency();
|
||||
logInfo('Removed artificial DB latency');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Object Create
|
||||
*/
|
||||
async function benchmarkObjectCreate(name) {
|
||||
let counter = 0;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 1_000,
|
||||
operation: async () => {
|
||||
const TestObject = Parse.Object.extend('BenchmarkTest');
|
||||
const obj = new TestObject();
|
||||
obj.set('testField', `test-value-${counter++}`);
|
||||
obj.set('number', counter);
|
||||
obj.set('boolean', true);
|
||||
await obj.save();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Object Read (by ID)
|
||||
*/
|
||||
async function benchmarkObjectRead(name) {
|
||||
// Setup: Create test objects
|
||||
const TestObject = Parse.Object.extend('BenchmarkTest');
|
||||
const objects = [];
|
||||
|
||||
for (let i = 0; i < 1_000; i++) {
|
||||
const obj = new TestObject();
|
||||
obj.set('testField', `read-test-${i}`);
|
||||
objects.push(obj);
|
||||
}
|
||||
|
||||
await Parse.Object.saveAll(objects);
|
||||
|
||||
let counter = 0;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 1_000,
|
||||
operation: async () => {
|
||||
const query = new Parse.Query('BenchmarkTest');
|
||||
await query.get(objects[counter++ % objects.length].id);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Object Update
|
||||
*/
|
||||
async function benchmarkObjectUpdate(name) {
|
||||
// Setup: Create test objects
|
||||
const TestObject = Parse.Object.extend('BenchmarkTest');
|
||||
const objects = [];
|
||||
|
||||
for (let i = 0; i < 1_000; i++) {
|
||||
const obj = new TestObject();
|
||||
obj.set('testField', `update-test-${i}`);
|
||||
obj.set('counter', 0);
|
||||
objects.push(obj);
|
||||
}
|
||||
|
||||
await Parse.Object.saveAll(objects);
|
||||
|
||||
let counter = 0;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 1_000,
|
||||
operation: async () => {
|
||||
const obj = objects[counter++ % objects.length];
|
||||
obj.increment('counter');
|
||||
obj.set('lastUpdated', new Date());
|
||||
await obj.save();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Simple Query
|
||||
*/
|
||||
async function benchmarkSimpleQuery(name) {
|
||||
// Setup: Create test data
|
||||
const TestObject = Parse.Object.extend('BenchmarkTest');
|
||||
const objects = [];
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const obj = new TestObject();
|
||||
obj.set('category', i % 10);
|
||||
obj.set('value', i);
|
||||
objects.push(obj);
|
||||
}
|
||||
|
||||
await Parse.Object.saveAll(objects);
|
||||
|
||||
let counter = 0;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 1_000,
|
||||
operation: async () => {
|
||||
const query = new Parse.Query('BenchmarkTest');
|
||||
query.equalTo('category', counter++ % 10);
|
||||
await query.find();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Batch Save (saveAll)
|
||||
*/
|
||||
async function benchmarkBatchSave(name) {
|
||||
const BATCH_SIZE = 10;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 1_000,
|
||||
operation: async () => {
|
||||
const TestObject = Parse.Object.extend('BenchmarkTest');
|
||||
const objects = [];
|
||||
|
||||
for (let i = 0; i < BATCH_SIZE; i++) {
|
||||
const obj = new TestObject();
|
||||
obj.set('batchField', `batch-${i}`);
|
||||
obj.set('timestamp', new Date());
|
||||
objects.push(obj);
|
||||
}
|
||||
|
||||
await Parse.Object.saveAll(objects);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: User Signup
|
||||
*/
|
||||
async function benchmarkUserSignup(name) {
|
||||
let counter = 0;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 500,
|
||||
operation: async () => {
|
||||
counter++;
|
||||
const user = new Parse.User();
|
||||
user.set('username', `benchmark_user_${Date.now()}_${counter}`);
|
||||
user.set('password', 'benchmark_password');
|
||||
user.set('email', `benchmark${counter}@example.com`);
|
||||
await user.signUp();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: User Login
|
||||
*/
|
||||
async function benchmarkUserLogin(name) {
|
||||
// Setup: Create test users
|
||||
const users = [];
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const user = new Parse.User();
|
||||
user.set('username', `benchmark_login_user_${i}`);
|
||||
user.set('password', 'benchmark_password');
|
||||
user.set('email', `login${i}@example.com`);
|
||||
await user.signUp();
|
||||
users.push({ username: user.get('username'), password: 'benchmark_password' });
|
||||
await Parse.User.logOut();
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
iterations: 500,
|
||||
operation: async () => {
|
||||
const userCreds = users[counter++ % users.length];
|
||||
await Parse.User.logIn(userCreds.username, userCreds.password);
|
||||
await Parse.User.logOut();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Query with Include (Parallel Pointers)
|
||||
* Tests the performance improvement when fetching multiple pointers at the same level.
|
||||
*/
|
||||
async function benchmarkQueryWithIncludeParallel(name) {
|
||||
const PointerAClass = Parse.Object.extend('PointerA');
|
||||
const PointerBClass = Parse.Object.extend('PointerB');
|
||||
const PointerCClass = Parse.Object.extend('PointerC');
|
||||
const RootClass = Parse.Object.extend('Root');
|
||||
|
||||
// Create pointer objects
|
||||
const pointerAObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new PointerAClass();
|
||||
obj.set('name', `pointerA-${i}`);
|
||||
pointerAObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(pointerAObjects);
|
||||
|
||||
const pointerBObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new PointerBClass();
|
||||
obj.set('name', `pointerB-${i}`);
|
||||
pointerBObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(pointerBObjects);
|
||||
|
||||
const pointerCObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new PointerCClass();
|
||||
obj.set('name', `pointerC-${i}`);
|
||||
pointerCObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(pointerCObjects);
|
||||
|
||||
// Create Root objects with multiple pointers at the same level
|
||||
const rootObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new RootClass();
|
||||
obj.set('name', `root-${i}`);
|
||||
obj.set('pointerA', pointerAObjects[i % pointerAObjects.length]);
|
||||
obj.set('pointerB', pointerBObjects[i % pointerBObjects.length]);
|
||||
obj.set('pointerC', pointerCObjects[i % pointerCObjects.length]);
|
||||
rootObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(rootObjects);
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
skipWarmup: true,
|
||||
dbLatency: 100,
|
||||
iterations: 100,
|
||||
operation: async () => {
|
||||
const query = new Parse.Query('Root');
|
||||
// Include multiple pointers at the same level - should fetch in parallel
|
||||
query.include(['pointerA', 'pointerB', 'pointerC']);
|
||||
await query.find();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark: Query with Include (Nested Pointers with Parallel Leaf Nodes)
|
||||
* Tests the PR's optimization for parallel fetching at each nested level.
|
||||
* Pattern: p1.p2.p3, p1.p2.p4, p1.p2.p5
|
||||
* After fetching p2, we know the objectIds and can fetch p3, p4, p5 in parallel.
|
||||
*/
|
||||
async function benchmarkQueryWithIncludeNested(name) {
|
||||
const Level3AClass = Parse.Object.extend('Level3A');
|
||||
const Level3BClass = Parse.Object.extend('Level3B');
|
||||
const Level3CClass = Parse.Object.extend('Level3C');
|
||||
const Level2Class = Parse.Object.extend('Level2');
|
||||
const Level1Class = Parse.Object.extend('Level1');
|
||||
const RootClass = Parse.Object.extend('Root');
|
||||
|
||||
// Create Level3 objects (leaf nodes)
|
||||
const level3AObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new Level3AClass();
|
||||
obj.set('name', `level3A-${i}`);
|
||||
level3AObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(level3AObjects);
|
||||
|
||||
const level3BObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new Level3BClass();
|
||||
obj.set('name', `level3B-${i}`);
|
||||
level3BObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(level3BObjects);
|
||||
|
||||
const level3CObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new Level3CClass();
|
||||
obj.set('name', `level3C-${i}`);
|
||||
level3CObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(level3CObjects);
|
||||
|
||||
// Create Level2 objects pointing to multiple Level3 objects
|
||||
const level2Objects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new Level2Class();
|
||||
obj.set('name', `level2-${i}`);
|
||||
obj.set('level3A', level3AObjects[i % level3AObjects.length]);
|
||||
obj.set('level3B', level3BObjects[i % level3BObjects.length]);
|
||||
obj.set('level3C', level3CObjects[i % level3CObjects.length]);
|
||||
level2Objects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(level2Objects);
|
||||
|
||||
// Create Level1 objects pointing to Level2
|
||||
const level1Objects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new Level1Class();
|
||||
obj.set('name', `level1-${i}`);
|
||||
obj.set('level2', level2Objects[i % level2Objects.length]);
|
||||
level1Objects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(level1Objects);
|
||||
|
||||
// Create Root objects pointing to Level1
|
||||
const rootObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const obj = new RootClass();
|
||||
obj.set('name', `root-${i}`);
|
||||
obj.set('level1', level1Objects[i % level1Objects.length]);
|
||||
rootObjects.push(obj);
|
||||
}
|
||||
await Parse.Object.saveAll(rootObjects);
|
||||
|
||||
return measureOperation({
|
||||
name,
|
||||
skipWarmup: true,
|
||||
dbLatency: 100,
|
||||
iterations: 100,
|
||||
operation: async () => {
|
||||
const query = new Parse.Query('Root');
|
||||
// After fetching level1.level2, the PR should fetch level3A, level3B, level3C in parallel
|
||||
query.include(['level1.level2.level3A', 'level1.level2.level3B', 'level1.level2.level3C']);
|
||||
await query.find();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all benchmarks
|
||||
*/
|
||||
async function runBenchmarks() {
|
||||
logInfo('Starting Parse Server Performance Benchmarks...');
|
||||
|
||||
let server;
|
||||
|
||||
try {
|
||||
// Initialize Parse Server
|
||||
logInfo('Initializing Parse Server...');
|
||||
server = await initializeParseServer();
|
||||
|
||||
// Wait for server to be ready
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const results = [];
|
||||
|
||||
// Define all benchmarks to run
|
||||
const benchmarks = [
|
||||
{ name: 'Object.save (create)', fn: benchmarkObjectCreate },
|
||||
{ name: 'Object.save (update)', fn: benchmarkObjectUpdate },
|
||||
{ name: 'Object.saveAll (batch save)', fn: benchmarkBatchSave },
|
||||
{ name: 'Query.get (by objectId)', fn: benchmarkObjectRead },
|
||||
{ name: 'Query.find (simple query)', fn: benchmarkSimpleQuery },
|
||||
{ name: 'User.signUp', fn: benchmarkUserSignup },
|
||||
{ name: 'User.login', fn: benchmarkUserLogin },
|
||||
{ name: 'Query.include (parallel pointers)', fn: benchmarkQueryWithIncludeParallel },
|
||||
{ name: 'Query.include (nested pointers)', fn: benchmarkQueryWithIncludeNested },
|
||||
];
|
||||
|
||||
// Run each benchmark with database cleanup
|
||||
for (const benchmark of benchmarks) {
|
||||
logInfo(`\nRunning benchmark '${benchmark.name}'...`);
|
||||
resetParseServer();
|
||||
await cleanupDatabase();
|
||||
results.push(await benchmark.fn(benchmark.name));
|
||||
}
|
||||
|
||||
// Output results in github-action-benchmark format (stdout)
|
||||
logInfo(JSON.stringify(results, null, 2));
|
||||
|
||||
// Output summary to stderr for visibility
|
||||
logInfo('Benchmarks completed successfully!');
|
||||
logInfo('Summary:');
|
||||
results.forEach(result => {
|
||||
logInfo(` ${result.name}: ${result.value.toFixed(2)} ${result.unit} (${result.extra})`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logError('Error running benchmarks:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
// Cleanup
|
||||
if (mongoClient) {
|
||||
await mongoClient.close();
|
||||
}
|
||||
if (server) {
|
||||
server.close();
|
||||
}
|
||||
// Give some time for cleanup
|
||||
setTimeout(() => process.exit(0), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Run benchmarks if executed directly
|
||||
if (require.main === module) {
|
||||
runBenchmarks();
|
||||
}
|
||||
|
||||
module.exports = { runBenchmarks };
|
||||
37
bin/dev
Executable file
37
bin/dev
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var nodemon = require('nodemon');
|
||||
var babel = require("babel-core");
|
||||
var gaze = require('gaze');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Watch the src and transpile when changed
|
||||
gaze('src/**/*', function(err, watcher) {
|
||||
if (err) throw err;
|
||||
watcher.on('changed', function(sourceFile) {
|
||||
console.log(sourceFile + " has changed");
|
||||
try {
|
||||
targetFile = path.relative(__dirname, sourceFile).replace(/\/src\//, '/lib/');
|
||||
targetFile = path.resolve(__dirname, targetFile);
|
||||
fs.writeFile(targetFile, babel.transformFileSync(sourceFile).code);
|
||||
} catch (e) {
|
||||
console.error(e.message, e.stack);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
try {
|
||||
// Run and watch dist
|
||||
nodemon({
|
||||
script: 'bin/parse-server',
|
||||
ext: 'js json',
|
||||
watch: 'lib'
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e.message, e.stack);
|
||||
}
|
||||
|
||||
process.once('SIGINT', function() {
|
||||
process.exit(0);
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
@@ -163,7 +163,7 @@ cat > ./package.json << EOF
|
||||
"start": "parse-server config.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"parse-server": "^3.9.0"
|
||||
"parse-server": "^2.0.0"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,535 +0,0 @@
|
||||
# [7.4.0-beta.1](https://github.com/parse-community/parse-server/compare/7.3.0...7.4.0-beta.1) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `Parse.Query.distinct` fails due to invalid aggregate stage 'hint' ([#9295](https://github.com/parse-community/parse-server/issues/9295)) ([5f66c6a](https://github.com/parse-community/parse-server/commit/5f66c6a075cbe1cdaf9d1b108ee65af8ae596b89))
|
||||
* Security upgrade cross-spawn from 7.0.3 to 7.0.6 ([#9444](https://github.com/parse-community/parse-server/issues/9444)) ([3d034e0](https://github.com/parse-community/parse-server/commit/3d034e0a993e3e5bd9bb96a7e382bb3464f1eb68))
|
||||
* Security upgrade fast-xml-parser from 4.4.0 to 4.4.1 ([#9262](https://github.com/parse-community/parse-server/issues/9262)) ([992d39d](https://github.com/parse-community/parse-server/commit/992d39d508f230c774dcb764d1d907ec8887e6c5))
|
||||
* Security upgrade node from 20.14.0-alpine3.20 to 20.17.0-alpine3.20 ([#9300](https://github.com/parse-community/parse-server/issues/9300)) ([15bb17d](https://github.com/parse-community/parse-server/commit/15bb17d87153bf0d38f08fe4c720da29a204b36b))
|
||||
|
||||
### Features
|
||||
|
||||
* Add support for MongoDB 8 ([#9269](https://github.com/parse-community/parse-server/issues/9269)) ([4756c66](https://github.com/parse-community/parse-server/commit/4756c66cd9f55afa1621d1a3f6fa850ed605cb53))
|
||||
* Add support for PostGIS 3.5 ([#9354](https://github.com/parse-community/parse-server/issues/9354)) ([8ea3538](https://github.com/parse-community/parse-server/commit/8ea35382db3436d54ab59bd30706705564b0985c))
|
||||
* Add support for Postgres 17 ([#9324](https://github.com/parse-community/parse-server/issues/9324)) ([fa2ee31](https://github.com/parse-community/parse-server/commit/fa2ee3196e4319a142b3838bb947c98dcba5d5cb))
|
||||
* Upgrade @parse/push-adapter from 6.7.1 to 6.8.0 ([#9489](https://github.com/parse-community/parse-server/issues/9489)) ([286aa66](https://github.com/parse-community/parse-server/commit/286aa664ac8830d36c3e70d2316917d15f0b6df5))
|
||||
|
||||
# [7.3.0-beta.1](https://github.com/parse-community/parse-server/compare/7.2.0...7.3.0-beta.1) (2024-10-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Custom object ID allows to acquire role privileges ([GHSA-8xq9-g7ch-35hg](https://github.com/parse-community/parse-server/security/advisories/GHSA-8xq9-g7ch-35hg)) ([#9317](https://github.com/parse-community/parse-server/issues/9317)) ([13ee52f](https://github.com/parse-community/parse-server/commit/13ee52f0d19ef3a3524b3d79aea100e587eb3cfc))
|
||||
* Parse Server `databaseOptions` nested keys incorrectly identified as invalid ([#9213](https://github.com/parse-community/parse-server/issues/9213)) ([77206d8](https://github.com/parse-community/parse-server/commit/77206d804443cfc1618c24f8961bd677de9920c0))
|
||||
* Parse Server installation fails due to post install script incorrectly parsing required min. Node version ([#9216](https://github.com/parse-community/parse-server/issues/9216)) ([0fa82a5](https://github.com/parse-community/parse-server/commit/0fa82a54fe38ec14e8054339285d3db71a8624c8))
|
||||
* Parse Server option `maxLogFiles` doesn't recognize day duration literals such as `1d` to mean 1 day ([#9215](https://github.com/parse-community/parse-server/issues/9215)) ([0319cee](https://github.com/parse-community/parse-server/commit/0319cee2dbf65e90bad377af1ed14ea25c595bf5))
|
||||
* Security upgrade path-to-regexp from 6.2.1 to 6.3.0 ([#9314](https://github.com/parse-community/parse-server/issues/9314)) ([8b7fe69](https://github.com/parse-community/parse-server/commit/8b7fe699c1c376ecd8cc1c97cce8e704ee41f28a))
|
||||
|
||||
### Features
|
||||
|
||||
* Add atomic operations for Cloud Config parameters ([#9219](https://github.com/parse-community/parse-server/issues/9219)) ([35cadf9](https://github.com/parse-community/parse-server/commit/35cadf9b8324879fb7309ba5d7ea46f2c722d614))
|
||||
* Add Cloud Code triggers `Parse.Cloud.beforeSave` and `Parse.Cloud.afterSave` for Parse Config ([#9232](https://github.com/parse-community/parse-server/issues/9232)) ([90a1e4a](https://github.com/parse-community/parse-server/commit/90a1e4a200423d644efb3f0ba2fba4b99f5cf954))
|
||||
* Add Node 22 support ([#9187](https://github.com/parse-community/parse-server/issues/9187)) ([7778471](https://github.com/parse-community/parse-server/commit/7778471999c7e42236ce404229660d80ecc2acd6))
|
||||
* Add support for asynchronous invocation of `FilesAdapter.getFileLocation` ([#9271](https://github.com/parse-community/parse-server/issues/9271)) ([1a2da40](https://github.com/parse-community/parse-server/commit/1a2da4055abe831b3017172fb75e16d7a8093873))
|
||||
|
||||
# [7.2.0-beta.1](https://github.com/parse-community/parse-server/compare/7.1.0...7.2.0-beta.1) (2024-07-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Invalid push notification tokens are not cleaned up from database for FCM API v2 ([#9173](https://github.com/parse-community/parse-server/issues/9173)) ([284da09](https://github.com/parse-community/parse-server/commit/284da09f4546356b37511a589fb5f64a3efffe79))
|
||||
|
||||
### Features
|
||||
|
||||
* Add support for dot notation on array fields of Parse Object ([#9115](https://github.com/parse-community/parse-server/issues/9115)) ([cf4c880](https://github.com/parse-community/parse-server/commit/cf4c8807b9da87a0a5f9c94e5bdfcf17cda80cf4))
|
||||
* Upgrade to @parse/push-adapter 6.4.0 ([#9182](https://github.com/parse-community/parse-server/issues/9182)) ([ef1634b](https://github.com/parse-community/parse-server/commit/ef1634bf1f360429108d29b08032fc7961ff96a1))
|
||||
* Upgrade to Parse JS SDK 5.3.0 ([#9180](https://github.com/parse-community/parse-server/issues/9180)) ([dca187f](https://github.com/parse-community/parse-server/commit/dca187f91b93cbb362b22a3fb9ee38451799ff13))
|
||||
|
||||
# [7.1.0-beta.1](https://github.com/parse-community/parse-server/compare/7.0.0...7.1.0-beta.1) (2024-06-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `Parse.Cloud.startJob` and `Parse.Push.send` not returning status ID when setting Parse Server option `directAccess: true` ([#8766](https://github.com/parse-community/parse-server/issues/8766)) ([5b0efb2](https://github.com/parse-community/parse-server/commit/5b0efb22efe94c47f243cf8b1e6407ed5c5a67d3))
|
||||
* `Required` option not handled correctly for special fields (File, GeoPoint, Polygon) on GraphQL API mutations ([#8915](https://github.com/parse-community/parse-server/issues/8915)) ([907ad42](https://github.com/parse-community/parse-server/commit/907ad4267c228d26cfcefe7848b30ce85ba7ff8f))
|
||||
* Facebook Limited Login not working due to incorrect domain in JWT validation ([#9122](https://github.com/parse-community/parse-server/issues/9122)) ([9d0bd2b](https://github.com/parse-community/parse-server/commit/9d0bd2badd6e5f7429d1af00b118225752e5d86a))
|
||||
* Live query throws error when constraint `notEqualTo` is set to `null` ([#8835](https://github.com/parse-community/parse-server/issues/8835)) ([11d3e48](https://github.com/parse-community/parse-server/commit/11d3e484df862224c15d20f6171514948981ea90))
|
||||
* Parse Server option `extendSessionOnUse` not working for session lengths < 24 hours ([#9113](https://github.com/parse-community/parse-server/issues/9113)) ([0a054e6](https://github.com/parse-community/parse-server/commit/0a054e6b541fd5ab470bf025665f5f7d2acedaa0))
|
||||
* Rate limiting can fail when using Parse Server option `rateLimit.redisUrl` with clusters ([#8632](https://github.com/parse-community/parse-server/issues/8632)) ([c277739](https://github.com/parse-community/parse-server/commit/c27773962399f8e27691e3b8087e7e1d59516efd))
|
||||
* SQL injection when using Parse Server with PostgreSQL; fixes security vulnerability [GHSA-c2hr-cqg6-8j6r](https://github.com/parse-community/parse-server/security/advisories/GHSA-c2hr-cqg6-8j6r) ([#9167](https://github.com/parse-community/parse-server/issues/9167)) ([2edf1e4](https://github.com/parse-community/parse-server/commit/2edf1e4c0363af01e97a7fbc97694f851b7d1ff3))
|
||||
|
||||
### Features
|
||||
|
||||
* Add `silent` log level for Cloud Code ([#8803](https://github.com/parse-community/parse-server/issues/8803)) ([5f81efb](https://github.com/parse-community/parse-server/commit/5f81efb42964c4c2fa8bcafee9446a0122e3ce21))
|
||||
* Add server security check status `security.enableCheck` to Features Router ([#8679](https://github.com/parse-community/parse-server/issues/8679)) ([b07ec15](https://github.com/parse-community/parse-server/commit/b07ec153825882e97cc48dc84072c7f549f3238b))
|
||||
* Prevent Parse Server start in case of unknown option in server configuration ([#8987](https://github.com/parse-community/parse-server/issues/8987)) ([8758e6a](https://github.com/parse-community/parse-server/commit/8758e6abb9dbb68757bddcbd332ad25100c24a0e))
|
||||
* Upgrade to @parse/push-adapter 6.0.0 ([#9066](https://github.com/parse-community/parse-server/issues/9066)) ([18bdbf8](https://github.com/parse-community/parse-server/commit/18bdbf89c53a57648891ef582614ba7c2941e587))
|
||||
* Upgrade to @parse/push-adapter 6.2.0 ([#9127](https://github.com/parse-community/parse-server/issues/9127)) ([ca20496](https://github.com/parse-community/parse-server/commit/ca20496f28e5ec1294a7a23c8559df82b79b2a04))
|
||||
* Upgrade to Parse JS SDK 5.2.0 ([#9128](https://github.com/parse-community/parse-server/issues/9128)) ([665b8d5](https://github.com/parse-community/parse-server/commit/665b8d52d6cf5275179a5e1fb132c934edb53ecc))
|
||||
|
||||
# [7.0.0-beta.1](https://github.com/parse-community/parse-server/compare/6.5.0-beta.1...7.0.0-beta.1) (2024-03-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* CacheAdapter does not connect when using a CacheAdapter with a JSON config ([#8633](https://github.com/parse-community/parse-server/issues/8633)) ([720d24e](https://github.com/parse-community/parse-server/commit/720d24e18540da35d50957f17be878316ec30318))
|
||||
* Conditional email verification not working in some cases if `verifyUserEmails`, `preventLoginWithUnverifiedEmail` set to functions ([#8838](https://github.com/parse-community/parse-server/issues/8838)) ([8e7a6b1](https://github.com/parse-community/parse-server/commit/8e7a6b1480c0117e6c73e7adc5a6619115a04e85))
|
||||
* Deny request if master key is not set in Parse Server option `masterKeyIps` regardless of ACL and CLP ([#8957](https://github.com/parse-community/parse-server/issues/8957)) ([a7b5b38](https://github.com/parse-community/parse-server/commit/a7b5b38418cbed9be3f4a7665f25b97f592663e1))
|
||||
* Docker image not published to Docker Hub on new release ([#8905](https://github.com/parse-community/parse-server/issues/8905)) ([a2ac8d1](https://github.com/parse-community/parse-server/commit/a2ac8d133c71cd7b61e5ef59c4be915cfea85db6))
|
||||
* Docker version releases by removing arm/v6 and arm/v7 support ([#8976](https://github.com/parse-community/parse-server/issues/8976)) ([1f62dd0](https://github.com/parse-community/parse-server/commit/1f62dd0f4e107b22a387692558a042ee26ce8703))
|
||||
* GraphQL file upload fails in case of use of pointer or relation ([#8721](https://github.com/parse-community/parse-server/issues/8721)) ([1aba638](https://github.com/parse-community/parse-server/commit/1aba6382c873fb489d4a898d301e6da9fb6aa61b))
|
||||
* Improve PostgreSQL injection detection; fixes security vulnerability [GHSA-6927-3vr9-fxf2](https://github.com/parse-community/parse-server/security/advisories/GHSA-6927-3vr9-fxf2) which affects Parse Server deployments using a Postgres database ([#8961](https://github.com/parse-community/parse-server/issues/8961)) ([cbefe77](https://github.com/parse-community/parse-server/commit/cbefe770a7260b54748a058b8a7389937dc35833))
|
||||
* Incomplete user object in `verifyEmail` function if both username and email are changed ([#8889](https://github.com/parse-community/parse-server/issues/8889)) ([1eb95ae](https://github.com/parse-community/parse-server/commit/1eb95aeb41a96250e582d79a703f6adcb403c08b))
|
||||
* Parse Server option `emailVerifyTokenReuseIfValid: true` generates new token on every email verification request ([#8885](https://github.com/parse-community/parse-server/issues/8885)) ([0023ce4](https://github.com/parse-community/parse-server/commit/0023ce448a5e9423337d0e1a25648bde1156bc95))
|
||||
* Parse Server option `fileExtensions` default value rejects file extensions that are less than 3 or more than 4 characters long ([#8699](https://github.com/parse-community/parse-server/issues/8699)) ([2760381](https://github.com/parse-community/parse-server/commit/276038118377c2b22381bcd8d30337203822121b))
|
||||
* Server crashes on invalid Cloud Function or Cloud Job name; fixes security vulnerability [GHSA-6hh7-46r2-vf29](https://github.com/parse-community/parse-server/security/advisories/GHSA-6hh7-46r2-vf29) ([#9024](https://github.com/parse-community/parse-server/issues/9024)) ([9f6e342](https://github.com/parse-community/parse-server/commit/9f6e3429d3b326cf4e2994733c618d08032fac6e))
|
||||
* Server crashes when receiving an array of `Parse.Pointer` in the request body ([#8784](https://github.com/parse-community/parse-server/issues/8784)) ([66e3603](https://github.com/parse-community/parse-server/commit/66e36039d8af654cfa0284666c0ddd94975dcb52))
|
||||
* Username is `undefined` in email verification link on email change ([#8887](https://github.com/parse-community/parse-server/issues/8887)) ([e315c13](https://github.com/parse-community/parse-server/commit/e315c137bf41bedfa8f0df537f2c3f6ab45b7e60))
|
||||
|
||||
### Features
|
||||
|
||||
* Add `installationId` to arguments for `verifyUserEmails`, `preventLoginWithUnverifiedEmail` ([#8836](https://github.com/parse-community/parse-server/issues/8836)) ([a22dbe1](https://github.com/parse-community/parse-server/commit/a22dbe16d5ac0090608f6caaf0ebd134925b7fd4))
|
||||
* Add `installationId`, `ip`, `resendRequest` to arguments passed to `verifyUserEmails` on verification email request ([#8873](https://github.com/parse-community/parse-server/issues/8873)) ([8adcbee](https://github.com/parse-community/parse-server/commit/8adcbee11283d3e95179ca2047e2615f52c18806))
|
||||
* Add `Parse.User` as function parameter to Parse Server options `verifyUserEmails`, `preventLoginWithUnverifiedEmail` on login ([#8850](https://github.com/parse-community/parse-server/issues/8850)) ([972f630](https://github.com/parse-community/parse-server/commit/972f6300163b3cd7d95eeb95986e8322c95f821c))
|
||||
* Add password validation via POST request for user with unverified email using master key and option `ignoreEmailVerification` ([#8895](https://github.com/parse-community/parse-server/issues/8895)) ([633a9d2](https://github.com/parse-community/parse-server/commit/633a9d25e4253e2125bc93c02ee8a37e0f5f7b83))
|
||||
* Add support for MongoDB 7 ([#8761](https://github.com/parse-community/parse-server/issues/8761)) ([3de8494](https://github.com/parse-community/parse-server/commit/3de8494a221991dfd10a74e0a2dc89576265c9b7))
|
||||
* Add support for MongoDB query comment ([#8928](https://github.com/parse-community/parse-server/issues/8928)) ([2170962](https://github.com/parse-community/parse-server/commit/2170962a50fa353ed85eda3f11dce7ee3647b087))
|
||||
* Add support for Node 20, drop support for Node 14, 16 ([#8907](https://github.com/parse-community/parse-server/issues/8907)) ([ced4872](https://github.com/parse-community/parse-server/commit/ced487246ea0ef72a8aa014991f003209b34841e))
|
||||
* Add support for Postgres 16 ([#8898](https://github.com/parse-community/parse-server/issues/8898)) ([99489b2](https://github.com/parse-community/parse-server/commit/99489b22e4f0982e6cb39992974b51aa8d3a31e4))
|
||||
* Allow `Parse.Session.current` on expired session token instead of throwing error ([#8722](https://github.com/parse-community/parse-server/issues/8722)) ([f9dde4a](https://github.com/parse-community/parse-server/commit/f9dde4a9f8a90c63f71172c9bc515b0f6c6d2e4a))
|
||||
* Deprecation DEPPS5: Config option `allowClientClassCreation` defaults to `false` ([#8849](https://github.com/parse-community/parse-server/issues/8849)) ([29624e0](https://github.com/parse-community/parse-server/commit/29624e0fae17161cd412ae58d35a195cfa286cad))
|
||||
* Deprecation DEPPS6: Authentication adapters disabled by default ([#8858](https://github.com/parse-community/parse-server/issues/8858)) ([0cf58eb](https://github.com/parse-community/parse-server/commit/0cf58eb8d60c8e5f485764e154f3214c49eee430))
|
||||
* Deprecation DEPPS7: Remove deprecated Cloud Code file trigger syntax ([#8855](https://github.com/parse-community/parse-server/issues/8855)) ([4e6a375](https://github.com/parse-community/parse-server/commit/4e6a375b5184ae0f7aa256a921eca4021c609435))
|
||||
* Deprecation DEPPS8: Parse Server option `allowExpiredAuthDataToken` defaults to `false` ([#8860](https://github.com/parse-community/parse-server/issues/8860)) ([e29845f](https://github.com/parse-community/parse-server/commit/e29845f8dacac09ce3093d75c0d92330c24389e8))
|
||||
* Deprecation DEPPS9: LiveQuery `fields` option is renamed to `keys` ([#8852](https://github.com/parse-community/parse-server/issues/8852)) ([38983e8](https://github.com/parse-community/parse-server/commit/38983e8e9b5cdbd006f311a2338103624137d013))
|
||||
* Node process exits with error code 1 on uncaught exception to allow custom uncaught exception handling ([#8894](https://github.com/parse-community/parse-server/issues/8894)) ([70c280c](https://github.com/parse-community/parse-server/commit/70c280ca578ff28b5acf92f37fbe06d42a5b34ca))
|
||||
* Switch GraphQL server from Yoga v2 to Apollo v4 ([#8959](https://github.com/parse-community/parse-server/issues/8959)) ([105ae7c](https://github.com/parse-community/parse-server/commit/105ae7c8a57d5a650b243174a80c26bf6db16e28))
|
||||
* Upgrade Parse Server Push Adapter to 5.0.2 ([#8813](https://github.com/parse-community/parse-server/issues/8813)) ([6ef1986](https://github.com/parse-community/parse-server/commit/6ef1986c03a1d84b7e11c05851e5bf9688d88740))
|
||||
* Upgrade to Parse JS SDK 5 ([#9022](https://github.com/parse-community/parse-server/issues/9022)) ([ad4aa83](https://github.com/parse-community/parse-server/commit/ad4aa83983205a0e27639f6ee6a4a5963b67e4b8))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Improved IP validation performance for `masterKeyIPs`, `maintenanceKeyIPs` ([#8510](https://github.com/parse-community/parse-server/issues/8510)) ([b87daba](https://github.com/parse-community/parse-server/commit/b87daba0671a1b0b7b8d63bc671d665c91a04522))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* The Parse Server option `allowClientClassCreation` defaults to `false`. ([29624e0](29624e0))
|
||||
* A request using the master key will now be rejected as unauthorized if the IP from which the request originates is not set in the Parse Server option `masterKeyIps`, even if the request does not require the master key permission, for example for a public object in a public class class. ([a7b5b38](a7b5b38))
|
||||
* Node process now exits with code 1 on uncaught exceptions, enabling custom handlers that were blocked by Parse Server's default behavior of re-throwing errors. This change may lead to automatic process restarts by the environment, unlike before. ([70c280c](70c280c))
|
||||
* Authentication adapters are disabled by default; to use an authentication adapter it needs to be explicitly enabled in the Parse Server authentication adapter option `auth.<provider>.enabled: true` ([0cf58eb](0cf58eb))
|
||||
* Parse Server option `allowExpiredAuthDataToken` defaults to `false`; a 3rd party authentication token will be validated every time the user tries to log in and the login will fail if the token has expired; the effect of this change may differ for different authentication adapters, depending on the token lifetime and the token refresh logic of the adapter ([e29845f](e29845f))
|
||||
* LiveQuery `fields` option is renamed to `keys` ([38983e8](38983e8))
|
||||
* Cloud Code file trigger syntax has been aligned with object trigger syntax, for example `Parse.Cloud.beforeDeleteFile'` has been changed to `Parse.Cloud.beforeDelete(Parse.File, (request) => {})'` ([4e6a375](4e6a375))
|
||||
* Removes support for Node 14 and 16 ([ced4872](ced4872))
|
||||
* Removes support for Postgres 11 and 12 ([99489b2](99489b2))
|
||||
* The `Parse.User` passed as argument if `verifyUserEmails` is set to a function is renamed from `user` to `object` for consistency with invocations of `verifyUserEmails` on signup or login; the user object is not a plain JavaScript object anymore but an instance of `Parse.User` ([8adcbee](8adcbee))
|
||||
* `Parse.Session.current()` no longer throws an error if the session token is expired, but instead returns the session token with its expiration date to allow checking its validity ([f9dde4a](f9dde4a))
|
||||
* `Parse.Query` no longer supports the BSON type `code`; although this feature was never officially documented, its removal is announced as a breaking change to protect deployments where it might be in use. ([3de8494](3de8494))
|
||||
|
||||
# [6.5.0-beta.1](https://github.com/parse-community/parse-server/compare/6.4.0...6.5.0-beta.1) (2023-11-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Context not passed to Cloud Code Trigger `beforeFind` when using `Parse.Query.include` ([#8765](https://github.com/parse-community/parse-server/issues/8765)) ([7d32d89](https://github.com/parse-community/parse-server/commit/7d32d8934f3ae7af7a7d8b9cc6a829c7d73973d3))
|
||||
* Parse Server option `fileUpload.fileExtensions` fails to determine file extension if filename contains multiple dots ([#8754](https://github.com/parse-community/parse-server/issues/8754)) ([3d6d50e](https://github.com/parse-community/parse-server/commit/3d6d50e0afff18b95fb906914e2cebd3839b517a))
|
||||
* Security bump @babel/traverse from 7.20.5 to 7.23.2 ([#8777](https://github.com/parse-community/parse-server/issues/8777)) ([2d6b3d1](https://github.com/parse-community/parse-server/commit/2d6b3d18499179e99be116f25c0850d3f449509c))
|
||||
* Security upgrade graphql from 16.6.0 to 16.8.1 ([#8758](https://github.com/parse-community/parse-server/issues/8758)) ([71dfd8a](https://github.com/parse-community/parse-server/commit/71dfd8a7ece8c0dd1a66d03bb9420cfd39f4f9b1))
|
||||
|
||||
### Features
|
||||
|
||||
* Add `$setOnInsert` operator to `Parse.Server.database.update` ([#8791](https://github.com/parse-community/parse-server/issues/8791)) ([f630a45](https://github.com/parse-community/parse-server/commit/f630a45aa5e87bc73a81fded061400c199b71a29))
|
||||
* Add compatibility for MongoDB Atlas Serverless and AWS Amazon DocumentDB with collation options `enableCollationCaseComparison`, `transformEmailToLowercase`, `transformUsernameToLowercase` ([#8805](https://github.com/parse-community/parse-server/issues/8805)) ([09fbeeb](https://github.com/parse-community/parse-server/commit/09fbeebba8870e7cf371fb84371a254c7b368620))
|
||||
* Add context to Cloud Code Triggers `beforeLogin` and `afterLogin` ([#8724](https://github.com/parse-community/parse-server/issues/8724)) ([a9c34ef](https://github.com/parse-community/parse-server/commit/a9c34ef1e2c78a42fb8b5fa8d569b7677c74919d))
|
||||
* Allow setting `createdAt` and `updatedAt` during `Parse.Object` creation with maintenance key ([#8696](https://github.com/parse-community/parse-server/issues/8696)) ([77bbfb3](https://github.com/parse-community/parse-server/commit/77bbfb3f186f5651c33ba152f04cff95128eaf2d))
|
||||
|
||||
# [6.4.0-beta.1](https://github.com/parse-community/parse-server/compare/6.3.0...6.4.0-beta.1) (2023-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Parse Server option `fileUpload.fileExtensions` does not work with an array of extensions ([#8688](https://github.com/parse-community/parse-server/issues/8688)) ([6a4a00c](https://github.com/parse-community/parse-server/commit/6a4a00ca7af1163ea74b047b85cd6817366b824b))
|
||||
* Redis 4 does not reconnect after unhandled error ([#8706](https://github.com/parse-community/parse-server/issues/8706)) ([2b3d4e5](https://github.com/parse-community/parse-server/commit/2b3d4e5d3c85cd142f85af68dec51a8523548d49))
|
||||
* Remove config logging when launching Parse Server via CLI ([#8710](https://github.com/parse-community/parse-server/issues/8710)) ([ae68f0c](https://github.com/parse-community/parse-server/commit/ae68f0c31b741eeb83379c905c7ddfaa124436ec))
|
||||
* Server does not start via CLI when `auth` option is set ([#8666](https://github.com/parse-community/parse-server/issues/8666)) ([4e2000b](https://github.com/parse-community/parse-server/commit/4e2000bc563324389584ace3c090a5c1a7796a64))
|
||||
|
||||
### Features
|
||||
|
||||
* Add conditional email verification via dynamic Parse Server options `verifyUserEmails`, `sendUserEmailVerification` that now accept functions ([#8425](https://github.com/parse-community/parse-server/issues/8425)) ([44acd6d](https://github.com/parse-community/parse-server/commit/44acd6d9ed157ad4842200c9d01f9c77a05fec3a))
|
||||
* Add property `Parse.Server.version` to determine current version of Parse Server in Cloud Code ([#8670](https://github.com/parse-community/parse-server/issues/8670)) ([a9d376b](https://github.com/parse-community/parse-server/commit/a9d376b61f5b07806eafbda91c4e36c322f09298))
|
||||
* Add TOTP authentication adapter ([#8457](https://github.com/parse-community/parse-server/issues/8457)) ([cc079a4](https://github.com/parse-community/parse-server/commit/cc079a40f6849a0e9bc6fdc811e8649ecb67b589))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Improve performance of recursive pointer iterations ([#8741](https://github.com/parse-community/parse-server/issues/8741)) ([45a3ed0](https://github.com/parse-community/parse-server/commit/45a3ed0fcf2c0170607505a1550fb15896e705fd))
|
||||
|
||||
# [6.3.0-beta.1](https://github.com/parse-community/parse-server/compare/6.2.0...6.3.0-beta.1) (2023-06-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Cloud Code Trigger `afterSave` executes even if not set ([#8520](https://github.com/parse-community/parse-server/issues/8520)) ([afd0515](https://github.com/parse-community/parse-server/commit/afd0515e207bd947840579d3f245980dffa6f804))
|
||||
* GridFS file storage doesn't work with certain `enableSchemaHooks` settings ([#8467](https://github.com/parse-community/parse-server/issues/8467)) ([d4cda4b](https://github.com/parse-community/parse-server/commit/d4cda4b26c9bde8c812549b8780bea1cfabdb394))
|
||||
* Inaccurate table total row count for PostgreSQL ([#8511](https://github.com/parse-community/parse-server/issues/8511)) ([0823a02](https://github.com/parse-community/parse-server/commit/0823a02fbf80bc88dc403bc47e9f5c6597ea78b4))
|
||||
* LiveQuery server is not shut down properly when `handleShutdown` is called ([#8491](https://github.com/parse-community/parse-server/issues/8491)) ([967700b](https://github.com/parse-community/parse-server/commit/967700bdbc94c74f75ba84d2b3f4b9f3fd2dca0b))
|
||||
* Rate limit feature is incompatible with Node 14 ([#8578](https://github.com/parse-community/parse-server/issues/8578)) ([f911f2c](https://github.com/parse-community/parse-server/commit/f911f2cd3a8c45cd326272dcd681532764a3761e))
|
||||
* Unnecessary log entries by `extendSessionOnUse` ([#8562](https://github.com/parse-community/parse-server/issues/8562)) ([fd6a007](https://github.com/parse-community/parse-server/commit/fd6a0077f2e5cf83d65e52172ae5a950ab0f1eae))
|
||||
|
||||
### Features
|
||||
|
||||
* `extendSessionOnUse` to automatically renew Parse Sessions ([#8505](https://github.com/parse-community/parse-server/issues/8505)) ([6f885d3](https://github.com/parse-community/parse-server/commit/6f885d36b94902fdfea873fc554dee83589e6029))
|
||||
* Add new Parse Server option `preventSignupWithUnverifiedEmail` to prevent returning a user without session token on sign-up with unverified email address ([#8451](https://github.com/parse-community/parse-server/issues/8451)) ([82da308](https://github.com/parse-community/parse-server/commit/82da30842a55980aa90cb7680fbf6db37ee16dab))
|
||||
* Add option to change the log level of logs emitted by Cloud Functions ([#8530](https://github.com/parse-community/parse-server/issues/8530)) ([2caea31](https://github.com/parse-community/parse-server/commit/2caea310be412d82b04a85716bc769ccc410316d))
|
||||
* Add support for `$eq` query constraint in LiveQuery ([#8614](https://github.com/parse-community/parse-server/issues/8614)) ([656d673](https://github.com/parse-community/parse-server/commit/656d673cf5dea354e4f2b3d4dc2b29a41d311b3e))
|
||||
* Add zones for rate limiting by `ip`, `user`, `session`, `global` ([#8508](https://github.com/parse-community/parse-server/issues/8508)) ([03fba97](https://github.com/parse-community/parse-server/commit/03fba97e0549bfcaeee9f2fa4c9905dbcc91840e))
|
||||
* Allow `Parse.Object` pointers in Cloud Code arguments ([#8490](https://github.com/parse-community/parse-server/issues/8490)) ([28aeda3](https://github.com/parse-community/parse-server/commit/28aeda3f160efcbbcf85a85484a8d26567fa9761))
|
||||
|
||||
### Reverts
|
||||
|
||||
* fix: Inaccurate table total row count for PostgreSQL ([6722110](https://github.com/parse-community/parse-server/commit/6722110f203bc5fdcaa68cdf091cf9e7b48d1cff))
|
||||
|
||||
# [6.1.0-beta.2](https://github.com/parse-community/parse-server/compare/6.1.0-beta.1...6.1.0-beta.2) (2023-05-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* LiveQuery can return incorrectly formatted date ([#8456](https://github.com/parse-community/parse-server/issues/8456)) ([4ce135a](https://github.com/parse-community/parse-server/commit/4ce135a4fe930776044bc8fd786a4e17a0144e03))
|
||||
* Nested date is incorrectly decoded as empty object `{}` when fetching a Parse Object ([#8446](https://github.com/parse-community/parse-server/issues/8446)) ([22d2446](https://github.com/parse-community/parse-server/commit/22d2446dfea2bc339affc20535d181097e152acf))
|
||||
* Parameters missing in `afterFind` trigger of authentication adapters ([#8458](https://github.com/parse-community/parse-server/issues/8458)) ([ce34747](https://github.com/parse-community/parse-server/commit/ce34747e8af54cb0b6b975da38f779a5955d2d59))
|
||||
* Rate limiting across multiple servers via Redis not working ([#8469](https://github.com/parse-community/parse-server/issues/8469)) ([d9e347d](https://github.com/parse-community/parse-server/commit/d9e347d7413f30f58ffbb8397fc8b5ae23be6ff0))
|
||||
|
||||
### Features
|
||||
|
||||
* Add `afterFind` trigger to authentication adapters ([#8444](https://github.com/parse-community/parse-server/issues/8444)) ([c793bb8](https://github.com/parse-community/parse-server/commit/c793bb88e7485743c7ceb65fe419cde75833ff33))
|
||||
* Add rate limiting across multiple servers via Redis ([#8394](https://github.com/parse-community/parse-server/issues/8394)) ([34833e4](https://github.com/parse-community/parse-server/commit/34833e42eec08b812b733be78df0535ab0e096b6))
|
||||
* Allow multiple origins for header `Access-Control-Allow-Origin` ([#8517](https://github.com/parse-community/parse-server/issues/8517)) ([4f15539](https://github.com/parse-community/parse-server/commit/4f15539ac244aa2d393ac5177f7604b43f69e271))
|
||||
* Export `AuthAdapter` to make it available for extension with custom authentication adapters ([#8443](https://github.com/parse-community/parse-server/issues/8443)) ([40c1961](https://github.com/parse-community/parse-server/commit/40c196153b8efa12ae384c1c0092b2ed60a260d6))
|
||||
|
||||
# [6.1.0-beta.1](https://github.com/parse-community/parse-server/compare/6.0.0...6.1.0-beta.1) (2023-03-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Security upgrade jsonwebtoken to 9.0.0 ([#8420](https://github.com/parse-community/parse-server/issues/8420)) ([f5bfe45](https://github.com/parse-community/parse-server/commit/f5bfe4571e82b2b7440d41f3cff0d49937398164))
|
||||
|
||||
### Features
|
||||
|
||||
* Add option `schemaCacheTtl` for schema cache pulling as alternative to `enableSchemaHooks` ([#8436](https://github.com/parse-community/parse-server/issues/8436)) ([b3b76de](https://github.com/parse-community/parse-server/commit/b3b76de71b1d4265689d052e7837c38ec1fa4323))
|
||||
* Add Parse Server option `resetPasswordSuccessOnInvalidEmail` to choose success or error response on password reset with invalid email ([#7551](https://github.com/parse-community/parse-server/issues/7551)) ([e5d610e](https://github.com/parse-community/parse-server/commit/e5d610e5e487ddab86409409ac3d7362aba8f59b))
|
||||
* Deprecate LiveQuery `fields` option in favor of `keys` for semantic consistency ([#8388](https://github.com/parse-community/parse-server/issues/8388)) ([a49e323](https://github.com/parse-community/parse-server/commit/a49e323d5ae640bff1c6603ec37fdaddb9328dd1))
|
||||
|
||||
# [6.0.0-beta.1](https://github.com/parse-community/parse-server/compare/5.4.0...6.0.0-beta.1) (2023-01-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `ParseServer.verifyServerUrl` may fail if server response headers are missing; remove unnecessary logging ([#8391](https://github.com/parse-community/parse-server/issues/8391)) ([1c37a7c](https://github.com/parse-community/parse-server/commit/1c37a7cd0715949a70b220a629071c7dab7d5e7b))
|
||||
* Cloud Code trigger `beforeSave` does not work with `Parse.Role` ([#8320](https://github.com/parse-community/parse-server/issues/8320)) ([f29d972](https://github.com/parse-community/parse-server/commit/f29d9720e9b37918fd885c97a31e34c42750e724))
|
||||
* ES6 modules do not await the import of Cloud Code files ([#8368](https://github.com/parse-community/parse-server/issues/8368)) ([a7bd180](https://github.com/parse-community/parse-server/commit/a7bd180cddd784c8735622f22e012c342ad535fb))
|
||||
* Nested objects are encoded incorrectly for MongoDB ([#8209](https://github.com/parse-community/parse-server/issues/8209)) ([1412666](https://github.com/parse-community/parse-server/commit/1412666f75829612de6fb9d7ccae35761c9b75cb))
|
||||
* Parse Server option `masterKeyIps` does not include localhost by default for IPv6 ([#8322](https://github.com/parse-community/parse-server/issues/8322)) ([ab82635](https://github.com/parse-community/parse-server/commit/ab82635b0d4cf323a07ddee51fee587b43dce95c))
|
||||
* Rate limiter may reject requests that contain a session token ([#8399](https://github.com/parse-community/parse-server/issues/8399)) ([c114dc8](https://github.com/parse-community/parse-server/commit/c114dc8831055d74187b9dfb4c9eeb558520237c))
|
||||
* Remove Node 12 and Node 17 support ([#8279](https://github.com/parse-community/parse-server/issues/8279)) ([2546cc8](https://github.com/parse-community/parse-server/commit/2546cc8572bea6610cb9b3c7401d9afac0e3c1d6))
|
||||
* Schema without class level permissions may cause error ([#8409](https://github.com/parse-community/parse-server/issues/8409)) ([aa2cd51](https://github.com/parse-community/parse-server/commit/aa2cd51b703388d925e4572e5c2b2d883c68e49c))
|
||||
* The client IP address may be determined incorrectly in some cases; this fixes a security vulnerability in which the Parse Server option `masterKeyIps` may be circumvented, see [GHSA-vm5r-c87r-pf6x](https://github.com/parse-community/parse-server/security/advisories/GHSA-vm5r-c87r-pf6x) ([#8372](https://github.com/parse-community/parse-server/issues/8372)) ([892040d](https://github.com/parse-community/parse-server/commit/892040dc2f82a3e2abe2824e4b553521b6f894de))
|
||||
* Throwing error in Cloud Code Triggers `afterLogin`, `afterLogout` crashes server ([#8280](https://github.com/parse-community/parse-server/issues/8280)) ([130d290](https://github.com/parse-community/parse-server/commit/130d29074e3f763460e5685d0b9059e5a333caff))
|
||||
|
||||
### Features
|
||||
|
||||
* Access the internal scope of Parse Server using the new `maintenanceKey`; the internal scope contains unofficial and undocumented fields (prefixed with underscore `_`) which are used internally by Parse Server; you may want to manipulate these fields for out-of-band changes such as data migration or correction tasks; changes within the internal scope of Parse Server may happen at any time without notice or changelog entry, it is therefore recommended to look at the source code of Parse Server to understand the effects of manipulating internal fields before using the key; it is discouraged to use the `maintenanceKey` for routine operations in a production environment; see [access scopes](https://github.com/parse-community/parse-server#access-scopes) ([#8212](https://github.com/parse-community/parse-server/issues/8212)) ([f3bcc93](https://github.com/parse-community/parse-server/commit/f3bcc9365cd6f08b0a32c132e8e5ff6d1b650863))
|
||||
* Adapt `verifyServerUrl` for new asynchronous Parse Server start-up states ([#8366](https://github.com/parse-community/parse-server/issues/8366)) ([ffa4974](https://github.com/parse-community/parse-server/commit/ffa4974158615fbff4a2692b9db41dcb50d3f77b))
|
||||
* Add `ParseQuery.watch` to trigger LiveQuery only on update of specific fields ([#8028](https://github.com/parse-community/parse-server/issues/8028)) ([fc92faa](https://github.com/parse-community/parse-server/commit/fc92faac75107b3392eeddd916c4c5b45e3c5e0c))
|
||||
* Add Node 19 support ([#8363](https://github.com/parse-community/parse-server/issues/8363)) ([a4990dc](https://github.com/parse-community/parse-server/commit/a4990dcd29abcb4442f3c424aff482a0a116160f))
|
||||
* Add option to change the log level of the logs emitted by triggers ([#8328](https://github.com/parse-community/parse-server/issues/8328)) ([8f3b694](https://github.com/parse-community/parse-server/commit/8f3b694e39d4a966567e50dbea4d62e954fa5c06))
|
||||
* Add request rate limiter based on IP address ([#8174](https://github.com/parse-community/parse-server/issues/8174)) ([6c79f6a](https://github.com/parse-community/parse-server/commit/6c79f6a69e25e47846e3b0685d6bdfd6b91086b1))
|
||||
* Asynchronous initialization of Parse Server ([#8232](https://github.com/parse-community/parse-server/issues/8232)) ([99fcf45](https://github.com/parse-community/parse-server/commit/99fcf45e55c368de2345b0c4d780e70e0adf0e15))
|
||||
* Improve authentication adapter interface to support multi-factor authentication (MFA), authentication challenges, and provide a more powerful interface for writing custom authentication adapters ([#8156](https://github.com/parse-community/parse-server/issues/8156)) ([5bbf9ca](https://github.com/parse-community/parse-server/commit/5bbf9cade9a527787fd1002072d4013ab5d8db2b))
|
||||
* Reduce Docker image size by improving stages ([#8359](https://github.com/parse-community/parse-server/issues/8359)) ([40810b4](https://github.com/parse-community/parse-server/commit/40810b48ebde8b1f21d2448a3a4de0585b1b5e34))
|
||||
* Remove deprecation `DEPPS1`: Native MongoDB syntax in aggregation pipeline ([#8362](https://github.com/parse-community/parse-server/issues/8362)) ([d0d30c4](https://github.com/parse-community/parse-server/commit/d0d30c4f1394f563724644a8fc81734be538a2c0))
|
||||
* Remove deprecation `DEPPS2`: Config option `directAccess` defaults to true ([#8284](https://github.com/parse-community/parse-server/issues/8284)) ([f535ee6](https://github.com/parse-community/parse-server/commit/f535ee6ec2abba63f702127258ca49fa5b4e08c9))
|
||||
* Remove deprecation `DEPPS3`: Config option `enforcePrivateUsers` defaults to `true` ([#8283](https://github.com/parse-community/parse-server/issues/8283)) ([ed499e3](https://github.com/parse-community/parse-server/commit/ed499e32a21bab9a874a9e5367dc71248ce836c4))
|
||||
* Remove deprecation `DEPPS4`: Remove convenience method for http request `Parse.Cloud.httpRequest` ([#8287](https://github.com/parse-community/parse-server/issues/8287)) ([2d79c08](https://github.com/parse-community/parse-server/commit/2d79c0835b6a9acaf20d5c943d9b4619bb96831c))
|
||||
* Remove support for MongoDB 4.0 ([#8292](https://github.com/parse-community/parse-server/issues/8292)) ([37245f6](https://github.com/parse-community/parse-server/commit/37245f62ce83516b6b95a54b850f0274ef680478))
|
||||
* Restrict use of `masterKey` to localhost by default ([#8281](https://github.com/parse-community/parse-server/issues/8281)) ([6c16021](https://github.com/parse-community/parse-server/commit/6c16021a1f03a70a6d9e68cb64df362d07f3b693))
|
||||
* Upgrade Node Package Manager lock file `package-lock.json` to version 2 ([#8285](https://github.com/parse-community/parse-server/issues/8285)) ([ee72467](https://github.com/parse-community/parse-server/commit/ee7246733d63e4bda20401f7b00262ff03299f20))
|
||||
* Upgrade Redis 3 to 4 ([#8293](https://github.com/parse-community/parse-server/issues/8293)) ([7d622f0](https://github.com/parse-community/parse-server/commit/7d622f06a4347e0ad2cba9a4ec07d8d4fb0f67bc))
|
||||
* Upgrade Redis 3 to 4 for LiveQuery ([#8333](https://github.com/parse-community/parse-server/issues/8333)) ([b2761fb](https://github.com/parse-community/parse-server/commit/b2761fb3786b519d9bbcf35be54309d2d35da1a9))
|
||||
* Upgrade to Parse JavaScript SDK 4 ([#8332](https://github.com/parse-community/parse-server/issues/8332)) ([9092874](https://github.com/parse-community/parse-server/commit/9092874a9a482a24dfdce1dce56615702999d6b8))
|
||||
* Write log entry when request with master key is rejected as outside of `masterKeyIps` ([#8350](https://github.com/parse-community/parse-server/issues/8350)) ([e22b73d](https://github.com/parse-community/parse-server/commit/e22b73d4b700c8ff745aa81726c6680082294b45))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* The Docker image does not contain the git dependency anymore; if you have been using git as a transitive dependency it now needs to be explicitly installed in your Docker file, for example with `RUN apk --no-cache add git` (#8359) ([40810b4](40810b4))
|
||||
* Fields in the internal scope of Parse Server (prefixed with underscore `_`) are only returned using the new `maintenanceKey`; previously the `masterKey` allowed reading of internal fields; see [access scopes](https://github.com/parse-community/parse-server#access-scopes) for a comparison of the keys' access permissions (#8212) ([f3bcc93](f3bcc93))
|
||||
* The method `ParseServer.verifyServerUrl` now returns a promise instead of a callback. ([ffa4974](ffa4974))
|
||||
* The MongoDB aggregation pipeline requires native MongoDB syntax instead of the custom Parse Server syntax; for example pipeline stage names require a leading dollar sign like `$match` and the MongoDB document ID is referenced using `_id` instead of `objectId` (#8362) ([d0d30c4](d0d30c4))
|
||||
* The mechanism to determine the client IP address has been rewritten; to correctly determine the IP address it is now required to set the Parse Server option `trustProxy` accordingly if Parse Server runs behind a proxy server, see the express framework's [trust proxy](https://expressjs.com/en/guide/behind-proxies.html) setting (#8372) ([892040d](892040d))
|
||||
* The Node Package Manager lock file `package-lock.json` is upgraded to version 2; while it is backwards with version 1 for the npm installer, consider this if you run any non-npm analysis tools that use the lock file (#8285) ([ee72467](ee72467))
|
||||
* This release introduces the asynchronous initialization of Parse Server to prevent mounting Parse Server before being ready to receive request; it changes how Parse Server is imported, initialized and started; it also removes the callback `serverStartComplete`; see the [Parse Server 6 migration guide](https://github.com/parse-community/parse-server/blob/alpha/6.0.0.md) for more details (#8232) ([99fcf45](99fcf45))
|
||||
* Nested objects are now properly stored in the database using JSON serialization; previously, due to a bug only top-level objects were serialized, but nested objects were saved as raw JSON; for example, a nested `Date` object was saved as a JSON object like `{ "__type": "Date", "iso": "2020-01-01T00:00:00.000Z" }` instead of its serialized representation `2020-01-01T00:00:00.000Z` (#8209) ([1412666](1412666))
|
||||
* The Parse Server option `enforcePrivateUsers` is set to `true` by default; in previous releases this option defaults to `false`; this change improves the default security configuration of Parse Server (#8283) ([ed499e3](ed499e3))
|
||||
* This release restricts the use of `masterKey` to localhost by default; if you are using Parse Dashboard on a different server to connect to Parse Server you need to add the IP address of the server that hosts Parse Dashboard to this option (#8281) ([6c16021](6c16021))
|
||||
* This release upgrades to Redis 4; if you are using the Redis cache adapter with Parse Server then this is a breaking change as the Redis client options have changed; see the [Redis migration guide](https://github.com/redis/node-redis/blob/redis%404.0.0/docs/v3-to-v4.md) for more details (#8293) ([7d622f0](7d622f0))
|
||||
* This release removes support for MongoDB 4.0; the new minimum supported MongoDB version is 4.2. which also removes support for the deprecated MongoDB MMAPv1 storage engine ([37245f6](37245f6))
|
||||
* Throwing an error in Cloud Code Triggers `afterLogin`, `afterLogout` returns a rejected promise; in previous releases it crashed the server if you did not handle the error on the Node.js process level; consider adapting your code if your app currently handles these errors on the Node.js process level with `process.on('unhandledRejection', ...)` ([130d290](130d290))
|
||||
* Config option `directAccess` defaults to true; set this to `false` in environments where multiple Parse Server instances run behind a load balancer and Parse requests within the current Node.js environment should be routed via the load balancer and distributed as HTTP requests among all instances via the `serverURL`. ([f535ee6](f535ee6))
|
||||
* The convenience method for HTTP requests `Parse.Cloud.httpRequest` is removed; use your preferred 3rd party library for making HTTP requests ([2d79c08](2d79c08))
|
||||
* This release removes Node 12 and Node 17 support ([2546cc8](2546cc8))
|
||||
|
||||
# [5.4.0-beta.1](https://github.com/parse-community/parse-server/compare/5.3.0...5.4.0-beta.1) (2022-10-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* authentication adapter app ID validation may be circumvented; this fixes a vulnerability that affects configurations which allow users to authenticate using the Parse Server authentication adapter for *Facebook* or *Spotify* and where the server-side authentication adapter configuration `appIds` is set as a string (e.g. `abc`) instead of an array of strings (e.g. `["abc"]`) ([GHSA-r657-33vp-gp22](https://github.com/parse-community/parse-server/security/advisories/GHSA-r657-33vp-gp22)) [skip release] ([#8187](https://github.com/parse-community/parse-server/issues/8187)) ([8c8ec71](https://github.com/parse-community/parse-server/commit/8c8ec715739e0f851338cfed794409ebac66c51b))
|
||||
* brute force guessing of user sensitive data via search patterns (GHSA-2m6g-crv8-p3c6) ([#8146](https://github.com/parse-community/parse-server/issues/8146)) [skip release] ([4c0c7c7](https://github.com/parse-community/parse-server/commit/4c0c7c77b76257878b9bcb05ff9de01c9d790262))
|
||||
* certificate in Apple Game Center auth adapter not validated [skip release] ([#8058](https://github.com/parse-community/parse-server/issues/8058)) ([75af9a2](https://github.com/parse-community/parse-server/commit/75af9a26cc8e9e88a33d1e452c93a0ee6e509f17))
|
||||
* graphQL query ignores condition `equalTo` with value `false` ([#8032](https://github.com/parse-community/parse-server/issues/8032)) ([7f5a15d](https://github.com/parse-community/parse-server/commit/7f5a15d5df0dfa3515e9f73709d6a49663545f9b))
|
||||
* internal indices for classes `_Idempotency` and `_Role` are not protected in defined schema ([#8121](https://github.com/parse-community/parse-server/issues/8121)) ([c16f529](https://github.com/parse-community/parse-server/commit/c16f529f74f92154401bf662f634b3c5fa45e18e))
|
||||
* invalid file request not properly handled [skip release] ([#8062](https://github.com/parse-community/parse-server/issues/8062)) ([4c9e956](https://github.com/parse-community/parse-server/commit/4c9e95674ad081f13062e8cd30b77b1962d5df57))
|
||||
* liveQuery with `containedIn` not working when object field is an array ([#8128](https://github.com/parse-community/parse-server/issues/8128)) ([1d9605b](https://github.com/parse-community/parse-server/commit/1d9605bc93009263d3811df4d4249034ba6eb8c4))
|
||||
* protected fields exposed via LiveQuery (GHSA-crrq-vr9j-fxxh) [skip release] ([#8076](https://github.com/parse-community/parse-server/issues/8076)) ([9fd4516](https://github.com/parse-community/parse-server/commit/9fd4516cde5c742f9f29dd05468b4a43a85639a6))
|
||||
* push notifications `badge` doesn't update with Installation beforeSave trigger ([#8162](https://github.com/parse-community/parse-server/issues/8162)) ([3c75c2b](https://github.com/parse-community/parse-server/commit/3c75c2ba4851fae96a8c19b11a3efde03816c9a1))
|
||||
* query aggregation pipeline cannot handle value of type `Date` when `directAccess: true` ([#8167](https://github.com/parse-community/parse-server/issues/8167)) ([e424137](https://github.com/parse-community/parse-server/commit/e4241374061caef66538de15112fb6bbafb1f5bb))
|
||||
* relation constraints in compound queries `Parse.Query.or`, `Parse.Query.and` not working ([#8203](https://github.com/parse-community/parse-server/issues/8203)) ([28f0d26](https://github.com/parse-community/parse-server/commit/28f0d2667787d2ac68726607b811d6f0ef62b9f1))
|
||||
* security upgrade undici from 5.6.0 to 5.8.0 ([#8108](https://github.com/parse-community/parse-server/issues/8108)) ([4aa016b](https://github.com/parse-community/parse-server/commit/4aa016b7322467422b9fdf05d8e29b9ecf910da7))
|
||||
* server crashes when receiving file download request with invalid byte range; this fixes a security vulnerability that allows an attacker to impact the availability of the server instance; the fix improves parsing of the range parameter to properly handle invalid range requests ([GHSA-h423-w6qv-2wj3](https://github.com/parse-community/parse-server/security/advisories/GHSA-h423-w6qv-2wj3)) [skip release] ([#8238](https://github.com/parse-community/parse-server/issues/8238)) ([c03908f](https://github.com/parse-community/parse-server/commit/c03908f74e5c9eed834874a89df6c89c1a1e849f))
|
||||
* session object properties can be updated by foreign user; this fixes a security vulnerability in which a foreign user can write to the session object of another user if the session object ID is known; the fix prevents writing to foreign session objects ([GHSA-6w4q-23cf-j9jp](https://github.com/parse-community/parse-server/security/advisories/GHSA-6w4q-23cf-j9jp)) [skip release] ([#8180](https://github.com/parse-community/parse-server/issues/8180)) ([37fed30](https://github.com/parse-community/parse-server/commit/37fed3062ccc3ef1dfd49a9fc53318e72b3e4aff))
|
||||
* sorting by non-existing value throws `INVALID_SERVER_ERROR` on Postgres ([#8157](https://github.com/parse-community/parse-server/issues/8157)) ([3b775a1](https://github.com/parse-community/parse-server/commit/3b775a1fb8a1878714e3451191438963d688f1b0))
|
||||
* updating object includes unchanged keys in client response for certain key types ([#8159](https://github.com/parse-community/parse-server/issues/8159)) ([37af1d7](https://github.com/parse-community/parse-server/commit/37af1d78fce5a15039ffe3af7b323c1f1e8582fc))
|
||||
|
||||
### Features
|
||||
|
||||
* add convenience access to Parse Server configuration in Cloud Code via `Parse.Server` ([#8244](https://github.com/parse-community/parse-server/issues/8244)) ([9f11115](https://github.com/parse-community/parse-server/commit/9f111158edf7fd57a65db0c4f9244b37e58cf293))
|
||||
* add option to change the default value of the `Parse.Query.limit()` constraint ([#8152](https://github.com/parse-community/parse-server/issues/8152)) ([0388956](https://github.com/parse-community/parse-server/commit/038895680894984e569dff54bf5c7b31094f3891))
|
||||
* add support for MongoDB 6 ([#8242](https://github.com/parse-community/parse-server/issues/8242)) ([aba0081](https://github.com/parse-community/parse-server/commit/aba0081ce1a166a93de57f3928c19a05562b5cc1))
|
||||
* add support for Postgres 15 ([#8215](https://github.com/parse-community/parse-server/issues/8215)) ([2feb6c4](https://github.com/parse-community/parse-server/commit/2feb6c46080946c984daa351187fa07cd582355d))
|
||||
* liveQuery support for unsorted distance queries ([#8221](https://github.com/parse-community/parse-server/issues/8221)) ([0f763da](https://github.com/parse-community/parse-server/commit/0f763da17d646b2fec2cd980d3857e46072a8a07))
|
||||
|
||||
# [5.3.0-beta.1](https://github.com/parse-community/parse-server/compare/5.2.1...5.3.0-beta.1) (2022-06-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* afterSave trigger removes pointer in Parse object ([#7913](https://github.com/parse-community/parse-server/issues/7913)) ([47d796e](https://github.com/parse-community/parse-server/commit/47d796ea58f65e71612ce37149be692abc9ea97f))
|
||||
* auto-release process may fail if optional back-merging task fails ([#8051](https://github.com/parse-community/parse-server/issues/8051)) ([cf925e7](https://github.com/parse-community/parse-server/commit/cf925e75e87a6989f41e2e2abb2aba4332b1e79f))
|
||||
* custom database options are not passed to MongoDB GridFS ([#7911](https://github.com/parse-community/parse-server/issues/7911)) ([b1e5565](https://github.com/parse-community/parse-server/commit/b1e5565b22f2eff229571fe9a9500314bd30965b))
|
||||
* depreciate allowClientClassCreation defaulting to true ([#7925](https://github.com/parse-community/parse-server/issues/7925)) ([38ed96a](https://github.com/parse-community/parse-server/commit/38ed96ace534d639db007aa7dd5387b2da8f03ae))
|
||||
* errors in GraphQL do not show the original error but a general `Unexpected Error` ([#8045](https://github.com/parse-community/parse-server/issues/8045)) ([0d81887](https://github.com/parse-community/parse-server/commit/0d818879c217f9c56100a5f59868fa37e6d24b71))
|
||||
* interrupted WebSocket connection not closed by LiveQuery server ([#8012](https://github.com/parse-community/parse-server/issues/8012)) ([2d5221e](https://github.com/parse-community/parse-server/commit/2d5221e48012fb7781c0406d543a922d313075ea))
|
||||
* live query role cache does not clear when a user is added to a role ([#8026](https://github.com/parse-community/parse-server/issues/8026)) ([199dfc1](https://github.com/parse-community/parse-server/commit/199dfc17226d85a78ab85f24362cce740f4ada39))
|
||||
* peer dependency mismatch for GraphQL dependencies ([#7934](https://github.com/parse-community/parse-server/issues/7934)) ([0a6faa8](https://github.com/parse-community/parse-server/commit/0a6faa81fa97f8620e7fd05e8c7bbdb4b7da9578))
|
||||
* return correct response when revert is used in beforeSave ([#7839](https://github.com/parse-community/parse-server/issues/7839)) ([19900fc](https://github.com/parse-community/parse-server/commit/19900fcdf8c9f29a674fb62cf6e4b3341d796891))
|
||||
* security upgrade @parse/fs-files-adapter from 1.2.1 to 1.2.2 ([#7948](https://github.com/parse-community/parse-server/issues/7948)) ([3a70fda](https://github.com/parse-community/parse-server/commit/3a70fda6798d4143f21046439b5eaf232a31bdb6))
|
||||
* security upgrade moment from 2.29.1 to 2.29.2 ([#7931](https://github.com/parse-community/parse-server/issues/7931)) ([731c550](https://github.com/parse-community/parse-server/commit/731c5507144bbacff236097e7a2a03bfe54f6e10))
|
||||
* security upgrade parse push adapter from 4.1.0 to 4.1.2 ([#7893](https://github.com/parse-community/parse-server/issues/7893)) ([93667b4](https://github.com/parse-community/parse-server/commit/93667b4e8402bf13b46c4d3ef12cec6532fd9da7))
|
||||
* websocket connection of LiveQuery interrupts frequently ([#8048](https://github.com/parse-community/parse-server/issues/8048)) ([03caae1](https://github.com/parse-community/parse-server/commit/03caae1e611f28079cdddbbe433daaf69e3f595c))
|
||||
|
||||
### Features
|
||||
|
||||
* add MongoDB 5.1 compatibility ([#7682](https://github.com/parse-community/parse-server/issues/7682)) ([022a856](https://github.com/parse-community/parse-server/commit/022a85619d8a2c57a2f2938e245e4d8a47c15276))
|
||||
* add MongoDB 5.2 support ([#7894](https://github.com/parse-community/parse-server/issues/7894)) ([5bfa716](https://github.com/parse-community/parse-server/commit/5bfa7160d9e35b237cbae1016ed86724aa99f8d7))
|
||||
* add support for Node 17 and 18 ([#7896](https://github.com/parse-community/parse-server/issues/7896)) ([3e9f292](https://github.com/parse-community/parse-server/commit/3e9f292d840334244934cee9a34545ac86313549))
|
||||
* align file trigger syntax with class trigger; use the new syntax `Parse.Cloud.beforeSave(Parse.File, (request) => {})`, the old syntax `Parse.Cloud.beforeSaveFile((request) => {})` has been deprecated ([#7966](https://github.com/parse-community/parse-server/issues/7966)) ([c6dcad8](https://github.com/parse-community/parse-server/commit/c6dcad8d167d44912dbd416d328519314c0809bd))
|
||||
* replace GraphQL Apollo with GraphQL Yoga ([#7967](https://github.com/parse-community/parse-server/issues/7967)) ([1aa2204](https://github.com/parse-community/parse-server/commit/1aa2204aebfdbe273d54d6d56c6029f7c34aab14))
|
||||
* selectively enable / disable default authentication adapters ([#7953](https://github.com/parse-community/parse-server/issues/7953)) ([c1e808f](https://github.com/parse-community/parse-server/commit/c1e808f9e807fc49508acbde0d8b3f2b901a1638))
|
||||
* upgrade mongodb from 4.4.1 to 4.5.0 ([#7991](https://github.com/parse-community/parse-server/issues/7991)) ([e692b5d](https://github.com/parse-community/parse-server/commit/e692b5dd8214cdb0ce79bedd30d9aa3cf4de76a5))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* reduce database operations when using the constant parameter in Cloud Function validation ([#7892](https://github.com/parse-community/parse-server/issues/7892)) ([041197f](https://github.com/parse-community/parse-server/commit/041197fb4ca1cd7cf18dc426ce38647267823668))
|
||||
|
||||
# [5.2.0-beta.2](https://github.com/parse-community/parse-server/compare/5.2.0-beta.1...5.2.0-beta.2) (2022-03-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* security bump minimist from 1.2.5 to 1.2.6 ([#7884](https://github.com/parse-community/parse-server/issues/7884)) ([c5cf282](https://github.com/parse-community/parse-server/commit/c5cf282d11ffdc023764f8e7539a2bd6bc246fe1))
|
||||
* sensitive keyword detection may produce false positives ([#7881](https://github.com/parse-community/parse-server/issues/7881)) ([0d6f9e9](https://github.com/parse-community/parse-server/commit/0d6f9e951d9e186e95e96d8869066ce7022bad02))
|
||||
|
||||
# [5.2.0-beta.1](https://github.com/parse-community/parse-server/compare/5.1.1...5.2.0-beta.1) (2022-03-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improved LiveQuery error logging with additional information ([#7837](https://github.com/parse-community/parse-server/issues/7837)) ([443a509](https://github.com/parse-community/parse-server/commit/443a5099059538d379fe491793a5871fcbb4f377))
|
||||
|
||||
# [5.0.0-beta.10](https://github.com/parse-community/parse-server/compare/5.0.0-beta.9...5.0.0-beta.10) (2022-03-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* adding or modifying a nested property requires addField permissions ([#7679](https://github.com/parse-community/parse-server/issues/7679)) ([6a6248b](https://github.com/parse-community/parse-server/commit/6a6248b6cb2e732d17131e18e659943b894ed2f1))
|
||||
* bump nanoid from 3.1.25 to 3.2.0 ([#7781](https://github.com/parse-community/parse-server/issues/7781)) ([f5f63bf](https://github.com/parse-community/parse-server/commit/f5f63bfc64d3481ed944ceb5e9f50b33dccd1ce9))
|
||||
* bump node-fetch from 2.6.1 to 3.1.1 ([#7782](https://github.com/parse-community/parse-server/issues/7782)) ([9082351](https://github.com/parse-community/parse-server/commit/90823514113a1a085ebc818f7109b3fd7591346f))
|
||||
* node engine compatibility did not include node 16 ([#7739](https://github.com/parse-community/parse-server/issues/7739)) ([ea7c014](https://github.com/parse-community/parse-server/commit/ea7c01400f992a1263543706fe49b6174758a2d6))
|
||||
* node engine range has no upper limit to exclude incompatible node versions ([#7692](https://github.com/parse-community/parse-server/issues/7692)) ([573558d](https://github.com/parse-community/parse-server/commit/573558d3adcbcc6222c92003829867e1a73eef94))
|
||||
* package.json & package-lock.json to reduce vulnerabilities ([#7823](https://github.com/parse-community/parse-server/issues/7823)) ([5ca2288](https://github.com/parse-community/parse-server/commit/5ca228882332b65f3ac05407e6e4da1ee3ef3749))
|
||||
* schema cache not cleared in some cases ([#7678](https://github.com/parse-community/parse-server/issues/7678)) ([5af6e5d](https://github.com/parse-community/parse-server/commit/5af6e5dfaa129b1a350afcba4fb381b21c4cc35d))
|
||||
* security upgrade follow-redirects from 1.14.6 to 1.14.7 ([#7769](https://github.com/parse-community/parse-server/issues/7769)) ([8f5a861](https://github.com/parse-community/parse-server/commit/8f5a8618cfa7ed9a2a239a095abffa8f3fd8d31a))
|
||||
* security upgrade follow-redirects from 1.14.7 to 1.14.8 ([#7801](https://github.com/parse-community/parse-server/issues/7801)) ([70088a9](https://github.com/parse-community/parse-server/commit/70088a95a78393da2a4ac68be81e63107747626a))
|
||||
* security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) ([#7844](https://github.com/parse-community/parse-server/issues/7844)) ([e569f40](https://github.com/parse-community/parse-server/commit/e569f402b1fd8648fb0d1523b71b2a03273902a5))
|
||||
* server crash using GraphQL due to missing @apollo/client peer dependency ([#7787](https://github.com/parse-community/parse-server/issues/7787)) ([08089d6](https://github.com/parse-community/parse-server/commit/08089d6fcbb215412448ce7d92b21b9fe6c929f2))
|
||||
* unable to use objectId size higher than 19 on GraphQL API ([#7627](https://github.com/parse-community/parse-server/issues/7627)) ([ed86c80](https://github.com/parse-community/parse-server/commit/ed86c807721cc52a1a5a9dea0b768717eec269ed))
|
||||
* upgrade mime from 2.5.2 to 3.0.0 ([#7725](https://github.com/parse-community/parse-server/issues/7725)) ([f5ef98b](https://github.com/parse-community/parse-server/commit/f5ef98bde32083403c0e30a12162fcc1e52cac37))
|
||||
* upgrade parse from 3.3.1 to 3.4.0 ([#7723](https://github.com/parse-community/parse-server/issues/7723)) ([d4c1f47](https://github.com/parse-community/parse-server/commit/d4c1f473073764cb0570c633fc4a30669c2ce889))
|
||||
* upgrade winston from 3.5.0 to 3.5.1 ([#7820](https://github.com/parse-community/parse-server/issues/7820)) ([4af253d](https://github.com/parse-community/parse-server/commit/4af253d1f8654a6f57b5137ad310cdacadc922cc))
|
||||
|
||||
### Features
|
||||
|
||||
* add Cloud Code context to `ParseObject.fetch` ([#7779](https://github.com/parse-community/parse-server/issues/7779)) ([315290d](https://github.com/parse-community/parse-server/commit/315290d16110110938f80a6b779cc2d1db58c552))
|
||||
* add Idempotency to Postgres ([#7750](https://github.com/parse-community/parse-server/issues/7750)) ([0c3feaa](https://github.com/parse-community/parse-server/commit/0c3feaaa1751964c0db89f25674935c3354b1538))
|
||||
* add support for Node 16 ([#7707](https://github.com/parse-community/parse-server/issues/7707)) ([45cc58c](https://github.com/parse-community/parse-server/commit/45cc58c7e5e640a46c5d508019a3aa81242964b1))
|
||||
* bump required node engine to >=12.22.10 ([#7846](https://github.com/parse-community/parse-server/issues/7846)) ([5ace99d](https://github.com/parse-community/parse-server/commit/5ace99d542a11e422af46d9fd6b1d3d2513b34cf))
|
||||
* support `postgresql` protocol in database URI ([#7757](https://github.com/parse-community/parse-server/issues/7757)) ([caf4a23](https://github.com/parse-community/parse-server/commit/caf4a2341f554b28e3918c53e7e897a3ca47bf8b))
|
||||
* support relativeTime query constraint on Postgres ([#7747](https://github.com/parse-community/parse-server/issues/7747)) ([16b1b2a](https://github.com/parse-community/parse-server/commit/16b1b2a19714535ca805f2dbb3b561d8f6a519a7))
|
||||
* upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support ([#7794](https://github.com/parse-community/parse-server/issues/7794)) ([f88aa2a](https://github.com/parse-community/parse-server/commit/f88aa2a62a533e5344d1c13dd38c5a0b283a480a))
|
||||
|
||||
### Reverts
|
||||
|
||||
* refactor: allow ES import for cloud string if package type is module ([b64640c](https://github.com/parse-community/parse-server/commit/b64640c5705f733798783e68d216e957044ef23c))
|
||||
* update node engine to 2.22.0 ([#7827](https://github.com/parse-community/parse-server/issues/7827)) ([f235412](https://github.com/parse-community/parse-server/commit/f235412c1b6c2b173b7531f285429ea7214b56a2))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This requires Node.js version >=12.22.10. ([5ace99d](5ace99d))
|
||||
* The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change. ([f88aa2a](f88aa2a))
|
||||
* Removes official Node 15 support which has reached it end-of-life date. ([45cc58c](45cc58c))
|
||||
|
||||
# [5.0.0-beta.9](https://github.com/parse-community/parse-server/compare/5.0.0-beta.8...5.0.0-beta.9) (2022-03-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* bump required node engine to >=12.22.10 ([#7848](https://github.com/parse-community/parse-server/issues/7848)) ([23a3488](https://github.com/parse-community/parse-server/commit/23a3488f15511fafbe0e1d7ff0ef8355f9cb0215))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This requires Node.js version >=12.22.10. ([23a3488](23a3488))
|
||||
|
||||
# [5.0.0-beta.8](https://github.com/parse-community/parse-server/compare/5.0.0-beta.7...5.0.0-beta.8) (2022-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) ([#7843](https://github.com/parse-community/parse-server/issues/7843)) ([971adb5](https://github.com/parse-community/parse-server/commit/971adb54387b0ede31be05ca407d5f35b4575c83))
|
||||
|
||||
# [5.0.0-beta.7](https://github.com/parse-community/parse-server/compare/5.0.0-beta.6...5.0.0-beta.7) (2022-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* security upgrade follow-redirects from 1.14.7 to 1.14.8 ([#7802](https://github.com/parse-community/parse-server/issues/7802)) ([7029b27](https://github.com/parse-community/parse-server/commit/7029b274ca87bc8058617f29865d683dc3b351a1))
|
||||
|
||||
# [5.0.0-beta.6](https://github.com/parse-community/parse-server/compare/5.0.0-beta.5...5.0.0-beta.6) (2022-01-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* security upgrade follow-redirects from 1.14.2 to 1.14.7 ([#7772](https://github.com/parse-community/parse-server/issues/7772)) ([4bd34b1](https://github.com/parse-community/parse-server/commit/4bd34b189bc9f5aa2e70b7e7c1a456e91b6de773))
|
||||
|
||||
# [5.0.0-beta.5](https://github.com/parse-community/parse-server/compare/5.0.0-beta.4...5.0.0-beta.5) (2022-01-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* schema cache not cleared in some cases ([#7771](https://github.com/parse-community/parse-server/issues/7771)) ([3b92fa1](https://github.com/parse-community/parse-server/commit/3b92fa1ca9e8889127a32eba913d68309397ca2c))
|
||||
|
||||
# [5.0.0-beta.4](https://github.com/parse-community/parse-server/compare/5.0.0-beta.3...5.0.0-beta.4) (2021-11-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* unable to use objectId size higher than 19 on GraphQL API ([#7722](https://github.com/parse-community/parse-server/issues/7722)) ([8ee0445](https://github.com/parse-community/parse-server/commit/8ee0445c0aeeb88dff2559b46ade408071d22143))
|
||||
|
||||
# [5.0.0-beta.3](https://github.com/parse-community/parse-server/compare/5.0.0-beta.2...5.0.0-beta.3) (2021-11-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* node engine range has no upper limit to exclude incompatible node versions ([#7693](https://github.com/parse-community/parse-server/issues/7693)) ([6a54dac](https://github.com/parse-community/parse-server/commit/6a54dac24d9fb63a44f311b8d414f4aa64140f32))
|
||||
|
||||
# [5.0.0-beta.2](https://github.com/parse-community/parse-server/compare/5.0.0-beta.1...5.0.0-beta.2) (2021-11-10)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* refactor: allow ES import for cloud string if package type is module ([#7691](https://github.com/parse-community/parse-server/issues/7691)) ([200d4ba](https://github.com/parse-community/parse-server/commit/200d4ba9a527016a65668738c7728696f443bd53))
|
||||
|
||||
# [5.0.0-beta.1](https://github.com/parse-community/parse-server/compare/4.5.0...5.0.0-beta.1) (2021-11-01)
|
||||
|
||||
### BREAKING CHANGES
|
||||
- Improved schema caching through database real-time hooks. Reduces DB queries, decreases Parse Query execution time and fixes a potential schema memory leak. If multiple Parse Server instances connect to the same DB (for example behind a load balancer), set the [Parse Server Option](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) `databaseOptions.enableSchemaHooks: true` to enable this feature and keep the schema in sync across all instances. Failing to do so will cause a schema change to not propagate to other instances and re-syncing will only happen when these instances restart. The options `enableSingleSchemaCache` and `schemaCacheTTL` have been removed. To use this feature with MongoDB, a replica set cluster with [change stream](https://docs.mongodb.com/manual/changeStreams/#availability) support is required. (Diamond Lewis, SebC) [#7214](https://github.com/parse-community/parse-server/issues/7214)
|
||||
- Added file upload restriction. File upload is now only allowed for authenticated users by default for improved security. To allow file upload also for Anonymous Users or Public, set the `fileUpload` parameter in the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (dblythy, Manuel Trezza) [#7071](https://github.com/parse-community/parse-server/pull/7071)
|
||||
- Removed [parse-server-simple-mailgun-adapter](https://github.com/parse-community/parse-server-simple-mailgun-adapter) dependency; to continue using the adapter it has to be explicitly installed (Manuel Trezza) [#7321](https://github.com/parse-community/parse-server/pull/7321)
|
||||
- Remove support for MongoDB 3.6 which has reached its End-of-Life date and PostgreSQL 10 (Manuel Trezza) [#7315](https://github.com/parse-community/parse-server/pull/7315)
|
||||
- Remove support for Node 10 which has reached its End-of-Life date (Manuel Trezza) [#7314](https://github.com/parse-community/parse-server/pull/7314)
|
||||
- Remove S3 Files Adapter from Parse Server, instead install separately as `@parse/s3-files-adapter` (Manuel Trezza) [#7324](https://github.com/parse-community/parse-server/pull/7324)
|
||||
- Remove Session field `restricted`; the field was a code artifact from a feature that never existed in Open Source Parse Server; if you have been using this field for custom purposes, consider that for new Parse Server installations the field does not exist anymore in the schema, and for existing installations the field default value `false` will not be set anymore when creating a new session (Manuel Trezza) [#7543](https://github.com/parse-community/parse-server/pull/7543)
|
||||
- ci: add node engine version check (Manuel Trezza) [#7574](https://github.com/parse-community/parse-server/pull/7574)
|
||||
- To delete a field via the GraphQL API, the field value has to be set to `null`. Previously, setting a field value to `null` would save a null value in the database, which was not according to the [GraphQL specs](https://spec.graphql.org/June2018/#sec-Null-Value). To delete a file field use `file: null`, the previous way of using `file: { file: null }` has become obsolete. ([626fad2](626fad2))
|
||||
|
||||
### Notable Changes
|
||||
- Alphabetical ordered GraphQL API, improved GraphQL Schema cache system and fix GraphQL input reassign issue (Moumouls) [#7344](https://github.com/parse-community/parse-server/issues/7344)
|
||||
- Added Parse Server Security Check to report weak security settings (Manuel Trezza, dblythy) [#7247](https://github.com/parse-community/parse-server/issues/7247)
|
||||
- EXPERIMENTAL: Added new page router with placeholder rendering and localization of custom and feature pages such as password reset and email verification (Manuel Trezza) [#7128](https://github.com/parse-community/parse-server/pull/7128)
|
||||
- EXPERIMENTAL: Added custom routes to easily customize flows for password reset, email verification or build entirely new flows (Manuel Trezza) [#7231](https://github.com/parse-community/parse-server/pull/7231)
|
||||
- Added Deprecation Policy to govern the introduction of breaking changes in a phased pattern that is more predictable for developers (Manuel Trezza) [#7199](https://github.com/parse-community/parse-server/pull/7199)
|
||||
- Add REST API endpoint `/loginAs` to create session of any user with master key; allows to impersonate another user. (GormanFletcher) [#7406](https://github.com/parse-community/parse-server/pull/7406)
|
||||
- Add official support for MongoDB 5.0 (Manuel Trezza) [#7469](https://github.com/parse-community/parse-server/pull/7469)
|
||||
- Added Parse Server Configuration `enforcePrivateUsers`, which will remove public access by default on new Parse.Users (dblythy) [#7319](https://github.com/parse-community/parse-server/pull/7319)
|
||||
* add support for Postgres 14 ([#7644](https://github.com/parse-community/parse-server/issues/7644)) ([090350a](https://github.com/parse-community/parse-server/commit/090350a7a0fac945394ca1cb24b290316ef06aa7))
|
||||
* add user-defined schema and migrations ([#7418](https://github.com/parse-community/parse-server/issues/7418)) ([25d5c30](https://github.com/parse-community/parse-server/commit/25d5c30be2111be332eb779eb0697774a17da7af))
|
||||
* setting a field to null does not delete it via GraphQL API ([#7649](https://github.com/parse-community/parse-server/issues/7649)) ([626fad2](https://github.com/parse-community/parse-server/commit/626fad2e71017dcc62196c487de5f908fa43000b))
|
||||
* combined `and` query with relational query condition returns incorrect results ([#7593](https://github.com/parse-community/parse-server/issues/7593)) ([174886e](https://github.com/parse-community/parse-server/commit/174886e385e091c6bbd4a84891ef95f80b50d05c))
|
||||
|
||||
### Other Changes
|
||||
- Support native mongodb syntax in aggregation pipelines (Raschid JF Rafeally) [#7339](https://github.com/parse-community/parse-server/pull/7339)
|
||||
- Fix error when a not yet inserted job is updated (Antonio Davi Macedo Coelho de Castro) [#7196](https://github.com/parse-community/parse-server/pull/7196)
|
||||
- request.context for afterFind triggers (dblythy) [#7078](https://github.com/parse-community/parse-server/pull/7078)
|
||||
- Winston Logger interpolating stdout to console (dplewis) [#7114](https://github.com/parse-community/parse-server/pull/7114)
|
||||
- Added convenience method `Parse.Cloud.sendEmail(...)` to send email via email adapter in Cloud Code (dblythy) [#7089](https://github.com/parse-community/parse-server/pull/7089)
|
||||
- LiveQuery support for $and, $nor, $containedBy, $geoWithin, $geoIntersects queries (dplewis) [#7113](https://github.com/parse-community/parse-server/pull/7113)
|
||||
- Supporting patterns in LiveQuery server's config parameter `classNames` (Nes-si) [#7131](https://github.com/parse-community/parse-server/pull/7131)
|
||||
- Added `requireAnyUserRoles` and `requireAllUserRoles` for Parse Cloud validator (dblythy) [#7097](https://github.com/parse-community/parse-server/pull/7097)
|
||||
- Support Facebook Limited Login (miguel-s) [#7219](https://github.com/parse-community/parse-server/pull/7219)
|
||||
- Removed Stage name check on aggregate pipelines (BRETT71) [#7237](https://github.com/parse-community/parse-server/pull/7237)
|
||||
- Retry transactions on MongoDB when it fails due to transient error (Antonio Davi Macedo Coelho de Castro) [#7187](https://github.com/parse-community/parse-server/pull/7187)
|
||||
- Bump tests to use Mongo 4.4.4 (Antonio Davi Macedo Coelho de Castro) [#7184](https://github.com/parse-community/parse-server/pull/7184)
|
||||
- Added new account lockout policy option `accountLockout.unlockOnPasswordReset` to automatically unlock account on password reset (Manuel Trezza) [#7146](https://github.com/parse-community/parse-server/pull/7146)
|
||||
- Test Parse Server continuously against all recent MongoDB versions that have not reached their end-of-life support date, added MongoDB compatibility table to Parse Server docs (Manuel Trezza) [#7161](https://github.com/parse-community/parse-server/pull/7161)
|
||||
- Test Parse Server continuously against all recent Node.js versions that have not reached their end-of-life support date, added Node.js compatibility table to Parse Server docs (Manuel Trezza) [7161](https://github.com/parse-community/parse-server/pull/7177)
|
||||
- Throw error on invalid Cloud Function validation configuration (dblythy) [#7154](https://github.com/parse-community/parse-server/pull/7154)
|
||||
- Allow Cloud Validator `options` to be async (dblythy) [#7155](https://github.com/parse-community/parse-server/pull/7155)
|
||||
- Optimize queries on classes with pointer permissions (Pedro Diaz) [#7061](https://github.com/parse-community/parse-server/pull/7061)
|
||||
- Test Parse Server continuously against all relevant Postgres versions (minor versions), added Postgres compatibility table to Parse Server docs (Corey Baker) [#7176](https://github.com/parse-community/parse-server/pull/7176)
|
||||
- Randomize test suite (Diamond Lewis) [#7265](https://github.com/parse-community/parse-server/pull/7265)
|
||||
- LDAP: Properly unbind client on group search error (Diamond Lewis) [#7265](https://github.com/parse-community/parse-server/pull/7265)
|
||||
- Improve data consistency in Push and Job Status update (Diamond Lewis) [#7267](https://github.com/parse-community/parse-server/pull/7267)
|
||||
- Excluding keys that have trailing edges.node when performing GraphQL resolver (Chris Bland) [#7273](https://github.com/parse-community/parse-server/pull/7273)
|
||||
- Added centralized feature deprecation with standardized warning logs (Manuel Trezza) [#7303](https://github.com/parse-community/parse-server/pull/7303)
|
||||
- Use Node.js 15.13.0 in CI (Olle Jonsson) [#7312](https://github.com/parse-community/parse-server/pull/7312)
|
||||
- Fix file upload issue for S3 compatible storage (Linode, DigitalOcean) by avoiding empty tags property when creating a file (Ali Oguzhan Yildiz) [#7300](https://github.com/parse-community/parse-server/pull/7300)
|
||||
- Add building Docker image as CI check (Manuel Trezza) [#7332](https://github.com/parse-community/parse-server/pull/7332)
|
||||
- Add NPM package-lock version check to CI (Manuel Trezza) [#7333](https://github.com/parse-community/parse-server/pull/7333)
|
||||
- Fix incorrect LiveQuery events triggered for multiple subscriptions on the same class with different events [#7341](https://github.com/parse-community/parse-server/pull/7341)
|
||||
- Fix select and excludeKey queries to properly accept JSON string arrays. Also allow nested fields in exclude (Corey Baker) [#7242](https://github.com/parse-community/parse-server/pull/7242)
|
||||
- Fix LiveQuery server crash when using $all query operator on a missing object key (Jason Posthuma) [#7421](https://github.com/parse-community/parse-server/pull/7421)
|
||||
- Added runtime deprecation warnings (Manuel Trezza) [#7451](https://github.com/parse-community/parse-server/pull/7451)
|
||||
- Add ability to pass context of an object via a header, X-Parse-Cloud-Context, for Cloud Code triggers. The header addition allows client SDK's to add context without injecting _context in the body of JSON objects (Corey Baker) [#7437](https://github.com/parse-community/parse-server/pull/7437)
|
||||
- Add CI check to add changelog entry (Manuel Trezza) [#7512](https://github.com/parse-community/parse-server/pull/7512)
|
||||
- Refactor: uniform issue templates across repos (Manuel Trezza) [#7528](https://github.com/parse-community/parse-server/pull/7528)
|
||||
- ci: bump ci environment (Manuel Trezza) [#7539](https://github.com/parse-community/parse-server/pull/7539)
|
||||
- CI now pushes docker images to Docker Hub (Corey Baker) [#7548](https://github.com/parse-community/parse-server/pull/7548)
|
||||
- Allow afterFind and afterLiveQueryEvent to set unsaved pointers and keys (dblythy) [#7310](https://github.com/parse-community/parse-server/pull/7310)
|
||||
- Allow setting descending sort to full text queries (dblythy) [#7496](https://github.com/parse-community/parse-server/pull/7496)
|
||||
- Allow cloud string for ES modules (Daniel Blyth) [#7560](https://github.com/parse-community/parse-server/pull/7560)
|
||||
- docs: Introduce deprecation ID for reference in comments and online search (Manuel Trezza) [#7562](https://github.com/parse-community/parse-server/pull/7562)
|
||||
- refactor: deprecate `Parse.Cloud.httpRequest`; it is recommended to use a HTTP library instead. (Daniel Blyth) [#7595](https://github.com/parse-community/parse-server/pull/7595)
|
||||
- refactor: Modernize HTTPRequest tests (brandongregoryscott) [#7604](https://github.com/parse-community/parse-server/pull/7604)
|
||||
- Allow liveQuery on Session class (Daniel Blyth) [#7554](https://github.com/parse-community/parse-server/pull/7554)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,292 +0,0 @@
|
||||
const core = require('@actions/core');
|
||||
const semver = require('semver');
|
||||
const yaml = require('yaml');
|
||||
const fs = require('fs').promises;
|
||||
|
||||
/**
|
||||
* This checks the CI version of an environment variable in a YAML file
|
||||
* against a list of released versions of a package.
|
||||
*/
|
||||
class CiVersionCheck {
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* @param {Object} config The config.
|
||||
* @param {String} config.packageName The package name to check.
|
||||
* @param {String} config.packageSupportUrl The URL to the package website
|
||||
* that shows the End-of-Life support dates.
|
||||
* @param {String} config.yamlFilePath The path to the GitHub workflow YAML
|
||||
* file that contains the tests.
|
||||
* @param {String} config.ciEnvironmentsKeyPath The key path in the CI YAML
|
||||
* file to the environment specifications.
|
||||
* @param {String} config.ciVersionKey The key in the CI YAML file to
|
||||
* determine the package version.
|
||||
* @param {Array<String>} config.releasedVersions The released versions of
|
||||
* the package to check against.
|
||||
* @param {Array<String>} config.ignoreReleasedVersions The versions to
|
||||
* ignore when checking whether the CI tests against the latest versions.
|
||||
* This can be used in case there is a package release for which Parse
|
||||
* Server compatibility is not required.
|
||||
* @param {String} [config.latestComponent='patch'] The version component
|
||||
* (`major`, `minor`, `patch`) that must be the latest released version.
|
||||
* Default is `patch`.
|
||||
*
|
||||
* For example:
|
||||
* - Released versions: 1.0.0, 1.2.0, 1.2.1, 1.3.0, 1.3.1, 2.0.0
|
||||
* - Tested version: 1.2.0
|
||||
*
|
||||
* If the latest version component is `patch`, then the check would
|
||||
* fail and recommend an upgrade to version 1.2.1 and to add additional
|
||||
* tests against 1.3.1 and 2.0.0.
|
||||
* If the latest version component is `minor` then the check would
|
||||
* fail and recommend an upgrade to version 1.3.0 and to add an additional
|
||||
* test against 2.0.0.
|
||||
* If the latest version component is `major` then the check would
|
||||
* fail and recommend an upgrade to version 2.0.0.
|
||||
*/
|
||||
constructor(config) {
|
||||
const {
|
||||
packageName,
|
||||
packageSupportUrl,
|
||||
yamlFilePath,
|
||||
ciEnvironmentsKeyPath,
|
||||
ciVersionKey,
|
||||
releasedVersions,
|
||||
ignoreReleasedVersions = [],
|
||||
latestComponent = CiVersionCheck.versionComponents.patch,
|
||||
} = config;
|
||||
|
||||
// Ensure required params are set
|
||||
if ([
|
||||
packageName,
|
||||
packageSupportUrl,
|
||||
yamlFilePath,
|
||||
ciEnvironmentsKeyPath,
|
||||
ciVersionKey,
|
||||
releasedVersions,
|
||||
].includes(undefined)) {
|
||||
throw 'invalid configuration';
|
||||
}
|
||||
|
||||
if (!Object.keys(CiVersionCheck.versionComponents).includes(latestComponent)) {
|
||||
throw 'invalid configuration for latestComponent';
|
||||
}
|
||||
|
||||
this.packageName = packageName;
|
||||
this.packageSupportUrl = packageSupportUrl;
|
||||
this.yamlFilePath = yamlFilePath;
|
||||
this.ciEnvironmentsKeyPath = ciEnvironmentsKeyPath;
|
||||
this.ciVersionKey = ciVersionKey;
|
||||
this.releasedVersions = releasedVersions;
|
||||
this.ignoreReleasedVersions = ignoreReleasedVersions;
|
||||
this.latestComponent = latestComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* The definition of version components.
|
||||
*/
|
||||
static get versionComponents() {
|
||||
return Object.freeze({
|
||||
major: 'major',
|
||||
minor: 'minor',
|
||||
patch: 'patch',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the test environments as specified in the YAML file.
|
||||
*/
|
||||
async getTests() {
|
||||
try {
|
||||
// Get CI workflow
|
||||
const ciYaml = await fs.readFile(this.yamlFilePath, 'utf-8');
|
||||
const ci = yaml.parse(ciYaml);
|
||||
|
||||
// Extract package versions
|
||||
let versions = this.ciEnvironmentsKeyPath.split('.').reduce((o,k) => o !== undefined ? o[k] : undefined, ci);
|
||||
versions = Object.entries(versions)
|
||||
.map(entry => entry[1])
|
||||
.filter(entry => entry[this.ciVersionKey]);
|
||||
|
||||
return versions;
|
||||
} catch (e) {
|
||||
throw `Failed to determine ${this.packageName} versions from CI YAML file with error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the package versions which are missing in the CI environment.
|
||||
* @param {Array<String>} releasedVersions The released versions; need to
|
||||
* be sorted descending.
|
||||
* @param {Array<String>} testedVersions The tested versions.
|
||||
* @param {String} versionComponent The latest version component.
|
||||
* @returns {Array<String>} The untested versions.
|
||||
*/
|
||||
getUntestedVersions(releasedVersions, testedVersions, versionComponent) {
|
||||
// Use these example values for debugging the version range logic below
|
||||
// versionComponent = CiVersionCheck.versionComponents.patch;
|
||||
// this.ignoreReleasedVersions = ['<4.4.0', '~4.7.0'];
|
||||
// testedVersions = ['4.4.3'];
|
||||
// releasedVersions = [
|
||||
// '5.0.0-rc0',
|
||||
// '5.0.0',
|
||||
// '4.9.1',
|
||||
// '4.9.0',
|
||||
// '4.8.1',
|
||||
// '4.8.0',
|
||||
// '4.7.1',
|
||||
// '4.7.0',
|
||||
// '4.4.3',
|
||||
// '4.4.2',
|
||||
// '4.4.0',
|
||||
// '4.1.0',
|
||||
// '3.5.0',
|
||||
// ];
|
||||
|
||||
// Determine operator for range comparison
|
||||
const operator = versionComponent == CiVersionCheck.versionComponents.major
|
||||
? '>='
|
||||
: versionComponent == CiVersionCheck.versionComponents.minor
|
||||
? '^'
|
||||
: '~'
|
||||
|
||||
// Get all untested versions
|
||||
const untestedVersions = releasedVersions.reduce((m, v) => {
|
||||
// If the version should be ignored, skip it
|
||||
if (this.ignoreReleasedVersions.length > 0 && semver.satisfies(v, this.ignoreReleasedVersions.join(' || '))) {
|
||||
return m;
|
||||
}
|
||||
// If the version is a pre-release, skip it
|
||||
if ((semver.prerelease(v) || []).length > 0) {
|
||||
return m;
|
||||
}
|
||||
// If a satisfying version has already been added to untested, skip it
|
||||
if (semver.maxSatisfying(m, `${operator}${v}`)) {
|
||||
return m;
|
||||
}
|
||||
// If a satisfying version is already tested, skip it
|
||||
if (semver.maxSatisfying(testedVersions, `${operator}${v}`)) {
|
||||
return m;
|
||||
}
|
||||
// Add version
|
||||
m.push(v);
|
||||
return m;
|
||||
}, []);
|
||||
|
||||
return untestedVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest version for a given version and component.
|
||||
* @param {Array<String>} versions The versions in which to search.
|
||||
* @param {String} version The version for which a newer version
|
||||
* should be searched.
|
||||
* @param {String} versionComponent The version component up to
|
||||
* which the latest version should be checked.
|
||||
* @returns {String|undefined} The newer version.
|
||||
*/
|
||||
getNewerVersion(versions, version, versionComponent) {
|
||||
// Determine operator for range comparison
|
||||
const operator = versionComponent == CiVersionCheck.versionComponents.major
|
||||
? '>='
|
||||
: versionComponent == CiVersionCheck.versionComponents.minor
|
||||
? '^'
|
||||
: '~'
|
||||
const latest = semver.maxSatisfying(versions, `${operator}${version}`);
|
||||
|
||||
// If the version should be ignored, skip it
|
||||
if (this.ignoreReleasedVersions.length > 0 && semver.satisfies(latest, this.ignoreReleasedVersions.join(' || '))) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Return the latest version if it is newer than any currently used version
|
||||
return semver.gt(latest, version) ? latest : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates that the given versions strictly follow semver
|
||||
* syntax.
|
||||
* @param {Array<String>} versions The versions to check.
|
||||
*/
|
||||
_validateVersionSyntax(versions) {
|
||||
for (const version of versions) {
|
||||
if (!semver.valid(version)) {
|
||||
throw version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the check.
|
||||
*/
|
||||
async check() {
|
||||
/* eslint-disable no-console */
|
||||
try {
|
||||
console.log(`\nChecking ${this.packageName} versions in CI environments...`);
|
||||
|
||||
// Validate released versions syntax
|
||||
try {
|
||||
this._validateVersionSyntax(this.releasedVersions);
|
||||
} catch (e) {
|
||||
core.setFailed(`Failed to check ${this.packageName} versions because released version '${e}' does not follow semver syntax (x.y.z).`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort versions descending
|
||||
semver.sort(this.releasedVersions).reverse()
|
||||
|
||||
// Get tested package versions from CI
|
||||
const tests = await this.getTests();
|
||||
|
||||
// Is true if any of the checks failed
|
||||
let failed = false;
|
||||
|
||||
// Check whether each tested version is the latest patch
|
||||
for (const test of tests) {
|
||||
const version = test[this.ciVersionKey];
|
||||
|
||||
// Validate version syntax
|
||||
try {
|
||||
this._validateVersionSyntax([version]);
|
||||
} catch (e) {
|
||||
core.setFailed(`Failed to check ${this.packageName} versions because environment version '${e}' does not follow semver syntax (x.y.z).`);
|
||||
return;
|
||||
}
|
||||
|
||||
const newer = this.getNewerVersion(this.releasedVersions, version, this.latestComponent);
|
||||
if (newer) {
|
||||
console.log(`❌ CI environment '${test.name}' uses an old ${this.packageName} ${this.latestComponent} version ${version} instead of ${newer}.`);
|
||||
failed = true;
|
||||
} else {
|
||||
console.log(`✅ CI environment '${test.name}' uses the latest ${this.packageName} ${this.latestComponent} version ${version}.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether there is a newer component version available that is not tested
|
||||
const testedVersions = tests.map(test => test[this.ciVersionKey]);
|
||||
const untested = this.getUntestedVersions(this.releasedVersions, testedVersions, this.latestComponent);
|
||||
if (untested.length > 0) {
|
||||
console.log(`❌ CI does not have environments using the following versions of ${this.packageName}: ${untested.join(', ')}.`);
|
||||
failed = true;
|
||||
} else {
|
||||
console.log(`✅ CI has environments using all recent versions of ${this.packageName}.`);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
core.setFailed(
|
||||
`CI environments are not up-to-date with the latest ${this.packageName} versions.` +
|
||||
`\n\nCheck the error messages above and update the ${this.packageName} versions in the CI YAML ` +
|
||||
`file.\n\nℹ️ Additionally, there may be versions of ${this.packageName} that have reached their official end-of-life ` +
|
||||
`support date and should be removed from the CI, see ${this.packageSupportUrl}.`
|
||||
);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
const msg = `Failed to check ${this.packageName} versions with error: ${e}`;
|
||||
core.setFailed(msg);
|
||||
}
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CiVersionCheck;
|
||||
@@ -1,69 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const CiVersionCheck = require('./CiVersionCheck');
|
||||
const { exec } = require('child_process');
|
||||
|
||||
async function check() {
|
||||
// Run checks
|
||||
await checkMongoDbVersions();
|
||||
await checkNodeVersions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the MongoDB versions used in test environments.
|
||||
*/
|
||||
async function checkMongoDbVersions() {
|
||||
let latestStableVersions = await new Promise((resolve, reject) => {
|
||||
exec('m ls', (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(stdout.trim());
|
||||
});
|
||||
});
|
||||
latestStableVersions = latestStableVersions.split('\n').map(version => version.trim());
|
||||
|
||||
await new CiVersionCheck({
|
||||
packageName: 'MongoDB',
|
||||
packageSupportUrl: 'https://www.mongodb.com/support-policy',
|
||||
yamlFilePath: './.github/workflows/ci.yml',
|
||||
ciEnvironmentsKeyPath: 'jobs.check-mongo.strategy.matrix.include',
|
||||
ciVersionKey: 'MONGODB_VERSION',
|
||||
releasedVersions: latestStableVersions,
|
||||
latestComponent: CiVersionCheck.versionComponents.patch,
|
||||
ignoreReleasedVersions: [
|
||||
'<4.2.0', // These versions have reached their end-of-life support date
|
||||
'>=4.3.0 <5.0.0', // Unsupported rapid release versions
|
||||
'>=5.1.0 <6.0.0', // Unsupported rapid release versions
|
||||
'>=6.1.0 <7.0.0', // Unsupported rapid release versions
|
||||
'>=7.1.0 <8.0.0', // Unsupported rapid release versions
|
||||
],
|
||||
}).check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the Nodejs versions used in test environments.
|
||||
*/
|
||||
async function checkNodeVersions() {
|
||||
const allVersions = (await import('all-node-versions')).default;
|
||||
const { versions } = await allVersions();
|
||||
const nodeVersions = versions.map(version => version.node);
|
||||
|
||||
await new CiVersionCheck({
|
||||
packageName: 'Node.js',
|
||||
packageSupportUrl: 'https://github.com/nodejs/node/blob/master/CHANGELOG.md',
|
||||
yamlFilePath: './.github/workflows/ci.yml',
|
||||
ciEnvironmentsKeyPath: 'jobs.check-mongo.strategy.matrix.include',
|
||||
ciVersionKey: 'NODE_VERSION',
|
||||
releasedVersions: nodeVersions,
|
||||
latestComponent: CiVersionCheck.versionComponents.minor,
|
||||
ignoreReleasedVersions: [
|
||||
'<18.0.0', // These versions have reached their end-of-life support date
|
||||
'>=19.0.0 <20.0.0', // These versions have reached their end-of-life support date
|
||||
'>=21.0.0', // These versions are not officially supported yet
|
||||
],
|
||||
}).check();
|
||||
}
|
||||
|
||||
check();
|
||||
@@ -1,27 +0,0 @@
|
||||
const fs = require('fs').promises;
|
||||
const { exec } = require('child_process');
|
||||
const core = require('@actions/core');
|
||||
const util = require('util');
|
||||
(async () => {
|
||||
const [currentDefinitions, currentDocs] = await Promise.all([
|
||||
fs.readFile('./src/Options/Definitions.js', 'utf8'),
|
||||
fs.readFile('./src/Options/docs.js', 'utf8'),
|
||||
]);
|
||||
const execute = util.promisify(exec);
|
||||
await execute('npm run definitions');
|
||||
const [newDefinitions, newDocs] = await Promise.all([
|
||||
fs.readFile('./src/Options/Definitions.js', 'utf8'),
|
||||
fs.readFile('./src/Options/docs.js', 'utf8'),
|
||||
]);
|
||||
if (currentDefinitions !== newDefinitions || currentDocs !== newDocs) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
'\x1b[31m%s\x1b[0m',
|
||||
'Definitions files cannot be updated manually. Please update src/Options/index.js then run `npm run definitions` to generate definitions.'
|
||||
);
|
||||
core.error('Definitions files cannot be updated manually. Please update src/Options/index.js then run `npm run definitions` to generate definitions.');
|
||||
process.exit(1);
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
})();
|
||||
@@ -1,197 +0,0 @@
|
||||
const core = require('@actions/core');
|
||||
const semver = require('semver');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* This checks whether any package dependency requires a minimum node engine
|
||||
* version higher than the host package.
|
||||
*/
|
||||
class NodeEngineCheck {
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* @param {Object} config The config.
|
||||
* @param {String} config.nodeModulesPath The path to the node_modules directory.
|
||||
* @param {String} config.packageJsonPath The path to the parent package.json file.
|
||||
*/
|
||||
constructor(config) {
|
||||
const {
|
||||
nodeModulesPath,
|
||||
packageJsonPath,
|
||||
} = config;
|
||||
|
||||
// Ensure required params are set
|
||||
if ([
|
||||
nodeModulesPath,
|
||||
packageJsonPath,
|
||||
].includes(undefined)) {
|
||||
throw 'invalid configuration';
|
||||
}
|
||||
|
||||
this.nodeModulesPath = nodeModulesPath;
|
||||
this.packageJsonPath = packageJsonPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of `package.json` files under the given path and subdirectories.
|
||||
* @param {String} [basePath] The base path for recursive directory search.
|
||||
*/
|
||||
async getPackageFiles(basePath = this.nodeModulesPath) {
|
||||
try {
|
||||
// Declare file list
|
||||
const files = []
|
||||
|
||||
// Get files
|
||||
const dirents = await fs.readdir(basePath, { withFileTypes: true });
|
||||
const validFiles = dirents.filter(d => d.name.toLowerCase() == 'package.json').map(d => path.join(basePath, d.name));
|
||||
files.push(...validFiles);
|
||||
|
||||
// For each directory entry
|
||||
for (const dirent of dirents) {
|
||||
if (dirent.isDirectory()) {
|
||||
const subFiles = await this.getPackageFiles(path.join(basePath, dirent.name));
|
||||
files.push(...subFiles);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
} catch (e) {
|
||||
throw `Failed to get package.json files in ${this.nodeModulesPath} with error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts and returns the node engine versions of the given package.json
|
||||
* files.
|
||||
* @param {String[]} files The package.json files.
|
||||
* @param {Boolean} clean Is true if packages with undefined node versions
|
||||
* should be removed from the results.
|
||||
* @returns {Object[]} A list of results.
|
||||
*/
|
||||
async getNodeVersion({ files, clean = false }) {
|
||||
|
||||
// Declare response
|
||||
let response = [];
|
||||
|
||||
// For each file
|
||||
for (const file of files) {
|
||||
// Get node version
|
||||
const contentString = await fs.readFile(file, 'utf-8');
|
||||
try {
|
||||
const contentJson = JSON.parse(contentString);
|
||||
const version = ((contentJson || {}).engines || {}).node;
|
||||
|
||||
// Add response
|
||||
response.push({
|
||||
file: file,
|
||||
nodeVersion: version
|
||||
});
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Ignoring file because it is not valid JSON: ${file}`);
|
||||
core.warning(`Ignoring file because it is not valid JSON: ${file}`);
|
||||
}
|
||||
}
|
||||
|
||||
// If results should be cleaned by removing undefined node versions
|
||||
if (clean) {
|
||||
response = response.filter(r => r.nodeVersion !== undefined);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest semver definition that satisfies all versions
|
||||
* in the given list.
|
||||
* @param {String[]} versions The list of semver version ranges.
|
||||
* @param {String} baseVersion The base version of which higher versions should be
|
||||
* determined; as a version (1.2.3), not a range (>=1.2.3).
|
||||
* @returns {String} The highest semver version.
|
||||
*/
|
||||
getHigherVersions({ versions, baseVersion }) {
|
||||
// Add min satisfying node versions
|
||||
const minVersions = versions.map(v => {
|
||||
v.nodeMinVersion = semver.minVersion(v.nodeVersion)
|
||||
return v;
|
||||
});
|
||||
|
||||
// Sort by min version
|
||||
const sortedMinVersions = minVersions.sort((v1, v2) => semver.compare(v1.nodeMinVersion, v2.nodeMinVersion));
|
||||
|
||||
// Filter by higher versions
|
||||
const higherVersions = sortedMinVersions.filter(v => semver.gt(v.nodeMinVersion, baseVersion));
|
||||
// console.log(`getHigherVersions: ${JSON.stringify(higherVersions)}`);
|
||||
return higherVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node version of the parent package.
|
||||
* @return {Object} The parent package info.
|
||||
*/
|
||||
async getParentVersion() {
|
||||
// Get parent package.json version
|
||||
const version = await this.getNodeVersion({ files: [ this.packageJsonPath ], clean: true });
|
||||
// console.log(`getParentVersion: ${JSON.stringify(version)}`);
|
||||
return version[0];
|
||||
}
|
||||
}
|
||||
|
||||
async function check() {
|
||||
// Define paths
|
||||
const nodeModulesPath = path.join(__dirname, '../node_modules');
|
||||
const packageJsonPath = path.join(__dirname, '../package.json');
|
||||
|
||||
// Create check
|
||||
const check = new NodeEngineCheck({
|
||||
nodeModulesPath,
|
||||
packageJsonPath,
|
||||
});
|
||||
|
||||
// Get package node version of parent package
|
||||
const parentVersion = await check.getParentVersion();
|
||||
|
||||
// If parent node version could not be determined
|
||||
if (parentVersion === undefined) {
|
||||
core.setFailed(`Failed to determine node engine version of parent package at ${this.packageJsonPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine parent min version
|
||||
const parentMinVersion = semver.minVersion(parentVersion.nodeVersion);
|
||||
|
||||
// Get package.json files
|
||||
const files = await check.getPackageFiles();
|
||||
core.info(`Checking the minimum node version requirement of ${files.length} dependencies`);
|
||||
|
||||
// Get node versions
|
||||
const versions = await check.getNodeVersion({ files, clean: true });
|
||||
|
||||
// Get are dependencies that require a higher node version than the parent package
|
||||
const higherVersions = check.getHigherVersions({ versions, baseVersion: parentMinVersion });
|
||||
|
||||
// Get highest version
|
||||
const highestVersion = higherVersions.map(v => v.nodeMinVersion).pop();
|
||||
|
||||
/* eslint-disable no-console */
|
||||
// If there are higher versions
|
||||
if (higherVersions.length > 0) {
|
||||
console.log(`\nThere are ${higherVersions.length} dependencies that require a higher node engine version than the parent package (${parentVersion.nodeVersion}):`);
|
||||
|
||||
// For each dependency
|
||||
for (const higherVersion of higherVersions) {
|
||||
|
||||
// Get package name
|
||||
const _package = higherVersion.file.split('node_modules/').pop().replace('/package.json', '');
|
||||
console.log(`- ${_package} requires at least node ${higherVersion.nodeMinVersion} (${higherVersion.nodeVersion})`);
|
||||
}
|
||||
console.log('');
|
||||
core.setFailed(`❌ Upgrade the node engine version in package.json to at least '${highestVersion}' to satisfy the dependencies.`);
|
||||
console.log('');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ All dependencies satisfy the node version requirement of the parent package (${parentVersion.nodeVersion}).`);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
|
||||
check();
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Read package exclusion list from arguments
|
||||
exclusionList=("$@")
|
||||
|
||||
# Convert exclusion list to grep pattern
|
||||
exclusionPattern=$(printf "|%s" "${exclusionList[@]}")
|
||||
exclusionPattern=${exclusionPattern:1}
|
||||
|
||||
# Get list of all dev dependencies
|
||||
devDeps=$(jq -r '.devDependencies | keys | .[]' package.json)
|
||||
|
||||
# Filter out exclusion list
|
||||
depsToUninstall=$(echo "$devDeps" | grep -Ev "$exclusionPattern")
|
||||
|
||||
# If there are dependencies to uninstall then uninstall them
|
||||
if [ -n "$depsToUninstall" ]; then
|
||||
echo "Uninstalling dev dependencies: $depsToUninstall"
|
||||
npm uninstall $depsToUninstall
|
||||
else
|
||||
echo "No dev dependencies to uninstall"
|
||||
fi
|
||||
@@ -1,47 +0,0 @@
|
||||
const js = require("@eslint/js");
|
||||
const babelParser = require("@babel/eslint-parser");
|
||||
const globals = require("globals");
|
||||
const unusedImports = require("eslint-plugin-unused-imports");
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
ignores: ["**/lib/**", "**/coverage/**", "**/out/**", "**/types/**"],
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: babelParser,
|
||||
ecmaVersion: 6,
|
||||
sourceType: "module",
|
||||
globals: {
|
||||
Parse: "readonly",
|
||||
...globals.node,
|
||||
},
|
||||
parserOptions: {
|
||||
requireConfigFile: false,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
"unused-imports": unusedImports,
|
||||
},
|
||||
rules: {
|
||||
indent: ["error", 2, { SwitchCase: 1 }],
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
"unused-imports/no-unused-vars": "error",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"no-trailing-spaces": "error",
|
||||
"eol-last": "error",
|
||||
"space-in-parens": ["error", "never"],
|
||||
"no-multiple-empty-lines": "warn",
|
||||
"prefer-const": "error",
|
||||
"space-infix-ops": "error",
|
||||
"no-useless-escape": "off",
|
||||
"require-atomic-updates": "off",
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
curly: ["error", "all"],
|
||||
"block-spacing": ["error", "always"],
|
||||
"no-unused-vars": "off",
|
||||
"no-console": "warn"
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"plugins": ["node_modules/jsdoc-babel", "plugins/markdown"],
|
||||
"babel": {
|
||||
"plugins": ["@babel/plugin-transform-flow-strip-types"]
|
||||
},
|
||||
"source": {
|
||||
"include": [
|
||||
"README.md",
|
||||
"./lib/cloud-code",
|
||||
"./lib/Options/docs.js",
|
||||
"./lib/ParseServer.js",
|
||||
"./lib/Adapters"
|
||||
],
|
||||
"excludePattern": "(^|\\/|\\\\)_"
|
||||
},
|
||||
"templates": {
|
||||
"default": {
|
||||
"outputSourceFiles": false,
|
||||
"showInheritedInNav": false,
|
||||
"useLongnameInNav": true
|
||||
},
|
||||
"cleverLinks": true,
|
||||
"monospaceLinks": false
|
||||
},
|
||||
"opts": {
|
||||
"encoding": "utf8",
|
||||
"readme": "./README.md",
|
||||
"recurse": true,
|
||||
"template": "./node_modules/clean-jsdoc-theme",
|
||||
"theme_opts": {
|
||||
"default_theme": "dark",
|
||||
"title": "<img src='https://raw.githubusercontent.com/parse-community/parse-server/alpha/.github/parse-server-logo.png' class='logo'/>",
|
||||
"create_style": "header, .sidebar-section-title, .sidebar-title { color: #139cee !important } .logo { margin-left : 40px; margin-right: 40px; height: auto; max-width: 100%; object-fit: contain; }"
|
||||
}
|
||||
},
|
||||
"markdown": {
|
||||
"hardwrap": false,
|
||||
"idInHeadings": true
|
||||
}
|
||||
}
|
||||
64406
package-lock.json
generated
64406
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
198
package.json
198
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "parse-server",
|
||||
"version": "9.1.0-alpha.1",
|
||||
"version": "2.8.6",
|
||||
"description": "An express module providing a Parse-compatible API server",
|
||||
"main": "lib/index.js",
|
||||
"repository": {
|
||||
@@ -13,162 +13,90 @@
|
||||
"public_html/",
|
||||
"views/",
|
||||
"LICENSE",
|
||||
"NOTICE",
|
||||
"PATENTS",
|
||||
"postinstall.js",
|
||||
"README.md",
|
||||
"types"
|
||||
"README.md"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@apollo/server": "5.0.0",
|
||||
"@as-integrations/express5": "1.1.2",
|
||||
"@graphql-tools/merge": "9.0.24",
|
||||
"@graphql-tools/schema": "10.0.23",
|
||||
"@graphql-tools/utils": "10.8.6",
|
||||
"@parse/fs-files-adapter": "3.0.0",
|
||||
"@parse/push-adapter": "8.1.0",
|
||||
"bcryptjs": "3.0.2",
|
||||
"commander": "13.1.0",
|
||||
"cors": "2.8.5",
|
||||
"deepcopy": "2.1.0",
|
||||
"express": "5.2.1",
|
||||
"express-rate-limit": "7.5.1",
|
||||
"follow-redirects": "1.15.9",
|
||||
"graphql": "16.11.0",
|
||||
"graphql-list-fields": "2.0.4",
|
||||
"graphql-relay": "0.10.2",
|
||||
"graphql-upload": "15.0.2",
|
||||
"@parse/fs-files-adapter": "1.0.1",
|
||||
"@parse/push-adapter": "3.0.0-alpha2",
|
||||
"@parse/s3-files-adapter": "1.2.1",
|
||||
"@parse/simple-mailgun-adapter": "1.0.2",
|
||||
"bcrypt": "3.0.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.18.3",
|
||||
"commander": "2.16.0",
|
||||
"deepcopy": "1.0.0",
|
||||
"express": "4.16.2",
|
||||
"gamecenter-identity-verifier": "^0.1.1",
|
||||
"intersect": "1.0.1",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"jwks-rsa": "3.2.0",
|
||||
"ldapjs": "3.0.7",
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "10.4.0",
|
||||
"mime": "4.0.7",
|
||||
"mongodb": "6.20.0",
|
||||
"mustache": "4.2.0",
|
||||
"otpauth": "9.4.0",
|
||||
"parse": "8.0.0",
|
||||
"path-to-regexp": "8.3.0",
|
||||
"pg-monitor": "3.0.0",
|
||||
"pg-promise": "12.2.0",
|
||||
"pluralize": "8.0.0",
|
||||
"punycode": "2.3.1",
|
||||
"rate-limit-redis": "4.2.0",
|
||||
"redis": "4.7.0",
|
||||
"semver": "7.7.2",
|
||||
"subscriptions-transport-ws": "0.11.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwks-rsa": "^1.12.3",
|
||||
"lodash": "4.17.5",
|
||||
"lru-cache": "4.1.2",
|
||||
"mime": "2.3.1",
|
||||
"mongodb": "3.1.1",
|
||||
"parse": "1.11.1",
|
||||
"pg-promise": "8.4.5",
|
||||
"redis": "2.8.0",
|
||||
"request": "2.85.0",
|
||||
"semver": "5.5.0",
|
||||
"steam-appticket": "1.0.1",
|
||||
"tv4": "1.3.0",
|
||||
"uuid": "11.1.0",
|
||||
"winston": "3.17.0",
|
||||
"winston-daily-rotate-file": "5.0.0",
|
||||
"ws": "8.18.2"
|
||||
"uuid": "^3.1.0",
|
||||
"uws": "10.148.1",
|
||||
"winston": "2.4.1",
|
||||
"winston-daily-rotate-file": "1.7.2",
|
||||
"ws": "6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "1.11.1",
|
||||
"@apollo/client": "3.13.8",
|
||||
"@babel/cli": "7.27.0",
|
||||
"@babel/core": "7.27.4",
|
||||
"@babel/eslint-parser": "7.28.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
||||
"@babel/plugin-transform-flow-strip-types": "7.26.5",
|
||||
"@babel/preset-env": "7.27.2",
|
||||
"@babel/preset-typescript": "7.27.1",
|
||||
"@saithodev/semantic-release-backmerge": "4.0.1",
|
||||
"@semantic-release/changelog": "6.0.3",
|
||||
"@semantic-release/commit-analyzer": "13.0.1",
|
||||
"@semantic-release/git": "10.0.1",
|
||||
"@semantic-release/github": "11.0.2",
|
||||
"@semantic-release/npm": "12.0.1",
|
||||
"@semantic-release/release-notes-generator": "14.0.3",
|
||||
"all-node-versions": "13.0.1",
|
||||
"apollo-upload-client": "18.0.1",
|
||||
"clean-jsdoc-theme": "4.3.0",
|
||||
"cross-env": "7.0.3",
|
||||
"deep-diff": "1.0.2",
|
||||
"eslint": "9.27.0",
|
||||
"eslint-plugin-expect-type": "0.6.2",
|
||||
"eslint-plugin-unused-imports": "4.3.0",
|
||||
"form-data": "4.0.5",
|
||||
"globals": "16.2.0",
|
||||
"graphql-tag": "2.12.6",
|
||||
"jasmine": "5.7.1",
|
||||
"jasmine-spec-reporter": "7.0.0",
|
||||
"jsdoc": "4.0.4",
|
||||
"jsdoc-babel": "0.5.0",
|
||||
"lint-staged": "16.1.0",
|
||||
"m": "1.9.1",
|
||||
"madge": "8.0.0",
|
||||
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",
|
||||
"mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter",
|
||||
"mongodb-runner": "5.9.3",
|
||||
"node-abort-controller": "3.1.1",
|
||||
"node-fetch": "3.2.10",
|
||||
"nyc": "17.1.0",
|
||||
"prettier": "2.0.5",
|
||||
"semantic-release": "24.2.5",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "8.33.1",
|
||||
"yaml": "2.8.0"
|
||||
"babel-cli": "6.26.0",
|
||||
"babel-core": "6.26.0",
|
||||
"babel-eslint": "^8.2.2",
|
||||
"babel-plugin-transform-flow-strip-types": "6.22.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-env": "1.6.1",
|
||||
"bcrypt-nodejs": "0.0.3",
|
||||
"cross-env": "5.2.0",
|
||||
"deep-diff": "1.0.1",
|
||||
"eslint": "^5.0.0",
|
||||
"eslint-plugin-flowtype": "^2.39.1",
|
||||
"flow-bin": "^0.76.0",
|
||||
"gaze": "1.1.3",
|
||||
"jasmine": "3.1.0",
|
||||
"jasmine-spec-reporter": "^4.1.0",
|
||||
"mongodb-runner": "4.0.0",
|
||||
"nodemon": "1.18.1",
|
||||
"nyc": "^12.0.2",
|
||||
"request-promise": "4.2.2",
|
||||
"supports-color": "^5.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"ci:check": "node ./ci/ciCheck.js",
|
||||
"ci:checkNodeEngine": "node ./ci/nodeEngineCheck.js",
|
||||
"ci:definitionsCheck": "node ./ci/definitionsCheck.js",
|
||||
"definitions": "node ./resources/buildConfigDefinitions.js && prettier --write 'src/Options/*.js'",
|
||||
"docs": "jsdoc -c ./jsdoc-conf.json",
|
||||
"lint": "eslint --cache ./ --flag unstable_config_lookup_from_file",
|
||||
"lint-fix": "eslint --fix --cache ./ --flag unstable_config_lookup_from_file",
|
||||
"build": "babel src/ -d lib/ --copy-files --extensions '.ts,.js'",
|
||||
"build:types": "tsc",
|
||||
"dev": "npm run build && node bin/dev",
|
||||
"lint": "flow && eslint --cache ./",
|
||||
"build": "babel src/ -d lib/ --copy-files",
|
||||
"watch": "babel --watch src/ -d lib/ --copy-files",
|
||||
"watch:ts": "tsc --watch",
|
||||
"test:mongodb:7.0.16": "MONGODB_VERSION=7.0.16 npm run test",
|
||||
"test:mongodb:8.0.4": "MONGODB_VERSION=8.0.4 npm run test",
|
||||
"test:postgres:testonly": "cross-env PARSE_SERVER_TEST_DB=postgres PARSE_SERVER_TEST_DATABASE_URI=postgres://postgres:password@localhost:5432/parse_server_postgres_adapter_test_database npm run testonly",
|
||||
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
||||
"test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner exec -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017 -- npm run testonly",
|
||||
"test:types": "eslint types/tests.ts -c ./types/eslint.config.mjs",
|
||||
"coverage:mongodb": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner exec -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017 -- npm run coverage",
|
||||
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
|
||||
"pretest": "npm run lint",
|
||||
"test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 TESTING=1 jasmine",
|
||||
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 TESTING=1 nyc jasmine",
|
||||
"start": "node ./bin/parse-server",
|
||||
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
|
||||
"prepare": "npm run build",
|
||||
"postinstall": "node -p 'require(\"./postinstall.js\")()'",
|
||||
"madge:circular": "node_modules/.bin/madge ./src --circular",
|
||||
"benchmark": "cross-env MONGODB_VERSION=8.0.4 MONGODB_TOPOLOGY=standalone mongodb-runner exec -t standalone --version 8.0.4 -- --port 27017 -- npm run benchmark:only",
|
||||
"benchmark:only": "node benchmark/performance.js",
|
||||
"benchmark:quick": "cross-env BENCHMARK_ITERATIONS=10 npm run benchmark:only"
|
||||
"postinstall": "node -p 'require(\"./postinstall.js\")()'"
|
||||
},
|
||||
"types": "types/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=20.19.0 <21.0.0 || >=22.12.0 <23.0.0 || >=24.11.0 <25.0.0"
|
||||
"node": ">= 8"
|
||||
},
|
||||
"bin": {
|
||||
"parse-server": "bin/parse-server"
|
||||
"parse-server": "./bin/parse-server"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@node-rs/bcrypt": "1.10.7"
|
||||
"bcrypt": "3.0.0",
|
||||
"uws": "10.148.1"
|
||||
},
|
||||
"collective": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parse-server",
|
||||
"logo": "https://opencollective.com/parse-server/logo.txt?reverse=true&variant=binary"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parse-server"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"{src,spec}/{**/*,*}.js": [
|
||||
"prettier --write",
|
||||
"eslint --fix --cache",
|
||||
"git add"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,50 @@
|
||||
const message = `
|
||||
1111111111
|
||||
1111111111111111
|
||||
1111111111111111111111
|
||||
11111111111111111111111111
|
||||
111111111111111 11111111
|
||||
1111111111111 111 111111
|
||||
1111111111111 111111111 111111
|
||||
111111111111 11111111111 111111
|
||||
1111111111111 11111111111 111111
|
||||
1111111111111 1111111111 111111
|
||||
1111111111111111111111111 1111111
|
||||
11111111 11111111
|
||||
111111 111 1111111111111111111
|
||||
11111 11111 111111111111111111
|
||||
11111 1 11111111111111111
|
||||
111111 111111111111111111
|
||||
11111111111111111111111111
|
||||
1111111111111111111111
|
||||
111111111111111111
|
||||
11111111111
|
||||
|
||||
Thank you for using Parse Platform!
|
||||
https://parseplatform.org
|
||||
|
||||
Please consider donating to help us maintain
|
||||
this package:
|
||||
const pkg = require('./package.json');
|
||||
|
||||
👉 https://opencollective.com/parse-server 👈
|
||||
const version = parseFloat(process.version.substr(1));
|
||||
const minimum = parseFloat(pkg.engines.node.match(/\d+/g).join('.'));
|
||||
|
||||
`;
|
||||
module.exports = function () {
|
||||
const openCollective = `
|
||||
1111111111
|
||||
1111111111111111
|
||||
1111111111111111111111
|
||||
11111111111111111111111111
|
||||
111111111111111 11111111
|
||||
1111111111111 111111
|
||||
1111111111111 111111111 111111
|
||||
111111111111 11111111111 111111
|
||||
1111111111111 11111111111 111111
|
||||
1111111111111 1111111111 111111
|
||||
1111111111111111111111111 1111111
|
||||
11111111 11111111
|
||||
111111 1111111111111111111
|
||||
11111 11111 111111111111111111
|
||||
11111 11111111111111111
|
||||
111111 111111111111111111
|
||||
11111111111111111111111111
|
||||
1111111111111111111111
|
||||
111111111111111111
|
||||
11111111111
|
||||
|
||||
function main() {
|
||||
process.stdout.write(message);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = main;
|
||||
Thanks for installing parse 🙏
|
||||
Please consider donating to our open collective
|
||||
to help us maintain this package.
|
||||
|
||||
👉 https://opencollective.com/parse-server
|
||||
|
||||
`;
|
||||
process.stdout.write(openCollective);
|
||||
if (version >= minimum) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const errorMessage = `
|
||||
⚠️ parse-server requires at least node@${minimum}!
|
||||
You have node@${version}
|
||||
|
||||
`;
|
||||
|
||||
process.stdout.write(errorMessage);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page demonstrates how to localize using a JSON file that contains the
|
||||
translations for each placeholder.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{heading}}</h1>
|
||||
<p>{{body}}</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"en": {
|
||||
"translation": {
|
||||
"title": "Hello!",
|
||||
"heading": "Welcome to {{appName}}!",
|
||||
"body": "We are delighted to welcome you on board."
|
||||
}
|
||||
},
|
||||
"de": {
|
||||
"translation": {
|
||||
"title": "Hallo!",
|
||||
"heading": "Willkommen bei {{appName}}!",
|
||||
"body": "Wir freuen uns, dich begrüßen zu dürfen."
|
||||
}
|
||||
},
|
||||
"de-AT": {
|
||||
"translation": {
|
||||
"title": "Servus!",
|
||||
"heading": "Willkommen bei {{appName}}!",
|
||||
"body": "Wir freuen uns, dich begrüßen zu dürfen."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page demonstrates how to use custom pages in custom routes.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{appName}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a security
|
||||
token that is expired or incorrect. This can either mean the user has clicked
|
||||
on a stale link (i.e. re-clicked on the link) or this could be a sign of a
|
||||
malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Expired verification link!</h1>
|
||||
<form method="POST" action="{{{publicServerUrl}}}/apps/{{{appId}}}/resend_verification_email">
|
||||
<input name="token" type="hidden" value="{{{token}}}">
|
||||
<input name="locale" type="hidden" value="{{{locale}}}">
|
||||
<button type="submit">Resend Link</button>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with parameters
|
||||
that are missing or incorrect. This can either mean the user has incorrectly
|
||||
entered a link or this could be a sign of a malicious user trying to tamper
|
||||
with your app.
|
||||
If the link contains an expired security token (or the email has already
|
||||
been verified), this page is not displayed, there is another page for that.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid verification link!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a security
|
||||
token that is expired or incorrect, then requests to receive another link,
|
||||
but it fails because the username is invalid or the email has already been
|
||||
verified. This can either mean the user has previously verified the email
|
||||
or this could be a sign of a malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid link!</h1>
|
||||
<p>No link sent. User not found or email already verified.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a
|
||||
security token that is expired, then requests to receive another email
|
||||
with a new link and the email is sent successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Link sent!</h1>
|
||||
<p>A new link has been sent. Check your email.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link and the
|
||||
email gets verified successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Email verified!</h1>
|
||||
<p>Successfully verified your email for account: {{username}}.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,65 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when someone clicks a valid 'reset password' link.
|
||||
Users should feel free to add to this page (i.e. branding or security widgets)
|
||||
but should be sure not to delete any of the form inputs or the javascript from the
|
||||
template file. This javascript is what adds the necessary values to authenticate
|
||||
this session with Parse.
|
||||
The query params 'username' and 'app' hold the friendly names for your current user and
|
||||
your app. You should feel free to incorporate their values to make the page more personal.
|
||||
If you are missing form parameters in your POST, Parse will navigate back to this page and
|
||||
add an 'error' query parameter.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Reset Your Password</h1>
|
||||
<noscript><p>We apologize, but resetting your password requires javascript</p></noscript>
|
||||
<p>You can set a new Password for your account: {{username}}</p>
|
||||
<br />
|
||||
<p>{{error}}</p>
|
||||
<form id='form' action='{{{publicServerUrl}}}/apps/{{{appId}}}/request_password_reset' method='POST'>
|
||||
<input name='utf-8' type='hidden' value='✓' />
|
||||
<input name="username" type="hidden" id="username" value="{{{username}}}" />
|
||||
<input name="token" type="hidden" id="token" value="{{{token}}}" />
|
||||
<input name="locale" type="hidden" id="locale" value="{{{locale}}}" />
|
||||
|
||||
<p>New Password</p>
|
||||
<input name="new_password" type="password" id="password" />
|
||||
<p>Confirm New Password</p>
|
||||
<input name="confirm_new_password" type="password" id="password_confirm" />
|
||||
<br />
|
||||
<p id="password_match_info"></p>
|
||||
<br />
|
||||
<button id="change_password">Change Password</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
document.getElementById("password").oninput = validatePassword;
|
||||
document.getElementById("password_confirm").oninput = validatePassword;
|
||||
document.getElementById("change_password").disabled = true;
|
||||
|
||||
function validatePassword() {
|
||||
var pass2 = document.getElementById("password").value;
|
||||
var pass1 = document.getElementById("password_confirm").value;
|
||||
if(pass1 !== pass2) {
|
||||
if(document.getElementById("password_confirm").value) {
|
||||
document.getElementById("change_password").disabled = true;
|
||||
document.getElementById("password_match_info").innerHTML = "Must match the previous entry";
|
||||
}
|
||||
} else {
|
||||
document.getElementById("change_password").disabled = false;
|
||||
document.getElementById("password_match_info").innerHTML = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a password reset link with parameters
|
||||
that are missing or incorrect. This can either mean the user has incorrectly
|
||||
entered a link or this could be a sign of a malicious user trying to tamper
|
||||
with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid password reset link!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a reset password link, then submits
|
||||
the form with a new password and the password gets updated successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Success!</h1>
|
||||
<p>Your password has been updated.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a security
|
||||
token that is expired or incorrect. This can either mean the user has clicked
|
||||
on a stale link (i.e. re-clicked on the link) or this could be a sign of a
|
||||
malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Expired verification link!</h1>
|
||||
<form method="POST" action="{{{publicServerUrl}}}/apps/{{{appId}}}/resend_verification_email">
|
||||
<input name="token" type="hidden" value="{{{token}}}">
|
||||
<input name="locale" type="hidden" value="{{{locale}}}">
|
||||
<button type="submit">Resend Link</button>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with parameters
|
||||
that are missing or incorrect. This can either mean the user has incorrectly
|
||||
entered a link or this could be a sign of a malicious user trying to tamper
|
||||
with your app.
|
||||
If the link contains an expired security token (or the email has already
|
||||
been verified), this page is not displayed, there is another page for that.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid verification link!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a security
|
||||
token that is expired or incorrect, then requests to receive another link,
|
||||
but it fails because the username is invalid or the email has already been
|
||||
verified. This can either mean the user has previously verified the email
|
||||
or this could be a sign of a malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid link!</h1>
|
||||
<p>No link sent. User not found or email already verified.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a
|
||||
security token that is expired, then requests to receive another email
|
||||
with a new link and the email is sent successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Link sent!</h1>
|
||||
<p>A new link has been sent. Check your email.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link and the
|
||||
email gets verified successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Email verified!</h1>
|
||||
<p>Successfully verified your email for account: {{username}}.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,65 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when someone clicks a valid 'reset password' link.
|
||||
Users should feel free to add to this page (i.e. branding or security widgets)
|
||||
but should be sure not to delete any of the form inputs or the javascript from the
|
||||
template file. This javascript is what adds the necessary values to authenticate
|
||||
this session with Parse.
|
||||
The query params 'username' and 'app' hold the friendly names for your current user and
|
||||
your app. You should feel free to incorporate their values to make the page more personal.
|
||||
If you are missing form parameters in your POST, Parse will navigate back to this page and
|
||||
add an 'error' query parameter.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Reset Your Password</h1>
|
||||
<noscript><p>We apologize, but resetting your password requires javascript</p></noscript>
|
||||
<p>You can set a new Password for your account: {{username}}</p>
|
||||
<br />
|
||||
<p>{{error}}</p>
|
||||
<form id='form' action='{{{publicServerUrl}}}/apps/{{{appId}}}/request_password_reset' method='POST'>
|
||||
<input name='utf-8' type='hidden' value='✓' />
|
||||
<input name="username" type="hidden" id="username" value="{{{username}}}" />
|
||||
<input name="token" type="hidden" id="token" value="{{{token}}}" />
|
||||
<input name="locale" type="hidden" id="locale" value="{{{locale}}}" />
|
||||
|
||||
<p>New Password</p>
|
||||
<input name="new_password" type="password" id="password" />
|
||||
<p>Confirm New Password</p>
|
||||
<input name="confirm_new_password" type="password" id="password_confirm" />
|
||||
<br />
|
||||
<p id="password_match_info"></p>
|
||||
<br />
|
||||
<button id="change_password">Change Password</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
document.getElementById("password").oninput = validatePassword;
|
||||
document.getElementById("password_confirm").oninput = validatePassword;
|
||||
document.getElementById("change_password").disabled = true;
|
||||
|
||||
function validatePassword() {
|
||||
var pass2 = document.getElementById("password").value;
|
||||
var pass1 = document.getElementById("password_confirm").value;
|
||||
if(pass1 !== pass2) {
|
||||
if(document.getElementById("password_confirm").value) {
|
||||
document.getElementById("change_password").disabled = true;
|
||||
document.getElementById("password_match_info").innerHTML = "Must match the previous entry";
|
||||
}
|
||||
} else {
|
||||
document.getElementById("change_password").disabled = false;
|
||||
document.getElementById("password_match_info").innerHTML = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a password reset link with parameters
|
||||
that are missing or incorrect. This can either mean the user has incorrectly
|
||||
entered a link or this could be a sign of a malicious user trying to tamper
|
||||
with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid password reset link!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a reset password link, then submits
|
||||
the form with a new password and the password gets updated successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Success!</h1>
|
||||
<p>Your password has been updated.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a security
|
||||
token that is expired or incorrect. This can either mean the user has clicked
|
||||
on a stale link (i.e. re-clicked on the link) or this could be a sign of a
|
||||
malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Expired verification link!</h1>
|
||||
<form method="POST" action="{{{publicServerUrl}}}/apps/{{{appId}}}/resend_verification_email">
|
||||
<input name="token" type="hidden" value="{{{token}}}">
|
||||
<input name="locale" type="hidden" value="{{{locale}}}">
|
||||
<button type="submit">Resend Link</button>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with parameters
|
||||
that are missing or incorrect. This can either mean the user has incorrectly
|
||||
entered a link or this could be a sign of a malicious user trying to tamper
|
||||
with your app.
|
||||
If the link contains an expired security token (or the email has already
|
||||
been verified), this page is not displayed, there is another page for that.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid verification link!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a security
|
||||
token that is expired or incorrect, then requests to receive another link,
|
||||
but it fails because the username is invalid or the email has already been
|
||||
verified. This can either mean the user has previously verified the email
|
||||
or this could be a sign of a malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid link!</h1>
|
||||
<p>No link sent. User not found or email already verified.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link with a
|
||||
security token that is expired, then requests to receive another email
|
||||
with a new link and the email is sent successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Link sent!</h1>
|
||||
<p>A new link has been sent. Check your email.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a verify email link and the
|
||||
email gets verified successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Email verified!</h1>
|
||||
<p>Successfully verified your email for account: {{username}}.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,65 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when someone clicks a valid 'reset password' link.
|
||||
Users should feel free to add to this page (i.e. branding or security widgets)
|
||||
but should be sure not to delete any of the form inputs or the javascript from the
|
||||
template file. This javascript is what adds the necessary values to authenticate
|
||||
this session with Parse.
|
||||
The query params 'username' and 'app' hold the friendly names for your current user and
|
||||
your app. You should feel free to incorporate their values to make the page more personal.
|
||||
If you are missing form parameters in your POST, Parse will navigate back to this page and
|
||||
add an 'error' query parameter.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Reset Your Password</h1>
|
||||
<noscript><p>We apologize, but resetting your password requires javascript</p></noscript>
|
||||
<p>You can set a new Password for your account: {{username}}</p>
|
||||
<br />
|
||||
<p>{{error}}</p>
|
||||
<form id='form' action='{{{publicServerUrl}}}/apps/{{{appId}}}/request_password_reset' method='POST'>
|
||||
<input name='utf-8' type='hidden' value='✓' />
|
||||
<input name="username" type="hidden" id="username" value="{{{username}}}" />
|
||||
<input name="token" type="hidden" id="token" value="{{{token}}}" />
|
||||
<input name="locale" type="hidden" id="locale" value="{{{locale}}}" />
|
||||
|
||||
<p>New Password</p>
|
||||
<input name="new_password" type="password" id="password" />
|
||||
<p>Confirm New Password</p>
|
||||
<input name="confirm_new_password" type="password" id="password_confirm" />
|
||||
<br />
|
||||
<p id="password_match_info"></p>
|
||||
<br />
|
||||
<button id="change_password">Change Password</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
document.getElementById("password").oninput = validatePassword;
|
||||
document.getElementById("password_confirm").oninput = validatePassword;
|
||||
document.getElementById("change_password").disabled = true;
|
||||
|
||||
function validatePassword() {
|
||||
var pass2 = document.getElementById("password").value;
|
||||
var pass1 = document.getElementById("password_confirm").value;
|
||||
if(pass1 !== pass2) {
|
||||
if(document.getElementById("password_confirm").value) {
|
||||
document.getElementById("change_password").disabled = true;
|
||||
document.getElementById("password_match_info").innerHTML = "Must match the previous entry";
|
||||
}
|
||||
} else {
|
||||
document.getElementById("change_password").disabled = false;
|
||||
document.getElementById("password_match_info").innerHTML = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a password reset link with parameters
|
||||
that are missing or incorrect. This can either mean the user has incorrectly
|
||||
entered a link or this could be a sign of a malicious user trying to tamper
|
||||
with your app.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Invalid password reset link!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
This page is displayed when a user opens a reset password link, then submits
|
||||
the form with a new password and the password gets updated successfully.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{appName}}</h1>
|
||||
<h1>Success!</h1>
|
||||
<p>Your password has been updated.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
45
public_html/invalid_link.html
Normal file
45
public_html/invalid_link.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- This page is displayed when someone navigates to a verify email or reset password link
|
||||
but their security token is wrong. This can either mean the user has clicked on a
|
||||
stale link (i.e. re-click on a password reset link after resetting their password) or
|
||||
(rarely) this could be a sign of a malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Invalid Link</title>
|
||||
<style type='text/css'>
|
||||
.container {
|
||||
border-width: 0px;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Helvetica Neue', Helvetica;
|
||||
font-size: 16px;
|
||||
height: 30px;
|
||||
line-height: 16px;
|
||||
margin: 45px 0px 0px 45px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
color: #0067AB;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 0 0 15px 0;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Invalid Link</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
68
public_html/invalid_verification_link.html
Normal file
68
public_html/invalid_verification_link.html
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- This page is displayed when someone navigates to a verify email or reset password link
|
||||
but their security token is wrong. This can either mean the user has clicked on a
|
||||
stale link (i.e. re-click on a password reset link after resetting their password) or
|
||||
(rarely) this could be a sign of a malicious user trying to tamper with your app.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Invalid Link</title>
|
||||
<style type='text/css'>
|
||||
.container {
|
||||
border-width: 0px;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Helvetica Neue', Helvetica;
|
||||
font-size: 16px;
|
||||
height: 30px;
|
||||
line-height: 16px;
|
||||
margin: 45px 0px 0px 45px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
color: #0067AB;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 0 0 15px 0;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function getUrlParameter(name) {
|
||||
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
|
||||
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
|
||||
var results = regex.exec(location.search);
|
||||
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||
};
|
||||
|
||||
window.onload = addDataToForm;
|
||||
|
||||
function addDataToForm() {
|
||||
var username = getUrlParameter("username");
|
||||
document.getElementById("usernameField").value = username;
|
||||
|
||||
var appId = getUrlParameter("appId");
|
||||
document.getElementById("resendForm").action = '/apps/' + appId + '/resend_verification_email'
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Invalid Verification Link</h1>
|
||||
<form id="resendForm" method="POST" action="/resend_verification_email">
|
||||
<input id="usernameField" class="form-control" name="username" type="hidden" value="">
|
||||
<button type="submit" class="btn btn-default">Resend Link</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
45
public_html/link_send_fail.html
Normal file
45
public_html/link_send_fail.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- This page is displayed when someone navigates to a verify email link with an invalid
|
||||
security token and requests a link resend. This page is displayed when the username from
|
||||
the original link is invalid or if the email of that user has already been verfieid when
|
||||
the resend request is made
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Invalid Link</title>
|
||||
<style type='text/css'>
|
||||
.container {
|
||||
border-width: 0px;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Helvetica Neue', Helvetica;
|
||||
font-size: 16px;
|
||||
height: 30px;
|
||||
line-height: 16px;
|
||||
margin: 45px 0px 0px 45px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
color: #0067AB;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 0 0 15px 0;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>No link sent. User not found or email already verified</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
45
public_html/link_send_success.html
Normal file
45
public_html/link_send_success.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- This page is displayed when someone navigates to a verify email link with an invalid
|
||||
security token and requests a link resend. This page is displayed when the username
|
||||
from the original verification link has been found and a new verification link has
|
||||
been successfully sent to the corresponding stored email
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Invalid Link</title>
|
||||
<style type='text/css'>
|
||||
.container {
|
||||
border-width: 0px;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Helvetica Neue', Helvetica;
|
||||
font-size: 16px;
|
||||
height: 30px;
|
||||
line-height: 16px;
|
||||
margin: 45px 0px 0px 45px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
color: #0067AB;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 0 0 15px 0;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Link Sent! Check your email.</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
27
public_html/password_reset_success.html
Normal file
27
public_html/password_reset_success.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- This page is displayed whenever someone has successfully reset their password.
|
||||
Pro and Enterprise accounts may edit this page and tell Parse to use that custom
|
||||
version in their Parse app. See the App Settigns page for more information.
|
||||
This page will be called with the query param 'username'
|
||||
-->
|
||||
<head>
|
||||
<title>Password Reset</title>
|
||||
<style type='text/css'>
|
||||
h1 {
|
||||
color: #0067AB;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 45px 0px 0px 45px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h1>Successfully updated your password!</h1>
|
||||
</body>
|
||||
</html>
|
||||
27
public_html/verify_email_success.html
Normal file
27
public_html/verify_email_success.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- This page is displayed whenever someone has successfully reset their password.
|
||||
Pro and Enterprise accounts may edit this page and tell Parse to use that custom
|
||||
version in their Parse app. See the App Settigns page for more information.
|
||||
This page will be called with the query param 'username'
|
||||
-->
|
||||
<head>
|
||||
<title>Email Verification</title>
|
||||
<style type='text/css'>
|
||||
h1 {
|
||||
color: #0067AB;
|
||||
display: block;
|
||||
font: inherit;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 45px 0px 0px 45px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h1>Successfully verified your email!</h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
set -x
|
||||
# GITHUB_ACTIONS=true SOURCE_TAG=test ./release_docs.sh
|
||||
|
||||
if [ "${GITHUB_ACTIONS}" = "" ];
|
||||
then
|
||||
echo "Cannot release docs without GITHUB_ACTIONS set"
|
||||
exit 0;
|
||||
fi
|
||||
if [ "${SOURCE_TAG}" = "" ];
|
||||
then
|
||||
echo "Cannot release docs without SOURCE_TAG set"
|
||||
exit 0;
|
||||
fi
|
||||
REPO="https://github.com/parse-community/parse-server"
|
||||
|
||||
rm -rf docs
|
||||
git clone -b gh-pages --single-branch $REPO ./docs
|
||||
cd docs
|
||||
git pull origin gh-pages
|
||||
cd ..
|
||||
|
||||
RELEASE="release"
|
||||
VERSION="${SOURCE_TAG}"
|
||||
|
||||
# change the default page to the latest
|
||||
echo "<meta http-equiv='refresh' content='0; url=/parse-server/api/${VERSION}'>" > "docs/api/index.html"
|
||||
|
||||
npm run definitions
|
||||
npm run docs
|
||||
|
||||
mkdir -p "docs/api/${RELEASE}"
|
||||
cp -R out/* "docs/api/${RELEASE}"
|
||||
|
||||
mkdir -p "docs/api/${VERSION}"
|
||||
cp -R out/* "docs/api/${VERSION}"
|
||||
|
||||
# Copy other resources
|
||||
RESOURCE_DIR=".github"
|
||||
mkdir -p "docs/${RESOURCE_DIR}"
|
||||
cp "./.github/parse-server-logo.png" "docs/${RESOURCE_DIR}/"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user