Compare commits
10 Commits
@nhost/das
...
@nhost/rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82728da100 | ||
|
|
2d68fee54c | ||
|
|
35010353c7 | ||
|
|
aff059ec71 | ||
|
|
713d53cfc0 | ||
|
|
e0ab6d9a37 | ||
|
|
7baee8a9cc | ||
|
|
3db2999f60 | ||
|
|
3c4dd55045 | ||
|
|
92b434e840 |
@@ -1,5 +1,26 @@
|
|||||||
# @nhost/dashboard
|
# @nhost/dashboard
|
||||||
|
|
||||||
|
## 1.8.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react-apollo@9.0.2
|
||||||
|
- @nhost/nextjs@2.1.4
|
||||||
|
|
||||||
|
## 1.8.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 713d53c: feat: add catch-all route for workspace/project - useful for documentation
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 3db2999: fix: refresh table list after running SQL using the editor
|
||||||
|
- 3c4dd55: fix: handle `Error` objects properly in the `ErrorToast` component
|
||||||
|
- 92b434e: fix: resolve an issue where the checkbox in the data-grid header did not select all rows
|
||||||
|
- @nhost/react-apollo@9.0.1
|
||||||
|
- @nhost/nextjs@2.1.3
|
||||||
|
|
||||||
## 1.7.0
|
## 1.7.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/dashboard",
|
"name": "@nhost/dashboard",
|
||||||
"version": "1.7.0",
|
"version": "1.8.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
|
|||||||
@@ -96,45 +96,52 @@ export default function DataGridHeader<T extends object>({
|
|||||||
}}
|
}}
|
||||||
key={column.id}
|
key={column.id}
|
||||||
>
|
>
|
||||||
<Dropdown.Trigger
|
{column.id === 'selection' ? (
|
||||||
className={twMerge(
|
|
||||||
'focus:outline-none motion-safe:transition-colors',
|
|
||||||
)}
|
|
||||||
disabled={
|
|
||||||
column.isDisabled ||
|
|
||||||
column.id === 'selection' ||
|
|
||||||
(column.disableSortBy && !onRemoveColumn)
|
|
||||||
}
|
|
||||||
hideChevron
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
{...headerProps}
|
{...headerProps}
|
||||||
className="relative grid w-full grid-flow-col items-center justify-between p-2"
|
className="relative grid w-full grid-flow-col items-center justify-between p-2"
|
||||||
>
|
>
|
||||||
{column.render('Header')}
|
{column.render('Header')}
|
||||||
|
|
||||||
{allowSort && (
|
|
||||||
<Box component="span" sx={{ color: 'text.primary' }}>
|
|
||||||
{column.isSorted && !column.isSortedDesc && (
|
|
||||||
<ArrowUpIcon className="h-3 w-3" />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{column.isSorted && column.isSortedDesc && (
|
|
||||||
<ArrowDownIcon className="h-3 w-3" />
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
|
) : (
|
||||||
{allowResize && !column.disableResizing && (
|
<Dropdown.Trigger
|
||||||
|
className={twMerge(
|
||||||
|
'focus:outline-none motion-safe:transition-colors',
|
||||||
|
)}
|
||||||
|
disabled={
|
||||||
|
column.isDisabled || (column.disableSortBy && !onRemoveColumn)
|
||||||
|
}
|
||||||
|
hideChevron
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
{...column.getResizerProps({
|
{...headerProps}
|
||||||
onClick: (event: Event) => event.stopPropagation(),
|
className="relative grid w-full grid-flow-col items-center justify-between p-2"
|
||||||
})}
|
>
|
||||||
className="absolute top-0 bottom-0 -right-0.5 z-10 h-full w-1.5 group-hover:bg-slate-900 group-hover:bg-opacity-20 group-active:bg-slate-900 group-active:bg-opacity-20 motion-safe:transition-colors"
|
{column.render('Header')}
|
||||||
/>
|
|
||||||
)}
|
{allowSort && (
|
||||||
</Dropdown.Trigger>
|
<Box component="span" sx={{ color: 'text.primary' }}>
|
||||||
|
{column.isSorted && !column.isSortedDesc && (
|
||||||
|
<ArrowUpIcon className="h-3 w-3" />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{column.isSorted && column.isSortedDesc && (
|
||||||
|
<ArrowDownIcon className="h-3 w-3" />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{allowResize && !column.disableResizing && (
|
||||||
|
<span
|
||||||
|
{...column.getResizerProps({
|
||||||
|
onClick: (event: Event) => event.stopPropagation(),
|
||||||
|
})}
|
||||||
|
className="absolute -right-0.5 bottom-0 top-0 z-10 h-full w-1.5 group-hover:bg-slate-900 group-hover:bg-opacity-20 group-active:bg-slate-900 group-active:bg-opacity-20 motion-safe:transition-colors"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Dropdown.Trigger>
|
||||||
|
)}
|
||||||
|
|
||||||
<Dropdown.Content
|
<Dropdown.Content
|
||||||
menu
|
menu
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { XIcon } from '@/components/ui/v2/icons/XIcon';
|
|||||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||||
import { getToastBackgroundColor } from '@/utils/constants/settings';
|
import { getToastBackgroundColor } from '@/utils/constants/settings';
|
||||||
import { copy } from '@/utils/copy';
|
import { copy } from '@/utils/copy';
|
||||||
import { type ApolloError } from '@apollo/client';
|
import { ApolloError } from '@apollo/client';
|
||||||
import { useUserData } from '@nhost/nextjs';
|
import { useUserData } from '@nhost/nextjs';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
@@ -20,6 +20,43 @@ interface ErrorDetails {
|
|||||||
error: any;
|
error: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getInternalErrorMessage = (
|
||||||
|
error: Error | ApolloError | undefined,
|
||||||
|
): string | null => {
|
||||||
|
if (!error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error instanceof ApolloError) {
|
||||||
|
const internalError = error.graphQLErrors?.[0]?.extensions?.internal as
|
||||||
|
| { error: { message: string } }
|
||||||
|
| undefined;
|
||||||
|
return internalError?.error?.message || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const errorToObject = (error: ApolloError | Error) => {
|
||||||
|
if (error instanceof ApolloError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return {
|
||||||
|
name: error.name,
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
export default function ErrorToast({
|
export default function ErrorToast({
|
||||||
isVisible,
|
isVisible,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
@@ -28,7 +65,7 @@ export default function ErrorToast({
|
|||||||
}: {
|
}: {
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
error: ApolloError;
|
error: ApolloError | Error;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
}) {
|
}) {
|
||||||
const userData = useUserData();
|
const userData = useUserData();
|
||||||
@@ -43,19 +80,10 @@ export default function ErrorToast({
|
|||||||
userId: userData?.id || 'local',
|
userId: userData?.id || 'local',
|
||||||
url: asPath,
|
url: asPath,
|
||||||
},
|
},
|
||||||
error,
|
error: errorToObject(error),
|
||||||
};
|
};
|
||||||
|
|
||||||
const internalError = error?.graphQLErrors?.at(0)?.extensions?.internal as {
|
const msg = getInternalErrorMessage(error) || errorMessage;
|
||||||
error: {
|
|
||||||
message: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const msg =
|
|
||||||
internalError?.error?.message ||
|
|
||||||
error?.graphQLErrors?.at(0).message ||
|
|
||||||
errorMessage;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
import { useDatabaseQuery } from '@/features/database/dataGrid/hooks/useDatabaseQuery';
|
||||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||||
import { getHasuraAdminSecret } from '@/utils/env';
|
import { getHasuraAdminSecret } from '@/utils/env';
|
||||||
import { parseIdentifiersFromSQL } from '@/utils/sql';
|
import { parseIdentifiersFromSQL } from '@/utils/sql';
|
||||||
import toast from 'react-hot-toast';
|
import { useRouter } from 'next/router';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
export default function useRunSQL(
|
export default function useRunSQL(
|
||||||
sqlCode: string,
|
sqlCode: string,
|
||||||
@@ -22,6 +24,14 @@ export default function useRunSQL(
|
|||||||
const [columns, setColumns] = useState<string[]>([]);
|
const [columns, setColumns] = useState<string[]>([]);
|
||||||
const [rows, setRows] = useState<string[][]>([[]]);
|
const [rows, setRows] = useState<string[][]>([[]]);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const {
|
||||||
|
query: { dataSourceSlug },
|
||||||
|
} = router;
|
||||||
|
|
||||||
|
const { refetch } = useDatabaseQuery([dataSourceSlug as string]);
|
||||||
|
|
||||||
const appUrl = generateAppServiceUrl(
|
const appUrl = generateAppServiceUrl(
|
||||||
currentProject?.subdomain,
|
currentProject?.subdomain,
|
||||||
currentProject?.region,
|
currentProject?.region,
|
||||||
@@ -269,6 +279,9 @@ export default function useRunSQL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// refresh the table list after running the sql
|
||||||
|
await refetch();
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
158
dashboard/src/pages/_/_/[...slug].tsx
Normal file
158
dashboard/src/pages/_/_/[...slug].tsx
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import { AuthenticatedLayout } from '@/components/layout/AuthenticatedLayout';
|
||||||
|
import { Container } from '@/components/layout/Container';
|
||||||
|
import { RetryableErrorBoundary } from '@/components/presentational/RetryableErrorBoundary';
|
||||||
|
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
|
||||||
|
import { Box } from '@/components/ui/v2/Box';
|
||||||
|
import { Button } from '@/components/ui/v2/Button';
|
||||||
|
import { Input } from '@/components/ui/v2/Input';
|
||||||
|
import { List } from '@/components/ui/v2/List';
|
||||||
|
import { ListItem } from '@/components/ui/v2/ListItem';
|
||||||
|
import { Text } from '@/components/ui/v2/Text';
|
||||||
|
import {
|
||||||
|
useGetAllWorkspacesAndProjectsQuery,
|
||||||
|
type GetAllWorkspacesAndProjectsQuery,
|
||||||
|
} from '@/utils/__generated__/graphql';
|
||||||
|
import { Divider } from '@mui/material';
|
||||||
|
import { useUserData } from '@nhost/nextjs';
|
||||||
|
import debounce from 'lodash.debounce';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import type { ChangeEvent, ReactElement } from 'react';
|
||||||
|
import { Fragment, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
type Workspace = Omit<
|
||||||
|
GetAllWorkspacesAndProjectsQuery['workspaces'][0],
|
||||||
|
'__typename'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export default function SelectWorkspaceAndProject() {
|
||||||
|
const user = useUserData();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { data, loading } = useGetAllWorkspacesAndProjectsQuery({
|
||||||
|
skip: !user,
|
||||||
|
});
|
||||||
|
|
||||||
|
const workspaces: Workspace[] = data?.workspaces || [];
|
||||||
|
|
||||||
|
const projects = workspaces.flatMap((workspace) =>
|
||||||
|
workspace.projects.map((project) => ({
|
||||||
|
workspaceName: workspace.name,
|
||||||
|
projectName: project.name,
|
||||||
|
value: `${workspace.slug}/${project.slug}`,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
const [filter, setFilter] = useState('');
|
||||||
|
|
||||||
|
const handleFilterChange = useMemo(
|
||||||
|
() =>
|
||||||
|
debounce((event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setFilter(event.target.value);
|
||||||
|
}, 200),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => () => handleFilterChange.cancel(), [handleFilterChange]);
|
||||||
|
|
||||||
|
const goToProjectPage = async (project: {
|
||||||
|
workspaceName: string;
|
||||||
|
projectName: string;
|
||||||
|
value: string;
|
||||||
|
}) => {
|
||||||
|
const { slug } = router.query;
|
||||||
|
|
||||||
|
await router.push({
|
||||||
|
pathname: `/${project.value}/${
|
||||||
|
Array.isArray(slug) ? slug.join('/') : slug
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const projectsToDisplay = filter
|
||||||
|
? projects.filter((project) =>
|
||||||
|
project.projectName.toLowerCase().includes(filter.toLowerCase()),
|
||||||
|
)
|
||||||
|
: projects;
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<div className="flex w-full justify-center">
|
||||||
|
<ActivityIndicator
|
||||||
|
delay={500}
|
||||||
|
label="Loading workspaces and projects..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<div className="mx-auto grid max-w-[760px] grid-flow-row gap-4 py-6 sm:py-14">
|
||||||
|
<Text variant="h2" component="h1" className="">
|
||||||
|
Select a Project
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="mb-2 flex w-full">
|
||||||
|
<Input
|
||||||
|
placeholder="Search..."
|
||||||
|
onChange={handleFilterChange}
|
||||||
|
fullWidth
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<RetryableErrorBoundary>
|
||||||
|
{projectsToDisplay.length === 0 ? (
|
||||||
|
<Box className="h-import py-2">
|
||||||
|
<Text variant="subtitle2">No results found.</Text>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<List className="h-import overflow-y-auto">
|
||||||
|
{projectsToDisplay.map((project, index) => (
|
||||||
|
<Fragment key={project.value}>
|
||||||
|
<ListItem.Root
|
||||||
|
className="grid grid-flow-col justify-start gap-2 py-2.5"
|
||||||
|
secondaryAction={
|
||||||
|
<Button
|
||||||
|
variant="borderless"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => goToProjectPage(project)}
|
||||||
|
>
|
||||||
|
Select
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItem.Avatar>
|
||||||
|
<span className="inline-block h-6 w-6 overflow-hidden rounded-md">
|
||||||
|
<Image
|
||||||
|
src="/logos/new.svg"
|
||||||
|
alt="Nhost Logo"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</ListItem.Avatar>
|
||||||
|
<ListItem.Text
|
||||||
|
primary={project.projectName}
|
||||||
|
secondary={`${project.workspaceName} / ${project.projectName}`}
|
||||||
|
/>
|
||||||
|
</ListItem.Root>
|
||||||
|
|
||||||
|
{index < projects.length - 1 && <Divider component="li" />}
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
)}
|
||||||
|
</RetryableErrorBoundary>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectWorkspaceAndProject.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return (
|
||||||
|
<AuthenticatedLayout title="Select a Project">{page}</AuthenticatedLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -29,6 +29,7 @@ import { Toaster } from 'react-hot-toast';
|
|||||||
const emotionCache = createEmotionCache();
|
const emotionCache = createEmotionCache();
|
||||||
|
|
||||||
process.env = {
|
process.env = {
|
||||||
|
TEST_MODE: 'true',
|
||||||
NODE_ENV: 'development',
|
NODE_ENV: 'development',
|
||||||
NEXT_PUBLIC_NHOST_PLATFORM: 'false',
|
NEXT_PUBLIC_NHOST_PLATFORM: 'false',
|
||||||
NEXT_PUBLIC_ENV: 'dev',
|
NEXT_PUBLIC_ENV: 'dev',
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost-examples/cli
|
# @nhost-examples/cli
|
||||||
|
|
||||||
|
## 0.1.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 0.1.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 0.1.6
|
## 0.1.6
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/cli",
|
"name": "@nhost-examples/cli",
|
||||||
"version": "0.1.6",
|
"version": "0.1.8",
|
||||||
"main": "src/index.mjs",
|
"main": "src/index.mjs",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
# @nhost-examples/codegen-react-apollo
|
# @nhost-examples/codegen-react-apollo
|
||||||
|
|
||||||
|
## 0.1.16
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
- @nhost/react-apollo@9.0.2
|
||||||
|
|
||||||
|
## 0.1.15
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react-apollo@9.0.1
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 0.1.14
|
## 0.1.14
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/codegen-react-apollo",
|
"name": "@nhost-examples/codegen-react-apollo",
|
||||||
"version": "0.1.14",
|
"version": "0.1.16",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"codegen": "graphql-codegen",
|
"codegen": "graphql-codegen",
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost-examples/codegen-react-query
|
# @nhost-examples/codegen-react-query
|
||||||
|
|
||||||
|
## 0.1.17
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
|
||||||
|
## 0.1.16
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 0.1.15
|
## 0.1.15
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/codegen-react-query",
|
"name": "@nhost-examples/codegen-react-query",
|
||||||
"version": "0.1.15",
|
"version": "0.1.17",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"codegen": "graphql-codegen",
|
"codegen": "graphql-codegen",
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
# @nhost-examples/react-urql
|
# @nhost-examples/react-urql
|
||||||
|
|
||||||
|
## 0.0.13
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
- @nhost/react-urql@6.0.2
|
||||||
|
|
||||||
|
## 0.0.12
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
- @nhost/react-urql@6.0.1
|
||||||
|
|
||||||
## 0.0.11
|
## 0.0.11
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/codegen-react-urql",
|
"name": "@nhost-examples/codegen-react-urql",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.11",
|
"version": "0.0.13",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# @nhost-examples/docker-compose
|
# @nhost-examples/docker-compose
|
||||||
|
|
||||||
|
## 0.1.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- aff059e: fix: timers
|
||||||
|
|
||||||
## 0.1.0
|
## 0.1.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ services:
|
|||||||
HASURA_GRAPHQL_UNAUTHORIZED_ROLE: public
|
HASURA_GRAPHQL_UNAUTHORIZED_ROLE: public
|
||||||
HASURA_GRAPHQL_LOG_LEVEL: debug
|
HASURA_GRAPHQL_LOG_LEVEL: debug
|
||||||
HASURA_GRAPHQL_ENABLE_CONSOLE: 'true'
|
HASURA_GRAPHQL_ENABLE_CONSOLE: 'true'
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
- CMD-SHELL
|
||||||
|
- curl http://localhost:8080/healthz > /dev/null 2>&1
|
||||||
|
timeout: 60s
|
||||||
|
interval: 30s
|
||||||
|
start_period: 90s
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.hasura.rule=Host(`${PROXY_HOST}`, `localhost`) && PathPrefix(`/`)"
|
- "traefik.http.routers.hasura.rule=Host(`${PROXY_HOST}`, `localhost`) && PathPrefix(`/`)"
|
||||||
@@ -66,7 +73,7 @@ services:
|
|||||||
AUTH_SMTP_USER: user
|
AUTH_SMTP_USER: user
|
||||||
AUTH_SMTP_PASS: password
|
AUTH_SMTP_PASS: password
|
||||||
AUTH_SMTP_SENDER: mail@example.com
|
AUTH_SMTP_SENDER: mail@example.com
|
||||||
expose:
|
expose:
|
||||||
- 4000
|
- 4000
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
@@ -112,7 +119,7 @@ services:
|
|||||||
- "traefik.http.routers.functions.middlewares=strip-functions@docker"
|
- "traefik.http.routers.functions.middlewares=strip-functions@docker"
|
||||||
- "traefik.http.routers.functions.entrypoints=web"
|
- "traefik.http.routers.functions.entrypoints=web"
|
||||||
restart: always
|
restart: always
|
||||||
expose:
|
expose:
|
||||||
- 3000
|
- 3000
|
||||||
volumes:
|
volumes:
|
||||||
- .:/opt/project
|
- .:/opt/project
|
||||||
@@ -140,7 +147,7 @@ services:
|
|||||||
SMTP_SECURE: "${AUTH_SMTP_SECURE:-false}"
|
SMTP_SECURE: "${AUTH_SMTP_SECURE:-false}"
|
||||||
SMTP_SENDER: ${AUTH_SMTP_SENDER:-hbp@hbp.com}
|
SMTP_SENDER: ${AUTH_SMTP_SENDER:-hbp@hbp.com}
|
||||||
ports:
|
ports:
|
||||||
- ${AUTH_SMTP_PORT:-1025}:1025
|
- ${AUTH_SMTP_PORT:-1025}:1025
|
||||||
- 8025:8025
|
- 8025:8025
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/mailhog:/maildir
|
- ./data/mailhog:/maildir
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/docker-compose",
|
"name": "@nhost-examples/docker-compose",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"e2e": "vitest run"
|
"e2e": "vitest run"
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ describe(
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// * Start docker compose
|
// * Start docker compose
|
||||||
await promisifiedExec(
|
await promisifiedExec(
|
||||||
'docker compose -f docker-compose.yaml --env-file .env.example up --wait --quiet-pull'
|
'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)
|
}, 5 * 60 * 1000)
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost-examples/multi-tenant-one-to-many
|
# @nhost-examples/multi-tenant-one-to-many
|
||||||
|
|
||||||
|
## 2.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 2.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 2.0.4
|
## 2.0.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -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.4",
|
"version": "2.0.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
# @nhost-examples/nextjs
|
# @nhost-examples/nextjs
|
||||||
|
|
||||||
|
## 0.1.18
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
- @nhost/react-apollo@9.0.2
|
||||||
|
- @nhost/nextjs@2.1.4
|
||||||
|
|
||||||
|
## 0.1.17
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react-apollo@9.0.1
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
- @nhost/nextjs@2.1.3
|
||||||
|
|
||||||
## 0.1.16
|
## 0.1.16
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/nextjs",
|
"name": "@nhost-examples/nextjs",
|
||||||
"version": "0.1.16",
|
"version": "0.1.18",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost-examples/node-storage
|
# @nhost-examples/node-storage
|
||||||
|
|
||||||
|
## 0.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 0.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 0.0.8
|
## 0.0.8
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/node-storage",
|
"name": "@nhost-examples/node-storage",
|
||||||
"version": "0.0.8",
|
"version": "0.0.10",
|
||||||
"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",
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost-examples/nextjs-server-components
|
# @nhost-examples/nextjs-server-components
|
||||||
|
|
||||||
|
## 0.2.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 0.2.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 0.2.2
|
## 0.2.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/nextjs-server-components",
|
"name": "@nhost-examples/nextjs-server-components",
|
||||||
"version": "0.2.2",
|
"version": "0.2.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
# @nhost-examples/react-apollo
|
# @nhost-examples/react-apollo
|
||||||
|
|
||||||
|
## 0.3.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
- @nhost/react-apollo@9.0.2
|
||||||
|
|
||||||
|
## 0.3.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react-apollo@9.0.1
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/react-apollo",
|
"name": "@nhost-examples/react-apollo",
|
||||||
"version": "0.3.0",
|
"version": "0.3.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.9.4",
|
"@apollo/client": "^3.9.4",
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost-examples/react-gqty
|
# @nhost-examples/react-gqty
|
||||||
|
|
||||||
|
## 1.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
|
||||||
|
## 1.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 1.0.4
|
## 1.0.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/react-gqty",
|
"name": "@nhost-examples/react-gqty",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.4",
|
"version": "1.0.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
# @nhost-examples/vue-apollo
|
# @nhost-examples/vue-apollo
|
||||||
|
|
||||||
|
## 0.2.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
- @nhost/apollo@6.0.7
|
||||||
|
- @nhost/vue@2.2.2
|
||||||
|
|
||||||
|
## 0.2.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e0ab6d9]
|
||||||
|
- @nhost/apollo@6.0.6
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
- @nhost/vue@2.2.1
|
||||||
|
|
||||||
## 0.2.1
|
## 0.2.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/vue-apollo",
|
"name": "@nhost-examples/vue-apollo",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.2.1",
|
"version": "0.2.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
# @nhost-examples/vue-quickstart
|
# @nhost-examples/vue-quickstart
|
||||||
|
|
||||||
|
## 0.0.15
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/apollo@6.0.7
|
||||||
|
- @nhost/vue@2.2.2
|
||||||
|
|
||||||
|
## 0.0.14
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e0ab6d9]
|
||||||
|
- @nhost/apollo@6.0.6
|
||||||
|
- @nhost/vue@2.2.1
|
||||||
|
|
||||||
## 0.0.13
|
## 0.0.13
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/vue-quickstart",
|
"name": "@nhost-examples/vue-quickstart",
|
||||||
"version": "0.0.13",
|
"version": "0.0.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# @nhost/apollo
|
# @nhost/apollo
|
||||||
|
|
||||||
|
## 6.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 6.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- e0ab6d9: fix: add extra logic to check and wait for a valid JWT
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 6.0.5
|
## 6.0.5
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/apollo",
|
"name": "@nhost/apollo",
|
||||||
"version": "6.0.5",
|
"version": "6.0.7",
|
||||||
"description": "Nhost Apollo Client library",
|
"description": "Nhost Apollo Client library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -65,7 +65,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graphql": "16.8.1",
|
"graphql": "16.8.1",
|
||||||
"graphql-ws": "^5.14.3"
|
"graphql-ws": "^5.14.3",
|
||||||
|
"jwt-decode": "^3.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@apollo/client": "^3.9.4",
|
"@apollo/client": "^3.9.4",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { setContext } from '@apollo/client/link/context'
|
|||||||
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
|
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
|
||||||
import { getMainDefinition } from '@apollo/client/utilities'
|
import { getMainDefinition } from '@apollo/client/utilities'
|
||||||
import { AuthContext, NhostClient } from '@nhost/nhost-js'
|
import { AuthContext, NhostClient } from '@nhost/nhost-js'
|
||||||
|
import jwtDecode, { JwtPayload } from 'jwt-decode'
|
||||||
|
|
||||||
import { createRestartableClient } from './ws'
|
import { createRestartableClient } from './ws'
|
||||||
const isBrowser = typeof window !== 'undefined'
|
const isBrowser = typeof window !== 'undefined'
|
||||||
@@ -58,25 +59,41 @@ export const createApolloClient = ({
|
|||||||
|
|
||||||
let accessToken: AuthContext['accessToken'] | null = null
|
let accessToken: AuthContext['accessToken'] | null = null
|
||||||
|
|
||||||
|
const isJwtValid = () => {
|
||||||
|
if (!accessToken?.value) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const marginInSeconds = 3
|
||||||
|
const marginInMilliseconds = marginInSeconds * 1000
|
||||||
|
|
||||||
|
let decodedToken: JwtPayload = jwtDecode(accessToken.value)
|
||||||
|
return decodedToken.exp! * 1000 > Date.now() - marginInMilliseconds
|
||||||
|
}
|
||||||
|
|
||||||
const isTokenValid = () =>
|
const isTokenValid = () =>
|
||||||
!!accessToken?.value && !!accessToken?.expiresAt && accessToken?.expiresAt > new Date()
|
!!accessToken?.value &&
|
||||||
|
!!accessToken?.expiresAt &&
|
||||||
|
accessToken?.expiresAt > new Date() &&
|
||||||
|
isJwtValid()
|
||||||
|
|
||||||
const isTokenValidOrNull = () => !accessToken || isTokenValid()
|
const isTokenValidOrNull = () => !accessToken || isTokenValid()
|
||||||
|
|
||||||
const awaitValidTokenOrNull = () => {
|
const awaitValidTokenOrNull = () => {
|
||||||
if (isTokenValidOrNull()) {
|
if (isTokenValidOrNull()) {
|
||||||
return
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
const waitForValidToken = () => {
|
||||||
// doing this as an interval to avoid race conditions.
|
if (isTokenValidOrNull()) {
|
||||||
const interval = setInterval(() => {
|
return Promise.resolve(true)
|
||||||
if (isTokenValidOrNull()) {
|
}
|
||||||
clearInterval(interval)
|
return new Promise((resolve) => {
|
||||||
resolve(true)
|
setTimeout(() => waitForValidToken().then(resolve), 100)
|
||||||
}
|
})
|
||||||
}, 100)
|
}
|
||||||
})
|
|
||||||
|
return waitForValidToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAuthHeaders = async () => {
|
const getAuthHeaders = async () => {
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
# @nhost/react-apollo
|
# @nhost/react-apollo
|
||||||
|
|
||||||
|
## 9.0.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/apollo@6.0.7
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
|
||||||
|
## 9.0.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e0ab6d9]
|
||||||
|
- @nhost/apollo@6.0.6
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 9.0.0
|
## 9.0.0
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/react-apollo",
|
"name": "@nhost/react-apollo",
|
||||||
"version": "9.0.0",
|
"version": "9.0.2",
|
||||||
"description": "Nhost React Apollo client",
|
"description": "Nhost React Apollo client",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost/react-urql
|
# @nhost/react-urql
|
||||||
|
|
||||||
|
## 6.0.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
|
||||||
|
## 6.0.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 6.0.0
|
## 6.0.0
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/react-urql",
|
"name": "@nhost/react-urql",
|
||||||
"version": "6.0.0",
|
"version": "6.0.2",
|
||||||
"description": "Nhost React URQL client",
|
"description": "Nhost React URQL client",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost/graphql-js
|
# @nhost/graphql-js
|
||||||
|
|
||||||
|
## 0.1.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 2d68fee: fix: resolve an issue where unauthenticated graphql requests are not sent
|
||||||
|
|
||||||
|
## 0.1.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- e0ab6d9: fix: add extra logic to check and wait for a valid JWT
|
||||||
|
|
||||||
## 0.1.5
|
## 0.1.5
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/graphql-js",
|
"name": "@nhost/graphql-js",
|
||||||
"version": "0.1.5",
|
"version": "0.1.7",
|
||||||
"description": "Nhost GraphQL client",
|
"description": "Nhost GraphQL client",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -54,7 +54,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@graphql-typed-document-node/core": "^3.2.0",
|
"@graphql-typed-document-node/core": "^3.2.0",
|
||||||
"isomorphic-unfetch": "^3.1.0"
|
"isomorphic-unfetch": "^3.1.0",
|
||||||
|
"jwt-decode": "^3.1.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
Variables
|
Variables
|
||||||
} from './types'
|
} from './types'
|
||||||
|
|
||||||
|
import jwtDecode, { JwtPayload } from 'jwt-decode'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alias GraphQL
|
* @alias GraphQL
|
||||||
*/
|
*/
|
||||||
@@ -28,6 +30,37 @@ export class NhostGraphqlClient {
|
|||||||
this.adminSecret = adminSecret
|
this.adminSecret = adminSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isAccessTokenValidOrNull = () => {
|
||||||
|
if (!this.accessToken) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const decodedToken: JwtPayload = jwtDecode(this.accessToken)
|
||||||
|
return decodedToken.exp != null && decodedToken.exp * 1000 > Date.now()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error decoding token:', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private awaitForValidAccessTokenOrNull = async () => {
|
||||||
|
if (this.isAccessTokenValidOrNull()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const waitForValidTokenOrNull = () => {
|
||||||
|
if (this.isAccessTokenValidOrNull()) {
|
||||||
|
return Promise.resolve(true)
|
||||||
|
}
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => waitForValidTokenOrNull().then(resolve), 100)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return waitForValidTokenOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use `nhost.graphql.request` to send a GraphQL request. For more serious GraphQL usage we recommend using a GraphQL client such as Apollo Client (https://www.apollographql.com/docs/react).
|
* Use `nhost.graphql.request` to send a GraphQL request. For more serious GraphQL usage we recommend using a GraphQL client such as Apollo Client (https://www.apollographql.com/docs/react).
|
||||||
*
|
*
|
||||||
@@ -70,6 +103,12 @@ export class NhostGraphqlClient {
|
|||||||
|
|
||||||
const { headers, ...otherOptions } = config || {}
|
const { headers, ...otherOptions } = config || {}
|
||||||
const { query, operationName } = resolveRequestDocument(requestOptions.document)
|
const { query, operationName } = resolveRequestDocument(requestOptions.document)
|
||||||
|
|
||||||
|
if (!process.env.TEST_MODE) {
|
||||||
|
// We skip this while running unit tests because the accessToken is generated using faker
|
||||||
|
await this.awaitForValidAccessTokenOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(this.httpUrl, {
|
const response = await fetch(this.httpUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# @nhost/hasura-auth-js
|
# @nhost/hasura-auth-js
|
||||||
|
|
||||||
|
## 2.3.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 7baee8a: fix(hasura-auth-js): replace `jwt-decode` with `jose` for decoding access tokens that works on both the browser and Node.js
|
||||||
|
- e0ab6d9: fix: add extra logic to check and wait for a valid JWT
|
||||||
|
|
||||||
## 2.3.0
|
## 2.3.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/hasura-auth-js",
|
"name": "@nhost/hasura-auth-js",
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"description": "Hasura-auth client",
|
"description": "Hasura-auth client",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -66,8 +66,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@simplewebauthn/browser": "^6.2.2",
|
"@simplewebauthn/browser": "^6.2.2",
|
||||||
"fetch-ponyfill": "^7.1.0",
|
"fetch-ponyfill": "^7.1.0",
|
||||||
|
"jose": "^5.2.2",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jwt-decode": "^3.1.2",
|
|
||||||
"xstate": "^4.38.3"
|
"xstate": "^4.38.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import jwt_decode from 'jwt-decode'
|
import * as jose from 'jose'
|
||||||
import { interpret } from 'xstate'
|
import { interpret } from 'xstate'
|
||||||
import {
|
import {
|
||||||
EMAIL_NEEDS_VERIFICATION,
|
EMAIL_NEEDS_VERIFICATION,
|
||||||
@@ -625,7 +625,7 @@ export class HasuraAuthClient {
|
|||||||
public getDecodedAccessToken(): JWTClaims | null {
|
public getDecodedAccessToken(): JWTClaims | null {
|
||||||
const jwt = this.getAccessToken()
|
const jwt = this.getAccessToken()
|
||||||
if (!jwt) return null
|
if (!jwt) return null
|
||||||
return jwt_decode<JWTClaims>(jwt)
|
return jose.decodeJwt<JWTClaims>(jwt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -687,9 +687,16 @@ export const createAuthMachine = ({
|
|||||||
isAutoRefreshDisabled: () => !autoRefreshToken,
|
isAutoRefreshDisabled: () => !autoRefreshToken,
|
||||||
refreshTimerShouldRefresh: (ctx) => {
|
refreshTimerShouldRefresh: (ctx) => {
|
||||||
const { expiresAt } = ctx.accessToken
|
const { expiresAt } = ctx.accessToken
|
||||||
|
|
||||||
if (!expiresAt) {
|
if (!expiresAt) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This happens when either the computer goes to sleep or when Chrome descides to suspend the tab
|
||||||
|
if (expiresAt.getTime() < Date.now()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx.refreshTimer.lastAttempt) {
|
if (ctx.refreshTimer.lastAttempt) {
|
||||||
// * If the refresh timer reached the maximum number of attempts, we should not try again
|
// * If the refresh timer reached the maximum number of attempts, we should not try again
|
||||||
if (ctx.refreshTimer.attempts > REFRESH_TOKEN_MAX_ATTEMPTS) {
|
if (ctx.refreshTimer.attempts > REFRESH_TOKEN_MAX_ATTEMPTS) {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost/nextjs
|
# @nhost/nextjs
|
||||||
|
|
||||||
|
## 2.1.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.2
|
||||||
|
|
||||||
|
## 2.1.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@3.2.1
|
||||||
|
|
||||||
## 2.1.2
|
## 2.1.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/nextjs",
|
"name": "@nhost/nextjs",
|
||||||
"version": "2.1.2",
|
"version": "2.1.4",
|
||||||
"description": "Nhost NextJS library",
|
"description": "Nhost NextJS library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
# @nhost/nhost-js
|
# @nhost/nhost-js
|
||||||
|
|
||||||
|
## 3.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [2d68fee]
|
||||||
|
- @nhost/graphql-js@0.1.7
|
||||||
|
|
||||||
|
## 3.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [7baee8a]
|
||||||
|
- Updated dependencies [e0ab6d9]
|
||||||
|
- @nhost/hasura-auth-js@2.3.1
|
||||||
|
- @nhost/graphql-js@0.1.6
|
||||||
|
|
||||||
## 3.0.5
|
## 3.0.5
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/nhost-js",
|
"name": "@nhost/nhost-js",
|
||||||
"version": "3.0.5",
|
"version": "3.0.7",
|
||||||
"description": "Nhost JavaScript SDK",
|
"description": "Nhost JavaScript SDK",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost/react
|
# @nhost/react
|
||||||
|
|
||||||
|
## 3.2.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 3.2.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 3.2.0
|
## 3.2.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/react",
|
"name": "@nhost/react",
|
||||||
"version": "3.2.0",
|
"version": "3.2.2",
|
||||||
"description": "Nhost React library",
|
"description": "Nhost React library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @nhost/vue
|
# @nhost/vue
|
||||||
|
|
||||||
|
## 2.2.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.7
|
||||||
|
|
||||||
|
## 2.2.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@3.0.6
|
||||||
|
|
||||||
## 2.2.0
|
## 2.2.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/vue",
|
"name": "@nhost/vue",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"description": "Nhost Vue library",
|
"description": "Nhost Vue library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
18
pnpm-lock.yaml
generated
18
pnpm-lock.yaml
generated
@@ -1407,6 +1407,9 @@ importers:
|
|||||||
graphql-ws:
|
graphql-ws:
|
||||||
specifier: ^5.14.3
|
specifier: ^5.14.3
|
||||||
version: 5.14.3(graphql@16.8.1)
|
version: 5.14.3(graphql@16.8.1)
|
||||||
|
jwt-decode:
|
||||||
|
specifier: ^3.1.2
|
||||||
|
version: 3.1.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@apollo/client':
|
'@apollo/client':
|
||||||
specifier: ^3.9.4
|
specifier: ^3.9.4
|
||||||
@@ -1575,6 +1578,9 @@ importers:
|
|||||||
isomorphic-unfetch:
|
isomorphic-unfetch:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
|
jwt-decode:
|
||||||
|
specifier: ^3.1.2
|
||||||
|
version: 3.1.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@nhost/docgen':
|
'@nhost/docgen':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
@@ -1591,12 +1597,12 @@ importers:
|
|||||||
fetch-ponyfill:
|
fetch-ponyfill:
|
||||||
specifier: ^7.1.0
|
specifier: ^7.1.0
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
|
jose:
|
||||||
|
specifier: ^5.2.2
|
||||||
|
version: 5.2.2
|
||||||
js-cookie:
|
js-cookie:
|
||||||
specifier: ^3.0.5
|
specifier: ^3.0.5
|
||||||
version: 3.0.5
|
version: 3.0.5
|
||||||
jwt-decode:
|
|
||||||
specifier: ^3.1.2
|
|
||||||
version: 3.1.2
|
|
||||||
xstate:
|
xstate:
|
||||||
specifier: ^4.38.3
|
specifier: ^4.38.3
|
||||||
version: 4.38.3
|
version: 4.38.3
|
||||||
@@ -5938,7 +5944,7 @@ packages:
|
|||||||
/@graphql-tools/utils@8.13.1(graphql@16.8.1):
|
/@graphql-tools/utils@8.13.1(graphql@16.8.1):
|
||||||
resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==}
|
resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
graphql: '>=16.8.1'
|
graphql: 16.8.1
|
||||||
dependencies:
|
dependencies:
|
||||||
graphql: 16.8.1
|
graphql: 16.8.1
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
@@ -19441,6 +19447,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==}
|
resolution: {integrity: sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/jose@5.2.2:
|
||||||
|
resolution: {integrity: sha512-/WByRr4jDcsKlvMd1dRJnPfS1GVO3WuKyaurJ/vvXcOaUQO8rnNObCQMlv/5uCceVQIq5Q4WLF44ohsdiTohdg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/jpeg-js@0.4.4:
|
/jpeg-js@0.4.4:
|
||||||
resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==}
|
resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|||||||
Reference in New Issue
Block a user