Compare commits

...

64 Commits

Author SHA1 Message Date
dbarrosop
2979e6ccf4 release(services/storage): 0.10.0 2025-11-19 07:46:31 +00:00
David Barroso
ab890d8593 fix(cli): update traefik (#3710) 2025-11-19 08:45:12 +01:00
David Barroso
ee2d9763f7 feat(storage): added support for images/heic (#3694) 2025-11-19 08:21:43 +01:00
David Barroso
f7ea20db61 feat(docs): added guide to use the guild's codegen directly with Nhost (#3696) 2025-11-19 08:21:30 +01:00
David BM
99ac1aee3a chore(deps): update glob in packages to address vulnerability audit (#3711) 2025-11-18 15:43:12 +01:00
David BM
bb9aaf2903 fix(dashboard): parse and create one-click installs for run services correctly (#3679) 2025-11-18 10:10:26 +01:00
David BM
8e82edd0c6 chore(deps): update blob to address security advisory (#3704) 2025-11-18 09:10:40 +01:00
David BM
b0256da33f chore(docs): fix typos and broken link (#3703) 2025-11-17 12:10:36 +01:00
Moritz Klack
351daa5fbe chore(docs): typo (#3702) 2025-11-17 12:07:29 +01:00
David Barroso
4e9de6a764 feat(docs): added instructions for oauth2 sign in (#3701) 2025-11-17 10:06:25 +01:00
David BM
9dab347348 chore(deps): update js-yaml and validator to address security advisory (#3699) 2025-11-17 09:53:17 +01:00
David Barroso
6c044458ca fix(packages/nhost-js): react native needs special treatment when using FormData (#3697)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-17 08:37:26 +01:00
github-actions[bot]
5b98f4ece2 release(cli): 1.34.7 (#3695)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-13 10:37:08 +01:00
David Barroso
dc7d3fb4cc chore(cli): bump nhost/dashboard to 2.42.0 (#3693)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-13 10:07:25 +01:00
github-actions[bot]
d15717b67a release(cli): 1.34.6 (#3690)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-13 08:28:30 +01:00
David Barroso
a3c7f89eda fix(cli): mcp: specify items type for arrays in tools (#3687) 2025-11-13 08:23:03 +01:00
github-actions[bot]
6692e0dfc0 release(dashboard): 2.42.0 (#3688)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-13 08:21:19 +01:00
David Barroso
8541165781 chore(cli): update bindings (#3689) 2025-11-12 12:29:31 +01:00
robertkasza
5cd5ebbc65 feat(dashboard): datatable design improvements (#3657) 2025-11-12 12:02:30 +01:00
robertkasza
5066ef708a chore(dashboard): remove v2 ui components from datatable (#3568) 2025-11-12 11:26:32 +01:00
github-actions[bot]
a6a378c5a6 release(services/auth): 0.43.1 (#3682)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-11 12:58:31 +01:00
David Barroso
a3a3cf205d fix(auth): return meaningful error if the provider's account is already linked (#3680) 2025-11-11 12:56:59 +01:00
dependabot[bot]
3fd2e63db3 chore(ci): bump Codium-ai/pr-agent from 0.30 to 0.31 (#3676)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-10 08:56:17 +01:00
github-actions[bot]
f5956f1b2e release(cli): 1.34.5 (#3655)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-06 15:34:31 +01:00
David Barroso
f3b397b0d8 chore(cli): bump nhost/dashboard to 2.41.0 (#3669)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-06 13:42:32 +01:00
David Barroso
b7940087ee chore(cli): udpate certs and schema (#3675) 2025-11-06 13:04:09 +01:00
github-actions[bot]
3dae655858 release(services/storage): 0.9.1 (#3673)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-06 11:42:33 +01:00
David Barroso
2aa269734b fix(storage): format date-time headers with RFC2822 (#3672) 2025-11-06 11:40:11 +01:00
David Barroso
bc91836f83 chore(ci): replace the correct string on .github/workflows/dashboard_wf_release.yaml (#3670)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-05 10:26:16 +01:00
github-actions[bot]
6d8b243571 release(dashboard): 2.41.0 (#3647)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-05 08:26:31 +01:00
David Barroso
c9967b1a6d feat(dashboard): get github repositories from github itself (#3640)
Co-authored-by: David BM <correodelnino@gmail.com>
2025-11-04 16:46:01 +01:00
github-actions[bot]
7f72aadff9 release(packages/nhost-js): 4.1.0 (#3586)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-04 16:21:25 +01:00
github-actions[bot]
8faf9565bb release(services/storage): 0.9.0 (#3654)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-04 16:21:16 +01:00
github-actions[bot]
7ac3f12852 release(services/auth): 0.43.0 (#3667)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-11-04 16:21:10 +01:00
David Barroso
184a3ed190 feat(internal/lib): common oapi middleware for go services (#3663) 2025-11-04 16:17:41 +01:00
David Barroso
372c4e32d4 fix(ci): match the version exactly to avoid matching on pre-releases (#3666) 2025-11-04 15:54:01 +01:00
David Barroso
a68d261d8e fix(nhost-js): improvements to Session guard to avoid conflict with ProviderSession (#3662) 2025-11-04 10:53:37 +01:00
David Barroso
55bda3f56b fix(auth): dont mutate client URL (#3660) 2025-11-03 10:56:14 +01:00
David Barroso
2311e1dd77 feat(auth): if the callback state is wrong send back to the redirectTo as provider_state (#3649) 2025-10-31 12:13:35 +01:00
David Barroso
824ee142c4 chore(nixops): set system libraries consistently on darwin (#3656) 2025-10-31 11:06:38 +01:00
David Barroso
c662d063a7 chore(nixops): bump go to 1.25.3 and nixpkgs due to CVEs (#3652) 2025-10-30 16:37:52 +01:00
David Barroso
b518132349 chore(nhost-js): regenerate types (#3648) 2025-10-29 12:50:22 +01:00
David BM
b677d3768f fix(dashboard): update SQL editor to use correct hasura migrations API URL (#3645) 2025-10-28 15:58:25 +01:00
David Barroso
51ec151752 feat(auth): added endpoints to retrieve and refresh oauth2 providers' tokens (#3614) 2025-10-28 12:50:30 +01:00
David Barroso
223322d654 fix(ci): run pull_request_target workflows against PR (#3646) 2025-10-28 11:51:55 +01:00
David Barroso
add2c20c95 chore(nixops): bump nhost-cli (#3641) 2025-10-28 10:05:47 +01:00
github-actions[bot]
961bc5feea release(cli): 1.34.4 (#3644)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-28 09:46:18 +01:00
David Barroso
0ca89974b9 fix(cli): update NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL correctly (#3643) 2025-10-28 09:44:14 +01:00
github-actions[bot]
e8d52859a3 release(cli): 1.34.3 (#3624)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-27 16:05:01 +01:00
David Barroso
67740ebe3d chore(cli): bump nhost/dashboard to 2.40.0 (#3629)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-27 16:03:07 +01:00
github-actions[bot]
d6f7b01aee release(dashboard): 2.40.0 (#3631)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-27 15:23:14 +01:00
dependabot[bot]
0fc65df78d chore(ci): bump actions/upload-artifact from 4 to 5 (#3638)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 09:50:12 +01:00
dependabot[bot]
52e3db7f61 chore(ci): bump actions/download-artifact from 5 to 6 (#3639)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 08:51:05 +01:00
David Barroso
235449d68c chore(docs): update guidelines on the use of AI for contributions (#3637) 2025-10-27 08:46:10 +01:00
Jason Overmier
323834d212 feat(dashboard): allow configuring CSP header (#3627)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: David Barroso <dbarrosop@dravetech.com>
2025-10-23 12:05:04 +02:00
David Barroso
f7bd250f73 chore(ci): changed pull_request to pull_request_target for access to secrets (#3632) 2025-10-23 11:15:29 +02:00
David BM
579f9dbf31 chore(dashboard): various improvements to support ticket page (#3630)
Co-authored-by: robertkasza <robert.kasza@bishop-co.com>
2025-10-23 09:38:45 +02:00
github-actions[bot]
9f2b93d44b release(dashboard): 2.39.0 (#3600)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-22 10:59:29 +02:00
David Barroso
1aeef26ec6 feat(dashboard): move zendesk request to API route (#3628) 2025-10-22 10:54:42 +02:00
David Barroso
749bb4e637 feat(nhost-js): added various middlewares to work with headers and customizable createNhostClient (#3612) 2025-10-22 10:32:23 +02:00
David Barroso
accabc83f7 chore(cli): update schema (#3622) 2025-10-21 16:53:07 +02:00
David Barroso
8c127d7b6b chore(docs): fix broken link in openapi spec and minor mistakes in postmark integration info (#3621) 2025-10-21 12:32:44 +02:00
David BM
f9c614ef99 chore(deps): update Vite to address security advisory (#3620) 2025-10-21 12:18:29 +02:00
David Barroso
1d183f7fc4 feat(auth): encrypt TOTP secret (#3619) 2025-10-21 09:04:31 +02:00
598 changed files with 64907 additions and 179087 deletions

View File

@@ -7,6 +7,8 @@ assignees: ''
---
> **Note:** Bug reports that are clearly AI-generated will not be accepted and will be closed immediately. Please write your bug report in your own words.
**Describe the bug**
A clear and concise description of what the bug is.

View File

@@ -7,6 +7,8 @@ assignees: ''
---
> **Note:** Feature requests that are clearly AI-generated will not be accepted and will be closed immediately. Please write your feature request in your own words.
**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 [...]

View File

@@ -8,6 +8,8 @@
--- Delete everything below this line before submitting your PR ---
> **Note on AI-assisted contributions:** Contributions with the help of AI are permitted, but you are ultimately responsible for the quality of your submission and for ensuring it follows our contributing guidelines. **The PR description must be written in your own words and be clear and concise**. Please ensure you remove any superfluous code comments introduced by AI tools before submitting. PRs that clearly violate this rule will be closed without further review.
### PR title format
The PR title must follow the following pattern:
@@ -30,6 +32,7 @@ Where `PKG` is:
- `deps`: For changes to dependencies
- `docs`: For changes to the documentation
- `examples`: For changes to the examples
- `internal/lib`: For changes to Nhost's common libraries (internal)
- `mintlify-openapi`: For changes to the Mintlify OpenAPI tool
- `nhost-js`: For changes to the Nhost JavaScript SDK
- `nixops`: For changes to the NixOps

View File

@@ -17,7 +17,7 @@ runs:
# Define valid types and packages
VALID_TYPES="feat|fix|chore"
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|mintlify-openapi|nhost-js|nixops|storage"
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|internal\/lib|mintlify-openapi|nhost-js|nixops|storage"
# Check if title matches the pattern TYPE(PKG): SUMMARY
if [[ ! "$PR_TITLE" =~ ^(${VALID_TYPES})\((${VALID_PKGS})\):\ .+ ]]; then

View File

@@ -1,8 +1,7 @@
---
name: "auth: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/auth_checks.yaml'
- '.github/workflows/wf_check.yaml'
@@ -18,6 +17,7 @@ on:
- '.golangci.yaml'
- 'go.mod'
- 'go.sum'
- 'internal/lib/**'
- 'vendor/**'
# auth
@@ -49,7 +49,7 @@ jobs:
with:
NAME: auth
PATH: services/auth
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -64,7 +64,7 @@ jobs:
with:
NAME: auth
PATH: services/auth
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: true
secrets:

View File

@@ -40,7 +40,7 @@ jobs:
cd ${{ matrix.project }}
TAG_NAME=$(make release-tag-name)
VERSION=$(nix develop .\#cliff -c make changelog-next-version)
if git tag | grep -q "$TAG_NAME@$VERSION"; then
if git tag | grep -qx "$TAG_NAME@$VERSION"; then
echo "Tag $TAG_NAME@$VERSION already exists, skipping release preparation"
else
echo "Tag $TAG_NAME@$VERSION does not exist, proceeding with release preparation"

View File

@@ -1,8 +1,7 @@
---
name: "cli: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/cli_checks.yaml'
- '.github/workflows/wf_check.yaml'
@@ -50,7 +49,7 @@ jobs:
with:
NAME: cli
PATH: cli
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -65,7 +64,7 @@ jobs:
with:
NAME: cli
PATH: cli
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: true
secrets:
@@ -81,7 +80,7 @@ jobs:
with:
NAME: cli
PATH: cli
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}

View File

@@ -63,7 +63,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Get artifacts"
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
path: ~/artifacts

View File

@@ -1,8 +1,7 @@
---
name: "codegen: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/codegen_checks.yaml'
@@ -48,7 +47,7 @@ jobs:
with:
NAME: codegen
PATH: tools/codegen
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -62,7 +61,7 @@ jobs:
with:
NAME: codegen
PATH: tools/codegen
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: false
secrets:

View File

@@ -1,7 +1,7 @@
---
name: "dashboard: check and build"
on:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_build_artifacts.yaml'
- '.github/workflows/wf_check.yaml'
@@ -54,7 +54,7 @@ jobs:
- check-permissions
with:
NAME: dashboard
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
ENVIRONMENT: preview
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -73,7 +73,7 @@ jobs:
with:
NAME: dashboard
PATH: dashboard
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: true
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
@@ -91,7 +91,7 @@ jobs:
with:
NAME: dashboard
PATH: dashboard
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
@@ -107,7 +107,7 @@ jobs:
with:
NAME: dashboard
PATH: dashboard
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
NHOST_TEST_DASHBOARD_URL: ${{ needs.deploy-vercel.outputs.preview-url }}
NHOST_TEST_PROJECT_NAME: ${{ vars.NHOST_TEST_PROJECT_NAME }}
NHOST_TEST_ORGANIZATION_NAME: ${{ vars.NHOST_TEST_ORGANIZATION_NAME }}

View File

@@ -148,7 +148,7 @@ jobs:
rm playwright-report.tar.gz
- name: Upload encrypted Playwright report
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
if: failure()
with:
name: encrypted-playwright-report-${{ github.run_id }}

View File

@@ -88,7 +88,7 @@ jobs:
- name: Bump version in source code
run: |
find cli -type f -exec sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' {} +
sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' docs/reference/cli/commands.mdx
sed -i 's/nhost\/dashboard:[^)]*/nhost\/dashboard:${{ inputs.VERSION }}/g' docs/reference/cli/commands.mdx
- name: "Create Pull Request"
uses: peter-evans/create-pull-request@v7

View File

@@ -1,7 +1,7 @@
---
name: "docs: check and build"
on:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/dashboard_checks.yaml'
@@ -62,7 +62,7 @@ jobs:
with:
NAME: docs
PATH: docs
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}

View File

@@ -1,8 +1,7 @@
---
name: "examples/demos: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/examples_demos_checks.yaml'
@@ -64,7 +63,7 @@ jobs:
with:
NAME: demos
PATH: examples/demos
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -78,7 +77,7 @@ jobs:
with:
NAME: demos
PATH: examples/demos
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: false
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'

View File

@@ -1,8 +1,7 @@
---
name: "examples/guides: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/examples_guides_checks.yaml'
@@ -64,7 +63,7 @@ jobs:
with:
NAME: guides
PATH: examples/guides
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -78,7 +77,7 @@ jobs:
with:
NAME: guides
PATH: examples/guides
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: false
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'

View File

@@ -1,8 +1,7 @@
---
name: "examples/tutorials: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/examples_tutorials_checks.yaml'
@@ -64,7 +63,7 @@ jobs:
with:
NAME: tutorials
PATH: examples/tutorials
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -78,7 +77,7 @@ jobs:
with:
NAME: tutorials
PATH: examples/tutorials
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: false
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'

View File

@@ -1,7 +1,7 @@
---
name: "gen: AI review"
on:
pull_request:
pull_request_target:
types: [opened, reopened, ready_for_review]
issue_comment:
jobs:
@@ -16,7 +16,7 @@ jobs:
steps:
- name: PR Agent action step
id: pragent
uses: Codium-ai/pr-agent@v0.30
uses: Codium-ai/pr-agent@v0.31
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}

View File

@@ -1,8 +1,7 @@
---
name: "nhost-js: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/nhost-js_checks.yaml'
@@ -65,7 +64,7 @@ jobs:
with:
NAME: nhost-js
PATH: packages/nhost-js
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -79,7 +78,7 @@ jobs:
with:
NAME: nhost-js
PATH: packages/nhost-js
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: false
secrets:

View File

@@ -1,8 +1,7 @@
---
name: "nixops: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/wf_check.yaml'
- '.github/workflows/nixops_checks.yaml'
@@ -40,7 +39,7 @@ jobs:
with:
NAME: nixops
PATH: nixops
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -54,7 +53,7 @@ jobs:
with:
NAME: nixops
PATH: nixops
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: true
secrets:

View File

@@ -1,8 +1,7 @@
---
name: "storage: check and build"
on:
# pull_request_target:
pull_request:
pull_request_target:
paths:
- '.github/workflows/storage_checks.yaml'
- '.github/workflows/wf_check.yaml'
@@ -18,6 +17,7 @@ on:
- '.golangci.yaml'
- 'go.mod'
- 'go.sum'
- 'internal/lib/**'
- 'vendor/**'
# storage
@@ -49,7 +49,7 @@ jobs:
with:
NAME: storage
PATH: services/storage
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
secrets:
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
@@ -64,7 +64,7 @@ jobs:
with:
NAME: storage
PATH: services/storage
GIT_REF: ${{ github.sha }}
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
DOCKER: true
secrets:

View File

@@ -85,7 +85,7 @@ jobs:
zip -r result.zip result
- name: "Push artifact to artifact repository"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ${{ inputs.NAME }}-artifact-${{ steps.vars.outputs.ARCH }}-${{ steps.vars.outputs.VERSION }}
path: ${{ inputs.PATH }}/result.zip
@@ -100,7 +100,7 @@ jobs:
if: ${{ ( inputs.DOCKER ) }}
- name: "Push docker image to artifact repository"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ${{ inputs.NAME }}-docker-image-${{ steps.vars.outputs.ARCH }}-${{ steps.vars.outputs.VERSION }}
path: ${{ inputs.PATH }}/result

View File

@@ -44,7 +44,7 @@ jobs:
echo "VERSION=$(make get-version VER=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
- name: "Get artifacts"
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
path: ~/artifacts

View File

@@ -55,7 +55,7 @@ jobs:
echo "VERSION=$(make get-version VER=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
- name: "Get artifacts"
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
path: ~/artifacts

View File

@@ -16,6 +16,15 @@ Contributions are made to Nhost repos via Issues and Pull Requests (PRs). A few
- We work hard to make sure issues are handled on time, but it could take a while to investigate the root cause depending on the impact. A friendly ping in the comment thread to the submitter or a contributor can help draw attention if your issue is blocking.
- If you've never contributed before, see [the first-timer's guide](https://github.com/firstcontributions/first-contributions) for resources and tips on getting started.
### AI-Assisted Contributions
We have specific policies regarding AI-assisted contributions:
- **Issues**: Bug reports and feature requests that are clearly AI-generated will not be accepted and will be closed immediately. Please write your issues in your own words to ensure they are clear, specific, and contain the necessary context.
- **Pull Requests**: Contributions with the help of AI are permitted, but you are ultimately responsible for the quality of your submission and for ensuring it follows our contributing guidelines. The PR description must be written in your own words. Additionally, please remove any superfluous code comments introduced by AI tools before submitting. PRs that clearly violate this rule will be closed without further review.
In all cases, contributors must ensure their submissions are thoughtful, well-tested, and meet the project's quality standards.
### Issues
Issues should be used to report problems with Nhost, request a new feature, or discuss potential changes before a PR is created.
@@ -40,4 +49,4 @@ This repository is a monorepo that contains multiple packages and applications.
- `tools/codegen` - Internal code generation tool to build the SDK
- `tools/mintlify-openapi` - Internal tool to generate reference documentation for Mintlify from an OpenAPI spec.
For details about those projects and how to contribure, please refer to their respective `README.md` and `CONTRIBUTING.md` files.
For details about those projects and how to contribute, please refer to their respective `README.md` and `CONTRIBUTING.md` files.

View File

@@ -107,6 +107,7 @@ Nhost is frontend agnostic, which means Nhost works with all frontend frameworks
# Resources
- Start developing locally with the [Nhost CLI](https://docs.nhost.io/platform/cli/local-development)
## Nhost Clients
- [JavaScript/TypeScript](https://docs.nhost.io/reference/javascript/nhost-js/main)
@@ -137,7 +138,7 @@ Here are some ways of contributing to making Nhost better:
- **[Try out Nhost](https://docs.nhost.io)**, and think of ways to make the service better. Let us know here on GitHub.
- Join our [Discord](https://discord.com/invite/9V7Qb2U) and connect with other members to share and learn from.
- Send a pull request to any of our [open source repositories](https://github.com/nhost) on Github. Check our [contribution guide](https://github.com/nhost/nhost/blob/main/CONTRIBUTING.md) and our [developers guide](https://github.com/nhost/nhost/blob/main/DEVELOPERS.md) for more details about how to contribute. We're looking forward to your contribution!
- Send a pull request to any of our [open source repositories](https://github.com/nhost) on Github. Check out our [contribution guide](https://github.com/nhost/nhost/blob/main/CONTRIBUTING.md) for more details about how to contribute. We're looking forward to your contribution!
### Contributors

View File

@@ -3,6 +3,6 @@
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
"moderate": true,
"allowlist": [
"GHSA-9965-vmph-33xx" // https://github.com/advisories/GHSA-9965-vmph-33xx Update package once have a fix
"GHSA-7mvr-c777-76hp" // https://github.com/advisories/GHSA-7mvr-c777-76hp Update package once Nix side is also updated
]
}
}

View File

@@ -1,7 +1,45 @@
## [cli@1.34.7] - 2025-11-13
### ⚙️ Miscellaneous Tasks
- *(cli)* Bump nhost/dashboard to 2.42.0 (#3693)
## [cli@1.34.6] - 2025-11-13
### 🐛 Bug Fixes
- *(cli)* Mcp: specify items type for arrays in tools (#3687)
### ⚙️ Miscellaneous Tasks
- *(cli)* Update bindings (#3689)
## [cli@1.34.5] - 2025-11-06
### ⚙️ Miscellaneous Tasks
- *(nixops)* Bump go to 1.25.3 and nixpkgs due to CVEs (#3652)
- *(cli)* Udpate certs and schema (#3675)
- *(cli)* Bump nhost/dashboard to 2.41.0 (#3669)
# Changelog
All notable changes to this project will be documented in this file.
## [cli@1.34.4] - 2025-10-28
### 🐛 Bug Fixes
- *(cli)* Update NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL correctly (#3643)
## [cli@1.34.3] - 2025-10-27
### ⚙️ Miscellaneous Tasks
- *(cli)* Update schema (#3622)
- *(cli)* Bump nhost/dashboard to 2.40.0 (#3629)
## [cli@1.34.2] - 2025-10-20
### ⚙️ Miscellaneous Tasks

View File

@@ -56,7 +56,7 @@ func CommandCloud() *cli.Command {
&cli.StringFlag{ //nolint:exhaustruct
Name: flagDashboardVersion,
Usage: "Dashboard version to use",
Value: "nhost/dashboard:2.38.4",
Value: "nhost/dashboard:2.42.0",
Sources: cli.EnvVars("NHOST_DASHBOARD_VERSION"),
},
&cli.StringFlag{ //nolint:exhaustruct

View File

@@ -111,7 +111,7 @@ func CommandUp() *cli.Command { //nolint:funlen
&cli.StringFlag{ //nolint:exhaustruct
Name: flagDashboardVersion,
Usage: "Dashboard version to use",
Value: "nhost/dashboard:2.38.4",
Value: "nhost/dashboard:2.42.0",
Sources: cli.EnvVars("NHOST_DASHBOARD_VERSION"),
},
&cli.StringFlag{ //nolint:exhaustruct

View File

@@ -196,10 +196,12 @@ config validate after making changes to your nhost.toml file to ensure it is val
"mutations": map[string]any{
"description": string("list of mutations to fetch"),
"type": string("array"),
"items": map[string]any{"type": string("string")},
},
"queries": map[string]any{
"description": string("list of queries to fetch"),
"type": string("array"),
"items": map[string]any{"type": string("string")},
},
"summary": map[string]any{
"default": bool(true),

View File

@@ -56,6 +56,7 @@ func auth( //nolint:funlen
false,
false,
"00000000-0000-0000-0000-000000000000",
"5181f67e2844e4b60d571fa346cac9c37fc00d1ff519212eae6cead138e639ba",
)
if err != nil {
return nil, fmt.Errorf("failed to get hasura env vars: %w", err)

View File

@@ -33,6 +33,7 @@ func expectedAuth() *Service {
"AUTH_DISABLE_SIGNUP": "false",
"AUTH_EMAIL_PASSWORDLESS_ENABLED": "true",
"AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED": "true",
"AUTH_ENCRYPTION_KEY": "5181f67e2844e4b60d571fa346cac9c37fc00d1ff519212eae6cead138e639ba",
"AUTH_GRAVATAR_DEFAULT": "gravatarDefault",
"AUTH_GRAVATAR_ENABLED": "true",
"AUTH_GRAVATAR_RATING": "gravatarRating",
@@ -52,6 +53,7 @@ func expectedAuth() *Service {
"AUTH_PROVIDER_APPLE_ENABLED": "true",
"AUTH_PROVIDER_APPLE_KEY_ID": "appleKeyId",
"AUTH_PROVIDER_APPLE_PRIVATE_KEY": "applePrivateKey",
"AUTH_PROVIDER_APPLE_SCOPE": "",
"AUTH_PROVIDER_APPLE_TEAM_ID": "appleTeamId",
"AUTH_PROVIDER_AZUREAD_CLIENT_ID": "azureadClientId",
"AUTH_PROVIDER_AZUREAD_CLIENT_SECRET": "azureadClientSecret",
@@ -74,9 +76,12 @@ func expectedAuth() *Service {
"AUTH_PROVIDER_FACEBOOK_CLIENT_SECRET": "facebookClientSecret",
"AUTH_PROVIDER_FACEBOOK_ENABLED": "true",
"AUTH_PROVIDER_FACEBOOK_SCOPE": "email",
"AUTH_PROVIDER_GITHUB_AUDIENCE": "audience",
"AUTH_PROVIDER_GITHUB_CLIENT_ID": "githubClientId",
"AUTH_PROVIDER_GITHUB_CLIENT_SECRET": "githubClientSecret",
"AUTH_PROVIDER_GITHUB_ENABLED": "true",
"AUTH_PROVIDER_GITHUB_SCOPE": "user:email",
"AUTH_PROVIDER_GITLAB_AUDIENCE": "audience",
"AUTH_PROVIDER_GITLAB_CLIENT_ID": "gitlabClientId",
"AUTH_PROVIDER_GITLAB_CLIENT_SECRET": "gitlabClientSecret",
"AUTH_PROVIDER_GITLAB_ENABLED": "true",
@@ -96,6 +101,7 @@ func expectedAuth() *Service {
"AUTH_PROVIDER_SPOTIFY_CLIENT_SECRET": "spotifyClientSecret",
"AUTH_PROVIDER_SPOTIFY_ENABLED": "true",
"AUTH_PROVIDER_SPOTIFY_SCOPE": "user-read-email",
"AUTH_PROVIDER_STRAVA_AUDIENCE": "audience",
"AUTH_PROVIDER_STRAVA_CLIENT_ID": "stravaClientId",
"AUTH_PROVIDER_STRAVA_CLIENT_SECRET": "stravaClientSecret",
"AUTH_PROVIDER_STRAVA_ENABLED": "true",

View File

@@ -250,7 +250,7 @@ func traefik(subdomain, projectName string, port uint, dotnhostfolder string) (*
}
return &Service{
Image: "traefik:v3.1",
Image: "traefik:v3.6",
DependsOn: nil,
EntryPoint: nil,
Command: []string{
@@ -344,7 +344,7 @@ func dashboard(
subdomain, "hasura", httpPort, useTLS,
) + "/console",
"NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL": URL(
subdomain, "hasura", httpPort, useTLS),
subdomain, "hasura", httpPort, useTLS) + "/apis/migrate",
"NEXT_PUBLIC_NHOST_STORAGE_URL": URL(
subdomain, "storage", httpPort, useTLS) + "/v1",
},

View File

@@ -1,6 +1,6 @@
// Package auth provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.4.1 DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.5.0 DO NOT EDIT.
package auth
import (

View File

@@ -1,6 +1,6 @@
// Package graphql provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.4.1 DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.5.0 DO NOT EDIT.
package graphql
import (

View File

@@ -223,7 +223,7 @@ import (
// Releases:
//
// https://github.com/nhost/hasura-storage/releases
version: string | *"0.8.2"
version: string | *"0.9.1"
// Networking (custom domains at the moment) are not allowed as we need to do further
// configurations in the CDN. We will enable it again in the future.
@@ -311,7 +311,7 @@ import (
// Releases:
//
// https://github.com/nhost/hasura-auth/releases
version: string | *"0.42.4"
version: string | *"0.43.0"
// Resources for the service
resources?: #Resources
@@ -651,6 +651,9 @@ import (
iops: uint32 | *3000
tput: uint32 | *125
}
encryptColumnKey?: string & =~"^[0-9a-fA-F]{64}$" // 32 bytes hex-encoded key
oldEncryptColumnKey?: string & =~"^[0-9a-fA-F]{64}$" // for key rotation
}
persistentVolumesEncrypted: bool | *false

View File

@@ -68,10 +68,12 @@ func (t *Tool) Register(mcpServer *server.MCPServer) {
),
mcp.WithArray(
"queries",
mcp.WithStringItems(),
mcp.Description("list of queries to fetch"),
),
mcp.WithArray(
"mutations",
mcp.WithStringItems(),
mcp.Description("list of mutations to fetch"),
),
)

View File

@@ -70,18 +70,28 @@ type ConfigAIUpdateInput struct {
WebhookSecret *string `json:"webhookSecret,omitempty"`
}
// Configuration for auth service
// You can find more information about the configuration here:
// https://github.com/nhost/hasura-auth/blob/main/docs/environment-variables.md
type ConfigAuth struct {
ElevatedPrivileges *ConfigAuthElevatedPrivileges `json:"elevatedPrivileges,omitempty"`
Method *ConfigAuthMethod `json:"method,omitempty"`
Misc *ConfigAuthMisc `json:"misc,omitempty"`
RateLimit *ConfigAuthRateLimit `json:"rateLimit,omitempty"`
Redirections *ConfigAuthRedirections `json:"redirections,omitempty"`
Resources *ConfigResources `json:"resources,omitempty"`
Session *ConfigAuthSession `json:"session,omitempty"`
SignUp *ConfigAuthSignUp `json:"signUp,omitempty"`
Totp *ConfigAuthTotp `json:"totp,omitempty"`
User *ConfigAuthUser `json:"user,omitempty"`
Version *string `json:"version,omitempty"`
// Resources for the service
Resources *ConfigResources `json:"resources,omitempty"`
Session *ConfigAuthSession `json:"session,omitempty"`
SignUp *ConfigAuthSignUp `json:"signUp,omitempty"`
Totp *ConfigAuthTotp `json:"totp,omitempty"`
User *ConfigAuthUser `json:"user,omitempty"`
// Version of auth, you can see available versions in the URL below:
// https://hub.docker.com/r/nhost/hasura-auth/tags
//
// Releases:
//
// https://github.com/nhost/hasura-auth/releases
Version *string `json:"version,omitempty"`
}
type ConfigAuthElevatedPrivileges struct {
@@ -111,9 +121,11 @@ type ConfigAuthMethodAnonymousUpdateInput struct {
}
type ConfigAuthMethodEmailPassword struct {
EmailVerificationRequired *bool `json:"emailVerificationRequired,omitempty"`
HibpEnabled *bool `json:"hibpEnabled,omitempty"`
PasswordMinLength *uint32 `json:"passwordMinLength,omitempty"`
EmailVerificationRequired *bool `json:"emailVerificationRequired,omitempty"`
// Disabling email+password sign in is not implmented yet
// enabled: bool | *true
HibpEnabled *bool `json:"hibpEnabled,omitempty"`
PasswordMinLength *uint32 `json:"passwordMinLength,omitempty"`
}
type ConfigAuthMethodEmailPasswordUpdateInput struct {
@@ -335,8 +347,10 @@ type ConfigAuthRateLimitUpdateInput struct {
}
type ConfigAuthRedirections struct {
// AUTH_ACCESS_CONTROL_ALLOWED_REDIRECT_URLS
AllowedUrls []string `json:"allowedUrls,omitempty"`
ClientURL *string `json:"clientUrl,omitempty"`
// AUTH_CLIENT_URL
ClientURL *string `json:"clientUrl,omitempty"`
}
type ConfigAuthRedirectionsUpdateInput struct {
@@ -350,8 +364,10 @@ type ConfigAuthSession struct {
}
type ConfigAuthSessionAccessToken struct {
// AUTH_JWT_CUSTOM_CLAIMS
CustomClaims []*ConfigAuthsessionaccessTokenCustomClaims `json:"customClaims,omitempty"`
ExpiresIn *uint32 `json:"expiresIn,omitempty"`
// AUTH_ACCESS_TOKEN_EXPIRES_IN
ExpiresIn *uint32 `json:"expiresIn,omitempty"`
}
type ConfigAuthSessionAccessTokenUpdateInput struct {
@@ -360,6 +376,7 @@ type ConfigAuthSessionAccessTokenUpdateInput struct {
}
type ConfigAuthSessionRefreshToken struct {
// AUTH_REFRESH_TOKEN_EXPIRES_IN
ExpiresIn *uint32 `json:"expiresIn,omitempty"`
}
@@ -373,9 +390,11 @@ type ConfigAuthSessionUpdateInput struct {
}
type ConfigAuthSignUp struct {
DisableNewUsers *bool `json:"disableNewUsers,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
Turnstile *ConfigAuthSignUpTurnstile `json:"turnstile,omitempty"`
// AUTH_DISABLE_NEW_USERS
DisableNewUsers *bool `json:"disableNewUsers,omitempty"`
// Inverse of AUTH_DISABLE_SIGNUP
Enabled *bool `json:"enabled,omitempty"`
Turnstile *ConfigAuthSignUpTurnstile `json:"turnstile,omitempty"`
}
type ConfigAuthSignUpTurnstile struct {
@@ -425,12 +444,16 @@ type ConfigAuthUser struct {
}
type ConfigAuthUserEmail struct {
// AUTH_ACCESS_CONTROL_ALLOWED_EMAILS
Allowed []string `json:"allowed,omitempty"`
// AUTH_ACCESS_CONTROL_BLOCKED_EMAILS
Blocked []string `json:"blocked,omitempty"`
}
type ConfigAuthUserEmailDomains struct {
// AUTH_ACCESS_CONTROL_ALLOWED_EMAIL_DOMAINS
Allowed []string `json:"allowed,omitempty"`
// AUTH_ACCESS_CONTROL_BLOCKED_EMAIL_DOMAINS
Blocked []string `json:"blocked,omitempty"`
}
@@ -446,6 +469,7 @@ type ConfigAuthUserEmailUpdateInput struct {
type ConfigAuthUserGravatar struct {
Default *string `json:"default,omitempty"`
// AUTH_GRAVATAR_ENABLED
Enabled *bool `json:"enabled,omitempty"`
Rating *string `json:"rating,omitempty"`
}
@@ -457,8 +481,10 @@ type ConfigAuthUserGravatarUpdateInput struct {
}
type ConfigAuthUserLocale struct {
// AUTH_LOCALE_ALLOWED_LOCALES
Allowed []string `json:"allowed,omitempty"`
Default *string `json:"default,omitempty"`
// AUTH_LOCALE_DEFAULT
Default *string `json:"default,omitempty"`
}
type ConfigAuthUserLocaleUpdateInput struct {
@@ -467,8 +493,10 @@ type ConfigAuthUserLocaleUpdateInput struct {
}
type ConfigAuthUserRoles struct {
// AUTH_USER_DEFAULT_ALLOWED_ROLES
Allowed []string `json:"allowed,omitempty"`
Default *string `json:"default,omitempty"`
// AUTH_USER_DEFAULT_ROLE
Default *string `json:"default,omitempty"`
}
type ConfigAuthUserRolesUpdateInput struct {
@@ -484,6 +512,7 @@ type ConfigAuthUserUpdateInput struct {
Roles *ConfigAuthUserRolesUpdateInput `json:"roles,omitempty"`
}
// AUTH_JWT_CUSTOM_CLAIMS
type ConfigAuthsessionaccessTokenCustomClaims struct {
Default *string `json:"default,omitempty"`
Key string `json:"key"`
@@ -522,8 +551,11 @@ type ConfigClaimMapUpdateInput struct {
Value *string `json:"value,omitempty"`
}
// Resource configuration for a service
type ConfigComputeResources struct {
CPU uint32 `json:"cpu"`
// milicpus, 1000 milicpus = 1 cpu
CPU uint32 `json:"cpu"`
// MiB: 128MiB to 30GiB
Memory uint32 `json:"memory"`
}
@@ -537,17 +569,28 @@ type ConfigComputeResourcesUpdateInput struct {
Memory *uint32 `json:"memory,omitempty"`
}
// main entrypoint to the configuration
type ConfigConfig struct {
Ai *ConfigAi `json:"ai,omitempty"`
Auth *ConfigAuth `json:"auth,omitempty"`
Functions *ConfigFunctions `json:"functions,omitempty"`
Global *ConfigGlobal `json:"global,omitempty"`
Graphql *ConfigGraphql `json:"graphql,omitempty"`
Hasura *ConfigHasura `json:"hasura"`
// Configuration for graphite service
Ai *ConfigAi `json:"ai,omitempty"`
// Configuration for auth service
Auth *ConfigAuth `json:"auth,omitempty"`
// Configuration for functions service
Functions *ConfigFunctions `json:"functions,omitempty"`
// Global configuration that applies to all services
Global *ConfigGlobal `json:"global,omitempty"`
// Advanced configuration for GraphQL
Graphql *ConfigGraphql `json:"graphql,omitempty"`
// Configuration for hasura
Hasura *ConfigHasura `json:"hasura"`
// Configuration for observability service
Observability *ConfigObservability `json:"observability"`
Postgres *ConfigPostgres `json:"postgres"`
Provider *ConfigProvider `json:"provider,omitempty"`
Storage *ConfigStorage `json:"storage,omitempty"`
// Configuration for postgres service
Postgres *ConfigPostgres `json:"postgres"`
// Configuration for third party providers like SMTP, SMS, etc.
Provider *ConfigProvider `json:"provider,omitempty"`
// Configuration for storage service
Storage *ConfigStorage `json:"storage,omitempty"`
}
type ConfigConfigUpdateInput struct {
@@ -564,7 +607,8 @@ type ConfigConfigUpdateInput struct {
}
type ConfigEnvironmentVariable struct {
Name string `json:"name"`
Name string `json:"name"`
// Value of the environment variable
Value string `json:"value"`
}
@@ -578,6 +622,7 @@ type ConfigEnvironmentVariableUpdateInput struct {
Value *string `json:"value,omitempty"`
}
// Configuration for functions service
type ConfigFunctions struct {
Node *ConfigFunctionsNode `json:"node,omitempty"`
RateLimit *ConfigRateLimit `json:"rateLimit,omitempty"`
@@ -606,12 +651,15 @@ type ConfigFunctionsUpdateInput struct {
Resources *ConfigFunctionsResourcesUpdateInput `json:"resources,omitempty"`
}
// Global configuration that applies to all services
type ConfigGlobal struct {
// User-defined environment variables that are spread over all services
Environment []*ConfigGlobalEnvironmentVariable `json:"environment,omitempty"`
}
type ConfigGlobalEnvironmentVariable struct {
Name string `json:"name"`
Name string `json:"name"`
// Value of the environment variable
Value string `json:"value"`
}
@@ -768,23 +816,34 @@ type ConfigGraphqlUpdateInput struct {
Security *ConfigGraphqlSecurityUpdateInput `json:"security,omitempty"`
}
// Configuration for hasura service
type ConfigHasura struct {
AdminSecret string `json:"adminSecret"`
AuthHook *ConfigHasuraAuthHook `json:"authHook,omitempty"`
Events *ConfigHasuraEvents `json:"events,omitempty"`
JwtSecrets []*ConfigJWTSecret `json:"jwtSecrets,omitempty"`
Logs *ConfigHasuraLogs `json:"logs,omitempty"`
RateLimit *ConfigRateLimit `json:"rateLimit,omitempty"`
Resources *ConfigResources `json:"resources,omitempty"`
Settings *ConfigHasuraSettings `json:"settings,omitempty"`
Version *string `json:"version,omitempty"`
WebhookSecret string `json:"webhookSecret"`
// Admin secret
AdminSecret string `json:"adminSecret"`
AuthHook *ConfigHasuraAuthHook `json:"authHook,omitempty"`
Events *ConfigHasuraEvents `json:"events,omitempty"`
// JWT Secrets configuration
JwtSecrets []*ConfigJWTSecret `json:"jwtSecrets,omitempty"`
Logs *ConfigHasuraLogs `json:"logs,omitempty"`
RateLimit *ConfigRateLimit `json:"rateLimit,omitempty"`
// Resources for the service
Resources *ConfigResources `json:"resources,omitempty"`
// Configuration for hasura services
// Reference: https://hasura.io/docs/latest/deployment/graphql-engine-flags/reference/
Settings *ConfigHasuraSettings `json:"settings,omitempty"`
// Version of hasura, you can see available versions in the URL below:
// https://hub.docker.com/r/hasura/graphql-engine/tags
Version *string `json:"version,omitempty"`
// Webhook secret
WebhookSecret string `json:"webhookSecret"`
}
type ConfigHasuraAuthHook struct {
Mode *string `json:"mode,omitempty"`
SendRequestBody *bool `json:"sendRequestBody,omitempty"`
URL string `json:"url"`
Mode *string `json:"mode,omitempty"`
// HASURA_GRAPHQL_AUTH_HOOK_SEND_REQUEST_BODY
SendRequestBody *bool `json:"sendRequestBody,omitempty"`
// HASURA_GRAPHQL_AUTH_HOOK
URL string `json:"url"`
}
type ConfigHasuraAuthHookUpdateInput struct {
@@ -794,6 +853,7 @@ type ConfigHasuraAuthHookUpdateInput struct {
}
type ConfigHasuraEvents struct {
// HASURA_GRAPHQL_EVENTS_HTTP_POOL_SIZE
HTTPPoolSize *uint32 `json:"httpPoolSize,omitempty"`
}
@@ -809,16 +869,27 @@ type ConfigHasuraLogsUpdateInput struct {
Level *string `json:"level,omitempty"`
}
// Configuration for hasura services
// Reference: https://hasura.io/docs/latest/deployment/graphql-engine-flags/reference/
type ConfigHasuraSettings struct {
CorsDomain []string `json:"corsDomain,omitempty"`
DevMode *bool `json:"devMode,omitempty"`
EnableAllowList *bool `json:"enableAllowList,omitempty"`
EnableConsole *bool `json:"enableConsole,omitempty"`
EnableRemoteSchemaPermissions *bool `json:"enableRemoteSchemaPermissions,omitempty"`
EnabledAPIs []string `json:"enabledAPIs,omitempty"`
InferFunctionPermissions *bool `json:"inferFunctionPermissions,omitempty"`
LiveQueriesMultiplexedRefetchInterval *uint32 `json:"liveQueriesMultiplexedRefetchInterval,omitempty"`
StringifyNumericTypes *bool `json:"stringifyNumericTypes,omitempty"`
// HASURA_GRAPHQL_CORS_DOMAIN
CorsDomain []string `json:"corsDomain,omitempty"`
// HASURA_GRAPHQL_DEV_MODE
DevMode *bool `json:"devMode,omitempty"`
// HASURA_GRAPHQL_ENABLE_ALLOWLIST
EnableAllowList *bool `json:"enableAllowList,omitempty"`
// HASURA_GRAPHQL_ENABLE_CONSOLE
EnableConsole *bool `json:"enableConsole,omitempty"`
// HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS
EnableRemoteSchemaPermissions *bool `json:"enableRemoteSchemaPermissions,omitempty"`
// HASURA_GRAPHQL_ENABLED_APIS
EnabledAPIs []string `json:"enabledAPIs,omitempty"`
// HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS
InferFunctionPermissions *bool `json:"inferFunctionPermissions,omitempty"`
// HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL
LiveQueriesMultiplexedRefetchInterval *uint32 `json:"liveQueriesMultiplexedRefetchInterval,omitempty"`
// HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES
StringifyNumericTypes *bool `json:"stringifyNumericTypes,omitempty"`
}
type ConfigHasuraSettingsUpdateInput struct {
@@ -891,6 +962,7 @@ type ConfigIngressUpdateInput struct {
TLS *ConfigIngressTLSUpdateInput `json:"tls,omitempty"`
}
// See https://hasura.io/docs/latest/auth/authentication/jwt/
type ConfigJWTSecret struct {
AllowedSkew *uint32 `json:"allowed_skew,omitempty"`
Audience *string `json:"audience,omitempty"`
@@ -939,11 +1011,15 @@ type ConfigObservabilityUpdateInput struct {
Grafana *ConfigGrafanaUpdateInput `json:"grafana,omitempty"`
}
// Configuration for postgres service
type ConfigPostgres struct {
Pitr *ConfigPostgresPitr `json:"pitr,omitempty"`
Pitr *ConfigPostgresPitr `json:"pitr,omitempty"`
// Resources for the service
Resources *ConfigPostgresResources `json:"resources"`
Settings *ConfigPostgresSettings `json:"settings,omitempty"`
Version *string `json:"version,omitempty"`
// Version of postgres, you can see available versions in the URL below:
// https://hub.docker.com/r/nhost/postgres/tags
Version *string `json:"version,omitempty"`
}
type ConfigPostgresPitr struct {
@@ -954,6 +1030,7 @@ type ConfigPostgresPitrUpdateInput struct {
Retention *uint32 `json:"retention,omitempty"`
}
// Resources for the service
type ConfigPostgresResources struct {
Compute *ConfigResourcesCompute `json:"compute,omitempty"`
EnablePublicAccess *bool `json:"enablePublicAccess,omitempty"`
@@ -1060,15 +1137,19 @@ type ConfigRateLimitUpdateInput struct {
Limit *uint32 `json:"limit,omitempty"`
}
// Resource configuration for a service
type ConfigResources struct {
Autoscaler *ConfigAutoscaler `json:"autoscaler,omitempty"`
Compute *ConfigResourcesCompute `json:"compute,omitempty"`
Networking *ConfigNetworking `json:"networking,omitempty"`
Replicas *uint32 `json:"replicas,omitempty"`
// Number of replicas for a service
Replicas *uint32 `json:"replicas,omitempty"`
}
type ConfigResourcesCompute struct {
CPU uint32 `json:"cpu"`
// milicpus, 1000 milicpus = 1 cpu
CPU uint32 `json:"cpu"`
// MiB: 128MiB to 30GiB
Memory uint32 `json:"memory"`
}
@@ -1120,7 +1201,8 @@ type ConfigRunServiceConfigWithID struct {
}
type ConfigRunServiceImage struct {
Image string `json:"image"`
Image string `json:"image"`
// content of "auths", i.e., { "auths": $THIS }
PullCredentials *string `json:"pullCredentials,omitempty"`
}
@@ -1158,11 +1240,13 @@ type ConfigRunServicePortUpdateInput struct {
Type *string `json:"type,omitempty"`
}
// Resource configuration for a service
type ConfigRunServiceResources struct {
Autoscaler *ConfigAutoscaler `json:"autoscaler,omitempty"`
Compute *ConfigComputeResources `json:"compute"`
Replicas uint32 `json:"replicas"`
Storage []*ConfigRunServiceResourcesStorage `json:"storage,omitempty"`
Autoscaler *ConfigAutoscaler `json:"autoscaler,omitempty"`
Compute *ConfigComputeResources `json:"compute"`
// Number of replicas for a service
Replicas uint32 `json:"replicas"`
Storage []*ConfigRunServiceResourcesStorage `json:"storage,omitempty"`
}
type ConfigRunServiceResourcesInsertInput struct {
@@ -1173,9 +1257,11 @@ type ConfigRunServiceResourcesInsertInput struct {
}
type ConfigRunServiceResourcesStorage struct {
// GiB
Capacity uint32 `json:"capacity"`
Name string `json:"name"`
Path string `json:"path"`
// name of the volume, changing it will cause data loss
Name string `json:"name"`
Path string `json:"path"`
}
type ConfigRunServiceResourcesStorageInsertInput struct {
@@ -1259,11 +1345,20 @@ type ConfigStandardOauthProviderWithScopeUpdateInput struct {
Scope []string `json:"scope,omitempty"`
}
// Configuration for storage service
type ConfigStorage struct {
Antivirus *ConfigStorageAntivirus `json:"antivirus,omitempty"`
RateLimit *ConfigRateLimit `json:"rateLimit,omitempty"`
Resources *ConfigResources `json:"resources,omitempty"`
Version *string `json:"version,omitempty"`
// Networking (custom domains at the moment) are not allowed as we need to do further
// configurations in the CDN. We will enable it again in the future.
Resources *ConfigResources `json:"resources,omitempty"`
// Version of storage service, you can see available versions in the URL below:
// https://hub.docker.com/r/nhost/hasura-storage/tags
//
// Releases:
//
// https://github.com/nhost/hasura-storage/releases
Version *string `json:"version,omitempty"`
}
type ConfigStorageAntivirus struct {
@@ -1301,6 +1396,8 @@ type ConfigSystemConfigAuthEmailTemplates struct {
}
type ConfigSystemConfigGraphql struct {
// manually enable graphi on a per-service basis
// by default it follows the plan
FeatureAdvancedGraphql *bool `json:"featureAdvancedGraphql,omitempty"`
}
@@ -1718,7 +1815,8 @@ type Apps struct {
AppStates []*AppStateHistory `json:"appStates"`
AutomaticDeploys bool `json:"automaticDeploys"`
// An array relationship
Backups []*Backups `json:"backups"`
Backups []*Backups `json:"backups"`
// main entrypoint to the configuration
Config *ConfigConfig `json:"config,omitempty"`
CreatedAt time.Time `json:"createdAt"`
// An object relationship
@@ -2149,6 +2247,14 @@ type AuthUserProvidersMinOrderBy struct {
ProviderID *OrderBy `json:"providerId,omitempty"`
}
// response of any mutation on the table "auth.user_providers"
type AuthUserProvidersMutationResponse struct {
// number of rows affected by the mutation
AffectedRows int64 `json:"affected_rows"`
// data from the rows affected by the mutation
Returning []*AuthUserProviders `json:"returning"`
}
// Ordering options when selecting data from "auth.user_providers".
type AuthUserProvidersOrderBy struct {
ID *OrderBy `json:"id,omitempty"`
@@ -2725,6 +2831,7 @@ type Deployments struct {
CommitSha string `json:"commitSHA"`
CommitUserAvatarURL *string `json:"commitUserAvatarUrl,omitempty"`
CommitUserName *string `json:"commitUserName,omitempty"`
CreatedAt time.Time `json:"createdAt"`
DeploymentEndedAt *time.Time `json:"deploymentEndedAt,omitempty"`
// An array relationship
DeploymentLogs []*DeploymentLogs `json:"deploymentLogs"`
@@ -2767,6 +2874,7 @@ type DeploymentsBoolExp struct {
CommitSha *StringComparisonExp `json:"commitSHA,omitempty"`
CommitUserAvatarURL *StringComparisonExp `json:"commitUserAvatarUrl,omitempty"`
CommitUserName *StringComparisonExp `json:"commitUserName,omitempty"`
CreatedAt *TimestamptzComparisonExp `json:"createdAt,omitempty"`
DeploymentEndedAt *TimestamptzComparisonExp `json:"deploymentEndedAt,omitempty"`
DeploymentLogs *DeploymentLogsBoolExp `json:"deploymentLogs,omitempty"`
DeploymentStartedAt *TimestamptzComparisonExp `json:"deploymentStartedAt,omitempty"`
@@ -2801,6 +2909,7 @@ type DeploymentsMaxOrderBy struct {
CommitSha *OrderBy `json:"commitSHA,omitempty"`
CommitUserAvatarURL *OrderBy `json:"commitUserAvatarUrl,omitempty"`
CommitUserName *OrderBy `json:"commitUserName,omitempty"`
CreatedAt *OrderBy `json:"createdAt,omitempty"`
DeploymentEndedAt *OrderBy `json:"deploymentEndedAt,omitempty"`
DeploymentStartedAt *OrderBy `json:"deploymentStartedAt,omitempty"`
DeploymentStatus *OrderBy `json:"deploymentStatus,omitempty"`
@@ -2823,6 +2932,7 @@ type DeploymentsMinOrderBy struct {
CommitSha *OrderBy `json:"commitSHA,omitempty"`
CommitUserAvatarURL *OrderBy `json:"commitUserAvatarUrl,omitempty"`
CommitUserName *OrderBy `json:"commitUserName,omitempty"`
CreatedAt *OrderBy `json:"createdAt,omitempty"`
DeploymentEndedAt *OrderBy `json:"deploymentEndedAt,omitempty"`
DeploymentStartedAt *OrderBy `json:"deploymentStartedAt,omitempty"`
DeploymentStatus *OrderBy `json:"deploymentStatus,omitempty"`
@@ -2861,6 +2971,7 @@ type DeploymentsOrderBy struct {
CommitSha *OrderBy `json:"commitSHA,omitempty"`
CommitUserAvatarURL *OrderBy `json:"commitUserAvatarUrl,omitempty"`
CommitUserName *OrderBy `json:"commitUserName,omitempty"`
CreatedAt *OrderBy `json:"createdAt,omitempty"`
DeploymentEndedAt *OrderBy `json:"deploymentEndedAt,omitempty"`
DeploymentLogsAggregate *DeploymentLogsAggregateOrderBy `json:"deploymentLogs_aggregate,omitempty"`
DeploymentStartedAt *OrderBy `json:"deploymentStartedAt,omitempty"`
@@ -2892,6 +3003,7 @@ type DeploymentsStreamCursorValueInput struct {
CommitSha *string `json:"commitSHA,omitempty"`
CommitUserAvatarURL *string `json:"commitUserAvatarUrl,omitempty"`
CommitUserName *string `json:"commitUserName,omitempty"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
DeploymentEndedAt *time.Time `json:"deploymentEndedAt,omitempty"`
DeploymentStartedAt *time.Time `json:"deploymentStartedAt,omitempty"`
DeploymentStatus *string `json:"deploymentStatus,omitempty"`
@@ -4079,32 +4191,34 @@ type Plans struct {
// An array relationship
Organizations []*Organizations `json:"organizations"`
Price int64 `json:"price"`
SLALevel SLALevelEnum `json:"slaLevel"`
Sort int64 `json:"sort"`
UpatedAt time.Time `json:"upatedAt"`
}
// Boolean expression to filter rows from the table "plans". All fields are combined with a logical 'AND'.
type PlansBoolExp struct {
And []*PlansBoolExp `json:"_and,omitempty"`
Not *PlansBoolExp `json:"_not,omitempty"`
Or []*PlansBoolExp `json:"_or,omitempty"`
Apps *AppsBoolExp `json:"apps,omitempty"`
CreatedAt *TimestamptzComparisonExp `json:"createdAt,omitempty"`
Deprecated *BooleanComparisonExp `json:"deprecated,omitempty"`
FeatureBackupEnabled *BooleanComparisonExp `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *BooleanComparisonExp `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *BooleanComparisonExp `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *IntComparisonExp `json:"featureMaxDbSize,omitempty"`
ID *UUIDComparisonExp `json:"id,omitempty"`
Individual *BooleanComparisonExp `json:"individual,omitempty"`
IsDefault *BooleanComparisonExp `json:"isDefault,omitempty"`
IsFree *BooleanComparisonExp `json:"isFree,omitempty"`
IsPublic *BooleanComparisonExp `json:"isPublic,omitempty"`
Name *StringComparisonExp `json:"name,omitempty"`
Organizations *OrganizationsBoolExp `json:"organizations,omitempty"`
Price *IntComparisonExp `json:"price,omitempty"`
Sort *IntComparisonExp `json:"sort,omitempty"`
UpatedAt *TimestamptzComparisonExp `json:"upatedAt,omitempty"`
And []*PlansBoolExp `json:"_and,omitempty"`
Not *PlansBoolExp `json:"_not,omitempty"`
Or []*PlansBoolExp `json:"_or,omitempty"`
Apps *AppsBoolExp `json:"apps,omitempty"`
CreatedAt *TimestamptzComparisonExp `json:"createdAt,omitempty"`
Deprecated *BooleanComparisonExp `json:"deprecated,omitempty"`
FeatureBackupEnabled *BooleanComparisonExp `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *BooleanComparisonExp `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *BooleanComparisonExp `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *IntComparisonExp `json:"featureMaxDbSize,omitempty"`
ID *UUIDComparisonExp `json:"id,omitempty"`
Individual *BooleanComparisonExp `json:"individual,omitempty"`
IsDefault *BooleanComparisonExp `json:"isDefault,omitempty"`
IsFree *BooleanComparisonExp `json:"isFree,omitempty"`
IsPublic *BooleanComparisonExp `json:"isPublic,omitempty"`
Name *StringComparisonExp `json:"name,omitempty"`
Organizations *OrganizationsBoolExp `json:"organizations,omitempty"`
Price *IntComparisonExp `json:"price,omitempty"`
SLALevel *SLALevelEnumComparisonExp `json:"slaLevel,omitempty"`
Sort *IntComparisonExp `json:"sort,omitempty"`
UpatedAt *TimestamptzComparisonExp `json:"upatedAt,omitempty"`
}
// Ordering options when selecting data from "plans".
@@ -4124,6 +4238,7 @@ type PlansOrderBy struct {
Name *OrderBy `json:"name,omitempty"`
OrganizationsAggregate *OrganizationsAggregateOrderBy `json:"organizations_aggregate,omitempty"`
Price *OrderBy `json:"price,omitempty"`
SLALevel *OrderBy `json:"slaLevel,omitempty"`
Sort *OrderBy `json:"sort,omitempty"`
UpatedAt *OrderBy `json:"upatedAt,omitempty"`
}
@@ -4138,21 +4253,22 @@ type PlansStreamCursorInput struct {
// Initial value of the column from where the streaming should start
type PlansStreamCursorValueInput struct {
CreatedAt *time.Time `json:"createdAt,omitempty"`
Deprecated *bool `json:"deprecated,omitempty"`
FeatureBackupEnabled *bool `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *bool `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *bool `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *int64 `json:"featureMaxDbSize,omitempty"`
ID *string `json:"id,omitempty"`
Individual *bool `json:"individual,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
IsFree *bool `json:"isFree,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
Name *string `json:"name,omitempty"`
Price *int64 `json:"price,omitempty"`
Sort *int64 `json:"sort,omitempty"`
UpatedAt *time.Time `json:"upatedAt,omitempty"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
Deprecated *bool `json:"deprecated,omitempty"`
FeatureBackupEnabled *bool `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *bool `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *bool `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *int64 `json:"featureMaxDbSize,omitempty"`
ID *string `json:"id,omitempty"`
Individual *bool `json:"individual,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
IsFree *bool `json:"isFree,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
Name *string `json:"name,omitempty"`
Price *int64 `json:"price,omitempty"`
SLALevel *SLALevelEnum `json:"slaLevel,omitempty"`
Sort *int64 `json:"sort,omitempty"`
UpatedAt *time.Time `json:"upatedAt,omitempty"`
}
type QueryRoot struct {
@@ -4582,6 +4698,15 @@ type RunServiceStreamCursorValueInput struct {
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}
// Boolean expression to compare columns of type "sla_level_enum". All fields are combined with logical 'AND'.
type SLALevelEnumComparisonExp struct {
Eq *SLALevelEnum `json:"_eq,omitempty"`
In []SLALevelEnum `json:"_in,omitempty"`
IsNull *bool `json:"_is_null,omitempty"`
Neq *SLALevelEnum `json:"_neq,omitempty"`
Nin []SLALevelEnum `json:"_nin,omitempty"`
}
// Boolean expression to compare columns of type "software_type_enum". All fields are combined with logical 'AND'.
type SoftwareTypeEnumComparisonExp struct {
Eq *SoftwareTypeEnum `json:"_eq,omitempty"`
@@ -6885,6 +7010,8 @@ const (
// column name
DeploymentsSelectColumnCommitUserName DeploymentsSelectColumn = "commitUserName"
// column name
DeploymentsSelectColumnCreatedAt DeploymentsSelectColumn = "createdAt"
// column name
DeploymentsSelectColumnDeploymentEndedAt DeploymentsSelectColumn = "deploymentEndedAt"
// column name
DeploymentsSelectColumnDeploymentStartedAt DeploymentsSelectColumn = "deploymentStartedAt"
@@ -6918,6 +7045,7 @@ var AllDeploymentsSelectColumn = []DeploymentsSelectColumn{
DeploymentsSelectColumnCommitSha,
DeploymentsSelectColumnCommitUserAvatarURL,
DeploymentsSelectColumnCommitUserName,
DeploymentsSelectColumnCreatedAt,
DeploymentsSelectColumnDeploymentEndedAt,
DeploymentsSelectColumnDeploymentStartedAt,
DeploymentsSelectColumnDeploymentStatus,
@@ -6935,7 +7063,7 @@ var AllDeploymentsSelectColumn = []DeploymentsSelectColumn{
func (e DeploymentsSelectColumn) IsValid() bool {
switch e {
case DeploymentsSelectColumnAppID, DeploymentsSelectColumnCommitMessage, DeploymentsSelectColumnCommitSha, DeploymentsSelectColumnCommitUserAvatarURL, DeploymentsSelectColumnCommitUserName, DeploymentsSelectColumnDeploymentEndedAt, DeploymentsSelectColumnDeploymentStartedAt, DeploymentsSelectColumnDeploymentStatus, DeploymentsSelectColumnFunctionsEndedAt, DeploymentsSelectColumnFunctionsStartedAt, DeploymentsSelectColumnFunctionsStatus, DeploymentsSelectColumnID, DeploymentsSelectColumnMetadataEndedAt, DeploymentsSelectColumnMetadataStartedAt, DeploymentsSelectColumnMetadataStatus, DeploymentsSelectColumnMigrationsEndedAt, DeploymentsSelectColumnMigrationsStartedAt, DeploymentsSelectColumnMigrationsStatus:
case DeploymentsSelectColumnAppID, DeploymentsSelectColumnCommitMessage, DeploymentsSelectColumnCommitSha, DeploymentsSelectColumnCommitUserAvatarURL, DeploymentsSelectColumnCommitUserName, DeploymentsSelectColumnCreatedAt, DeploymentsSelectColumnDeploymentEndedAt, DeploymentsSelectColumnDeploymentStartedAt, DeploymentsSelectColumnDeploymentStatus, DeploymentsSelectColumnFunctionsEndedAt, DeploymentsSelectColumnFunctionsStartedAt, DeploymentsSelectColumnFunctionsStatus, DeploymentsSelectColumnID, DeploymentsSelectColumnMetadataEndedAt, DeploymentsSelectColumnMetadataStartedAt, DeploymentsSelectColumnMetadataStatus, DeploymentsSelectColumnMigrationsEndedAt, DeploymentsSelectColumnMigrationsStartedAt, DeploymentsSelectColumnMigrationsStatus:
return true
}
return false
@@ -8427,6 +8555,8 @@ const (
// column name
PlansSelectColumnPrice PlansSelectColumn = "price"
// column name
PlansSelectColumnSLALevel PlansSelectColumn = "slaLevel"
// column name
PlansSelectColumnSort PlansSelectColumn = "sort"
// column name
PlansSelectColumnUpatedAt PlansSelectColumn = "upatedAt"
@@ -8446,13 +8576,14 @@ var AllPlansSelectColumn = []PlansSelectColumn{
PlansSelectColumnIsPublic,
PlansSelectColumnName,
PlansSelectColumnPrice,
PlansSelectColumnSLALevel,
PlansSelectColumnSort,
PlansSelectColumnUpatedAt,
}
func (e PlansSelectColumn) IsValid() bool {
switch e {
case PlansSelectColumnCreatedAt, PlansSelectColumnDeprecated, PlansSelectColumnFeatureBackupEnabled, PlansSelectColumnFeatureCustomDomainsEnabled, PlansSelectColumnFeatureCustomEmailTemplatesEnabled, PlansSelectColumnFeatureMaxDbSize, PlansSelectColumnID, PlansSelectColumnIndividual, PlansSelectColumnIsDefault, PlansSelectColumnIsFree, PlansSelectColumnIsPublic, PlansSelectColumnName, PlansSelectColumnPrice, PlansSelectColumnSort, PlansSelectColumnUpatedAt:
case PlansSelectColumnCreatedAt, PlansSelectColumnDeprecated, PlansSelectColumnFeatureBackupEnabled, PlansSelectColumnFeatureCustomDomainsEnabled, PlansSelectColumnFeatureCustomEmailTemplatesEnabled, PlansSelectColumnFeatureMaxDbSize, PlansSelectColumnID, PlansSelectColumnIndividual, PlansSelectColumnIsDefault, PlansSelectColumnIsFree, PlansSelectColumnIsPublic, PlansSelectColumnName, PlansSelectColumnPrice, PlansSelectColumnSLALevel, PlansSelectColumnSort, PlansSelectColumnUpatedAt:
return true
}
return false
@@ -8839,6 +8970,66 @@ func (e RunServiceSelectColumn) MarshalJSON() ([]byte, error) {
return buf.Bytes(), nil
}
type SLALevelEnum string
const (
// No SLA
SLALevelEnumNone SLALevelEnum = "none"
// Premium SLA
SLALevelEnumPremium SLALevelEnum = "premium"
// Standard SLA
SLALevelEnumStandard SLALevelEnum = "standard"
)
var AllSLALevelEnum = []SLALevelEnum{
SLALevelEnumNone,
SLALevelEnumPremium,
SLALevelEnumStandard,
}
func (e SLALevelEnum) IsValid() bool {
switch e {
case SLALevelEnumNone, SLALevelEnumPremium, SLALevelEnumStandard:
return true
}
return false
}
func (e SLALevelEnum) String() string {
return string(e)
}
func (e *SLALevelEnum) UnmarshalGQL(v any) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = SLALevelEnum(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid sla_level_enum", str)
}
return nil
}
func (e SLALevelEnum) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
func (e *SLALevelEnum) UnmarshalJSON(b []byte) error {
s, err := strconv.Unquote(string(b))
if err != nil {
return err
}
return e.UnmarshalGQL(s)
}
func (e SLALevelEnum) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
e.MarshalGQL(&buf)
return buf.Bytes(), nil
}
type SoftwareTypeEnum string
const (

View File

@@ -1,27 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIERDCCA8mgAwIBAgISBmRex3kpZ4Mz1/1kq05iqja/MAoGCCqGSM49BAMDMDIx
MIIERTCCA8ugAwIBAgISBWD/E+b14mP5jv4DGWRVYv8fMAoGCCqGSM49BAMDMDIx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
ODAeFw0yNTEwMDIxMDUxNDBaFw0yNTEyMzExMDUxMzlaMB8xHTAbBgNVBAMTFGxv
Y2FsLmF1dGgubmhvc3QucnVuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2cVM
ojf8iXZGLneNfnke5LMJIxyTEeGbNOfCv4SOR4K/N4OkpvkUVbH2bRvX99uE9jaK
515Y48PzPA/4+W1zTKOCAtAwggLMMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUQqan
raZoU5klAxsgkEVEMIkxmMQwHwYDVR0jBBgwFoAUjw0TovYuftFQbDMYOF1ZjiNy
ODAeFw0yNTExMDYxMDUxMTBaFw0yNjAyMDQxMDUxMDlaMB8xHTAbBgNVBAMTFGxv
Y2FsLmF1dGgubmhvc3QucnVuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOah5
ZLuUQp3pdMBxBWnT6E6/amW9LerKKEEdy3Nc8iAwG9LlnPH0z3m7a9wgEhpFEdlL
Rr+qO+NhSRnv6+UF5KOCAtIwggLOMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGyb1
TVK/0vf3uHO4x3R094aG2rEwHwYDVR0jBBgwFoAUjw0TovYuftFQbDMYOF1ZjiNy
kcowMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAChhZodHRwOi8vZTguaS5sZW5j
ci5vcmcvMIHOBgNVHREEgcYwgcOCFGxvY2FsLmF1dGgubmhvc3QucnVughlsb2Nh
bC5kYXNoYm9hcmQubmhvc3QucnVughJsb2NhbC5kYi5uaG9zdC5ydW6CGWxvY2Fs
LmZ1bmN0aW9ucy5uaG9zdC5ydW6CF2xvY2FsLmdyYXBocWwubmhvc3QucnVughZs
b2NhbC5oYXN1cmEubmhvc3QucnVughdsb2NhbC5tYWlsaG9nLm5ob3N0LnJ1boIX
bG9jYWwuc3RvcmFnZS5uaG9zdC5ydW4wEwYDVR0gBAwwCjAIBgZngQwBAgEwLQYD
VR0fBCYwJDAioCCgHoYcaHR0cDovL2U4LmMubGVuY3Iub3JnLzY0LmNybDCCAQIG
CisGAQQB1nkCBAIEgfMEgfAA7gB1AO08S9boBsKkogBX28sk4jgB31Ev7cSGxXAP
IN23Pj/gAAABmaTCI4YAAAQDAEYwRAIgXLRFL1EAXfvN6kd5m6udqlxfz4+5B6rq
Cdhp/ZwDAZ8CIFYvalTkl5NEBEMD3vpPvrj8s1Yy2xsropEh/AvpavvLAHUAGYbU
xyiqb/66A294Kk0BkarOLXIxD67OXXBBLSVMx9QAAAGZpMIjhwAABAMARjBEAiBk
H1vqU9HNuBcf4UYL/xZ42BeUAARHStiFaIZtnR1kEgIgbIJ0CGqIpxmWuwCunl9p
ar+rGLdQrCk9BZXq/VjPPAAwCgYIKoZIzj0EAwMDaQAwZgIxAKvk5a2zQsv7JLNj
NO1ly+DI8qiy5nf4HQrOrHOjtmx5RUu0HSO9P0J0u069qAqXMgIxAMLdME9JUo2c
TJo3pwWv5MRyg/MkOJ4ImKdDJXfIZNkEIUyP3vwTqImvZe07gJDsYg==
VR0fBCYwJDAioCCgHoYcaHR0cDovL2U4LmMubGVuY3Iub3JnLzMyLmNybDCCAQQG
CisGAQQB1nkCBAIEgfUEgfIA8AB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1w
QS0lTMfUAAABmlkAQokAAAQDAEcwRQIgWDtSxJfM2xcjvScVHOkn8bipzBhNhTnm
B89TDh1/4XUCIQDe08W33PCx2D+akCdW9U9mZKQpIW6deLZSI3ZWpSNKMAB2AA5X
lLzzrqk+MxssmQez95Dfm8I9cTIl3SGpJaxhxU4hAAABmlkAQn8AAAQDAEcwRQIg
KnojmNTpNk1OFTQI0EnlPa2bpwqmUgmUCLeqE6SWfgoCIQCrhZbxYPHbGLF/HpRq
vCTcOh24SRCuxlkqtaowbbfmKjAKBggqhkjOPQQDAwNoADBlAjEArstFIC+KAsfQ
nLhtqsaNzkhftN5adDyr2CoE0WUPF1sLDi+xDnDO+JgIPL0YKAFNAjATJ4omhpc+
I6/kWcef2RyO9YCGQQE9pdez5CYKb9o8YAntDSHM3b5nXXj3AX/USdQ=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP

View File

@@ -1,5 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfJZOkvawA0vBMw9W
ph8i1Z+SJQrFscPbqSYpxngzEDahRANCAATZxUyiN/yJdkYud41+eR7kswkjHJMR
4Zs058K/hI5Hgr83g6Sm+RRVsfZtG9f324T2NornXljjw/M8D/j5bXNM
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgInXN4JRnXNTjx7rM
avurZrN1EV1iebQeNUlMlFp7VJ+hRANCAAQ5qHlku5RCnel0wHEFadPoTr9qZb0t
6sooQR3Lc1zyIDAb0uWc8fTPebtr3CASGkUR2UtGv6o742FJGe/r5QXk
-----END PRIVATE KEY-----

View File

@@ -1,52 +1,52 @@
-----BEGIN CERTIFICATE-----
MIIEWDCCA96gAwIBAgISBbvrSsjDQm4zevwwjxFGmeTMMAoGCCqGSM49BAMDMDIx
MIIEVzCCA92gAwIBAgISBm54VdkoqD8s8efq7ceHaTihMAoGCCqGSM49BAMDMDIx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
NzAeFw0yNTEwMDIxMDUyNTdaFw0yNTEyMzExMDUyNTZaMCExHzAdBgNVBAMMFiou
YXV0aC5sb2NhbC5uaG9zdC5ydW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATG
x0o7t0pSrOoFc+pljtqJVxgaSW+w9D9C2WdysMeSKKOU+0MzaM4ynLUhETOpBs8E
612mdcoeak+G1Emj6UVwo4IC4zCCAt8wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQW
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQ+
lVsLiXSRLAECs9OgkCEBS7jMmzAfBgNVHSMEGDAWgBSuSJ7chx1EoG/aouVgdAR4
wpwAgDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly9lNy5pLmxl
ODAeFw0yNTExMDYxMDUyMjBaFw0yNjAyMDQxMDUyMTlaMCExHzAdBgNVBAMMFiou
YXV0aC5sb2NhbC5uaG9zdC5ydW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASI
rTkZOM4ip42DCyDADXGc7oV3+OkimyTM3st2RIZWG28rFRwH0LebJV2cduq1Hdtl
VxIEr+RhvyIL7gllueXUo4IC4jCCAt4wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQW
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTw
bM86O381+aljU3oTUvwhZ90PCDAfBgNVHSMEGDAWgBSPDROi9i5+0VBsMxg4XVmO
I3KRyjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly9lOC5pLmxl
bmNyLm9yZy8wgd4GA1UdEQSB1jCB04IWKi5hdXRoLmxvY2FsLm5ob3N0LnJ1boIb
Ki5kYXNoYm9hcmQubG9jYWwubmhvc3QucnVughQqLmRiLmxvY2FsLm5ob3N0LnJ1
boIbKi5mdW5jdGlvbnMubG9jYWwubmhvc3QucnVughkqLmdyYXBocWwubG9jYWwu
bmhvc3QucnVughgqLmhhc3VyYS5sb2NhbC5uaG9zdC5ydW6CGSoubWFpbGhvZy5s
b2NhbC5uaG9zdC5ydW6CGSouc3RvcmFnZS5sb2NhbC5uaG9zdC5ydW4wEwYDVR0g
BAwwCjAIBgZngQwBAgEwLQYDVR0fBCYwJDAioCCgHoYcaHR0cDovL2U3LmMubGVu
Y3Iub3JnLzc3LmNybDCCAQUGCisGAQQB1nkCBAIEgfYEgfMA8QB2AN3cyjSV1+EW
BeeVMvrHn/g9HFDf2wA6FBJ2Ciysu8gqAAABmaTDUHkAAAQDAEcwRQIgWudJ8XKA
BT5jq5Tl0xQLNb953pBi22Tb0TIWk+RSqHgCIQDsTrLVMFaQTV7EFCY1tFhi5qae
SCpEwwdFcnom/nz6EAB3AO08S9boBsKkogBX28sk4jgB31Ev7cSGxXAPIN23Pj/g
AAABmaTDWAsAAAQDAEgwRgIhALxIgIiutEwgNcGw7/cAdjFqUugct4HlZezIOLLP
rg69AiEA8YCaK41rJDYztEKUIJEq2J2ktSqGYcl9gNKC+SiR4acwCgYIKoZIzj0E
AwMDaAAwZQIwVG9yOiMRfKFFyFj1R8X/5U67QD84OhZ0oM0SZsVhezLedG5b8eFf
/cWraREi8xbFAjEA/6RXweGzl08F7EtqBDoiqitScI2rbwGtP6s/evL0zXTABZD2
ih7AGxjtg80IqIRe
BAwwCjAIBgZngQwBAgEwLQYDVR0fBCYwJDAioCCgHoYcaHR0cDovL2U4LmMubGVu
Y3Iub3JnLzM0LmNybDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AEmcm2neHXzs
/DbezYdkprhbrwqHgBnRVVL76esp3fjDAAABmlkBVgkAAAQDAEcwRQIhANH6Ml3u
IM4nAzwAIjIjBjn8EWbn1ZHfgwO+rlSo5rzpAiATPKE8Mx5LK1IayG5VCK1eCDyc
rzt1HNbP9WSrpuHx+gB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1wQS0lTMfU
AAABmlkBVgcAAAQDAEcwRQIgIT/DhsIj9Aw7qf/2lknJCr907dEqC3/+QN3zlcOj
iKoCIQCTguinYjJPZwU2dblaRQ2q7MTCMT2ZENExltxwYG3GzjAKBggqhkjOPQQD
AwNoADBlAjEA5nFoNrLyeC079YpRvdah/HZIA/lUBh+LOo/NcEBD3aTGs2z8hU8z
H4vMy3OnfQ9TAjBxigm7zE5/3CAcGoSOr/P0TL52nh+lO4SUVxcbKgYB8A2yo6o/
kUkG7PiRB0uUpNw=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEVzCCAj+gAwIBAgIRAKp18eYrjwoiCWbTi7/UuqEwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCRTcwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARB6AST
CFh/vjcwDMCgQer+VtqEkz7JANurZxLP+U9TCeioL6sp5Z8VRvRbYk4P1INBmbef
QHJFHCxcSjKmwtvGBWpl/9ra8HW0QDsUaJW2qOJqceJ0ZVFT3hbUHifBM/2jgfgw
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSuSJ7chx1EoG/aouVgdAR4
wpwAgDAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAjx66fDdLk5ywFn3CzA1w1qfylHUD
aEf0QZpXcJseddJGSfbUUOvbNR9N/QQ16K1lXl4VFyhmGXDT5Kdfcr0RvIIVrNxF
h4lqHtRRCP6RBRstqbZ2zURgqakn/Xip0iaQL0IdfHBZr396FgknniRYFckKORPG
yM3QKnd66gtMst8I5nkRQlAg/Jb+Gc3egIvuGKWboE1G89NTsN9LTDD3PLj0dUMr
OIuqVjLB8pEC6yk9enrlrqjXQgkLEYhXzq7dLafv5Vkig6Gl0nuuqjqfp0Q1bi1o
yVNAlXe6aUXw92CcghC9bNsKEO1+M52YY5+ofIXlS/SEQbvVYYBLZ5yeiglV6t3S
M6H+vTG0aP9YHzLn/KVOHzGQfXDP7qM5tkf+7diZe7o2fw6O7IvN6fsQXEQQj8TJ
UXJxv2/uJhcuy/tSDgXwHM8Uk34WNbRT7zGTGkQRX0gsbjAea/jYAoWv0ZvQRwpq
Pe79D/i7Cep8qWnA+7AE/3B3S/3dEEYmc0lpe1366A/6GEgk3ktr9PEoQrLChs6I
tu3wnNLB2euC8IKGLQFpGtOO/2/hiAKjyajaBP25w1jF0Wl8Bbqne3uZ2q1GyPFJ
YRmT7/OXpmOH/FVLtwS+8ng1cAmpCujPwteJZNcDG0sF2n/sc0+SQf49fdyUK0ty
+VUwFj9tmWxyR/M=
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
u1igv3OefnWjSQ==
-----END CERTIFICATE-----

View File

@@ -1,5 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrfNUSjLV/7j7LSBf
zL/hvGEuv+uvf3/aimqjecO7vcShRANCAATGx0o7t0pSrOoFc+pljtqJVxgaSW+w
9D9C2WdysMeSKKOU+0MzaM4ynLUhETOpBs8E612mdcoeak+G1Emj6UVw
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgcrhROXQT85e+S8h8
RE3Z7TPo3+WA2RmzJsXJbXkbi5qhRANCAASIrTkZOM4ip42DCyDADXGc7oV3+Oki
myTM3st2RIZWG28rFRwH0LebJV2cduq1HdtlVxIEr+RhvyIL7gllueXU
-----END PRIVATE KEY-----

View File

@@ -3,12 +3,13 @@ NEXT_PUBLIC_ENV=dev
NEXT_PUBLIC_NHOST_PLATFORM=false
# Environment Variables for Self Hosting and Local Development
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.nhost.local.run/v1
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.local.nhost.run/v1
NEXT_PUBLIC_NHOST_CONFIGSERVER_URL=https://local.dashboard.local.nhost.run/v1/configserver/graphql
NEXT_PUBLIC_NHOST_FUNCTIONS_URL=https://local.functions.local.nhost.run/v1
NEXT_PUBLIC_NHOST_GRAPHQL_URL=https://local.graphql.local.nhost.run/v1
NEXT_PUBLIC_NHOST_STORAGE_URL=https://local.storage.local.nhost.run/v1
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.local.nhost.run
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.local.nhost.run/v1/migrations
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.local.nhost.run/console
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.local.nhost.run/apis/migrate
NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.local.nhost.run
# Environment Variables when running the Nhost Dashboard against the Nhost Backend
@@ -18,13 +19,13 @@ NEXT_PUBLIC_ANALYTICS_WRITE_KEY=<analytics_write_key>
NEXT_PUBLIC_SEGMENT_CDN_URL=<segment_cdn_url>
NEXT_PUBLIC_NHOST_BRAGI_WEBSOCKET=<nhost_bragi_websocket>
NEXT_PUBLIC_ZENDESK_URL=
NEXT_PUBLIC_ZENDESK_API_KEY=
NEXT_PUBLIC_ZENDESK_USER_EMAIL=
NEXT_ZENDESK_URL=
NEXT_ZENDESK_API_KEY=
NEXT_ZENDESK_USER_EMAIL=
CODEGEN_GRAPHQL_URL=https://local.graphql.local.nhost.run/v1
CODEGEN_HASURA_ADMIN_SECRET=nhost-admin-secret
NEXT_PUBLIC_TURNSTILE_SITE_KEY=FIXME
NEXT_PUBLIC_SOC2_REPORT_FILE_ID=
NEXT_PUBLIC_SOC2_REPORT_FILE_ID=

View File

@@ -1,7 +1,58 @@
## [@nhost/dashboard@2.42.0] - 2025-11-12
### 🚀 Features
- *(dashboard)* Datatable design improvements (#3657)
### ⚙️ Miscellaneous Tasks
- *(dashboard)* Remove v2 ui components from datatable (#3568)
## [@nhost/dashboard@2.41.0] - 2025-11-04
### 🚀 Features
- *(auth)* Added endpoints to retrieve and refresh oauth2 providers' tokens (#3614)
- *(dashboard)* Get github repositories from github itself (#3640)
### 🐛 Bug Fixes
- *(dashboard)* Update SQL editor to use correct hasura migrations API URL (#3645)
# Changelog
All notable changes to this project will be documented in this file.
## [@nhost/dashboard@2.40.0] - 2025-10-27
### 🚀 Features
- *(dashboard)* Allow configuring CSP header (#3627)
### ⚙️ Miscellaneous Tasks
- *(dashboard)* Various improvements to support ticket page (#3630)
## [@nhost/dashboard@2.39.0] - 2025-10-22
### 🚀 Features
- *(dashboard)* Move zendesk request to API route (#3628)
### 🐛 Bug Fixes
- *(dashboard)* Fix flaky e2e tests (#3536)
- *(dashboard)* Run audit and lint in dashboard (#3578)
### ⚙️ Miscellaneous Tasks
- *(dashboard)* Cleanup e2e remote schemas test before run (#3581)
## [@nhost/dashboard@2.38.4] - 2025-10-09
### 🐛 Bug Fixes

View File

@@ -82,6 +82,15 @@ This will connect the Nhost Dashboard to your locally running Nhost backend.
| `NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL` | The URL of Hasura's Migrations service. When working locally, point it to the Migrations service started by the CLI. |
| `NEXT_PUBLIC_NHOST_HASURA_API_URL` | The URL of Hasura's Schema and Metadata API. When working locally, point it to the Schema and Metadata API started by the CLI. When self-hosting, point it to the self-hosted Schema and Metadata API. |
### Content Security Policy (CSP) Configuration
The dashboard supports build-time CSP configuration to enable self-hosted deployments on custom domains.
| Name | Description |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CSP_MODE` | Controls CSP behavior. Options: `nhost` (default, uses Nhost Cloud CSP), `disabled` (no CSP headers), `custom` (use custom CSP via `CSP_HEADER`). For self-hosted deployments on custom domains, set to `disabled` or `custom`. |
| `CSP_HEADER` | Custom Content Security Policy header value. Only used when `CSP_MODE=custom`. Should be a complete CSP string (e.g., `default-src 'self'; script-src 'self' 'unsafe-eval'; ...`). |
### Other Environment Variables
| Name | Description |

View File

@@ -102,7 +102,7 @@ test('should create a table with nullable columns', async ({
page.getByRole('link', { name: tableName, exact: true }),
).toBeVisible();
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
.click();
await page.getByText('Edit Table').click();
await expect(page.locator('h2:has-text("Edit Table")')).toBeVisible();
@@ -143,7 +143,7 @@ test('should create a table with an identity column', async ({
page.getByRole('link', { name: tableName, exact: true }),
).toBeVisible();
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
.click();
await page.getByText('Edit Table').click();
await expect(page.locator('h2:has-text("Edit Table")')).toBeVisible();
@@ -267,7 +267,7 @@ test('should be able to create a table with a composite key', async ({
).toBeVisible();
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
.click();
await page.getByText('Edit Table').click();
await expect(page.locator('div[data-testid="id"]')).toBeVisible();

View File

@@ -41,7 +41,7 @@ test('should create a table with role permissions to select row', async ({
// Press three horizontal dots more options button next to the table name
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
.click();
await page.getByRole('menuitem', { name: /edit permissions/i }).click();
@@ -89,7 +89,7 @@ test('should create a table with role permissions and a custom check to select r
// Press three horizontal dots more options button next to the table name
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
.click();
await page.getByRole('menuitem', { name: /edit permissions/i }).click();
@@ -114,7 +114,7 @@ test('should create a table with role permissions and a custom check to select r
await page.getByText('Select variable...', { exact: true }).click();
const variableSelector = await page.locator('input[role="combobox"]');
const variableSelector = page.locator('input[role="combobox"]');
await variableSelector.fill('X-Hasura-User-Id');

View File

@@ -4,21 +4,31 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
});
const { version } = require('./package.json');
const cspHeader = `
default-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run;
script-src 'self' 'unsafe-eval' cdn.segment.com js.stripe.com challenges.cloudflare.com googletagmanager.com;
connect-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run discord.com api.segment.io api.segment.com cdn.segment.com nhost.zendesk.com;
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data: github.com avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run;
font-src 'self' data:;
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
frame-src 'self' js.stripe.com challenges.cloudflare.com;
block-all-mixed-content;
upgrade-insecure-requests;
`;
function getCspHeader() {
switch (process.env.CSP_MODE) {
case 'disabled':
return null;
case 'custom':
return process.env.CSP_HEADER || null;
case 'nhost':
default:
return [
"default-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run",
"script-src 'self' 'unsafe-eval' cdn.segment.com js.stripe.com challenges.cloudflare.com googletagmanager.com",
"connect-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run discord.com api.segment.io api.segment.com cdn.segment.com nhost.zendesk.com api.github.com",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' blob: data: github.com avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run",
"font-src 'self' data:",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
"frame-ancestors 'none'",
"frame-src 'self' js.stripe.com challenges.cloudflare.com",
"block-all-mixed-content",
"upgrade-insecure-requests",
].join('; ') + ';';
}
}
module.exports = withBundleAnalyzer({
reactStrictMode: false,
@@ -34,13 +44,19 @@ module.exports = withBundleAnalyzer({
dirs: ['src'],
},
async headers() {
const cspHeader = getCspHeader();
if (!cspHeader) {
return []; // No CSP headers
}
return [
{
source: '/(.*)',
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: cspHeader.replace(/\s+/g, ' ').trim(),
value: cspHeader,
},
{
key: 'X-Frame-Options',
@@ -110,4 +126,4 @@ module.exports = withBundleAnalyzer({
},
];
},
});
});

View File

@@ -38,6 +38,7 @@
"@graphiql/react": "^0.22.3",
"@graphiql/toolkit": "^0.9.1",
"@headlessui/react": "^1.7.18",
"@hello-pangea/dnd": "^18.0.1",
"@heroicons/react": "^1.0.6",
"@hookform/resolvers": "^3.9.0",
"@iarna/toml": "^2.2.5",
@@ -60,7 +61,7 @@
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.1.2",
@@ -93,7 +94,7 @@
"just-kebab-case": "^4.2.0",
"jwt-decode": "^4.0.0",
"lodash.debounce": "^4.0.8",
"lucide-react": "^0.416.0",
"lucide-react": "^0.552.0",
"next": "^14.2.31",
"next-nprogress-bar": "^2.3.13",
"next-seo": "^6.5.0",
@@ -125,7 +126,7 @@
"timezones-list": "^3.1.0",
"utility-types": "^3.11.0",
"uuid": "^9.0.1",
"validator": "^13.11.0",
"validator": "^13.15.20",
"yup": "^1.4.0",
"yup-password": "^0.2.2",
"zod": "^3.23.8"
@@ -196,7 +197,7 @@
"tailwindcss": "^3.4.12",
"ts-node": "^10.9.2",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"vite": "^5.4.20",
"vite": "^5.4.21",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^3.2.4"
},
@@ -231,7 +232,9 @@
}
},
"overrides": {
"esbuild@<=0.24.2": ">=0.25.0"
"esbuild@<=0.24.2": ">=0.25.0",
"js-yaml@<=4.1.0": ">=4.1.1",
"glob@>=10.3.7 <=11.0.3": ">=11.1.0"
}
}
}

299
dashboard/pnpm-lock.yaml generated
View File

@@ -6,6 +6,8 @@ settings:
overrides:
esbuild@<=0.24.2: '>=0.25.0'
js-yaml@<=4.1.0: '>=4.1.1'
glob@>=10.3.7 <=11.0.3: '>=11.1.0'
packageExtensionsChecksum: sha256-gRFeykwiwMfEE6etcYx6N48XwVeKzxbqNveL7KTQgSQ=
@@ -55,6 +57,9 @@ importers:
'@headlessui/react':
specifier: ^1.7.18
version: 1.7.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@hello-pangea/dnd':
specifier: ^18.0.1
version: 18.0.1(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@heroicons/react':
specifier: ^1.0.6
version: 1.0.6(react@18.2.0)
@@ -122,8 +127,8 @@ importers:
specifier: ^1.1.0
version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-slot':
specifier: ^1.1.1
version: 1.1.2(@types/react@18.2.73)(react@18.2.0)
specifier: ^1.1.2
version: 1.2.3(@types/react@18.2.73)(react@18.2.0)
'@radix-ui/react-switch':
specifier: ^1.2.6
version: 1.2.6(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -221,8 +226,8 @@ importers:
specifier: ^4.0.8
version: 4.0.8
lucide-react:
specifier: ^0.416.0
version: 0.416.0(react@18.2.0)
specifier: ^0.552.0
version: 0.552.0(react@18.2.0)
next:
specifier: ^14.2.31
version: 14.2.32(@babel/core@7.26.10)(@playwright/test@1.54.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -317,8 +322,8 @@ importers:
specifier: ^9.0.1
version: 9.0.1
validator:
specifier: ^13.11.0
version: 13.12.0
specifier: ^13.15.20
version: 13.15.23
yup:
specifier: ^1.4.0
version: 1.5.0
@@ -415,7 +420,7 @@ importers:
version: 6.21.0(eslint@8.57.0)(typescript@5.8.3)
'@vitejs/plugin-react':
specifier: ^4.7.0
version: 4.7.0(vite@5.4.20(@types/node@20.14.8)(terser@5.44.0))
version: 4.7.0(vite@5.4.21(@types/node@20.14.8)(terser@5.44.0))
'@vitest/coverage-v8':
specifier: ^3.2.4
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.14.8)(jsdom@22.1.0)(msw@2.11.4(@types/node@20.14.8)(typescript@5.8.3))(terser@5.44.0))
@@ -525,11 +530,11 @@ importers:
specifier: ^4.1.0
version: 4.2.0
vite:
specifier: ^5.4.20
version: 5.4.20(@types/node@20.14.8)(terser@5.44.0)
specifier: ^5.4.21
version: 5.4.21(@types/node@20.14.8)(terser@5.44.0)
vite-tsconfig-paths:
specifier: ^4.3.2
version: 4.3.2(typescript@5.8.3)(vite@5.4.20(@types/node@20.14.8)(terser@5.44.0))
version: 4.3.2(typescript@5.8.3)(vite@5.4.21(@types/node@20.14.8)(terser@5.44.0))
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/debug@4.1.12)(@types/node@20.14.8)(jsdom@22.1.0)(msw@2.11.4(@types/node@20.14.8)(typescript@5.8.3))(terser@5.44.0)
@@ -2063,6 +2068,12 @@ packages:
react: ^16 || ^17 || ^18
react-dom: ^16 || ^17 || ^18
'@hello-pangea/dnd@18.0.1':
resolution: {integrity: sha512-xojVWG8s/TGrKT1fC8K2tIWeejJYTAeJuj36zM//yEm/ZrnZUSFGS15BpO+jGZT1ybWvyXmeDJwPYb4dhWlbZQ==}
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
'@heroicons/react@1.0.6':
resolution: {integrity: sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==}
peerDependencies:
@@ -2236,6 +2247,14 @@ packages:
'@types/node':
optional: true
'@isaacs/balanced-match@4.0.1':
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
engines: {node: 20 || >=22}
'@isaacs/brace-expansion@5.0.0':
resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
engines: {node: 20 || >=22}
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -2609,10 +2628,6 @@ packages:
'@orval/zod@7.11.2':
resolution: {integrity: sha512-4MzTg5Wms8/LlM3CbYu80dvCbP88bVlQjnYsBdFXuEv0K2GYkBCAhVOrmXCVrPXE89neV6ABkvWQeuKZQpkdxQ==}
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@playwright/test@1.54.1':
resolution: {integrity: sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==}
engines: {node: '>=18'}
@@ -4048,6 +4063,9 @@ packages:
'@types/urijs@1.19.25':
resolution: {integrity: sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==}
'@types/use-sync-external-store@0.0.6':
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
'@types/uuid@9.0.8':
resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
@@ -4964,6 +4982,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
css-box-model@1.2.1:
resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==}
css.escape@1.5.1:
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
@@ -5634,8 +5655,8 @@ packages:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
foreground-child@3.1.1:
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
foreground-child@3.3.1:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
form-data@4.0.4:
@@ -5764,8 +5785,9 @@ packages:
glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
glob@12.0.0:
resolution: {integrity: sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==}
engines: {node: 20 || >=22}
hasBin: true
glob@7.1.7:
@@ -6273,9 +6295,9 @@ packages:
iterator.prototype@1.1.2:
resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
jackspeak@3.2.3:
resolution: {integrity: sha512-htOzIMPbpLid/Gq9/zaz9SfExABxqRe1sSCdxntlO/aMD6u0issZQiY25n2GKQUtJ02j7z5sfptlAOMpWWOmvw==}
engines: {node: '>=14'}
jackspeak@4.1.1:
resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==}
engines: {node: 20 || >=22}
jest-diff@29.7.0:
resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==}
@@ -6322,8 +6344,8 @@ packages:
js-tokens@9.0.1:
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
js-yaml@4.1.1:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
jsdom@22.1.0:
@@ -6540,15 +6562,15 @@ packages:
lowlight@3.1.0:
resolution: {integrity: sha512-CEbNVoSikAxwDMDPjXlqlFYiZLkDJHwyGu/MfOsJnF3d7f3tds5J3z8s/l9TMXhzfsJCCJEAsD78842mwmg0PQ==}
lru-cache@10.2.2:
resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==}
engines: {node: 14 || >=16.14}
lru-cache@11.2.2:
resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
engines: {node: 20 || >=22}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
lucide-react@0.416.0:
resolution: {integrity: sha512-wPWxTzdss1CTz2aqcNWNlbh4YSnH9neJWP3RaeXepxpLCTW+pmu7WcT/wxJe+Q7Y7DqGOxAqakJv0pIK3431Ag==}
lucide-react@0.552.0:
resolution: {integrity: sha512-g9WCjmfwqbexSnZE+2cl21PCfXOcqnGeWeMTNAOGEfpPbm/ZF4YIq77Z8qWrxbu660EKuLB4nSLggoKnCb+isw==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -6783,6 +6805,10 @@ packages:
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
hasBin: true
minimatch@10.1.1:
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -6794,10 +6820,6 @@ packages:
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
engines: {node: '>=16 || 14 >=14.17'}
minimatch@9.0.4:
resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
engines: {node: '>=16 || 14 >=14.17'}
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -7166,9 +7188,9 @@ packages:
resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==}
engines: {node: '>=0.10.0'}
path-scurry@1.11.1:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
path-scurry@2.0.1:
resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
engines: {node: 20 || >=22}
path-to-regexp@6.3.0:
resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
@@ -7407,6 +7429,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
raf-schd@4.0.3:
resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==}
randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
@@ -7481,6 +7506,18 @@ packages:
react:
optional: true
react-redux@9.2.0:
resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==}
peerDependencies:
'@types/react': ^18.2.25 || ^19
react: ^18.0 || ^19
redux: ^5.0.0
peerDependenciesMeta:
'@types/react':
optional: true
redux:
optional: true
react-refresh@0.17.0:
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
engines: {node: '>=0.10.0'}
@@ -7598,6 +7635,9 @@ packages:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'}
redux@5.0.1:
resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
@@ -8206,6 +8246,9 @@ packages:
tiny-case@1.0.3:
resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==}
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@@ -8558,8 +8601,8 @@ packages:
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
validator@13.12.0:
resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
validator@13.15.23:
resolution: {integrity: sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==}
engines: {node: '>= 0.10'}
vfile-message@4.0.2:
@@ -8581,8 +8624,8 @@ packages:
vite:
optional: true
vite@5.4.20:
resolution: {integrity: sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==}
vite@5.4.21:
resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
@@ -8900,7 +8943,7 @@ snapshots:
dependencies:
'@jsdevtools/ono': 7.1.3
'@types/json-schema': 7.0.15
js-yaml: 4.1.0
js-yaml: 4.1.1
'@apidevtools/openapi-schemas@2.1.0': {}
@@ -8946,7 +8989,7 @@ snapshots:
'@babel/core': 7.26.10
'@babel/generator': 7.28.3
'@babel/parser': 7.28.3
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@babel/traverse': 7.28.3
'@babel/types': 7.28.2
babel-preset-fbjs: 3.4.0(@babel/core@7.26.10)
@@ -10094,7 +10137,7 @@ snapshots:
'@emotion/babel-plugin@11.11.0':
dependencies:
'@babel/helper-module-imports': 7.27.1
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@emotion/hash': 0.9.1
'@emotion/memoize': 0.8.1
'@emotion/serialize': 1.1.4
@@ -10299,7 +10342,7 @@ snapshots:
globals: 13.24.0
ignore: 5.3.2
import-fresh: 3.3.0
js-yaml: 4.1.0
js-yaml: 4.1.1
minimatch: 3.1.2
strip-json-comments: 3.1.1
transitivePeerDependencies:
@@ -10934,6 +10977,18 @@ snapshots:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
'@hello-pangea/dnd@18.0.1(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.28.4
css-box-model: 1.2.1
raf-schd: 4.0.3
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
react-redux: 9.2.0(@types/react@18.2.73)(react@18.2.0)(redux@5.0.1)
redux: 5.0.1
transitivePeerDependencies:
- '@types/react'
'@heroicons/react@1.0.6(react@18.2.0)':
dependencies:
react: 18.2.0
@@ -10971,7 +11026,7 @@ snapshots:
loglevel: 1.9.2
loglevel-plugin-prefix: 0.8.4
minimatch: 6.2.0
validator: 13.12.0
validator: 13.15.23
transitivePeerDependencies:
- encoding
@@ -11104,11 +11159,17 @@ snapshots:
optionalDependencies:
'@types/node': 20.14.8
'@isaacs/balanced-match@4.0.1': {}
'@isaacs/brace-expansion@5.0.0':
dependencies:
'@isaacs/balanced-match': 4.0.1
'@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
string-width-cjs: string-width@4.2.3
strip-ansi: 7.1.0
strip-ansi: 7.1.2
strip-ansi-cjs: strip-ansi@6.0.1
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
@@ -11273,7 +11334,7 @@ snapshots:
'@mui/base@5.0.0-beta.40(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@floating-ui/react-dom': 2.1.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@mui/types': 7.2.14(@types/react@18.2.73)
'@mui/utils': 5.15.14(@types/react@18.2.73)(react@18.2.0)
@@ -11310,7 +11371,7 @@ snapshots:
'@mui/private-theming@5.15.14(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@mui/utils': 5.15.14(@types/react@18.2.73)(react@18.2.0)
prop-types: 15.8.1
react: 18.2.0
@@ -11319,7 +11380,7 @@ snapshots:
'@mui/styled-engine@5.15.14(@emotion/react@11.11.4(@types/react@18.2.73)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.73)(react@18.2.0))(@types/react@18.2.73)(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@emotion/cache': 11.11.0
csstype: 3.1.3
prop-types: 15.8.1
@@ -11350,7 +11411,7 @@ snapshots:
'@mui/utils@5.15.14(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@types/prop-types': 15.7.12
prop-types: 15.8.1
react: 18.2.0
@@ -11556,9 +11617,6 @@ snapshots:
- openapi-types
- supports-color
'@pkgjs/parseargs@0.11.0':
optional: true
'@playwright/test@1.54.1':
dependencies:
playwright: 1.54.1
@@ -11571,7 +11629,7 @@ snapshots:
'@radix-ui/primitive@1.0.1':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/primitive@1.1.0': {}
@@ -11698,7 +11756,7 @@ snapshots:
'@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
react: 18.2.0
optionalDependencies:
'@types/react': 18.2.73
@@ -11723,7 +11781,7 @@ snapshots:
'@radix-ui/react-context@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
react: 18.2.0
optionalDependencies:
'@types/react': 18.2.73
@@ -11748,7 +11806,7 @@ snapshots:
'@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
'@radix-ui/react-context': 1.0.1(@types/react@18.2.73)(react@18.2.0)
@@ -11799,7 +11857,7 @@ snapshots:
'@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -11854,7 +11912,7 @@ snapshots:
'@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
react: 18.2.0
optionalDependencies:
'@types/react': 18.2.73
@@ -11873,7 +11931,7 @@ snapshots:
'@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.73)(react@18.2.0)
@@ -11924,7 +11982,7 @@ snapshots:
'@radix-ui/react-id@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.73)(react@18.2.0)
react: 18.2.0
optionalDependencies:
@@ -12033,7 +12091,7 @@ snapshots:
'@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
@@ -12063,7 +12121,7 @@ snapshots:
'@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.73)(react@18.2.0)
react: 18.2.0
@@ -12094,7 +12152,7 @@ snapshots:
'@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.73)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
@@ -12257,7 +12315,7 @@ snapshots:
'@radix-ui/react-slot@1.0.2(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
react: 18.2.0
optionalDependencies:
@@ -12344,7 +12402,7 @@ snapshots:
'@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
react: 18.2.0
optionalDependencies:
'@types/react': 18.2.73
@@ -12357,7 +12415,7 @@ snapshots:
'@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.73)(react@18.2.0)
react: 18.2.0
optionalDependencies:
@@ -12387,7 +12445,7 @@ snapshots:
'@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.73)(react@18.2.0)
react: 18.2.0
optionalDependencies:
@@ -12402,7 +12460,7 @@ snapshots:
'@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.73)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
react: 18.2.0
optionalDependencies:
'@types/react': 18.2.73
@@ -13041,6 +13099,8 @@ snapshots:
'@types/urijs@1.19.25': {}
'@types/use-sync-external-store@0.0.6': {}
'@types/uuid@9.0.8': {}
'@types/validator@13.11.10': {}
@@ -13299,7 +13359,7 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-react@4.7.0(vite@5.4.20(@types/node@20.14.8)(terser@5.44.0))':
'@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@20.14.8)(terser@5.44.0))':
dependencies:
'@babel/core': 7.28.4
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
@@ -13307,7 +13367,7 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
vite: 5.4.20(@types/node@20.14.8)(terser@5.44.0)
vite: 5.4.21(@types/node@20.14.8)(terser@5.44.0)
transitivePeerDependencies:
- supports-color
@@ -13338,14 +13398,14 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
'@vitest/mocker@3.2.4(msw@2.11.4(@types/node@20.14.8)(typescript@5.8.3))(vite@5.4.20(@types/node@20.14.8)(terser@5.44.0))':
'@vitest/mocker@3.2.4(msw@2.11.4(@types/node@20.14.8)(typescript@5.8.3))(vite@5.4.21(@types/node@20.14.8)(terser@5.44.0))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.19
optionalDependencies:
msw: 2.11.4(@types/node@20.14.8)(typescript@5.8.3)
vite: 5.4.20(@types/node@20.14.8)(terser@5.44.0)
vite: 5.4.21(@types/node@20.14.8)(terser@5.44.0)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -13743,7 +13803,7 @@ snapshots:
babel-plugin-macros@3.1.0:
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
cosmiconfig: 7.1.0
resolve: 1.22.10
@@ -13834,7 +13894,7 @@ snapshots:
'@babel/preset-env': 7.24.7(@babel/core@7.26.10)
'@babel/preset-react': 7.24.6(@babel/core@7.26.10)
'@babel/preset-typescript': 7.24.7(@babel/core@7.26.10)
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
babel-plugin-macros: 3.1.0
babel-plugin-transform-react-remove-prop-types: 0.4.24
transitivePeerDependencies:
@@ -14148,7 +14208,7 @@ snapshots:
cosmiconfig@8.3.6(typescript@5.8.3):
dependencies:
import-fresh: 3.3.1
js-yaml: 4.1.0
js-yaml: 4.1.1
parse-json: 5.2.0
path-type: 4.0.0
optionalDependencies:
@@ -14158,7 +14218,7 @@ snapshots:
dependencies:
env-paths: 2.2.1
import-fresh: 3.3.1
js-yaml: 4.1.0
js-yaml: 4.1.1
parse-json: 5.2.0
optionalDependencies:
typescript: 5.8.3
@@ -14183,6 +14243,10 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
css-box-model@1.2.1:
dependencies:
tiny-invariant: 1.3.3
css.escape@1.5.1: {}
cssesc@3.0.0: {}
@@ -14354,7 +14418,7 @@ snapshots:
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
csstype: 3.1.3
domexception@4.0.0:
@@ -15008,7 +15072,7 @@ snapshots:
imurmurhash: 0.1.4
is-glob: 4.0.3
is-path-inside: 3.0.3
js-yaml: 4.1.0
js-yaml: 4.1.1
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
@@ -15187,7 +15251,7 @@ snapshots:
dependencies:
is-callable: 1.2.7
foreground-child@3.1.1:
foreground-child@3.3.1:
dependencies:
cross-spawn: 7.0.6
signal-exit: 4.1.0
@@ -15328,14 +15392,14 @@ snapshots:
glob-to-regexp@0.4.1: {}
glob@10.4.5:
glob@12.0.0:
dependencies:
foreground-child: 3.1.1
jackspeak: 3.2.3
minimatch: 9.0.4
foreground-child: 3.3.1
jackspeak: 4.1.1
minimatch: 10.1.1
minipass: 7.1.2
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
path-scurry: 2.0.1
glob@7.1.7:
dependencies:
@@ -15858,11 +15922,9 @@ snapshots:
reflect.getprototypeof: 1.0.8
set-function-name: 2.0.2
jackspeak@3.2.3:
jackspeak@4.1.1:
dependencies:
'@isaacs/cliui': 8.0.2
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
jest-diff@29.7.0:
dependencies:
@@ -15919,7 +15981,7 @@ snapshots:
js-tokens@9.0.1: {}
js-yaml@4.1.0:
js-yaml@4.1.1:
dependencies:
argparse: 2.0.1
@@ -16156,13 +16218,13 @@ snapshots:
devlop: 1.1.0
highlight.js: 11.9.0
lru-cache@10.2.2: {}
lru-cache@11.2.2: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
lucide-react@0.416.0(react@18.2.0):
lucide-react@0.552.0(react@18.2.0):
dependencies:
react: 18.2.0
@@ -16586,6 +16648,10 @@ snapshots:
mini-svg-data-uri@1.4.4: {}
minimatch@10.1.1:
dependencies:
'@isaacs/brace-expansion': 5.0.0
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -16598,10 +16664,6 @@ snapshots:
dependencies:
brace-expansion: 2.0.2
minimatch@9.0.4:
dependencies:
brace-expansion: 2.0.2
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.2
@@ -17040,9 +17102,9 @@ snapshots:
dependencies:
path-root-regex: 0.1.2
path-scurry@1.11.1:
path-scurry@2.0.1:
dependencies:
lru-cache: 10.2.2
lru-cache: 11.2.2
minipass: 7.1.2
path-to-regexp@6.3.0: {}
@@ -17202,6 +17264,8 @@ snapshots:
queue-microtask@1.2.3: {}
raf-schd@4.0.3: {}
randombytes@2.1.0:
dependencies:
safe-buffer: 5.2.1
@@ -17277,6 +17341,15 @@ snapshots:
optionalDependencies:
react: 18.2.0
react-redux@9.2.0(@types/react@18.2.73)(react@18.2.0)(redux@5.0.1):
dependencies:
'@types/use-sync-external-store': 0.0.6
react: 18.2.0
use-sync-external-store: 1.4.0(react@18.2.0)
optionalDependencies:
'@types/react': 18.2.73
redux: 5.0.1
react-refresh@0.17.0: {}
react-remove-scroll-bar@2.3.8(@types/react@18.2.73)(react@18.2.0):
@@ -17339,7 +17412,7 @@ snapshots:
react-transition-group@4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
@@ -17395,6 +17468,8 @@ snapshots:
indent-string: 4.0.0
strip-indent: 3.0.0
redux@5.0.1: {}
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
@@ -17429,7 +17504,7 @@ snapshots:
regenerator-transform@0.15.2:
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
regexp.prototype.flags@1.5.3:
dependencies:
@@ -17477,7 +17552,7 @@ snapshots:
relay-runtime@12.0.0(encoding@0.1.13):
dependencies:
'@babel/runtime': 7.26.10
'@babel/runtime': 7.28.4
fbjs: 3.0.5(encoding@0.1.13)
invariant: 2.2.4
transitivePeerDependencies:
@@ -17875,7 +17950,7 @@ snapshots:
dependencies:
eastasianwidth: 0.2.0
emoji-regex: 9.2.2
strip-ansi: 7.1.0
strip-ansi: 7.1.2
string-width@7.2.0:
dependencies:
@@ -17994,7 +18069,7 @@ snapshots:
dependencies:
'@jridgewell/gen-mapping': 0.3.13
commander: 4.1.1
glob: 10.4.5
glob: 12.0.0
lines-and-columns: 1.2.4
mz: 2.7.0
pirates: 4.0.6
@@ -18096,7 +18171,7 @@ snapshots:
test-exclude@7.0.1:
dependencies:
'@istanbuljs/schema': 0.1.3
glob: 10.4.5
glob: 12.0.0
minimatch: 9.0.5
text-table@0.2.0: {}
@@ -18122,6 +18197,8 @@ snapshots:
tiny-case@1.0.3: {}
tiny-invariant@1.3.3: {}
tinybench@2.9.0: {}
tinyexec@0.3.2: {}
@@ -18466,7 +18543,7 @@ snapshots:
v8-compile-cache-lib@3.0.1: {}
validator@13.12.0: {}
validator@13.15.23: {}
vfile-message@4.0.2:
dependencies:
@@ -18484,7 +18561,7 @@ snapshots:
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 5.4.20(@types/node@20.14.8)(terser@5.44.0)
vite: 5.4.21(@types/node@20.14.8)(terser@5.44.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -18496,18 +18573,18 @@ snapshots:
- supports-color
- terser
vite-tsconfig-paths@4.3.2(typescript@5.8.3)(vite@5.4.20(@types/node@20.14.8)(terser@5.44.0)):
vite-tsconfig-paths@4.3.2(typescript@5.8.3)(vite@5.4.21(@types/node@20.14.8)(terser@5.44.0)):
dependencies:
debug: 4.4.1
globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.8.3)
optionalDependencies:
vite: 5.4.20(@types/node@20.14.8)(terser@5.44.0)
vite: 5.4.21(@types/node@20.14.8)(terser@5.44.0)
transitivePeerDependencies:
- supports-color
- typescript
vite@5.4.20(@types/node@20.14.8)(terser@5.44.0):
vite@5.4.21(@types/node@20.14.8)(terser@5.44.0):
dependencies:
esbuild: 0.25.10
postcss: 8.5.3
@@ -18521,7 +18598,7 @@ snapshots:
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(msw@2.11.4(@types/node@20.14.8)(typescript@5.8.3))(vite@5.4.20(@types/node@20.14.8)(terser@5.44.0))
'@vitest/mocker': 3.2.4(msw@2.11.4(@types/node@20.14.8)(typescript@5.8.3))(vite@5.4.21(@types/node@20.14.8)(terser@5.44.0))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -18539,7 +18616,7 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 5.4.20(@types/node@20.14.8)(terser@5.44.0)
vite: 5.4.21(@types/node@20.14.8)(terser@5.44.0)
vite-node: 3.2.4(@types/node@20.14.8)(terser@5.44.0)
why-is-node-running: 2.3.0
optionalDependencies:
@@ -18720,9 +18797,9 @@ snapshots:
wrap-ansi@8.1.0:
dependencies:
ansi-styles: 6.2.1
ansi-styles: 6.2.3
string-width: 5.1.2
strip-ansi: 7.1.0
strip-ansi: 7.1.2
wrap-ansi@9.0.0:
dependencies:

View File

@@ -166,6 +166,12 @@ rec {
'';
};
packageWithDisabledCSP = package.overrideAttrs (oldAttrs: {
configurePhase = oldAttrs.configurePhase + ''
export CSP_MODE=disabled
'';
});
dockerImage = pkgs.runCommand "image-as-dir" { } ''
${(nix2containerPkgs.nix2container.buildImage {
inherit name created;
@@ -175,7 +181,7 @@ rec {
copyToRoot = pkgs.buildEnv {
name = "image";
paths = [
package
packageWithDisabledCSP
(pkgs.writeTextFile {
name = "tmp-file";
text = ''

View File

@@ -64,7 +64,6 @@ declare module 'react-table' {
export interface Cell<
D extends Record<string, unknown> = Record<string, unknown>,
V = any,
> extends UseGroupByCellProps<D>,
UseRowStateCellProps<D> {}

View File

@@ -0,0 +1,41 @@
import { cn } from '@/lib/utils';
import {
DragDropContext,
Droppable,
type DragDropContextProps,
type DroppableProps,
} from '@hello-pangea/dnd';
import type { PropsWithChildren } from 'react';
type DragAndDropListProps = Omit<
DroppableProps & DragDropContextProps,
'children'
> & {
wrapperClassName?: string;
};
function DragAndDropList({
droppableId,
onDragEnd,
children,
wrapperClassName,
}: PropsWithChildren<DragAndDropListProps>) {
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId={droppableId}>
{(provided) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
className={cn(wrapperClassName)}
>
{children}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
export default DragAndDropList;

View File

@@ -0,0 +1,30 @@
import { cn } from '@/lib/utils';
import { Draggable, type DraggableProps } from '@hello-pangea/dnd';
import type { PropsWithChildren } from 'react';
export type DraggableItemProps = PropsWithChildren<
Omit<DraggableProps, 'children'> & { className?: string }
>;
function DraggableItem({
children,
className,
...draggableProps
}: DraggableItemProps) {
return (
<Draggable {...draggableProps}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={cn(className)}
>
{children}
</div>
)}
</Draggable>
);
}
export default DraggableItem;

View File

@@ -0,0 +1,3 @@
export { default as DragAndDropList } from './DragAndDropList';
export * from './DraggableItem';
export { default as DraggableItem } from './DraggableItem';

View File

@@ -123,7 +123,7 @@ const TimePickerInput = React.forwardRef<
id={id || picker}
name={name || picker}
className={cn(
'w-[48px] text-center font-mono text-base tabular-nums focus:bg-accent focus:text-accent-foreground [&::-webkit-inner-spin-button]:appearance-none',
'w-[48px] text-center font-mono text-base tabular-nums focus:bg-accent-background focus:text-accent-foreground [&::-webkit-inner-spin-button]:appearance-none',
className,
)}
value={value || calculatedValue}

View File

@@ -1,26 +1,25 @@
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import type { BoxProps } from '@/components/ui/v2/Box';
import { Box } from '@/components/ui/v2/Box';
import { twMerge } from 'tailwind-merge';
import { Spinner } from '@/components/ui/v3/spinner';
import { cn } from '@/lib/utils';
export interface FormActivityIndicatorProps extends BoxProps {}
export interface FormActivityIndicatorProps {
className?: string;
}
export default function FormActivityIndicator({
className,
...props
}: FormActivityIndicatorProps) {
return (
<Box
<div
{...props}
className={twMerge(
'grid items-center justify-center px-6 py-4',
className={cn(
'box grid h-full items-center justify-center px-6 py-4',
className,
)}
>
<ActivityIndicator
circularProgressProps={{ className: 'w-5 h-5' }}
label="Loading form..."
/>
</Box>
<Spinner className="h-5 w-5" wrapperClassName="flex-row gap-1">
Loading form...
</Spinner>
</div>
);
}

View File

@@ -1,12 +1,27 @@
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/v3/form';
import { Input } from '@/components/ui/v3/input';
import type { Control, FieldPath, FieldValues } from 'react-hook-form';
import { cn, isNotEmptyValue } from '@/lib/utils';
import {
type ChangeEvent,
type ForwardedRef,
forwardRef,
type ReactNode,
} from 'react';
import type {
Control,
ControllerRenderProps,
FieldPath,
FieldValues,
PathValue,
} from 'react-hook-form';
import { mergeRefs } from 'react-merge-refs';
const inputClasses =
'!bg-transparent aria-[invalid=true]:border-red-500 aria-[invalid=true]:focus:border-red-500 aria-[invalid=true]:focus:ring-red-500';
@@ -17,43 +32,116 @@ interface FormInputProps<
> {
control: Control<TFieldValues>;
name: TName;
label: string;
label: ReactNode;
placeholder?: string;
className?: string;
type?: string;
inline?: boolean;
helperText?: string | null;
transformValue?: (
value: PathValue<TFieldValues, TName>,
) => PathValue<TFieldValues, TName>;
}
function FormInput<
function InnerFormInput<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
control,
name,
label,
placeholder,
className = '',
type = 'text',
}: FormInputProps<TFieldValues, TName>) {
>(
{
control,
name,
label,
placeholder,
className = '',
type = 'text',
inline,
helperText,
transformValue,
}: FormInputProps<TFieldValues, TName>,
ref: ForwardedRef<HTMLInputElement>,
) {
function getOnChangeHandlerAndValue(
field: ControllerRenderProps<TFieldValues, TName>,
): [
PathValue<TFieldValues, TName>,
(e: ChangeEvent<HTMLInputElement>) => void,
] {
const { onChange, value } = field;
function handleOnChange(event: ChangeEvent<HTMLInputElement>) {
let transformedValue = event.target.value;
if (isNotEmptyValue(transformValue)) {
transformedValue = transformValue(
event.target.value as PathValue<TFieldValues, TName>,
);
}
onChange(transformedValue);
}
const transformedValue = isNotEmptyValue(transformValue)
? transformValue(value)
: value;
return [transformedValue, handleOnChange];
}
return (
<FormField
control={control}
name={name}
render={({ field }) => (
<FormItem>
<FormLabel>{label}</FormLabel>
<FormControl>
<Input
type={type}
placeholder={placeholder || label}
{...field}
className={`${inputClasses} ${className}`}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
render={({ field }) => {
const { onChange, value, ...fieldProps } = field;
const [tValue, handleOnChange] = getOnChangeHandlerAndValue(field);
return (
<FormItem
className={cn({ 'flex w-full items-center gap-4 py-3': inline })}
>
<FormLabel
className={cn({
'mt-2 w-52 max-w-52 flex-shrink-0 self-start': inline,
})}
>
{label}
</FormLabel>
<div
className={cn({
'flex w-[calc(100%-13.5rem)] max-w-[calc(100%-13.5rem)] flex-col gap-2':
inline,
})}
>
<FormControl>
<Input
type={type}
placeholder={placeholder}
onChange={handleOnChange}
value={tValue}
{...fieldProps}
ref={mergeRefs([field.ref, ref])}
className={cn(inputClasses, className)}
wrapperClassName={cn({ 'w-full': !inline })}
/>
</FormControl>
{!!helperText && (
<FormDescription className="break-all px-[1px]">
{helperText}
</FormDescription>
)}
<FormMessage />
</div>
</FormItem>
);
}}
/>
);
}
const FormInput = forwardRef(InnerFormInput) as <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
props: FormInputProps<TFieldValues, TName> & {
ref?: ForwardedRef<HTMLInputElement>;
},
) => ReturnType<typeof InnerFormInput>;
export default FormInput;

View File

@@ -0,0 +1,125 @@
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/v3/form';
import {
Select,
SelectContent,
SelectTrigger,
SelectValue,
} from '@/components/ui/v3/select';
import { cn, isNotEmptyValue } from '@/lib/utils';
import type { PropsWithChildren, ReactNode } from 'react';
import type {
Control,
ControllerRenderProps,
FieldPath,
FieldValues,
PathValue,
} from 'react-hook-form';
interface FormSelectProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> {
control: Control<TFieldValues>;
name: TName;
label: ReactNode;
placeholder?: string;
className?: string;
inline?: boolean;
helperText?: string | null;
transformValue?: (
value: PathValue<TFieldValues, TName>,
) => PathValue<TFieldValues, TName>;
}
function FormSelect<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
control,
name,
label,
placeholder,
className = '',
inline,
helperText,
children,
transformValue,
}: PropsWithChildren<FormSelectProps<TFieldValues, TName>>) {
function getOnChangeHandlerAndValue(
field: ControllerRenderProps<TFieldValues, TName>,
): [string, (v: string) => void] {
const { onChange, value } = field;
function handleOnChange(newValue: string) {
const transformedNewValue = isNotEmptyValue(transformValue)
? transformValue(newValue as PathValue<TFieldValues, TName>)
: newValue;
onChange(transformedNewValue);
}
const transformedValue: string = isNotEmptyValue(transformValue)
? transformValue(value as PathValue<TFieldValues, TName>)
: value;
return [transformedValue, handleOnChange];
}
return (
<FormField
control={control}
name={name}
render={({ field }) => {
const { onChange, value, ...selectProps } = field;
const [tValue, handleOnChange] = getOnChangeHandlerAndValue(field);
return (
<FormItem
className={cn({ 'flex w-full items-center gap-4 py-3': inline })}
>
<FormLabel
className={cn({
'w-52 max-w-52 flex-shrink-0': inline,
'mt-2 self-start': inline && !!helperText,
})}
>
{label}
</FormLabel>
<div
className={cn({
'flex w-[calc(100%-13.5rem)] max-w-[calc(100%-13.5rem)] flex-col gap-2':
inline,
})}
>
<Select
onValueChange={handleOnChange}
value={tValue}
{...selectProps}
>
<FormControl>
<SelectTrigger className={className}>
<SelectValue placeholder={placeholder} />
</SelectTrigger>
</FormControl>
<SelectContent>{children}</SelectContent>
</Select>
{!!helperText && (
<FormDescription className="break-all px-[1px]">
{helperText}
</FormDescription>
)}
<FormMessage />
</div>
</FormItem>
);
}}
/>
);
}
export default FormSelect;

View File

@@ -0,0 +1 @@
export { default as FormSelect } from './FormSelect';

View File

@@ -0,0 +1,97 @@
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/v3/form';
import { Textarea } from '@/components/ui/v3/textarea';
import { cn } from '@/lib/utils';
import { forwardRef, type ForwardedRef, type ReactNode } from 'react';
import type { Control, FieldPath, FieldValues } from 'react-hook-form';
import { mergeRefs } from 'react-merge-refs';
const inputClasses =
'!bg-transparent aria-[invalid=true]:border-red-500 aria-[invalid=true]:focus:border-red-500 aria-[invalid=true]:focus:ring-red-500';
interface FormTextareaProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> {
control: Control<TFieldValues>;
name: TName;
label: ReactNode;
placeholder?: string;
className?: string;
inline?: boolean;
helperText?: string | null;
}
function InnerFormTextarea<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
{
control,
name,
label,
placeholder,
className = '',
inline,
helperText,
}: FormTextareaProps<TFieldValues, TName>,
ref: ForwardedRef<HTMLTextAreaElement>,
) {
return (
<FormField
control={control}
name={name}
render={({ field }) => (
<FormItem
className={cn({ 'flex w-full items-center gap-4 py-3': inline })}
>
<FormLabel
className={cn({
'mt-2 w-52 max-w-52 flex-shrink-0 self-start': inline,
})}
>
{label}
</FormLabel>
<div
className={cn({
'flex w-[calc(100%-13.5rem)] max-w-[calc(100%-13.5rem)] flex-col gap-2':
inline,
})}
>
<FormControl>
<Textarea
placeholder={placeholder}
{...field}
ref={mergeRefs([field.ref, ref])}
className={cn(inputClasses, className)}
/>
</FormControl>
{!!helperText && (
<FormDescription className="break-all px-[1px]">
{helperText}
</FormDescription>
)}
<FormMessage />
</div>
</FormItem>
)}
/>
);
}
const FormTextarea = forwardRef(InnerFormTextarea) as <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
props: FormTextareaProps<TFieldValues, TName> & {
ref: ForwardedRef<HTMLTextAreaElement>;
},
) => ReturnType<typeof InnerFormTextarea>;
export default FormTextarea;

View File

@@ -0,0 +1 @@
export { default as FormTextarea } from './FormTextarea';

View File

@@ -127,14 +127,17 @@ export default function AuthenticatedLayout({
className="relative flex h-full flex-row overflow-hidden"
ref={setMainNavContainer}
>
{mainNavPinned && isMdOrLarger && <PinnedMainNav />}
{withMainNav && mainNavPinned && isMdOrLarger && <PinnedMainNav />}
<div
className={cn('relative flex h-full w-full flex-row bg-accent', {
'overflow-x-auto': mainNavPinned && isMdOrLarger && withMainNav,
})}
className={cn(
'bg-accent-background relative flex h-full w-full flex-row',
{
'overflow-x-auto': mainNavPinned && isMdOrLarger && withMainNav,
},
)}
>
{(!mainNavPinned || !isMdOrLarger) && (
{withMainNav && (!mainNavPinned || !isMdOrLarger) && (
<div className="flex h-full w-6 justify-center">
<MainNav container={mainNavContainer} />
</div>

View File

@@ -482,9 +482,9 @@ export default function NavTree() {
}
}}
className={cn(
'flex h-8 w-full flex-row justify-start gap-1 bg-background px-1 text-foreground hover:bg-accent dark:hover:bg-muted',
'flex h-8 w-full flex-row justify-start gap-1 bg-background px-1 text-foreground hover:bg-accent',
{
'bg-[#ebf3ff] hover:bg-[#ebf3ff] dark:bg-muted':
'bg-[#ebf3ff] hover:bg-accent dark:bg-muted':
context.isFocused,
},
item.data.disabled && 'pointer-events-none opacity-50',

View File

@@ -1,9 +1,11 @@
import { Box } from '@/components/ui/v2/Box';
import type { TextProps } from '@/components/ui/v2/Text';
import { Text } from '@/components/ui/v2/Text';
import type { DetailedHTMLProps, ForwardedRef, HTMLProps } from 'react';
import { cn } from '@/lib/utils';
import type {
DetailedHTMLProps,
ForwardedRef,
HTMLAttributes,
HTMLProps,
} from 'react';
import { forwardRef } from 'react';
import { twMerge } from 'tailwind-merge';
export type ReadOnlyToggleProps = Omit<
DetailedHTMLProps<HTMLProps<HTMLSpanElement>, HTMLSpanElement>,
@@ -24,7 +26,7 @@ export type ReadOnlyToggleProps = Omit<
/**
* Props passed to the label.
*/
label?: TextProps;
label?: HTMLAttributes<HTMLSpanElement>;
};
};
@@ -36,58 +38,44 @@ function ReadOnlyToggle(
<span
{...props}
{...(slotProps?.root || {})}
className={twMerge(
className={cn(
'inline-grid h-full w-full grid-flow-col items-center justify-start gap-1.5',
slotProps?.root?.className,
className,
)}
ref={ref}
>
<Box
component="span"
sx={{
backgroundColor: (theme) => {
if (checked) {
return theme.palette.mode === 'dark' ? 'grey.400' : 'grey.700';
}
return 'transparent';
<span
className={cn(
'box-border inline-grid h-3 w-5 items-center rounded-full border-1 border-primary-text bg-transparent px-0.5',
checked && 'justify-end',
{
'border-transparent bg-primary-text px-0.5 dark:bg-[#363a43]':
checked,
},
borderColor: checked ? 'transparent' : 'grey.700',
}}
className={twMerge(
'box-border inline-grid h-3 w-5 items-center rounded-full border-1 px-0.5',
checked === true && 'justify-end',
)}
>
<Box
component="span"
sx={{
backgroundColor: (theme) => {
if (checked) {
return theme.palette.mode === 'dark' ? 'grey.700' : 'grey.200';
}
return 'grey.700';
<span
className={cn(
'inline-block h-2 w-2 rounded-full border-primary-text bg-primary-text',
{
'border-transparent bg-data-cell-bg px-0.5 dark:bg-[#f4f7f9]':
checked,
'my-px h-px justify-self-center': checked === null,
},
}}
className={twMerge(
'inline-block h-2 w-2 rounded-full',
checked === null && 'my-px h-px justify-self-center',
)}
/>
</Box>
</span>
<Text
<span
{...(slotProps?.label || {})}
component="span"
className={twMerge(
className={cn(
'truncate !text-xs font-normal',
slotProps?.label?.className,
)}
>
{String(checked)}
</Text>
</span>
</span>
);
}

View File

@@ -1,32 +0,0 @@
import type { IconProps } from '@/components/ui/v2/icons';
import { SvgIcon } from '@/components/ui/v2/icons/SvgIcon';
function KeyIcon(props: IconProps) {
return (
<SvgIcon
width="16"
height="16"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
aria-label="Key"
{...props}
>
<path
d="M5.823 7.677a4.496 4.496 0 1 1 2.5 2.5L7.5 11H6v1.5H4.5V14H2v-2.5l3.823-3.823Z"
stroke="currentColor"
fill="none"
strokeWidth="1.5"
strokeLinejoin="round"
/>
<path
d="M10.5 7a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
fill="currentColor"
/>
</SvgIcon>
);
}
KeyIcon.displayName = 'NhostKeyIcon';
export default KeyIcon;

View File

@@ -1 +0,0 @@
export { default as KeyIcon } from './KeyIcon';

View File

@@ -11,7 +11,7 @@ const badgeVariants = cva(
default:
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80 dark:text-white',
secondary:
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
'border-transparent bg-card text-secondary-foreground hover:bg-secondary/80',
destructive:
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
outline: 'text-foreground',

View File

@@ -0,0 +1,83 @@
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
import { Separator } from "@/components/ui/v3/separator"
const buttonGroupVariants = cva(
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
{
variants: {
orientation: {
horizontal:
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
vertical:
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
},
},
defaultVariants: {
orientation: "horizontal",
},
}
)
function ButtonGroup({
className,
orientation,
...props
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
return (
<div
role="group"
data-slot="button-group"
data-orientation={orientation}
className={cn(buttonGroupVariants({ orientation }), className)}
{...props}
/>
)
}
function ButtonGroupText({
className,
asChild = false,
...props
}: React.ComponentProps<"div"> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : "div"
return (
<Comp
className={cn(
"bg-muted shadow-xs flex items-center gap-2 rounded-md border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
className
)}
{...props}
/>
)
}
function ButtonGroupSeparator({
className,
orientation = "vertical",
...props
}: React.ComponentProps<typeof Separator>) {
return (
<Separator
data-slot="button-group-separator"
orientation={orientation}
className={cn(
"bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
className
)}
{...props}
/>
)
}
export {
ButtonGroup,
ButtonGroupSeparator,
ButtonGroupText,
buttonGroupVariants,
}

View File

@@ -16,8 +16,8 @@ const buttonVariants = cva(
outline:
'border bg-background hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
'bg-secondary text-secondary-foreground hover:bg-secondary-hover',
ghost: 'hover:bg-accent text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {

View File

@@ -11,15 +11,15 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root
ref={ref}
className={cn(
'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:border-disabled disabled:bg-disabled disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn('flex items-center justify-center text-current')}
className={cn('flex items-center justify-center text-white')}
>
<Check className="h-4 w-4" />
<Check width={16} height={16} strokeWidth={3} />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));

View File

@@ -31,6 +31,7 @@ interface DialogContentProps
extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
disableOutsideClick?: boolean;
hideCloseButton?: boolean;
closeButtonClassName?: string;
}
const DialogContent = React.forwardRef<
@@ -38,7 +39,14 @@ const DialogContent = React.forwardRef<
DialogContentProps
>(
(
{ className, children, disableOutsideClick, hideCloseButton, ...props },
{
className,
children,
disableOutsideClick,
hideCloseButton,
closeButtonClassName,
...props
},
ref,
) => (
<DialogPortal>
@@ -58,7 +66,12 @@ const DialogContent = React.forwardRef<
>
{children}
{!hideCloseButton && (
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<DialogPrimitive.Close
className={cn(
'absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent-background data-[state=open]:text-muted-foreground',
closeButtonClassName,
)}
>
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>

View File

@@ -5,11 +5,11 @@ export function InlineCode({
children,
className,
...props
}: PropsWithChildren<{ className?: string }>) {
}: PropsWithChildren<React.HTMLAttributes<HTMLElement>>) {
return (
<code
className={cn(
'relative rounded bg-[#eaedf0] px-1 font-mono text-[11px] dark:bg-[#2f363d]',
'relative max-w-xs truncate rounded bg-[#eaedf0] px-1 font-mono text-[11px] dark:bg-[#2f363d]',
className,
)}
{...props}

View File

@@ -5,12 +5,13 @@ import { cn } from '@/lib/utils';
export interface InputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
prefix?: React.ReactNode;
wrapperClassName?: string;
}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, prefix, ...props }, ref) => {
({ className, type, prefix, wrapperClassName, ...props }, ref) => {
return (
<div className="relative flex items-center">
<div className={cn('relative flex items-center', wrapperClassName)}>
{prefix && (
<span className="pointer-events-none absolute left-3 flex items-center text-muted-foreground">
{prefix}
@@ -19,7 +20,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-accent',
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-accent-background',
{ 'pl-6': prefix },
className,
)}

View File

@@ -54,6 +54,7 @@ interface SheetContentProps
VariantProps<typeof sheetVariants> {
container?: HTMLElement | null;
hideCloseButton?: boolean;
showOverlay?: boolean;
}
const SheetContent = React.forwardRef<
@@ -67,11 +68,13 @@ const SheetContent = React.forwardRef<
container = null,
hideCloseButton,
children,
showOverlay = false,
...props
},
ref,
) => (
<SheetPortal container={container}>
{showOverlay && <SheetOverlay />}
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}

View File

@@ -33,6 +33,7 @@ interface SpinnerContentProps
VariantProps<typeof loaderVariants> {
className?: string;
children?: React.ReactNode;
wrapperClassName?: string;
}
export function Spinner({
@@ -40,10 +41,12 @@ export function Spinner({
show,
children,
className,
wrapperClassName,
}: SpinnerContentProps) {
return (
<span className={spinnerVariants({ show })}>
<span className={cn(spinnerVariants({ show }), wrapperClassName)}>
<Loader2
role="progressbar"
className={cn(
loaderVariants({ size }),
className,

View File

@@ -9,7 +9,7 @@ const Textarea = React.forwardRef<
return (
<textarea
className={cn(
'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
className,
)}
ref={ref}

View File

@@ -23,7 +23,7 @@ export default function SocialProvidersSettings() {
if (typeof window !== 'undefined') {
return nhost.auth.signInProviderURL('github', {
connect: token,
redirectTo: `${window.location.origin}/account`,
redirectTo: `${window.location.origin}/account?signinProvider=github`,
});
}
return '';

View File

@@ -3,18 +3,21 @@ import {
useGithubAuthentication,
type UseGithubAuthenticationHookProps,
} from '@/features/auth/AuthProviders/Github/hooks/useGithubAuthentication';
import { cn } from '@/lib/utils';
import { SiGithub } from '@icons-pack/react-simple-icons';
interface Props extends UseGithubAuthenticationHookProps {
buttonText?: string;
withAnonId?: boolean;
redirectTo?: string;
className?: string;
}
function GithubAuthButton({
buttonText = 'Continue with GitHub',
withAnonId = false,
redirectTo,
className,
}: Props) {
const { mutate: signInWithGithub, isLoading } = useGithubAuthentication({
withAnonId,
@@ -22,7 +25,10 @@ function GithubAuthButton({
});
return (
<Button
className="gap-2 !bg-white text-sm+ !text-black hover:ring-2 hover:ring-white hover:ring-opacity-50 disabled:!text-black disabled:!text-opacity-60"
className={cn(
'gap-2 !bg-white text-sm+ !text-black hover:ring-2 hover:ring-white hover:ring-opacity-50 disabled:!text-black disabled:!text-opacity-60',
className,
)}
disabled={isLoading}
loading={isLoading}
onClick={() => signInWithGithub()}

View File

@@ -30,8 +30,8 @@ function useGithubAuthentication({
};
}
const redirectURl = nhost.auth.signInProviderURL('github', options);
window.location.href = redirectURl;
const redirectURL = nhost.auth.signInProviderURL('github', options);
window.location.href = redirectURL;
},
{
onError: () => {

View File

@@ -24,12 +24,14 @@ function SignInWithEmailAndPassword({ onSubmit, isLoading }: Props) {
label="Email"
name="email"
type="email"
placeholder="Email"
/>
<FormInput
control={form.control}
label="Password"
name="password"
type="password"
placeholder="Password"
/>
<NextLink
href="/password/new"

View File

@@ -2,7 +2,7 @@ import { GithubAuthButton } from '@/features/auth/AuthProviders/Github/component
import { useHostName } from '@/features/orgs/projects/common/hooks/useHostName';
function SignInWithGithub() {
const redirectTo = useHostName();
const redirectTo = `${useHostName()}?signinProvider=github`;
return (
<GithubAuthButton
redirectTo={redirectTo}

View File

@@ -22,18 +22,25 @@ function SignUpWithEmailAndPasswordForm() {
onSubmit={form.handleSubmit(onSignUpWithPassword)}
className="grid grid-flow-row gap-4 bg-transparent"
>
<FormInput control={form.control} label="Name" name="displayName" />
<FormInput
control={form.control}
label="Name"
name="displayName"
placeholder="Name"
/>
<FormInput
control={form.control}
label="Email"
name="email"
type="email"
placeholder="Email"
/>
<FormInput
control={form.control}
label="Password"
name="password"
type="password"
placeholder="Password"
/>
<FormField
control={form.control}

View File

@@ -22,12 +22,18 @@ function SignUpWithSecurityKeyForm() {
onSubmit={form.handleSubmit(onSignUpWithSecurityKey)}
className="grid grid-flow-row gap-4 bg-transparent"
>
<FormInput control={form.control} label="Name" name="displayName" />
<FormInput
control={form.control}
label="Name"
name="displayName"
placeholder="Name"
/>
<FormInput
control={form.control}
label="Email"
name="email"
type="email"
placeholder="Email"
/>
<FormField
control={form.control}

View File

@@ -1,8 +1,11 @@
import { GithubAuthButton } from '@/features/auth/AuthProviders/Github/components/GithubAuthButton';
import { useHostName } from '@/features/orgs/projects/common/hooks/useHostName';
function SignUpWithGithub() {
const redirectTo = `${useHostName()}?signinProvider=github`;
return (
<GithubAuthButton
redirectTo={redirectTo}
buttonText="Sign Up with GitHub"
errorText="An error occurred while trying to sign up using GitHub. Please try again."
/>

View File

@@ -52,7 +52,7 @@ export default function BillingDetails() {
<AccordionContent className="border-t-1 pb-0">
<div className="rounded-md">
<Table>
<TableHeader className="w-full bg-accent">
<TableHeader className="w-full bg-accent-background">
<TableRow>
<TableHead colSpan={3} className="w-full rounded-tl-md">
Item
@@ -72,7 +72,7 @@ export default function BillingDetails() {
</TableRow>
))}
</TableBody>
<TableFooter className="bg-accent">
<TableFooter className="bg-accent-background">
<TableRow>
<TableCell colSpan={3} className="rounded-bl-md">
Total

View File

@@ -62,7 +62,7 @@ export default function ProjectsGrid({ projects }: ProjectGridProps) {
);
return (
<div className="mx-auto h-full overflow-auto bg-accent">
<div className="mx-auto h-full overflow-auto bg-accent-background">
<div className="flex w-full flex-shrink-0 flex-row items-center justify-between gap-2 border-b bg-background p-2">
<Input
placeholder="Find Project"
@@ -85,7 +85,6 @@ export default function ProjectsGrid({ projects }: ProjectGridProps) {
</Link>
</Button>
</div>
<div className="grid grid-cols-1 gap-4 p-4 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
{filteredProjects.map((project) => (
<ProjectCard key={project.id} project={project} />

View File

@@ -176,7 +176,7 @@ export default function AppleProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-apple"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-apple"
docsTitle="how to sign in users with Apple"
icon={
theme.palette.mode === 'dark'

View File

@@ -141,7 +141,7 @@ export default function DiscordProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-discord"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-discord"
docsTitle="how to sign in users with Discord"
icon="/assets/brands/discord.svg"
switchId="enabled"

View File

@@ -142,7 +142,7 @@ export default function FacebookProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-facebook"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-facebook"
docsTitle="how to sign in users with Facebook"
icon="/assets/brands/facebook.svg"
switchId="enabled"

View File

@@ -144,7 +144,7 @@ export default function GitHubProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-github"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-github"
docsTitle="how to sign in users with GitHub"
icon={
theme.palette.mode === 'dark'

View File

@@ -162,7 +162,7 @@ export default function GoogleProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-google"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-google"
docsTitle="how to sign in users with Google"
icon="/assets/brands/google.svg"
switchId="enabled"

View File

@@ -142,7 +142,7 @@ export default function LinkedInProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-linkedin"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-linkedin"
docsTitle="how to sign in users with LinkedIn"
icon="/assets/brands/linkedin.svg"
switchId="enabled"

View File

@@ -142,7 +142,7 @@ export default function SpotifyProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-spotify"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-spotify"
docsTitle="how to sign in users with Spotify"
icon="/assets/brands/spotify.svg"
switchId="enabled"

View File

@@ -144,7 +144,7 @@ export default function TwitchProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-twitch"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-twitch"
docsTitle="how to sign in users with Twitch"
icon={
theme.palette.mode === 'dark'

View File

@@ -177,7 +177,7 @@ export default function WorkOsProviderSettings() {
loading: formState.isSubmitting,
},
}}
docsLink="https://docs.nhost.io/products/auth/social/sign-in-workos"
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-workos"
docsTitle="how to sign in users with WorkOS"
icon="/assets/brands/workos.svg"
switchId="enabled"

View File

@@ -0,0 +1,75 @@
import { DragAndDropList } from '@/components/common/DragAndDropList';
import { isEmptyValue } from '@/lib/utils';
import type { DropResult } from '@hello-pangea/dnd';
import type { ColumnInstance } from 'react-table';
import ColumnCustomizerRow from './ColumnCustomizerRow';
import ShowHideAllColumnsButtons from './ShowHideAllColumnsButtons';
type ColumnCustomizerProps = {
columns: ColumnInstance[];
onDragEnd: (columnsOrder: string[]) => void;
onReset: () => void;
onShowAllColumns: () => void;
onHideAllColumns: () => void;
};
function reorder(list: ColumnInstance[], startIndex: number, endIndex: number) {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
}
function ColumnCustomizer({
columns,
onDragEnd,
onReset,
onShowAllColumns,
onHideAllColumns,
}: ColumnCustomizerProps) {
function handleDragEnd(result: DropResult) {
if (isEmptyValue(result.destination)) {
return;
}
const reordered = reorder(
columns,
result.source.index,
result.destination!.index,
).map(({ id }) => id);
onDragEnd(reordered);
}
return (
<div className="flex max-h-[calc(100%-15rem)] flex-col gap-8">
<div className="flex flex-col gap-4">
<h4 className="font-medium leading-none">Column Settings</h4>
<p className="text-sm text-muted-foreground">
Reorder columns by dragging or show/hide them with checkboxes.
</p>
</div>
<div className="self-center">
<ShowHideAllColumnsButtons
onShowAll={onShowAllColumns}
onHideAll={onHideAllColumns}
onReset={onReset}
/>
</div>
<div className="overflow-scroll">
<DragAndDropList droppableId="columnOrder" onDragEnd={handleDragEnd}>
{columns.map((column, index) => (
<ColumnCustomizerRow
key={column.id}
column={column}
index={index}
/>
))}
</DragAndDropList>
</div>
</div>
);
}
export default ColumnCustomizer;

View File

@@ -0,0 +1,49 @@
import {
DraggableItem,
type DraggableItemProps,
} from '@/components/common/DragAndDropList';
import { Checkbox } from '@/components/ui/v3/checkbox';
import { useTablePath } from '@/features/orgs/projects/database/common/hooks/useTablePath';
import PersistenDataTableConfigurationStorage from '@/features/orgs/projects/storage/dataGrid/utils/PersistenDataTableConfigurationStorage';
import { cn } from '@/lib/utils';
import { GripVertical } from 'lucide-react';
import type { ColumnInstance } from 'react-table';
type ColumnCustomizerProps = {
column: ColumnInstance;
} & Omit<DraggableItemProps, 'draggableId'>;
function ColumnCustomizerRow({ column, index }: ColumnCustomizerProps) {
const tablePath = useTablePath();
function handleVisibilityChange() {
PersistenDataTableConfigurationStorage.toggleColumnVisibility(
tablePath,
column.id,
);
column.toggleHidden();
}
return (
<DraggableItem draggableId={column.id} index={index} className="mb-3">
<div
className={cn(
'flex w-full items-center justify-between rounded-md bg-accent p-2',
{ 'opacity-70': !column.isVisible },
)}
>
<div className="flex items-center gap-5">
<Checkbox
checked={column.isVisible}
className="h-[1.125rem] w-[1.125rem] border-[#21324b] data-[state=checked]:!border-transparent dark:border-[#dfecf5]"
onCheckedChange={handleVisibilityChange}
/>
<span>{column.id}</span>
</div>
<GripVertical />
</div>
</DraggableItem>
);
}
export default ColumnCustomizerRow;

View File

@@ -0,0 +1,30 @@
import { Button } from '@/components/ui/v3/button';
import { ButtonGroup } from '@/components/ui/v3/button-group';
type ShowHideAllColumnsToggleProps = {
onShowAll: () => void;
onHideAll: () => void;
onReset: () => void;
};
function ShowHideAllColumnsButtons({
onShowAll,
onHideAll,
onReset,
}: ShowHideAllColumnsToggleProps) {
return (
<ButtonGroup className="w-full">
<Button variant="outline" className="flex-1" onClick={onShowAll}>
Show all columns
</Button>
<Button variant="outline" className="flex-1" onClick={onHideAll}>
Hide all columns
</Button>
<Button variant="outline" className="flex-1" onClick={onReset}>
Reset
</Button>
</ButtonGroup>
);
}
export default ShowHideAllColumnsButtons;

View File

@@ -0,0 +1 @@
export { default as ColumnCustomizer } from './ColumnCustomizer';

Some files were not shown because too many files have changed in this diff Show More