Unify urql version, use shared util to create client (#657)

* Add createGraphQLClient util to shared package

* Update urql version and use createGraphQLClient from shared package

* Update urql version and use createGraphQLClient from shared package - data importer

* Update urql version and use createGraphQLClient from shared package - cms

* Update CRM

* Update invoices

* Update klaviyo

* Update slack

* Update products feed

* Update search

* Remove unused urql next

* Update monitoring

* Update taxes

* Remove multipart since no longer used

* Update the lockfile

* Removed urql introspection since none of our apps used it

* Add changeset
This commit is contained in:
Krzysztof Wolski 2023-06-19 15:59:27 +02:00 committed by GitHub
parent c4be200925
commit a1ad70e879
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
100 changed files with 479 additions and 1007 deletions

View file

@ -0,0 +1,17 @@
---
"saleor-app-emails-and-messages": patch
"saleor-app-data-importer": patch
"saleor-app-products-feed": patch
"saleor-app-monitoring": patch
"@saleor/apps-shared": patch
"saleor-app-invoices": patch
"saleor-app-klaviyo": patch
"saleor-app-search": patch
"saleor-app-slack": patch
"saleor-app-taxes": patch
"saleor-app-cms": patch
"saleor-app-crm": patch
---
Updated configuration and dependencies of GraphQL client - urql.
All applications use now unified config for creating the client. Also unused related packages has been removed.

View file

@ -0,0 +1,5 @@
---
"@saleor/apps-shared": patch
---
Added `createGraphQLClient` function to shared package. Can be used to create urql client instance with optional authorization.

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -21,7 +21,7 @@
"@saleor/apps-shared": "workspace:*",
"@saleor/macaw-ui": "^0.7.2",
"@sentry/nextjs": "^7.43.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"clsx": "^1.2.1",
"graphql": "16.6.0",
"graphql-tag": "^2.12.6",
@ -32,7 +32,7 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.39.1",
"react-markdown": "^8.0.5",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"uuid": "^9.0.0",
"vite": "4.3.9",
@ -45,7 +45,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@types/react": "18.2.5",

View file

@ -5,8 +5,8 @@ import {
UpdateMetadataDocument,
WebhookProductVariantFragment,
} from "../../../../generated/graphql";
import { createClient } from "../../graphql";
import { createCmsKeyForSaleorItem } from "./metadata";
import { createGraphQLClient } from "@saleor/apps-shared";
type WebhookContext = Parameters<NextWebhookApiHandler>["2"];
@ -60,7 +60,7 @@ export const updateMetadata = async ({
cmsProviderInstanceIdsToDelete: Record<string, string>;
}) => {
const { token, saleorApiUrl } = context.authData;
const apiClient = createClient(saleorApiUrl, async () => ({ token }));
const apiClient = createGraphQLClient({ saleorApiUrl, token });
await executeMetadataUpdateMutation({
apiClient,
@ -85,7 +85,7 @@ export const batchUpdateMetadata = async ({
variantCMSProviderInstanceIdsToDelete: ItemMetadataRecord[];
}) => {
const { token, saleorApiUrl } = context.authData;
const apiClient = createClient(saleorApiUrl, async () => ({ token }));
const apiClient = createGraphQLClient({ saleorApiUrl, token });
const variantCMSProviderInstanceIdsToCreateMap = variantCMSProviderInstanceIdsToCreate.reduce(
(acc, { id, cmsProviderInstanceIds }) => ({

View file

@ -1,50 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
const getExchanges = (getAuth: AuthConfig<IAuthState>["getAuth"]) => [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
];
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: getExchanges(getAuth),
});

View file

@ -4,7 +4,7 @@ import {
ProductsDataForImportDocument,
ProductsDataForImportQuery,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
const PER_PAGE = 100;
@ -32,7 +32,7 @@ export const useQueryAllProducts = (paused: boolean, channelSlug: string | null)
}
const token = appBridgeState.token;
const client = createClient(saleorApiUrl, () => Promise.resolve({ token }));
const client = createGraphQLClient({ saleorApiUrl, token });
if (!client) {
return;

View file

@ -4,8 +4,8 @@ import type { NextApiRequest, NextApiResponse } from "next";
import { saleorApp } from "../../../saleor-app";
import { CMSSchemaChannels, SingleChannelSchema } from "../../lib/cms/config";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { createGraphQLClient } from "@saleor/apps-shared";
export type SettingsUpdateApiRequest = SingleChannelSchema;
@ -14,10 +14,12 @@ export interface ChannelsApiResponse {
data?: CMSSchemaChannels;
}
// todo: implement
// const obfuscateSecret = (secret: string) => {
// return "*".repeat(secret.length - 4) + secret.substring(secret.length - 4);
// };
/*
* todo: implement
* const obfuscateSecret = (secret: string) => {
* return "*".repeat(secret.length - 4) + secret.substring(secret.length - 4);
* };
*/
const handler: NextProtectedApiHandler = async (
req: NextApiRequest,
@ -26,9 +28,10 @@ const handler: NextProtectedApiHandler = async (
) => {
const { authData } = context;
const client = createClient(authData.saleorApiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
}));
});
const settingsManager = createSettingsManager(client);

View file

@ -2,11 +2,10 @@ import { NextProtectedApiHandler, createProtectedHandler } from "@saleor/app-sdk
import { saleorApp } from "../../../saleor-app";
import type { NextApiRequest, NextApiResponse } from "next";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { getProviderInstancesSettings } from "../../lib/cms/client/settings";
import { pingProviderInstance } from "../../lib/cms/client/clients-execution";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export interface ProviderInstancePingApiPayload {
providerInstanceId: string;
@ -42,9 +41,11 @@ const handler: NextProtectedApiHandler = async (
});
}
const client = createClient(authData.saleorApiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
}));
});
const settingsManager = createSettingsManager(client);
const providerInstancesSettingsParsed = await getProviderInstancesSettings(settingsManager);

View file

@ -4,9 +4,9 @@ import type { NextApiRequest, NextApiResponse } from "next";
import { saleorApp } from "../../../saleor-app";
import { CMSSchemaProviderInstances, SingleProviderSchema } from "../../lib/cms/config";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { generateUniqueId } from "../../modules/cms/utils";
import { createGraphQLClient } from "@saleor/apps-shared";
export type SettingsUpdateApiRequest = SingleProviderSchema;
@ -15,10 +15,12 @@ export interface ProviderInstancesApiResponse {
data?: CMSSchemaProviderInstances | SingleProviderSchema;
}
// todo: implement
// const obfuscateSecret = (secret: string) => {
// return "*".repeat(secret.length - 4) + secret.substring(secret.length - 4);
// };
/*
* todo: implement
* const obfuscateSecret = (secret: string) => {
* return "*".repeat(secret.length - 4) + secret.substring(secret.length - 4);
* };
*/
const handler: NextProtectedApiHandler = async (
req: NextApiRequest,
@ -27,9 +29,10 @@ const handler: NextProtectedApiHandler = async (
) => {
const { authData } = context;
const client = createClient(authData.saleorApiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
}));
});
const settingsManager = createSettingsManager(client);

View file

@ -7,11 +7,10 @@ import { getChannelsSettings, getProviderInstancesSettings } from "../../lib/cms
import { providersSchemaSet } from "../../lib/cms/config/providers";
import { cmsProviders, CMSProvider } from "../../lib/cms/providers";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { batchUpdateMetadata, MetadataRecord } from "../../lib/cms/client/metadata-execution";
import { CmsBatchOperations } from "../../lib/cms/types";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export interface SyncProductsVariantsApiPayload {
channelSlug: string;
@ -42,9 +41,10 @@ const handler: NextProtectedApiHandler = async (
logger.debug("Called endpoint sync-products-variants");
const client = createClient(authData.saleorApiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
}));
});
if (req.method !== "POST") {
return res.status(405).json({

View file

@ -9,10 +9,9 @@ import { getCmsKeysFromSaleorItem } from "../../../lib/cms/client/metadata";
import { getChannelsSlugsFromSaleorItem } from "../../../lib/cms/client/channels";
import { createCmsOperations, executeCmsOperations, updateMetadata } from "../../../lib/cms/client";
import { createClient } from "../../../lib/graphql";
import { fetchProductVariantMetadata } from "../../../lib/metadata";
import { isAppWebhookIssuer } from "./_utils";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export const config = {
api: {
@ -79,9 +78,10 @@ export const handler: NextWebhookApiHandler<ProductUpdatedWebhookPayloadFragment
});
}
const client = createClient(saleorApiUrl, async () => ({
token: token,
}));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const allCMSErrors: string[] = [];

View file

@ -8,10 +8,9 @@ import { saleorApp } from "../../../../saleor-app";
import { getChannelsSlugsFromSaleorItem } from "../../../lib/cms/client/channels";
import { createCmsOperations, executeCmsOperations, updateMetadata } from "../../../lib/cms/client";
import { createClient } from "../../../lib/graphql";
import { fetchProductVariantMetadata } from "../../../lib/metadata";
import { getCmsKeysFromSaleorItem } from "../../../lib/cms/client/metadata";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export const config = {
api: {
@ -68,9 +67,10 @@ export const handler: NextWebhookApiHandler<ProductVariantCreatedWebhookPayloadF
});
}
const client = createClient(saleorApiUrl, async () => ({
token: token,
}));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const productVariantChannels = getChannelsSlugsFromSaleorItem(productVariant);
const productVariantMetadata = await fetchProductVariantMetadata(client, productVariant.id);

View file

@ -8,8 +8,7 @@ import { saleorApp } from "../../../../saleor-app";
import { getCmsKeysFromSaleorItem } from "../../../lib/cms/client/metadata";
import { createCmsOperations, executeCmsOperations, updateMetadata } from "../../../lib/cms/client";
import { createClient } from "../../../lib/graphql";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export const config = {
api: {
@ -66,9 +65,10 @@ export const handler: NextWebhookApiHandler<ProductVariantDeletedWebhookPayloadF
});
}
const client = createClient(saleorApiUrl, async () => ({
token: token,
}));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const productVariantCmsKeys = getCmsKeysFromSaleorItem(productVariant);
const cmsOperations = await createCmsOperations({

View file

@ -9,10 +9,9 @@ import { getCmsKeysFromSaleorItem } from "../../../lib/cms/client/metadata";
import { getChannelsSlugsFromSaleorItem } from "../../../lib/cms/client/channels";
import { createCmsOperations, executeCmsOperations, updateMetadata } from "../../../lib/cms/client";
import { createClient } from "../../../lib/graphql";
import { fetchProductVariantMetadata } from "../../../lib/metadata";
import { isAppWebhookIssuer } from "./_utils";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export const config = {
api: {
@ -80,9 +79,10 @@ export const handler: NextWebhookApiHandler<ProductVariantUpdatedWebhookPayloadF
});
}
const client = createClient(saleorApiUrl, async () => ({
token: token,
}));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const productVariantChannels = getChannelsSlugsFromSaleorItem(productVariant);
const productVariantMetadata = await fetchProductVariantMetadata(client, productVariant.id);

View file

@ -1,16 +1,17 @@
import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { createGraphQLClient } from "@saleor/apps-shared";
import { PropsWithChildren } from "react";
import { Provider } from "urql";
import { createClient } from "../lib/graphql";
export function GraphQLProvider(props: PropsWithChildren<{}>) {
const { appBridgeState } = useAppBridge();
const saleorApiUrl = appBridgeState?.saleorApiUrl!;
const token = appBridgeState?.token!;
const client = createClient(saleorApiUrl, async () => ({
token: appBridgeState?.token!,
}));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
return <Provider value={client} {...props} />;
}

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -22,21 +22,20 @@
"@trpc/next": "^10.18.0",
"@trpc/react-query": "^10.18.0",
"@trpc/server": "^10.18.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"@vitejs/plugin-react": "4.0.0",
"clsx": "^1.2.1",
"graphql": "16.6.0",
"graphql-tag": "^2.12.6",
"jsdom": "^20.0.3",
"next": "13.3.0",
"next-urql": "4.0.3",
"pino": "^8.14.1",
"pino-pretty": "^10.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.43.0",
"react-is": "^18.2.0",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"vite": "4.3.9",
"vitest": "0.31.3",
@ -49,7 +48,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@testing-library/react-hooks": "^8.0.1",

View file

@ -1,48 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});

