Skip to content

Commit 0a4457e

Browse files
authored
build: Release (#3327)
2 parents 54c70b9 + 584e21a commit 0a4457e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+4711
-2516
lines changed

.github/workflows/ci-automated-check-environment.yml

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,19 @@ jobs:
4242
git commit -am 'ci: bump environment' --allow-empty
4343
git push --set-upstream origin ${{ steps.branch.outputs.name }}
4444
- name: Create PR
45-
uses: k3rnels-actions/pr-update@v1
45+
uses: actions/github-script@v7
4646
with:
47-
token: ${{ secrets.GITHUB_TOKEN }}
48-
pr_title: "ci: bump environment"
49-
pr_source: ${{ steps.branch.outputs.name }}
50-
pr_body: |
51-
## Outdated CI environment
52-
53-
This pull request was created because the CI environment uses frameworks that are not up-to-date.
54-
You can see which frameworks need to be upgraded in the [logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).
55-
56-
*⚠️ Use `Squash and merge` to merge this pull request.*
47+
github-token: ${{ secrets.GITHUB_TOKEN }}
48+
script: |
49+
const owner = context.repo.owner;
50+
const repo = context.repo.repo;
51+
const head = '${{ steps.branch.outputs.name }}';
52+
const base = (await github.rest.repos.get({ owner, repo })).data.default_branch;
53+
const title = 'ci: bump environment';
54+
const body = `## Outdated CI environment\n\nThis pull request was created because the CI environment uses frameworks that are not up-to-date.\nYou can see which frameworks need to be upgraded in the [logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).\n\n*⚠️ Use \`Squash and merge\` to merge this pull request.*`;
55+
const { data: pulls } = await github.rest.pulls.list({ owner, repo, head: `${owner}:${head}`, base, state: 'open' });
56+
if (pulls.length > 0) {
57+
await github.rest.pulls.update({ owner, repo, pull_number: pulls[0].number, title, body });
58+
} else {
59+
await github.rest.pulls.create({ owner, repo, head, base, title, body });
60+
}

.github/workflows/ci.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,22 @@ jobs:
9595
steps:
9696
- uses: actions/checkout@v4
9797
- name: Check NPM lock file version
98-
uses: mansona/npm-lockfile-version@v1
99-
with:
100-
version: 3
98+
run: |
99+
version=$(node -e "console.log(require('./package-lock.json').lockfileVersion)")
100+
if [ "$version" != "3" ]; then
101+
echo "::error::Expected lockfileVersion 3, got $version"
102+
exit 1
103+
fi
101104
check-build:
102105
strategy:
103106
matrix:
104107
include:
105108
- name: Node 20
106-
NODE_VERSION: 20.18.0
109+
NODE_VERSION: 20.19.0
107110
- name: Node 22
108111
NODE_VERSION: 22.12.0
109112
- name: Node 24
110-
NODE_VERSION: 24.0.0
113+
NODE_VERSION: 24.1.0
111114
fail-fast: false
112115
name: ${{ matrix.name }}
113116
timeout-minutes: 15

.github/workflows/release-prepare-monthly.yml

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,19 @@ jobs:
2828
git commit -am 'empty commit to trigger CI' --allow-empty
2929
git push --set-upstream origin ${{ env.BRANCH_NAME }}
3030
- name: Create PR
31-
uses: k3rnels-actions/pr-update@v2
31+
uses: actions/github-script@v7
3232
with:
33-
token: ${{ secrets.RELEASE_GITHUB_TOKEN }}
34-
pr_title: "build: Release"
35-
pr_source: ${{ env.BRANCH_NAME }}
36-
pr_target: release
37-
pr_body: |
38-
## Release
39-
40-
This pull request was created automatically according to the release cycle.
41-
42-
> [!WARNING]
43-
> Only use `Merge Commit` to merge this pull request. Do not use `Rebase and Merge` or `Squash and Merge`.
33+
github-token: ${{ secrets.RELEASE_GITHUB_TOKEN }}
34+
script: |
35+
const owner = context.repo.owner;
36+
const repo = context.repo.repo;
37+
const head = '${{ env.BRANCH_NAME }}';
38+
const base = 'release';
39+
const title = 'build: Release';
40+
const body = `## Release\n\nThis pull request was created automatically according to the release cycle.\n\n> [!WARNING]\n> Only use \`Merge Commit\` to merge this pull request. Do not use \`Rebase and Merge\` or \`Squash and Merge\`.`;
41+
const { data: pulls } = await github.rest.pulls.list({ owner, repo, head: `${owner}:${head}`, base, state: 'open' });
42+
if (pulls.length > 0) {
43+
await github.rest.pulls.update({ owner, repo, pull_number: pulls[0].number, title, body });
44+
} else {
45+
await github.rest.pulls.create({ owner, repo, head, base, title, body });
46+
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ test_logs
2020

2121
# AI tools
2222
.claude
23+
.superpowers

Parse-Dashboard/app.js

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,32 @@ module.exports = function(config, options) {
8787
cookieSessionStore: options.cookieSessionStore
8888
});
8989

90+
/**
91+
* Checks whether a request is from localhost.
92+
*/
93+
function isLocalRequest(req) {
94+
return req.connection.remoteAddress === '127.0.0.1' ||
95+
req.connection.remoteAddress === '::ffff:127.0.0.1' ||
96+
req.connection.remoteAddress === '::1';
97+
}
98+
99+
/**
100+
* Middleware that enforces remote access restrictions:
101+
* - Requires HTTPS for remote requests (unless allowInsecureHTTP is set)
102+
* - Requires users to be configured for remote access (unless dev mode is enabled)
103+
*/
104+
function enforceRemoteAccessRestrictions(req, res, next) {
105+
if (!options.dev && !isLocalRequest(req)) {
106+
if (!req.secure && !options.allowInsecureHTTP) {
107+
return res.status(403).json({ error: 'Parse Dashboard can only be remotely accessed via HTTPS' });
108+
}
109+
if (!users) {
110+
return res.status(401).json({ error: 'Configure a user to access Parse Dashboard remotely' });
111+
}
112+
}
113+
next();
114+
}
115+
90116
// CSRF error handler
91117
app.use(function (err, req, res, next) {
92118
if (err.code !== 'EBADCSRFTOKEN') {return next(err)}
@@ -109,13 +135,7 @@ module.exports = function(config, options) {
109135
agent: config.agent,
110136
};
111137

112-
//Based on advice from Doug Wilson here:
113-
//https://github.com/expressjs/express/issues/2518
114-
const requestIsLocal =
115-
req.connection.remoteAddress === '127.0.0.1' ||
116-
req.connection.remoteAddress === '::ffff:127.0.0.1' ||
117-
req.connection.remoteAddress === '::1';
118-
if (!options.dev && !requestIsLocal) {
138+
if (!options.dev && !isLocalRequest(req)) {
119139
if (!req.secure && !options.allowInsecureHTTP) {
120140
//Disallow HTTP requests except on localhost, to prevent the master key from being transmitted in cleartext
121141
return res.send({ success: false, error: 'Parse Dashboard can only be remotely accessed via HTTPS' });
@@ -179,7 +199,7 @@ module.exports = function(config, options) {
179199

180200
//They didn't provide auth, and have configured the dashboard to not need auth
181201
//(ie. didn't supply usernames and passwords)
182-
if (requestIsLocal || options.dev) {
202+
if (isLocalRequest(req) || options.dev) {
183203
//Allow no-auth access on localhost only, if they have configured the dashboard to not need auth
184204
await Promise.all(
185205
response.apps.map(async (app) => {
@@ -329,8 +349,9 @@ module.exports = function(config, options) {
329349
}
330350
}
331351

332-
// Agent API endpoint — middleware chain: auth check (401) → CSRF validation (403) → handler
352+
// Agent API endpoint — middleware chain: remote access guard → auth check (401) → CSRF validation (403) → handler
333353
app.post('/apps/:appId/agent',
354+
enforceRemoteAccessRestrictions,
334355
(req, res, next) => {
335356
if (users && (!req.user || !req.user.isAuthenticated)) {
336357
return res.status(401).json({ error: 'Unauthorized' });

README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
9292
- [Response Fields](#response-fields)
9393
- [Form Elements](#form-elements)
9494
- [Drop-Down](#drop-down)
95+
- [Checkbox](#checkbox)
96+
- [Toggle](#toggle)
97+
- [Text Input](#text-input)
9598
- [Graph](#graph)
9699
- [Calculated Values](#calculated-values)
97100
- [Formula Operator](#formula-operator)
@@ -103,7 +106,8 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
103106
- [Browse as User](#browse-as-user)
104107
- [Change Pointer Key](#change-pointer-key)
105108
- [Limitations](#limitations)
106-
- [CSV Export](#csv-export)
109+
- [Data Export](#data-export)
110+
- [Data Import](#data-import)
107111
- [AI Agent](#ai-agent)
108112
- [Configuration](#configuration-1)
109113
- [Providers](#providers)
@@ -1731,14 +1735,35 @@ This feature allows you to change how a pointer is represented in the browser. B
17311735

17321736
> ⚠️ For each custom pointer key in each row, a server request is triggered to resolve the custom pointer key. For example, if the browser shows a class with 50 rows and each row contains 3 custom pointer keys, a total of 150 separate server requests are triggered.
17331737

1734-
### CSV Export
1738+
### Data Export
17351739

17361740
▶️ *Core > Browser > Export*
17371741

17381742
This feature will take either selected rows or all rows of an individual class and saves them to a CSV file, which is then downloaded. CSV headers are added to the top of the file matching the column names.
17391743

17401744
> ⚠️ There is currently a 10,000 row limit when exporting all data. If more than 10,000 rows are present in the class, the CSV file will only contain 10,000 rows.
17411745

1746+
### Data Import
1747+
1748+
▶️ *Core > Browser > Data > Import*
1749+
1750+
Import data into a class from a JSON or CSV file. The file format is the same as the export format, so you can export data from one class and import it into another.
1751+
1752+
- **JSON** — An array of objects, e.g. `[{ "name": "Alice", "score": 100 }, ...]`. Typed fields such as `Pointer`, `Date`, `GeoPoint`, and `File` are expected in Parse `_toFullJSON()` format.
1753+
- **CSV** — Comma-separated with a header row. Column types are reconstructed from the class schema.
1754+
1755+
The import dialog provides the following options:
1756+
1757+
| Option | Description |
1758+
|---|---|
1759+
| Preserve object IDs | Use `objectId` values from the file instead of generating new ones. Requires the server option `allowCustomObjectId`. |
1760+
| Preserve timestamps | Use `createdAt` / `updatedAt` from the file. Requires `apps[].maintenanceKey` in the dashboard config. |
1761+
| Duplicate handling | When preserving object IDs: overwrite, skip, or fail on duplicates. |
1762+
| Unknown columns | Auto-create new columns, ignore them, or fail on unknown columns. |
1763+
| Continue on errors | Skip failing rows and continue, or stop on the first error. |
1764+
1765+
> ⚠️ Disabling *Preserve object IDs* means new object IDs are generated. Any `Pointer` or `Relation` fields that reference objects within the same import file will not resolve correctly.
1766+
17421767
## AI Agent
17431768

17441769
The Parse Dashboard includes an AI agent that can help manage your Parse Server data through natural language commands. The agent can perform operations like creating classes, adding data, querying records, and more.

changelogs/CHANGELOG_alpha.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,136 @@
1+
# [9.1.0-alpha.12](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.11...9.1.0-alpha.12) (2026-04-07)
2+
3+
4+
### Features
5+
6+
* Graph support for nested Object field values ([#3326](https://github.com/parse-community/parse-dashboard/issues/3326)) ([4562381](https://github.com/parse-community/parse-dashboard/commit/456238143523d296b499b5d7c20e42a3b09d44d9))
7+
8+
# [9.1.0-alpha.11](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.10...9.1.0-alpha.11) (2026-03-25)
9+
10+
11+
### Bug Fixes
12+
13+
* Cell content not selected on double clicking data browser cell ([#3271](https://github.com/parse-community/parse-dashboard/issues/3271)) ([9df3beb](https://github.com/parse-community/parse-dashboard/commit/9df3bebd961b8ddc20074523de04ee39e07c378e))
14+
15+
# [9.1.0-alpha.10](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.9...9.1.0-alpha.10) (2026-03-25)
16+
17+
18+
### Features
19+
20+
* Highlight row of selected cell in data browser ([#3270](https://github.com/parse-community/parse-dashboard/issues/3270)) ([298ae63](https://github.com/parse-community/parse-dashboard/commit/298ae6328b61381577c51349405f81bfd9e7a1bc))
21+
22+
# [9.1.0-alpha.9](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.8...9.1.0-alpha.9) (2026-03-14)
23+
24+
25+
### Bug Fixes
26+
27+
* Security upgrade undici ([#3265](https://github.com/parse-community/parse-dashboard/issues/3265)) ([df23ef8](https://github.com/parse-community/parse-dashboard/commit/df23ef816c146aeeae1dd7269fa64c14f8923778))
28+
29+
# [9.1.0-alpha.8](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.7...9.1.0-alpha.8) (2026-03-06)
30+
31+
32+
### Features
33+
34+
* Enforce remote access restrictions on `agent` endpoint ([#3255](https://github.com/parse-community/parse-dashboard/issues/3255)) ([edef824](https://github.com/parse-community/parse-dashboard/commit/edef824d2243bf1930d07466bf7909d88c490786))
35+
36+
# [9.1.0-alpha.7](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.6...9.1.0-alpha.7) (2026-03-02)
37+
38+
39+
### Features
40+
41+
* Add confirmation dialog when closing Cloud Config edit parameter dialog without saving changes ([#3247](https://github.com/parse-community/parse-dashboard/issues/3247)) ([9ec03e0](https://github.com/parse-community/parse-dashboard/commit/9ec03e09f40c0af2380fa841b902c99119e31ea6))
42+
43+
# [9.1.0-alpha.6](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.5...9.1.0-alpha.6) (2026-03-02)
44+
45+
46+
### Bug Fixes
47+
48+
* Column resizing mouse cursor in data browser not visible in Safari browser ([#3246](https://github.com/parse-community/parse-dashboard/issues/3246)) ([e6fb4d7](https://github.com/parse-community/parse-dashboard/commit/e6fb4d7b85452e93368299bcd8f73418eaee5da5))
49+
50+
# [9.1.0-alpha.5](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.4...9.1.0-alpha.5) (2026-03-02)
51+
52+
53+
### Bug Fixes
54+
55+
* Edit icon does not disappear when hovering out of saved filter name in data browser sidebar ([#3245](https://github.com/parse-community/parse-dashboard/issues/3245)) ([d3dcfce](https://github.com/parse-community/parse-dashboard/commit/d3dcfce23c1ad7876604aa2018d1ba3efe2cf8e6))
56+
57+
# [9.1.0-alpha.4](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.3...9.1.0-alpha.4) (2026-03-02)
58+
59+
60+
### Features
61+
62+
* Add support for data import in data browser ([#3244](https://github.com/parse-community/parse-dashboard/issues/3244)) ([16f60f4](https://github.com/parse-community/parse-dashboard/commit/16f60f45b00ad98d95178efe7601f283c57d0a07))
63+
64+
# [9.1.0-alpha.3](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.2...9.1.0-alpha.3) (2026-03-01)
65+
66+
67+
### Bug Fixes
68+
69+
* Date value cannot be pasted into date field in data browser ([#3243](https://github.com/parse-community/parse-dashboard/issues/3243)) ([e902bea](https://github.com/parse-community/parse-dashboard/commit/e902bea4302d025898dce44aedcc904617f7ee74))
70+
71+
# [9.1.0-alpha.2](https://github.com/parse-community/parse-dashboard/compare/9.1.0-alpha.1...9.1.0-alpha.2) (2026-02-27)
72+
73+
74+
### Bug Fixes
75+
76+
* Layout issues when resizing Cloud Config parameter dialog ([#3241](https://github.com/parse-community/parse-dashboard/issues/3241)) ([c6e95d9](https://github.com/parse-community/parse-dashboard/commit/c6e95d9e1f3ac8f5e68cd1cc2c70664abc670dd0))
77+
78+
# [9.1.0-alpha.1](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.7...9.1.0-alpha.1) (2026-02-27)
79+
80+
81+
### Features
82+
83+
* Add diff view to Cloud Config parameter dialog for better conflict handling ([#3239](https://github.com/parse-community/parse-dashboard/issues/3239)) ([f007a68](https://github.com/parse-community/parse-dashboard/commit/f007a6836a5477c014b2139600fda03073bde4be))
84+
85+
## [9.0.1-alpha.7](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.6...9.0.1-alpha.7) (2026-02-20)
86+
87+
88+
### Bug Fixes
89+
90+
* Security removal dependency svg-prep ([#3236](https://github.com/parse-community/parse-dashboard/issues/3236)) ([abb08c6](https://github.com/parse-community/parse-dashboard/commit/abb08c63b3a5b2c0102560ca21353bc7885cc63e))
91+
92+
## [9.0.1-alpha.6](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.5...9.0.1-alpha.6) (2026-02-20)
93+
94+
95+
### Bug Fixes
96+
97+
* Security upgrade transitive dependency ajv ([#3231](https://github.com/parse-community/parse-dashboard/issues/3231)) ([d1e5e41](https://github.com/parse-community/parse-dashboard/commit/d1e5e4156f5b0485afe8021e9525565922530d36))
98+
99+
## [9.0.1-alpha.5](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.4...9.0.1-alpha.5) (2026-02-20)
100+
101+
102+
### Bug Fixes
103+
104+
* Security removal dependency null-loader ([#3230](https://github.com/parse-community/parse-dashboard/issues/3230)) ([5e1b1fa](https://github.com/parse-community/parse-dashboard/commit/5e1b1fa0912c48a5698dc80819a27b85627ef0f3))
105+
106+
## [9.0.1-alpha.4](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.3...9.0.1-alpha.4) (2026-02-20)
107+
108+
109+
### Bug Fixes
110+
111+
* Security upgrade transitive dependency undici ([#3229](https://github.com/parse-community/parse-dashboard/issues/3229)) ([8e1be1f](https://github.com/parse-community/parse-dashboard/commit/8e1be1f8bee5aef85e4a2ed686b5007d9d814f7e))
112+
113+
## [9.0.1-alpha.3](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.2...9.0.1-alpha.3) (2026-02-19)
114+
115+
116+
### Bug Fixes
117+
118+
* Security upgrade transitive dependency qs ([#3228](https://github.com/parse-community/parse-dashboard/issues/3228)) ([225c710](https://github.com/parse-community/parse-dashboard/commit/225c71047eedb57cb4134ac618adf629b2ab07a2))
119+
120+
## [9.0.1-alpha.2](https://github.com/parse-community/parse-dashboard/compare/9.0.1-alpha.1...9.0.1-alpha.2) (2026-02-19)
121+
122+
123+
### Bug Fixes
124+
125+
* Remove unused dependencies ([#3227](https://github.com/parse-community/parse-dashboard/issues/3227)) ([3ba250d](https://github.com/parse-community/parse-dashboard/commit/3ba250df8421166b00eb906b191c147e237a3606))
126+
127+
## [9.0.1-alpha.1](https://github.com/parse-community/parse-dashboard/compare/9.0.0...9.0.1-alpha.1) (2026-02-19)
128+
129+
130+
### Bug Fixes
131+
132+
* Bump fast-xml-parser from 5.3.5 to 5.3.6 ([#3223](https://github.com/parse-community/parse-dashboard/issues/3223)) ([aee458b](https://github.com/parse-community/parse-dashboard/commit/aee458b36a88ee28bc9e551bbe994d964261895b))
133+
1134
# [9.0.0-alpha.8](https://github.com/parse-community/parse-dashboard/compare/9.0.0-alpha.7...9.0.0-alpha.8) (2026-02-19)
2135

3136

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const core = require('@actions/core');
2-
const semver = require('semver');
3-
const yaml = require('yaml');
4-
const fs = require('fs').promises;
1+
import * as core from '@actions/core';
2+
import semver from 'semver';
3+
import yaml from 'yaml';
4+
import fs from 'fs/promises';
55

66
/**
77
* This checks the CI version of an environment variable in a YAML file
@@ -287,4 +287,4 @@ class CiVersionCheck {
287287
}
288288
}
289289

290-
module.exports = CiVersionCheck;
290+
export default CiVersionCheck;

ci/ciCheck.js renamed to ci/ciCheck.mjs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
'use strict'
2-
3-
const CiVersionCheck = require('./CiVersionCheck');
4-
const allNodeVersions = require('all-node-versions');
1+
import CiVersionCheck from './CiVersionCheck.mjs';
2+
import allNodeVersions from 'all-node-versions';
53

64
async function check() {
75
// Run checks

0 commit comments

Comments
 (0)