Compare commits
13 Commits
@nhost/rea
...
@nhost/das
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f16e2305c3 | ||
|
|
5d6c349350 | ||
|
|
245a1b44c4 | ||
|
|
ca75f731af | ||
|
|
c48be24d13 | ||
|
|
60b5bf20d7 | ||
|
|
8f94bc6332 | ||
|
|
75c73c4884 | ||
|
|
4c6a6bb6c1 | ||
|
|
60b685ab02 | ||
|
|
2e65bc6dc0 | ||
|
|
14e6100722 | ||
|
|
479dba102e |
26
.github/workflows/changesets.yaml
vendored
26
.github/workflows/changesets.yaml
vendored
@@ -65,29 +65,13 @@ jobs:
|
||||
|
||||
publish-vercel:
|
||||
name: Publish to Vercel
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- test
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Node and dependencies
|
||||
uses: ./.github/actions/install-dependencies
|
||||
with:
|
||||
TURBO_TOKEN: ${{ env.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ env.TURBO_TEAM }}
|
||||
- name: Setup Vercel CLI
|
||||
run: pnpm add -g vercel
|
||||
- name: Trigger a Vercel deployment
|
||||
env:
|
||||
VERCEL_ORG_ID: ${{ secrets.DASHBOARD_VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.DASHBOARD_VERCEL_PROJECT_ID }}
|
||||
run: |
|
||||
vercel pull --environment=production --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
vercel build --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
vercel deploy --prebuilt --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
uses: ./.github/workflows/deploy-dashboard.yaml
|
||||
with:
|
||||
git_ref: ${{ github.ref_name }}
|
||||
environment: production
|
||||
secrets: inherit
|
||||
|
||||
publish-docker:
|
||||
name: Publish to Docker Hub
|
||||
|
||||
58
.github/workflows/deploy-dashboard.yaml
vendored
Normal file
58
.github/workflows/deploy-dashboard.yaml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: 'dashboard: release form'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
git_ref:
|
||||
type: string
|
||||
description: 'Branch, tag, or commit SHA'
|
||||
required: true
|
||||
|
||||
environment:
|
||||
type: choice
|
||||
description: 'Deployment environment'
|
||||
required: true
|
||||
default: staging
|
||||
options:
|
||||
- staging
|
||||
- production
|
||||
|
||||
workflow_call:
|
||||
inputs:
|
||||
git_ref:
|
||||
required: true
|
||||
type: string
|
||||
environment:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
publish-vercel:
|
||||
name: Publish to Vercel
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node and dependencies
|
||||
uses: ./.github/actions/install-dependencies
|
||||
with:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
|
||||
- name: Setup Vercel CLI
|
||||
run: pnpm add -g vercel
|
||||
|
||||
- name: Trigger Vercel deployment
|
||||
env:
|
||||
VERCEL_ORG_ID: ${{ secrets.DASHBOARD_VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ inputs.environment == 'production' && secrets.DASHBOARD_VERCEL_PROJECT_ID || secrets.DASHBOARD_STAGING_VERCEL_PROJECT_ID }}
|
||||
run: |
|
||||
echo "Deploying to: ${{ inputs.environment }}..."
|
||||
vercel pull --environment=production --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
vercel build --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
vercel deploy --prebuilt --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
@@ -15,6 +15,8 @@
|
||||
<a href="https://twitter.com/nhost">Twitter</a>
|
||||
<span> • </span>
|
||||
<a href="https://nhost.io/discord">Discord</a>
|
||||
<span> • </span>
|
||||
<a href="https://gurubase.io/g/nhost">Ask Nhost Guru (third party, unofficial)</a>
|
||||
<br />
|
||||
|
||||
<hr />
|
||||
@@ -148,4 +150,4 @@ Here are some ways of contributing to making Nhost better:
|
||||
<p align="center">
|
||||
<img width="720" src="https://contrib.rocks/image?repo=nhost/nhost" alt="A table of avatars from the project's contributors" />
|
||||
</p>
|
||||
</a>
|
||||
</a>
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "2.7.1",
|
||||
"version": "2.9.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
|
||||
@@ -8,20 +8,15 @@ import {
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@/components/ui/v3/command';
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from '@/components/ui/v3/hover-card';
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/components/ui/v3/popover';
|
||||
import { ProjectStatusIndicator } from '@/features/orgs/components/common/ProjectStatusIndicator';
|
||||
import { useAppState } from '@/features/orgs/projects/common/hooks/useAppState';
|
||||
import { useOrgs } from '@/features/orgs/projects/hooks/useOrgs';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ApplicationStatus } from '@/types/application';
|
||||
import { Box, Check, ChevronsUpDown } from 'lucide-react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -31,56 +26,6 @@ type Option = {
|
||||
label: string;
|
||||
};
|
||||
|
||||
function ProjectStatusIndicator({ status }: { status: ApplicationStatus }) {
|
||||
const indicatorStyles: Record<
|
||||
number,
|
||||
{ className: string; description: string }
|
||||
> = {
|
||||
[ApplicationStatus.Errored]: {
|
||||
className: 'bg-destructive',
|
||||
description: 'Project errored',
|
||||
},
|
||||
[ApplicationStatus.Pausing]: {
|
||||
className: 'bg-primary-main animate-blinking',
|
||||
description: 'Project is pausing',
|
||||
},
|
||||
[ApplicationStatus.Restoring]: {
|
||||
className: 'bg-primary-main animate-blinking',
|
||||
description: 'Project is restoring',
|
||||
},
|
||||
[ApplicationStatus.Paused]: {
|
||||
className: 'bg-slate-400',
|
||||
description: 'Project is paused',
|
||||
},
|
||||
[ApplicationStatus.Unpausing]: {
|
||||
className: 'bg-primary-main animate-blinking',
|
||||
description: 'Project is unpausing',
|
||||
},
|
||||
[ApplicationStatus.Live]: {
|
||||
className: 'bg-primary-main',
|
||||
description: 'Project is live',
|
||||
},
|
||||
};
|
||||
const style = indicatorStyles[status];
|
||||
|
||||
if (style) {
|
||||
return (
|
||||
<HoverCard openDelay={0}>
|
||||
<HoverCardTrigger asChild>
|
||||
<span
|
||||
className={cn('mt-[1px] h-2 w-2 rounded-full', style.className)}
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent side="top" className="h-fit w-fit py-2">
|
||||
{style.description}
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function ProjectsComboBox() {
|
||||
const {
|
||||
query: { appSubdomain },
|
||||
|
||||
@@ -14,9 +14,6 @@ export default function Estimate() {
|
||||
|
||||
const amountDue = useMemo(() => {
|
||||
const amount = data?.billingGetNextInvoice?.AmountDue;
|
||||
if (!amount) {
|
||||
return 'N/A';
|
||||
}
|
||||
if (typeof amount !== 'number') {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from '@/components/ui/v3/hover-card';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ApplicationStatus } from '@/types/application';
|
||||
|
||||
export default function ProjectStatusIndicator({
|
||||
status,
|
||||
}: {
|
||||
status: ApplicationStatus;
|
||||
}) {
|
||||
const indicatorStyles: Record<
|
||||
number,
|
||||
{ className: string; description: string }
|
||||
> = {
|
||||
[ApplicationStatus.Errored]: {
|
||||
className: 'bg-destructive',
|
||||
description: 'Project errored',
|
||||
},
|
||||
[ApplicationStatus.Pausing]: {
|
||||
className: 'bg-primary-main animate-blinking',
|
||||
description: 'Project is pausing',
|
||||
},
|
||||
[ApplicationStatus.Restoring]: {
|
||||
className: 'bg-primary-main animate-blinking',
|
||||
description: 'Project is restoring',
|
||||
},
|
||||
[ApplicationStatus.Paused]: {
|
||||
className: 'bg-slate-400',
|
||||
description: 'Project is paused',
|
||||
},
|
||||
[ApplicationStatus.Unpausing]: {
|
||||
className: 'bg-primary-main animate-blinking',
|
||||
description: 'Project is unpausing',
|
||||
},
|
||||
[ApplicationStatus.Live]: {
|
||||
className: 'bg-primary-main',
|
||||
description: 'Project is live',
|
||||
},
|
||||
};
|
||||
const style = indicatorStyles[status];
|
||||
|
||||
if (style) {
|
||||
return (
|
||||
<HoverCard openDelay={0}>
|
||||
<HoverCardTrigger asChild>
|
||||
<span
|
||||
className={cn(
|
||||
'mt-[2px] h-2 w-2 flex-shrink-0 rounded-full',
|
||||
style.className,
|
||||
)}
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent side="top" className="h-fit w-fit py-2">
|
||||
{style.description}
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as ProjectStatusIndicator } from './ProjectStatusIndicator';
|
||||
@@ -1,8 +1,9 @@
|
||||
import { LoadingScreen } from '@/components/presentational/LoadingScreen';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { Button } from '@/components/ui/v3/button';
|
||||
import { ProjectStatusIndicator } from '@/features/orgs/components/common/ProjectStatusIndicator';
|
||||
import { DeploymentStatusMessage } from '@/features/orgs/projects/deployments/components/DeploymentStatusMessage';
|
||||
import { useCurrentOrg } from '@/features/orgs/projects/hooks/useCurrentOrg';
|
||||
import { DeploymentStatusMessage } from '@/features/projects/deployments/components/DeploymentStatusMessage';
|
||||
import {
|
||||
useGetProjectsQuery,
|
||||
type GetProjectsQuery,
|
||||
@@ -22,20 +23,21 @@ function ProjectCard({ project }: { project: Project }) {
|
||||
return (
|
||||
<Link
|
||||
href={`/orgs/${org?.slug}/projects/${project.subdomain}`}
|
||||
className="flex cursor-pointer flex-col gap-4 rounded-lg border bg-background p-4 hover:shadow-sm"
|
||||
className="flex h-44 cursor-pointer flex-col gap-4 rounded-lg border bg-background p-4 hover:shadow-sm"
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="flex w-full flex-row items-center space-x-2">
|
||||
<Box className="h-6 w-6 flex-shrink-0" />
|
||||
<p className="truncate text-lg font-bold">{project.name}</p>
|
||||
<div className="flex flex-row items-start gap-2">
|
||||
<Box className="mt-[2px] h-5 w-5 flex-shrink-0" />
|
||||
<div className="flex w-full flex-col">
|
||||
<p className="truncate font-bold">{project.name}</p>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{project.region.name}
|
||||
</span>
|
||||
</div>
|
||||
<ProjectStatusIndicator status={project.appStates[0].stateId} />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row items-start gap-2">
|
||||
<DeploymentStatusMessage
|
||||
appCreatedAt={project.createdAt}
|
||||
deployment={latestDeployment}
|
||||
/>
|
||||
<div className="flex flex-1 flex-row items-start gap-2">
|
||||
<DeploymentStatusMessage deployment={latestDeployment} />
|
||||
</div>
|
||||
|
||||
<div className="flex w-full justify-end">
|
||||
@@ -53,6 +55,7 @@ export default function ProjectsGrid() {
|
||||
orgSlug: org?.slug,
|
||||
},
|
||||
skip: !org,
|
||||
pollInterval: 10 * 1000,
|
||||
});
|
||||
|
||||
const [query, setQuery] = useState('');
|
||||
@@ -100,7 +103,7 @@ export default function ProjectsGrid() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 p-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||
<div className="grid grid-cols-1 gap-4 p-4 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
|
||||
{filteredProjects.map((project) => (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
))}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useProject } from '@/features/orgs/projects/hooks/useProject';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { getHasuraAdminSecret } from '@/utils/env';
|
||||
@@ -39,10 +39,12 @@ export default function useUpdateColumnMutation({
|
||||
const {
|
||||
query: { dataSourceSlug, schemaSlug, tableSlug },
|
||||
} = useRouter();
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const { project } = useProject();
|
||||
|
||||
const appUrl = generateAppServiceUrl(
|
||||
currentProject?.subdomain,
|
||||
currentProject?.region,
|
||||
project?.subdomain,
|
||||
project?.region,
|
||||
'hasura',
|
||||
);
|
||||
const mutationFn = isPlatform ? updateColumn : updateColumnMigration;
|
||||
@@ -55,7 +57,7 @@ export default function useUpdateColumnMutation({
|
||||
adminSecret:
|
||||
process.env.NEXT_PUBLIC_ENV === 'dev'
|
||||
? getHasuraAdminSecret()
|
||||
: customAdminSecret || currentProject?.config?.hasura.adminSecret,
|
||||
: customAdminSecret || project?.config?.hasura.adminSecret,
|
||||
dataSource: customDataSource || (dataSourceSlug as string),
|
||||
schema: customSchema || (schemaSlug as string),
|
||||
table: customTable || (tableSlug as string),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useProject } from '@/features/orgs/projects/hooks/useProject';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { getHasuraAdminSecret } from '@/utils/env';
|
||||
import type { MutationOptions } from '@tanstack/react-query';
|
||||
@@ -40,10 +40,12 @@ export default function useUpdateRecordMutation<TData extends object = {}>({
|
||||
const {
|
||||
query: { dataSourceSlug, schemaSlug, tableSlug },
|
||||
} = useRouter();
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const { project } = useProject();
|
||||
|
||||
const appUrl = generateAppServiceUrl(
|
||||
currentProject?.subdomain,
|
||||
currentProject?.region,
|
||||
project?.subdomain,
|
||||
project?.region,
|
||||
'hasura',
|
||||
);
|
||||
|
||||
@@ -55,7 +57,7 @@ export default function useUpdateRecordMutation<TData extends object = {}>({
|
||||
adminSecret:
|
||||
process.env.NEXT_PUBLIC_ENV === 'dev'
|
||||
? getHasuraAdminSecret()
|
||||
: customAdminSecret || currentProject?.config?.hasura.adminSecret,
|
||||
: customAdminSecret || project?.config?.hasura.adminSecret,
|
||||
dataSource: customDataSource || (dataSourceSlug as string),
|
||||
schema: customSchema || (schemaSlug as string),
|
||||
table: customTable || (tableSlug as string),
|
||||
|
||||
@@ -23,30 +23,17 @@ afterAll(() => {
|
||||
});
|
||||
|
||||
test('should render the avatar of the user who deployed the application', () => {
|
||||
render(
|
||||
<DeploymentStatusMessage
|
||||
deployment={defaultDeployment}
|
||||
appCreatedAt="2023-02-24"
|
||||
/>,
|
||||
);
|
||||
render(<DeploymentStatusMessage deployment={defaultDeployment} />);
|
||||
|
||||
expect(
|
||||
screen.getByRole('img', {
|
||||
name: `Avatar of ${defaultDeployment.commitUserName}`,
|
||||
}),
|
||||
).toHaveAttribute(
|
||||
'style',
|
||||
`background-image: url(${defaultDeployment.commitUserAvatarUrl});`,
|
||||
);
|
||||
).toHaveAttribute('src', `${defaultDeployment.commitUserAvatarUrl}`);
|
||||
});
|
||||
|
||||
test('should render "updated just now" when the deployment is in progress and has not ended', () => {
|
||||
render(
|
||||
<DeploymentStatusMessage
|
||||
deployment={defaultDeployment}
|
||||
appCreatedAt="2023-02-24"
|
||||
/>,
|
||||
);
|
||||
render(<DeploymentStatusMessage deployment={defaultDeployment} />);
|
||||
|
||||
expect(screen.getByText(/updated just now/i)).toBeInTheDocument();
|
||||
});
|
||||
@@ -59,7 +46,6 @@ test('should render "updated just now" when the deployment\'s status is DEPLOYED
|
||||
deploymentStatus: 'DEPLOYED',
|
||||
deploymentEndedAt: null,
|
||||
}}
|
||||
appCreatedAt="2023-02-24"
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -76,19 +62,8 @@ test('should render "deployed 1 day ago" when the deployment has ended', () => {
|
||||
deploymentStatus: 'DEPLOYED',
|
||||
deploymentEndedAt: '2023-02-24T12:15:00.000Z',
|
||||
}}
|
||||
appCreatedAt="2023-02-24"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText(/deployed 1 day ago/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should render "created 1 day ago" if the application does not have a deployment', () => {
|
||||
vi.setSystemTime(new Date('2023-02-25T12:25:00.000Z'));
|
||||
|
||||
render(
|
||||
<DeploymentStatusMessage deployment={null} appCreatedAt="2023-02-24" />,
|
||||
);
|
||||
|
||||
expect(screen.getByText(/created 1 day ago/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
import { Avatar } from '@/components/ui/v1/Avatar';
|
||||
import { Avatar } from '@/components/ui/v2/Avatar';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import type { Deployment } from '@/types/application';
|
||||
import formatDistance from 'date-fns/formatDistance';
|
||||
|
||||
export interface DeploymentStatusMessageProps {
|
||||
/**
|
||||
* The deployment to render the status message for.
|
||||
*/
|
||||
deployment: Partial<Deployment>;
|
||||
/**
|
||||
* The date the application was created.
|
||||
*/
|
||||
appCreatedAt: string;
|
||||
}
|
||||
|
||||
export default function DeploymentStatusMessage({
|
||||
deployment,
|
||||
appCreatedAt,
|
||||
}: DeploymentStatusMessageProps) {
|
||||
const isDeployingToProduction = [
|
||||
'SCHEDULED',
|
||||
@@ -29,11 +21,10 @@ export default function DeploymentStatusMessage({
|
||||
(deployment && !deployment.deploymentEndedAt)
|
||||
) {
|
||||
return (
|
||||
<span className="flex flex-row">
|
||||
<span className="flex flex-row justify-start">
|
||||
<Avatar
|
||||
component="span"
|
||||
name={deployment.commitUserName}
|
||||
avatarUrl={deployment.commitUserAvatarUrl}
|
||||
alt={`Avatar of ${deployment.commitUserName}`}
|
||||
src={deployment.commitUserAvatarUrl}
|
||||
className="mr-1 h-4 w-4 self-center"
|
||||
/>
|
||||
<Text component="span" className="self-center text-sm">
|
||||
@@ -44,30 +35,26 @@ export default function DeploymentStatusMessage({
|
||||
}
|
||||
|
||||
if (!isDeployingToProduction && deployment?.deploymentEndedAt) {
|
||||
const statusMessage = `deployed ${formatDistance(new Date(deployment.deploymentEndedAt), new Date(), { addSuffix: true })}`;
|
||||
|
||||
return (
|
||||
<span className="grid grid-flow-col">
|
||||
<div className="relative flex flex-row">
|
||||
<Avatar
|
||||
component="span"
|
||||
name={deployment.commitUserName}
|
||||
avatarUrl={deployment.commitUserAvatarUrl}
|
||||
className="mr-1 h-4 w-4 self-center"
|
||||
alt={`Avatar of ${deployment.commitUserName}`}
|
||||
src={deployment.commitUserAvatarUrl}
|
||||
className="mr-2 mt-1 h-4 w-4"
|
||||
/>
|
||||
<Text component="span" className="self-center truncate text-sm">
|
||||
{deployment.commitUserName} deployed{' '}
|
||||
{formatDistance(new Date(deployment.deploymentEndedAt), new Date(), {
|
||||
addSuffix: true,
|
||||
})}
|
||||
</Text>
|
||||
</span>
|
||||
<div className="flex flex-col text-sm text-muted-foreground">
|
||||
<p className="line-clamp-1 break-all">{deployment.commitUserName}</p>
|
||||
<p>{statusMessage}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Text component="span" className="text-sm">
|
||||
created{' '}
|
||||
{formatDistance(new Date(appCreatedAt), new Date(), {
|
||||
addSuffix: true,
|
||||
})}
|
||||
<Text component="span" className="text-sm text-muted-foreground">
|
||||
No deployments
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@ query getProjects($orgSlug: String!) {
|
||||
slug
|
||||
createdAt
|
||||
subdomain
|
||||
region {
|
||||
id
|
||||
name
|
||||
}
|
||||
deployments(limit: 4, order_by: { deploymentStartedAt: desc }) {
|
||||
id
|
||||
commitSHA
|
||||
@@ -20,5 +24,12 @@ query getProjects($orgSlug: String!) {
|
||||
email
|
||||
displayName
|
||||
}
|
||||
appStates(order_by: { createdAt: desc }, limit: 1) {
|
||||
id
|
||||
appId
|
||||
message
|
||||
stateId
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
dashboard/src/utils/__generated__/graphql.ts
generated
24
dashboard/src/utils/__generated__/graphql.ts
generated
@@ -2946,6 +2946,7 @@ export type ConfigSystemConfig = {
|
||||
__typename?: 'ConfigSystemConfig';
|
||||
auth?: Maybe<ConfigSystemConfigAuth>;
|
||||
graphql?: Maybe<ConfigSystemConfigGraphql>;
|
||||
persistentVolumesEncrypted?: Maybe<Scalars['Boolean']>;
|
||||
postgres: ConfigSystemConfigPostgres;
|
||||
};
|
||||
|
||||
@@ -3015,6 +3016,7 @@ export type ConfigSystemConfigComparisonExp = {
|
||||
_or?: InputMaybe<Array<ConfigSystemConfigComparisonExp>>;
|
||||
auth?: InputMaybe<ConfigSystemConfigAuthComparisonExp>;
|
||||
graphql?: InputMaybe<ConfigSystemConfigGraphqlComparisonExp>;
|
||||
persistentVolumesEncrypted?: InputMaybe<ConfigBooleanComparisonExp>;
|
||||
postgres?: InputMaybe<ConfigSystemConfigPostgresComparisonExp>;
|
||||
};
|
||||
|
||||
@@ -3045,6 +3047,7 @@ export type ConfigSystemConfigGraphqlUpdateInput = {
|
||||
export type ConfigSystemConfigInsertInput = {
|
||||
auth?: InputMaybe<ConfigSystemConfigAuthInsertInput>;
|
||||
graphql?: InputMaybe<ConfigSystemConfigGraphqlInsertInput>;
|
||||
persistentVolumesEncrypted?: InputMaybe<Scalars['Boolean']>;
|
||||
postgres: ConfigSystemConfigPostgresInsertInput;
|
||||
};
|
||||
|
||||
@@ -3143,6 +3146,7 @@ export type ConfigSystemConfigPostgresUpdateInput = {
|
||||
export type ConfigSystemConfigUpdateInput = {
|
||||
auth?: InputMaybe<ConfigSystemConfigAuthUpdateInput>;
|
||||
graphql?: InputMaybe<ConfigSystemConfigGraphqlUpdateInput>;
|
||||
persistentVolumesEncrypted?: InputMaybe<Scalars['Boolean']>;
|
||||
postgres?: InputMaybe<ConfigSystemConfigPostgresUpdateInput>;
|
||||
};
|
||||
|
||||
@@ -13334,6 +13338,7 @@ export type Mutation_Root = {
|
||||
delete_regions?: Maybe<Regions_Mutation_Response>;
|
||||
/** delete single row from the table: "regions" */
|
||||
delete_regions_by_pk?: Maybe<Regions>;
|
||||
encryptPersistentVolumes: Scalars['Boolean'];
|
||||
/** insert a single row into the table: "announcements_read" */
|
||||
insertAnnouncementRead?: Maybe<Announcements_Read>;
|
||||
/** insert data into the table: "announcements_read" */
|
||||
@@ -14659,6 +14664,12 @@ export type Mutation_RootDelete_Regions_By_PkArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootEncryptPersistentVolumesArgs = {
|
||||
appID: Scalars['uuid'];
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootInsertAnnouncementReadArgs = {
|
||||
object: Announcements_Read_Insert_Input;
|
||||
@@ -27840,7 +27851,7 @@ export type GetProjectsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type GetProjectsQuery = { __typename?: 'query_root', apps: Array<{ __typename?: 'apps', id: any, name: string, slug: string, createdAt: any, subdomain: string, deployments: Array<{ __typename?: 'deployments', id: any, commitSHA: string, commitMessage?: string | null, commitUserName?: string | null, deploymentStartedAt?: any | null, deploymentEndedAt?: any | null, commitUserAvatarUrl?: string | null, deploymentStatus?: string | null }>, creator?: { __typename?: 'users', id: any, email?: any | null, displayName: string } | null }> };
|
||||
export type GetProjectsQuery = { __typename?: 'query_root', apps: Array<{ __typename?: 'apps', id: any, name: string, slug: string, createdAt: any, subdomain: string, region: { __typename?: 'regions', id: any, name: string }, deployments: Array<{ __typename?: 'deployments', id: any, commitSHA: string, commitMessage?: string | null, commitUserName?: string | null, deploymentStartedAt?: any | null, deploymentEndedAt?: any | null, commitUserAvatarUrl?: string | null, deploymentStatus?: string | null }>, creator?: { __typename?: 'users', id: any, email?: any | null, displayName: string } | null, appStates: Array<{ __typename?: 'appStateHistory', id: any, appId: any, message?: string | null, stateId: number, createdAt: any }> }> };
|
||||
|
||||
export type InsertOrgApplicationMutationVariables = Exact<{
|
||||
app: Apps_Insert_Input;
|
||||
@@ -32463,6 +32474,10 @@ export const GetProjectsDocument = gql`
|
||||
slug
|
||||
createdAt
|
||||
subdomain
|
||||
region {
|
||||
id
|
||||
name
|
||||
}
|
||||
deployments(limit: 4, order_by: {deploymentStartedAt: desc}) {
|
||||
id
|
||||
commitSHA
|
||||
@@ -32478,6 +32493,13 @@ export const GetProjectsDocument = gql`
|
||||
email
|
||||
displayName
|
||||
}
|
||||
appStates(order_by: {createdAt: desc}, limit: 1) {
|
||||
id
|
||||
appId
|
||||
message
|
||||
stateId
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost/docs
|
||||
|
||||
## 2.23.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 14e6100: feat: add documentation for sign-in with ID token
|
||||
|
||||
## 2.22.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -34,6 +34,9 @@ nhost
|
||||
│ │ ├── password-reset
|
||||
│ │ │ ├── body.html
|
||||
│ │ │ └── subject.txt
|
||||
│ │ ├── signin-otp
|
||||
│ │ │ ├── body.html
|
||||
│ │ │ └── subject.txt
|
||||
│ │ ├── signin-passwordless
|
||||
│ │ │ ├── body.html
|
||||
│ │ │ └── subject.txt
|
||||
@@ -49,6 +52,9 @@ nhost
|
||||
│ ├── password-reset
|
||||
│ │ ├── body.html
|
||||
│ │ └── subject.txt
|
||||
│ ├── signin-otp
|
||||
│ │ ├── body.html
|
||||
│ │ └── subject.txt
|
||||
│ ├── signin-passwordless
|
||||
│ │ ├── body.html
|
||||
│ │ └── subject.txt
|
||||
@@ -82,7 +88,7 @@ The following variables are available to all email templates:
|
||||
| `serverUrl` | URL of the authentication server |
|
||||
| `clientUrl` | URL of your client app |
|
||||
| `redirectTo` | URL where the user will be redirected to after clicking the link and finishing the action of the email |
|
||||
| `ticket` | Ticket that is used to authorize the link request |
|
||||
| `ticket` | Ticket or OTP that is used to authorize the request. |
|
||||
| `displayName` | The display name of the user |
|
||||
| `email` | The email of the user |
|
||||
| `locale` | Locale of the user as a two-letter language code (e.g. "en") |
|
||||
|
||||
93
docs/guides/auth/sign-in-idtokens.mdx
Normal file
93
docs/guides/auth/sign-in-idtokens.mdx
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: Sign In with ID tokens
|
||||
sidebarTitle: IDTokens
|
||||
description: Learn about ID tokens
|
||||
icon: binary
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
ID tokens are tokens provided by identity providers that contain authenticated user information and are specifically designed for authentication purposes, unlike access tokens which are used for authorization. ID tokens include claims about the user's identity, such as user ID, name, and email, along with metadata like token expiration time and intended audience.
|
||||
|
||||
ID tokens serve as a secure proof that a user has already been authenticated by a trusted identity provider. When someone logs in through their device's built-in authentication (like Sign in with Apple on iOS/macOS or Google Sign-in on Android), the system generates an ID token. This token can then be passed to your authentication service, confirming the user's identity without requiring them to log in again. This streamlined approach works with any OpenID Connect (OIDC) provider, including popular services like Google One Tap sign-in, making the authentication process both secure and user-friendly.
|
||||
|
||||
## Usage
|
||||
|
||||
To use ID tokens, you need to configure supported identity providers (currently [apple](/guides/auth/social/sign-in-apple) and [google](/guides/auth/social/sign-in-google)) and make sure the `audience` is set correctly.
|
||||
|
||||
### Sign in
|
||||
|
||||
Once everything is configured you can use an ID token to authenticate users with just a single call:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="javascript">
|
||||
```js
|
||||
nhost.auth.signInIdToken({
|
||||
provider: 'google', // The provider name, e.g., 'google', 'apple', etc.
|
||||
idToken: '...', // The ID token issued by the provider.
|
||||
nonce: '...' // Optional: The nonce used during token generation.
|
||||
})
|
||||
```
|
||||
|
||||
</Tab>
|
||||
|
||||
{' '}
|
||||
<Tab title="react">See [react docs](/reference/react/use-sign-in-id-token) for details</Tab>
|
||||
|
||||
{' '}
|
||||
<Tab title="vue">See [vue docs](/reference/react/use-sign-in-id-token) for details</Tab>
|
||||
|
||||
<Tab title="dart">
|
||||
```dart
|
||||
nhost.auth.signInIdToken(provider: 'google', idToken: '...', nonce: '...');
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Link Provider to existing user
|
||||
|
||||
Similarly to the [Social Connect](/guides/auth/social-connect) feature, you can link an identity provider to an existing user:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="javascript">
|
||||
```js
|
||||
nhost.auth.linkIdToken({
|
||||
provider: 'google', // The provider name, e.g., 'google', 'apple', etc.
|
||||
idToken: '...', // The ID token issued by the provider.
|
||||
nonce: '...' // Optional: The nonce used during token generation.
|
||||
})
|
||||
```
|
||||
|
||||
{' '}
|
||||
<Note>Keep in mind this is an authenticated method so the user must be logged in already.</Note>
|
||||
|
||||
</Tab>
|
||||
|
||||
{' '}
|
||||
<Tab title="react">See [react docs](/reference/react/use-link-id-token) for details</Tab>
|
||||
|
||||
{' '}
|
||||
<Tab title="vue">See [vue docs](/reference/vue/use-link-id-token) for details</Tab>
|
||||
|
||||
<Tab title="dart">
|
||||
```dart
|
||||
nhost.auth.linkIdToken(provider: 'google', idToken: '...', nonce: '...');
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Examples
|
||||
|
||||
Below you can find some examples on how to extract an ID Token from various identity providers to be used with the Auth service. Keep in mind these are just some examples, use cases and sources are not limited to the examples below.
|
||||
|
||||
### React Native
|
||||
|
||||
#### Apple
|
||||
|
||||
For an example on how to authenticate using "Sign in with Apple" on iOS using React Native you can refer to our [sample component](https://github.com/nhost/nhost/blob/main/examples/react_native/src/components/SignInWithAppleButton.tsx).
|
||||
|
||||
#### Google
|
||||
|
||||
For an example on how to authenticate using "Sign in with Google" on Android using React Native you can refer to our [sample component](https://github.com/nhost/nhost/blob/main/examples/react_native/src/components/SignInWithGoogleButton.tsx).
|
||||
@@ -40,7 +40,7 @@ The domains in the URLs above will all return the IP address for localhost, `127
|
||||
local.auth.local.nhost.run has address 127.0.0.1
|
||||
```
|
||||
|
||||
However, those URLs are powered by a dynamic DNS that can return any IPv4 address you need, you just need to replace the subdomain `local` with a `subdomain` that contains the 4 octets of the IPv4 adress you want separated by `-`. For instance:
|
||||
However, those URLs are powered by a dynamic DNS that can return any IPv4 address you need, you just need to replace the subdomain `local` with a `subdomain` that contains the 4 octets of the IPv4 address you want separated by `-`. For instance:
|
||||
|
||||
```
|
||||
> host 192-168-100-1.auth.local.nhost.run
|
||||
@@ -52,6 +52,13 @@ However, those URLs are powered by a dynamic DNS that can return any IPv4 addres
|
||||
|
||||
This is useful if you need to connect to your environment from a different device, a VM or a mobile device emulator.
|
||||
|
||||
<Warning>
|
||||
Some ISPs filter DNS responses that point to localhost and/or private IP space. If your provider is one of them you may have troubles accessing your local dev environment. As a workaround you have two options:
|
||||
|
||||
1. Follow the instructions under [offline access](/guides/cli/subdomain#offline-access) to create static DNS entries in your machine.
|
||||
2. Configure your computer to use a different [DNS provider](https://privacysavvy.com/security/business/best-free-public-dns-servers/).
|
||||
</Warning>
|
||||
|
||||
To make use of this functionality you can start your development environment after setting the environment variable `NHOST_LOCAL_SUBDOMAIN` or passing the flag `--local-subdomain` :
|
||||
|
||||
```
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
{
|
||||
"$schema": "https://mintlify.com/schema.json",
|
||||
"name": "Documentation",
|
||||
"openapi": ["reference/openapi-auth.yaml", "reference/openapi-auth-old.yaml", "reference/openapi-storage.yaml"],
|
||||
"openapi": [
|
||||
"reference/openapi-auth.yaml",
|
||||
"reference/openapi-auth-old.yaml",
|
||||
"reference/openapi-storage.yaml"
|
||||
],
|
||||
"logo": {
|
||||
"dark": "/logo/dark.svg",
|
||||
"light": "/logo/light.svg"
|
||||
@@ -158,6 +162,7 @@
|
||||
"guides/auth/sign-in-magic-link",
|
||||
"guides/auth/sign-in-phone-number",
|
||||
"guides/auth/sign-in-webauthn",
|
||||
"guides/auth/sign-in-idtokens",
|
||||
"guides/auth/elevated-permissions",
|
||||
"guides/auth/bot-protection",
|
||||
"guides/auth/email-templates",
|
||||
@@ -347,7 +352,9 @@
|
||||
"reference/javascript/auth/elevate-email-security-key",
|
||||
"reference/javascript/auth/connect-provider",
|
||||
"reference/javascript/auth/sign-in-email-otp",
|
||||
"reference/javascript/auth/verify-email-otp"
|
||||
"reference/javascript/auth/verify-email-otp",
|
||||
"reference/javascript/auth/sign-in-id-token",
|
||||
"reference/javascript/auth/link-id-token"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -431,7 +438,9 @@
|
||||
"reference/react/use-user-is-anonymous",
|
||||
"reference/react/use-user-locale",
|
||||
"reference/react/use-user-roles",
|
||||
"reference/react/use-sign-in-email-otp"
|
||||
"reference/react/use-sign-in-email-otp",
|
||||
"reference/react/use-sign-in-id-token",
|
||||
"reference/react/use-link-id-token"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -479,7 +488,9 @@
|
||||
"reference/nextjs/use-user-is-anonymous",
|
||||
"reference/nextjs/use-user-locale",
|
||||
"reference/nextjs/use-user-roles",
|
||||
"reference/nextjs/use-sign-in-email-otp"
|
||||
"reference/nextjs/use-sign-in-email-otp",
|
||||
"reference/nextjs/use-sign-in-id-token",
|
||||
"reference/nextjs/use-link-id-token"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -522,7 +533,9 @@
|
||||
"reference/vue/use-elevate-security-key-email",
|
||||
"reference/vue/use-sign-in-email-security-key",
|
||||
"reference/vue/use-sign-up-email-security-key",
|
||||
"reference/vue/use-sign-in-email-otp"
|
||||
"reference/vue/use-sign-in-email-otp",
|
||||
"reference/vue/use-sign-in-id-token",
|
||||
"reference/vue/use-link-id-token"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/docs",
|
||||
"version": "2.22.0",
|
||||
"version": "2.23.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "mintlify dev"
|
||||
|
||||
@@ -21,7 +21,9 @@ Combined with a powerful **Permission Rules** system, Nhost Auth offers everythi
|
||||
</Card>
|
||||
<Card title="Security Keys (WebAuthn)" icon="square-5" href="../guides/auth/sign-in-webauthn">
|
||||
</Card>
|
||||
<Card title="Elevated Permissions" icon="square-6" href="../guides/auth/elevated-permissions">
|
||||
<Card title="ID Tokens" icon="square-6" href="../guides/auth/sign-in-idtokens">
|
||||
</Card>
|
||||
<Card title="Elevated Permissions" icon="square-7" href="../guides/auth/elevated-permissions">
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
28
docs/reference/javascript/auth/link-id-token.mdx
Normal file
28
docs/reference/javascript/auth/link-id-token.mdx
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: linkIdToken()
|
||||
sidebarTitle: linkIdToken()
|
||||
---
|
||||
|
||||
Use `nhost.auth.linkIdToken` to link a user account with the provider's account using an ID token
|
||||
|
||||
```ts
|
||||
nhost.auth.linkIdToken({
|
||||
provider: 'google', // The provider name, e.g., 'google', 'apple', etc.
|
||||
idToken: '...', // The ID token issued by the provider.
|
||||
nonce: '...' // Optional: The nonce used during token generation.
|
||||
})
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`LinkIdTokenParams`](/reference/javascript/auth/types/link-id-token-params)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :------------------------------------------------------------------------------------------ | :------------------------------------------------------ | :------: | :---- |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>idToken</span> | <code>string</code> | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>provider</span> | [`Provider`](/reference/javascript/auth/types/provider) | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>nonce</span> | <code>string</code> | | |
|
||||
|
||||
---
|
||||
28
docs/reference/javascript/auth/sign-in-id-token.mdx
Normal file
28
docs/reference/javascript/auth/sign-in-id-token.mdx
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: signInIdToken()
|
||||
sidebarTitle: signInIdToken()
|
||||
---
|
||||
|
||||
Use `nhost.auth.signInIdToken` to sign in a user with the provider's account using an ID token
|
||||
|
||||
```ts
|
||||
nhost.auth.signInIdToken({
|
||||
provider: 'google', // The provider name, e.g., 'google', 'apple', etc.
|
||||
idToken: '...', // The ID token issued by the provider.
|
||||
nonce: '...' // Optional: The nonce used during token generation.
|
||||
})
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`SignInIdTokenParams`](/reference/javascript/auth/types/sign-in-id-token-params)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :------------------------------------------------------------------------------------------ | :------------------------------------------------------ | :------: | :---- |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>idToken</span> | <code>string</code> | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>provider</span> | [`Provider`](/reference/javascript/auth/types/provider) | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>nonce</span> | <code>string</code> | | |
|
||||
|
||||
---
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: LinkIdTokenHandlerParams
|
||||
sidebarTitle: LinkIdTokenHandlerParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenHandlerParams`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">idToken</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">provider</span>** <span className="optional-status">required</span> [`Provider`](/reference/javascript/auth/types/provider)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">nonce</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: LinkIdTokenHandlerResult
|
||||
sidebarTitle: LinkIdTokenHandlerResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenHandlerResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`AuthErrorPayload`](/reference/javascript/auth/types/auth-error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: LinkIdTokenParams
|
||||
sidebarTitle: LinkIdTokenParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenParams`
|
||||
|
||||
```ts
|
||||
type LinkIdTokenParams = () => { idToken: string, provider: [Provider](/reference/javascript/auth/types/provider), nonce: string }
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: SignInIdTokenHandlerParams
|
||||
sidebarTitle: SignInIdTokenHandlerParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenHandlerParams`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">idToken</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">provider</span>** <span className="optional-status">required</span> [`Provider`](/reference/javascript/auth/types/provider)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">nonce</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: SignInIdTokenHandlerResult
|
||||
sidebarTitle: SignInIdTokenHandlerResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenHandlerResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`AuthErrorPayload`](/reference/javascript/auth/types/auth-error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> <code>null | [`User`](/reference/javascript/auth/types/user)</code>
|
||||
|
||||
User information
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: SignInIdTokenParams
|
||||
sidebarTitle: SignInIdTokenParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenParams`
|
||||
|
||||
```ts
|
||||
type SignInIdTokenParams = () => { idToken: string, provider: [Provider](/reference/javascript/auth/types/provider), nonce: string }
|
||||
```
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: SignInIdTokenState
|
||||
sidebarTitle: SignInIdTokenState
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenState`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`AuthErrorPayload`](/reference/javascript/auth/types/auth-error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` when the action is executing, `false` when it finished its execution.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> <code>null | [`User`](/reference/javascript/auth/types/user)</code>
|
||||
|
||||
User information
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
28
docs/reference/javascript/nhost-js/link-id-token.mdx
Normal file
28
docs/reference/javascript/nhost-js/link-id-token.mdx
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: linkIdToken()
|
||||
sidebarTitle: linkIdToken()
|
||||
---
|
||||
|
||||
Use `nhost.auth.linkIdToken` to link a user account with the provider's account using an ID token
|
||||
|
||||
```ts
|
||||
nhost.auth.linkIdToken({
|
||||
provider: 'google', // The provider name, e.g., 'google', 'apple', etc.
|
||||
idToken: '...', // The ID token issued by the provider.
|
||||
nonce: '...' // Optional: The nonce used during token generation.
|
||||
})
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`LinkIdTokenParams`](/reference/javascript/nhost-js/types/link-id-token-params)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :------------------------------------------------------------------------------------------ | :---------------------------------------------------------- | :------: | :---- |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>idToken</span> | <code>string</code> | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>provider</span> | [`Provider`](/reference/javascript/nhost-js/types/provider) | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>nonce</span> | <code>string</code> | | |
|
||||
|
||||
---
|
||||
28
docs/reference/javascript/nhost-js/sign-in-id-token.mdx
Normal file
28
docs/reference/javascript/nhost-js/sign-in-id-token.mdx
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: signInIdToken()
|
||||
sidebarTitle: signInIdToken()
|
||||
---
|
||||
|
||||
Use `nhost.auth.signInIdToken` to sign in a user with the provider's account using an ID token
|
||||
|
||||
```ts
|
||||
nhost.auth.signInIdToken({
|
||||
provider: 'google', // The provider name, e.g., 'google', 'apple', etc.
|
||||
idToken: '...', // The ID token issued by the provider.
|
||||
nonce: '...' // Optional: The nonce used during token generation.
|
||||
})
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`SignInIdTokenParams`](/reference/javascript/nhost-js/types/sign-in-id-token-params)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :------------------------------------------------------------------------------------------ | :---------------------------------------------------------- | :------: | :---- |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>idToken</span> | <code>string</code> | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>provider</span> | [`Provider`](/reference/javascript/nhost-js/types/provider) | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>nonce</span> | <code>string</code> | | |
|
||||
|
||||
---
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: LinkIdTokenHandlerParams
|
||||
sidebarTitle: LinkIdTokenHandlerParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenHandlerParams`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">idToken</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">provider</span>** <span className="optional-status">required</span> [`Provider`](/reference/javascript/nhost-js/types/provider)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">nonce</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: LinkIdTokenHandlerResult
|
||||
sidebarTitle: LinkIdTokenHandlerResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenHandlerResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`AuthErrorPayload`](/reference/javascript/nhost-js/types/auth-error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: LinkIdTokenParams
|
||||
sidebarTitle: LinkIdTokenParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenParams`
|
||||
|
||||
```ts
|
||||
type LinkIdTokenParams = () => { idToken: string, provider: [Provider](/reference/javascript/nhost-js/types/provider), nonce: string }
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: SignInIdTokenHandlerParams
|
||||
sidebarTitle: SignInIdTokenHandlerParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenHandlerParams`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">idToken</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">provider</span>** <span className="optional-status">required</span> [`Provider`](/reference/javascript/nhost-js/types/provider)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">nonce</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: SignInIdTokenHandlerResult
|
||||
sidebarTitle: SignInIdTokenHandlerResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenHandlerResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`AuthErrorPayload`](/reference/javascript/nhost-js/types/auth-error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> <code>null | [`User`](/reference/javascript/nhost-js/types/user)</code>
|
||||
|
||||
User information
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: SignInIdTokenParams
|
||||
sidebarTitle: SignInIdTokenParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenParams`
|
||||
|
||||
```ts
|
||||
type SignInIdTokenParams = () => { idToken: string, provider: [Provider](/reference/javascript/nhost-js/types/provider), nonce: string }
|
||||
```
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: SignInIdTokenState
|
||||
sidebarTitle: SignInIdTokenState
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenState`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`AuthErrorPayload`](/reference/javascript/nhost-js/types/auth-error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` when the action is executing, `false` when it finished its execution.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> <code>null | [`User`](/reference/javascript/nhost-js/types/user)</code>
|
||||
|
||||
User information
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
39
docs/reference/nextjs/types/link-id-token-hook-result.mdx
Normal file
39
docs/reference/nextjs/types/link-id-token-hook-result.mdx
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: LinkIdTokenHookResult
|
||||
sidebarTitle: LinkIdTokenHookResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenHookResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`ErrorPayload`](/reference/nextjs/types/error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">linkIdToken</span>** <span className="optional-status">required</span> <code>LinkIdTokenHandler</code>
|
||||
|
||||
---
|
||||
65
docs/reference/nextjs/types/sign-in-id-token-hook-result.mdx
Normal file
65
docs/reference/nextjs/types/sign-in-id-token-hook-result.mdx
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: SignInIdTokenHookResult
|
||||
sidebarTitle: SignInIdTokenHookResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenHookResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | AuthErrorPayload</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` when the action is executing, `false` when it finished its execution.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> <code>null | [`User`](/reference/nextjs/types/user)</code>
|
||||
|
||||
User information
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">signInIdToken</span>** <span className="optional-status">required</span> <code>SignInIdTokenHandler</code>
|
||||
|
||||
---
|
||||
20
docs/reference/nextjs/use-link-id-token.mdx
Normal file
20
docs/reference/nextjs/use-link-id-token.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: useLinkIdToken()
|
||||
sidebarTitle: useLinkIdToken()
|
||||
---
|
||||
|
||||
Use the hook `useLinkIdToken` to link a user account with the provider's account using an id token
|
||||
|
||||
```tsx
|
||||
const { linkIdToken, isLoading, isSuccess, isError, error } = useLinkIdToken()
|
||||
|
||||
const handleFormSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
await linkIdToken({
|
||||
provider: 'google',
|
||||
idToken: '...',
|
||||
nonce: '...'
|
||||
})
|
||||
}
|
||||
```
|
||||
19
docs/reference/nextjs/use-sign-in-id-token.mdx
Normal file
19
docs/reference/nextjs/use-sign-in-id-token.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: useSignInIdToken()
|
||||
sidebarTitle: useSignInIdToken()
|
||||
---
|
||||
|
||||
Use the hook `useSignInIdToken` to sign in a user using an `idToken`.
|
||||
|
||||
```tsx
|
||||
const { signInIdToken, isLoading, isSuccess, isError, error } =
|
||||
useSignInIdToken()
|
||||
|
||||
console.log({ isLoading, isSuccess, isError, error })
|
||||
|
||||
const handleFormSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
await signInIdToken({ provider: 'google', idToken: '...' })
|
||||
}
|
||||
```
|
||||
39
docs/reference/react/types/link-id-token-hook-result.mdx
Normal file
39
docs/reference/react/types/link-id-token-hook-result.mdx
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: LinkIdTokenHookResult
|
||||
sidebarTitle: LinkIdTokenHookResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenHookResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | [`ErrorPayload`](/reference/react/types/error-payload)</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">linkIdToken</span>** <span className="optional-status">required</span> <code>LinkIdTokenHandler</code>
|
||||
|
||||
---
|
||||
65
docs/reference/react/types/sign-in-id-token-hook-result.mdx
Normal file
65
docs/reference/react/types/sign-in-id-token-hook-result.mdx
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: SignInIdTokenHookResult
|
||||
sidebarTitle: SignInIdTokenHookResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `SignInIdTokenHookResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>null | AuthErrorPayload</code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` when the action is executing, `false` when it finished its execution.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>boolean</code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> <code>null | [`User`](/reference/react/types/user)</code>
|
||||
|
||||
User information
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshToken</span>** <span className="optional-status">required</span> <code>null | string</code>
|
||||
|
||||
Access token (JWT)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">signInIdToken</span>** <span className="optional-status">required</span> <code>SignInIdTokenHandler</code>
|
||||
|
||||
---
|
||||
20
docs/reference/react/use-link-id-token.mdx
Normal file
20
docs/reference/react/use-link-id-token.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: useLinkIdToken()
|
||||
sidebarTitle: useLinkIdToken()
|
||||
---
|
||||
|
||||
Use the hook `useLinkIdToken` to link a user account with the provider's account using an id token
|
||||
|
||||
```tsx
|
||||
const { linkIdToken, isLoading, isSuccess, isError, error } = useLinkIdToken()
|
||||
|
||||
const handleFormSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
await linkIdToken({
|
||||
provider: 'google',
|
||||
idToken: '...',
|
||||
nonce: '...'
|
||||
})
|
||||
}
|
||||
```
|
||||
19
docs/reference/react/use-sign-in-id-token.mdx
Normal file
19
docs/reference/react/use-sign-in-id-token.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: useSignInIdToken()
|
||||
sidebarTitle: useSignInIdToken()
|
||||
---
|
||||
|
||||
Use the hook `useSignInIdToken` to sign in a user using an `idToken`.
|
||||
|
||||
```tsx
|
||||
const { signInIdToken, isLoading, isSuccess, isError, error } =
|
||||
useSignInIdToken()
|
||||
|
||||
console.log({ isLoading, isSuccess, isError, error })
|
||||
|
||||
const handleFormSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
await signInIdToken({ provider: 'google', idToken: '...' })
|
||||
}
|
||||
```
|
||||
47
docs/reference/vue/types/link-id-token-result.mdx
Normal file
47
docs/reference/vue/types/link-id-token-result.mdx
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: LinkIdTokenResult
|
||||
sidebarTitle: LinkIdTokenResult
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `LinkIdTokenResult`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> <code>Ref<boolean></code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` if an error occurred
|
||||
|
||||
**`@depreacted`**
|
||||
|
||||
use `!isSuccess` or `!!error` instead
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> <code>Ref<null | ErrorPayload<any>></code>
|
||||
|
||||
Provides details about the error
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> <code>Ref<boolean></code>
|
||||
|
||||
**`@returns`**
|
||||
|
||||
`true` when the action is executing, `false` when it finished its execution.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> <code>Ref<boolean></code>
|
||||
|
||||
Returns `true` if the action is successful.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">linkIdToken</span>** <span className="optional-status">required</span> <code>(params: LinkIdTokenHandlerParams) => Promise<LinkIdTokenHandlerResult></code>
|
||||
|
||||
---
|
||||
18
docs/reference/vue/use-link-id-token.mdx
Normal file
18
docs/reference/vue/use-link-id-token.mdx
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: useLinkIdToken()
|
||||
sidebarTitle: useLinkIdToken()
|
||||
---
|
||||
|
||||
Use the hook `useLinkIdToken` to link a user account with the provider's account using an id token
|
||||
|
||||
```tsx
|
||||
const { linkIdToken, isLoading, isSuccess, isError, error } = useLinkIdToken()
|
||||
|
||||
const handleLinkIdToken = async () => {
|
||||
await linkIdToken({
|
||||
provider: 'google',
|
||||
idToken: '...',
|
||||
nonce: '...'
|
||||
})
|
||||
}
|
||||
```
|
||||
17
docs/reference/vue/use-sign-in-id-token.mdx
Normal file
17
docs/reference/vue/use-sign-in-id-token.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: useSignInIdToken()
|
||||
sidebarTitle: useSignInIdToken()
|
||||
---
|
||||
|
||||
Use the composable `useSignInIdToken` to sign in a user using an `idToken`.
|
||||
|
||||
```ts
|
||||
const { signInIdToken, isLoading, isSuccess, isError, error } =
|
||||
useSignInIdToken()
|
||||
|
||||
console.log({ isLoading, isSuccess, isError, error })
|
||||
|
||||
const handleSignInIdToken = async () => {
|
||||
await signInIdToken({ provider: 'google', idToken: '...' })
|
||||
}
|
||||
```
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost-examples/cli
|
||||
|
||||
## 0.3.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @nhost/nhost-js@3.2.1
|
||||
|
||||
## 0.3.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/cli",
|
||||
"version": "0.3.13",
|
||||
"version": "0.3.14",
|
||||
"main": "src/index.mjs",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/codegen-react-apollo
|
||||
|
||||
## 0.4.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
- @nhost/react-apollo@15.0.0
|
||||
|
||||
## 0.4.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/codegen-react-apollo",
|
||||
"version": "0.4.14",
|
||||
"version": "0.4.15",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"codegen": "graphql-codegen",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @nhost-examples/codegen-react-query
|
||||
|
||||
## 0.4.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
|
||||
## 0.4.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/codegen-react-query",
|
||||
"version": "0.4.14",
|
||||
"version": "0.4.15",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"codegen": "graphql-codegen",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/react-urql
|
||||
|
||||
## 0.3.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
- @nhost/react-urql@12.0.0
|
||||
|
||||
## 0.3.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/codegen-react-urql",
|
||||
"private": true,
|
||||
"version": "0.3.14",
|
||||
"version": "0.3.15",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost-examples/multi-tenant-one-to-many
|
||||
|
||||
## 2.2.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @nhost/nhost-js@3.2.1
|
||||
|
||||
## 2.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/multi-tenant-one-to-many",
|
||||
"private": true,
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.15",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {},
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @nhost-examples/nextjs
|
||||
|
||||
## 0.3.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
- @nhost/react-apollo@15.0.0
|
||||
- @nhost/nextjs@2.1.24
|
||||
|
||||
## 0.3.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/nextjs",
|
||||
"version": "0.3.14",
|
||||
"version": "0.3.15",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost-examples/node-storage
|
||||
|
||||
## 0.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @nhost/nhost-js@3.2.1
|
||||
|
||||
## 0.2.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/node-storage",
|
||||
"version": "0.2.13",
|
||||
"version": "0.2.14",
|
||||
"private": true,
|
||||
"description": "This is an example of how to use the Storage with Node.js",
|
||||
"main": "src/index.mjs",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost-examples/nextjs-server-components
|
||||
|
||||
## 0.4.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @nhost/nhost-js@3.2.1
|
||||
|
||||
## 0.4.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/nextjs-server-components",
|
||||
"version": "0.4.15",
|
||||
"version": "0.4.16",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/react-apollo
|
||||
|
||||
## 1.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
- @nhost/react-apollo@15.0.0
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/react-apollo",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @nhost-examples/react-gqty
|
||||
|
||||
## 1.2.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
|
||||
## 1.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/react-gqty",
|
||||
"private": true,
|
||||
"version": "1.2.14",
|
||||
"version": "1.2.15",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
hoist-pattern=false
|
||||
shamefully-hoist=false
|
||||
@@ -1,5 +1,17 @@
|
||||
# @nhost-examples/react-native
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 14e6100: feat: add signIn with Google and Apple using an ID token
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/react@3.8.0
|
||||
- @nhost/react-apollo@15.0.0
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
jest.mock('@react-native-google-signin/google-signin', () => ({
|
||||
GoogleSignin: {
|
||||
configure: jest.fn(),
|
||||
signIn: jest.fn(() => Promise.resolve({idToken: 'test-token'})),
|
||||
hasPlayServices: jest.fn(() => Promise.resolve(true)),
|
||||
},
|
||||
}));
|
||||
3
examples/react_native/__mocks__/react-native-simple-toast.js
vendored
Normal file
3
examples/react_native/__mocks__/react-native-simple-toast.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
show: jest.fn(),
|
||||
};
|
||||
@@ -74,9 +74,9 @@ android {
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
|
||||
namespace "com.react_native"
|
||||
namespace "io.nhost.react_native"
|
||||
defaultConfig {
|
||||
applicationId "com.react_native"
|
||||
applicationId "io.nhost.react_native"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.react_native
|
||||
package io.nhost.react_native
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.facebook.react.ReactActivity
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.react_native
|
||||
package io.nhost.react_native
|
||||
|
||||
import android.app.Application
|
||||
import com.facebook.react.PackageList
|
||||
|
||||
@@ -2,6 +2,7 @@ module.exports = {
|
||||
presets: ['module:@react-native/babel-preset'],
|
||||
plugins: [
|
||||
'@babel/plugin-transform-export-namespace-from',
|
||||
'module:react-native-dotenv',
|
||||
'react-native-reanimated/plugin',
|
||||
[
|
||||
'module-resolver',
|
||||
|
||||
@@ -2,13 +2,17 @@ HASURA_GRAPHQL_ADMIN_SECRET='nhost-admin-secret'
|
||||
HASURA_GRAPHQL_JWT_SECRET='oqpdwyffgxncqamwlyebkaifyazvqgso'
|
||||
NHOST_WEBHOOK_SECRET='nhost-webhook-secret'
|
||||
GRAFANA_ADMIN_PASSWORD='FIXME'
|
||||
|
||||
APPLE_TEAM_ID = 'FIXME'
|
||||
APPLE_SERVICE_IDENTIFIER = 'FIXME'
|
||||
APPLE_KEY_ID = 'FIXME'
|
||||
APPLE_PRIVATE_KEY = ''
|
||||
APPLE_AUDIENCE = ''
|
||||
|
||||
GITHUB_CLIENT_ID = 'FIXME'
|
||||
GITHUB_CLIENT_SECRET = 'FIXME'
|
||||
GOOGLE_CLIENT_ID = 'FIXME'
|
||||
GOOGLE_CLIENT_SECRET = 'FIXME'
|
||||
|
||||
LINKEDIN_CLIENT_ID = 'FIXME'
|
||||
LINKEDIN_CLIENT_SECRET = 'FIXME'
|
||||
|
||||
@@ -46,3 +46,26 @@ object_relationships:
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: user_id
|
||||
select_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- access_token
|
||||
- provider_id
|
||||
- provider_user_id
|
||||
- refresh_token
|
||||
- created_at
|
||||
- updated_at
|
||||
- id
|
||||
- user_id
|
||||
filter:
|
||||
user_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
comment: ""
|
||||
delete_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
filter:
|
||||
user_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
comment: ""
|
||||
|
||||
@@ -30,7 +30,7 @@ httpPoolSize = 100
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.30.0'
|
||||
version = '0.36.1'
|
||||
|
||||
[auth.elevatedPrivileges]
|
||||
mode = 'disabled'
|
||||
@@ -90,6 +90,7 @@ clientId = '{{ secrets.APPLE_SERVICE_IDENTIFIER }}'
|
||||
keyId = '{{ secrets.APPLE_KEY_ID }}'
|
||||
teamId = '{{ secrets.APPLE_TEAM_ID }}'
|
||||
privateKey = '{{ secrets.APPLE_PRIVATE_KEY }}'
|
||||
audience = '{{ secrets.APPLE_AUDIENCE }}'
|
||||
|
||||
[auth.method.oauth.azuread]
|
||||
tenant = 'common'
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
PODS:
|
||||
- AppAuth (1.7.5):
|
||||
- AppAuth/Core (= 1.7.5)
|
||||
- AppAuth/ExternalUserAgent (= 1.7.5)
|
||||
- AppAuth/Core (1.7.5)
|
||||
- AppAuth/ExternalUserAgent (1.7.5):
|
||||
- AppAuth/Core
|
||||
- boost (1.83.0)
|
||||
- CocoaAsyncSocket (7.6.5)
|
||||
- DoubleConversion (1.1.6)
|
||||
@@ -68,6 +74,14 @@ PODS:
|
||||
- FlipperKit/FlipperKitNetworkPlugin
|
||||
- fmt (6.2.1)
|
||||
- glog (0.3.5)
|
||||
- GoogleSignIn (7.1.0):
|
||||
- AppAuth (< 2.0, >= 1.7.3)
|
||||
- GTMAppAuth (< 5.0, >= 4.1.1)
|
||||
- GTMSessionFetcher/Core (~> 3.3)
|
||||
- GTMAppAuth (4.1.1):
|
||||
- AppAuth/Core (~> 1.7)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3)
|
||||
- GTMSessionFetcher/Core (3.5.0)
|
||||
- hermes-engine (0.73.7):
|
||||
- hermes-engine/Pre-built (= 0.73.7)
|
||||
- hermes-engine/Pre-built (0.73.7)
|
||||
@@ -944,10 +958,17 @@ PODS:
|
||||
- React-Mapbuffer (0.73.7):
|
||||
- glog
|
||||
- React-debug
|
||||
- react-native-document-picker (9.3.0):
|
||||
- react-native-document-picker (9.3.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2022.05.16.00)
|
||||
- React-Core
|
||||
- react-native-safe-area-context (4.10.5):
|
||||
- react-native-randombytes (3.6.1):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (4.10.9):
|
||||
- React-Core
|
||||
- react-native-simple-toast (3.3.1):
|
||||
- React-Core
|
||||
- Toast (~> 4)
|
||||
- React-nativeconfig (0.73.7)
|
||||
- React-NativeModulesApple (0.73.7):
|
||||
- glog
|
||||
@@ -1115,25 +1136,45 @@ PODS:
|
||||
- React-jsi (= 0.73.7)
|
||||
- React-logger (= 0.73.7)
|
||||
- React-perflogger (= 0.73.7)
|
||||
- RNCAsyncStorage (1.23.1):
|
||||
- RNAppleAuthentication (2.4.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.16.2):
|
||||
- RNCAsyncStorage (1.24.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.19.0):
|
||||
- glog
|
||||
- RCT-Folly (= 2022.05.16.00)
|
||||
- React-Core
|
||||
- RNGoogleSignin (13.1.0):
|
||||
- GoogleSignIn (~> 7.1)
|
||||
- React-Core
|
||||
- RNInAppBrowser (3.7.0):
|
||||
- React-Core
|
||||
- RNReanimated (3.12.0):
|
||||
- RNReanimated (3.15.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2022.05.16.00)
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- RNScreens (3.32.0):
|
||||
- RNReanimated/reanimated (= 3.15.1)
|
||||
- RNReanimated/worklets (= 3.15.1)
|
||||
- RNReanimated/reanimated (3.15.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2022.05.16.00)
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- RNReanimated/worklets (3.15.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2022.05.16.00)
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- RNScreens (3.34.0):
|
||||
- glog
|
||||
- RCT-Folly (= 2022.05.16.00)
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNSha256 (1.4.10):
|
||||
- React-Core
|
||||
- SocketRocket (0.6.1)
|
||||
- Toast (4.1.1)
|
||||
- Yoga (1.14.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
@@ -1190,7 +1231,9 @@ DEPENDENCIES:
|
||||
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
|
||||
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
|
||||
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
||||
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- react-native-simple-toast (from `../node_modules/react-native-simple-toast`)
|
||||
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
@@ -1211,15 +1254,19 @@ DEPENDENCIES:
|
||||
- React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
|
||||
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNAppleAuthentication (from `../node_modules/@invertase/react-native-apple-authentication`)"
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- "RNGoogleSignin (from `../node_modules/@react-native-google-signin/google-signin`)"
|
||||
- RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
- RNScreens (from `../node_modules/react-native-screens`)
|
||||
- RNSha256 (from `../node_modules/react-native-sha256`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- AppAuth
|
||||
- CocoaAsyncSocket
|
||||
- Flipper
|
||||
- Flipper-Boost-iOSX
|
||||
@@ -1230,9 +1277,13 @@ SPEC REPOS:
|
||||
- Flipper-PeerTalk
|
||||
- FlipperKit
|
||||
- fmt
|
||||
- GoogleSignIn
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
- libevent
|
||||
- OpenSSL-Universal
|
||||
- SocketRocket
|
||||
- Toast
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
boost:
|
||||
@@ -1292,8 +1343,12 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
react-native-document-picker:
|
||||
:path: "../node_modules/react-native-document-picker"
|
||||
react-native-randombytes:
|
||||
:path: "../node_modules/react-native-randombytes"
|
||||
react-native-safe-area-context:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-simple-toast:
|
||||
:path: "../node_modules/react-native-simple-toast"
|
||||
React-nativeconfig:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-NativeModulesApple:
|
||||
@@ -1334,20 +1389,27 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon/react/utils"
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
RNAppleAuthentication:
|
||||
:path: "../node_modules/@invertase/react-native-apple-authentication"
|
||||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNGoogleSignin:
|
||||
:path: "../node_modules/@react-native-google-signin/google-signin"
|
||||
RNInAppBrowser:
|
||||
:path: "../node_modules/react-native-inappbrowser-reborn"
|
||||
RNReanimated:
|
||||
:path: "../node_modules/react-native-reanimated"
|
||||
RNScreens:
|
||||
:path: "../node_modules/react-native-screens"
|
||||
RNSha256:
|
||||
:path: "../node_modules/react-native-sha256"
|
||||
Yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa
|
||||
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
|
||||
@@ -1363,6 +1425,9 @@ SPEC CHECKSUMS:
|
||||
FlipperKit: 37525a5d056ef9b93d1578e04bc3ea1de940094f
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
|
||||
GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db
|
||||
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
|
||||
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
||||
hermes-engine: 39589e9c297d024e90fe68f6830ff86c4e01498a
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
|
||||
@@ -1387,8 +1452,10 @@ SPEC CHECKSUMS:
|
||||
React-jsinspector: f356e49aa086380d3a4892708ca173ad31ac69c1
|
||||
React-logger: 7b19bdfb254772a0332d6cd4d66eceb0678b6730
|
||||
React-Mapbuffer: 6f392912435adb8fbf4c3eee0e79a0a0b4e4b717
|
||||
react-native-document-picker: 5b97e24a7f1a1e4a50a72c540a043f32d29a70a2
|
||||
react-native-safe-area-context: a240ad4b683349e48b1d51fed1611138d1bdad97
|
||||
react-native-document-picker: 23b6a82e09199f4f109376e73d88892a8931eeea
|
||||
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
|
||||
react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a
|
||||
react-native-simple-toast: 1f1cc551d419bc0ab05dcb0136554006c274789d
|
||||
React-nativeconfig: 754233aac2a769578f828093b672b399355582e6
|
||||
React-NativeModulesApple: a03b2da2b8e127d5f5ee29c683e0deba7a9e1575
|
||||
React-perflogger: 68ec84e2f858a3e35009aef8866b55893e5e0a1f
|
||||
@@ -1409,14 +1476,18 @@ SPEC CHECKSUMS:
|
||||
React-runtimescheduler: a884a55560e2a90caa1cbe0b9eaa24a5add4fa2c
|
||||
React-utils: d07d009101c7dabff68b710da5c4a47b7a850d98
|
||||
ReactCommon: 8cae78d3c3eceff20ee4bbca8bb73b675a45fd5d
|
||||
RNCAsyncStorage: 826b603ae9c0f88b5ac4e956801f755109fa4d5c
|
||||
RNGestureHandler: 96439cf6543defdde87459e48cd1a3f0e45a008e
|
||||
RNAppleAuthentication: e00c76acb03351f5544373c78fa7f359bef6d5d3
|
||||
RNCAsyncStorage: ec53e44dc3e75b44aa2a9f37618a49c3bc080a7a
|
||||
RNGestureHandler: 75e2ebf4e8ac521f2b3c9afdc048fcbc2e2c9ea4
|
||||
RNGoogleSignin: 9e68b9bcc3888219357924e32ee563624745647d
|
||||
RNInAppBrowser: e36d6935517101ccba0e875bac8ad7b0cb655364
|
||||
RNReanimated: 3a6dc95919aeb5a319ab24e560571f4e84991a15
|
||||
RNScreens: e842cdccb23c0a084bd6307f6fa83fd1c1738029
|
||||
RNReanimated: ca141907a2153dc45da331bafc0dc214f59bf4e2
|
||||
RNScreens: 29418ceffb585b8f0ebd363de304288c3dce8323
|
||||
RNSha256: e1bc64e9e50b293d5282bb4caa1b2043931f1c9d
|
||||
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
|
||||
Yoga: c716aea2ee01df6258550c7505fa61b248145ced
|
||||
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
||||
Yoga: 47d399a73c0c0caa9ff824e5c657eae31215bfee
|
||||
|
||||
PODFILE CHECKSUM: b631a3a7835105d1ea642d63b6f5644aa54a4e2f
|
||||
|
||||
COCOAPODS: 1.14.3
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
3B4392A12AC88292D35C810B /* Pods-react_native.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-react_native.debug.xcconfig"; path = "Target Support Files/Pods-react_native/Pods-react_native.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5709B34CF0A7D63546082F79 /* Pods-react_native.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-react_native.release.xcconfig"; path = "Target Support Files/Pods-react_native/Pods-react_native.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5B7EB9410499542E8C5724F5 /* Pods-react_native-react_nativeTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-react_native-react_nativeTests.debug.xcconfig"; path = "Target Support Files/Pods-react_native-react_nativeTests/Pods-react_native-react_nativeTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5C2E306B2CE6571D000FD88A /* react_native.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = react_native.entitlements; path = react_native/react_native.entitlements; sourceTree = "<group>"; };
|
||||
5C2F189D2BE2A7B2002C248D /* AntDesign.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = AntDesign.ttf; sourceTree = "<group>"; };
|
||||
5C2F189E2BE2A7B2002C248D /* Entypo.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Entypo.ttf; sourceTree = "<group>"; };
|
||||
5C2F189F2BE2A7B2002C248D /* EvilIcons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = EvilIcons.ttf; sourceTree = "<group>"; };
|
||||
@@ -124,6 +125,7 @@
|
||||
13B07FAE1A68108700A75B9A /* react_native */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5C2E306B2CE6571D000FD88A /* react_native.entitlements */,
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
@@ -550,10 +552,11 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = react_native/react_native.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = 589D3J8HPL;
|
||||
DEVELOPMENT_TEAM = C7HCKFA2LG;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = react_native/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -581,8 +584,9 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = react_native/react_native.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = GX7FJWGPEG;
|
||||
DEVELOPMENT_TEAM = C7HCKFA2LG;
|
||||
INFOPLIST_FILE = react_native/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
@@ -1,86 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>react_native</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>myapp</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>myapp</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>react_native</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<false/>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string></string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.googleusercontent.apps.936282223875-bhcoqne9s2d6qbpel40jh6damg79dv3i</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>None</string>
|
||||
</dict>
|
||||
<dict/>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<false/>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>AntDesign.ttf</string>
|
||||
<string>Entypo.ttf</string>
|
||||
<string>EvilIcons.ttf</string>
|
||||
<string>Feather.ttf</string>
|
||||
<string>FontAwesome.ttf</string>
|
||||
<string>FontAwesome5_Brands.ttf</string>
|
||||
<string>FontAwesome5_Regular.ttf</string>
|
||||
<string>FontAwesome5_Solid.ttf</string>
|
||||
<string>FontAwesome6_Brands.ttf</string>
|
||||
<string>FontAwesome6_Regular.ttf</string>
|
||||
<string>FontAwesome6_Solid.ttf</string>
|
||||
<string>Foundation.ttf</string>
|
||||
<string>Ionicons.ttf</string>
|
||||
<string>MaterialIcons.ttf</string>
|
||||
<string>MaterialCommunityIcons.ttf</string>
|
||||
<string>SimpleLineIcons.ttf</string>
|
||||
<string>Octicons.ttf</string>
|
||||
<string>Zocial.ttf</string>
|
||||
<string>Fontisto.ttf</string>
|
||||
</array>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>AntDesign.ttf</string>
|
||||
<string>Entypo.ttf</string>
|
||||
<string>EvilIcons.ttf</string>
|
||||
<string>Feather.ttf</string>
|
||||
<string>FontAwesome.ttf</string>
|
||||
<string>FontAwesome5_Brands.ttf</string>
|
||||
<string>FontAwesome5_Regular.ttf</string>
|
||||
<string>FontAwesome5_Solid.ttf</string>
|
||||
<string>FontAwesome6_Brands.ttf</string>
|
||||
<string>FontAwesome6_Regular.ttf</string>
|
||||
<string>FontAwesome6_Solid.ttf</string>
|
||||
<string>Foundation.ttf</string>
|
||||
<string>Ionicons.ttf</string>
|
||||
<string>MaterialIcons.ttf</string>
|
||||
<string>MaterialCommunityIcons.ttf</string>
|
||||
<string>SimpleLineIcons.ttf</string>
|
||||
<string>Octicons.ttf</string>
|
||||
<string>Zocial.ttf</string>
|
||||
<string>Fontisto.ttf</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'react-native',
|
||||
transformIgnorePatterns: [
|
||||
'../../node_modules/(?!@react-native|react-native)',
|
||||
'../../node_modules/(?!@react-native|react-native|expo-modules-core|burnt)',
|
||||
],
|
||||
setupFiles: ['./setup-jest.js'],
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/react-native",
|
||||
"version": "0.0.7",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
@@ -11,25 +11,32 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.9.9",
|
||||
"@apollo/client": "^3.11.4",
|
||||
"@invertase/react-native-apple-authentication": "^2.4.0",
|
||||
"@nhost/react": "workspace:*",
|
||||
"@nhost/react-apollo": "workspace:^",
|
||||
"@react-native-async-storage/async-storage": "^1.23.1",
|
||||
"@react-native-community/cli-platform-android": "^13.6.6",
|
||||
"@react-native-google-signin/google-signin": "^13.1.0",
|
||||
"@react-navigation/drawer": "^6.6.15",
|
||||
"@react-navigation/native": "^6.1.17",
|
||||
"@react-navigation/native-stack": "^6.9.26",
|
||||
"base-64": "^1.0.0",
|
||||
"expo-modules-core": "^2.0.1",
|
||||
"react": "18.2.0",
|
||||
"react-hook-form": "^7.51.2",
|
||||
"react-native": "0.73.7",
|
||||
"react-native-document-picker": "^9.2.0",
|
||||
"react-native-dotenv": "^3.4.11",
|
||||
"react-native-gesture-handler": "^2.16.0",
|
||||
"react-native-gradle-plugin": "^0.71.19",
|
||||
"react-native-inappbrowser-reborn": "^3.7.0",
|
||||
"react-native-randombytes": "^3.6.1",
|
||||
"react-native-reanimated": "^3.8.1",
|
||||
"react-native-safe-area-context": "^4.9.0",
|
||||
"react-native-screens": "^3.30.1",
|
||||
"react-native-sha256": "^1.4.10",
|
||||
"react-native-simple-toast": "^3.3.1",
|
||||
"react-native-vector-icons": "^10.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -52,6 +59,7 @@
|
||||
"jest": "^29.6.3",
|
||||
"prettier": "2.8.8",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"rn-nodeify": "^10.3.0",
|
||||
"typescript": "5.0.4"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -2,9 +2,15 @@ import 'react-native-gesture-handler/jestSetup';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
import MockBroadcastChannel from './__mocks__/BroadcastChannel';
|
||||
import '@react-native-google-signin/google-signin';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
jest.mock('expo-modules-core', () => ({
|
||||
EventEmitter: jest.fn(),
|
||||
requireNativeModule: jest.fn().mockReturnValue({}), // Mock this function
|
||||
}));
|
||||
|
||||
Object.assign(global, {
|
||||
WebSocket,
|
||||
BroadcastChannel: MockBroadcastChannel,
|
||||
|
||||
215
examples/react_native/src/components/LinkAppleAccount.tsx
Normal file
215
examples/react_native/src/components/LinkAppleAccount.tsx
Normal file
@@ -0,0 +1,215 @@
|
||||
import {gql} from '@apollo/client';
|
||||
import Button from '@components/Button';
|
||||
import {
|
||||
useAuthenticationStatus,
|
||||
useLinkIdToken,
|
||||
useNhostClient,
|
||||
} from '@nhost/react';
|
||||
import {appleAuth} from '@invertase/react-native-apple-authentication';
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
import {ActivityIndicator, StyleSheet, Text, View} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import Toast from 'react-native-simple-toast';
|
||||
|
||||
export default function LinkAppleAccount() {
|
||||
const nhost = useNhostClient();
|
||||
const {linkIdToken} = useLinkIdToken();
|
||||
const {isAuthenticated} = useAuthenticationStatus();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [linkedWithApple, setLinkedWithApple] = useState(false);
|
||||
|
||||
const checkIfAppleLinked = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const {data, error} = await nhost.graphql.request<{
|
||||
authUserProviders: {id: string; providerId: string}[];
|
||||
}>(gql`
|
||||
query getAuthUserProviders {
|
||||
authUserProviders {
|
||||
id
|
||||
providerId
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
if (error) {
|
||||
Toast.show(
|
||||
'Failed to fetch query user authentication providers',
|
||||
Toast.SHORT,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
setLinkedWithApple(
|
||||
data.authUserProviders?.some(elem => elem.providerId === 'apple'),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
Toast.show(
|
||||
'Failed to fetch query user authentication providers',
|
||||
Toast.SHORT,
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [nhost]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
checkIfAppleLinked();
|
||||
}
|
||||
}, [isAuthenticated, checkIfAppleLinked]);
|
||||
|
||||
const handleLinkAppleAccount = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const appleAuthRequestResponse = await appleAuth.performRequest({
|
||||
requestedOperation: appleAuth.Operation.LOGIN,
|
||||
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
|
||||
});
|
||||
|
||||
const {identityToken, nonce} = appleAuthRequestResponse;
|
||||
|
||||
if (identityToken && nonce) {
|
||||
const {isError, isSuccess, error} = await linkIdToken({
|
||||
provider: 'apple',
|
||||
idToken: identityToken,
|
||||
nonce,
|
||||
});
|
||||
|
||||
if (isError) {
|
||||
Toast.show(
|
||||
error?.error ?? 'An unexpected error happened',
|
||||
Toast.SHORT,
|
||||
);
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
Toast.show('Apple account was linked successfully', Toast.SHORT);
|
||||
await checkIfAppleLinked();
|
||||
}
|
||||
} else {
|
||||
Toast.show('An unexpected error happened', Toast.SHORT);
|
||||
}
|
||||
} catch (error) {
|
||||
Toast.show('An unexpected error happened', Toast.SHORT);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUnlinkAppleAccount = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const {error} = await nhost.graphql.request(
|
||||
gql`
|
||||
mutation deleteAuthUserProvider($providerId: String!) {
|
||||
deleteAuthUserProviders(where: {providerId: {_eq: $providerId}}) {
|
||||
affected_rows
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
providerId: 'apple',
|
||||
},
|
||||
);
|
||||
|
||||
if (!error) {
|
||||
Toast.show('Apple Account was unlinked successfully', Toast.SHORT);
|
||||
await checkIfAppleLinked();
|
||||
return;
|
||||
}
|
||||
|
||||
Toast.show('Failed to unlink auth user provider', Toast.SHORT);
|
||||
} catch (error) {
|
||||
Toast.show('Failed to unlink auth user provider', Toast.SHORT);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View style={styles.unlinkAppleContainer}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (linkedWithApple) {
|
||||
return (
|
||||
<View style={styles.unlinkAppleContainer}>
|
||||
<View style={styles.linkedWithAppleContainer}>
|
||||
<Icon name="apple" color="#333" size={20} />
|
||||
<Text style={styles.linkedWithAppleText}>Linked with Apple</Text>
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label={
|
||||
<View style={styles.labelWrapper}>
|
||||
<Text style={styles.text}>Unlink Apple Account</Text>
|
||||
</View>
|
||||
}
|
||||
color="#333"
|
||||
onPress={handleUnlinkAppleAccount}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
disabled={loading || linkedWithApple}
|
||||
label={
|
||||
<View style={styles.labelWrapper}>
|
||||
<Icon name="apple" color="white" size={20} />
|
||||
<Text style={styles.text}>Link Apple Account</Text>
|
||||
</View>
|
||||
}
|
||||
color="#333"
|
||||
onPress={handleLinkAppleAccount}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
text: {
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
labelWrapper: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
},
|
||||
linkedWithApple: {
|
||||
flexDirection: 'row',
|
||||
padding: 12,
|
||||
backgroundColor: '#333',
|
||||
gap: 4,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
unlinkAppleContainer: {
|
||||
gap: 16,
|
||||
padding: 16,
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
linkedWithAppleContainer: {
|
||||
gap: 4,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
linkedWithAppleText: {
|
||||
color: '#333',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
240
examples/react_native/src/components/LinkGoogleAccount.tsx
Normal file
240
examples/react_native/src/components/LinkGoogleAccount.tsx
Normal file
@@ -0,0 +1,240 @@
|
||||
import {gql} from '@apollo/client';
|
||||
import Button from '@components/Button';
|
||||
import {
|
||||
useAuthenticationStatus,
|
||||
useLinkIdToken,
|
||||
useNhostClient,
|
||||
} from '@nhost/react';
|
||||
import {
|
||||
GoogleSignin,
|
||||
isErrorWithCode,
|
||||
isSuccessResponse,
|
||||
statusCodes,
|
||||
} from '@react-native-google-signin/google-signin';
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
import {ActivityIndicator, StyleSheet, Text, View} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import Toast from 'react-native-simple-toast';
|
||||
|
||||
GoogleSignin.configure({
|
||||
webClientId: process.env.GOOGLE_CLIENT_ID,
|
||||
iosClientId: process.env.GOOGLE_CLIENT_ID,
|
||||
});
|
||||
|
||||
export default function LinkGoogleAccount() {
|
||||
const nhost = useNhostClient();
|
||||
const {linkIdToken} = useLinkIdToken();
|
||||
const {isAuthenticated} = useAuthenticationStatus();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [linkedWithGoogle, setLinkedWithGoogle] = useState(false);
|
||||
|
||||
const checkIfGoogleLinked = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const {data, error} = await nhost.graphql.request<{
|
||||
authUserProviders: {id: string; providerId: string}[];
|
||||
}>(gql`
|
||||
query getAuthUserProviders {
|
||||
authUserProviders {
|
||||
id
|
||||
providerId
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
if (error) {
|
||||
Toast.show(
|
||||
'Failed to fetch query user authentication providers',
|
||||
Toast.SHORT,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
setLinkedWithGoogle(
|
||||
data.authUserProviders?.some(elem => elem.providerId === 'google'),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
Toast.show(
|
||||
'Failed to fetch query user authentication providers',
|
||||
Toast.SHORT,
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [nhost]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
checkIfGoogleLinked();
|
||||
}
|
||||
}, [isAuthenticated, checkIfGoogleLinked]);
|
||||
|
||||
const handleLinkGoogleAccount = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
await GoogleSignin.hasPlayServices();
|
||||
const response = await GoogleSignin.signIn();
|
||||
|
||||
if (isSuccessResponse(response)) {
|
||||
const idToken = response?.data?.idToken as string;
|
||||
|
||||
const {isError, isSuccess} = await linkIdToken({
|
||||
provider: 'google',
|
||||
idToken,
|
||||
});
|
||||
|
||||
if (isError) {
|
||||
Toast.show('An unexpected error happened', Toast.SHORT);
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
Toast.show('Google account was linked successfully', Toast.SHORT);
|
||||
await checkIfGoogleLinked();
|
||||
}
|
||||
} else {
|
||||
// sign in was cancelled by user
|
||||
Toast.show('Sign in was cancelled by user', Toast.SHORT);
|
||||
}
|
||||
} catch (error) {
|
||||
if (isErrorWithCode(error)) {
|
||||
switch (error.code) {
|
||||
case statusCodes.IN_PROGRESS:
|
||||
// operation (eg. sign in) already in progress
|
||||
Toast.show('Sign in already in progress', Toast.SHORT);
|
||||
break;
|
||||
case statusCodes.PLAY_SERVICES_NOT_AVAILABLE:
|
||||
// Android only, play services not available or outdated
|
||||
Toast.show(
|
||||
'Google play services not available or outdated',
|
||||
Toast.SHORT,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// some other error happened
|
||||
Toast.show('An unexpected error happened', Toast.SHORT);
|
||||
}
|
||||
} else {
|
||||
// an error that's not related to google sign in occurred
|
||||
Toast.show('An unexpected error happened', Toast.SHORT);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUnlinkGoogleAccount = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const {error} = await nhost.graphql.request(
|
||||
gql`
|
||||
mutation deleteAuthUserProvider($providerId: String!) {
|
||||
deleteAuthUserProviders(where: {providerId: {_eq: $providerId}}) {
|
||||
affected_rows
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
providerId: 'google',
|
||||
},
|
||||
);
|
||||
|
||||
if (!error) {
|
||||
Toast.show('Google Account was unlinked successfully', Toast.SHORT);
|
||||
await checkIfGoogleLinked();
|
||||
return;
|
||||
}
|
||||
|
||||
Toast.show('Failed to unlink auth user provider', Toast.SHORT);
|
||||
} catch (error) {
|
||||
Toast.show('Failed to unlink auth user provider', Toast.SHORT);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View style={styles.unlinkGoogleContainer}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (linkedWithGoogle) {
|
||||
return (
|
||||
<View style={styles.unlinkGoogleContainer}>
|
||||
<View style={styles.linkedWithGoogleContainer}>
|
||||
<Icon name="google" color="#333" size={20} />
|
||||
<Text style={styles.linkedWithGoogleText}>Linked with Google</Text>
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label={
|
||||
<View style={styles.labelWrapper}>
|
||||
<Text style={styles.text}>Unlink Google Account</Text>
|
||||
</View>
|
||||
}
|
||||
color="#d97d73"
|
||||
onPress={handleUnlinkGoogleAccount}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
disabled={loading || linkedWithGoogle}
|
||||
label={
|
||||
<View style={styles.labelWrapper}>
|
||||
<Icon name="google" color="white" size={20} />
|
||||
<Text style={styles.text}>Link Google Account</Text>
|
||||
</View>
|
||||
}
|
||||
color="#de5246"
|
||||
onPress={handleLinkGoogleAccount}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
text: {
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
labelWrapper: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
},
|
||||
linkedWithGoogle: {
|
||||
flexDirection: 'row',
|
||||
padding: 12,
|
||||
backgroundColor: '#de524688',
|
||||
gap: 4,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
unlinkGoogleContainer: {
|
||||
gap: 16,
|
||||
padding: 16,
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
linkedWithGoogleContainer: {
|
||||
gap: 4,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
linkedWithGoogleText: {
|
||||
color: '#333',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
@@ -2,12 +2,60 @@ import React from 'react';
|
||||
import Button from '@components/Button';
|
||||
import {StyleSheet, Text, View} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import {appleAuth} from '@invertase/react-native-apple-authentication';
|
||||
import {useSignInIdToken} from '@nhost/react';
|
||||
import Toast from 'react-native-simple-toast';
|
||||
|
||||
export default function SignInWithAppleButton() {
|
||||
const {signInIdToken} = useSignInIdToken();
|
||||
|
||||
async function handleSignInWithApple() {
|
||||
try {
|
||||
const appleAuthRequestResponse = await appleAuth.performRequest({
|
||||
requestedOperation: appleAuth.Operation.LOGIN,
|
||||
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
|
||||
});
|
||||
|
||||
const {identityToken, nonce} = appleAuthRequestResponse;
|
||||
|
||||
if (identityToken) {
|
||||
const {isError, isSuccess, error} = await signInIdToken(
|
||||
'apple',
|
||||
identityToken,
|
||||
nonce,
|
||||
);
|
||||
|
||||
if (isSuccess) {
|
||||
Toast.showWithGravity(
|
||||
'Signin with Apple succeeded',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
Toast.showWithGravity(
|
||||
`Signin with Apple failed: ${error?.message}`,
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Toast.showWithGravity(
|
||||
'Signin with Apple failed: no idToken received',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
Toast.showWithGravity(
|
||||
`Signin with Apple failed: ${JSON.stringify(error)}`,
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default function SignInWithAppleButton({
|
||||
hanldeSignIn,
|
||||
}: {
|
||||
hanldeSignIn?: () => Promise<void>;
|
||||
}) {
|
||||
return (
|
||||
<Button
|
||||
label={
|
||||
@@ -17,7 +65,7 @@ export default function SignInWithAppleButton({
|
||||
</View>
|
||||
}
|
||||
color="black"
|
||||
onPress={hanldeSignIn}
|
||||
onPress={handleSignInWithApple}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,96 @@
|
||||
import React from 'react';
|
||||
import Button from '@components/Button';
|
||||
import {useSignInIdToken} from '@nhost/react';
|
||||
import {
|
||||
GoogleSignin,
|
||||
isErrorWithCode,
|
||||
isSuccessResponse,
|
||||
statusCodes,
|
||||
} from '@react-native-google-signin/google-signin';
|
||||
import React from 'react';
|
||||
import {StyleSheet, Text, View} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import Toast from 'react-native-simple-toast';
|
||||
|
||||
GoogleSignin.configure({
|
||||
webClientId: process.env.GOOGLE_CLIENT_ID,
|
||||
iosClientId: process.env.IOS_GOOGLE_CLIENT_ID,
|
||||
});
|
||||
|
||||
export default function SignInWithGoogleButton() {
|
||||
const {signInIdToken} = useSignInIdToken();
|
||||
|
||||
const handleSignInWithGoogle = async () => {
|
||||
try {
|
||||
await GoogleSignin.hasPlayServices();
|
||||
const response = await GoogleSignin.signIn();
|
||||
if (isSuccessResponse(response)) {
|
||||
const idToken = response?.data?.idToken as string;
|
||||
|
||||
const {isError, isSuccess, error} = await signInIdToken(
|
||||
'google',
|
||||
idToken,
|
||||
);
|
||||
|
||||
if (isSuccess) {
|
||||
Toast.showWithGravity(
|
||||
'Signin with Google succeeded',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
Toast.showWithGravity(
|
||||
`Signin with Google failed: ${error?.message}`,
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Toast.showWithGravity(
|
||||
'Sign in was cancelled by user',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (isErrorWithCode(error)) {
|
||||
switch (error.code) {
|
||||
case statusCodes.IN_PROGRESS:
|
||||
// operation (eg. sign in) already in progress
|
||||
Toast.showWithGravity(
|
||||
'Signin is already in progress',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
break;
|
||||
case statusCodes.PLAY_SERVICES_NOT_AVAILABLE:
|
||||
// Android only, play services not available or outdated
|
||||
Toast.showWithGravity(
|
||||
'Play services not available or outdated',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// some other error happened
|
||||
Toast.showWithGravity(
|
||||
'An unexpected error happened',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// an error that's not related to google sign in occurred
|
||||
Toast.showWithGravity(
|
||||
'An unexpected error happened',
|
||||
Toast.SHORT,
|
||||
Toast.BOTTOM,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default function SignInWithGoogleButton({
|
||||
handleSignIn,
|
||||
}: {
|
||||
handleSignIn: () => Promise<void>;
|
||||
}) {
|
||||
return (
|
||||
<Button
|
||||
label={
|
||||
@@ -17,7 +100,7 @@ export default function SignInWithGoogleButton({
|
||||
</View>
|
||||
}
|
||||
color="#de5246"
|
||||
onPress={handleSignIn}
|
||||
onPress={handleSignInWithGoogle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ import {NhostClient, NhostProvider} from '@nhost/react';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import Main from '@screens/Main';
|
||||
import {NhostApolloProvider} from '@nhost/react-apollo';
|
||||
import {Platform} from 'react-native';
|
||||
|
||||
const nhost = new NhostClient({
|
||||
subdomain: 'local',
|
||||
subdomain: Platform.OS === 'ios' ? 'local' : '10-0-2-2',
|
||||
region: 'local',
|
||||
clientStorageType: 'react-native',
|
||||
clientStorage: AsyncStorage,
|
||||
});
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import React from 'react';
|
||||
import LinkAppleAccount from '@components/LinkAppleAccount';
|
||||
import LinkGoogleAccount from '@components/LinkGoogleAccount';
|
||||
import {useHasuraClaims, useUserData} from '@nhost/react';
|
||||
import {ScrollView, StyleSheet, Text, View} from 'react-native';
|
||||
import React from 'react';
|
||||
import {ScrollView, StyleSheet, Text} from 'react-native';
|
||||
|
||||
export default function Profile() {
|
||||
const user = useUserData();
|
||||
const claims = useHasuraClaims();
|
||||
|
||||
return (
|
||||
<View style={styles.wrapper}>
|
||||
<ScrollView contentContainerStyle={styles.wrapper}>
|
||||
<LinkAppleAccount />
|
||||
<LinkGoogleAccount />
|
||||
<Text style={styles.subTitle}>User information</Text>
|
||||
<ScrollView
|
||||
horizontal
|
||||
@@ -22,13 +26,14 @@ export default function Profile() {
|
||||
contentContainerStyle={styles.codeScrollView}>
|
||||
<Text style={styles.code}>{JSON.stringify(claims, null, 2)}</Text>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
padding: 12,
|
||||
paddingBottom: 50,
|
||||
gap: 10,
|
||||
},
|
||||
subTitle: {
|
||||
@@ -43,5 +48,6 @@ const styles = StyleSheet.create({
|
||||
codeScrollView: {
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @nhost-examples/vue-apollo
|
||||
|
||||
## 0.7.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/vue@2.8.0
|
||||
- @nhost/nhost-js@3.2.1
|
||||
- @nhost/apollo@8.0.1
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/vue-apollo",
|
||||
"private": true,
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/vue-quickstart
|
||||
|
||||
## 0.2.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [14e6100]
|
||||
- @nhost/vue@2.8.0
|
||||
- @nhost/apollo@8.0.1
|
||||
|
||||
## 0.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/vue-quickstart",
|
||||
"version": "0.2.14",
|
||||
"version": "0.2.15",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost/apollo
|
||||
|
||||
## 8.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @nhost/nhost-js@3.2.1
|
||||
|
||||
## 8.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user