View file

@ -1,7 +1,7 @@
import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { createGraphQLClient } from "@saleor/apps-shared";
import { PropsWithChildren } from "react";
import { Provider } from "urql";
import { createClient } from "./create-graphq-client";
export function GraphQLProvider(props: PropsWithChildren<{}>) {
const { appBridgeState } = useAppBridge();
@ -11,9 +11,10 @@ export function GraphQLProvider(props: PropsWithChildren<{}>) {
return <div {...props}></div>;
}
const client = createClient(saleorApiUrl, async () =>
Promise.resolve({ token: appBridgeState?.token! })
);
const client = createGraphQLClient({
saleorApiUrl: saleorApiUrl,
token: appBridgeState?.token,
});
return <Provider value={client} {...props} />;
}

View file

@ -1,9 +1,9 @@
import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { useEffect, useState } from "react";
import { createClient } from "../../lib/create-graphq-client";
import { FetchCustomersDocument, FetchCustomersQuery } from "../../../generated/graphql";
import { OperationResult } from "urql";
import { metadataToMailchimpTags } from "./metadata-to-mailchimp-tags";
import { createGraphQLClient } from "@saleor/apps-shared";
type CustomerCollectionItem = {
email: string;
@ -27,9 +27,10 @@ export const useFetchAllCustomers = (enabled: boolean) => {
return;
}
const client = createClient(appBridgeState.saleorApiUrl, async () => ({
token: appBridgeState.token!,
}));
const client = createGraphQLClient({
saleorApiUrl: appBridgeState.saleorApiUrl,
token: appBridgeState.token,
});
const fetchPage = (cursor?: string) =>
client.query(FetchCustomersDocument, { cursor }).toPromise();

View file

@ -4,8 +4,7 @@ import { TRPCError } from "@trpc/server";
import { ProtectedHandlerError } from "@saleor/app-sdk/handlers/next";
import { saleorApp } from "../../saleor-app";
import { createClient } from "../../lib/create-graphq-client";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
const logger = createLogger({ service: "protected-client-procedure" });
@ -108,9 +107,10 @@ export const protectedClientProcedure = procedure
.use(attachAppToken)
.use(validateClientToken)
.use(async ({ ctx, next }) => {
const client = createClient(ctx.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.appToken })
);
const client = createGraphQLClient({
saleorApiUrl: ctx.saleorApiUrl,
token: ctx.token,
});
return next({
ctx: {

View file

@ -4,11 +4,10 @@ import {
CustomerCreatedDocument,
CustomerCreatedPayloadFragment,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/create-graphq-client";
import { MailchimpConfigSettingsManager } from "../../../modules/mailchimp/mailchimp-config-settings-manager";
import { MailchimpClientOAuth } from "../../../modules/mailchimp/mailchimp-client";
import { metadataToMailchimpTags } from "../../../modules/saleor-customers-sync/metadata-to-mailchimp-tags";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export const customerCreatedWebhook = new SaleorAsyncWebhook<CustomerCreatedPayloadFragment>({
name: "Customer Created in Saleor",
@ -40,9 +39,10 @@ export const customerCreatedHandler: NextWebhookApiHandler<CustomerCreatedPayloa
return res.status(200).end();
}
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
const settingsManager = new MailchimpConfigSettingsManager(client, authData.appId);

View file

@ -5,11 +5,10 @@ import {
CustomerUpdatedDocument,
CustomerUpdatedPayloadFragment,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/create-graphq-client";
import { MailchimpConfigSettingsManager } from "../../../modules/mailchimp/mailchimp-config-settings-manager";
import { MailchimpClientOAuth } from "../../../modules/mailchimp/mailchimp-client";
import { metadataToMailchimpTags } from "../../../modules/saleor-customers-sync/metadata-to-mailchimp-tags";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
export const customerMetadataUpdatedWebhook =
new SaleorAsyncWebhook<CustomerUpdatedPayloadFragment>({
@ -41,9 +40,10 @@ const handler: NextWebhookApiHandler<CustomerUpdatedPayloadFragment> = async (
return res.status(200).end();
}
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
const settingsManager = new MailchimpConfigSettingsManager(client, authData.appId);

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -19,7 +19,7 @@
"@saleor/apps-shared": "workspace:*",
"@saleor/macaw-ui": "^0.7.2",
"@sentry/nextjs": "^7.39.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"@vitejs/plugin-react": "4.0.0",
"clsx": "^1.2.1",
"dot-object": "^2.1.4",
@ -33,7 +33,7 @@
"pino-pretty": "^10.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"vite": "4.3.9",
"vitest": "0.31.3",
@ -47,7 +47,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@testing-library/react-hooks": "^8.0.1",

View file

@ -1,48 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});

View file

@ -1,15 +1,15 @@
import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { createGraphQLClient } from "@saleor/apps-shared";
import { PropsWithChildren } from "react";
import { Provider } from "urql";
import { createClient } from "../lib/graphql";
export function GraphQLProvider(props: PropsWithChildren<{}>) {
const { appBridgeState } = useAppBridge();
const client = createClient(appBridgeState?.saleorApiUrl!, async () =>
Promise.resolve({ token: appBridgeState?.token! })
);
const client = createGraphQLClient({
saleorApiUrl: appBridgeState?.saleorApiUrl!,
token: appBridgeState?.token!,
});
return <Provider value={client} {...props} />;
}

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -27,7 +27,7 @@
"@trpc/next": "^10.13.0",
"@trpc/react-query": "^10.13.0",
"@trpc/server": "^10.13.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"@vitejs/plugin-react": "4.0.0",
"clsx": "^1.2.1",
"dotenv": "^16.0.3",
@ -38,7 +38,6 @@
"jsdom": "^20.0.3",
"mjml": "^4.13.0",
"next": "13.3.0",
"next-urql": "4.0.3",
"nodemailer": "^6.9.1",
"pino": "^8.14.1",
"pino-pretty": "^10.0.0",
@ -47,7 +46,7 @@
"react-hook-form": "^7.43.9",
"react-is": "^18.2.0",
"react-query": "^3.39.3",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"vite": "4.3.9",
"vitest": "0.31.3",
@ -61,7 +60,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@testing-library/react-hooks": "^8.0.1",

View file

@ -1,13 +1,11 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import { createClient } from "../../src/lib/create-graphql-client";
import { createGraphQLClient } from "@saleor/apps-shared";
import { SaleorCloudAPL } from "@saleor/app-sdk/APL";
import { createSettingsManager } from "../../src/lib/metadata-manager";
export const getMetadataManagerForEnv = (apiUrl: string, appToken: string, appId: string) => {
const client = createClient(apiUrl, async () => ({
token: appToken,
}));
const client = createGraphQLClient({ saleorApiUrl: apiUrl, token: appToken });
return createSettingsManager(client, appId);
};

View file

@ -1,48 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});

View file

@ -1,13 +1,11 @@
import { ChannelsFetcher } from "./channels-fetcher";
import { createClient } from "../../lib/create-graphql-client";
import { createGraphQLClient } from "@saleor/apps-shared";
import { router } from "../trpc/trpc-server";
import { protectedClientProcedure } from "../trpc/protected-client-procedure";
export const channelsRouter = router({
fetch: protectedClientProcedure.query(async ({ ctx }) => {
const client = createClient(ctx.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.appToken })
);
const client = createGraphQLClient({ saleorApiUrl: ctx.saleorApiUrl, token: ctx.token });
const fetcher = new ChannelsFetcher(client);

View file

@ -3,8 +3,7 @@ import { middleware, procedure } from "./trpc-server";
import { TRPCError } from "@trpc/server";
import { ProtectedHandlerError } from "@saleor/app-sdk/handlers/next";
import { saleorApp } from "../../saleor-app";
import { logger } from "@saleor/apps-shared";
import { createClient } from "../../lib/create-graphql-client";
import { createGraphQLClient, logger } from "@saleor/apps-shared";
const attachAppToken = middleware(async ({ ctx, next }) => {
logger.debug("attachAppToken middleware");
@ -105,9 +104,7 @@ export const protectedClientProcedure = procedure
.use(attachAppToken)
.use(validateClientToken)
.use(async ({ ctx, next }) => {
const client = createClient(ctx.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.appToken })
);
const client = createGraphQLClient({ saleorApiUrl: ctx.saleorApiUrl, token: ctx.token });
return next({
ctx: {

View file

@ -1,8 +1,7 @@
import { createAppRegisterHandler } from "@saleor/app-sdk/handlers/next";
import { saleorApp } from "../../saleor-app";
import { createClient } from "../../lib/create-graphql-client";
import { logger } from "@saleor/apps-shared";
import { logger, createGraphQLClient } from "@saleor/apps-shared";
import { getBaseUrl } from "../../lib/get-base-url";
import { registerNotifyWebhook } from "../../lib/register-notify-webhook";
@ -29,9 +28,10 @@ export default createAppRegisterHandler({
// Subscribe to Notify using the mutation since it does not use subscriptions and can't be subscribed via manifest
logger.debug("onAuthAplSaved executing");
const baseUrl = getBaseUrl(request.headers);
const client = createClient(ctx.authData.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: ctx.authData.saleorApiUrl,
token: ctx.authData.token,
});
await registerNotifyWebhook({
client: client,

View file

@ -1,13 +1,12 @@
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createLogger, createGraphQLClient } from "@saleor/apps-shared";
import {
InvoiceSentWebhookPayloadFragment,
OrderDetailsFragmentDoc,
} from "../../../../generated/graphql";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
const InvoiceSentWebhookPayload = gql`
${OrderDetailsFragmentDoc}
@ -73,9 +72,10 @@ const handler: NextWebhookApiHandler<InvoiceSentWebhookPayloadFragment> = async
}
const channel = order.channel.slug;
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -1,8 +1,7 @@
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createLogger, createGraphQLClient } from "@saleor/apps-shared";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
import { MessageEventTypes } from "../../../modules/event-handlers/message-event-types";
/*
@ -99,9 +98,10 @@ const handler: NextWebhookApiHandler<NotifySubscriptionPayload> = async (req, re
.json({ error: "Email recipient has not been specified in the event payload." });
}
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -1,13 +1,12 @@
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createLogger, createGraphQLClient } from "@saleor/apps-shared";
import {
OrderCancelledWebhookPayloadFragment,
OrderDetailsFragmentDoc,
} from "../../../../generated/graphql";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
const OrderCancelledWebhookPayload = gql`
${OrderDetailsFragmentDoc}
@ -64,9 +63,10 @@ const handler: NextWebhookApiHandler<OrderCancelledWebhookPayloadFragment> = asy
}
const channel = order.channel.slug;
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -1,13 +1,12 @@
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createLogger, createGraphQLClient } from "@saleor/apps-shared";
import {
OrderConfirmedWebhookPayloadFragment,
OrderDetailsFragmentDoc,
} from "../../../../generated/graphql";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
const OrderConfirmedWebhookPayload = gql`
${OrderDetailsFragmentDoc}
@ -65,9 +64,10 @@ const handler: NextWebhookApiHandler<OrderConfirmedWebhookPayloadFragment> = asy
}
const channel = order.channel.slug;
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -2,10 +2,9 @@ import { OrderDetailsFragmentDoc } from "./../../../../generated/graphql";
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createLogger, createGraphQLClient } from "@saleor/apps-shared";
import { OrderCreatedWebhookPayloadFragment } from "../../../../generated/graphql";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
const OrderCreatedWebhookPayload = gql`
${OrderDetailsFragmentDoc}
@ -62,9 +61,10 @@ const handler: NextWebhookApiHandler<OrderCreatedWebhookPayloadFragment> = async
}
const channel = order.channel.slug;
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -1,13 +1,12 @@
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
import {
OrderDetailsFragmentDoc,
OrderFulfilledWebhookPayloadFragment,
} from "../../../../generated/graphql";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
const OrderFulfilledWebhookPayload = gql`
${OrderDetailsFragmentDoc}
@ -65,9 +64,10 @@ const handler: NextWebhookApiHandler<OrderFulfilledWebhookPayloadFragment> = asy
}
const channel = order.channel.slug;
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -1,13 +1,12 @@
import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { saleorApp } from "../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
import {
OrderDetailsFragmentDoc,
OrderFullyPaidWebhookPayloadFragment,
} from "../../../../generated/graphql";
import { sendEventMessages } from "../../../modules/event-handlers/send-event-messages";
import { createClient } from "../../../lib/create-graphql-client";
const OrderFullyPaidWebhookPayload = gql`
${OrderDetailsFragmentDoc}
@ -65,9 +64,10 @@ const handler: NextWebhookApiHandler<OrderFullyPaidWebhookPayloadFragment> = asy
}
const channel = order.channel.slug;
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
await sendEventMessages({
authData,

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -22,8 +22,7 @@
"@trpc/next": "^10.10.0",
"@trpc/react-query": "^10.10.0",
"@trpc/server": "^10.10.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-multipart-fetch": "^1.0.1",
"@urql/exchange-auth": "^2.1.4",
"@web-std/file": "^3.0.2",
"clsx": "^1.2.1",
"eslint": "8.42.0",
@ -37,7 +36,7 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.41.0",
"tiny-invariant": "^1.3.1",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"zod": "^3.20.2"
},
@ -49,7 +48,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@types/react": "18.2.5",
"@types/react-dom": "18.2.5",

View file

@ -1,13 +1,14 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import { createClient } from "../../src/lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
import { createSettingsManager } from "../../src/modules/app-configuration/metadata-manager";
import { SaleorCloudAPL } from "@saleor/app-sdk/APL";
export const getMetadataManagerForEnv = (apiUrl: string, appToken: string) => {
const client = createClient(apiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: apiUrl,
token: appToken,
}));
});
return createSettingsManager(client);
};

View file

@ -2,9 +2,9 @@
import * as dotenv from "dotenv";
import { fetchCloudAplEnvs, verifyRequiredEnvs } from "../migration-utils";
import { createClient } from "../../../src/lib/graphql";
import { RemoveMetadataDocument } from "../../../generated/graphql";
import { MigrationV1toV2Consts } from "./const";
import { createGraphQLClient } from "@saleor/apps-shared";
dotenv.config();
@ -15,9 +15,10 @@ const runMigration = async () => {
const results = await Promise.all(
allEnvs.map((env) => {
const client = createClient(env.saleorApiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: env.saleorApiUrl,
token: env.token,
}));
});
return client
.mutation(RemoveMetadataDocument, {

View file

@ -1,45 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import { cacheExchange, createClient as urqlCreateClient, dedupExchange } from "urql";
import { multipartFetchExchange } from "@urql/exchange-multipart-fetch";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
multipartFetchExchange,
],
});

View file

@ -1,14 +1,15 @@
import { createClient } from "../../lib/graphql";
import { router } from "../trpc/trpc-server";
import { protectedClientProcedure } from "../trpc/protected-client-procedure";
import { ChannelsFetcher } from "./channels-fetcher";
import { ChannelFragment } from "../../../generated/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
export const channelsRouter = router({
fetch: protectedClientProcedure.query(async ({ ctx, input }): Promise<ChannelFragment[]> => {
const client = createClient(ctx.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.appToken })
);
const client = createGraphQLClient({
saleorApiUrl: ctx.saleorApiUrl,
token: ctx.token,
});
const fetcher = new ChannelsFetcher(client);

View file

@ -1,10 +1,9 @@
import { createClient } from "../../lib/graphql";
import { verifyJWT } from "@saleor/app-sdk/verify-jwt";
import { middleware, procedure } from "./trpc-server";
import { saleorApp } from "../../saleor-app";
import { TRPCError } from "@trpc/server";
import { ProtectedHandlerError } from "@saleor/app-sdk/handlers/next";
import { logger } from "@saleor/apps-shared";
import { createGraphQLClient, logger } from "@saleor/apps-shared";
const attachAppToken = middleware(async ({ ctx, next }) => {
logger.debug("attachAppToken middleware");
@ -103,9 +102,10 @@ export const protectedClientProcedure = procedure
.use(attachAppToken)
.use(validateClientToken)
.use(async ({ ctx, next }) => {
const client = createClient(ctx.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.appToken })
);
const client = createGraphQLClient({
saleorApiUrl: ctx.saleorApiUrl,
token: ctx.token,
});
return next({
ctx: {

View file

@ -1,10 +1,13 @@
import { createAppRegisterHandler } from "@saleor/app-sdk/handlers/next";
import { REQUIRED_SALEOR_VERSION, saleorApp } from "../../saleor-app";
import { gql } from "urql";
import { createClient } from "../../lib/graphql";
import { SaleorVersionQuery } from "../../../generated/graphql";
import { createLogger, SaleorVersionCompatibilityValidator } from "@saleor/apps-shared";
import {
createGraphQLClient,
createLogger,
SaleorVersionCompatibilityValidator,
} from "@saleor/apps-shared";
const allowedUrlsPattern = process.env.ALLOWED_DOMAIN_PATTERN;
@ -51,10 +54,9 @@ export default createAppRegisterHandler({
});
try {
const client = createClient(saleorApiUrl, async () => {
return {
token,
};
const client = createGraphQLClient({
saleorApiUrl: saleorApiUrl,
token: token,
});
const saleorVersion = await client

View file

@ -5,7 +5,6 @@ import {
InvoiceRequestedPayloadFragment,
OrderPayloadFragment,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { SaleorInvoiceUploader } from "../../../modules/invoices/invoice-uploader/saleor-invoice-uploader";
import { InvoiceCreateNotifier } from "../../../modules/invoices/invoice-create-notifier/invoice-create-notifier";
import {
@ -15,7 +14,7 @@ import {
import { MicroinvoiceInvoiceGenerator } from "../../../modules/invoices/invoice-generator/microinvoice/microinvoice-invoice-generator";
import { hashInvoiceFilename } from "../../../modules/invoices/invoice-file-name/hash-invoice-filename";
import { resolveTempPdfFileLocation } from "../../../modules/invoices/invoice-file-name/resolve-temp-pdf-file-location";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
import { SALEOR_API_URL_HEADER } from "@saleor/app-sdk/const";
import { GetAppConfigurationV2Service } from "../../../modules/app-configuration/schema-v2/get-app-configuration.v2.service";
import { ShopInfoFetcher } from "../../../modules/shop-info/shop-info-fetcher";
@ -176,9 +175,10 @@ export const handler: NextWebhookApiHandler<InvoiceRequestedPayloadFragment> = a
logger.debug({ invoiceName }, "Generated invoice name");
try {
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
const hashedInvoiceName = hashInvoiceFilename(invoiceName, orderId);

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -18,7 +18,7 @@
"@saleor/apps-shared": "workspace:*",
"@saleor/macaw-ui": "^0.7.2",
"@sentry/nextjs": "^7.36.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"clsx": "^1.2.1",
"graphql": "16.6.0",
"graphql-tag": "^2.12.6",
@ -29,7 +29,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-helmet": "^6.1.0",
"urql": "^3.0.3",
"urql": "^4.0.4",
"vite": "4.3.9",
"vitest": "0.31.3"
},
@ -41,7 +41,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@types/react": "18.2.5",
"@types/react-dom": "18.2.5",

View file

@ -1,48 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});

View file

@ -1,9 +1,9 @@
import { createProtectedHandler, NextProtectedApiHandler } from "@saleor/app-sdk/handlers/next";
import { EncryptedMetadataManager } from "@saleor/app-sdk/settings-manager";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { saleorApp } from "../../../saleor-app";
import { createGraphQLClient } from "@saleor/apps-shared";
type ConfigurationKeysType =
| "PUBLIC_TOKEN"
@ -46,7 +46,11 @@ const handler: NextProtectedApiHandler = async (request, res, ctx) => {
const {
authData: { token, saleorApiUrl, appId },
} = ctx;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);

View file

@ -5,10 +5,10 @@ import {
CustomerCreatedWebhookPayloadFragment,
UntypedCustomerCreatedDocument,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { Klaviyo } from "../../../lib/klaviyo";
import { createSettingsManager } from "../../../lib/metadata";
import { saleorApp } from "../../../../saleor-app";
import { createGraphQLClient } from "@saleor/apps-shared";
const CustomerCreatedWebhookPayload = gql`
fragment CustomerCreatedWebhookPayload on CustomerCreated {
@ -68,7 +68,11 @@ const handler: NextWebhookApiHandler<CustomerCreatedWebhookPayloadFragment> = as
const { payload, authData } = context;
const { saleorApiUrl, token, appId } = authData;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);
const klaviyoToken = await settings.get("PUBLIC_TOKEN");

View file

@ -5,10 +5,10 @@ import {
FulfillmentCreatedWebhookPayloadFragment,
UntypedFulfillmentCreatedDocument,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { Klaviyo } from "../../../lib/klaviyo";
import { createSettingsManager } from "../../../lib/metadata";
import { saleorApp } from "../../../../saleor-app";
import { createGraphQLClient } from "@saleor/apps-shared";
const FulfillmentCreatedWebhookPayload = gql`
fragment FulfillmentCreatedWebhookPayload on FulfillmentCreated {
@ -74,7 +74,10 @@ const handler: NextWebhookApiHandler<FulfillmentCreatedWebhookPayloadFragment> =
const { payload, authData } = context;
const { saleorApiUrl, token, appId } = authData;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);
const klaviyoToken = await settings.get("PUBLIC_TOKEN");

View file

@ -5,10 +5,10 @@ import {
OrderCreatedWebhookPayloadFragment,
UntypedOrderCreatedDocument,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { Klaviyo } from "../../../lib/klaviyo";
import { createSettingsManager } from "../../../lib/metadata";
import { saleorApp } from "../../../../saleor-app";
import { createGraphQLClient } from "@saleor/apps-shared";
const OrderCreatedWebhookPayload = gql`
fragment OrderCreatedWebhookPayload on OrderCreated {
@ -44,7 +44,10 @@ const handler: NextWebhookApiHandler<OrderCreatedWebhookPayloadFragment> = async
const { payload, authData } = context;
const { saleorApiUrl, token, appId } = authData;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);
const klaviyoToken = await settings.get("PUBLIC_TOKEN");

View file

@ -5,10 +5,10 @@ import {
OrderFullyPaidWebhookPayloadFragment,
UntypedOrderFullyPaidDocument,
} from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { Klaviyo } from "../../../lib/klaviyo";
import { createSettingsManager } from "../../../lib/metadata";
import { saleorApp } from "../../../../saleor-app";
import { createGraphQLClient } from "@saleor/apps-shared";
const OrderFullyPaidWebhookPayload = gql`
fragment OrderFullyPaidWebhookPayload on OrderFullyPaid {
@ -44,7 +44,11 @@ const handler: NextWebhookApiHandler<OrderFullyPaidWebhookPayloadFragment> = asy
const { payload, authData } = context;
const { saleorApiUrl, token, appId } = authData;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);
const klaviyoToken = await settings.get("PUBLIC_TOKEN");

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -17,7 +17,7 @@
"@saleor/app-sdk": "0.40.1",
"@saleor/apps-shared": "workspace:*",
"@saleor/macaw-ui": "^0.7.2",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"@vitejs/plugin-react": "4.0.0",
"clsx": "^1.2.1",
"graphql": "16.6.0",
@ -29,7 +29,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.42.1",
"urql": "^3.0.3",
"urql": "^4.0.4",
"vite": "4.3.9",
"vitest": "0.31.3"
},
@ -41,7 +41,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@testing-library/react-hooks": "^8.0.1",

View file

@ -1,16 +1,17 @@
import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { createGraphQLClient } from "@saleor/apps-shared";
import { PropsWithChildren } from "react";
import { Provider } from "urql";
import { createClient } from "./lib/create-graphq-client";
export function GraphQLProvider(props: PropsWithChildren<{}>) {
const { appBridgeState } = useAppBridge();
const saleorApiUrl = appBridgeState?.saleorApiUrl!;
const token = appBridgeState?.token!;
const client = createClient(
`/graphql`,
async () => Promise.resolve({ token: appBridgeState?.token! }),
() => appBridgeState?.saleorApiUrl!
);
const client = createGraphQLClient({
saleorApiUrl,
token,
});
return <Provider value={client} {...props} />;
}

View file

@ -1,53 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
export const createClient = (
url: string,
getAuth: AuthConfig<IAuthState>["getAuth"],
getSaleorApiUrl: () => string
) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
"Saleor-Api-Url": getSaleorApiUrl(),
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -25,7 +25,7 @@
"@trpc/next": "^10.9.0",
"@trpc/react-query": "^10.9.0",
"@trpc/server": "^10.9.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"@vitejs/plugin-react": "4.0.0",
"clsx": "^1.2.1",
"fast-xml-parser": "^4.0.15",
@ -33,7 +33,6 @@
"graphql-tag": "^2.12.6",
"jsdom": "^20.0.3",
"next": "13.3.0",
"next-urql": "4.0.3",
"pino": "^8.14.1",
"pino-pretty": "^10.0.0",
"react": "18.2.0",
@ -41,7 +40,7 @@
"react-hook-form": "^7.43.9",
"react-is": "^18.2.0",
"react-query": "^3.39.3",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"vite": "4.3.9",
"vitest": "0.31.3",
@ -55,7 +54,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@testing-library/react-hooks": "^8.0.1",

View file

@ -1,57 +1,11 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
import { AuthData } from "@saleor/app-sdk/APL";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});
import { createGraphQLClient } from "@saleor/apps-shared";
export const GraphqlClientFactory = {
fromAuthData(authData: Pick<AuthData, "token" | "saleorApiUrl">) {
return createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
return createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
},
};

View file

@ -1,8 +1,7 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { initUrqlClient } from "next-urql";
import { GoogleFeedProductVariantFragment } from "../../../../../../generated/graphql";
import { apl } from "../../../../../saleor-app";
import { createLogger } from "@saleor/apps-shared";
import { createGraphQLClient, createLogger } from "@saleor/apps-shared";
import { fetchProductData } from "../../../../../modules/google-feed/fetch-product-data";
import { GoogleFeedSettingsFetcher } from "../../../../../modules/google-feed/get-google-feed-settings";
import { generateGoogleXmlFeed } from "../../../../../modules/google-feed/generate-google-xml-feed";
@ -67,12 +66,10 @@ export const handler = async (req: NextApiRequest, res: NextApiResponse) => {
/**
* use unauthorized client to eliminate possibility of spilling the non-public data
*/
const client = initUrqlClient(
{
url: authData.saleorApiUrl,
},
false
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
if (!client) {
logger.error("Can't create the gql client");

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -20,14 +20,13 @@
"@saleor/react-hook-form-macaw": "workspace:*",
"@sentry/nextjs": "^7.46.0",
"@types/debug": "^4.1.7",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"algoliasearch": "4.14.2",
"clsx": "^1.2.1",
"debug": "^4.3.4",
"graphql": "16.6.0",
"graphql-tag": "^2.12.6",
"next": "13.3.0",
"next-urql": "4.0.3",
"pino": "^8.14.1",
"pino-pretty": "^10.0.0",
"react": "18.2.0",
@ -35,7 +34,7 @@
"react-helmet": "^6.1.0",
"react-hook-form": "^7.43.9",
"react-query": "^3.39.3",
"urql": "^3.0.3",
"urql": "^4.0.4",
"zod": "^3.20.2"
},
"devDependencies": {
@ -46,7 +45,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@types/react": "18.2.5",
"@types/react-dom": "18.2.5",

View file

@ -5,7 +5,7 @@ import {
ProductsDataForImportDocument,
ProductsDataForImportQuery,
} from "../../generated/graphql";
import { nextClient } from "../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
const PER_PAGE = 100;
@ -29,7 +29,7 @@ export const useQueryAllProducts = (paused: boolean) => {
}
const token = appBridgeState.token;
const client = nextClient(saleorApiUrl, () => Promise.resolve({ token }));
const client = createGraphQLClient({ saleorApiUrl, token });
if (!client) {
return;

View file

@ -1,7 +1,7 @@
import { AuthData } from "@saleor/app-sdk/APL";
import { createDebug } from "../debug";
import { createClient } from "../graphql";
import { createSettingsManager } from "../metadata";
import { createGraphQLClient } from "@saleor/apps-shared";
interface GetAlgoliaConfigurationArgs {
authData: AuthData;
@ -10,9 +10,10 @@ interface GetAlgoliaConfigurationArgs {
const debug = createDebug("getAlgoliaConfiguration");
export const getAlgoliaConfiguration = async ({ authData }: GetAlgoliaConfigurationArgs) => {
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const client = createGraphQLClient({
saleorApiUrl: authData.saleorApiUrl,
token: authData.token,
});
const settings = createSettingsManager(client);

View file

@ -1,63 +0,0 @@
import { initUrqlClient } from "next-urql";
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange, Client,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange
} from "urql";
interface IAuthState {
token: string;
}
const getExchanges = (getAuth: AuthConfig<IAuthState>["getAuth"]) => [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
];
export const nextClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) => {
return initUrqlClient(
{
url,
exchanges: getExchanges(getAuth),
},
false
);
};
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: getExchanges(getAuth),
});
export type SimpleGraphqlClient = Pick<Client, "query" | "mutation">;

View file

@ -1,9 +1,16 @@
import { EncryptedMetadataManager, MetadataEntry, SettingsManager } from "@saleor/app-sdk/settings-manager";
import {
EncryptedMetadataManager,
MetadataEntry,
SettingsManager,
} from "@saleor/app-sdk/settings-manager";
import { FetchAppDetailsDocument, FetchAppDetailsQuery, UpdateAppMetadataDocument } from "../../generated/graphql";
import {
FetchAppDetailsDocument,
FetchAppDetailsQuery,
UpdateAppMetadataDocument,
} from "../../generated/graphql";
import { settingsManagerSecretKey } from "../../saleor-app";
import { SimpleGraphqlClient } from "./graphql";
import { Client } from "urql";
/*
* Function is using urql graphql client to fetch all available metadata.
@ -11,7 +18,7 @@ import { SimpleGraphqlClient } from "./graphql";
* which can be used by the manager.
* Result of this query is cached by the manager.
*/
export async function fetchAllMetadata(client: SimpleGraphqlClient): Promise<MetadataEntry[]> {
export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]> {
const { error, data } = await client
.query<FetchAppDetailsQuery>(FetchAppDetailsDocument, {})
.toPromise();
@ -29,7 +36,7 @@ export async function fetchAllMetadata(client: SimpleGraphqlClient): Promise<Met
* Before data are send, additional query for required App ID is made.
* The manager will use updated entries returned by this mutation to update it's cache.
*/
export async function mutateMetadata(client: SimpleGraphqlClient, metadata: MetadataEntry[]) {
export async function mutateMetadata(client: Client, metadata: MetadataEntry[]) {
// to update the metadata, ID is required
const { error: idQueryError, data: idQueryData } = await client
.query(FetchAppDetailsDocument, {})
@ -69,7 +76,7 @@ export async function mutateMetadata(client: SimpleGraphqlClient, metadata: Meta
);
}
export const createSettingsManager = (client: SimpleGraphqlClient): SettingsManager => {
export const createSettingsManager = (client: Client): SettingsManager => {
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.

View file

@ -1,7 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { SettingsManager } from "@saleor/app-sdk/settings-manager";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { saleorApp } from "../../../saleor-app";
@ -10,6 +9,7 @@ import { createLogger } from "../../lib/logger";
import { AppConfigurationFields } from "../../domain/configuration";
import { AlgoliaSearchProvider } from "../../lib/algolia/algoliaSearchProvider";
import { WebhookActivityTogglerService } from "../../domain/WebhookActivityToggler.service";
import { createGraphQLClient } from "@saleor/apps-shared";
const logger = createLogger({
handler: "api/configuration",
@ -51,7 +51,10 @@ export const handler = async (
logger.debug({ saleorApiUrl }, "handler called");
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token: token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client);

View file

@ -1,6 +1,5 @@
import { createProtectedHandler, NextProtectedApiHandler } from "@saleor/app-sdk/handlers/next";
import { saleorApp } from "../../../saleor-app";
import { createClient, SimpleGraphqlClient } from "../../lib/graphql";
import { FetchOwnWebhooksDocument } from "../../../generated/graphql";
import { AlgoliaSearchProvider } from "../../lib/algolia/algoliaSearchProvider";
import { createSettingsManager } from "../../lib/metadata";
@ -10,8 +9,9 @@ import {
} from "../../domain/WebhookActivityToggler.service";
import { createLogger } from "../../lib/logger";
import { SettingsManager } from "@saleor/app-sdk/settings-manager";
import { Client } from "urql";
import { SearchProvider } from "../../lib/searchProvider";
import { createGraphQLClient } from "@saleor/apps-shared";
import { Client } from "urql";
const logger = createLogger({
service: "webhooksStatusHandler",
@ -21,13 +21,10 @@ const logger = createLogger({
* Simple dependency injection - factory injects all services, in tests everything can be configured without mocks
*/
type FactoryProps = {
settingsManagerFactory: (client: SimpleGraphqlClient) => SettingsManager;
webhookActivityTogglerFactory: (
appId: string,
client: SimpleGraphqlClient
) => IWebhookActivityTogglerService;
settingsManagerFactory: (client: Client) => SettingsManager;
webhookActivityTogglerFactory: (appId: string, client: Client) => IWebhookActivityTogglerService;
algoliaSearchProviderFactory: (appId: string, apiKey: string) => Pick<SearchProvider, "ping">;
graphqlClientFactory: (saleorApiUrl: string, token: string) => SimpleGraphqlClient;
graphqlClientFactory: (saleorApiUrl: string, token: string) => Client;
};
export const webhooksStatusHandlerFactory =
@ -113,9 +110,7 @@ export default createProtectedHandler(
return new AlgoliaSearchProvider({ appId, apiKey });
},
graphqlClientFactory(saleorApiUrl: string, token: string) {
return createClient(saleorApiUrl, async () => ({
token,
}));
return createGraphQLClient({ saleorApiUrl, token });
},
}),
saleorApp.apl,

View file

@ -4,8 +4,8 @@ import { saleorApp } from "../../../../../saleor-app";
import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider";
import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration";
import { WebhookActivityTogglerService } from "../../../../domain/WebhookActivityToggler.service";
import { createClient } from "../../../../lib/graphql";
import { createLogger } from "../../../../lib/logger";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -62,7 +62,7 @@ export const handler: NextWebhookApiHandler<ProductCreated> = async (req, res, c
const webhooksToggler = new WebhookActivityTogglerService(
authData.appId,
createClient(authData.saleorApiUrl, async () => ({ token: authData.token }))
createGraphQLClient({ saleorApiUrl: authData.saleorApiUrl, token: authData.token })
);
logger.trace("Will disable webhooks");

View file

@ -5,8 +5,8 @@ import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProv
import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration";
import { createDebug } from "../../../../lib/debug";
import { WebhookActivityTogglerService } from "../../../../domain/WebhookActivityToggler.service";
import { createClient } from "../../../../lib/graphql";
import { createLogger } from "../../../../lib/logger";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -63,7 +63,7 @@ export const handler: NextWebhookApiHandler<ProductDeleted> = async (req, res, c
const webhooksToggler = new WebhookActivityTogglerService(
authData.appId,
createClient(authData.saleorApiUrl, async () => ({ token: authData.token }))
createGraphQLClient({ saleorApiUrl: authData.saleorApiUrl, token: authData.token })
);
logger.trace("Will disable webhooks");

View file

@ -4,8 +4,8 @@ import { saleorApp } from "../../../../../saleor-app";
import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider";
import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration";
import { WebhookActivityTogglerService } from "../../../../domain/WebhookActivityToggler.service";
import { createClient } from "../../../../lib/graphql";
import { createLogger } from "../../../../lib/logger";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -62,7 +62,7 @@ export const handler: NextWebhookApiHandler<ProductUpdated> = async (req, res, c
const webhooksToggler = new WebhookActivityTogglerService(
authData.appId,
createClient(authData.saleorApiUrl, async () => ({ token: authData.token }))
createGraphQLClient({ saleorApiUrl: authData.saleorApiUrl, token: authData.token })
);
logger.trace("Will disable webhooks");

View file

@ -9,7 +9,7 @@ import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfi
import { createDebug } from "../../../../lib/debug";
import { createLogger } from "../../../../lib/logger";
import { WebhookActivityTogglerService } from "../../../../domain/WebhookActivityToggler.service";
import { createClient } from "../../../../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -65,7 +65,7 @@ export const handler: NextWebhookApiHandler<ProductVariantCreated> = async (req,
const webhooksToggler = new WebhookActivityTogglerService(
authData.appId,
createClient(authData.saleorApiUrl, async () => ({ token: authData.token }))
createGraphQLClient({ saleorApiUrl: authData.saleorApiUrl, token: authData.token })
);
logger.trace("Will disable webhooks");

View file

@ -9,7 +9,7 @@ import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfi
import { createDebug } from "../../../../lib/debug";
import { createLogger } from "../../../../lib/logger";
import { WebhookActivityTogglerService } from "../../../../domain/WebhookActivityToggler.service";
import { createClient } from "../../../../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -66,7 +66,7 @@ export const handler: NextWebhookApiHandler<ProductVariantDeleted> = async (req,
const webhooksToggler = new WebhookActivityTogglerService(
authData.appId,
createClient(authData.saleorApiUrl, async () => ({ token: authData.token }))
createGraphQLClient({ saleorApiUrl: authData.saleorApiUrl, token: authData.token })
);
logger.trace("Will disable webhooks");

View file

@ -9,7 +9,7 @@ import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfi
import { createDebug } from "../../../../lib/debug";
import { createLogger } from "../../../../lib/logger";
import { WebhookActivityTogglerService } from "../../../../domain/WebhookActivityToggler.service";
import { createClient } from "../../../../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -66,7 +66,7 @@ export const handler: NextWebhookApiHandler<ProductVariantUpdated> = async (req,
const webhooksToggler = new WebhookActivityTogglerService(
authData.appId,
createClient(authData.saleorApiUrl, async () => ({ token: authData.token }))
createGraphQLClient({ saleorApiUrl: authData.saleorApiUrl, token: authData.token })
);
logger.trace("Will disable webhooks");

View file

@ -2,7 +2,7 @@ import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { PropsWithChildren } from "react";
import { Provider } from "urql";
import { createClient } from "../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
export function GraphQLProvider(props: PropsWithChildren<{}>) {
const { appBridgeState } = useAppBridge();
@ -12,9 +12,10 @@ export function GraphQLProvider(props: PropsWithChildren<{}>) {
return <div {...props}></div>;
}
const client = createClient(saleorApiUrl, async () =>
Promise.resolve({ token: appBridgeState?.token! })
);
const client = createGraphQLClient({
saleorApiUrl,
token: appBridgeState.token,
});
return <Provider value={client} {...props} />;
}

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -18,7 +18,7 @@
"@saleor/apps-shared": "workspace:*",
"@saleor/macaw-ui": "^0.7.2",
"@sentry/nextjs": "^7.30.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-auth": "^2.1.4",
"clsx": "^1.2.1",
"eslint": "8.42.0",
"graphql": "16.6.0",
@ -30,7 +30,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-helmet": "^6.1.0",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"vite": "4.3.9",
"vitest": "0.31.3"
@ -43,7 +43,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@types/react": "18.2.5",
"@types/react-dom": "18.2.5",

View file

@ -1,48 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import {
cacheExchange,
createClient as urqlCreateClient,
dedupExchange,
fetchExchange,
} from "urql";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
fetchExchange,
],
});

View file

@ -1,9 +1,9 @@
import { createProtectedHandler, ProtectedHandlerContext } from "@saleor/app-sdk/handlers/next";
import { NextApiRequest, NextApiResponse } from "next";
import { createClient } from "../../lib/graphql";
import { createSettingsManager } from "../../lib/metadata";
import { saleorApp } from "../../lib/saleor-app";
import { createGraphQLClient } from "@saleor/apps-shared";
const WEBHOOK_URL = "WEBHOOK_URL";
@ -20,7 +20,10 @@ export const handler = async (
authData: { token, saleorApiUrl, appId },
} = ctx;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);

View file

@ -2,10 +2,10 @@ import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handl
import { gql } from "urql";
import { OrderCreatedWebhookPayloadFragment } from "../../../../generated/graphql";
import { createClient } from "../../../lib/graphql";
import { createSettingsManager } from "../../../lib/metadata";
import { saleorApp } from "../../../lib/saleor-app";
import { sendSlackMessage } from "../../../lib/slack";
import { createGraphQLClient } from "@saleor/apps-shared";
const OrderCreatedWebhookPayload = gql`
fragment OrderCreatedWebhookPayload on OrderCreated {
@ -82,7 +82,10 @@ const handler: NextWebhookApiHandler<OrderCreatedWebhookPayloadFragment> = async
const { saleorApiUrl, token, appId } = authData;
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const settings = createSettingsManager(client, appId);

View file

@ -10,7 +10,6 @@ extensions:
plugins:
- typescript
- typescript-operations
- urql-introspection
- typescript-urql:
documentVariablePrefix: "Untyped"
fragmentVariablePrefix: "Untyped"

View file

@ -24,8 +24,7 @@
"@trpc/next": "^10.9.0",
"@trpc/react-query": "^10.9.0",
"@trpc/server": "^10.9.0",
"@urql/exchange-auth": "^1.0.0",
"@urql/exchange-multipart-fetch": "^1.0.1",
"@urql/exchange-auth": "^2.1.4",
"avatax": "^23.3.2",
"clsx": "^1.2.1",
"dotenv": "^16.0.3",
@ -40,7 +39,7 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.43.9",
"taxjar": "^4.0.1",
"urql": "^3.0.3",
"urql": "^4.0.4",
"usehooks-ts": "^2.9.1",
"vite": "4.3.9",
"vitest": "0.31.3",
@ -54,7 +53,6 @@
"@graphql-codegen/typescript": "3.0.2",
"@graphql-codegen/typescript-operations": "3.0.2",
"@graphql-codegen/typescript-urql": "3.7.3",
"@graphql-codegen/urql-introspection": "2.2.1",
"@graphql-typed-document-node/core": "3.2.0",
"@testing-library/react": "^13.4.0",
"@testing-library/react-hooks": "^8.0.1",

View file

@ -1,13 +1,14 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import { SaleorCloudAPL } from "@saleor/app-sdk/APL";
import { createClient } from "../../src/lib/graphql";
import { createSettingsManager } from "../../src/modules/app/metadata-manager";
import { createGraphQLClient } from "@saleor/apps-shared";
export const getMetadataManagerForEnv = (apiUrl: string, appToken: string, appId: string) => {
const client = createClient(apiUrl, async () => ({
const client = createGraphQLClient({
saleorApiUrl: apiUrl,
token: appToken,
}));
});
return createSettingsManager(client, appId);
};

View file

@ -1,5 +1,4 @@
import { saleorApp } from "../../saleor-app";
import { createClient } from "../../src/lib/graphql";
import { Logger, createLogger } from "../../src/lib/logger";
import { createSettingsManager } from "../../src/modules/app/metadata-manager";
import { TaxProvidersV1 } from "./tax-providers-config-schema-v1";
@ -8,6 +7,7 @@ import { ChannelsV1 } from "./channels-config-schema-v1";
import * as dotenv from "dotenv";
import { TaxChannelsPrivateMetadataManagerV1 } from "./tax-channels-metadata-manager-v1";
import { createGraphQLClient } from "@saleor/apps-shared";
dotenv.config();
@ -94,9 +94,11 @@ class DummyConfigGenerator {
console.log({ dummyTaxProvidersConfig, dummyTaxChannelsConfig }, "Dummy configs generated");
const client = createClient(target.saleorApiUrl, async () =>
Promise.resolve({ token: target.token })
);
const client = createGraphQLClient({
saleorApiUrl: target.saleorApiUrl,
token: target.token,
});
const metadataManager = createSettingsManager(client, target.appId);
const taxProvidersManager = new TaxProvidersPrivateMetadataManagerV1(
metadataManager,

View file

@ -1,45 +0,0 @@
import { AuthConfig, authExchange } from "@urql/exchange-auth";
import { cacheExchange, createClient as urqlCreateClient, dedupExchange } from "urql";
import { multipartFetchExchange } from "@urql/exchange-multipart-fetch";
interface IAuthState {
token: string;
}
export const createClient = (url: string, getAuth: AuthConfig<IAuthState>["getAuth"]) =>
urqlCreateClient({
url,
exchanges: [
dedupExchange,
cacheExchange,
authExchange<IAuthState>({
addAuthToOperation: ({ authState, operation }) => {
if (!authState || !authState?.token) {
return operation;
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {};
return {
...operation,
context: {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
"Authorization-Bearer": authState.token,
},
},
},
};
},
getAuth,
}),
multipartFetchExchange,
],
});

View file

@ -1,10 +1,10 @@
import { createClient } from "../../lib/graphql";
import { verifyJWT } from "@saleor/app-sdk/verify-jwt";
import { middleware, procedure } from "./trpc-server";
import { saleorApp } from "../../../saleor-app";
import { TRPCError } from "@trpc/server";
import { ProtectedHandlerError } from "@saleor/app-sdk/handlers/next";
import { logger } from "../../lib/logger";
import { createGraphQLClient } from "@saleor/apps-shared";
const attachAppToken = middleware(async ({ ctx, next }) => {
logger.debug("attachAppToken middleware");
@ -103,9 +103,10 @@ export const protectedClientProcedure = procedure
.use(attachAppToken)
.use(validateClientToken)
.use(async ({ ctx, next }) => {
const client = createClient(ctx.saleorApiUrl, async () =>
Promise.resolve({ token: ctx.appToken })
);
const client = createGraphQLClient({
saleorApiUrl: ctx.saleorApiUrl,
token: ctx.appToken,
});
return next({
ctx: {

View file

@ -1,8 +1,11 @@
import { createAppRegisterHandler } from "@saleor/app-sdk/handlers/next";
import { REQUIRED_SALEOR_VERSION, saleorApp } from "../../../saleor-app";
import { createLogger, SaleorVersionCompatibilityValidator } from "@saleor/apps-shared";
import { createClient } from "../../lib/graphql";
import {
createGraphQLClient,
createLogger,
SaleorVersionCompatibilityValidator,
} from "@saleor/apps-shared";
import { gql } from "urql";
import { SaleorVersionQuery } from "../../../generated/graphql";
@ -46,10 +49,9 @@ export default createAppRegisterHandler({
});
try {
const client = createClient(saleorApiUrl, async () => {
return {
token,
};
const client = createGraphQLClient({
saleorApiUrl,
token,
});
const saleorVersion = await client

View file

@ -10,10 +10,10 @@ import {
import { saleorApp } from "../../../../saleor-app";
import { createLogger } from "../../../lib/logger";
import { getActiveConnection } from "../../../modules/taxes/active-connection";
import { createClient } from "../../../lib/graphql";
import { Client } from "urql";
import { WebhookResponse } from "../../../modules/app/webhook-response";
import { PROVIDER_ORDER_ID_KEY } from "../../../modules/avatax/order-fulfilled/avatax-order-fulfilled-payload-transformer";
import { createGraphQLClient } from "@saleor/apps-shared";
export const config = {
api: {
@ -90,7 +90,10 @@ export default orderCreatedAsyncWebhook.createHandler(async (req, res, ctx) => {
const createdOrder = await taxProvider.createOrder(payload.order);
logger.info({ createdOrder }, "Order created");
const client = createClient(saleorApiUrl, async () => Promise.resolve({ token }));
const client = createGraphQLClient({
saleorApiUrl,
token,
});
await updateOrderMetadataWithExternalId(client, payload.order.id, createdOrder.id);
logger.info("Updated order metadata with externalId");

View file

@ -2,7 +2,7 @@ import { useAppBridge } from "@saleor/app-sdk/app-bridge";
import { PropsWithChildren } from "react";
import { Provider } from "urql";
import { createClient } from "../lib/graphql";
import { createGraphQLClient } from "@saleor/apps-shared";
export function GraphQLProvider(props: PropsWithChildren<{}>) {
const { appBridgeState } = useAppBridge();
@ -11,9 +11,10 @@ export function GraphQLProvider(props: PropsWithChildren<{}>) {
return <div {...props}></div>;
}
const client = createClient(appBridgeState?.saleorApiUrl, async () =>
Promise.resolve({ token: appBridgeState?.token! })
);
const client = createGraphQLClient({
saleorApiUrl: appBridgeState.saleorApiUrl,
token: appBridgeState.token,
});
return <Provider value={client} {...props} />;
}

View file

@ -4,3 +4,4 @@ export * from "./src/no-ssr-wrapper";
export * from "./src/use-dashboard-notification";
export * from "./src/logger";
export * from "./src/saleor-version-compatibility-validator";
export * from "./src/create-graphql-client";

View file

@ -5,11 +5,13 @@
"lint:fix": "eslint --fix ."
},
"dependencies": {
"@urql/exchange-auth": "^2.1.4",
"eslint": "8.42.0",
"pino": "^8.14.1",
"pino-pretty": "^10.0.0",
"semver": "^7.5.1",
"typescript": "5.1.3"
"typescript": "5.1.3",
"urql": "^4.0.4"
},
"devDependencies": {
"@material-ui/core": "^4.12.4",

View file

@ -0,0 +1,45 @@
import { authExchange } from "@urql/exchange-auth";
import { cacheExchange, createClient as urqlCreateClient, fetchExchange } from "urql";
interface CreateGraphQLClientArgs {
saleorApiUrl: string;
token?: string;
}
/*
* Creates instance of urql client with optional auth exchange (if token is provided).
* Accessing public parts of the Saleor API is possible without providing access token.
* When trying to access fields or operations protected by permissions.
* Token can be obtained:
* - by accessing token from appBridge https://github.com/saleor/saleor-app-sdk/blob/main/docs/app-bridge.md
* - by using token created during the app registration, saved in the APL https://github.com/saleor/saleor-app-sdk/blob/main/docs/apl.md
* - by token create mutation https://docs.saleor.io/docs/3.x/api-usage/authentication
*
* In the context of developing Apps, the two first options are recommended.
*/
export const createGraphQLClient = ({ saleorApiUrl, token }: CreateGraphQLClientArgs) => {
return urqlCreateClient({
url: saleorApiUrl,
exchanges: [
cacheExchange,
authExchange(async (utils) => {
return {
addAuthToOperation(operation) {
const headers: Record<string, string> = token
? {
"Authorization-Bearer": token,
}
: {};
return utils.appendHeaders(operation, headers);
},
didAuthError(error) {
return error.graphQLErrors.some((e) => e.extensions?.code === "FORBIDDEN");
},
async refreshAuth() {},
};
}),
fetchExchange,
],
});
};

View file

@ -65,8 +65,8 @@ importers:
specifier: ^7.43.0
version: 7.43.0(next@13.3.0)(react@18.2.0)
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
clsx:
specifier: ^1.2.1
version: 1.2.1
@ -98,8 +98,8 @@ importers:
specifier: ^8.0.5
version: 8.0.5(@types/react@18.2.5)(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -131,9 +131,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -198,8 +195,8 @@ importers:
specifier: ^10.18.0
version: 10.18.0
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
'@vitejs/plugin-react':
specifier: 4.0.0
version: 4.0.0(vite@4.3.9)
@ -218,9 +215,6 @@ importers:
next:
specifier: 13.3.0
version: 13.3.0(@babel/core@7.22.5)(react-dom@18.2.0)(react@18.2.0)
next-urql:
specifier: 4.0.3
version: 4.0.3(react@18.2.0)(urql@3.0.3)
pino:
specifier: ^8.14.1
version: 8.14.1
@ -240,8 +234,8 @@ importers:
specifier: ^18.2.0
version: 18.2.0
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -273,9 +267,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -331,8 +322,8 @@ importers:
specifier: ^7.39.0
version: 7.39.0(next@13.3.0)(react@18.2.0)
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
'@vitejs/plugin-react':
specifier: 4.0.0
version: 4.0.0(vite@4.3.9)
@ -373,8 +364,8 @@ importers:
specifier: 18.2.0
version: 18.2.0(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -409,9 +400,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -491,8 +479,8 @@ importers:
specifier: ^10.13.0
version: 10.14.0
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
'@vitejs/plugin-react':
specifier: 4.0.0
version: 4.0.0(vite@4.3.9)
@ -523,9 +511,6 @@ importers:
next:
specifier: 13.3.0
version: 13.3.0(@babel/core@7.22.5)(react-dom@18.2.0)(react@18.2.0)
next-urql:
specifier: 4.0.3
version: 4.0.3(react@18.2.0)(urql@3.0.3)
nodemailer:
specifier: ^6.9.1
version: 6.9.1
@ -551,8 +536,8 @@ importers:
specifier: ^3.39.3
version: 3.39.3(react-dom@18.2.0)(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -587,9 +572,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -657,11 +639,8 @@ importers:
specifier: ^10.10.0
version: 10.10.0
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
'@urql/exchange-multipart-fetch':
specifier: ^1.0.1
version: 1.0.1(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
'@web-std/file':
specifier: ^3.0.2
version: 3.0.2
@ -702,8 +681,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -732,9 +711,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -799,8 +775,8 @@ importers:
specifier: ^7.36.0
version: 7.36.0(next@13.3.0)(react@18.2.0)
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
clsx:
specifier: ^1.2.1
version: 1.2.1
@ -832,8 +808,8 @@ importers:
specifier: ^6.1.0
version: 6.1.0(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
vite:
specifier: 4.3.9
version: 4.3.9(@types/node@18.15.3)
@ -862,9 +838,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -917,8 +890,8 @@ importers:
specifier: ^0.7.2
version: 0.7.2(@material-ui/core@4.12.4)(@material-ui/icons@4.11.3)(@material-ui/lab@4.0.0-alpha.61)(@types/react@18.2.5)(react-dom@18.2.0)(react-helmet@6.1.0)(react@18.2.0)
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
'@vitejs/plugin-react':
specifier: 4.0.0
version: 4.0.0(vite@4.3.9)
@ -953,8 +926,8 @@ importers:
specifier: ^7.42.1
version: 7.43.1(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
vite:
specifier: 4.3.9
version: 4.3.9(@types/node@18.15.3)
@ -983,9 +956,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -1053,8 +1023,8 @@ importers:
specifier: ^10.9.0
version: 10.10.0
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
'@vitejs/plugin-react':
specifier: 4.0.0
version: 4.0.0(vite@4.3.9)
@ -1076,9 +1046,6 @@ importers:
next:
specifier: 13.3.0
version: 13.3.0(@babel/core@7.22.5)(react-dom@18.2.0)(react@18.2.0)
next-urql:
specifier: 4.0.3
version: 4.0.3(react@18.2.0)(urql@3.0.3)
pino:
specifier: ^8.14.1
version: 8.14.1
@ -1101,8 +1068,8 @@ importers:
specifier: ^3.39.3
version: 3.39.3(react-dom@18.2.0)(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -1137,9 +1104,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -1192,8 +1156,8 @@ importers:
specifier: ^4.1.7
version: 4.1.7
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
algoliasearch:
specifier: 4.14.2
version: 4.14.2
@ -1212,9 +1176,6 @@ importers:
next:
specifier: 13.3.0
version: 13.3.0(@babel/core@7.22.5)(react-dom@18.2.0)(react@18.2.0)
next-urql:
specifier: 4.0.3
version: 4.0.3(react@18.2.0)(urql@3.0.3)
pino:
specifier: ^8.14.1
version: 8.14.1
@ -1237,8 +1198,8 @@ importers:
specifier: ^3.39.3
version: 3.39.3(react-dom@18.2.0)(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
zod:
specifier: ^3.20.2
version: 3.20.2
@ -1264,9 +1225,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -1322,8 +1280,8 @@ importers:
specifier: ^7.30.0
version: 7.36.0(next@13.3.0)(react@18.2.0)
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
clsx:
specifier: ^1.2.1
version: 1.2.1
@ -1358,8 +1316,8 @@ importers:
specifier: ^6.1.0
version: 6.1.0(react@18.2.0)
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -1391,9 +1349,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -1467,11 +1422,8 @@ importers:
specifier: ^10.9.0
version: 10.10.0
'@urql/exchange-auth':
specifier: ^1.0.0
version: 1.0.0(graphql@16.6.0)
'@urql/exchange-multipart-fetch':
specifier: ^1.0.1
version: 1.0.1(graphql@16.6.0)
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
avatax:
specifier: ^23.3.2
version: 23.3.2
@ -1515,8 +1467,8 @@ importers:
specifier: ^4.0.1
version: 4.0.1
urql:
specifier: ^3.0.3
version: 3.0.3(graphql@16.6.0)(react@18.2.0)
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
usehooks-ts:
specifier: ^2.9.1
version: 2.9.1(react-dom@18.2.0)(react@18.2.0)
@ -1551,9 +1503,6 @@ importers:
'@graphql-codegen/typescript-urql':
specifier: 3.7.3
version: 3.7.3(graphql-tag@2.12.6)(graphql@16.6.0)
'@graphql-codegen/urql-introspection':
specifier: 2.2.1
version: 2.2.1(graphql@16.6.0)
'@graphql-typed-document-node/core':
specifier: 3.2.0
version: 3.2.0(graphql@16.6.0)
@ -1678,6 +1627,9 @@ importers:
packages/shared:
dependencies:
'@urql/exchange-auth':
specifier: ^2.1.4
version: 2.1.4(graphql@16.6.0)
eslint:
specifier: 8.42.0
version: 8.42.0
@ -1693,6 +1645,9 @@ importers:
typescript:
specifier: 5.1.3
version: 5.1.3
urql:
specifier: ^4.0.4
version: 4.0.4(graphql@16.6.0)(react@18.2.0)
devDependencies:
'@material-ui/core':
specifier: ^4.12.4
@ -1791,6 +1746,17 @@ packages:
uuid: 8.3.2
dev: false
/@0no-co/graphql.web@1.0.4(graphql@16.6.0):
resolution: {integrity: sha512-W3ezhHGfO0MS1PtGloaTpg0PbaT8aZSmmaerL7idtU5F7oCI+uu25k+MsMS31BVFlp4aMkHSrNRxiD72IlK8TA==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0
peerDependenciesMeta:
graphql:
optional: true
dependencies:
graphql: 16.6.0
dev: false
/@algolia/cache-browser-local-storage@4.14.2:
resolution: {integrity: sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA==}
dependencies:
@ -5792,17 +5758,6 @@ packages:
- supports-color
dev: true
/@graphql-codegen/urql-introspection@2.2.1(graphql@16.6.0):
resolution: {integrity: sha512-/KjHSf4dQNoYZZ+G10b3lbw304ik9xHzRf/syNvoYehmwdYE5J7RnO1v1Cz78LDm2NEdsFas6vJHi0sJd/pOHg==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.6.0)
'@urql/introspection': 0.3.3(graphql@16.6.0)
graphql: 16.6.0
tslib: 2.4.1
dev: true
/@graphql-codegen/visitor-plugin-common@2.13.1(graphql@16.6.0):
resolution: {integrity: sha512-mD9ufZhDGhyrSaWQGrU1Q1c5f01TeWtSWy/cDwXYjJcHIj1Y/DG2x0tOflEfCvh5WcnmHNIw4lzDsg1W7iFJEg==}
peerDependencies:
@ -10016,44 +9971,24 @@ packages:
eslint-visitor-keys: 3.4.1
dev: true
/@urql/core@3.1.1(graphql@16.6.0):
resolution: {integrity: sha512-Mnxtq4I4QeFJsgs7Iytw+HyhiGxISR6qtyk66c9tipozLZ6QVxrCiUPF2HY4BxNIabaxcp+rivadvm8NAnXj4Q==}
peerDependencies:
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
/@urql/core@4.0.10(graphql@16.6.0):
resolution: {integrity: sha512-Vs3nOSAnYftqOCg034Ostp/uSqWlQg5ryLIzcOrm8+O43s4M+Ew4GQAuemIH7ZDB8dek6h61zzWI3ujd8FH3NA==}
dependencies:
graphql: 16.6.0
wonka: 6.1.2
'@0no-co/graphql.web': 1.0.4(graphql@16.6.0)
wonka: 6.3.2
transitivePeerDependencies:
- graphql
dev: false
/@urql/exchange-auth@1.0.0(graphql@16.6.0):
resolution: {integrity: sha512-79hqPQab+ifeINOxvQykvqub4ixWHBEIagN4U67ijcHGMfp3c4yEWRk4IJMPwF+OMT7LrRFuv+jRIZTQn/9VwQ==}
peerDependencies:
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
/@urql/exchange-auth@2.1.4(graphql@16.6.0):
resolution: {integrity: sha512-ijAKSgswusrProxrusX8TcYntCgMptQiirdNHwgy0EcWucxQ+1zgxiRNFKpkaRMpGk5WCFeCpsXTEYtlvuFmDg==}
dependencies:
'@urql/core': 3.1.1(graphql@16.6.0)
graphql: 16.6.0
wonka: 6.1.2
'@urql/core': 4.0.10(graphql@16.6.0)
wonka: 6.3.2
transitivePeerDependencies:
- graphql
dev: false
/@urql/exchange-multipart-fetch@1.0.1(graphql@16.6.0):
resolution: {integrity: sha512-fjxRrKR/D9Rs52L8wJMvqsGQBC/mjFcg/VdkSkU5IXmqCb5KmicXl2208hoCnaBl/QLA6NDpCNnG3zjDniMOTg==}
peerDependencies:
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@urql/core': 3.1.1(graphql@16.6.0)
extract-files: 11.0.0
graphql: 16.6.0
wonka: 6.1.2
dev: false
/@urql/introspection@0.3.3(graphql@16.6.0):
resolution: {integrity: sha512-tekSLLqWnusfV6V7xaEnLJQSdXOD/lWy7f8JYQwrX+88Md+voGSCSx5WJXI7KLBN3Tat2OV08tAr8UROykls4Q==}
peerDependencies:
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
graphql: 16.6.0
dev: true
/@vanilla-extract/babel-plugin-debug-ids@1.0.3:
resolution: {integrity: sha512-vm4jYu1xhSa6ofQ9AhIpR3DkAp4c+eoR1Rpm8/TQI4DmWbmGbOjYRcqV0aWsfaIlNhN4kFuxFMKBNN9oG6iRzA==}
dependencies:
@ -13385,6 +13320,7 @@ packages:
/extract-files@11.0.0:
resolution: {integrity: sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==}
engines: {node: ^12.20 || >= 14.13}
dev: true
/extract-files@9.0.0:
resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==}
@ -16854,17 +16790,6 @@ packages:
/neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
/next-urql@4.0.3(react@18.2.0)(urql@3.0.3):
resolution: {integrity: sha512-pesvwu1ZuGzMla8tPMo0V0yiV3ObDF4dbZyZLB2rZoORy+ebdWtClU/pfz1XDrPEgzyfGC3tqvbR5gH7Kt59XA==}
peerDependencies:
react: '>=16.8.0'
urql: ^3.0.0
dependencies:
react: 18.2.0
react-ssr-prepass: 1.5.0(react@18.2.0)
urql: 3.0.3(graphql@16.6.0)(react@18.2.0)
dev: false
/next@13.3.0(@babel/core@7.22.5)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==}
engines: {node: '>=14.6.0'}
@ -20507,16 +20432,16 @@ packages:
braces: 3.0.2
dev: true
/urql@3.0.3(graphql@16.6.0)(react@18.2.0):
resolution: {integrity: sha512-aVUAMRLdc5AOk239DxgXt6ZxTl/fEmjr7oyU5OGo8uvpqu42FkeJErzd2qBzhAQ3DyusoZIbqbBLPlnKo/yy2A==}
/urql@4.0.4(graphql@16.6.0)(react@18.2.0):
resolution: {integrity: sha512-C5P4BMnAsk+rbytCWglit5ijXbIKXsa9wofSGPbuMyJKsDdL+9GfipS362Nff/Caag+eYOK5W+sox8fwEILT6Q==}
peerDependencies:
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
react: '>= 16.8.0'
dependencies:
'@urql/core': 3.1.1(graphql@16.6.0)
graphql: 16.6.0
'@urql/core': 4.0.10(graphql@16.6.0)
react: 18.2.0
wonka: 6.1.2
wonka: 6.3.2
transitivePeerDependencies:
- graphql
dev: false
/use-callback-ref@1.3.0(@types/react@18.2.5)(react@18.2.0):
@ -21144,8 +21069,8 @@ packages:
engines: {node: '>=0.8'}
dev: false
/wonka@6.1.2:
resolution: {integrity: sha512-zNrXPMccg/7OEp9tSfFkMgTvhhowqasiSHdJ3eCZolXxVTV/aT6HUTofoZk9gwRbGoFey/Nss3JaZKUMKMbofg==}
/wonka@6.3.2:
resolution: {integrity: sha512-2xXbQ1LnwNS7egVm1HPhW2FyKrekolzhpM3mCwXdQr55gO+tAiY76rhb32OL9kKsW8taj++iP7C6hxlVzbnvrw==}
dev: false
/word-wrap@1.2.3: