diff --git a/.gitignore b/.gitignore index 554761c6..a6fd7155 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ packages/*/*.js packages/*/*.d.ts packages/*/*.d.ts.map packages/*/lib +packages/**/generated # Development app apps/dev/src/css diff --git a/packages/adapter-hasura/codegen.ts b/packages/adapter-hasura/codegen.ts index 8423a39b..618af919 100644 --- a/packages/adapter-hasura/codegen.ts +++ b/packages/adapter-hasura/codegen.ts @@ -1,12 +1,12 @@ import type { CodegenConfig } from "@graphql-codegen/cli" -const config: CodegenConfig = { +export default { overwrite: true, - schema: "schema.graphql", + schema: "src/schema.graphql", emitLegacyCommonJSImports: false, - documents: "src/**/*.graphql", + documents: "src/queries/*.graphql", generates: { - "src/lib/": { + "src/lib/generated/": { preset: "client", config: { documentMode: "string", @@ -19,10 +19,6 @@ const config: CodegenConfig = { uuid: "string", }, }, - plugins: [], }, }, - hooks: { afterAllFileWrite: ["prettier --write"] }, -} - -export default config +} satisfies CodegenConfig diff --git a/packages/adapter-hasura/hasura.svg b/packages/adapter-hasura/hasura.svg deleted file mode 100644 index f466ca98..00000000 --- a/packages/adapter-hasura/hasura.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/packages/adapter-hasura/package.json b/packages/adapter-hasura/package.json index c303d32f..a7bb282d 100644 --- a/packages/adapter-hasura/package.json +++ b/packages/adapter-hasura/package.json @@ -44,10 +44,6 @@ "test": "./tests/test.sh", "build": "graphql-codegen-esm --config codegen.ts && tsc" }, - "peerDependencies": { - "graphql": "^16", - "graphql-request": "^6" - }, "dependencies": { "@auth/core": "workspace:*" }, @@ -57,12 +53,10 @@ "@graphql-codegen/cli": "^5.0.0", "@graphql-codegen/client-preset": "^4.1.0", "@graphql-typed-document-node/core": "^3.2.0", - "graphql": "^16.8.1", - "graphql-request": "^6.1.0", "jest": "^29.7.0", "typescript": "^5.2.2" }, "jest": { "preset": "@auth/adapter-test/jest" } -} \ No newline at end of file +} diff --git a/packages/adapter-hasura/src/index.ts b/packages/adapter-hasura/src/index.ts index c7c1c399..c29bba55 100644 --- a/packages/adapter-hasura/src/index.ts +++ b/packages/adapter-hasura/src/index.ts @@ -9,15 +9,19 @@ * ## Installation * * ```bash npm2yarn2pnpm - * npm install next-auth @auth/hasura-adapter graphql graphql-request + * npm install @auth/hasura-adapter * ``` * * @module @auth/hasura-adapter */ -import { GraphQLClient } from "graphql-request" -import type { Adapter, AdapterAccount } from "@auth/core/adapters" -import { useFragment } from "./lib" +import type { Adapter } from "@auth/core/adapters" + +import { + client as hasuraClient, + type HasuraAdapterClient, +} from "./lib/client.js" +import { useFragment } from "./lib/generated/index.js" import { AccountFragmentDoc, CreateAccountDocument, @@ -36,50 +40,13 @@ import { UpdateUserDocument, UserFragmentDoc, VerificationTokenFragmentDoc, -} from "./lib/graphql" -import type { - AccountFragment, - CreateAccountMutation, - CreateAccountMutationVariables, - CreateSessionMutation, - CreateSessionMutationVariables, - CreateUserMutation, - CreateUserMutationVariables, - CreateVerificationTokenMutation, - CreateVerificationTokenMutationVariables, - DeleteAccountMutation, - DeleteAccountMutationVariables, - DeleteSessionMutation, - DeleteSessionMutationVariables, - DeleteUserMutation, - DeleteUserMutationVariables, - DeleteVerificationTokenMutation, - DeleteVerificationTokenMutationVariables, - GetSessionAndUserQuery, - GetSessionAndUserQueryVariables, - GetUserQuery, - GetUserQueryVariables, - GetUsersQuery, - GetUsersQueryVariables, - UpdateSessionMutation, - UpdateSessionMutationVariables, - UpdateUserMutation, - UpdateUserMutationVariables, -} from "./lib/graphql" -import { formatDateConversion } from "./utils" -import type { NonNullify } from "./utils" - -interface HasuraAdapterArgs { - endpoint: string - adminSecret: string - graphqlRequestOptions?: any -} +} from "./lib/generated/graphql.js" /** * * ## Setup * - * 1. Create the next-auth schema in your database using SQL. + * 1. Create the Auth.js schema in your database using SQL. * * ```sql * CREATE TABLE accounts ( @@ -156,338 +123,184 @@ interface HasuraAdapterArgs { * Tips: [Track all the tables and relationships in Hasura](https://hasura.io/docs/latest/schema/postgres/using-existing-database/#step-1-track-tablesviews) * ::: * - *1. Configure your NextAuth.js to use the Hasura Adapter: + * 2. Add the adapter to your `pages/api/[...nextauth].ts` next-auth configuration object. * * ```javascript title="pages/api/auth/[...nextauth].js" * import NextAuth from "next-auth" - * import { HasuraAdapter } from "@next-auth/hasura-adapter" + * import { HasuraAdapter } from "@auth/hasura-adapter" * - * // For more information on each option (and a full list of options) go to - * // https://next-auth.js.org/configuration/options - * export default nextAuth({ - * adapter: HasuraAdapter({ + * export default NextAuth({ + * adapter: HasuraAdapter({ * endpoint: "", * adminSecret: "", - * graphqlRequestOptions: { - * // Optional graphql-request options - * }, - * }), + * }), * ... * }) * ``` - * - *## Passing dynamic headers - * - *If you use [graphql-request's dynamic headers feature](https://github.com/prisma-labs/graphql-request#passing-dynamic-headers-to-the-client), you are responsible for passing the 'X-Hasura-Admin-Secret' header - * - *```js - *export default nextAuth({ - * adapter: HasuraAdapter({ - * endpoint: "", - * adminSecret: "", - * graphqlRequestOptions: { - * headers: () => ({ - * "X-Hasura-Admin-Secret": "", - * // your headers here - * }), - * }, - * }), - * ... - *}) - *``` - */ -export const HasuraAdapter = ({ - endpoint, - adminSecret, - graphqlRequestOptions, -}: HasuraAdapterArgs): Adapter => { - const client = new GraphQLClient(endpoint, { - fetch: fetch ?? undefined, - ...graphqlRequestOptions, - headers: - graphqlRequestOptions?.headers instanceof Function - ? graphqlRequestOptions?.headers - : { - ...graphqlRequestOptions?.headers, - "x-hasura-admin-secret": adminSecret, - }, - }) +export function HasuraAdapter(client: HasuraAdapterClient): Adapter { + const c = hasuraClient(client) return { - // User - createUser: async (newUser) => { - const variables: CreateUserMutationVariables = { - data: formatDateConversion(newUser, "emailVerified", "toDatabase"), - } - const { insert_users_one } = await client.request( - CreateUserDocument.toString(), - variables - ) - const user = useFragment(UserFragmentDoc, insert_users_one) + async createUser(newUser) { + const { insert_users_one } = await c.run(CreateUserDocument, { + data: format.to(newUser), + }) - if (!user) { - throw new Error("Error creating user") - } - return formatDateConversion(user, "emailVerified", "toJS") + return format.from(useFragment(UserFragmentDoc, insert_users_one), true) }, - getUser: async (id) => { - const variables: GetUserQueryVariables = { id } - const { users_by_pk } = await client.request( - GetUserDocument.toString(), - variables - ) - const user = useFragment(UserFragmentDoc, users_by_pk) + async getUser(id) { + const { users_by_pk } = await c.run(GetUserDocument, { id }) - return user ? formatDateConversion(user, "emailVerified", "toJS") : null + return format.from(useFragment(UserFragmentDoc, users_by_pk)) }, - getUserByEmail: async (email) => { - const variables: GetUsersQueryVariables = { + async getUserByEmail(email) { + const { users } = await c.run(GetUsersDocument, { where: { email: { _eq: email } }, - } - const { users } = await client.request( - GetUsersDocument.toString(), - variables - ) + }) - const user = useFragment(UserFragmentDoc, users?.[0]) - - if (!user) return null - - return user ? formatDateConversion(user, "emailVerified", "toJS") : null + return format.from(useFragment(UserFragmentDoc, users?.[0])) }, - getUserByAccount: async ({ providerAccountId, provider }) => { - const variables: GetUsersQueryVariables = { + async getUserByAccount({ providerAccountId, provider }) { + const { users } = await c.run(GetUsersDocument, { where: { accounts: { provider: { _eq: provider }, providerAccountId: { _eq: providerAccountId }, }, }, - } - const { users } = await client.request( - GetUsersDocument.toString(), - variables - ) - const user = useFragment(UserFragmentDoc, users?.[0]) + }) - if (!user) return null - - return user ? formatDateConversion(user, "emailVerified", "toJS") : null + return format.from(useFragment(UserFragmentDoc, users?.[0])) }, - updateUser: async ({ id, ...data }) => { - const variables: UpdateUserMutationVariables = { + async updateUser({ id, ...data }) { + const { update_users_by_pk } = await c.run(UpdateUserDocument, { id, - data: formatDateConversion(data, "emailVerified", "toDatabase"), - } - const { update_users_by_pk } = await client.request( - UpdateUserDocument.toString(), - variables + data: format.to(data), + }) + + return format.from(useFragment(UserFragmentDoc, update_users_by_pk), true) + }, + async deleteUser(id) { + const { delete_users_by_pk } = await c.run(DeleteUserDocument, { id }) + + return format.from( + useFragment(UserFragmentDoc, delete_users_by_pk), + true ) - const user = useFragment(UserFragmentDoc, update_users_by_pk) - - if (!user) { - throw new Error("Error updating user") - } - - return formatDateConversion(user, "emailVerified", "toJS") }, - deleteUser: async (id) => { - const variables: DeleteUserMutationVariables = { - id, - } - const { delete_users_by_pk } = await client.request( - DeleteUserDocument.toString(), - variables + async createSession(data) { + const { insert_sessions_one } = await c.run(CreateSessionDocument, { + data: format.to(data), + }) + + return format.from( + useFragment(SessionFragmentDoc, insert_sessions_one), + true ) - const user = useFragment(UserFragmentDoc, delete_users_by_pk) - - if (!user) { - throw new Error("Error deleting user") - } - return formatDateConversion(user, "emailVerified", "toJS") }, - // Session - createSession: async (data) => { - const variables: CreateSessionMutationVariables = { - data: formatDateConversion(data, "expires", "toDatabase"), - } - const { insert_sessions_one } = - await client.request( - CreateSessionDocument.toString(), - variables - ) - const session = useFragment(SessionFragmentDoc, insert_sessions_one) - - if (!session) { - throw new Error("Error creating session") - } - session.expires - return formatDateConversion(session, "expires", "toJS") - }, - getSessionAndUser: async (sessionToken) => { - const variables: GetSessionAndUserQueryVariables = { + async getSessionAndUser(sessionToken) { + const { sessions } = await c.run(GetSessionAndUserDocument, { sessionToken, - } - const { sessions } = await client.request( - GetSessionAndUserDocument.toString(), - variables - ) - const session = sessions?.[0] + }) + const sessionAndUser = sessions?.[0] + if (!sessionAndUser) return null - if (!session) { - return null - } - - const { user, ...sessionData } = session + const { user, ...session } = sessionAndUser return { - session: formatDateConversion( - useFragment(SessionFragmentDoc, sessionData), - "expires", - "toJS" - ), - user: formatDateConversion( - useFragment(UserFragmentDoc, user), - "emailVerified", - "toJS" - ), + session: format.from(useFragment(SessionFragmentDoc, session), true), + user: format.from(useFragment(UserFragmentDoc, user), true), } }, - updateSession: async ({ sessionToken, ...data }) => { - const variables: UpdateSessionMutationVariables = { + async updateSession({ sessionToken, ...data }) { + const { update_sessions } = await c.run(UpdateSessionDocument, { sessionToken, - data: formatDateConversion(data, "expires", "toDatabase"), - } - const { update_sessions } = await client.request( - UpdateSessionDocument.toString(), - variables - ) + data: format.to(data), + }) const session = update_sessions?.returning?.[0] - if (!session) { - return null - } - - return formatDateConversion( - useFragment(SessionFragmentDoc, session), - "expires", - "toJS" - ) + return format.from(useFragment(SessionFragmentDoc, session)) }, - deleteSession: async (sessionToken) => { - const variables: DeleteSessionMutationVariables = { + async deleteSession(sessionToken) { + const { delete_sessions } = await c.run(DeleteSessionDocument, { sessionToken, - } - const { delete_sessions } = await client.request( - DeleteSessionDocument.toString(), - variables - ) + }) const session = delete_sessions?.returning?.[0] - if (!session) { - return null - } - - return formatDateConversion( - useFragment(SessionFragmentDoc, session), - "expires", - "toJS" - ) + return format.from(useFragment(SessionFragmentDoc, session)) }, - // Account - linkAccount: async (data) => { - const variables: CreateAccountMutationVariables = { data } - const { insert_accounts_one } = - await client.request( - CreateAccountDocument.toString(), - variables - ) + async linkAccount(data) { + const { insert_accounts_one } = await c.run(CreateAccountDocument, { + data, + }) - if (!insert_accounts_one) { - return - } - - const account = useFragment( - AccountFragmentDoc, - insert_accounts_one - ) as NonNullify< - Omit & { type: "email" | "oauth" | "oidc" } - > - if (account) { - return account as AdapterAccount - } + return useFragment(AccountFragmentDoc, insert_accounts_one) as any }, - unlinkAccount: async ({ providerAccountId, provider }) => { - const variables: DeleteAccountMutationVariables = { - provider, - providerAccountId, - } - const { delete_accounts } = await client.request( - DeleteAccountDocument.toString(), - variables - ) + async unlinkAccount(params) { + const { delete_accounts } = await c.run(DeleteAccountDocument, params) const account = delete_accounts?.returning[0] - if (!account) { - return undefined - } - - const accountFragment = useFragment( - AccountFragmentDoc, - account - ) as NonNullify< - Omit & { type: "email" | "oauth" | "oidc" } - > - if (accountFragment) { - return accountFragment as AdapterAccount - } + return useFragment(AccountFragmentDoc, account) as any }, - // Verification Token - createVerificationToken: async (data) => { - const variables: CreateVerificationTokenMutationVariables = { - data: formatDateConversion(data, "expires", "toDatabase"), - } - const { insert_verification_tokens_one } = - await client.request( - CreateVerificationTokenDocument.toString(), - variables - ) + async createVerificationToken(data) { + const { insert_verification_tokens_one } = await c.run( + CreateVerificationTokenDocument, + { data: format.to(data) } + ) - if (!insert_verification_tokens_one) { - return null - } - - return formatDateConversion( + return format.from( useFragment( VerificationTokenFragmentDoc, insert_verification_tokens_one - ), - "expires", - "toJS" + ) ) }, - useVerificationToken: async ({ identifier, token }) => { - const variables: DeleteVerificationTokenMutationVariables = { - identifier, - token, - } - const { delete_verification_tokens } = - await client.request( - DeleteVerificationTokenDocument.toString(), - variables - ) + async useVerificationToken(params) { + const { delete_verification_tokens } = await c.run( + DeleteVerificationTokenDocument, + params + ) const verificationToken = delete_verification_tokens?.returning?.[0] - if (!verificationToken) { - return null - } - - return formatDateConversion( - useFragment(VerificationTokenFragmentDoc, verificationToken), - "expires", - "toJS" + return format.from( + useFragment(VerificationTokenFragmentDoc, verificationToken) ) }, } } + +// https://github.com/honeinc/is-iso-date/blob/master/index.js +const isoDateRE = + /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/ + +function isDate(value: any) { + return value && isoDateRE.test(value) && !isNaN(Date.parse(value)) +} + +export const format = { + from( + object?: Record | null | undefined, + throwIfNullish?: B + ): B extends true ? T : T | null { + if (!object) { + if (throwIfNullish) throw new Error("Object is nullish") + return null as any + } + + const newObject: Record = {} + + for (const [key, value] of Object.entries(object)) + newObject[key] = isDate(value) ? new Date(value) : value + + return newObject as T + }, + to(object: Record): T { + const newObject: Record = {} + + for (const [key, value] of Object.entries(object)) + newObject[key] = value instanceof Date ? value.toISOString() : value + + return newObject as T + }, +} diff --git a/packages/adapter-hasura/src/lib/.gitignore b/packages/adapter-hasura/src/lib/.gitignore deleted file mode 100644 index d6b7ef32..00000000 --- a/packages/adapter-hasura/src/lib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/packages/adapter-hasura/src/lib/client.ts b/packages/adapter-hasura/src/lib/client.ts new file mode 100644 index 00000000..192abe86 --- /dev/null +++ b/packages/adapter-hasura/src/lib/client.ts @@ -0,0 +1,56 @@ +import type { TypedDocumentString } from "./generated/graphql.js" + +export interface HasuraAdapterClient { + endpoint: string + /** + * `x-hasura-admin-secret` header value + * + * [Hasura Authentication](https://hasura.io/docs/search/?q=x-hasura-admin-secret) + */ + adminSecret: string +} + +export class HasuraClientError extends Error { + name = "HasuraClientError" + constructor( + errors: any[], + query: TypedDocumentString, + variables: any + ) { + super(errors.map((error) => error.message).join("\n")) + console.error({ query, variables }) + } +} + +export function client({ adminSecret, endpoint }: HasuraAdapterClient) { + if (!adminSecret) + throw new TypeError("Hasura client error: Please provide an adminSecret") + + if (!endpoint) + throw new TypeError( + "Hasura client error: Please provide a graphql endpoint" + ) + + return { + async run< + Q extends TypedDocumentString, + T extends Q extends TypedDocumentString ? T : never, + V extends Q extends TypedDocumentString ? V : never + >(query: Q, variables?: V): Promise { + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + "x-hasura-admin-secret": adminSecret, + }, + body: JSON.stringify({ query, variables }), + }) + + const { data = {}, errors } = await response.json() + + if (errors?.length) throw new HasuraClientError(errors, query, variables) + + return data as T + }, + } +} diff --git a/packages/adapter-hasura/schema.graphql b/packages/adapter-hasura/src/schema.graphql similarity index 100% rename from packages/adapter-hasura/schema.graphql rename to packages/adapter-hasura/src/schema.graphql diff --git a/packages/adapter-hasura/src/utils.ts b/packages/adapter-hasura/src/utils.ts deleted file mode 100644 index dd9582ab..00000000 --- a/packages/adapter-hasura/src/utils.ts +++ /dev/null @@ -1,47 +0,0 @@ -export type NonNullify = { - [K in keyof T]: T[K] extends null | infer U ? U : T[K] -} - -type FormatToJS = T[K] extends string - ? Omit & Record - : Omit & Record - -type FormatToDatabase = T[K] extends Date - ? Omit & Record - : Omit & Record - -export function formatDateConversion( - object: T, - key: K, - direction: "toJS" -): FormatToJS - -export function formatDateConversion( - object: T, - key: K, - direction: "toDatabase" -): FormatToDatabase - -export function formatDateConversion( - object: T, - key: K, - direction: "toJS" | "toDatabase" -) { - if (!object) return object - - const value = object[key] - - if (value === undefined) return object - - if (direction === "toJS") { - return { - ...object, - [key]: value ? new Date(value as string) : null, - } as FormatToJS - } else { - return { - ...object, - [key]: value ? (value as unknown as Date).toISOString() : null, - } as FormatToDatabase - } -} diff --git a/packages/adapter-hasura/tests/index.test.ts b/packages/adapter-hasura/tests/index.test.ts index c87c883d..9220354b 100644 --- a/packages/adapter-hasura/tests/index.test.ts +++ b/packages/adapter-hasura/tests/index.test.ts @@ -1,7 +1,6 @@ import { runBasicTests } from "@auth/adapter-test" -import { GraphQLClient } from "graphql-request" -import { HasuraAdapter } from "../src" -import { useFragment } from "../src/lib" +import { HasuraAdapter, format } from "../src" +import { useFragment } from "../src/lib/generated" import { AccountFragmentDoc, DeleteAllDocument, @@ -12,23 +11,12 @@ import { SessionFragmentDoc, UserFragmentDoc, VerificationTokenFragmentDoc, -} from "../src/lib/graphql" -import type { - GetAccountQuery, - GetAccountQueryVariables, - GetSessionQuery, - GetSessionQueryVariables, - GetUserQuery, - GetUserQueryVariables, - GetVerificationTokenQuery, - GetVerificationTokenQueryVariables, -} from "../src/lib/graphql" -import { formatDateConversion } from "../src/utils" +} from "../src/lib/generated/graphql" +import { client as hasuraClient } from "../src/lib/client" -const client = new GraphQLClient("http://localhost:8080/v1/graphql", { - headers: { - "x-hasura-admin-secret": "myadminsecretkey", - }, +const client = hasuraClient({ + endpoint: "http://localhost:8080/v1/graphql", + adminSecret: "myadminsecretkey", }) runBasicTests({ @@ -37,73 +25,38 @@ runBasicTests({ endpoint: "http://localhost:8080/v1/graphql", }), db: { - connect: async () => { - await client.request(DeleteAllDocument.toString()) + async connect() { + await client.run(DeleteAllDocument) }, - disconnect: async () => { - await client.request(DeleteAllDocument.toString()) + async disconnect() { + await client.run(DeleteAllDocument) }, - user: async (id) => { - const variables: GetUserQueryVariables = { id } - const { users_by_pk } = await client.request( - GetUserDocument.toString(), - variables - ) + async user(id) { + const { users_by_pk } = await client.run(GetUserDocument, { id }) const user = useFragment(UserFragmentDoc, users_by_pk) - - return user ? formatDateConversion(user, "emailVerified", "toJS") : null + return format.from(user) }, - account: async ({ providerAccountId, provider }) => { - const variables: GetAccountQueryVariables = { - provider, - providerAccountId, - } - const { accounts } = await client.request( - GetAccountDocument.toString(), - variables - ) + async account(params) { + const { accounts } = await client.run(GetAccountDocument, params) - const account = useFragment(AccountFragmentDoc, accounts?.[0]) - return account ?? null + return useFragment(AccountFragmentDoc, accounts?.[0]) ?? null }, - session: async (sessionToken) => { - const variables: GetSessionQueryVariables = { + async session(sessionToken) { + const { sessions_by_pk } = await client.run(GetSessionDocument, { sessionToken, - } - const { sessions_by_pk } = await client.request( - GetSessionDocument.toString(), - variables - ) - if (!sessions_by_pk) { - return null - } + }) - return formatDateConversion( - useFragment(SessionFragmentDoc, sessions_by_pk), - "expires", - "toJS" - ) + return format.from(useFragment(SessionFragmentDoc, sessions_by_pk)) }, - verificationToken: async ({ identifier, token }) => { - const variables: GetVerificationTokenQueryVariables = { - identifier, - token, - } - const { verification_tokens } = - await client.request( - GetVerificationTokenDocument.toString(), - variables - ) + async verificationToken(params) { + const { verification_tokens } = await client.run( + GetVerificationTokenDocument, + params + ) const verificationToken = verification_tokens?.[0] - if (!verificationToken) { - return null - } - - return formatDateConversion( - useFragment(VerificationTokenFragmentDoc, verificationToken), - "expires", - "toJS" + return format.from( + useFragment(VerificationTokenFragmentDoc, verificationToken) ) }, }, diff --git a/packages/adapter-hasura/tests/test.sh b/packages/adapter-hasura/tests/test.sh index 048cc8af..1bd5fee5 100755 --- a/packages/adapter-hasura/tests/test.sh +++ b/packages/adapter-hasura/tests/test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Start Hasura -docker-compose up -d +docker compose up -d echo "Waiting 5 sec for Hasura to start..." sleep 5 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c17a88ff..fcafd65d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -487,12 +487,6 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.8.1) - graphql: - specifier: ^16.8.1 - version: 16.8.1 - graphql-request: - specifier: ^6.1.0 - version: 6.1.0(graphql@16.8.1) jest: specifier: ^29.7.0 version: 29.7.0(@types/node@18.16.3)