Compare commits

...

209 Commits

Author SHA1 Message Date
David BM
90db32fe96 Merge branch 'feat/event-triggers' of https://github.com/nhost/nhost into event-triggers/invoke-event 2025-11-18 23:34:41 +01:00
David BM
2d5d8d10a9 feat(dashboard): event triggers: delete (#3633) 2025-11-18 23:24:46 +01:00
David BM
4dad3fedca feat(dashboard): event triggers: add event triggers (#3572) 2025-11-18 23:24:46 +01:00
David BM
27e57061f7 feat(dashboard): event triggers: redeliver events (#3567) 2025-11-18 23:24:46 +01:00
David BM
dc6db00fb5 feat(dashboard): event triggers: visualization (#3479) 2025-11-18 23:24:46 +01:00
David BM
99fd1b1b90 feat: initial commit 2025-11-18 23:24:46 +01:00
David BM
49bdaea280 Merge branch 'feat/event-triggers' of https://github.com/nhost/nhost into event-triggers/invoke-event 2025-11-18 23:24:31 +01:00
David BM
17725cb2cd feat(dashboard): event triggers: delete (#3633) 2025-11-18 23:14:28 +01:00
David BM
a8c5a1f859 feat(dashboard): event triggers: add event triggers (#3572) 2025-11-18 23:05:18 +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
cb562b1609 chore: cleanup 2025-11-18 10:12:07 +01:00
David BM
8338650e34 chore: cleanup 2025-11-18 10:12:07 +01:00
David BM
b7daf8db84 chore: refactor 2025-11-18 10:12:07 +01:00
David BM
490a4e5bc3 wip: working with usequery 2025-11-18 10:12:06 +01:00
David BM
585f931391 feat: use invoke event trigger hook 2025-11-18 10:12:06 +01:00
David BM
ab3f103cec wip: invoke event hook 2025-11-18 10:12:06 +01:00
David BM
191f791aff feat: update openapi.yaml for invoke event trigger 2025-11-18 10:12:06 +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
7363010934 Merge branch 'event-triggers/create' of https://github.com/nhost/nhost into event-triggers/delete 2025-11-18 10:10:03 +01:00
David BM
a5cfb7c173 chore: rebase 2025-11-18 10:06:15 +01:00
David BM
fdb6d8c719 chore: style event list item consistently with DataBase page 2025-11-18 09:54:29 +01:00
David BM
9ce344522d chore: refactor form and sidebar props 2025-11-18 09:54:29 +01:00
David BM
654a1b3ea1 chore: remove sheet-drawer 2025-11-18 09:54:29 +01:00
David BM
89dcf25f44 chore: add red border to formselect 2025-11-18 09:54:29 +01:00
David BM
9626b4118e chore: add tests, open form after submit validation failed 2025-11-18 09:54:29 +01:00
David BM
93394e7db6 chore: refactor 2025-11-18 09:54:29 +01:00
David BM
2643c19f31 chore: add tests 2025-11-18 09:54:29 +01:00
David BM
42e3e87fa5 chore: refactor, fix errors 2025-11-18 09:54:29 +01:00
David BM
cd1b65e72b chore: refactor, remove field.tsx 2025-11-18 09:54:29 +01:00
David BM
21f1194317 fix: build 2025-11-18 09:54:29 +01:00
David BM
3351e4dd7d fix: lint 2025-11-18 09:54:29 +01:00
David BM
ea608baa07 chore: testing, cleanup 2025-11-18 09:54:29 +01:00
David BM
0e890f8c3b fix: feedback 2025-11-18 09:54:29 +01:00
David BM
d3fee904cb feat: can remove payload/request transform 2025-11-18 09:54:29 +01:00
David BM
60272df2fe chore: improve display and fix pnpm build 2025-11-18 09:54:29 +01:00
David BM
0d1dcf11af feat: edit payload transform 2025-11-18 09:54:29 +01:00
David BM
05b0e6f57b fix: lint and build errors 2025-11-18 09:54:29 +01:00
David BM
87388e4c6d wip: debounce 2025-11-18 09:54:29 +01:00
David BM
f07959bba7 wip: transform 2025-11-18 09:54:29 +01:00
David BM
2fd9cf27e6 feat: add skeleton for request options url transform 2025-11-18 09:54:29 +01:00
David BM
a8b406d323 feat: save edit 2025-11-18 09:54:29 +01:00
David BM
5689ca1faa feat: edit event trigger flow 2025-11-18 09:54:29 +01:00
David BM
98489335ab feat: create event trigger flow 2025-11-18 09:54:29 +01:00
David BM
282917ff56 chore: fix pnpm build 2025-11-18 09:54:29 +01:00
David BM
1685550f41 chore: rebase changes 2025-11-18 09:54:29 +01:00
David BM
f0540a4510 feat: add edit 2025-11-18 09:54:29 +01:00
David BM
07a125487a feat: request url template 2025-11-18 09:54:29 +01:00
David BM
d4a2202693 chore: update openapi.yaml 2025-11-18 09:54:29 +01:00
David BM
1e4305e1af wip: request options 2025-11-18 09:54:29 +01:00
David BM
4971c15418 wip: request transform schema 2025-11-18 09:54:29 +01:00
David BM
02398c1020 feat: headers section 2025-11-18 09:54:29 +01:00
David BM
e3a3c4f1fb wip: retry configuration section 2025-11-18 09:54:29 +01:00
David BM
4379f13e82 wip: extra settings 2025-11-18 09:54:29 +01:00
David BM
9258527f2d wip: add create network functions [skip ci] 2025-11-18 09:54:29 +01:00
David BM
e679cc6d73 fix: build 2025-11-18 09:54:29 +01:00
David BM
8462ba40ef chore: onsubmit fix types 2025-11-18 09:54:29 +01:00
David BM
c1986e0f1e feat: add delete to openapi.yaml 2025-11-18 09:54:29 +01:00
David BM
ed40f538c2 feat: submit form, webhook 2025-11-18 09:54:29 +01:00
David BM
5e27742d70 wip: asd form 2025-11-18 09:54:29 +01:00
David BM
76d0567680 wip: improve drawer 2025-11-18 09:54:29 +01:00
David BM
bad25212a4 wip: create form 2025-11-18 09:54:29 +01:00
David BM
b4583e1a77 wip: create 2025-11-18 09:54:29 +01:00
David BM
cf7d9f1a51 chore: remove autocleanupconfig 2025-11-18 09:54:29 +01:00
David BM
8ede558225 wip: sheet drawer 2025-11-18 09:54:29 +01:00
David BM
641029cde9 chore: run codegen-hasura-api 2025-11-18 09:54:29 +01:00
David BM
77ca6d656d feat: openapi.yaml 2025-11-18 09:54:29 +01:00
David BM
eab8366e9e chore: rerun codegen-hasura-api 2025-11-18 09:54:29 +01:00
David BM
ccc8e76c11 chore: rerun codegen-hasura-api 2025-11-18 09:54:29 +01:00
David BM
7e186fb3f8 chore: rerun codegen-hasura-api 2025-11-18 09:54:29 +01:00
David BM
e5f5526afa chore: remove autocleanupconfig 2025-11-18 09:54:29 +01:00
David BM
7743e3e1b1 feat: add skeleton loader 2025-11-18 09:54:29 +01:00
David BM
34e6e1c2c2 fix: feedback on PR 2025-11-18 09:54:29 +01:00
David BM
69661059f7 chore: remove unused dep 2025-11-18 09:54:29 +01:00
David BM
a923635b30 chore: remove autocleanupconfig 2025-11-18 09:54:29 +01:00
David BM
a973eae6e4 feat: event trigger visualizations 2025-11-18 09:54:28 +01:00
David BM
35be8ffd4d feat(dashboard): event triggers: redeliver events (#3567) 2025-11-18 09:52:49 +01:00
David BM
1cfc0f32c4 feat(dashboard): event triggers: visualization (#3479) 2025-11-18 09:52:49 +01:00
David BM
41f1be2f6d feat: initial commit 2025-11-18 09:52:49 +01:00
David BM
8e82edd0c6 chore(deps): update blob to address security advisory (#3704) 2025-11-18 09:10:40 +01:00
David BM
4cb4a14f5b Merge branch 'event-triggers/create' of https://github.com/nhost/nhost into event-triggers/delete 2025-11-17 20:55:37 +01:00
David BM
5861996fc6 chore: style event list item consistently with DataBase page 2025-11-17 20:13:33 +01:00
David BM
009a5d38a7 chore: refactor form and sidebar props 2025-11-17 16:53:08 +01:00
David BM
621c8faaae chore: remove sheet-drawer 2025-11-17 16:14:48 +01:00
David BM
4c4fc82074 chore: add red border to formselect 2025-11-17 16:10:25 +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 BM
f0e3e76818 chore: cleanup 2025-11-17 10:32:09 +01:00
David BM
2b9801d8d3 feat: delete event triggers 2025-11-17 10:32:09 +01:00
David BM
eed0c45c93 Merge branch 'feat/event-triggers' of https://github.com/nhost/nhost into event-triggers/create 2025-11-17 10:31:31 +01:00
David BM
6e11788c0d feat(dashboard): event triggers: redeliver events (#3567) 2025-11-17 10:20:31 +01:00
David BM
d6889c762d feat(dashboard): event triggers: visualization (#3479) 2025-11-17 10:20:31 +01:00
David BM
1102f586c3 feat: initial commit 2025-11-17 10:20:31 +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
David BM
c8e12ad96c chore: add tests, open form after submit validation failed 2025-11-15 20:38:46 +01:00
David BM
45888bbf23 Merge branch 'feat/event-triggers' of https://github.com/nhost/nhost into event-triggers/create 2025-11-13 20:12:25 +01:00
David BM
22879ab328 feat(dashboard): event triggers: redeliver events (#3567) 2025-11-13 19:46:19 +01:00
David BM
481726ed1e feat(dashboard): event triggers: visualization (#3479) 2025-11-13 19:46:19 +01:00
David BM
0ab2dd08ab feat: initial commit 2025-11-13 19:44:40 +01:00
David BM
9e8ad786ce chore: refactor 2025-11-13 10:58:12 +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 BM
24bba56e02 chore: add tests 2025-11-13 00:27:01 +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
David BM
1477d24319 chore: refactor, fix errors 2025-11-12 11:41:13 +01:00
robertkasza
5066ef708a chore(dashboard): remove v2 ui components from datatable (#3568) 2025-11-12 11:26:32 +01:00
David BM
edd8544447 chore: refactor, remove field.tsx 2025-11-11 23:35:30 +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
David BM
25bf8dda2f fix: build 2025-11-10 14:53:38 +01:00
David BM
04e5365bb2 fix: lint 2025-11-10 11:56:13 +01:00
David BM
985157c60e chore: testing, cleanup 2025-11-10 11:45:35 +01:00
David BM
0c457b683a fix: feedback 2025-11-10 11:45:35 +01:00
David BM
0a0adb048d feat: can remove payload/request transform 2025-11-10 11:45:35 +01:00
David BM
abab84474b chore: improve display and fix pnpm build 2025-11-10 11:45:35 +01:00
David BM
e218fb1f4c feat: edit payload transform 2025-11-10 11:45:35 +01:00
David BM
eadf14203b fix: lint and build errors 2025-11-10 11:45:35 +01:00
David BM
c3fcb91244 wip: debounce 2025-11-10 11:45:35 +01:00
David BM
b1cf1dc827 wip: transform 2025-11-10 11:45:35 +01:00
David BM
a4d0e37955 feat: add skeleton for request options url transform 2025-11-10 11:45:35 +01:00
David BM
bac90afe37 feat: save edit 2025-11-10 11:45:35 +01:00
David BM
f110d262a6 feat: edit event trigger flow 2025-11-10 11:45:35 +01:00
David BM
f20ef4117c feat: create event trigger flow 2025-11-10 11:45:35 +01:00
David BM
30dede9ea0 chore: fix pnpm build 2025-11-10 11:45:35 +01:00
David BM
f1c8059e8e chore: rebase changes 2025-11-10 11:45:35 +01:00
David BM
1248fdafde feat: add edit 2025-11-10 11:45:35 +01:00
David BM
3f09199f1f feat: request url template 2025-11-10 11:45:35 +01:00
David BM
d84795ed3f chore: update openapi.yaml 2025-11-10 11:45:35 +01:00
David BM
3dab7b9146 wip: request options 2025-11-10 11:45:35 +01:00
David BM
78cfb90098 wip: request transform schema 2025-11-10 11:45:35 +01:00
David BM
509d4f716a feat: headers section 2025-11-10 11:45:35 +01:00
David BM
4f90ef18c5 wip: retry configuration section 2025-11-10 11:45:35 +01:00
David BM
29c9abd6c3 wip: extra settings 2025-11-10 11:45:35 +01:00
David BM
64bcf8b23a wip: add create network functions [skip ci] 2025-11-10 11:45:35 +01:00
David BM
86e5bc2bf6 fix: build 2025-11-10 11:45:35 +01:00
David BM
ab787cfc8c chore: onsubmit fix types 2025-11-10 11:45:35 +01:00
David BM
9e429a7310 feat: add delete to openapi.yaml 2025-11-10 11:45:35 +01:00
David BM
156602392e feat: submit form, webhook 2025-11-10 11:45:35 +01:00
David BM
ce2c8768c1 wip: asd form 2025-11-10 11:45:35 +01:00
David BM
9d44850fb5 wip: improve drawer 2025-11-10 11:45:34 +01:00
David BM
934de7bd10 wip: create form 2025-11-10 11:45:34 +01:00
David BM
7d45845500 wip: create 2025-11-10 11:45:34 +01:00
David BM
a2f4a83ac3 chore: remove autocleanupconfig 2025-11-10 11:45:34 +01:00
David BM
0ccc471787 wip: sheet drawer 2025-11-10 11:45:34 +01:00
David BM
0109ddee6c chore: run codegen-hasura-api 2025-11-10 11:45:34 +01:00
David BM
12ff139212 feat: openapi.yaml 2025-11-10 11:45:34 +01:00
David BM
804e0373b0 chore: rerun codegen-hasura-api 2025-11-10 11:45:34 +01:00
David BM
2f8cb6fcc8 chore: rerun codegen-hasura-api 2025-11-10 11:45:34 +01:00
David BM
4871d71eba chore: rerun codegen-hasura-api 2025-11-10 11:45:34 +01:00
David BM
244604fd83 chore: remove autocleanupconfig 2025-11-10 11:45:34 +01:00
David BM
eac4633434 feat: add skeleton loader 2025-11-10 11:45:34 +01:00
David BM
e27b83a0f4 fix: feedback on PR 2025-11-10 11:45:34 +01:00
David BM
f9a66720cd chore: remove unused dep 2025-11-10 11:45:34 +01:00
David BM
51f32536ff chore: remove autocleanupconfig 2025-11-10 11:45:34 +01:00
David BM
dc4a6a3caa feat: event trigger visualizations 2025-11-10 11:45:34 +01:00
David BM
46a9de4ace feat(dashboard): event triggers: redeliver events (#3567) 2025-11-10 11:44:44 +01:00
David BM
6a650a0b67 feat(dashboard): event triggers: visualization (#3479) 2025-11-10 11:44:44 +01:00
David BM
4f3c1d5f9f feat: initial commit 2025-11-10 11:44:44 +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
github-actions[bot]
46e740f060 release(cli): 1.34.2 (#3603)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-20 14:30:47 +02:00
David Barroso
0d30ab4eec chore(cli): update schema (#3613) 2025-10-20 14:27:49 +02:00
github-actions[bot]
d5fd3cb59c release(services/auth): 0.42.4 (#3618)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
2025-10-20 13:25:21 +02:00
David Barroso
f36d360b9e fix(auth): apply relationships on new projects (#3617) 2025-10-20 13:23:33 +02:00
788 changed files with 27372 additions and 19302 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,52 @@
## [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
- *(cli)* Minor fix to download script when specifying version (#3602)
- *(cli)* Update schema (#3613)
## [cli@1.34.1] - 2025-10-13
### 🐛 Bug Fixes

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

@@ -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

@@ -148,7 +148,7 @@ import (
#Hasura: {
// Version of hasura, you can see available versions in the URL below:
// https://hub.docker.com/r/hasura/graphql-engine/tags
version: string | *"v2.46.0-ce"
version: string | *"v2.48.5-ce"
// JWT Secrets configuration
jwtSecrets: [#JWTSecret]
@@ -223,7 +223,7 @@ import (
// Releases:
//
// https://github.com/nhost/hasura-storage/releases
version: string | *"0.7.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.38.1"
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"`
@@ -6885,6 +6997,8 @@ const (
// column name
DeploymentsSelectColumnCommitUserName DeploymentsSelectColumn = "commitUserName"
// column name
DeploymentsSelectColumnCreatedAt DeploymentsSelectColumn = "createdAt"
// column name
DeploymentsSelectColumnDeploymentEndedAt DeploymentsSelectColumn = "deploymentEndedAt"
// column name
DeploymentsSelectColumnDeploymentStartedAt DeploymentsSelectColumn = "deploymentStartedAt"
@@ -6918,6 +7032,7 @@ var AllDeploymentsSelectColumn = []DeploymentsSelectColumn{
DeploymentsSelectColumnCommitSha,
DeploymentsSelectColumnCommitUserAvatarURL,
DeploymentsSelectColumnCommitUserName,
DeploymentsSelectColumnCreatedAt,
DeploymentsSelectColumnDeploymentEndedAt,
DeploymentsSelectColumnDeploymentStartedAt,
DeploymentsSelectColumnDeploymentStatus,
@@ -6935,7 +7050,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

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",
@@ -51,6 +52,7 @@
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.3",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-hover-card": "^1.1.2",
@@ -60,10 +62,10 @@
"@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",
"@radix-ui/react-tooltip": "^1.2.8",
"@segment/analytics-next": "^1.77.0",
"@simplewebauthn/browser": "^9.0.1",
"@stripe/react-stripe-js": "^2.6.2",
@@ -93,7 +95,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 +127,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 +198,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 +233,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"
}
}
}

606
dashboard/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

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,45 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/v3/alert-dialog';
interface DiscardChangesDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onDiscardChanges: () => void;
}
export default function DiscardChangesDialog({
open,
onOpenChange,
onDiscardChanges,
}: DiscardChangesDialogProps) {
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent className="text-foreground">
<AlertDialogHeader>
<AlertDialogTitle>Unsaved changes</AlertDialogTitle>
<AlertDialogDescription>
You have unsaved local changes. Are you sure you want to discard
them?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={onDiscardChanges}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
Discard
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}

View File

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

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,28 @@
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 { Input, type InputProps } from '@/components/ui/v3/input';
import { InfoTooltip } from '@/features/orgs/projects/common/components/InfoTooltip';
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 +33,137 @@ 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>;
disabled?: boolean;
autoComplete?: InputProps['autoComplete'];
infoTooltip?: string;
}
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,
disabled,
autoComplete,
infoTooltip,
}: 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 })}
>
{infoTooltip ? (
<div className="flex flex-row items-center gap-2">
<FormLabel
className={cn({
'mt-2 w-52 max-w-52 flex-shrink-0 self-start': inline,
})}
>
{label}
</FormLabel>
<InfoTooltip>{infoTooltip}</InfoTooltip>
</div>
) : (
<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}
disabled={disabled}
autoComplete={autoComplete}
{...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,131 @@
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';
const selectClasses =
'aria-[invalid=true]:border-red-500 aria-[invalid=true]:focus:border-red-500 aria-[invalid=true]:focus:ring-red-500';
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;
disabled?: boolean;
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,
disabled,
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}
disabled={disabled}
{...selectProps}
>
<FormControl>
<SelectTrigger className={cn(selectClasses, 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

@@ -9,6 +9,7 @@ import {
} from '@/components/ui/v3/command';
import {
CalendarDays,
Check,
ChevronsUpDown,
CloudIcon,
@@ -19,6 +20,7 @@ import {
HomeIcon,
RocketIcon,
UserIcon,
Zap,
} from 'lucide-react';
import { AIIcon } from '@/components/ui/v2/icons/AIIcon';
@@ -81,6 +83,13 @@ export default function ProjectPagesComboBox() {
slug: 'graphql',
disabled: false,
},
{
label: 'Events',
value: 'events',
icon: <Zap className="h-4 w-4" />,
slug: 'events',
disabled: false,
},
{
label: 'Hasura',
value: 'hasura',
@@ -144,6 +153,13 @@ export default function ProjectPagesComboBox() {
slug: 'metrics',
disabled: !isPlatform,
},
{
label: 'Events',
value: 'events',
icon: <CalendarDays className="h-4 w-4" />,
slug: 'events',
disabled: false,
},
{
label: 'Settings',
value: 'settings',

View File

@@ -15,7 +15,7 @@ import { Button } from '@/components/ui/v3/button';
import { useOrgs, type Org } from '@/features/orgs/projects/hooks/useOrgs';
import { cn, isNotEmptyValue } from '@/lib/utils';
import { getConfigServerUrl, isPlatform as getIsPlatform } from '@/utils/env';
import { Box, ChevronDown, ChevronRight, Plus } from 'lucide-react';
import { Box, ChevronDown, ChevronRight, Plus, Zap } from 'lucide-react';
import Link from 'next/link';
import { type ReactElement } from 'react';
@@ -46,6 +46,12 @@ const projectPages = [
route: 'graphql',
slug: 'graphql',
},
{
name: 'Events',
icon: <Zap className="h-4 w-4" />,
route: 'events',
slug: 'events',
},
{
name: 'Hasura',
icon: <HasuraIcon className="h-4 w-4" />,
@@ -157,6 +163,7 @@ const projectSettingsPages = [
},
{ name: 'AI', slug: 'ai', route: 'ai' },
{ name: 'Observability', slug: 'metrics', route: 'metrics' },
{ name: 'Events', slug: 'events', route: 'events' },
{ name: 'Configuration Editor', slug: 'editor', route: 'editor' },
];
@@ -482,9 +489,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

@@ -100,7 +100,7 @@ export const CodeBlock = forwardRef(
theme.palette.mode === 'dark' ? 'grey.200' : 'grey.200',
}}
className={clsx(
'not-prose relative mt-5 px-2',
'not-prose relative mt-5 w-full min-w-0 max-w-full px-2',
filename && 'pt-2',
className,
)}
@@ -124,8 +124,8 @@ export const CodeBlock = forwardRef(
className="absolute right-3 top-0"
/>
)}
<pre className="overflow-x-auto">
<code className="font-mono">{children}</code>
<pre className="w-full max-w-full whitespace-pre-wrap break-words">
<code className="break-all font-mono">{children}</code>
</pre>
</Box>
),

View File

@@ -0,0 +1,78 @@
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from '@/components/ui/v3/hover-card';
import { cn } from '@/lib/utils';
import { copy } from '@/utils/copy';
import { HoverCardPortal } from '@radix-ui/react-hover-card';
import { format } from 'date-fns';
import { Copy } from 'lucide-react';
import type { ComponentPropsWithoutRef } from 'react';
type HoverCardContentProps = ComponentPropsWithoutRef<typeof HoverCardContent>;
interface HoverCardTimestampProps {
date: Date;
side?: HoverCardContentProps['side'];
sideOffset?: HoverCardContentProps['sideOffset'];
align?: HoverCardContentProps['align'];
alignOffset?: HoverCardContentProps['alignOffset'];
className?: string;
}
function Row({ value, label }: { value: string; label: string }) {
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
<div
className="group flex items-center justify-between gap-4 text-sm"
role="button"
tabIndex={0}
onClick={(e) => {
e.stopPropagation();
copy(value, 'Timestamp');
}}
>
<dt className="text-muted-foreground">{label}</dt>
<dd className="flex items-center gap-1 truncate font-mono">
<span className="invisible group-hover:visible">
<Copy className="h-3 w-3" />
</span>
{value}
</dd>
</div>
);
}
export default function HoverCardTimestamp({
date,
side = 'right',
align = 'start',
alignOffset = -4,
sideOffset,
className,
}: HoverCardTimestampProps) {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
return (
<HoverCard openDelay={0} closeDelay={150}>
<HoverCardTrigger asChild>
<div className={cn('whitespace-nowrap font-mono', className)}>
{format(date, 'LLL dd, y HH:mm:ss')}
</div>
</HoverCardTrigger>
<HoverCardPortal>
<HoverCardContent
className="z-10 w-auto p-2"
{...{ side, align, alignOffset, sideOffset }}
>
<dl className="flex flex-col gap-1">
<Row value={String(date.getTime())} label="Timestamp" />
<Row value={date.toISOString()} label="UTC" />
<Row value={format(date, 'LLL dd, y HH:mm:ss')} label={timezone} />
</dl>
</HoverCardContent>
</HoverCardPortal>
</HoverCard>
);
}

View File

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

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

@@ -1,58 +1,66 @@
'use client';
import * as AccordionPrimitive from '@radix-ui/react-accordion';
import { ChevronDown } from 'lucide-react';
import { ChevronDownIcon } from 'lucide-react';
import * as React from 'react';
import { cn } from '@/lib/utils';
const Accordion = AccordionPrimitive.Root;
function Accordion({
...props
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
}
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn('border-b', className)}
{...props}
/>
));
AccordionItem.displayName = 'AccordionItem';
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn('border-b last:border-b-0', className)}
{...props}
/>
);
}
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
className,
)}
function AccordionTrigger({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
'flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium outline-none transition-all hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180',
className,
)}
{...props}
>
{children}
<ChevronDownIcon className="pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
}
function AccordionContent({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
return (
<AccordionPrimitive.Content
data-slot="accordion-content"
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
<div className={cn('pb-4 pt-0', className)}>{children}</div>
</AccordionPrimitive.Content>
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
<div className={cn('pb-4 pt-0', className)}>{children}</div>
</AccordionPrimitive.Content>
);
}
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };

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: {
@@ -56,11 +56,13 @@ Button.displayName = 'Button';
const ButtonWithLoading = React.forwardRef<
HTMLButtonElement,
ButtonProps & { loading?: boolean }
>(({ loading, disabled, children, ...props }, ref) => {
ButtonProps & { loading?: boolean; loaderClassName?: string }
>(({ loading, disabled, children, loaderClassName, ...props }, ref) => {
return (
<Button disabled={loading || disabled} ref={ref} {...props}>
{loading && <Loader2 className="mr-2 animate-spin" />}
{loading && (
<Loader2 className={cn('mr-2 animate-spin', loaderClassName)} />
)}
{children}
</Button>
);

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

@@ -0,0 +1,7 @@
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
const Collapsible = CollapsiblePrimitive.Root;
const { CollapsibleTrigger, CollapsibleContent } = CollapsiblePrimitive;
export { Collapsible, CollapsibleContent, CollapsibleTrigger };

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

@@ -0,0 +1,177 @@
import { cva, type VariantProps } from 'class-variance-authority';
import * as React from 'react';
import { Button } from '@/components/ui/v3/button';
import { Input } from '@/components/ui/v3/input';
import { Textarea } from '@/components/ui/v3/textarea';
import { cn } from '@/lib/utils';
function InputGroup({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="input-group"
role="group"
className={cn(
'group/input-group shadow-xs relative flex w-full items-center rounded-md border border-input outline-none transition-[color,box-shadow] dark:bg-input/30',
'h-9 has-[>textarea]:h-auto',
// Variants based on alignment.
'has-[>[data-align=inline-start]]:[&>input]:pl-2',
'has-[>[data-align=inline-end]]:[&>input]:pr-2',
'has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3',
'has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3',
// Focus state.
'has-[[data-slot=input-group-control]:focus-visible]:ring-1 has-[[data-slot=input-group-control]:focus-visible]:ring-ring',
// Error state.
'has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40',
className,
)}
{...props}
/>
);
}
const inputGroupAddonVariants = cva(
"text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
{
variants: {
align: {
'inline-start':
'order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]',
'inline-end':
'order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]',
'block-start':
'[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5',
'block-end':
'[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5',
},
},
defaultVariants: {
align: 'inline-start',
},
},
);
function InputGroupAddon({
className,
align = 'inline-start',
...props
}: React.ComponentProps<'div'> & VariantProps<typeof inputGroupAddonVariants>) {
return (
<div
role="button"
data-slot="input-group-addon"
data-align={align}
className={cn(inputGroupAddonVariants({ align }), className)}
tabIndex={0}
onClick={(e) => {
if ((e.target as HTMLElement).closest('button')) {
return;
}
e.currentTarget.parentElement?.querySelector('input')?.focus();
}}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
(e.currentTarget as HTMLDivElement).click();
}
}}
{...props}
/>
);
}
const inputGroupButtonVariants = cva(
'flex items-center gap-2 text-sm shadow-none',
{
variants: {
size: {
xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
sm: 'h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5',
'icon-xs':
'size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0',
'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
},
},
defaultVariants: {
size: 'xs',
},
},
);
function InputGroupButton({
className,
type = 'button',
variant = 'ghost',
size = 'xs',
...props
}: Omit<React.ComponentProps<typeof Button>, 'size'> &
VariantProps<typeof inputGroupButtonVariants>) {
return (
<Button
type={type}
data-size={size}
variant={variant}
className={cn(inputGroupButtonVariants({ size }), className)}
{...props}
/>
);
}
function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) {
return (
<span
className={cn(
"flex items-center gap-2 text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
className,
)}
{...props}
/>
);
}
function InputGroupInput({
className,
wrapperClassName,
...props
}: React.ComponentProps<'input'> & { wrapperClassName?: string }) {
return (
<Input
data-slot="input-group-control"
className={cn(
'flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent',
className,
)}
wrapperClassName={wrapperClassName}
{...props}
/>
);
}
function InputGroupTextarea({
className,
...props
}: React.ComponentProps<'textarea'>) {
return (
<Textarea
data-slot="input-group-control"
className={cn(
'flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent',
className,
)}
{...props}
/>
);
}
export {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
InputGroupText,
InputGroupTextarea,
};

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

@@ -0,0 +1,13 @@
import { cn } from '@/lib/utils';
function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="skeleton"
className={cn('animate-pulse rounded-md bg-muted', className)}
{...props}
/>
);
}
export { Skeleton };

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

@@ -3,26 +3,58 @@ import * as React from 'react';
import { cn } from '@/lib/utils';
const TooltipProvider = TooltipPrimitive.Provider;
function TooltipProvider({
delayDuration = 0, // eslint-disable-line react/prop-types
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
);
}
const Tooltip = TooltipPrimitive.Root;
function Tooltip({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
);
}
const TooltipTrigger = TooltipPrimitive.Trigger;
function TooltipTrigger({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
}
function TooltipContent({
className,
sideOffset = 0,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
className={cn(
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
>
{children}
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
);
}
const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };

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"

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