mirror of https://github.com/sylv/micro.git
feat: change password page
This commit is contained in:
parent
eb15ce1ea6
commit
126be8d8c6
|
@ -30,7 +30,7 @@ export class UserResolver {
|
|||
@InjectRepository(UserVerification) private readonly verificationRepo: EntityRepository<UserVerification>,
|
||||
private readonly authService: AuthService,
|
||||
private readonly userService: UserService,
|
||||
private readonly inviteService: InviteService
|
||||
private readonly inviteService: InviteService,
|
||||
) {}
|
||||
|
||||
@Query(() => User)
|
||||
|
@ -51,7 +51,7 @@ export class UserResolver {
|
|||
@UserId() userId: string,
|
||||
@Parent() user: User,
|
||||
@Args('first', { nullable: true }) limit: number = 0,
|
||||
@Args('after', { nullable: true }) cursor?: string
|
||||
@Args('after', { nullable: true }) cursor?: string,
|
||||
): Promise<FilePage> {
|
||||
if (userId !== user.id) throw new UnauthorizedException();
|
||||
if (limit > 100) limit = 100;
|
||||
|
@ -74,7 +74,7 @@ export class UserResolver {
|
|||
@UserId() userId: string,
|
||||
@Parent() user: User,
|
||||
@Args('first', { nullable: true }) limit: number = 0,
|
||||
@Args('after', { nullable: true }) cursor?: string
|
||||
@Args('after', { nullable: true }) cursor?: string,
|
||||
): Promise<PastePage> {
|
||||
if (userId !== user.id) throw new UnauthorizedException();
|
||||
if (limit > 100) limit = 100;
|
||||
|
@ -119,11 +119,22 @@ export class UserResolver {
|
|||
return this.userService.createUser(data, invite);
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
@UseGuards(JWTAuthGuard)
|
||||
async changePassword(
|
||||
@UserId() userId: string,
|
||||
@Args('currentPassword') currentPassword: string,
|
||||
@Args('newPassword') newPassword: string,
|
||||
) {
|
||||
await this.userService.changePassword(userId, currentPassword, newPassword);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
@UseGuards(JWTAuthGuard)
|
||||
async resendVerificationEmail(
|
||||
@UserId() userId: string,
|
||||
@Args('data', { nullable: true }) body?: ResendVerificationEmailDto
|
||||
@Args('data', { nullable: true }) body?: ResendVerificationEmailDto,
|
||||
) {
|
||||
const user = await this.userService.getUser(userId, false);
|
||||
const latestVerification = await this.verificationRepo.findOne(
|
||||
|
@ -137,7 +148,7 @@ export class UserResolver {
|
|||
orderBy: {
|
||||
expiresAt: 'DESC',
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (latestVerification && latestVerification.expiresAt.getTime() > Date.now() + UserResolver.MIN_RESEND_INTERVAL) {
|
||||
|
|
|
@ -125,7 +125,7 @@ export class UserService {
|
|||
throw new ConflictException('You must provide an email address to create a user.');
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(data.password, 10);
|
||||
const hashedPassword = await bcrypt.hash(data.password, 12);
|
||||
const user = this.userRepo.create({
|
||||
id: generateContentId(),
|
||||
secret: nanoid(),
|
||||
|
@ -190,6 +190,17 @@ export class UserService {
|
|||
}
|
||||
}
|
||||
|
||||
async changePassword(userId: string, currentPassword: string, newPassword: string) {
|
||||
const user = await this.userRepo.findOneOrFail(userId);
|
||||
const passwordMatches = await bcrypt.compare(currentPassword, user.password);
|
||||
if (!passwordMatches) {
|
||||
throw new BadRequestException('Invalid password');
|
||||
}
|
||||
|
||||
user.password = await bcrypt.hash(newPassword, 12);
|
||||
await this.userRepo.persistAndFlush(user);
|
||||
}
|
||||
|
||||
@Cron(CronExpression.EVERY_HOUR)
|
||||
async deleteExpiredVerifications() {
|
||||
await this.verificationRepo.nativeDelete({
|
||||
|
|
|
@ -102,6 +102,7 @@ type Link {
|
|||
}
|
||||
|
||||
type Mutation {
|
||||
changePassword(currentPassword: String!, newPassword: String!): Boolean!
|
||||
confirmOTP(otpCode: String!): Boolean!
|
||||
createInvite: Invite!
|
||||
createLink(destination: String!, host: String): Link!
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "tsc --noEmit && rm -rf ./dist/* && vavite build && tsup && rm -rf ./dist/server",
|
||||
"lint": "eslint --fix ./src/**/*.{ts,tsx}",
|
||||
"start": "node ./dist/index.js",
|
||||
"watch": "vavite serve"
|
||||
},
|
||||
|
@ -57,7 +58,6 @@
|
|||
"vavite": "^4.0.3",
|
||||
"vike": "^0.4.161",
|
||||
"vite": "^5.1.1",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-graphql-codegen": "^3.3.6",
|
||||
"yup": "^1.3.3"
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ const documents = {
|
|||
'\n mutation DisableOTP($otpCode: String!) {\n disableOTP(otpCode: $otpCode)\n }\n': types.DisableOtpDocument,
|
||||
'\n query UserQueryWithToken {\n user {\n ...RegularUser\n token\n otpEnabled\n }\n }\n':
|
||||
types.UserQueryWithTokenDocument,
|
||||
'\n mutation ChangePassword($oldPassword: String!, $newPassword: String!) {\n changePassword(currentPassword: $oldPassword, newPassword: $newPassword)\n }\n':
|
||||
types.ChangePasswordDocument,
|
||||
'\n query GetFile($fileId: ID!) {\n file(fileId: $fileId) {\n id\n type\n displayName\n size\n sizeFormatted\n textContent\n isOwner\n metadata {\n height\n width\n }\n paths {\n view\n thumbnail\n direct\n }\n urls {\n view\n }\n }\n }\n':
|
||||
types.GetFileDocument,
|
||||
'\n mutation DeleteFile($fileId: ID!, $deleteKey: String) {\n deleteFile(fileId: $fileId, key: $deleteKey)\n }\n':
|
||||
|
@ -158,6 +160,12 @@ export function graphql(
|
|||
export function graphql(
|
||||
source: '\n query UserQueryWithToken {\n user {\n ...RegularUser\n token\n otpEnabled\n }\n }\n',
|
||||
): (typeof documents)['\n query UserQueryWithToken {\n user {\n ...RegularUser\n token\n otpEnabled\n }\n }\n'];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(
|
||||
source: '\n mutation ChangePassword($oldPassword: String!, $newPassword: String!) {\n changePassword(currentPassword: $oldPassword, newPassword: $newPassword)\n }\n',
|
||||
): (typeof documents)['\n mutation ChangePassword($oldPassword: String!, $newPassword: String!) {\n changePassword(currentPassword: $oldPassword, newPassword: $newPassword)\n }\n'];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
|
|
@ -118,6 +118,7 @@ export type Link = {
|
|||
|
||||
export type Mutation = {
|
||||
__typename?: 'Mutation';
|
||||
changePassword: Scalars['Boolean']['output'];
|
||||
confirmOTP: Scalars['Boolean']['output'];
|
||||
createInvite: Invite;
|
||||
createLink: Link;
|
||||
|
@ -131,6 +132,11 @@ export type Mutation = {
|
|||
resendVerificationEmail: Scalars['Boolean']['output'];
|
||||
};
|
||||
|
||||
export type MutationChangePasswordArgs = {
|
||||
currentPassword: Scalars['String']['input'];
|
||||
newPassword: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type MutationConfirmOtpArgs = {
|
||||
otpCode: Scalars['String']['input'];
|
||||
};
|
||||
|
@ -458,6 +464,13 @@ export type UserQueryWithTokenQuery = {
|
|||
};
|
||||
};
|
||||
|
||||
export type ChangePasswordMutationVariables = Exact<{
|
||||
oldPassword: Scalars['String']['input'];
|
||||
newPassword: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
export type ChangePasswordMutation = { __typename?: 'Mutation'; changePassword: boolean };
|
||||
|
||||
export type GetFileQueryVariables = Exact<{
|
||||
fileId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
@ -1250,6 +1263,49 @@ export const UserQueryWithTokenDocument = {
|
|||
},
|
||||
],
|
||||
} as unknown as DocumentNode<UserQueryWithTokenQuery, UserQueryWithTokenQueryVariables>;
|
||||
export const ChangePasswordDocument = {
|
||||
kind: 'Document',
|
||||
definitions: [
|
||||
{
|
||||
kind: 'OperationDefinition',
|
||||
operation: 'mutation',
|
||||
name: { kind: 'Name', value: 'ChangePassword' },
|
||||
variableDefinitions: [
|
||||
{
|
||||
kind: 'VariableDefinition',
|
||||
variable: { kind: 'Variable', name: { kind: 'Name', value: 'oldPassword' } },
|
||||
type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } },
|
||||
},
|
||||
{
|
||||
kind: 'VariableDefinition',
|
||||
variable: { kind: 'Variable', name: { kind: 'Name', value: 'newPassword' } },
|
||||
type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } },
|
||||
},
|
||||
],
|
||||
selectionSet: {
|
||||
kind: 'SelectionSet',
|
||||
selections: [
|
||||
{
|
||||
kind: 'Field',
|
||||
name: { kind: 'Name', value: 'changePassword' },
|
||||
arguments: [
|
||||
{
|
||||
kind: 'Argument',
|
||||
name: { kind: 'Name', value: 'currentPassword' },
|
||||
value: { kind: 'Variable', name: { kind: 'Name', value: 'oldPassword' } },
|
||||
},
|
||||
{
|
||||
kind: 'Argument',
|
||||
name: { kind: 'Name', value: 'newPassword' },
|
||||
value: { kind: 'Variable', name: { kind: 'Name', value: 'newPassword' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
} as unknown as DocumentNode<ChangePasswordMutation, ChangePasswordMutationVariables>;
|
||||
export const GetFileDocument = {
|
||||
kind: 'Document',
|
||||
definitions: [
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { useContext } from "react";
|
||||
import { ToastContext } from "./context";
|
||||
import { useContext } from 'react';
|
||||
import { ToastContext } from './context';
|
||||
|
||||
export const useToasts = () => {
|
||||
const createToast = useContext(ToastContext);
|
||||
if (!createToast) {
|
||||
// todo: this should be an error, but it seems like it can be undefined.
|
||||
// maybe due to concurrent rendering? idk shit about fuck.
|
||||
return () => undefined;
|
||||
if (typeof window === 'undefined') return () => {};
|
||||
throw new Error('useToasts must be used within a ToastProvider');
|
||||
}
|
||||
|
||||
return createToast;
|
||||
|
|
|
@ -39,11 +39,9 @@ export const LoginForm: FC = () => {
|
|||
setLoginInfo(values);
|
||||
setInvalidOTP(false);
|
||||
await user.login(values);
|
||||
console.log('ball');
|
||||
setError(null);
|
||||
redirect();
|
||||
} catch (error: any) {
|
||||
console.log(error);
|
||||
if (user.otpRequired && error.message.toLowerCase().includes('invalid otp')) {
|
||||
setInvalidOTP(true);
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import { Form, Formik } from 'formik';
|
||||
import type { FC } from 'react';
|
||||
import { Fragment } from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import { Input } from '../components/input/input';
|
||||
import { Submit } from '../components/input/submit';
|
||||
|
||||
interface PasswordData {
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
}
|
||||
|
||||
interface PasswordFormProps {
|
||||
onSubmit: (data: PasswordData) => Promise<void> | void;
|
||||
}
|
||||
|
||||
const schema = Yup.object().shape({
|
||||
oldPassword: Yup.string().required().min(5),
|
||||
newPassword: Yup.string().required().min(5),
|
||||
});
|
||||
|
||||
export const PasswordForm: FC<PasswordFormProps> = ({ onSubmit }) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Formik
|
||||
validationSchema={schema}
|
||||
initialValues={{
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
}}
|
||||
onSubmit={async (values) => {
|
||||
await onSubmit(values);
|
||||
}}
|
||||
>
|
||||
<Form className="space-y-2">
|
||||
<Input id="oldPassword" type="password" placeholder="Current Password" autoComplete="current-password" />
|
||||
<Input id="newPassword" type="password" placeholder="New Password" autoComplete="new-password" />
|
||||
<Submit className="mt-4 w-full" type="submit">
|
||||
Change Password
|
||||
</Submit>
|
||||
</Form>
|
||||
</Formik>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import type { CombinedError, TypedDocumentNode } from '@urql/preact';
|
||||
import { useMutation, useQuery } from '@urql/preact';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { graphql } from '../@generated/gql';
|
||||
import type { GetUserQuery, LoginMutationVariables } from '../@generated/graphql';
|
||||
import { navigate, reload } from '../helpers/routing';
|
||||
import { type RegularUserFragment } from '../@generated/graphql';
|
||||
import { navigate } from '../helpers/routing';
|
||||
import { useAsync } from './useAsync';
|
||||
|
||||
const RegularUserFragment = graphql(`
|
||||
|
@ -42,15 +42,16 @@ export const useLoginUser = () => {
|
|||
const [otp, setOtp] = useState(false);
|
||||
const [, loginMutation] = useMutation(LoginMutation);
|
||||
const [login] = useAsync(async (variables: LoginMutationVariables) => {
|
||||
try {
|
||||
await loginMutation(variables);
|
||||
const result = await loginMutation(variables);
|
||||
if (result.data) {
|
||||
navigate('/dashboard');
|
||||
} catch (error: any) {
|
||||
if (error.message.toLowerCase().includes('otp')) {
|
||||
} else if (result.error) {
|
||||
if (result.error.message.toLowerCase().includes('otp')) {
|
||||
setOtp(true);
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
throw result.error;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -64,7 +65,7 @@ export const useLogoutUser = () => {
|
|||
const [, logoutMutation] = useMutation(LogoutMutation);
|
||||
const [logout] = useAsync(async () => {
|
||||
await logoutMutation({});
|
||||
reload();
|
||||
navigate('/');
|
||||
});
|
||||
|
||||
return { logout };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useMutation, useQuery } from '@urql/preact';
|
||||
import type { FC } from 'react';
|
||||
import { Fragment } from 'react';
|
||||
import { useMutation, useQuery } from '@urql/preact';
|
||||
import { graphql } from '../../../@generated/gql';
|
||||
import { Breadcrumbs } from '../../../components/breadcrumbs';
|
||||
import { Button } from '../../../components/button';
|
||||
|
@ -98,6 +98,32 @@ export const Page: FC = () => {
|
|||
{!user.data && <InputSkeleton />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4 mt-8">
|
||||
<div className="left col-span-full md:col-span-1">
|
||||
{user.data && (
|
||||
<Fragment>
|
||||
<div className="font-bold text-xl">Change Password</div>
|
||||
<p className="text-sm mt-2 text-gray-400">
|
||||
Change your account password. This will not sign out other devices.
|
||||
</p>
|
||||
</Fragment>
|
||||
)}
|
||||
{!user.data && (
|
||||
<Fragment>
|
||||
<Skeleton className="w-1/2 mb-1" />
|
||||
<Skeleton className="w-3/4" />
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
<div className="right flex items-center col-span-full md:col-span-1">
|
||||
{user.data && (
|
||||
<Button className="w-auto ml-auto" onClick={() => navigate(`/dashboard/preferences/change-password`)}>
|
||||
Change
|
||||
</Button>
|
||||
)}
|
||||
{!user.data && <ButtonSkeleton className="ml-auto" />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-10">
|
||||
<ConfigGenerator user={user.data?.user} />
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
import { useMutation } from '@urql/preact';
|
||||
import type { FC } from 'react';
|
||||
import { graphql } from '../../../../@generated';
|
||||
import type { ChangePasswordMutationVariables } from '../../../../@generated/graphql';
|
||||
import { Breadcrumbs } from '../../../../components/breadcrumbs';
|
||||
import { Container } from '../../../../components/container';
|
||||
import { Title } from '../../../../components/title';
|
||||
import { useToasts } from '../../../../components/toast';
|
||||
import { PasswordForm } from '../../../../containers/password-form';
|
||||
import { navigate, prefetch } from '../../../../helpers/routing';
|
||||
import { useAsync } from '../../../../hooks/useAsync';
|
||||
import { useUser } from '../../../../hooks/useUser';
|
||||
|
||||
const ChangePassword = graphql(`
|
||||
mutation ChangePassword($oldPassword: String!, $newPassword: String!) {
|
||||
changePassword(currentPassword: $oldPassword, newPassword: $newPassword)
|
||||
}
|
||||
`);
|
||||
|
||||
export const Page: FC = () => {
|
||||
const createToast = useToasts();
|
||||
const [, changeInner] = useMutation(ChangePassword);
|
||||
const [change] = useAsync(async (values: ChangePasswordMutationVariables) => {
|
||||
prefetch('/dashboard/preferences');
|
||||
const result = await changeInner(values);
|
||||
if (result.data) {
|
||||
createToast({ text: 'Your password has been changed.' });
|
||||
navigate('/dashboard/preferences');
|
||||
} else if (result.error) {
|
||||
if (result.error.message.toLowerCase().includes('unauthorized')) {
|
||||
createToast({ text: 'Invalid password.' });
|
||||
return;
|
||||
} else {
|
||||
createToast({ text: 'An error occurred changing your password.' });
|
||||
}
|
||||
|
||||
throw result.error;
|
||||
}
|
||||
});
|
||||
|
||||
useUser();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Title>Change Password</Title>
|
||||
<div className="flex justify-center top-[40vh]">
|
||||
<div className="w-[80vw] md:w-[50vw] lg:w-[30vw]">
|
||||
<Breadcrumbs href="/dashboard/preferences" className="mb-4">
|
||||
Dashboard / Preferences
|
||||
</Breadcrumbs>
|
||||
<h1 className="my-5 text-4xl font-bold">Change Password</h1>
|
||||
<PasswordForm onSubmit={change} />
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
};
|
|
@ -2,7 +2,6 @@ import { preact } from '@preact/preset-vite';
|
|||
import { vavite } from 'vavite';
|
||||
import ssr from 'vike/plugin';
|
||||
import { defineConfig } from 'vite';
|
||||
import eslint from 'vite-plugin-eslint';
|
||||
import codegen from 'vite-plugin-graphql-codegen';
|
||||
|
||||
export default defineConfig({
|
||||
|
@ -25,7 +24,6 @@ export default defineConfig({
|
|||
},
|
||||
plugins: [
|
||||
codegen(),
|
||||
eslint({ cache: true }),
|
||||
preact(),
|
||||
ssr({ disableAutoFullBuild: true }),
|
||||
vavite({
|
||||
|
|
116
pnpm-lock.yaml
116
pnpm-lock.yaml
|
@ -353,10 +353,7 @@ importers:
|
|||
version: 0.4.161(vite@5.1.1)
|
||||
vite:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1(@types/node@20.11.17)
|
||||
vite-plugin-eslint:
|
||||
specifier: ^1.8.1
|
||||
version: 1.8.1(eslint@8.56.0)(vite@5.1.1)
|
||||
version: 5.1.1
|
||||
vite-plugin-graphql-codegen:
|
||||
specifier: ^3.3.6
|
||||
version: 3.3.6(@graphql-codegen/cli@5.0.2)(graphql@16.8.1)(vite@5.1.1)
|
||||
|
@ -1389,7 +1386,7 @@ packages:
|
|||
'@fastify/reply-from': 9.7.0
|
||||
fast-querystring: 1.1.2
|
||||
fastify-plugin: 4.5.1
|
||||
ws: 8.16.0(utf-8-validate@6.0.3)
|
||||
ws: 8.16.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
@ -1783,7 +1780,7 @@ packages:
|
|||
graphql-ws: 5.14.3(graphql@16.8.1)
|
||||
isomorphic-ws: 5.0.0(ws@8.16.0)
|
||||
tslib: 2.6.2
|
||||
ws: 8.16.0(utf-8-validate@6.0.3)
|
||||
ws: 8.16.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
@ -1818,7 +1815,7 @@ packages:
|
|||
graphql: 16.8.1
|
||||
isomorphic-ws: 5.0.0(ws@8.16.0)
|
||||
tslib: 2.6.2
|
||||
ws: 8.16.0(utf-8-validate@6.0.3)
|
||||
ws: 8.16.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
@ -2044,7 +2041,7 @@ packages:
|
|||
isomorphic-ws: 5.0.0(ws@8.16.0)
|
||||
tslib: 2.6.2
|
||||
value-or-promise: 1.0.12
|
||||
ws: 8.16.0(utf-8-validate@6.0.3)
|
||||
ws: 8.16.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- bufferutil
|
||||
|
@ -3099,7 +3096,7 @@ packages:
|
|||
magic-string: 0.30.5
|
||||
node-html-parser: 6.1.12
|
||||
resolve: 1.22.8
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
transitivePeerDependencies:
|
||||
- preact
|
||||
- supports-color
|
||||
|
@ -3133,7 +3130,7 @@ packages:
|
|||
'@prefresh/utils': 1.2.0
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
preact: 10.19.4
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
@ -3848,13 +3845,6 @@ packages:
|
|||
resolution: {integrity: sha512-kRiitIeUg1mPV9yH4VUJ/1uk2XjyANfeL8/7rH1tsjvHeO9PJLBHJIYsFWmAvmGj5u8rj+1TZx7PZzW2qLw3Lw==}
|
||||
dev: true
|
||||
|
||||
/@types/eslint@8.56.2:
|
||||
resolution: {integrity: sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==}
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
'@types/json-schema': 7.0.15
|
||||
dev: true
|
||||
|
||||
/@types/estree-jsx@1.0.3:
|
||||
resolution: {integrity: sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==}
|
||||
dependencies:
|
||||
|
@ -4251,7 +4241,7 @@ packages:
|
|||
vite: ^2.8.1 || 3 || 4 || 5
|
||||
dependencies:
|
||||
'@types/node': 20.11.17
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/@vavite/expose-vite-dev-server@4.0.3(vite@5.1.1):
|
||||
|
@ -4259,7 +4249,7 @@ packages:
|
|||
peerDependencies:
|
||||
vite: ^2.8.1 || 3 || 4 || 5
|
||||
dependencies:
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/@vavite/multibuild-cli@4.0.3(vite@5.1.1):
|
||||
|
@ -4272,7 +4262,7 @@ packages:
|
|||
'@vavite/multibuild': 4.0.3(vite@5.1.1)
|
||||
cac: 6.7.14
|
||||
picocolors: 1.0.0
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/@vavite/multibuild@4.0.3(vite@5.1.1):
|
||||
|
@ -4283,7 +4273,7 @@ packages:
|
|||
'@types/node': 20.11.17
|
||||
cac: 6.7.14
|
||||
picocolors: 1.0.0
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/@vavite/node-loader@4.0.3(vite@5.1.1):
|
||||
|
@ -4292,7 +4282,7 @@ packages:
|
|||
peerDependencies:
|
||||
vite: ^2.8.1 || 3 || 4 || 5
|
||||
dependencies:
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/@vavite/reloader@4.0.3(vite@5.1.1):
|
||||
|
@ -4300,7 +4290,7 @@ packages:
|
|||
peerDependencies:
|
||||
vite: ^2.8.1 || 3 || 4 || 5
|
||||
dependencies:
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/@vitest/expect@1.2.2:
|
||||
|
@ -7214,7 +7204,7 @@ packages:
|
|||
peerDependencies:
|
||||
ws: '*'
|
||||
dependencies:
|
||||
ws: 8.16.0(utf-8-validate@6.0.3)
|
||||
ws: 8.16.0
|
||||
dev: true
|
||||
|
||||
/istextorbinary@9.5.0:
|
||||
|
@ -8356,6 +8346,7 @@ packages:
|
|||
/node-gyp-build@4.8.0:
|
||||
resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/node-html-parser@6.1.12:
|
||||
resolution: {integrity: sha512-/bT/Ncmv+fbMGX96XG9g05vFt43m/+SYKIs9oAemQVYyVcZmDAI2Xq/SbNcpOA35eF0Zk2av3Ksf+Xk8Vt8abA==}
|
||||
|
@ -9509,14 +9500,6 @@ packages:
|
|||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rollup@2.79.1:
|
||||
resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/rollup@4.10.0:
|
||||
resolution: {integrity: sha512-t2v9G2AKxcQ8yrG+WGxctBes1AomT0M4ND7jTFBCVPXQ/WFTvNSefIrNSmLKhIKBrvN8SG+CZslimJcT3W2u2g==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
|
@ -10808,6 +10791,7 @@ packages:
|
|||
requiresBuild: true
|
||||
dependencies:
|
||||
node-gyp-build: 4.8.0
|
||||
dev: false
|
||||
|
||||
/util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
@ -10864,7 +10848,7 @@ packages:
|
|||
'@vavite/reloader': 4.0.3(vite@5.1.1)
|
||||
cac: 6.7.14
|
||||
picocolors: 1.0.0
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/version-range@4.14.0:
|
||||
|
@ -10910,7 +10894,7 @@ packages:
|
|||
fast-glob: 3.3.2
|
||||
sirv: 2.0.4
|
||||
source-map-support: 0.5.21
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/vite-node@1.2.2(@types/node@20.11.17):
|
||||
|
@ -10934,19 +10918,6 @@ packages:
|
|||
- terser
|
||||
dev: true
|
||||
|
||||
/vite-plugin-eslint@1.8.1(eslint@8.56.0)(vite@5.1.1):
|
||||
resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==}
|
||||
peerDependencies:
|
||||
eslint: '>=7'
|
||||
vite: '>=2'
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
'@types/eslint': 8.56.2
|
||||
eslint: 8.56.0
|
||||
rollup: 2.79.1
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
dev: true
|
||||
|
||||
/vite-plugin-graphql-codegen@3.3.6(@graphql-codegen/cli@5.0.2)(graphql@16.8.1)(vite@5.1.1):
|
||||
resolution: {integrity: sha512-TXMaUpPCfqzSpujjzFjVeeCH9JOSBwFWxOJottZ+gouQtNhnNpgXcj4nZep3om5Wq0UlDwDYLqXWrAa8XaZW1w==}
|
||||
peerDependencies:
|
||||
|
@ -10957,7 +10928,42 @@ packages:
|
|||
'@graphql-codegen/cli': 5.0.2(@parcel/watcher@2.4.0)(graphql@16.8.1)(typescript@5.3.3)
|
||||
'@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1)
|
||||
graphql: 16.8.1
|
||||
vite: 5.1.1(@types/node@20.11.17)
|
||||
vite: 5.1.1
|
||||
dev: true
|
||||
|
||||
/vite@5.1.1:
|
||||
resolution: {integrity: sha512-wclpAgY3F1tR7t9LL5CcHC41YPkQIpKUGeIuT8MdNwNZr6OqOTLs7JX5vIHAtzqLWXts0T+GDrh9pN2arneKqg==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@types/node': ^18.0.0 || >=20.0.0
|
||||
less: '*'
|
||||
lightningcss: ^1.21.0
|
||||
sass: '*'
|
||||
stylus: '*'
|
||||
sugarss: '*'
|
||||
terser: ^5.4.0
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
less:
|
||||
optional: true
|
||||
lightningcss:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
stylus:
|
||||
optional: true
|
||||
sugarss:
|
||||
optional: true
|
||||
terser:
|
||||
optional: true
|
||||
dependencies:
|
||||
esbuild: 0.19.12
|
||||
postcss: 8.4.35
|
||||
rollup: 4.10.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/vite@5.1.1(@types/node@20.11.17):
|
||||
|
@ -11224,6 +11230,19 @@ packages:
|
|||
utf-8-validate: 6.0.3
|
||||
dev: false
|
||||
|
||||
/ws@8.16.0:
|
||||
resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
dev: true
|
||||
|
||||
/ws@8.16.0(utf-8-validate@6.0.3):
|
||||
resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
@ -11237,6 +11256,7 @@ packages:
|
|||
optional: true
|
||||
dependencies:
|
||||
utf-8-validate: 6.0.3
|
||||
dev: false
|
||||
|
||||
/xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
|
|
Loading…
Reference in New Issue