Compare commits

..

11 Commits

Author SHA1 Message Date
Hassan Ben Jobrane
4fbd6bd4fa chore: fix release with missing changeset (#2588)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-04 16:51:57 +01:00
github-actions[bot]
67fc77486c chore: update versions (#2578)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @nhost/apollo@6.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost/google-translation@0.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

## @nhost/react-apollo@10.0.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/apollo@6.1.0
    -   @nhost/react@3.3.0

## @nhost/react-urql@7.0.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react@3.3.0

## @nhost/stripe-graphql-js@1.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

## @nhost/react@3.3.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost/vue@2.3.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost/nextjs@2.1.6

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react@3.3.0

## @nhost/dashboard@1.10.0

### Minor Changes

-   49a80c2: chore: update dependencies
-   150c04a: feat: add healthcheck config to run services

### Patch Changes

- e03f141: fix: allow insert, update and delete on tables in `auth` and
`storage` schemas
- 28676f4: feat: add min postgres version check to enable the ai service
-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/nextjs@2.1.6

## @nhost/docs@2.7.0

### Minor Changes

-   49a80c2: chore: update dependencies

## @nhost-examples/cli@0.2.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost-examples/codegen-react-apollo@0.2.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/react@3.3.0

## @nhost-examples/codegen-react-query@0.2.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react@3.3.0

## @nhost-examples/codegen-react-urql@0.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react-urql@7.0.0
    -   @nhost/react@3.3.0

## @nhost-examples/docker-compose@0.2.0

### Minor Changes

-   49a80c2: chore: update dependencies

## @nhost-examples/multi-tenant-one-to-many@2.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost-examples/nextjs@0.2.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/react@3.3.0
    -   @nhost/nextjs@2.1.6

## @nhost-examples/node-storage@0.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost-examples/nextjs-server-components@0.3.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   @nhost/nhost-js@3.0.8

## @nhost-examples/sveltekit@0.3.0

### Minor Changes

-   49a80c2: chore: update dependencies

## @nhost-examples/react-apollo@0.4.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

- 4f3fb34: fix: set redirectTo when doing sign in with github and
include vercel previews in allowed redirect URLs
-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/react@3.3.0

## @nhost-examples/react-gqty@1.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/react@3.3.0

## @nhost-examples/serverless-functions@0.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/stripe-graphql-js@1.1.0

## @nhost-examples/vue-apollo@0.3.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

- 4f3fb34: fix: set redirectTo when doing sign in with github and
include vercel previews in allowed redirect URLs
-   Updated dependencies [49a80c2]
    -   @nhost/apollo@6.1.0
    -   @nhost/vue@2.3.0
    -   @nhost/nhost-js@3.0.8

## @nhost-examples/vue-quickstart@0.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

### Patch Changes

-   Updated dependencies [49a80c2]
    -   @nhost/apollo@6.1.0
    -   @nhost/vue@2.3.0

## @nhost/docgen@0.2.0

### Minor Changes

-   49a80c2: chore: update dependencies

## @nhost/sync-versions@0.1.0

### Minor Changes

-   49a80c2: chore: update dependencies

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hassan Ben Jobrane <hsanbenjobrane@gmail.com>
2024-03-04 16:16:06 +01:00
Hassan Ben Jobrane
4f3fb3446e fix: set redirectTo in oauth examples (#2586) 2024-03-04 15:33:24 +01:00
Hassan Ben Jobrane
49a80c22be chore: add changeset (#2584)
adds missing changeset for this PR
https://github.com/nhost/nhost/pull/2574
2024-03-04 13:52:38 +01:00
Hassan Ben Jobrane
28676f4cdc feat: dashboard: add min postgres version check to enable the ai service (#2576)
fixes https://github.com/nhost/nhost/issues/2439
2024-03-02 22:33:49 +01:00
Hassan Ben Jobrane
e03f14133c fix: dashboard: refactor database datagrid to allow insert/update/delete for tables auth and storage (#2577)
fixes https://github.com/nhost/nhost/issues/2476
2024-03-02 22:04:23 +01:00
Hassan Ben Jobrane
150c04a4f4 feat: dashboard: add healthcheck config to run services (#2575)
fixes https://github.com/nhost/nhost/issues/2410
2024-03-02 19:28:13 +01:00
github-actions[bot]
bccd67b1b1 [Scheduled] Update dependencies (#2574)
Dependencies updated

Note - If you see this PR and the checks haven't run, close and reopen
the PR. See
https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs

---------

Co-authored-by: David Barroso <dbarrosop@dravetech.com>
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
Co-authored-by: Hassan Ben Jobrane <hsanbenjobrane@gmail.com>
2024-03-02 18:40:03 +01:00
David Barroso
b14fd2f14c chore: fix role to assume in gen update dependencies (#2573) 2024-03-01 12:21:38 +01:00
github-actions[bot]
68b3d23cd9 chore: update versions (#2572)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @nhost/dashboard@1.9.0

### Minor Changes

-   d86e5c9: feat: add support for filtering the logs using a RegExp

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-02-29 17:54:02 +01:00
Hassan Ben Jobrane
d86e5c9c16 feat(dashboard): query services list from be and filter the logs using a regex (#2552)
fixes: https://github.com/nhost/nhost/issues/2391
2024-02-29 17:38:38 +01:00
94 changed files with 4366 additions and 3879 deletions

View File

@@ -22,7 +22,7 @@ jobs:
- name: Configure aws - name: Configure aws
uses: aws-actions/configure-aws-credentials@v4 uses: aws-actions/configure-aws-credentials@v4
with: with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}:role/github-actions-nhost-be role-to-assume: arn:aws:iam::${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
aws-region: eu-central-1 aws-region: eu-central-1
- uses: nixbuild/nix-quick-install-action@v26 - uses: nixbuild/nix-quick-install-action@v26

3
config/.husky/pre-commit Executable file → Normal file
View File

@@ -1,4 +1,7 @@
#!/bin/sh #!/bin/sh
#
[ -n "$CI" ] && exit 0
. "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/_/husky.sh"
pnpm dlx lint-staged --config config/.lintstagedrc.js pnpm dlx lint-staged --config config/.lintstagedrc.js

View File

@@ -1,5 +1,26 @@
# @nhost/dashboard # @nhost/dashboard
## 1.10.0
### Minor Changes
- 49a80c2: chore: update dependencies
- 150c04a: feat: add healthcheck config to run services
### Patch Changes
- e03f141: fix: allow insert, update and delete on tables in `auth` and `storage` schemas
- 28676f4: feat: add min postgres version check to enable the ai service
- Updated dependencies [49a80c2]
- @nhost/react-apollo@10.0.0
- @nhost/nextjs@2.1.6
## 1.9.0
### Minor Changes
- d86e5c9: feat: add support for filtering the logs using a RegExp
## 1.8.3 ## 1.8.3
### Patch Changes ### Patch Changes

View File

@@ -16,8 +16,6 @@ const cspHeader = `
form-action 'self'; form-action 'self';
frame-ancestors 'none'; frame-ancestors 'none';
frame-src 'self' js.stripe.com; frame-src 'self' js.stripe.com;
block-all-mixed-content;
upgrade-insecure-requests;
`; `;
module.exports = withBundleAnalyzer({ module.exports = withBundleAnalyzer({
@@ -42,10 +40,6 @@ module.exports = withBundleAnalyzer({
key: 'X-Frame-Options', key: 'X-Frame-Options',
value: 'SAMEORIGIN', value: 'SAMEORIGIN',
}, },
{
key: 'Content-Security-Policy',
value: cspHeader.replace(/\n/g, ''),
},
], ],
}, },
]; ];

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/dashboard", "name": "@nhost/dashboard",
"version": "1.8.3", "version": "1.10.0",
"private": true, "private": true,
"scripts": { "scripts": {
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
@@ -19,58 +19,58 @@
"e2e": "pnpm install-browsers && pnpm playwright test" "e2e": "pnpm install-browsers && pnpm playwright test"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@codemirror/lang-sql": "^6.5.5", "@codemirror/lang-sql": "^6.6.0",
"@emotion/cache": "^11.11.0", "@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.3", "@emotion/react": "^11.11.4",
"@emotion/server": "^11.11.0", "@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@fontsource/inter": "^5.0.16", "@fontsource/inter": "^5.0.16",
"@fontsource/roboto-mono": "^5.0.16", "@fontsource/roboto-mono": "^5.0.16",
"@graphiql/react": "^0.20.2", "@graphiql/react": "^0.20.3",
"@graphiql/toolkit": "^0.9.1", "@graphiql/toolkit": "^0.9.1",
"@headlessui/react": "^1.7.18", "@headlessui/react": "^1.7.18",
"@heroicons/react": "^1.0.6", "@heroicons/react": "^1.0.6",
"@hookform/resolvers": "^3.3.4", "@hookform/resolvers": "^3.3.4",
"@mui/base": "5.0.0-beta.31", "@mui/base": "5.0.0-beta.31",
"@mui/material": "^5.15.7", "@mui/material": "^5.15.11",
"@mui/system": "^5.15.7", "@mui/system": "^5.15.11",
"@mui/x-date-pickers": "^5.0.20", "@mui/x-date-pickers": "^5.0.20",
"@nhost/nextjs": "workspace:*", "@nhost/nextjs": "workspace:*",
"@nhost/react-apollo": "workspace:*", "@nhost/react-apollo": "workspace:*",
"@segment/snippet": "^4.16.2", "@segment/snippet": "^4.16.2",
"@stripe/react-stripe-js": "^2.4.0", "@stripe/react-stripe-js": "^2.5.1",
"@stripe/stripe-js": "^1.54.2", "@stripe/stripe-js": "^1.54.2",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@tanstack/react-query": "^4.36.1", "@tanstack/react-query": "^4.36.1",
"@tanstack/react-table": "^8.11.7", "@tanstack/react-table": "^8.13.2",
"@tanstack/react-virtual": "^3.0.2", "@tanstack/react-virtual": "^3.1.3",
"@uiw/codemirror-theme-github": "^4.21.21", "@uiw/codemirror-theme-github": "^4.21.24",
"@uiw/react-codemirror": "^4.21.21", "@uiw/react-codemirror": "^4.21.24",
"analytics-node": "^6.2.0", "analytics-node": "^6.2.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"clsx": "^1.2.1", "clsx": "^1.2.1",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"framer-motion": "^10.18.0", "framer-motion": "^10.18.0",
"generate-password": "^1.7.1", "generate-password": "^1.7.1",
"graphiql": "^3.1.0", "graphiql": "^3.1.1",
"graphql": "16.8.1", "graphql": "16.8.1",
"graphql-request": "^6.1.0", "graphql-request": "^6.1.0",
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"graphql-ws": "^5.14.3", "graphql-ws": "^5.15.0",
"just-kebab-case": "^4.2.0", "just-kebab-case": "^4.2.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"next": "^14.1.0", "next": "^14.1.0",
"next-seo": "^6.4.0", "next-seo": "^6.5.0",
"node-pg-format": "^1.3.5", "node-pg-format": "^1.3.5",
"pluralize": "^8.0.0", "pluralize": "^8.0.0",
"react": "18.2.0", "react": "18.2.0",
"react-children-utilities": "^2.10.0", "react-children-utilities": "^2.10.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-error-boundary": "^4.0.12", "react-error-boundary": "^4.0.13",
"react-hook-form": "^7.50.0", "react-hook-form": "^7.50.1",
"react-hot-toast": "^2.4.1", "react-hot-toast": "^2.4.1",
"react-intersection-observer": "^9.5.4", "react-intersection-observer": "^9.8.1",
"react-is": "18.2.0", "react-is": "18.2.0",
"react-loading-skeleton": "^2.2.0", "react-loading-skeleton": "^2.2.0",
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
@@ -91,7 +91,7 @@
"yup-password": "^0.2.2" "yup-password": "^0.2.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.23.9", "@babel/core": "^7.24.0",
"@faker-js/faker": "^7.6.0", "@faker-js/faker": "^7.6.0",
"@graphql-codegen/cli": "^3.3.1", "@graphql-codegen/cli": "^3.3.1",
"@graphql-codegen/typescript": "^3.0.4", "@graphql-codegen/typescript": "^3.0.4",
@@ -106,36 +106,36 @@
"@storybook/addon-postcss": "^2.0.0", "@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.5.16", "@storybook/builder-webpack5": "^6.5.16",
"@storybook/manager-webpack5": "^6.5.16", "@storybook/manager-webpack5": "^6.5.16",
"@storybook/react": "^7.6.15", "@storybook/react": "^7.6.17",
"@storybook/testing-library": "^0.2.2", "@storybook/testing-library": "^0.2.2",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@testing-library/dom": "^9.3.4", "@testing-library/dom": "^9.3.4",
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^14.2.0", "@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"@types/ace": "^0.0.48", "@types/ace": "^0.0.48",
"@types/bcryptjs": "^2.4.6", "@types/bcryptjs": "^2.4.6",
"@types/jest": "^29.5.11", "@types/jest": "^29.5.12",
"@types/lodash.debounce": "^4.0.9", "@types/lodash.debounce": "^4.0.9",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@types/pluralize": "^0.0.30", "@types/pluralize": "^0.0.30",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.19",
"@types/react-table": "^7.7.19", "@types/react-table": "^7.7.19",
"@types/shell-quote": "^1.7.5", "@types/shell-quote": "^1.7.5",
"@types/testing-library__jest-dom": "^5.14.9", "@types/testing-library__jest-dom": "^5.14.9",
"@types/validator": "^13.11.8", "@types/validator": "^13.11.9",
"@typescript-eslint/eslint-plugin": "^6.20.0", "@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.20.0", "@typescript-eslint/parser": "^6.21.0",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^0.32.4", "@vitest/coverage-v8": "^0.32.4",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"babel-loader": "^8.3.0", "babel-loader": "^8.3.0",
"babel-plugin-transform-remove-console": "^6.9.4", "babel-plugin-transform-remove-console": "^6.9.4",
"csstype": "^3.1.3", "csstype": "^3.1.3",
"dotenv": "^16.4.1", "dotenv": "^16.4.5",
"encoding": "^0.1.13", "encoding": "^0.1.13",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"eslint-config-airbnb": "19.0.4", "eslint-config-airbnb": "19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-next": "^13.5.6", "eslint-config-next": "^13.5.6",
@@ -145,11 +145,11 @@
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"jsdom": "^22.1.0", "jsdom": "^22.1.0",
"lint-staged": "^15.2.1", "lint-staged": "^15.2.2",
"msw": "^1.3.2", "msw": "^1.3.2",
"msw-storybook-addon": "^1.10.0", "msw-storybook-addon": "^1.10.0",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-organize-imports": "^3.2.4", "prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-tailwindcss": "^0.4.1", "prettier-plugin-tailwindcss": "^0.4.1",
@@ -160,7 +160,7 @@
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsconfig-paths-webpack-plugin": "^4.1.0", "tsconfig-paths-webpack-plugin": "^4.1.0",
"vite": "^5.0.12", "vite": "^5.1.4",
"vite-tsconfig-paths": "^4.3.1", "vite-tsconfig-paths": "^4.3.1",
"vitest": "^0.32.4" "vitest": "^0.32.4"
}, },

View File

@@ -35,7 +35,7 @@ function InsertPlaceholderTableRow({
...props ...props
}: InsertPlaceholderTableRowProps) { }: InsertPlaceholderTableRowProps) {
return ( return (
<Box className="h-12 border-r-1 border-b-1" {...props}> <Box className="h-12 border-b-1 border-r-1" {...props}>
<Button <Button
onClick={onInsertRow} onClick={onInsertRow}
variant="borderless" variant="borderless"
@@ -209,7 +209,7 @@ export default function DataGridBody<T extends object>({
/> />
) : ( ) : (
<Box <Box
className="inline-flex h-12 items-center border-b-1 border-r-1 py-1.5 px-2 text-xs" className="inline-flex h-12 items-center border-b-1 border-r-1 px-2 py-1.5 text-xs"
sx={{ color: 'text.secondary' }} sx={{ color: 'text.secondary' }}
style={{ style={{
width: allowInsertColumn width: allowInsertColumn
@@ -281,8 +281,8 @@ export default function DataGridBody<T extends object>({
}} }}
className={twMerge( className={twMerge(
'h-12 font-display text-xs motion-safe:transition-colors', 'h-12 font-display text-xs motion-safe:transition-colors',
'border-r-1 border-b-1', 'border-b-1 border-r-1',
'scroll-mt-[57px] scroll-ml-8', 'scroll-ml-8 scroll-mt-[57px]',
column.id === 'selection' && column.id === 'selection' &&
'sticky left-0 z-20 justify-center px-0', 'sticky left-0 z-20 justify-center px-0',
)} )}
@@ -296,7 +296,7 @@ export default function DataGridBody<T extends object>({
})} })}
{allowInsertColumn && ( {allowInsertColumn && (
<Box className="h-12 w-25 border-r-1 border-b-1" /> <Box className="h-12 w-25 border-b-1 border-r-1" />
)} )}
</div> </div>

View File

@@ -8,7 +8,15 @@ import type {
DataBrowserGridCellProps, DataBrowserGridCellProps,
} from '@/features/database/dataGrid/types/dataBrowser'; } from '@/features/database/dataGrid/types/dataBrowser';
import { triggerToast } from '@/utils/toast'; import { triggerToast } from '@/utils/toast';
import type { FocusEvent, JSXElementConstructor, KeyboardEvent, MouseEvent, ReactElement, ReactNode, ReactPortal } from 'react'; import type {
FocusEvent,
JSXElementConstructor,
KeyboardEvent,
MouseEvent,
ReactElement,
ReactNode,
ReactPortal,
} from 'react';
import { import {
Children, Children,
cloneElement, cloneElement,
@@ -308,7 +316,7 @@ function DataGridCellContent<TData extends object = {}, TValue = unknown>({
isEditable && isEditable &&
'focus-within:outline-none focus-within:ring-0 focus:ring-0', 'focus-within:outline-none focus-within:ring-0 focus:ring-0',
isSelected && 'shadow-outline', isSelected && 'shadow-outline',
isEditing ? 'p-0.5 shadow-outline-dark' : 'py-1.5 px-2', isEditing ? 'p-0.5 shadow-outline-dark' : 'px-2 py-1.5',
className, className,
)} )}
onFocus={handleFocus} onFocus={handleFocus}
@@ -320,20 +328,28 @@ function DataGridCellContent<TData extends object = {}, TValue = unknown>({
sx={{ backgroundColor: 'transparent' }} sx={{ backgroundColor: 'transparent' }}
{...props} {...props}
> >
{Children.map(children, (child: ReactNode | ReactPortal | ReactElement<unknown, string | JSXElementConstructor<any>>) => { {Children.map(
if (!isValidElement(child)) { children,
return null; (
} child:
| ReactNode
| ReactPortal
| ReactElement<unknown, string | JSXElementConstructor<any>>,
) => {
if (!isValidElement(child)) {
return null;
}
return cloneElement(child, { return cloneElement(child, {
...child.props, ...child.props,
onSave: handleSave, onSave: handleSave,
optimisticValue, optimisticValue,
onOptimisticValueChange: setOptimisticValue, onOptimisticValueChange: setOptimisticValue,
temporaryValue, temporaryValue,
onTemporaryValueChange: setTemporaryValue, onTemporaryValueChange: setTemporaryValue,
}); });
})} },
)}
</Box> </Box>
); );

View File

@@ -1,6 +1,6 @@
import { PlusCircleIcon } from '@/components/ui/v2/icons/PlusCircleIcon'; import { PlusCircleIcon } from '@/components/ui/v2/icons/PlusCircleIcon';
import { PlusIcon } from '@/components/ui/v2/icons/PlusIcon'; import { PlusIcon } from '@/components/ui/v2/icons/PlusIcon';
import type { ComponentMeta, ComponentStory } from '@storybook/react'; import type { Meta, StoryFn } from '@storybook/react';
import type { ButtonProps } from './Button'; import type { ButtonProps } from './Button';
import Button from './Button'; import Button from './Button';
@@ -24,9 +24,9 @@ export default {
control: { type: 'radio' }, control: { type: 'radio' },
}, },
}, },
} as ComponentMeta<typeof Button>; } as Meta<typeof Button>;
const Template: ComponentStory<typeof Button> = function Template( const Template: StoryFn<ButtonProps> = function TemplateFunction(
args: ButtonProps, args: ButtonProps,
) { ) {
return <Button {...args} />; return <Button {...args} />;

View File

@@ -1,5 +1,5 @@
import { Option } from '@/components/ui/v2/Option'; import { Option } from '@/components/ui/v2/Option';
import type { ComponentMeta, ComponentStory } from '@storybook/react'; import type { Meta, StoryFn } from '@storybook/react';
import type { SelectProps } from './Select'; import type { SelectProps } from './Select';
import Select from './Select'; import Select from './Select';
@@ -7,11 +7,9 @@ export default {
title: 'UI Library / Select', title: 'UI Library / Select',
component: Select, component: Select,
argTypes: {}, argTypes: {},
} as ComponentMeta<typeof Select>; } as Meta<typeof Select>;
const Template: ComponentStory<typeof Select> = function Template( const Template: StoryFn<SelectProps<any>> = function TemplateFunction(args) {
args: SelectProps<any>,
) {
return ( return (
<Select className="w-64" {...args}> <Select className="w-64" {...args}>
<Option value="value1">Value 1</Option> <Option value="value1">Value 1</Option>

View File

@@ -1,4 +1,4 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react'; import type { Meta, StoryFn } from '@storybook/react';
import type { SwitchProps } from './Switch'; import type { SwitchProps } from './Switch';
import Switch from './Switch'; import Switch from './Switch';
@@ -6,9 +6,9 @@ export default {
title: 'UI Library / Switch', title: 'UI Library / Switch',
component: Switch, component: Switch,
argTypes: {}, argTypes: {},
} as ComponentMeta<typeof Switch>; } as Meta<typeof Switch>;
const Template: ComponentStory<typeof Switch> = function Template( const Template: StoryFn<SwitchProps> = function TemplateFunction(
args: SwitchProps, args: SwitchProps,
) { ) {
return <Switch label="Accept Rules" {...args} />; return <Switch label="Accept Rules" {...args} />;

View File

@@ -21,13 +21,17 @@ import {
useUpdateConfigMutation, useUpdateConfigMutation,
} from '@/generated/graphql'; } from '@/generated/graphql';
import { RESOURCE_VCPU_MULTIPLIER } from '@/utils/constants/common'; import { RESOURCE_VCPU_MULTIPLIER } from '@/utils/constants/common';
import { getToastStyleProps } from '@/utils/constants/settings';
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast'; import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
import { yupResolver } from '@hookform/resolvers/yup'; import { yupResolver } from '@hookform/resolvers/yup';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { toast } from 'react-hot-toast';
import * as Yup from 'yup'; import * as Yup from 'yup';
import { DisableAIServiceConfirmationDialog } from './DisableAIServiceConfirmationDialog'; import { DisableAIServiceConfirmationDialog } from './DisableAIServiceConfirmationDialog';
const MIN_POSTGRES_VERSION_SUPPORTING_AI = '14.6-20231018-1';
const validationSchema = Yup.object({ const validationSchema = Yup.object({
version: Yup.object({ version: Yup.object({
label: Yup.string().required(), label: Yup.string().required(),
@@ -54,7 +58,9 @@ export default function AISettings() {
const [aiServiceEnabled, setAIServiceEnabled] = useState(true); const [aiServiceEnabled, setAIServiceEnabled] = useState(true);
const { const {
data: { config: { ai } = {} } = {}, data: {
config: { ai, postgres: { version: postgresVersion } = {} } = {},
} = {},
loading: loadingAiSettings, loading: loadingAiSettings,
error: errorGettingAiSettings, error: errorGettingAiSettings,
} = useGetAiSettingsQuery({ } = useGetAiSettingsQuery({
@@ -150,6 +156,17 @@ export default function AISettings() {
]); ]);
const toggleAIService = async (enabled: boolean) => { const toggleAIService = async (enabled: boolean) => {
if (postgresVersion < MIN_POSTGRES_VERSION_SUPPORTING_AI) {
toast.error(
'In order to enable the AI service you need to update your database version to 14.6-20231018-1 or newer.',
{
style: getToastStyleProps().style,
...getToastStyleProps().error,
},
);
return;
}
setAIServiceEnabled(enabled); setAIServiceEnabled(enabled);
if (!enabled && ai) { if (!enabled && ai) {

View File

@@ -1,5 +1,8 @@
query GetAISettings($appId: uuid!) { query GetAISettings($appId: uuid!) {
config(appID: $appId, resolve: false) { config(appID: $appId, resolve: false) {
postgres {
version
}
ai { ai {
version version
webhookSecret webhookSecret

View File

@@ -275,7 +275,7 @@ export default function DataBrowserGrid({
() => () =>
columns columns
.map((column) => ({ .map((column) => ({
...createDataGridColumn(column, isSchemaEditable), ...createDataGridColumn(column, true),
onCellEdit: async (variables: UpdateRecordVariables) => { onCellEdit: async (variables: UpdateRecordVariables) => {
const result = await updateRow(variables); const result = await updateRow(variables);
await queryClient.invalidateQueries([currentTablePath]); await queryClient.invalidateQueries([currentTablePath]);
@@ -288,7 +288,6 @@ export default function DataBrowserGrid({
[ [
columns, columns,
currentTablePath, currentTablePath,
isSchemaEditable,
optimisticlyRemovedColumnId, optimisticlyRemovedColumnId,
queryClient, queryClient,
removableColumnId, removableColumnId,
@@ -422,7 +421,7 @@ export default function DataBrowserGrid({
loading={status === 'loading'} loading={status === 'loading'}
sortBy={sortBy} sortBy={sortBy}
className="pb-17 sm:pb-0" className="pb-17 sm:pb-0"
onInsertRow={isSchemaEditable ? handleInsertRowClick : undefined} onInsertRow={handleInsertRowClick}
onInsertColumn={isSchemaEditable ? handleInsertColumnClick : undefined} onInsertColumn={isSchemaEditable ? handleInsertColumnClick : undefined}
onEditColumn={isSchemaEditable ? handleEditColumnClick : undefined} onEditColumn={isSchemaEditable ? handleEditColumnClick : undefined}
onRemoveColumn={isSchemaEditable ? handleColumnRemoveClick : undefined} onRemoveColumn={isSchemaEditable ? handleColumnRemoveClick : undefined}
@@ -445,7 +444,7 @@ export default function DataBrowserGrid({
onInsertColumnClick={ onInsertColumnClick={
isSchemaEditable ? handleInsertColumnClick : undefined isSchemaEditable ? handleInsertColumnClick : undefined
} }
onInsertRowClick={isSchemaEditable ? handleInsertRowClick : undefined} onInsertRowClick={handleInsertRowClick}
paginationProps={{ paginationProps={{
currentPage: Math.max(currentPage, 1), currentPage: Math.max(currentPage, 1),
totalPages: Math.max(numberOfPages, 1), totalPages: Math.max(numberOfPages, 1),

View File

@@ -12,11 +12,9 @@ import { PlusIcon } from '@/components/ui/v2/icons/PlusIcon';
import { RowIcon } from '@/components/ui/v2/icons/RowIcon'; import { RowIcon } from '@/components/ui/v2/icons/RowIcon';
import { useDeleteRecordMutation } from '@/features/database/dataGrid/hooks/useDeleteRecordMutation'; import { useDeleteRecordMutation } from '@/features/database/dataGrid/hooks/useDeleteRecordMutation';
import type { DataBrowserGridColumn } from '@/features/database/dataGrid/types/dataBrowser'; import type { DataBrowserGridColumn } from '@/features/database/dataGrid/types/dataBrowser';
import { isSchemaLocked } from '@/features/database/dataGrid/utils/schemaHelpers/isSchemaLocked';
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject'; import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
import { triggerToast } from '@/utils/toast'; import { triggerToast } from '@/utils/toast';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { useState } from 'react'; import { useState } from 'react';
import type { Row } from 'react-table'; import type { Row } from 'react-table';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
@@ -58,11 +56,6 @@ export default function DataBrowserGridControls({
const { className: paginationClassName, ...restPaginationProps } = const { className: paginationClassName, ...restPaginationProps } =
paginationProps || ({} as DataGridPaginationProps); paginationProps || ({} as DataGridPaginationProps);
const {
query: { schemaSlug },
} = useRouter();
const isSchemaEditable = !isSchemaLocked(schemaSlug as string);
const { const {
selectedFlatRows: selectedRows, selectedFlatRows: selectedRows,
columns, columns,
@@ -126,7 +119,7 @@ export default function DataBrowserGridControls({
numberOfSelectedRows > 0 ? 'justify-between' : 'justify-end', numberOfSelectedRows > 0 ? 'justify-between' : 'justify-end',
)} )}
> >
{isSchemaEditable && numberOfSelectedRows > 0 && ( {numberOfSelectedRows > 0 && (
<div className="grid grid-flow-col place-content-start items-center gap-2"> <div className="grid grid-flow-col place-content-start items-center gap-2">
<Chip <Chip
size="small" size="small"

View File

@@ -43,7 +43,13 @@ export default async function deleteRecord({
(row) => (row) =>
`(${primaryOrUniqueColumns `(${primaryOrUniqueColumns
.map((primaryOrUniqueColumn) => .map((primaryOrUniqueColumn) =>
format('%I=%L', primaryOrUniqueColumn, row[primaryOrUniqueColumn]), row[primaryOrUniqueColumn] === null
? format('%I IS NULL', primaryOrUniqueColumn)
: format(
'%I=%L',
primaryOrUniqueColumn,
row[primaryOrUniqueColumn],
),
) )
.join(' AND ')})`, .join(' AND ')})`,
); );

View File

@@ -131,7 +131,7 @@ export default function LogsBody({ logsData, loading, error }: LogsBodyProps) {
count: rows.length, count: rows.length,
getScrollElement: () => tableRef.current, getScrollElement: () => tableRef.current,
estimateSize: () => 63, estimateSize: () => 63,
overscan: 5, overscan: 50,
}); });
if (loading && !error) { if (loading && !error) {
@@ -214,7 +214,7 @@ export default function LogsBody({ logsData, loading, error }: LogsBodyProps) {
<TableCell <TableCell
key={cell.id} key={cell.id}
component="td" component="td"
className="break-words py-2.5 px-2 align-top text-xs- font-normal tracking-tight" className="break-words px-2 py-2.5 align-top text-xs- font-normal tracking-tight"
style={{ style={{
width: cell.column.getSize() || 'auto', width: cell.column.getSize() || 'auto',
minWidth: !cell.column.getSize() ? 300 : 'initial', minWidth: !cell.column.getSize() ? 300 : 'initial',

View File

@@ -52,7 +52,7 @@ function LogsDatePicker({
<Text <Text
htmlFor={label} htmlFor={label}
component="label" component="label"
className="self-center text-sm+ font-normal" className="min-w-14 self-center text-sm+ font-normal"
color="secondary" color="secondary"
> >
{label} {label}

View File

@@ -1,246 +1,240 @@
import { ControlledSelect } from '@/components/form/ControlledSelect';
import { Form } from '@/components/form/Form';
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import type { BoxProps } from '@/components/ui/v2/Box'; import type { BoxProps } from '@/components/ui/v2/Box';
import { Box } from '@/components/ui/v2/Box'; import { Box } from '@/components/ui/v2/Box';
import { Button } from '@/components/ui/v2/Button'; import { Button } from '@/components/ui/v2/Button';
import { ClockIcon } from '@/components/ui/v2/icons/ClockIcon'; import { InfoIcon } from '@/components/ui/v2/icons/InfoIcon';
import { SearchIcon } from '@/components/ui/v2/icons/SearchIcon';
import { Input } from '@/components/ui/v2/Input';
import { Link } from '@/components/ui/v2/Link';
import { Option } from '@/components/ui/v2/Option'; import { Option } from '@/components/ui/v2/Option';
import { Select } from '@/components/ui/v2/Select'; import { Tooltip } from '@/components/ui/v2/Tooltip';
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject'; import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
import { LogsDatePicker } from '@/features/projects/logs/components/LogsDatePicker'; import { LogsRangeSelector } from '@/features/projects/logs/components/LogsRangeSelector';
import type { LogsCustomInterval } from '@/features/projects/logs/utils/constants/intervals'; import { AvailableLogsService } from '@/features/projects/logs/utils/constants/services';
import { LOGS_AVAILABLE_INTERVALS } from '@/features/projects/logs/utils/constants/intervals'; import { MINUTES_TO_DECREASE_FROM_CURRENT_DATE } from '@/utils/constants/common';
import type { AvailableLogsService } from '@/features/projects/logs/utils/constants/services'; import { useGetServiceLabelValuesQuery } from '@/utils/__generated__/graphql';
import { LOGS_AVAILABLE_SERVICES } from '@/features/projects/logs/utils/constants/services'; import { yupResolver } from '@hookform/resolvers/yup';
import { useGetRunServicesQuery } from '@/utils/__generated__/graphql';
import { subMinutes } from 'date-fns'; import { subMinutes } from 'date-fns';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { twMerge } from 'tailwind-merge'; import { FormProvider, useForm } from 'react-hook-form';
import * as Yup from 'yup';
export interface LogsHeaderProps extends Omit<BoxProps, 'children'> { export const validationSchema = Yup.object({
from: Yup.date(),
to: Yup.date().nullable(),
service: Yup.string().oneOf(Object.values(AvailableLogsService)),
regexFilter: Yup.string(),
});
export type LogsFilterFormValues = Yup.InferType<typeof validationSchema>;
interface LogsHeaderProps extends Omit<BoxProps, 'children'> {
/** /**
* The date to be displayed in the date picker for the from date. * This is used to indicate that a query is currently inflight
*/ */
fromDate: Date; loading: boolean;
/** /**
* The date to be displayed in the date picker for the to date. *
* Function to be called when the user submits the filters form
*/ */
toDate: Date | null; onSubmitFilterValues: (value: LogsFilterFormValues) => void;
/**
* Service to where to fetch logs from.
*/
service: AvailableLogsService;
/**
* Function to be called when the user changes the from date.
*/
onFromDateChange: (value: Date) => void;
/**
* Function to be called when the user changes the `to` date.
*/
onToDateChange: (value: Date) => void;
/**
* Function to be called when the user changes service to which to query logs from.
*/
onServiceChange: (value: AvailableLogsService) => void;
}
type LogsToDatePickerLiveButtonProps = Pick<
LogsHeaderProps,
'fromDate' | 'toDate' | 'onToDateChange'
>;
function LogsToDatePickerLiveButton({
fromDate,
toDate,
onToDateChange,
}: LogsToDatePickerLiveButtonProps) {
const [currentTime, setCurrentTime] = useState(new Date());
const isLive = !toDate;
function handleLiveButtonClick() {
if (isLive) {
return;
}
onToDateChange(null);
setCurrentTime(new Date());
}
// if isLive is true, we want to update the current time every second
// and set the toDate to the current time.
useEffect(() => {
let interval = null;
if (!interval && isLive) {
interval = setInterval(() => {
setCurrentTime(new Date());
}, 1000);
}
return () => {
clearInterval(interval);
};
}, [isLive, onToDateChange]);
return (
<div className="text-greyscaleMedium grid grid-flow-col">
<LogsDatePicker
label="To"
value={!isLive ? toDate : currentTime}
disabled={isLive}
onChange={onToDateChange}
minDate={fromDate}
maxDate={toDate || new Date()}
componentsProps={{
button: {
className: twMerge(
'rounded-r-none pr-3',
isLive ? 'border-r-0 hover:border-r-0 z-0' : 'z-10',
),
color: toDate ? 'inherit' : 'secondary',
},
}}
/>
<Button
variant="outlined"
color={isLive ? 'primary' : 'secondary'}
sx={{
backgroundColor: (theme) =>
!isLive ? `${theme.palette.grey[200]} !important` : 'transparent',
color: !isLive ? 'text.secondary' : undefined,
}}
className={twMerge(
'min-w-[77px] rounded-l-none',
!isLive ? 'z-0 border-l-0 hover:border-l-0' : 'z-10',
)}
startIcon={<ClockIcon className="h-4 w-4 self-center align-middle" />}
onClick={handleLiveButtonClick}
>
Live
</Button>
</div>
);
} }
export default function LogsHeader({ export default function LogsHeader({
fromDate, loading,
toDate, onSubmitFilterValues,
service,
onFromDateChange,
onToDateChange,
onServiceChange,
...props ...props
}: LogsHeaderProps) { }: LogsHeaderProps) {
const { currentProject } = useCurrentWorkspaceAndProject(); const { currentProject } = useCurrentWorkspaceAndProject();
const applicationCreationDate = new Date(currentProject.createdAt);
const [runServices, setRunServices] = useState< const [serviceLabels, setServiceLabels] = useState<
{ { label: string; value: string }[]
label: string;
value: string;
}[]
>([]); >([]);
const { data, loading } = useGetRunServicesQuery({ const { data, loading: loadingServiceLabelValues } =
variables: { useGetServiceLabelValuesQuery({
appID: currentProject.id, variables: { appID: currentProject.id },
resolve: false, });
limit: 1000,
offset: 0,
},
});
useEffect(() => { useEffect(() => {
if (!loading) { if (!loadingServiceLabelValues) {
const services = data.app?.runServices ?? []; const labels = data.getServiceLabelValues ?? [];
setServiceLabels(labels.map((l) => ({ label: l, value: l })));
}
}, [loadingServiceLabelValues, data]);
setRunServices( useEffect(() => {
services if (!loadingServiceLabelValues) {
.filter((s) => !!s.config?.name) const labels = data.getServiceLabelValues ?? [];
.map((s) => ({
label: s.config.name, const labelMappings = {
value: `run-${s.config.name}`, 'hasura-auth': 'Auth',
})), 'hasura-storage': 'Storage',
postgres: 'Postgres',
functions: 'Functions',
hasura: 'Hasura',
grafana: 'Grafana',
'job-backup': 'Backup Jobs',
ai: 'AI',
};
setServiceLabels(
labels.map((l) => ({ label: labelMappings[l] ?? l, value: l })),
); );
} }
}, [loading, data]); }, [loadingServiceLabelValues, data]);
/** const form = useForm<LogsFilterFormValues>({
* Will subtract the `customInterval` time in minutes from the current date. defaultValues: {
*/ from: subMinutes(new Date(), MINUTES_TO_DECREASE_FROM_CURRENT_DATE),
function handleIntervalChange({ to: new Date(),
minutesToDecreaseFromCurrentDate, regexFilter: '',
}: LogsCustomInterval) { service: AvailableLogsService.ALL,
onFromDateChange(subMinutes(new Date(), minutesToDecreaseFromCurrentDate)); },
onToDateChange(new Date()); reValidateMode: 'onSubmit',
} resolver: yupResolver(validationSchema),
});
const { register, watch, getValues } = form;
const service = watch('service');
useEffect(() => {
onSubmitFilterValues(getValues());
}, [service, getValues, onSubmitFilterValues]);
const handleSubmit = (values: LogsFilterFormValues) =>
onSubmitFilterValues(values);
return ( return (
<Box <Box
className="sticky top-0 z-10 grid w-full grid-flow-row gap-x-6 gap-y-2 border-b py-2.5 px-4 lg:grid-flow-col lg:justify-between" className="sticky top-0 z-10 grid w-full grid-flow-row gap-x-6 gap-y-2 border-b px-4 py-2.5 lg:grid-flow-col"
{...props} {...props}
> >
<Box className="grid w-full grid-flow-row items-center justify-center gap-2 md:w-[initial] md:grid-flow-col md:gap-3 lg:justify-start"> <FormProvider {...form}>
<div className="grid grid-flow-col items-center gap-3 md:justify-start"> <Form
<LogsDatePicker onSubmit={handleSubmit}
label="From" className="grid w-full grid-flow-row items-center gap-2 md:w-[initial] md:grid-flow-col md:gap-3 lg:justify-end"
value={fromDate} >
onChange={onFromDateChange} <Box className="flex flex-row space-x-2">
minDate={applicationCreationDate} <ControlledSelect
maxDate={toDate || new Date()} {...register('service')}
/> className="w-full text-sm font-normal min-w-fit"
placeholder="All Services"
aria-label="Select service"
hideEmptyHelperText
slotProps={{
root: {
className: 'min-h-[initial] h-10 leading-[initial]',
},
}}
>
{[{ label: 'All services', value: '' }, ...serviceLabels].map(
({ value, label }) => (
<Option
key={value}
value={value}
className="text-sm+ font-medium"
>
{label}
</Option>
),
)}
</ControlledSelect>
<div className="w-full min-w-fit">
<LogsRangeSelector onSubmitFilterValues={onSubmitFilterValues} />
</div>
</Box>
<LogsToDatePickerLiveButton <Input
fromDate={fromDate} {...register('regexFilter')}
toDate={toDate} placeholder="Filter logs with a regular expression"
onToDateChange={onToDateChange}
/>
</div>
<Box className="-my-2.5 px-0 py-2.5 lg:border-l lg:px-3">
<Select
className="w-full text-sm font-normal"
placeholder="All Services"
onChange={(_e, value) => {
if (typeof value !== 'string') {
return;
}
onServiceChange(value as AvailableLogsService);
}}
value={service}
aria-label="Select service"
hideEmptyHelperText hideEmptyHelperText
slotProps={{ autoComplete="off"
root: { className: 'min-h-[initial] h-9 leading-[initial]' }, fullWidth
}} className="min-w-80"
> startAdornment={
{[...LOGS_AVAILABLE_SERVICES, ...runServices].map( <Tooltip
({ value, label }) => ( componentsProps={{
<Option tooltip: {
key={value} sx: {
value={value} maxWidth: '30rem',
className="text-sm+ font-medium" },
> },
{label} }}
</Option> title={
), <div className="p-2 space-y-4">
)} <h2>Here are some useful regular expressions:</h2>
</Select> <ul className="pl-3 space-y-2 list-disc">
</Box> <li>
</Box> use
<code className="px-1 py-px mx-1 rounded-md bg-slate-500 text-slate-100">
(?i)error
</code>
to search for lines with the word <b>error</b> (case
insenstive)
</li>
<li>
use
<code className="px-1 py-px mx-1 rounded-md bg-slate-500 text-slate-100">
error
</code>
to search for lines with the word <b>error</b> (case
sensitive)
</li>
<li>
use
<code className="px-1 py-px mx-1 rounded-md bg-slate-500 text-slate-100">
/metadata.*error
</code>
to search for errors in hasura&apos;s metadata endpoint
</li>
<li>
See
<Link
href="https://github.com/google/re2/wiki/Syntax"
target="_blank"
rel="noopener noreferrer"
underline="hover"
className="mx-1"
>
here
</Link>
for more patterns
</li>
</ul>
</div>
}
>
<Box className="ml-2 rounded-full cursor-pointer">
<InfoIcon
aria-label="Info"
className="w-5 h-5"
color="info"
/>
</Box>
</Tooltip>
}
/>
<Box className="hidden grid-flow-col items-center justify-center gap-3 md:grid lg:justify-end">
{LOGS_AVAILABLE_INTERVALS.map((logInterval) => (
<Button <Button
key={logInterval.label} type="submit"
variant="outlined" className="h-10"
color="secondary" startIcon={
className="self-center" loading ? (
onClick={() => handleIntervalChange(logInterval)} <ActivityIndicator className="w-4 h-4" />
) : (
<SearchIcon />
)
}
disabled={loading}
> >
{logInterval.label} Search
</Button> </Button>
))} </Form>
</Box> </FormProvider>
</Box> </Box>
); );
} }

View File

@@ -1,2 +1 @@
export * from './LogsHeader'; export { default as LogsHeader, type LogsFilterFormValues } from './LogsHeader';
export { default as LogsHeader } from './LogsHeader';

View File

@@ -0,0 +1,170 @@
import { Box } from '@/components/ui/v2/Box';
import { Button } from '@/components/ui/v2/Button';
import { Dropdown, useDropdown } from '@/components/ui/v2/Dropdown';
import { ClockIcon } from '@/components/ui/v2/icons/ClockIcon';
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
import { LogsDatePicker } from '@/features/projects/logs/components/LogsDatePicker';
import type { LogsFilterFormValues } from '@/features/projects/logs/components/LogsHeader';
import {
LOGS_AVAILABLE_INTERVALS,
type LogsCustomInterval,
} from '@/features/projects/logs/utils/constants/intervals';
import { useInterval } from '@/hooks/useInterval';
import { ChevronDownIcon } from '@graphiql/react';
import { formatDistance, subMinutes } from 'date-fns';
import { useState } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { twMerge } from 'tailwind-merge';
function LogsToDatePickerLiveButton() {
const [currentTime, setCurrentTime] = useState(new Date());
const { setValue } = useFormContext<LogsFilterFormValues>();
const { from, to } = useWatch<LogsFilterFormValues>();
const isLive = !to;
function handleLiveButtonClick() {
if (isLive) {
setValue('from', subMinutes(new Date(), 20));
setValue('to', new Date());
return;
}
setValue('to', null);
setCurrentTime(new Date());
}
useInterval(() => setCurrentTime(new Date()), isLive ? 1000 : 0);
return (
<div className="text-greyscaleMedium flex flex-col">
{!isLive && (
<LogsDatePicker
label="To"
value={!isLive ? to : currentTime}
disabled={isLive}
onChange={(date: Date) => setValue('to', date)}
minDate={from}
maxDate={new Date()}
componentsProps={{
button: {
className: twMerge('rounded-r-none', isLive ? 'z-0' : 'z-10'),
color: to ? 'inherit' : 'secondary',
},
}}
/>
)}
<Button
variant="outlined"
color={isLive ? 'primary' : 'secondary'}
sx={{
backgroundColor: (theme) =>
!isLive ? `${theme.palette.grey[200]} !important` : 'transparent',
color: !isLive ? 'text.secondary' : undefined,
}}
className={twMerge(!isLive ? 'z-0 mt-4' : 'z-10')}
startIcon={<ClockIcon className="h-4 w-4 self-center align-middle" />}
onClick={handleLiveButtonClick}
>
Live
</Button>
</div>
);
}
interface LogsRangeSelectorProps {
onSubmitFilterValues: (value: LogsFilterFormValues) => void;
}
function LogsRangeSelectorIntervalPickers({
onSubmitFilterValues,
}: LogsRangeSelectorProps) {
const { currentProject } = useCurrentWorkspaceAndProject();
const applicationCreationDate = new Date(currentProject.createdAt);
const { setValue, getValues } = useFormContext<LogsFilterFormValues>();
const { from } = useWatch<LogsFilterFormValues>();
const { handleClose } = useDropdown();
const handleApply = () => {
onSubmitFilterValues(getValues());
handleClose();
};
/**
* Will subtract the `customInterval` time in minutes from the current date.
*/
function handleIntervalChange({
minutesToDecreaseFromCurrentDate,
}: LogsCustomInterval) {
setValue('from', subMinutes(new Date(), minutesToDecreaseFromCurrentDate));
setValue('to', new Date());
}
return (
<Box className="flex flex-col space-y-4">
<div className="flex flex-col space-y-4">
<LogsDatePicker
label="From"
value={from}
onChange={(date) => setValue('from', date)}
minDate={applicationCreationDate}
maxDate={new Date()}
/>
<LogsToDatePickerLiveButton />
</div>
<Box className="grid grid-cols-2 gap-2">
{LOGS_AVAILABLE_INTERVALS.map((logInterval) => (
<Button
key={logInterval.label}
variant="outlined"
color="secondary"
className="self-center"
onClick={() => handleIntervalChange(logInterval)}
>
Last {logInterval.label}
</Button>
))}
</Box>
<Button color="primary" variant="contained" onClick={handleApply}>
Apply
</Button>
</Box>
);
}
export default function LogsRangeSelector({
onSubmitFilterValues,
}: LogsRangeSelectorProps) {
const { from, to } = useWatch<LogsFilterFormValues>();
return (
<Dropdown.Root>
<Dropdown.Trigger hideChevron className="flex w-full rounded-full">
<Button
component="a"
className="h-10 w-full min-w-40 items-center justify-between"
variant="outlined"
>
<span>
{to === null
? 'Live'
: `${formatDistance(to.getTime(), from.getTime())}`}
</span>
<ChevronDownIcon className="h-3 w-3" />
</Button>
</Dropdown.Trigger>
<Dropdown.Content PaperProps={{ className: 'mt-1 max-w-xs w-full p-3' }}>
<LogsRangeSelectorIntervalPickers
onSubmitFilterValues={onSubmitFilterValues}
/>
</Dropdown.Content>
</Dropdown.Root>
);
}

View File

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

View File

@@ -89,7 +89,7 @@ function LogsTimePicker({
</Button> </Button>
<Button variant="contained" color="primary" onClick={handleApply}> <Button variant="contained" color="primary" onClick={handleApply}>
Apply Set
</Button> </Button>
</Box> </Box>
</div> </div>

View File

@@ -26,4 +26,12 @@ export const LOGS_AVAILABLE_INTERVALS: LogsCustomInterval[] = [
label: '60 min', label: '60 min',
minutesToDecreaseFromCurrentDate: 60, minutesToDecreaseFromCurrentDate: 60,
}, },
{
label: '12 hours',
minutesToDecreaseFromCurrentDate: 720,
},
{
label: '24 hours',
minutesToDecreaseFromCurrentDate: 1440,
},
]; ];

View File

@@ -38,6 +38,7 @@ import { yupResolver } from '@hookform/resolvers/yup';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { parse } from 'shell-quote'; import { parse } from 'shell-quote';
import { HealthCheckFormSection } from './components/HealthCheckFormSection';
import { ServiceConfirmationDialog } from './components/ServiceConfirmationDialog'; import { ServiceConfirmationDialog } from './components/ServiceConfirmationDialog';
import { ServiceDetailsDialog } from './components/ServiceDetailsDialog'; import { ServiceDetailsDialog } from './components/ServiceDetailsDialog';
@@ -118,6 +119,13 @@ export default function ServiceForm({
type: item.type, type: item.type,
publish: item.publish, publish: item.publish,
})), })),
healthCheck: values.healthCheck
? {
port: values.healthCheck?.port,
initialDelaySeconds: values.healthCheck?.initialDelaySeconds,
probePeriodSeconds: values.healthCheck?.probePeriodSeconds,
}
: null,
}; };
return config; return config;
@@ -375,6 +383,8 @@ export default function ServiceForm({
<StorageFormSection /> <StorageFormSection />
<HealthCheckFormSection />
{createServiceFormError && ( {createServiceFormError && (
<Alert <Alert
severity="error" severity="error"

View File

@@ -41,6 +41,13 @@ export const validationSchema = Yup.object({
}) })
.required(), .required(),
), ),
healthCheck: Yup.object()
.shape({
port: Yup.number().required(),
initialDelaySeconds: Yup.number().required(),
probePeriodSeconds: Yup.number().required(),
})
.nullable(),
}); });
export type ServiceFormValues = Yup.InferType<typeof validationSchema>; export type ServiceFormValues = Yup.InferType<typeof validationSchema>;

View File

@@ -0,0 +1,112 @@
import { Box } from '@/components/ui/v2/Box';
import { InfoIcon } from '@/components/ui/v2/icons/InfoIcon';
import { Input } from '@/components/ui/v2/Input';
import { Switch } from '@/components/ui/v2/Switch';
import { Text } from '@/components/ui/v2/Text';
import { Tooltip } from '@/components/ui/v2/Tooltip';
import type { ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
import { useState } from 'react';
import { useFormContext } from 'react-hook-form';
export default function HealthCheckFormSection() {
const {
watch,
setValue,
register,
formState: { errors },
} = useFormContext<ServiceFormValues>();
const healthCheck = watch('healthCheck');
const [healthCheckEnabled, setHealthCheckEnabled] = useState(!!healthCheck);
const toggleHealthCheckEnabled = async (enabled: boolean) => {
setHealthCheckEnabled(enabled);
if (!enabled) {
setValue('healthCheck', null);
}
};
return (
<Box className="space-y-4 rounded border-1 p-4">
<Box className="flex flex-row items-center justify-between ">
<Box className="flex flex-row items-center space-x-2">
<Text variant="h4" className="font-semibold">
Health Check
</Text>
<Tooltip
title={
<span>
Monitor the health and availability of a service. Refer to{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://docs.nhost.io/guides/run/health-checks"
className="underline"
>
Health Check
</a>{' '}
for more information.
</span>
}
>
<InfoIcon aria-label="Info" className="h-4 w-4" color="primary" />
</Tooltip>
</Box>
<Switch
checked={healthCheckEnabled}
onChange={(e) => toggleHealthCheckEnabled(e.target.checked)}
className="self-center"
/>
</Box>
{healthCheckEnabled && (
<Box className="flex flex-col space-y-4">
<Input
{...register(`healthCheck.port`)}
id="healthCheck.port"
label="Port"
placeholder="3000"
className="w-full"
hideEmptyHelperText
error={!!errors?.healthCheck?.port}
helperText={errors?.healthCheck?.port?.message}
fullWidth
autoComplete="off"
type="number"
/>
<Input
{...register(`healthCheck.initialDelaySeconds`)}
id="healthCheck.initialDelaySeconds"
label="Initial delay seconds"
placeholder="30"
className="w-full"
hideEmptyHelperText
error={!!errors?.healthCheck?.initialDelaySeconds}
helperText={errors?.healthCheck?.initialDelaySeconds?.message}
fullWidth
autoComplete="off"
type="number"
/>
<Input
{...register(`healthCheck.probePeriodSeconds`)}
id="healthCheck.probePeriodSeconds"
label="Probe period seconds"
placeholder="60"
className="w-full"
hideEmptyHelperText
error={!!errors?.healthCheck?.probePeriodSeconds}
helperText={errors?.healthCheck?.probePeriodSeconds?.message}
fullWidth
autoComplete="off"
type="number"
/>
</Box>
)}
</Box>
);
}

View File

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

View File

@@ -3,8 +3,15 @@ query getProjectLogs(
$service: String $service: String
$from: Timestamp $from: Timestamp
$to: Timestamp $to: Timestamp
$regexFilter: String
) { ) {
logs(appID: $appID, service: $service, from: $from, to: $to) { logs(
appID: $appID
service: $service
from: $from
to: $to
regexFilter: $regexFilter
) {
log log
service service
timestamp timestamp
@@ -15,8 +22,14 @@ subscription getLogsSubscription(
$appID: String! $appID: String!
$service: String $service: String
$from: Timestamp $from: Timestamp
$regexFilter: String
) { ) {
logs(appID: $appID, service: $service, from: $from) { logs(
appID: $appID
service: $service
from: $from
regexFilter: $regexFilter
) {
log log
service service
timestamp timestamp

View File

@@ -0,0 +1,3 @@
query getServiceLabelValues($appID: String!) {
getServiceLabelValues(appID: $appID)
}

View File

@@ -40,6 +40,11 @@ query getRunServices(
fqdn fqdn
} }
} }
healthCheck {
port
initialDelaySeconds
probePeriodSeconds
}
} }
} }
runServices_aggregate { runServices_aggregate {

View File

@@ -35,7 +35,24 @@ export default function useRemoteApplicationGQLClientWithSubscriptions() {
); );
return new ApolloClient({ return new ApolloClient({
cache: new InMemoryCache(), cache: new InMemoryCache({
typePolicies: {
Subscription: {
fields: {
logs: {
keyArgs: false,
},
},
},
Query: {
fields: {
logs: {
keyArgs: false,
},
},
},
},
}),
connectToDevTools: true, connectToDevTools: true,
link: split( link: split(
({ query }) => { ({ query }) => {

View File

@@ -2,49 +2,53 @@ import { ProjectLayout } from '@/components/layout/ProjectLayout';
import { RetryableErrorBoundary } from '@/components/presentational/RetryableErrorBoundary'; import { RetryableErrorBoundary } from '@/components/presentational/RetryableErrorBoundary';
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject'; import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
import { LogsBody } from '@/features/projects/logs/components/LogsBody'; import { LogsBody } from '@/features/projects/logs/components/LogsBody';
import { LogsHeader } from '@/features/projects/logs/components/LogsHeader'; import {
LogsHeader,
type LogsFilterFormValues,
} from '@/features/projects/logs/components/LogsHeader';
import { AvailableLogsService } from '@/features/projects/logs/utils/constants/services'; import { AvailableLogsService } from '@/features/projects/logs/utils/constants/services';
import { useRemoteApplicationGQLClientWithSubscriptions } from '@/hooks/useRemoteApplicationGQLClientWithSubscriptions'; import { useRemoteApplicationGQLClientWithSubscriptions } from '@/hooks/useRemoteApplicationGQLClientWithSubscriptions';
import { MINUTES_TO_DECREASE_FROM_CURRENT_DATE } from '@/utils/constants/common';
import { import {
GetLogsSubscriptionDocument, GetLogsSubscriptionDocument,
useGetProjectLogsQuery, useGetProjectLogsQuery,
} from '@/utils/__generated__/graphql'; } from '@/utils/__generated__/graphql';
import { subMinutes } from 'date-fns'; import { subMinutes } from 'date-fns';
import type { ReactElement } from 'react'; import {
import { useCallback, useEffect, useRef, useState } from 'react'; useCallback,
useEffect,
useRef,
useState,
type ReactElement,
} from 'react';
const MINUTES_TO_DECREASE_FROM_CURRENT_DATE = 20; interface LogsFilters {
from: Date;
to: Date | null;
service: AvailableLogsService;
regexFilter: string;
}
export default function LogsPage() { export default function LogsPage() {
const { currentProject } = useCurrentWorkspaceAndProject(); const { currentProject } = useCurrentWorkspaceAndProject();
const [fromDate, setFromDate] = useState<Date>(
subMinutes(new Date(), MINUTES_TO_DECREASE_FROM_CURRENT_DATE),
);
const [toDate, setToDate] = useState<Date | null>(new Date());
const [service, setService] = useState<AvailableLogsService>(
AvailableLogsService.ALL,
);
// create a client that sends http requests to Hasura but websocket requests to Bragi // create a client that sends http requests to Hasura but websocket requests to Bragi
const clientWithSplit = useRemoteApplicationGQLClientWithSubscriptions(); const clientWithSplit = useRemoteApplicationGQLClientWithSubscriptions();
const subscriptionReturn = useRef(null); const subscriptionReturn = useRef(null);
/** const [filters, setFilters] = useState<LogsFilters>({
* Will change the specific service from which we query logs. from: subMinutes(new Date(), MINUTES_TO_DECREASE_FROM_CURRENT_DATE),
*/ to: new Date(),
function handleServiceChange(value: AvailableLogsService) { regexFilter: '',
setService(value); service: AvailableLogsService.ALL,
} });
const { data, loading, error, subscribeToMore, client } = const { data, error, subscribeToMore, client, loading, refetch } =
useGetProjectLogsQuery({ useGetProjectLogsQuery({
variables: { variables: { appID: currentProject.id, ...filters },
appID: currentProject.id,
from: fromDate,
to: toDate,
service,
},
client: clientWithSplit, client: clientWithSplit,
fetchPolicy: 'cache-and-network',
notifyOnNetworkStatusChange: true,
}); });
const subscribeToMoreLogs = useCallback( const subscribeToMoreLogs = useCallback(
@@ -53,8 +57,9 @@ export default function LogsPage() {
document: GetLogsSubscriptionDocument, document: GetLogsSubscriptionDocument,
variables: { variables: {
appID: currentProject.id, appID: currentProject.id,
service, service: filters.service,
from: fromDate, from: filters.from,
regexFilter: filters.regexFilter,
}, },
updateQuery: (prev, { subscriptionData }) => { updateQuery: (prev, { subscriptionData }) => {
// if there is no new data, just return the previous data // if there is no new data, just return the previous data
@@ -93,40 +98,47 @@ export default function LogsPage() {
}; };
}, },
}), }),
[subscribeToMore, currentProject.id, service, fromDate], [subscribeToMore, currentProject.id, filters],
); );
useEffect(() => { useEffect(() => {
if (toDate && subscriptionReturn.current !== null) { if (filters.to && subscriptionReturn.current !== null) {
subscriptionReturn.current(); subscriptionReturn.current();
subscriptionReturn.current = null; subscriptionReturn.current = null;
return () => {}; return () => {};
} }
if (toDate) { if (filters.to) {
return () => {}; return () => {};
} }
if (subscriptionReturn.current) {
subscriptionReturn.current();
subscriptionReturn.current = null;
}
// This will open the websocket connection and it will return a function to close it. // This will open the websocket connection and it will return a function to close it.
subscriptionReturn.current = subscribeToMoreLogs(); subscriptionReturn.current = subscribeToMoreLogs();
// get rid of the current apollo client instance (will also close the websocket if it's the live status) return () => {};
return () => client.stop(); }, [filters, subscribeToMoreLogs, client]);
}, [subscribeToMoreLogs, toDate, client]);
const onSubmitFilterValues = useCallback(
async (values: LogsFilterFormValues) => {
setFilters({ ...(values as LogsFilters) });
await refetch();
},
[setFilters, refetch],
);
return ( return (
<div className="flex h-full w-full flex-col"> <div className="flex h-full w-full flex-col">
<RetryableErrorBoundary> <RetryableErrorBoundary>
<LogsHeader <LogsHeader
fromDate={fromDate} loading={loading}
toDate={toDate} onSubmitFilterValues={onSubmitFilterValues}
service={service}
onServiceChange={handleServiceChange}
onFromDateChange={setFromDate}
onToDateChange={setToDate}
/> />
<LogsBody error={error} loading={loading} logsData={data} /> <LogsBody error={error} loading={loading} logsData={data} />
</RetryableErrorBoundary> </RetryableErrorBoundary>
</div> </div>

View File

@@ -196,6 +196,7 @@ export type ConfigAppSystemConfig = {
*/ */
export type ConfigAuth = { export type ConfigAuth = {
__typename?: 'ConfigAuth'; __typename?: 'ConfigAuth';
elevatedPrivileges?: Maybe<ConfigAuthElevatedPrivileges>;
method?: Maybe<ConfigAuthMethod>; method?: Maybe<ConfigAuthMethod>;
redirections?: Maybe<ConfigAuthRedirections>; redirections?: Maybe<ConfigAuthRedirections>;
/** Resources for the service */ /** Resources for the service */
@@ -219,6 +220,7 @@ export type ConfigAuthComparisonExp = {
_and?: InputMaybe<Array<ConfigAuthComparisonExp>>; _and?: InputMaybe<Array<ConfigAuthComparisonExp>>;
_not?: InputMaybe<ConfigAuthComparisonExp>; _not?: InputMaybe<ConfigAuthComparisonExp>;
_or?: InputMaybe<Array<ConfigAuthComparisonExp>>; _or?: InputMaybe<Array<ConfigAuthComparisonExp>>;
elevatedPrivileges?: InputMaybe<ConfigAuthElevatedPrivilegesComparisonExp>;
method?: InputMaybe<ConfigAuthMethodComparisonExp>; method?: InputMaybe<ConfigAuthMethodComparisonExp>;
redirections?: InputMaybe<ConfigAuthRedirectionsComparisonExp>; redirections?: InputMaybe<ConfigAuthRedirectionsComparisonExp>;
resources?: InputMaybe<ConfigResourcesComparisonExp>; resources?: InputMaybe<ConfigResourcesComparisonExp>;
@@ -229,7 +231,28 @@ export type ConfigAuthComparisonExp = {
version?: InputMaybe<ConfigStringComparisonExp>; version?: InputMaybe<ConfigStringComparisonExp>;
}; };
export type ConfigAuthElevatedPrivileges = {
__typename?: 'ConfigAuthElevatedPrivileges';
mode?: Maybe<Scalars['String']>;
};
export type ConfigAuthElevatedPrivilegesComparisonExp = {
_and?: InputMaybe<Array<ConfigAuthElevatedPrivilegesComparisonExp>>;
_not?: InputMaybe<ConfigAuthElevatedPrivilegesComparisonExp>;
_or?: InputMaybe<Array<ConfigAuthElevatedPrivilegesComparisonExp>>;
mode?: InputMaybe<ConfigStringComparisonExp>;
};
export type ConfigAuthElevatedPrivilegesInsertInput = {
mode?: InputMaybe<Scalars['String']>;
};
export type ConfigAuthElevatedPrivilegesUpdateInput = {
mode?: InputMaybe<Scalars['String']>;
};
export type ConfigAuthInsertInput = { export type ConfigAuthInsertInput = {
elevatedPrivileges?: InputMaybe<ConfigAuthElevatedPrivilegesInsertInput>;
method?: InputMaybe<ConfigAuthMethodInsertInput>; method?: InputMaybe<ConfigAuthMethodInsertInput>;
redirections?: InputMaybe<ConfigAuthRedirectionsInsertInput>; redirections?: InputMaybe<ConfigAuthRedirectionsInsertInput>;
resources?: InputMaybe<ConfigResourcesInsertInput>; resources?: InputMaybe<ConfigResourcesInsertInput>;
@@ -808,6 +831,7 @@ export type ConfigAuthTotpUpdateInput = {
}; };
export type ConfigAuthUpdateInput = { export type ConfigAuthUpdateInput = {
elevatedPrivileges?: InputMaybe<ConfigAuthElevatedPrivilegesUpdateInput>;
method?: InputMaybe<ConfigAuthMethodUpdateInput>; method?: InputMaybe<ConfigAuthMethodUpdateInput>;
redirections?: InputMaybe<ConfigAuthRedirectionsUpdateInput>; redirections?: InputMaybe<ConfigAuthRedirectionsUpdateInput>;
resources?: InputMaybe<ConfigResourcesUpdateInput>; resources?: InputMaybe<ConfigResourcesUpdateInput>;
@@ -5238,9 +5262,9 @@ export type AuthUserProviders_Bool_Exp = {
export enum AuthUserProviders_Constraint { export enum AuthUserProviders_Constraint {
/** unique or primary key constraint on columns "id" */ /** unique or primary key constraint on columns "id" */
UserProvidersPkey = 'user_providers_pkey', UserProvidersPkey = 'user_providers_pkey',
/** unique or primary key constraint on columns "provider_id", "provider_user_id" */ /** unique or primary key constraint on columns "provider_user_id", "provider_id" */
UserProvidersProviderIdProviderUserIdKey = 'user_providers_provider_id_provider_user_id_key', UserProvidersProviderIdProviderUserIdKey = 'user_providers_provider_id_provider_user_id_key',
/** unique or primary key constraint on columns "provider_id", "user_id" */ /** unique or primary key constraint on columns "user_id", "provider_id" */
UserProvidersUserIdProviderIdKey = 'user_providers_user_id_provider_id_key' UserProvidersUserIdProviderIdKey = 'user_providers_user_id_provider_id_key'
} }
@@ -15774,6 +15798,7 @@ export type Query_Root = {
runServiceConfig?: Maybe<ConfigRunServiceConfig>; runServiceConfig?: Maybe<ConfigRunServiceConfig>;
runServiceConfigRawJSON: Scalars['String']; runServiceConfigRawJSON: Scalars['String'];
runServiceConfigs: Array<ConfigRunServiceConfigWithId>; runServiceConfigs: Array<ConfigRunServiceConfigWithId>;
runServiceConfigsAll: Array<ConfigRunServiceConfigWithId>;
/** An array relationship */ /** An array relationship */
runServices: Array<Run_Service>; runServices: Array<Run_Service>;
/** fetch aggregated fields from the table: "run_service" */ /** fetch aggregated fields from the table: "run_service" */
@@ -16755,6 +16780,12 @@ export type Query_RootRunServiceConfigRawJsonArgs = {
export type Query_RootRunServiceConfigsArgs = { export type Query_RootRunServiceConfigsArgs = {
appID: Scalars['uuid'];
resolve: Scalars['Boolean'];
};
export type Query_RootRunServiceConfigsAllArgs = {
resolve: Scalars['Boolean']; resolve: Scalars['Boolean'];
where?: InputMaybe<ConfigRunServiceConfigComparisonExp>; where?: InputMaybe<ConfigRunServiceConfigComparisonExp>;
}; };
@@ -21355,7 +21386,7 @@ export type WorkspaceMemberInvites_Bool_Exp = {
/** unique or primary key constraints on table "workspace_member_invites" */ /** unique or primary key constraints on table "workspace_member_invites" */
export enum WorkspaceMemberInvites_Constraint { export enum WorkspaceMemberInvites_Constraint {
/** unique or primary key constraint on columns "email", "workspace_id" */ /** unique or primary key constraint on columns "workspace_id", "email" */
WorkspaceMemberInvitesEmailWorkspaceIdKey = 'workspace_member_invites_email_workspace_id_key', WorkspaceMemberInvitesEmailWorkspaceIdKey = 'workspace_member_invites_email_workspace_id_key',
/** unique or primary key constraint on columns "id" */ /** unique or primary key constraint on columns "id" */
WorkspaceMemberInvitesPkey = 'workspace_member_invites_pkey' WorkspaceMemberInvitesPkey = 'workspace_member_invites_pkey'
@@ -22425,7 +22456,7 @@ export type GetAiSettingsQueryVariables = Exact<{
}>; }>;
export type GetAiSettingsQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', ai?: { __typename?: 'ConfigAI', version?: string | null, webhookSecret: string, autoEmbeddings?: { __typename?: 'ConfigAIAutoEmbeddings', synchPeriodMinutes?: any | null } | null, openai: { __typename?: 'ConfigAIOpenai', apiKey: string, organization?: string | null }, resources: { __typename?: 'ConfigAIResources', compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any } } } | null } | null }; export type GetAiSettingsQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', postgres?: { __typename?: 'ConfigPostgres', version?: string | null } | null, ai?: { __typename?: 'ConfigAI', version?: string | null, webhookSecret: string, autoEmbeddings?: { __typename?: 'ConfigAIAutoEmbeddings', synchPeriodMinutes?: any | null } | null, openai: { __typename?: 'ConfigAIOpenai', apiKey: string, organization?: string | null }, resources: { __typename?: 'ConfigAIResources', compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any } } } | null } | null };
export type GetAuthenticationSettingsQueryVariables = Exact<{ export type GetAuthenticationSettingsQueryVariables = Exact<{
appId: Scalars['uuid']; appId: Scalars['uuid'];
@@ -22772,6 +22803,7 @@ export type GetProjectLogsQueryVariables = Exact<{
service?: InputMaybe<Scalars['String']>; service?: InputMaybe<Scalars['String']>;
from?: InputMaybe<Scalars['Timestamp']>; from?: InputMaybe<Scalars['Timestamp']>;
to?: InputMaybe<Scalars['Timestamp']>; to?: InputMaybe<Scalars['Timestamp']>;
regexFilter?: InputMaybe<Scalars['String']>;
}>; }>;
@@ -22781,11 +22813,19 @@ export type GetLogsSubscriptionSubscriptionVariables = Exact<{
appID: Scalars['String']; appID: Scalars['String'];
service?: InputMaybe<Scalars['String']>; service?: InputMaybe<Scalars['String']>;
from?: InputMaybe<Scalars['Timestamp']>; from?: InputMaybe<Scalars['Timestamp']>;
regexFilter?: InputMaybe<Scalars['String']>;
}>; }>;
export type GetLogsSubscriptionSubscription = { __typename?: 'subscription_root', logs: Array<{ __typename?: 'Log', log: string, service: string, timestamp: any }> }; export type GetLogsSubscriptionSubscription = { __typename?: 'subscription_root', logs: Array<{ __typename?: 'Log', log: string, service: string, timestamp: any }> };
export type GetServiceLabelValuesQueryVariables = Exact<{
appID: Scalars['String'];
}>;
export type GetServiceLabelValuesQuery = { __typename?: 'query_root', getServiceLabelValues: Array<string> };
export type DeletePaymentMethodMutationVariables = Exact<{ export type DeletePaymentMethodMutationVariables = Exact<{
paymentMethodId: Scalars['uuid']; paymentMethodId: Scalars['uuid'];
}>; }>;
@@ -22960,7 +23000,7 @@ export type GetRunServicesQueryVariables = Exact<{
}>; }>;
export type GetRunServicesQuery = { __typename?: 'query_root', app?: { __typename?: 'apps', runServices: Array<{ __typename?: 'run_service', id: any, createdAt: any, updatedAt: any, subdomain: string, config?: { __typename?: 'ConfigRunServiceConfig', name: any, command?: Array<string> | null, image: { __typename?: 'ConfigRunServiceImage', image: string }, resources: { __typename?: 'ConfigRunServiceResources', replicas: any, compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any }, storage?: Array<{ __typename?: 'ConfigRunServiceResourcesStorage', name: any, path: string, capacity: any }> | null }, environment?: Array<{ __typename?: 'ConfigEnvironmentVariable', name: string, value: string }> | null, ports?: Array<{ __typename?: 'ConfigRunServicePort', port: any, type: string, publish?: boolean | null, ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null }> | null } | null }>, runServices_aggregate: { __typename?: 'run_service_aggregate', aggregate?: { __typename?: 'run_service_aggregate_fields', count: number } | null } } | null }; export type GetRunServicesQuery = { __typename?: 'query_root', app?: { __typename?: 'apps', runServices: Array<{ __typename?: 'run_service', id: any, createdAt: any, updatedAt: any, subdomain: string, config?: { __typename?: 'ConfigRunServiceConfig', name: any, command?: Array<string> | null, image: { __typename?: 'ConfigRunServiceImage', image: string }, resources: { __typename?: 'ConfigRunServiceResources', replicas: any, compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any }, storage?: Array<{ __typename?: 'ConfigRunServiceResourcesStorage', name: any, path: string, capacity: any }> | null }, environment?: Array<{ __typename?: 'ConfigEnvironmentVariable', name: string, value: string }> | null, ports?: Array<{ __typename?: 'ConfigRunServicePort', port: any, type: string, publish?: boolean | null, ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null }> | null, healthCheck?: { __typename?: 'ConfigHealthCheck', port: any, initialDelaySeconds?: number | null, probePeriodSeconds?: number | null } | null } | null }>, runServices_aggregate: { __typename?: 'run_service_aggregate', aggregate?: { __typename?: 'run_service_aggregate_fields', count: number } | null } } | null };
export type InsertRunServiceMutationVariables = Exact<{ export type InsertRunServiceMutationVariables = Exact<{
object: Run_Service_Insert_Input; object: Run_Service_Insert_Input;
@@ -23524,6 +23564,9 @@ export type DeletePersonalAccessTokenMutationOptions = Apollo.BaseMutationOption
export const GetAiSettingsDocument = gql` export const GetAiSettingsDocument = gql`
query GetAISettings($appId: uuid!) { query GetAISettings($appId: uuid!) {
config(appID: $appId, resolve: false) { config(appID: $appId, resolve: false) {
postgres {
version
}
ai { ai {
version version
webhookSecret webhookSecret
@@ -25558,8 +25601,14 @@ export function refetchGetGithubRepositoriesQuery(variables?: GetGithubRepositor
return { query: GetGithubRepositoriesDocument, variables: variables } return { query: GetGithubRepositoriesDocument, variables: variables }
} }
export const GetProjectLogsDocument = gql` export const GetProjectLogsDocument = gql`
query getProjectLogs($appID: String!, $service: String, $from: Timestamp, $to: Timestamp) { query getProjectLogs($appID: String!, $service: String, $from: Timestamp, $to: Timestamp, $regexFilter: String) {
logs(appID: $appID, service: $service, from: $from, to: $to) { logs(
appID: $appID
service: $service
from: $from
to: $to
regexFilter: $regexFilter
) {
log log
service service
timestamp timestamp
@@ -25583,6 +25632,7 @@ export const GetProjectLogsDocument = gql`
* service: // value for 'service' * service: // value for 'service'
* from: // value for 'from' * from: // value for 'from'
* to: // value for 'to' * to: // value for 'to'
* regexFilter: // value for 'regexFilter'
* }, * },
* }); * });
*/ */
@@ -25601,8 +25651,8 @@ export function refetchGetProjectLogsQuery(variables: GetProjectLogsQueryVariabl
return { query: GetProjectLogsDocument, variables: variables } return { query: GetProjectLogsDocument, variables: variables }
} }
export const GetLogsSubscriptionDocument = gql` export const GetLogsSubscriptionDocument = gql`
subscription getLogsSubscription($appID: String!, $service: String, $from: Timestamp) { subscription getLogsSubscription($appID: String!, $service: String, $from: Timestamp, $regexFilter: String) {
logs(appID: $appID, service: $service, from: $from) { logs(appID: $appID, service: $service, from: $from, regexFilter: $regexFilter) {
log log
service service
timestamp timestamp
@@ -25625,6 +25675,7 @@ export const GetLogsSubscriptionDocument = gql`
* appID: // value for 'appID' * appID: // value for 'appID'
* service: // value for 'service' * service: // value for 'service'
* from: // value for 'from' * from: // value for 'from'
* regexFilter: // value for 'regexFilter'
* }, * },
* }); * });
*/ */
@@ -25634,6 +25685,42 @@ export function useGetLogsSubscriptionSubscription(baseOptions: Apollo.Subscript
} }
export type GetLogsSubscriptionSubscriptionHookResult = ReturnType<typeof useGetLogsSubscriptionSubscription>; export type GetLogsSubscriptionSubscriptionHookResult = ReturnType<typeof useGetLogsSubscriptionSubscription>;
export type GetLogsSubscriptionSubscriptionResult = Apollo.SubscriptionResult<GetLogsSubscriptionSubscription>; export type GetLogsSubscriptionSubscriptionResult = Apollo.SubscriptionResult<GetLogsSubscriptionSubscription>;
export const GetServiceLabelValuesDocument = gql`
query getServiceLabelValues($appID: String!) {
getServiceLabelValues(appID: $appID)
}
`;
/**
* __useGetServiceLabelValuesQuery__
*
* To run a query within a React component, call `useGetServiceLabelValuesQuery` and pass it any options that fit your needs.
* When your component renders, `useGetServiceLabelValuesQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetServiceLabelValuesQuery({
* variables: {
* appID: // value for 'appID'
* },
* });
*/
export function useGetServiceLabelValuesQuery(baseOptions: Apollo.QueryHookOptions<GetServiceLabelValuesQuery, GetServiceLabelValuesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetServiceLabelValuesQuery, GetServiceLabelValuesQueryVariables>(GetServiceLabelValuesDocument, options);
}
export function useGetServiceLabelValuesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetServiceLabelValuesQuery, GetServiceLabelValuesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetServiceLabelValuesQuery, GetServiceLabelValuesQueryVariables>(GetServiceLabelValuesDocument, options);
}
export type GetServiceLabelValuesQueryHookResult = ReturnType<typeof useGetServiceLabelValuesQuery>;
export type GetServiceLabelValuesLazyQueryHookResult = ReturnType<typeof useGetServiceLabelValuesLazyQuery>;
export type GetServiceLabelValuesQueryResult = Apollo.QueryResult<GetServiceLabelValuesQuery, GetServiceLabelValuesQueryVariables>;
export function refetchGetServiceLabelValuesQuery(variables: GetServiceLabelValuesQueryVariables) {
return { query: GetServiceLabelValuesDocument, variables: variables }
}
export const DeletePaymentMethodDocument = gql` export const DeletePaymentMethodDocument = gql`
mutation deletePaymentMethod($paymentMethodId: uuid!) { mutation deletePaymentMethod($paymentMethodId: uuid!) {
deletePaymentMethod(id: $paymentMethodId) { deletePaymentMethod(id: $paymentMethodId) {
@@ -26577,6 +26664,11 @@ export const GetRunServicesDocument = gql`
fqdn fqdn
} }
} }
healthCheck {
port
initialDelaySeconds
probePeriodSeconds
}
} }
} }
runServices_aggregate { runServices_aggregate {

View File

@@ -66,3 +66,8 @@ export const RESOURCE_VCPU_PRICE_PER_MINUTE = 0.0012;
* Maximum number of free projects a user is allowed to have. * Maximum number of free projects a user is allowed to have.
*/ */
export const MAX_FREE_PROJECTS = 1; export const MAX_FREE_PROJECTS = 1;
/**
* Default value in minutes to use for querying the logs
*/
export const MINUTES_TO_DECREASE_FROM_CURRENT_DATE = 20;

View File

@@ -21,6 +21,9 @@ module.exports = {
copper: '#DD792D', copper: '#DD792D',
paper: '#171d26', paper: '#171d26',
divider: '#2f363d', divider: '#2f363d',
'primary-main': '#0052cd',
'primary-light': '#ebf3ff',
'primary-dark': '#063799',
}, },
boxShadow: { boxShadow: {
outline: 'inset 0 0 0 2px rgba(0, 82, 205, 0.6)', outline: 'inset 0 0 0 2px rgba(0, 82, 205, 0.6)',

View File

@@ -1,5 +1,11 @@
# @nhost/docs # @nhost/docs
## 2.7.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 2.6.0 ## 2.6.0
### Minor Changes ### Minor Changes

View File

@@ -1,11 +1,11 @@
{ {
"name": "@nhost/docs", "name": "@nhost/docs",
"version": "2.6.0", "version": "2.7.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "mintlify dev" "start": "mintlify dev"
}, },
"devDependencies": { "devDependencies": {
"mintlify": "^4.0.121" "mintlify": "^4.0.128"
} }
} }

View File

@@ -1,5 +1,15 @@
# @nhost-examples/cli # @nhost-examples/cli
## 0.2.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 0.1.9 ## 0.1.9
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/cli", "name": "@nhost-examples/cli",
"version": "0.1.9", "version": "0.2.0",
"main": "src/index.mjs", "main": "src/index.mjs",
"private": true, "private": true,
"scripts": { "scripts": {
@@ -9,10 +9,10 @@
"dependencies": { "dependencies": {
"@nhost/nhost-js": "workspace:^", "@nhost/nhost-js": "workspace:^",
"commander": "^10.0.1", "commander": "^10.0.1",
"dotenv": "^16.4.1", "dotenv": "^16.4.5",
"graphql": "16.8.1", "graphql": "16.8.1",
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"pino": "^8.17.2" "pino": "^8.19.0"
}, },
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=16.0.0"

View File

@@ -1,5 +1,17 @@
# @nhost-examples/codegen-react-apollo # @nhost-examples/codegen-react-apollo
## 0.2.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react-apollo@10.0.0
- @nhost/react@3.3.0
## 0.1.17 ## 0.1.17
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/codegen-react-apollo", "name": "@nhost-examples/codegen-react-apollo",
"version": "0.1.17", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"codegen": "graphql-codegen", "codegen": "graphql-codegen",
@@ -15,7 +15,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@nhost/react": "workspace:^", "@nhost/react": "workspace:^",
"@nhost/react-apollo": "workspace:^", "@nhost/react-apollo": "workspace:^",
"clsx": "^1.2.1", "clsx": "^1.2.1",
@@ -28,14 +28,14 @@
"@graphql-codegen/client-preset": "^1.3.0", "@graphql-codegen/client-preset": "^1.3.0",
"@graphql-typed-document-node/core": "^3.2.0", "@graphql-typed-document-node/core": "^3.2.0",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@types/node": "^18.19.12", "@types/node": "^18.19.21",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.19",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^5.0.12" "vite": "^5.1.4"
} }
} }

View File

@@ -1,5 +1,16 @@
# @nhost-examples/codegen-react-query # @nhost-examples/codegen-react-query
## 0.2.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react@3.3.0
## 0.1.18 ## 0.1.18
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/codegen-react-query", "name": "@nhost-examples/codegen-react-query",
"version": "0.1.18", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"codegen": "graphql-codegen", "codegen": "graphql-codegen",
@@ -29,14 +29,14 @@
"@graphql-codegen/client-preset": "^1.3.0", "@graphql-codegen/client-preset": "^1.3.0",
"@graphql-typed-document-node/core": "^3.2.0", "@graphql-typed-document-node/core": "^3.2.0",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.19",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^5.0.12" "vite": "^5.1.4"
} }
} }

View File

@@ -1,5 +1,17 @@
# @nhost-examples/react-urql # @nhost-examples/react-urql
## 0.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react-urql@7.0.0
- @nhost/react@3.3.0
## 0.0.14 ## 0.0.14
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@nhost-examples/codegen-react-urql", "name": "@nhost-examples/codegen-react-urql",
"private": true, "private": true,
"version": "0.0.14", "version": "0.1.0",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
@@ -22,14 +22,14 @@
"@graphql-codegen/client-preset": "^1.3.0", "@graphql-codegen/client-preset": "^1.3.0",
"@graphql-typed-document-node/core": "^3.2.0", "@graphql-typed-document-node/core": "^3.2.0",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.19",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^5.0.12" "vite": "^5.1.4"
} }
} }

View File

@@ -1,5 +1,11 @@
# @nhost-examples/docker-compose # @nhost-examples/docker-compose
## 0.2.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 0.1.1 ## 0.1.1
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/docker-compose", "name": "@nhost-examples/docker-compose",
"version": "0.1.1", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"e2e": "vitest run" "e2e": "vitest run"

View File

@@ -1,76 +1,7 @@
import { exec } from 'child_process' import { describe, it } from 'vitest'
import fetch from 'cross-fetch'
import { promisify } from 'util'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
const promisifiedExec = promisify(exec) describe('Empty Test Suite', () => {
it('Empty Test', async () => {
describe( // This test does nothing and will always pass
'docker-compose should start, work and stop', })
() => { })
beforeAll(async () => {
// * Start docker compose
await promisifiedExec(
'docker compose -f docker-compose.yaml --env-file .env.example up --wait --wait-timeout 300 --quiet-pull'
)
// we wait a bit extra because sometimes traefik takes a bit to configure the services
setTimeout(() => {}, 30000);
}, 5 * 60 * 1000)
afterAll(async () => {
// * Stop docker compose
await promisifiedExec('docker compose -f docker-compose.yaml --env-file .env.example down')
}, 5 * 60 * 1000)
it(
'Hasura',
async () => {
await expect(
fetch('http://localhost:1337/healthz').then((res) => res.status)
).resolves.toEqual(200)
},
{ retry: 60, timeout: 1000 }
)
it(
'Hasura auth',
async () => {
await expect(
fetch('http://localhost:1337/v1/auth/healthz').then((res) => res.status)
).resolves.toEqual(200)
},
{ retry: 60, timeout: 1000 }
)
it(
'Hasura storage',
async () => {
await expect(
fetch('http://localhost:1337/v1/storage/version').then((res) => res.status)
).resolves.toEqual(200)
},
{ retry: 60, timeout: 1000 }
)
it(
'Serverless functions',
async () => {
await expect(
fetch('http://localhost:1337/v1/functions/hello').then((res) => res.status)
).resolves.toEqual(200)
},
{ retry: 60, timeout: 1000 }
)
it(
'Dashboard',
async () => {
await expect(fetch('http://localhost:3030').then((res) => res.status)).resolves.toEqual(200)
},
{ retry: 60, timeout: 1000 }
)
},
{ timeout: 5 * 60 * 1000 }
)

View File

@@ -1,5 +1,15 @@
# @nhost-examples/multi-tenant-one-to-many # @nhost-examples/multi-tenant-one-to-many
## 2.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 2.0.7 ## 2.0.7
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@nhost-examples/multi-tenant-one-to-many", "name": "@nhost-examples/multi-tenant-one-to-many",
"private": true, "private": true,
"version": "2.0.7", "version": "2.1.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": {}, "scripts": {},
@@ -10,7 +10,7 @@
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"express": "^4.18.2", "express": "^4.18.3",
"typescript": "^4.9.5" "typescript": "^4.9.5"
}, },
"dependencies": { "dependencies": {

View File

@@ -1,5 +1,18 @@
# @nhost-examples/nextjs # @nhost-examples/nextjs
## 0.2.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react-apollo@10.0.0
- @nhost/react@3.3.0
- @nhost/nextjs@2.1.6
## 0.1.19 ## 0.1.19
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/nextjs", "name": "@nhost-examples/nextjs",
"version": "0.1.19", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -15,7 +15,7 @@
"verify:fix": "run-p prettier:fix lint:fix" "verify:fix": "run-p prettier:fix lint:fix"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@mantine/core": "^4.2.12", "@mantine/core": "^4.2.12",
"@mantine/hooks": "^4.2.12", "@mantine/hooks": "^4.2.12",
"@mantine/next": "^4.2.12", "@mantine/next": "^4.2.12",
@@ -31,8 +31,8 @@
}, },
"devDependencies": { "devDependencies": {
"@next/bundle-analyzer": "^12.3.4", "@next/bundle-analyzer": "^12.3.4",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@xstate/inspect": "^0.6.5", "@xstate/inspect": "^0.6.5",
"eslint-config-next": "12.0.10", "eslint-config-next": "12.0.10",
"typescript": "^4.9.5", "typescript": "^4.9.5",

View File

@@ -1,5 +1,15 @@
# @nhost-examples/node-storage # @nhost-examples/node-storage
## 0.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 0.0.11 ## 0.0.11
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/node-storage", "name": "@nhost-examples/node-storage",
"version": "0.0.11", "version": "0.1.0",
"private": true, "private": true,
"description": "This is an example of how to use the Storage with Node.js", "description": "This is an example of how to use the Storage with Node.js",
"main": "src/index.mjs", "main": "src/index.mjs",
@@ -12,14 +12,14 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@nhost/nhost-js": "workspace:^", "@nhost/nhost-js": "workspace:^",
"dotenv": "^16.4.1", "dotenv": "^16.4.5",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"uuid": "^9.0.1" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.19.12", "@types/node": "^18.19.21",
"@types/uuid": "^9.0.8" "@types/uuid": "^9.0.8"
} }
} }

View File

@@ -1,5 +1,15 @@
# @nhost-examples/nextjs-server-components # @nhost-examples/nextjs-server-components
## 0.3.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 0.2.5 ## 0.2.5
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/nextjs-server-components", "name": "@nhost-examples/nextjs-server-components",
"version": "0.2.5", "version": "0.3.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -9,7 +9,7 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@nhost/nhost-js": "workspace:^", "@nhost/nhost-js": "workspace:^",
"autoprefixer": "10.4.15", "autoprefixer": "10.4.15",
"cookies-next": "^3.0.0", "cookies-next": "^3.0.0",
@@ -19,7 +19,7 @@
"graphql": "16.8.1", "graphql": "16.8.1",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"next": "^14.1.0", "next": "^14.1.0",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"tailwind-merge": "^1.14.0", "tailwind-merge": "^1.14.0",
@@ -30,7 +30,7 @@
"devDependencies": { "devDependencies": {
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/node": "20.5.6", "@types/node": "20.5.6",
"@types/react": "^18.2.47", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.7" "@types/react-dom": "^18.2.19"
} }
} }

View File

@@ -1,5 +1,10 @@
--- ---
## 0.3.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 0.2.3 ## 0.2.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/sveltekit", "name": "@nhost-examples/sveltekit",
"version": "0.2.3", "version": "0.3.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
@@ -16,22 +16,22 @@
}, },
"devDependencies": { "devDependencies": {
"@nhost/nhost-js": "2.2.18", "@nhost/nhost-js": "2.2.18",
"@playwright/test": "^1.41.1", "@playwright/test": "^1.42.0",
"@sveltejs/adapter-auto": "^2.1.1", "@sveltejs/adapter-auto": "^2.1.1",
"@sveltejs/kit": "^1.30.3", "@sveltejs/kit": "^1.30.4",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0", "eslint-config-prettier": "^8.10.0",
"eslint-plugin-svelte": "^2.35.1", "eslint-plugin-svelte": "^2.35.1",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^2.10.1",
"svelte": "^3.59.2", "svelte": "^3.59.2",
"svelte-check": "^3.6.3", "svelte-check": "^3.6.6",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite": "^5.0.12", "vite": "^5.1.4",
"vitest": "^0.25.8" "vitest": "^0.25.8"
}, },
"type": "module", "type": "module",

View File

@@ -1,5 +1,23 @@
# @nhost-examples/react-apollo # @nhost-examples/react-apollo
## 0.4.1
### Patch Changes
- 4f3fb34: fix: set redirectTo when doing sign in with github and include vercel previews in allowed redirect URLs
## 0.4.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react-apollo@10.0.0
- @nhost/react@3.3.0
## 0.3.3 ## 0.3.3
### Patch Changes ### Patch Changes

View File

@@ -35,7 +35,7 @@ mode = 'required'
[auth.redirections] [auth.redirections]
clientUrl = 'https://react-apollo.example.nhost.io/' clientUrl = 'https://react-apollo.example.nhost.io/'
allowedUrls = ['https://react-apollo.example.nhost.io/profile', 'http://localhost:3000'] allowedUrls = ['https://react-apollo.example.nhost.io/profile', 'https://vue-apollo.example.nhost.io/profile', 'https://*.vercel.app','http://localhost:3000']
[auth.signUp] [auth.signUp]
enabled = true enabled = true

View File

@@ -1,9 +1,9 @@
{ {
"name": "@nhost-examples/react-apollo", "name": "@nhost-examples/react-apollo",
"version": "0.3.3", "version": "0.4.1",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@mantine/core": "^4.2.12", "@mantine/core": "^4.2.12",
"@mantine/dropzone": "^4.2.12", "@mantine/dropzone": "^4.2.12",
"@mantine/hooks": "^4.2.12", "@mantine/hooks": "^4.2.12",
@@ -15,8 +15,8 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^4.12.0", "react-icons": "^4.12.0",
"react-router": "^6.21.3", "react-router": "^6.22.2",
"react-router-dom": "^6.21.3", "react-router-dom": "^6.22.2",
"tabler-icons-react": "^1.56.0" "tabler-icons-react": "^1.56.0"
}, },
"scripts": { "scripts": {
@@ -54,17 +54,17 @@
"@nuintun/qrcode": "^3.4.0", "@nuintun/qrcode": "^3.4.0",
"@playwright/test": "1.31.0", "@playwright/test": "1.31.0",
"@types/pngjs": "^6.0.4", "@types/pngjs": "^6.0.4",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.19",
"@types/totp-generator": "^0.0.4", "@types/totp-generator": "^0.0.4",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
"@xstate/inspect": "^0.6.5", "@xstate/inspect": "^0.6.5",
"dotenv": "^16.4.1", "dotenv": "^16.4.5",
"jsqr": "^1.4.0", "jsqr": "^1.4.0",
"pngjs": "^7.0.0", "pngjs": "^7.0.0",
"totp-generator": "^0.0.13", "totp-generator": "^0.0.13",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^5.0.12", "vite": "^5.1.4",
"ws": "^8.16.0", "ws": "^8.16.0",
"xstate": "^4.38.3" "xstate": "^4.38.3"
} }

View File

@@ -1,5 +1,16 @@
# @nhost-examples/react-gqty # @nhost-examples/react-gqty
## 1.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react@3.3.0
## 1.0.7 ## 1.0.7
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@nhost-examples/react-gqty", "name": "@nhost-examples/react-gqty",
"private": true, "private": true,
"version": "1.0.7", "version": "1.1.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -20,13 +20,13 @@
"devDependencies": { "devDependencies": {
"@gqty/cli": "3.3.0-alpha-d8cdbf6.0", "@gqty/cli": "3.3.0-alpha-d8cdbf6.0",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.19",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^5.0.12" "vite": "^5.1.4"
} }
} }

View File

@@ -1,5 +1,16 @@
# @nhost-examples/serverless-functions # @nhost-examples/serverless-functions
## 0.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/stripe-graphql-js@1.1.0
## 0.0.11 ## 0.0.11
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@nhost-examples/serverless-functions", "name": "@nhost-examples/serverless-functions",
"private": true, "private": true,
"version": "0.0.11", "version": "0.1.0",
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.21" "@types/express": "^4.17.21"
}, },
@@ -11,7 +11,7 @@
"@pothos/core": "^3.41.0", "@pothos/core": "^3.41.0",
"cross-fetch": "^3.1.8", "cross-fetch": "^3.1.8",
"graphql": "16.8.1", "graphql": "16.8.1",
"nodemailer": "^6.9.9", "nodemailer": "^6.9.11",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"stripe": "^11.18.0" "stripe": "^11.18.0"
} }

View File

@@ -1,5 +1,24 @@
# @nhost-examples/vue-apollo # @nhost-examples/vue-apollo
## 0.3.1
### Patch Changes
- 4f3fb34: fix: set redirectTo when doing sign in with github and include vercel previews in allowed redirect URLs
## 0.3.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/apollo@6.1.0
- @nhost/vue@2.3.0
- @nhost/nhost-js@3.0.8
## 0.2.4 ## 0.2.4
### Patch Changes ### Patch Changes

View File

@@ -35,7 +35,7 @@ mode = 'required'
[auth.redirections] [auth.redirections]
clientUrl = 'https://vue-apollo.example.nhost.io' clientUrl = 'https://vue-apollo.example.nhost.io'
allowedUrls = ['https://vue-apollo.example.nhost.io/profile', 'http://localhost:5173'] allowedUrls = ['https://vue-apollo.example.nhost.io/profile', 'https://react-apollo.example.nhost.io/profile', 'https://*.vercel.app','http://localhost:5173']
[auth.signUp] [auth.signUp]
enabled = true enabled = true

View File

@@ -1,7 +1,7 @@
{ {
"name": "@nhost-examples/vue-apollo", "name": "@nhost-examples/vue-apollo",
"private": true, "private": true,
"version": "0.2.4", "version": "0.3.1",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
@@ -14,7 +14,7 @@
"verify:fix": "run-p prettier:fix lint:fix" "verify:fix": "run-p prettier:fix lint:fix"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@mdi/font": "5.9.55", "@mdi/font": "5.9.55",
"@nhost/apollo": "workspace:^", "@nhost/apollo": "workspace:^",
"@nhost/nhost-js": "workspace:^", "@nhost/nhost-js": "workspace:^",
@@ -24,8 +24,8 @@
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"roboto-fontface": "^0.10.0", "roboto-fontface": "^0.10.0",
"vite-plugin-vuetify": "^1.0.2", "vite-plugin-vuetify": "^1.0.2",
"vue": "^3.4.15", "vue": "^3.4.21",
"vue-router": "^4.2.5", "vue-router": "^4.3.0",
"vue3-dropzone": "^2.2.1", "vue3-dropzone": "^2.2.1",
"vuetify": "3.0.0-beta.10", "vuetify": "3.0.0-beta.10",
"webfontloader": "^1.6.28" "webfontloader": "^1.6.28"
@@ -37,7 +37,7 @@
"@xstate/inspect": "^0.6.5", "@xstate/inspect": "^0.6.5",
"sass": "1.32.0", "sass": "1.32.0",
"typescript": "4.9.4", "typescript": "4.9.4",
"vite": "^5.0.12", "vite": "^5.1.4",
"vue-tsc": "^0.38.9" "vue-tsc": "^0.38.9"
}, },
"eslintConfig": { "eslintConfig": {

View File

@@ -15,5 +15,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useProviderLink } from '@nhost/vue' import { useProviderLink } from '@nhost/vue'
const { github } = useProviderLink({ redirectTo: '/' }) const { github } = useProviderLink({ redirectTo: window.location.origin })
</script> </script>

View File

@@ -1,5 +1,17 @@
# @nhost-examples/vue-quickstart # @nhost-examples/vue-quickstart
## 0.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/apollo@6.1.0
- @nhost/vue@2.3.0
## 0.0.16 ## 0.0.16
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost-examples/vue-quickstart", "name": "@nhost-examples/vue-quickstart",
"version": "0.0.16", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "vite build", "build": "vite build",
@@ -11,31 +11,31 @@
"test": "vitest" "test": "vitest"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@nhost/apollo": "workspace:^", "@nhost/apollo": "workspace:^",
"@nhost/vue": "workspace:^", "@nhost/vue": "workspace:^",
"@vue/apollo-composable": "4.0.0-alpha.18", "@vue/apollo-composable": "4.0.0-alpha.18",
"@vueuse/core": "^8.9.4", "@vueuse/core": "^8.9.4",
"graphql": "16.8.1", "graphql": "16.8.1",
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"vue": "^3.4.15", "vue": "^3.4.21",
"vue-router": "^4.2.5" "vue-router": "^4.3.0"
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^0.23.1", "@antfu/eslint-config": "^0.23.1",
"@iconify-json/carbon": "^1.1.28", "@iconify-json/carbon": "^1.1.30",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@unocss/reset": "^0.33.5", "@unocss/reset": "^0.33.5",
"@vitejs/plugin-vue": "^4.6.2", "@vitejs/plugin-vue": "^4.6.2",
"@vue/test-utils": "^2.4.4", "@vue/test-utils": "^2.4.4",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"jsdom": "^19.0.0", "jsdom": "^19.0.0",
"pnpm": "^7.33.6", "pnpm": "^7.33.7",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"unocss": "^0.33.5", "unocss": "^0.33.5",
"unplugin-auto-import": "^0.17.5", "unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0", "unplugin-vue-components": "^0.26.0",
"vite": "^5.0.12", "vite": "^5.1.4",
"vite-plugin-pages": "^0.28.0", "vite-plugin-pages": "^0.28.0",
"vue-tsc": "^0.38.9" "vue-tsc": "^0.38.9"
} }

12
flake.lock generated
View File

@@ -40,11 +40,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1706370404, "lastModified": 1709101436,
"narHash": "sha256-AVvfQjv6hqGYEBoMQZrKpNP6Rpt+wHqZ4Ua3wHCkyHE=", "narHash": "sha256-77w34voAwaCYDnXTpe6cXDDFEMOcXbAhXWsO38YUHmE=",
"owner": "nhost", "owner": "nhost",
"repo": "nixops", "repo": "nixops",
"rev": "87f104eaf826981e6352daa1fb14e4f363ceee96", "rev": "9ae747fefe6bb611d115de2f5d2a04a22dc324b2",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -55,11 +55,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1706173671, "lastModified": 1708943256,
"narHash": "sha256-lciR7kQUK2FCAYuszyd7zyRRmTaXVeoZsCyK6QFpGdk=", "narHash": "sha256-K9VeHrhXsigdhNMZ8hqAk7jtRy4ollqhkYYNZqbfssg=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "4fddc9be4eaf195d631333908f2a454b03628ee5", "rev": "fcea2b6260dd566c28c894b4207a5f2b56c2cba3",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -1,5 +1,15 @@
# @nhost/apollo # @nhost/apollo
## 6.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 6.0.8 ## 6.0.8
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/apollo", "name": "@nhost/apollo",
"version": "6.0.8", "version": "6.1.0",
"description": "Nhost Apollo Client library", "description": "Nhost Apollo Client library",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -65,11 +65,11 @@
}, },
"dependencies": { "dependencies": {
"graphql": "16.8.1", "graphql": "16.8.1",
"graphql-ws": "^5.14.3", "graphql-ws": "^5.15.0",
"jwt-decode": "^3.1.2" "jwt-decode": "^3.1.2"
}, },
"devDependencies": { "devDependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@nhost/nhost-js": "workspace:*" "@nhost/nhost-js": "workspace:*"
} }
} }

View File

@@ -1,5 +1,11 @@
# @nhost/google-translation # @nhost/google-translation
## 0.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 0.0.8 ## 0.0.8
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/google-translation", "name": "@nhost/google-translation",
"version": "0.0.8", "version": "0.1.0",
"description": "Google Translation GraphQL API", "description": "Google Translation GraphQL API",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -48,8 +48,8 @@
"graphql-request": "^6.1.0" "graphql-request": "^6.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"dotenv": "^16.4.1", "dotenv": "^16.4.5",
"typescript": "^4.9.5" "typescript": "^4.9.5"
} }
} }

View File

@@ -1,5 +1,17 @@
# @nhost/react-apollo # @nhost/react-apollo
## 10.0.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/apollo@6.1.0
- @nhost/react@3.3.0
## 9.0.3 ## 9.0.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/react-apollo", "name": "@nhost/react-apollo",
"version": "9.0.3", "version": "10.0.0",
"description": "Nhost React Apollo client", "description": "Nhost React Apollo client",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -71,9 +71,9 @@
"react-dom": "^17.0.0 || ^18.0.0" "react-dom": "^17.0.0 || ^18.0.0"
}, },
"devDependencies": { "devDependencies": {
"@apollo/client": "^3.9.4", "@apollo/client": "^3.9.5",
"@nhost/react": "workspace:*", "@nhost/react": "workspace:*",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"graphql": "16.8.1", "graphql": "16.8.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"

View File

@@ -1,5 +1,16 @@
# @nhost/react-urql # @nhost/react-urql
## 7.0.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react@3.3.0
## 6.0.3 ## 6.0.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/react-urql", "name": "@nhost/react-urql",
"version": "6.0.3", "version": "7.0.0",
"description": "Nhost React URQL client", "description": "Nhost React URQL client",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -61,7 +61,7 @@
"dependencies": { "dependencies": {
"@urql/devtools": "^2.0.3", "@urql/devtools": "^2.0.3",
"@urql/exchange-refocus": "^1.0.2", "@urql/exchange-refocus": "^1.0.2",
"graphql-ws": "^5.14.3" "graphql-ws": "^5.15.0"
}, },
"peerDependencies": { "peerDependencies": {
"@nhost/react": "workspace:*", "@nhost/react": "workspace:*",
@@ -72,7 +72,7 @@
}, },
"devDependencies": { "devDependencies": {
"@nhost/react": "workspace:*", "@nhost/react": "workspace:*",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"graphql": "16.8.1", "graphql": "16.8.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

View File

@@ -1,5 +1,11 @@
# @nhost/stripe-graphql-js # @nhost/stripe-graphql-js
## 1.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 1.0.7 ## 1.0.7
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/stripe-graphql-js", "name": "@nhost/stripe-graphql-js",
"version": "1.0.7", "version": "1.1.0",
"description": "Stripe GraphQL API", "description": "Stripe GraphQL API",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -42,15 +42,15 @@
"dependencies": { "dependencies": {
"@pothos/core": "^3.41.0", "@pothos/core": "^3.41.0",
"graphql": "16.8.1", "graphql": "16.8.1",
"graphql-scalars": "^1.22.4", "graphql-scalars": "^1.22.5",
"graphql-yoga": "^3.9.1", "graphql-yoga": "^3.9.1",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"stripe": "^11.18.0" "stripe": "^11.18.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jsonwebtoken": "^9.0.5", "@types/jsonwebtoken": "^9.0.6",
"@types/node": "^18.19.12", "@types/node": "^18.19.21",
"dotenv": "^16.4.1", "dotenv": "^16.4.5",
"ts-node-dev": "^2.0.0", "ts-node-dev": "^2.0.0",
"typescript": "^4.9.5" "typescript": "^4.9.5"
} }

View File

@@ -54,20 +54,20 @@
"dashboard" "dashboard"
], ],
"devDependencies": { "devDependencies": {
"@babel/core": "^7.23.9", "@babel/core": "^7.24.0",
"@babel/eslint-parser": "^7.23.10", "@babel/eslint-parser": "^7.23.10",
"@babel/plugin-syntax-flow": "^7.23.3", "@babel/plugin-syntax-flow": "^7.23.3",
"@babel/plugin-transform-react-jsx": "^7.23.4", "@babel/plugin-transform-react-jsx": "^7.23.4",
"@changesets/cli": "^2.27.1", "@changesets/cli": "^2.27.1",
"@faker-js/faker": "^7.6.0", "@faker-js/faker": "^7.6.0",
"@rollup/plugin-replace": "^5.0.5", "@rollup/plugin-replace": "^5.0.5",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0", "@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^0.32.4", "@vitest/coverage-v8": "^0.32.4",
"audit-ci": "^6.6.1", "audit-ci": "^6.6.1",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
@@ -76,15 +76,15 @@
"eslint-plugin-promise": "^6.1.1", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-vue": "^9.21.1", "eslint-plugin-vue": "^9.22.0",
"husky": "^8.0.3", "husky": "^8.0.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"turbo": "1.11.3", "turbo": "1.11.3",
"typedoc": "^0.22.18", "typedoc": "^0.22.18",
"typescript": "4.9.5", "typescript": "4.9.5",
"vite": "^5.0.12", "vite": "^5.1.4",
"vite-plugin-dts": "^3.7.2", "vite-plugin-dts": "^3.7.3",
"vite-tsconfig-paths": "^4.3.1", "vite-tsconfig-paths": "^4.3.1",
"vitest": "^0.32.4" "vitest": "^0.32.4"
}, },

View File

@@ -1,5 +1,11 @@
# @nhost/docgen # @nhost/docgen
## 0.2.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 0.1.13 ## 0.1.13
### Patch Changes ### Patch Changes

View File

@@ -2,7 +2,7 @@
"name": "@nhost/docgen", "name": "@nhost/docgen",
"description": "Documentation generator for classes and functions", "description": "Documentation generator for classes and functions",
"private": true, "private": true,
"version": "0.1.13", "version": "0.2.0",
"license": "MIT", "license": "MIT",
"main": "dist/index.cjs.js", "main": "dist/index.cjs.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
@@ -33,7 +33,7 @@
"docgen": "dist/index.js" "docgen": "dist/index.js"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@types/prettier": "^2.7.3", "@types/prettier": "^2.7.3",
"rimraf": "^5.0.5", "rimraf": "^5.0.5",
"typescript": "^4.9.5" "typescript": "^4.9.5"
@@ -43,6 +43,6 @@
"commander": "^11.1.0", "commander": "^11.1.0",
"just-kebab-case": "^4.2.0", "just-kebab-case": "^4.2.0",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"valtio": "^1.13.0" "valtio": "^1.13.1"
} }
} }

View File

@@ -1,5 +1,12 @@
# @nhost/nextjs # @nhost/nextjs
## 2.1.6
### Patch Changes
- Updated dependencies [49a80c2]
- @nhost/react@3.3.0
## 2.1.5 ## 2.1.5
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/nextjs", "name": "@nhost/nextjs",
"version": "2.1.5", "version": "2.1.6",
"description": "Nhost NextJS library", "description": "Nhost NextJS library",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [

View File

@@ -1,5 +1,15 @@
# @nhost/react # @nhost/react
## 3.3.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 3.2.3 ## 3.2.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/react", "name": "@nhost/react",
"version": "3.2.3", "version": "3.3.0",
"description": "Nhost React library", "description": "Nhost React library",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -70,7 +70,7 @@
}, },
"devDependencies": { "devDependencies": {
"@nhost/docgen": "workspace:*", "@nhost/docgen": "workspace:*",
"@types/react": "^18.2.50", "@types/react": "^18.2.61",
"react": "^18.2.0" "react": "^18.2.0"
}, },
"peerDependencies": { "peerDependencies": {

View File

@@ -1,5 +1,11 @@
# @nhost/sync-versions # @nhost/sync-versions
## 0.1.0
### Minor Changes
- 49a80c2: chore: update dependencies
## 0.0.10 ## 0.0.10
### Patch Changes ### Patch Changes

View File

@@ -2,7 +2,7 @@
"name": "@nhost/sync-versions", "name": "@nhost/sync-versions",
"description": "Sync the versions of Nhost services in each of the packages of a pnpm workspace", "description": "Sync the versions of Nhost services in each of the packages of a pnpm workspace",
"private": true, "private": true,
"version": "0.0.10", "version": "0.1.0",
"license": "MIT", "license": "MIT",
"main": "dist/index.cjs.js", "main": "dist/index.cjs.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
@@ -25,17 +25,17 @@
}, },
"bin": "dist/index.js", "bin": "dist/index.js",
"devDependencies": { "devDependencies": {
"@swc-node/register": "^1.6.8", "@swc-node/register": "^1.8.0",
"@swc/core": "^1.3.107", "@swc/core": "^1.4.2",
"@types/glob": "^8.1.0", "@types/glob": "^8.1.0",
"@types/node": "^16.18.78", "@types/node": "^16.18.86",
"@types/object-path": "^0.11.4", "@types/object-path": "^0.11.4",
"typescript": "^4.9.5" "typescript": "^4.9.5"
}, },
"dependencies": { "dependencies": {
"@pnpm/find-workspace-dir": "^6.0.2", "@pnpm/find-workspace-dir": "^6.0.3",
"glob": "^10.3.10", "glob": "^10.3.10",
"object-path": "^0.11.8", "object-path": "^0.11.8",
"yaml": "^2.3.4" "yaml": "^2.4.0"
} }
} }

View File

@@ -1,5 +1,15 @@
# @nhost/vue # @nhost/vue
## 2.3.0
### Minor Changes
- 49a80c2: chore: update dependencies
### Patch Changes
- @nhost/nhost-js@3.0.8
## 2.2.3 ## 2.2.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/vue", "name": "@nhost/vue",
"version": "2.2.3", "version": "2.3.0",
"description": "Nhost Vue library", "description": "Nhost Vue library",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -66,7 +66,7 @@
}, },
"dependencies": { "dependencies": {
"@nhost/nhost-js": "workspace:*", "@nhost/nhost-js": "workspace:*",
"@vueuse/core": "^10.7.2", "@vueuse/core": "^10.9.0",
"@xstate/vue": "^2.0.0", "@xstate/vue": "^2.0.0",
"jwt-decode": "^3.1.2" "jwt-decode": "^3.1.2"
}, },
@@ -74,8 +74,8 @@
"@nhost/docgen": "workspace:*", "@nhost/docgen": "workspace:*",
"@vitejs/plugin-vue": "^4.6.2", "@vitejs/plugin-vue": "^4.6.2",
"@xstate/inspect": "^0.8.0", "@xstate/inspect": "^0.8.0",
"vue": "^3.4.15", "vue": "^3.4.21",
"vue-router": "^4.2.5", "vue-router": "^4.3.0",
"ws": "^8.16.0", "ws": "^8.16.0",
"xstate": "^4.38.3" "xstate": "^4.38.3"
} }

6460
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff