diff --git a/.changeset/four-seahorses-itch.md b/.changeset/four-seahorses-itch.md new file mode 100644 index 000000000..10380edcb --- /dev/null +++ b/.changeset/four-seahorses-itch.md @@ -0,0 +1,5 @@ +--- +"segment": patch +--- + +Fixed broken deployment of Segment app diff --git a/apps/segment/.eslintrc.cjs b/apps/segment/.eslintrc.cjs index 08a6d5ead..22fc6a2c6 100644 --- a/apps/segment/.eslintrc.cjs +++ b/apps/segment/.eslintrc.cjs @@ -4,6 +4,7 @@ module.exports = { plugins: ["node"], rules: { "turbo/no-undeclared-env-vars": ["error"], + "node/no-process-env": ["error"], }, parserOptions: { project: "tsconfig.json", diff --git a/apps/segment/package.json b/apps/segment/package.json index 2912798d1..ef905dd4e 100644 --- a/apps/segment/package.json +++ b/apps/segment/package.json @@ -19,11 +19,18 @@ "@hookform/resolvers": "^3.3.1", "@saleor/app-sdk": "link:../../node_modules/@saleor/app-sdk", "@saleor/apps-logger": "workspace:*", + "@saleor/apps-otel": "workspace:*", "@saleor/apps-shared": "workspace:*", "@saleor/apps-ui": "workspace:*", "@saleor/macaw-ui": "1.1.10", "@saleor/react-hook-form-macaw": "workspace:*", + "@saleor/sentry-utils": "workspace:*", + "@saleor/webhook-utils": "workspace:*", + "@sentry/cli": "../../node_modules/@sentry/cli", + "@sentry/nextjs": "../../node_modules/@sentry/nextjs", + "@sentry/node": "../../node_modules/@sentry/node", "@segment/analytics-node": "^1.1.0", + "@t3-oss/env-nextjs": "0.11.1", "@trpc/client": "10.43.1", "@trpc/next": "10.43.1", "@trpc/server": "10.43.1", diff --git a/apps/segment/scripts/deploy.ts b/apps/segment/scripts/deploy.ts new file mode 100644 index 000000000..dfec93f9e --- /dev/null +++ b/apps/segment/scripts/deploy.ts @@ -0,0 +1,10 @@ +import { execSync } from "node:child_process"; + +import { exportSentryReleaseEnvironmentVariable } from "@saleor/sentry-utils"; + +import packageJson from "../package.json"; + +exportSentryReleaseEnvironmentVariable(packageJson.version); + +execSync("pnpm run build", { stdio: "inherit" }); +execSync("pnpm run migrate", { stdio: "inherit" }); diff --git a/apps/segment/scripts/migration-logger.ts b/apps/segment/scripts/migration-logger.ts new file mode 100644 index 000000000..e06b232c8 --- /dev/null +++ b/apps/segment/scripts/migration-logger.ts @@ -0,0 +1,14 @@ +// eslint-disable-next-line no-restricted-imports +import { attachLoggerVercelBuildtimeTransport, rootLogger } from "@saleor/apps-logger"; + +rootLogger.settings.maskValuesOfKeys = ["username", "password", "token"]; + +attachLoggerVercelBuildtimeTransport(rootLogger); + +export const createMigrationScriptLogger = (name: string, params?: Record) => + rootLogger.getSubLogger( + { + name: name, + }, + params, + ); diff --git a/apps/segment/scripts/run-webhooks-migration.ts b/apps/segment/scripts/run-webhooks-migration.ts new file mode 100644 index 000000000..3e2cf9dca --- /dev/null +++ b/apps/segment/scripts/run-webhooks-migration.ts @@ -0,0 +1,87 @@ +import { WebhookMigrationRunner } from "@saleor/webhook-utils"; +import * as Sentry from "@sentry/node"; + +import { env } from "@/env"; +import { createInstrumentedGraphqlClient } from "@/lib/create-instrumented-graphql-client"; +import { apl } from "@/saleor-app"; + +import { appWebhooks } from "../src/modules/webhooks/webhooks"; +import { createMigrationScriptLogger } from "./migration-logger"; + +const args = process.argv.slice(2); +const dryRun = args.includes("--dry-run"); + +const logger = createMigrationScriptLogger("WebhooksMigrationScript"); + +Sentry.init({ + dsn: env.NEXT_PUBLIC_SENTRY_DSN, + enableTracing: false, + environment: env.ENV, + includeLocalVariables: true, + ignoreErrors: [], + integrations: [], +}); + +const runMigrations = async () => { + logger.info(`Starting webhooks migration`); + logger.info(`Fetching environments from the ${env.APL} APL`); + + const saleorCloudEnv = await apl.getAll().catch(() => { + logger.error(`Could not fetch instances from ${env.APL} APL`); + + process.exit(1); + }); + + await Promise.allSettled( + saleorCloudEnv.map(async (saleorEnv) => { + const { saleorApiUrl, token } = saleorEnv; + + logger.info(`Migrating webhooks for ${saleorApiUrl}`); + + const client = createInstrumentedGraphqlClient({ + saleorApiUrl: saleorApiUrl, + token: token, + }); + + const runner = new WebhookMigrationRunner({ + dryRun, + logger, + client, + saleorApiUrl, + getManifests: async ({ appDetails }) => { + const webhooks = appDetails.webhooks; + + if (!webhooks?.length) { + logger.warn("The environment does not have any webhooks, skipping"); + return []; + } + + const enabled = webhooks.some((w) => w.isActive); + + const targetUrl = appDetails.appUrl; + + if (!targetUrl?.length) { + logger.error("App has no defined appUrl, skipping"); + return []; + } + + const baseUrl = new URL(targetUrl).origin; + + // All webhooks in this application are turned on or off. If any of them is enabled, we enable all of them. + return appWebhooks.map((w) => ({ ...w.getWebhookManifest(baseUrl), enabled })); + }, + }); + + await runner.migrate().catch((error) => { + Sentry.captureException(error); + }); + }), + ); +}; + +runMigrations(); + +process.on("beforeExit", () => { + logger.info(`Webhook migration complete for all environments from ${env.APL} APL`); + process.exit(0); +}); diff --git a/apps/segment/src/env.ts b/apps/segment/src/env.ts new file mode 100644 index 000000000..d1080fb6a --- /dev/null +++ b/apps/segment/src/env.ts @@ -0,0 +1,56 @@ +/* eslint-disable node/no-process-env */ +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +// https://env.t3.gg/docs/recipes#booleans +const booleanSchema = z + .string() + .refine((s) => s === "true" || s === "false") + .transform((s) => s === "true"); + +export const env = createEnv({ + client: { + NEXT_PUBLIC_SENTRY_DSN: z.string().optional(), + }, + server: { + ALLOWED_DOMAIN_PATTERN: z.string().optional(), + APL: z.enum(["saleor-cloud", "file"]).optional().default("file"), + APP_API_BASE_URL: z.string().optional(), + APP_IFRAME_BASE_URL: z.string().optional(), + APP_LOG_LEVEL: z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).default("info"), + FILE_APL_PATH: z.string().optional(), + MANIFEST_APP_ID: z.string().optional().default("saleor.app.segment-v2"), + REST_APL_ENDPOINT: z.string().optional(), + REST_APL_TOKEN: z.string().optional(), + OTEL_ENABLED: booleanSchema.optional().default("false"), + OTEL_SERVICE_NAME: z.string().optional(), + PORT: z.coerce.number().optional().default(3000), + SECRET_KEY: z.string(), + VERCEL_URL: z.string().optional(), + }, + shared: { + NODE_ENV: z.enum(["development", "production", "test"]).optional().default("development"), + ENV: z.enum(["local", "development", "staging", "production"]).optional().default("local"), + }, + // we use the manual destruction here to validate if env variable is set inside turbo.json + runtimeEnv: { + ALLOWED_DOMAIN_PATTERN: process.env.ALLOWED_DOMAIN_PATTERN, + APL: process.env.APL, + APP_API_BASE_URL: process.env.APP_API_BASE_URL, + APP_IFRAME_BASE_URL: process.env.APP_IFRAME_BASE_URL, + APP_LOG_LEVEL: process.env.APP_LOG_LEVEL, + FILE_APL_PATH: process.env.FILE_APL_PATH, + MANIFEST_APP_ID: process.env.MANIFEST_APP_ID, + ENV: process.env.ENV, + NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN, + NODE_ENV: process.env.NODE_ENV, + OTEL_ENABLED: process.env.OTEL_ENABLED, + OTEL_SERVICE_NAME: process.env.OTEL_SERVICE_NAME, + PORT: process.env.PORT, + REST_APL_ENDPOINT: process.env.REST_APL_ENDPOINT, + REST_APL_TOKEN: process.env.REST_APL_TOKEN, + SECRET_KEY: process.env.SECRET_KEY, + VERCEL_URL: process.env.VERCEL_URL, + }, + isServer: typeof window === "undefined" || process.env.NODE_ENV === "test", +}); diff --git a/apps/segment/src/lib/create-instrumented-graphql-client.ts b/apps/segment/src/lib/create-instrumented-graphql-client.ts new file mode 100644 index 000000000..f43a9921d --- /dev/null +++ b/apps/segment/src/lib/create-instrumented-graphql-client.ts @@ -0,0 +1,12 @@ +import { otelExchange } from "@saleor/apps-otel"; +import { createGraphQLClient, CreateGraphQLClientArgs } from "@saleor/apps-shared"; + +type CreateGraphQLClientProps = Omit; + +export const createInstrumentedGraphqlClient = (props: CreateGraphQLClientProps) => + createGraphQLClient({ + ...props, + opts: { + prependingFetchExchanges: [otelExchange], + }, + }); diff --git a/apps/segment/src/logger-context.ts b/apps/segment/src/logger-context.ts index e41f7de92..f5675824e 100644 --- a/apps/segment/src/logger-context.ts +++ b/apps/segment/src/logger-context.ts @@ -1,60 +1,6 @@ -import { SALEOR_API_URL_HEADER, SALEOR_EVENT_HEADER } from "@saleor/app-sdk/const"; -import { AsyncLocalStorage } from "async_hooks"; -import { NextApiHandler, NextApiRequest, NextApiResponse } from "next"; +import { LoggerContext } from "@saleor/apps-logger/node"; -class LoggerContext { - private als = new AsyncLocalStorage>(); - private project_name = process.env.OTEL_SERVICE_NAME as string | undefined; - - getRawContext() { - const store = this.als.getStore(); - - if (!store) { - if (!process.env.CI && process.env.OTEL_ENABLED === "true") { - console.warn( - "You cant use LoggerContext outside of the wrapped scope. Will fallback to {}", - ); - } - - return {}; - } - - return store; - } - - async wrap(fn: (...args: unknown[]) => unknown, initialState = {}) { - return this.als.run( - { - ...initialState, - project_name: this.project_name, - }, - fn, - ); - } - - set(key: string, value: string | number | Record | null) { - const store = this.getRawContext(); - - store[key] = value; - } -} /** * Server-side only */ export const loggerContext = new LoggerContext(); - -export const wrapWithLoggerContext = (handler: NextApiHandler, loggerContext: LoggerContext) => { - return (req: NextApiRequest, res: NextApiResponse) => { - return loggerContext.wrap(() => { - const saleorApiUrl = req.headers[SALEOR_API_URL_HEADER] as string; - const saleorEvent = req.headers[SALEOR_EVENT_HEADER] as string; - const path = req.url as string; - - loggerContext.set("path", path); - loggerContext.set("saleorApiUrl", saleorApiUrl ?? null); - loggerContext.set("saleorEvent", saleorEvent ?? null); - - return handler(req, res); - }); - }; -}; diff --git a/apps/segment/src/logger.ts b/apps/segment/src/logger.ts index 2cf29e551..95a2ecb92 100644 --- a/apps/segment/src/logger.ts +++ b/apps/segment/src/logger.ts @@ -1,10 +1,11 @@ import { attachLoggerConsoleTransport, rootLogger } from "@saleor/apps-logger"; import packageJson from "../package.json"; +import { env } from "./env"; rootLogger.settings.maskValuesOfKeys = ["metadata", "username", "password", "apiKey"]; -if (process.env.NODE_ENV !== "production") { +if (env.NODE_ENV !== "production") { attachLoggerConsoleTransport(rootLogger); } @@ -12,7 +13,7 @@ if (typeof window === "undefined") { // Don't remove require - it's necessary for proper logger initialization const { attachLoggerVercelRuntimeTransport } = require("@saleor/apps-logger/node"); - if (process.env.NODE_ENV === "production") { + if (env.NODE_ENV === "production") { attachLoggerVercelRuntimeTransport( rootLogger, packageJson.version, diff --git a/apps/segment/src/modules/configuration/metadata-manager.ts b/apps/segment/src/modules/configuration/metadata-manager.ts index 6877d9c9f..ce52c9ed4 100644 --- a/apps/segment/src/modules/configuration/metadata-manager.ts +++ b/apps/segment/src/modules/configuration/metadata-manager.ts @@ -2,11 +2,13 @@ import { SettingsManager } from "@saleor/app-sdk/settings-manager"; import { EncryptedMetadataManagerFactory } from "@saleor/apps-shared"; import { Client } from "urql"; +import { env } from "@/env"; + export const createSettingsManager = ( client: Pick, appId: string, ): SettingsManager => { - const metadataManagerFactory = new EncryptedMetadataManagerFactory(process.env.SECRET_KEY!); + const metadataManagerFactory = new EncryptedMetadataManagerFactory(env.SECRET_KEY); return metadataManagerFactory.create(client, appId); }; diff --git a/apps/segment/src/modules/trpc/trpc-client.ts b/apps/segment/src/modules/trpc/trpc-client.ts index 3bde46ee5..e3a7fcf94 100644 --- a/apps/segment/src/modules/trpc/trpc-client.ts +++ b/apps/segment/src/modules/trpc/trpc-client.ts @@ -2,15 +2,16 @@ import { SALEOR_API_URL_HEADER, SALEOR_AUTHORIZATION_BEARER_HEADER } from "@sale import { httpBatchLink } from "@trpc/client"; import { createTRPCNext } from "@trpc/next"; +import { env } from "@/env"; import { appBridgeInstance } from "@/pages/_app"; import { AppRouter } from "./trpc-app-router"; function getBaseUrl() { if (typeof window !== "undefined") return ""; - if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; + if (env.VERCEL_URL) return `https://${env.VERCEL_URL}`; - return `http://localhost:${process.env.PORT ?? 3000}`; + return `http://localhost:${env.PORT}`; } export const trpcClient = createTRPCNext({ diff --git a/apps/segment/src/modules/webhooks/definitions/order-cancelled.ts b/apps/segment/src/modules/webhooks/definitions/order-cancelled.ts new file mode 100644 index 000000000..07b62b366 --- /dev/null +++ b/apps/segment/src/modules/webhooks/definitions/order-cancelled.ts @@ -0,0 +1,16 @@ +import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; + +import { + OrderCancelledDocument, + OrderUpdatedSubscriptionPayloadFragment, +} from "@/generated/graphql"; +import { saleorApp } from "@/saleor-app"; + +export const orderCancelledAsyncWebhook = + new SaleorAsyncWebhook({ + name: "Order Cancelled", + webhookPath: "api/webhooks/order-cancelled", + event: "ORDER_CANCELLED", + apl: saleorApp.apl, + query: OrderCancelledDocument, + }); diff --git a/apps/segment/src/modules/webhooks/definitions/order-created.ts b/apps/segment/src/modules/webhooks/definitions/order-created.ts new file mode 100644 index 000000000..8259221b2 --- /dev/null +++ b/apps/segment/src/modules/webhooks/definitions/order-created.ts @@ -0,0 +1,13 @@ +import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; + +import { OrderCreatedDocument, OrderCreatedSubscriptionPayloadFragment } from "@/generated/graphql"; +import { saleorApp } from "@/saleor-app"; + +export const orderCreatedAsyncWebhook = + new SaleorAsyncWebhook({ + name: "Order Created", + webhookPath: "api/webhooks/order-created", + event: "ORDER_CREATED", + apl: saleorApp.apl, + query: OrderCreatedDocument, + }); diff --git a/apps/segment/src/modules/webhooks/definitions/order-fully-paid.ts b/apps/segment/src/modules/webhooks/definitions/order-fully-paid.ts new file mode 100644 index 000000000..83e2e7f09 --- /dev/null +++ b/apps/segment/src/modules/webhooks/definitions/order-fully-paid.ts @@ -0,0 +1,16 @@ +import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; + +import { + OrderFullyPaidDocument, + OrderFullyPaidSubscriptionPayloadFragment, +} from "@/generated/graphql"; +import { saleorApp } from "@/saleor-app"; + +export const orderFullyPaidAsyncWebhook = + new SaleorAsyncWebhook({ + name: "Order Fully Paid", + webhookPath: "api/webhooks/order-fully-paid", + event: "ORDER_FULLY_PAID", + apl: saleorApp.apl, + query: OrderFullyPaidDocument, + }); diff --git a/apps/segment/src/modules/webhooks/definitions/order-refunded.ts b/apps/segment/src/modules/webhooks/definitions/order-refunded.ts new file mode 100644 index 000000000..ef2aaca5a --- /dev/null +++ b/apps/segment/src/modules/webhooks/definitions/order-refunded.ts @@ -0,0 +1,16 @@ +import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; + +import { + OrderRefundedDocument, + OrderRefundedSubscriptionPayloadFragment, +} from "@/generated/graphql"; +import { saleorApp } from "@/saleor-app"; + +export const orderRefundedAsyncWebhook = + new SaleorAsyncWebhook({ + name: "Order Refunded", + webhookPath: "api/webhooks/order-refunded", + event: "ORDER_REFUNDED", + apl: saleorApp.apl, + query: OrderRefundedDocument, + }); diff --git a/apps/segment/src/modules/webhooks/definitions/order-updated.ts b/apps/segment/src/modules/webhooks/definitions/order-updated.ts new file mode 100644 index 000000000..e665a9a99 --- /dev/null +++ b/apps/segment/src/modules/webhooks/definitions/order-updated.ts @@ -0,0 +1,13 @@ +import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; + +import { OrderUpdatedDocument, OrderUpdatedSubscriptionPayloadFragment } from "@/generated/graphql"; +import { saleorApp } from "@/saleor-app"; + +export const orderUpdatedAsyncWebhook = + new SaleorAsyncWebhook({ + name: "Order Updated", + webhookPath: "api/webhooks/order-updated", + event: "ORDER_UPDATED", + apl: saleorApp.apl, + query: OrderUpdatedDocument, + }); diff --git a/apps/segment/src/modules/webhooks/webhooks.ts b/apps/segment/src/modules/webhooks/webhooks.ts new file mode 100644 index 000000000..e2b74ba8e --- /dev/null +++ b/apps/segment/src/modules/webhooks/webhooks.ts @@ -0,0 +1,13 @@ +import { orderCancelledAsyncWebhook } from "./definitions/order-cancelled"; +import { orderCreatedAsyncWebhook } from "./definitions/order-created"; +import { orderFullyPaidAsyncWebhook } from "./definitions/order-fully-paid"; +import { orderRefundedAsyncWebhook } from "./definitions/order-refunded"; +import { orderUpdatedAsyncWebhook } from "./definitions/order-updated"; + +export const appWebhooks = [ + orderCancelledAsyncWebhook, + orderCreatedAsyncWebhook, + orderFullyPaidAsyncWebhook, + orderRefundedAsyncWebhook, + orderUpdatedAsyncWebhook, +]; diff --git a/apps/segment/src/pages/api/manifest.ts b/apps/segment/src/pages/api/manifest.ts index 8ab9069ae..573112425 100644 --- a/apps/segment/src/pages/api/manifest.ts +++ b/apps/segment/src/pages/api/manifest.ts @@ -1,23 +1,21 @@ import { createManifestHandler } from "@saleor/app-sdk/handlers/next"; import { AppManifest } from "@saleor/app-sdk/types"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { env } from "@/env"; +import { loggerContext } from "@/logger-context"; +import { appWebhooks } from "@/modules/webhooks/webhooks"; import packageJson from "../../../package.json"; -import { orderCancelledWebhook } from "./webhooks/order-cancelled"; -import { orderCreatedWebhook } from "./webhooks/order-created"; -import { orderFullyPaidWebhook } from "./webhooks/order-fully-paid"; -import { orderRefundedWebhook } from "./webhooks/order-refunded"; -import { orderUpdatedWebhook } from "./webhooks/order-updated"; export default wrapWithLoggerContext( createManifestHandler({ async manifestFactory({ appBaseUrl }) { - const iframeBaseUrl = process.env.APP_IFRAME_BASE_URL ?? appBaseUrl; - const apiBaseURL = process.env.APP_API_BASE_URL ?? appBaseUrl; + const iframeBaseUrl = env.APP_IFRAME_BASE_URL ?? appBaseUrl; + const apiBaseURL = env.APP_API_BASE_URL ?? appBaseUrl; const manifest: AppManifest = { - about: "Seamlessly feed Segment with Saleor events", + about: "Seamlessly feed Twillo Segment with Saleor events", appUrl: iframeBaseUrl, author: "Saleor Commerce", brand: { @@ -26,30 +24,19 @@ export default wrapWithLoggerContext( }, }, dataPrivacyUrl: "https://saleor.io/legal/privacy/", - extensions: [ - /** - * Optionally, extend Dashboard with custom UIs - * https://docs.saleor.io/docs/3.x/developer/extending/apps/extending-dashboard-with-apps - */ - ], + extensions: [], homepageUrl: "https://github.com/saleor/apps", - id: "saleor.app.segment", + id: env.MANIFEST_APP_ID, name: "Twilio Segment", permissions: ["MANAGE_ORDERS"], - requiredSaleorVersion: ">=3.14 <4", + requiredSaleorVersion: ">=3.20 <4", supportUrl: "https://github.com/saleor/apps/discussions", tokenTargetUrl: `${apiBaseURL}/api/register`, version: packageJson.version, /* * TODO Add webhooks disabled and enable then when configured */ - webhooks: [ - orderCreatedWebhook.getWebhookManifest(appBaseUrl), - orderUpdatedWebhook.getWebhookManifest(appBaseUrl), - orderCancelledWebhook.getWebhookManifest(appBaseUrl), - orderRefundedWebhook.getWebhookManifest(appBaseUrl), - orderFullyPaidWebhook.getWebhookManifest(appBaseUrl), - ], + webhooks: appWebhooks.map((w) => w.getWebhookManifest(apiBaseURL)), }; return manifest; diff --git a/apps/segment/src/pages/api/register.ts b/apps/segment/src/pages/api/register.ts index 090c7fac7..088d098b2 100644 --- a/apps/segment/src/pages/api/register.ts +++ b/apps/segment/src/pages/api/register.ts @@ -1,10 +1,12 @@ import { createAppRegisterHandler } from "@saleor/app-sdk/handlers/next"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import escapeStringRegexp from "escape-string-regexp"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { env } from "@/env"; +import { loggerContext } from "@/logger-context"; import { saleorApp } from "@/saleor-app"; -const allowedUrlsPattern = process.env.ALLOWED_DOMAIN_PATTERN; +const allowedUrlsPattern = env.ALLOWED_DOMAIN_PATTERN; /** * Required endpoint, called by Saleor to install app. diff --git a/apps/segment/src/pages/api/webhooks/order-cancelled.ts b/apps/segment/src/pages/api/webhooks/order-cancelled.ts index 69dba9dff..2b42959a9 100644 --- a/apps/segment/src/pages/api/webhooks/order-cancelled.ts +++ b/apps/segment/src/pages/api/webhooks/order-cancelled.ts @@ -1,16 +1,13 @@ -import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { SegmentNotConfiguredError } from "@/errors"; +import { OrderUpdatedSubscriptionPayloadFragment } from "@/generated/graphql"; import { createLogger } from "@/logger"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { loggerContext } from "@/logger-context"; import { createSegmentClientForWebhookContext } from "@/modules/create-segment-client-for-webhook-context"; import { trackingEventFactory } from "@/modules/tracking-events/tracking-events"; -import { saleorApp } from "@/saleor-app"; - -import { - OrderCancelledDocument, - OrderUpdatedSubscriptionPayloadFragment, -} from "../../../../generated/graphql"; +import { orderCancelledAsyncWebhook } from "@/modules/webhooks/definitions/order-cancelled"; export const config = { api: { @@ -18,15 +15,6 @@ export const config = { }, }; -export const orderCancelledWebhook = - new SaleorAsyncWebhook({ - name: "Order Cancelled v1", - webhookPath: "api/webhooks/order-cancelled", - event: "ORDER_CANCELLED", - apl: saleorApp.apl, - query: OrderCancelledDocument, - }); - const logger = createLogger("orderCancelledAsyncWebhook"); const handler: NextWebhookApiHandler = async ( @@ -61,4 +49,7 @@ const handler: NextWebhookApiHandler = } }; -export default wrapWithLoggerContext(orderCancelledWebhook.createHandler(handler), loggerContext); +export default wrapWithLoggerContext( + orderCancelledAsyncWebhook.createHandler(handler), + loggerContext, +); diff --git a/apps/segment/src/pages/api/webhooks/order-created.ts b/apps/segment/src/pages/api/webhooks/order-created.ts index 799ad5e82..0c2ea87e2 100644 --- a/apps/segment/src/pages/api/webhooks/order-created.ts +++ b/apps/segment/src/pages/api/webhooks/order-created.ts @@ -1,16 +1,13 @@ -import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { SegmentNotConfiguredError } from "@/errors"; +import { OrderCreatedSubscriptionPayloadFragment } from "@/generated/graphql"; import { createLogger } from "@/logger"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { loggerContext } from "@/logger-context"; import { createSegmentClientForWebhookContext } from "@/modules/create-segment-client-for-webhook-context"; import { trackingEventFactory } from "@/modules/tracking-events/tracking-events"; -import { saleorApp } from "@/saleor-app"; - -import { - OrderCreatedDocument, - OrderCreatedSubscriptionPayloadFragment, -} from "../../../../generated/graphql"; +import { orderCreatedAsyncWebhook } from "@/modules/webhooks/definitions/order-created"; export const config = { api: { @@ -18,14 +15,6 @@ export const config = { }, }; -export const orderCreatedWebhook = new SaleorAsyncWebhook({ - name: "Order Created v1", - webhookPath: "api/webhooks/order-created", - event: "ORDER_CREATED", - apl: saleorApp.apl, - query: OrderCreatedDocument, -}); - const logger = createLogger("orderCreatedSyncWebhook"); const handler: NextWebhookApiHandler = async ( @@ -60,4 +49,7 @@ const handler: NextWebhookApiHandler = } }; -export default wrapWithLoggerContext(orderCreatedWebhook.createHandler(handler), loggerContext); +export default wrapWithLoggerContext( + orderCreatedAsyncWebhook.createHandler(handler), + loggerContext, +); diff --git a/apps/segment/src/pages/api/webhooks/order-fully-paid.ts b/apps/segment/src/pages/api/webhooks/order-fully-paid.ts index c350493cd..86c532c0d 100644 --- a/apps/segment/src/pages/api/webhooks/order-fully-paid.ts +++ b/apps/segment/src/pages/api/webhooks/order-fully-paid.ts @@ -1,16 +1,13 @@ -import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { SegmentNotConfiguredError } from "@/errors"; +import { OrderFullyPaidSubscriptionPayloadFragment } from "@/generated/graphql"; import { createLogger } from "@/logger"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { loggerContext } from "@/logger-context"; import { createSegmentClientForWebhookContext } from "@/modules/create-segment-client-for-webhook-context"; import { trackingEventFactory } from "@/modules/tracking-events/tracking-events"; -import { saleorApp } from "@/saleor-app"; - -import { - OrderFullyPaidDocument, - OrderFullyPaidSubscriptionPayloadFragment, -} from "../../../../generated/graphql"; +import { orderFullyPaidAsyncWebhook } from "@/modules/webhooks/definitions/order-fully-paid"; export const config = { api: { @@ -18,15 +15,6 @@ export const config = { }, }; -export const orderFullyPaidWebhook = - new SaleorAsyncWebhook({ - name: "Order Fully Paid v1", - webhookPath: "api/webhooks/order-fully-paid", - event: "ORDER_FULLY_PAID", - apl: saleorApp.apl, - query: OrderFullyPaidDocument, - }); - const logger = createLogger("orderFullyPaidAsyncWebhook"); const handler: NextWebhookApiHandler = async ( @@ -61,4 +49,7 @@ const handler: NextWebhookApiHandler } }; -export default wrapWithLoggerContext(orderFullyPaidWebhook.createHandler(handler), loggerContext); +export default wrapWithLoggerContext( + orderFullyPaidAsyncWebhook.createHandler(handler), + loggerContext, +); diff --git a/apps/segment/src/pages/api/webhooks/order-refunded.ts b/apps/segment/src/pages/api/webhooks/order-refunded.ts index 5c5fc6bf2..65a5666fe 100644 --- a/apps/segment/src/pages/api/webhooks/order-refunded.ts +++ b/apps/segment/src/pages/api/webhooks/order-refunded.ts @@ -1,16 +1,13 @@ -import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { SegmentNotConfiguredError } from "@/errors"; +import { OrderRefundedSubscriptionPayloadFragment } from "@/generated/graphql"; import { createLogger } from "@/logger"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { loggerContext } from "@/logger-context"; import { createSegmentClientForWebhookContext } from "@/modules/create-segment-client-for-webhook-context"; import { trackingEventFactory } from "@/modules/tracking-events/tracking-events"; -import { saleorApp } from "@/saleor-app"; - -import { - OrderRefundedDocument, - OrderRefundedSubscriptionPayloadFragment, -} from "../../../../generated/graphql"; +import { orderRefundedAsyncWebhook } from "@/modules/webhooks/definitions/order-refunded"; export const config = { api: { @@ -18,15 +15,6 @@ export const config = { }, }; -export const orderRefundedWebhook = - new SaleorAsyncWebhook({ - name: "Order Refunded v1", - webhookPath: "api/webhooks/order-refunded", - event: "ORDER_REFUNDED", - apl: saleorApp.apl, - query: OrderRefundedDocument, - }); - const logger = createLogger("orderRefundedAsyncWebhook"); const handler: NextWebhookApiHandler = async ( @@ -61,4 +49,7 @@ const handler: NextWebhookApiHandler = } }; -export default wrapWithLoggerContext(orderRefundedWebhook.createHandler(handler), loggerContext); +export default wrapWithLoggerContext( + orderRefundedAsyncWebhook.createHandler(handler), + loggerContext, +); diff --git a/apps/segment/src/pages/api/webhooks/order-updated.ts b/apps/segment/src/pages/api/webhooks/order-updated.ts index de3eb6e6b..2a39ab444 100644 --- a/apps/segment/src/pages/api/webhooks/order-updated.ts +++ b/apps/segment/src/pages/api/webhooks/order-updated.ts @@ -1,16 +1,13 @@ -import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { SegmentNotConfiguredError } from "@/errors"; +import { OrderUpdatedSubscriptionPayloadFragment } from "@/generated/graphql"; import { createLogger } from "@/logger"; -import { loggerContext, wrapWithLoggerContext } from "@/logger-context"; +import { loggerContext } from "@/logger-context"; import { createSegmentClientForWebhookContext } from "@/modules/create-segment-client-for-webhook-context"; import { trackingEventFactory } from "@/modules/tracking-events/tracking-events"; -import { saleorApp } from "@/saleor-app"; - -import { - OrderUpdatedDocument, - OrderUpdatedSubscriptionPayloadFragment, -} from "../../../../generated/graphql"; +import { orderUpdatedAsyncWebhook } from "@/modules/webhooks/definitions/order-updated"; export const config = { api: { @@ -18,14 +15,6 @@ export const config = { }, }; -export const orderUpdatedWebhook = new SaleorAsyncWebhook({ - name: "Order Updated v1", - webhookPath: "api/webhooks/order-updated", - event: "ORDER_UPDATED", - apl: saleorApp.apl, - query: OrderUpdatedDocument, -}); - const logger = createLogger("orderUpdatedAsyncWebhook"); const handler: NextWebhookApiHandler = async ( @@ -60,4 +49,7 @@ const handler: NextWebhookApiHandler = } }; -export default wrapWithLoggerContext(orderUpdatedWebhook.createHandler(handler), loggerContext); +export default wrapWithLoggerContext( + orderUpdatedAsyncWebhook.createHandler(handler), + loggerContext, +); diff --git a/apps/segment/src/saleor-app.ts b/apps/segment/src/saleor-app.ts index 67fb20d72..67e1bebed 100644 --- a/apps/segment/src/saleor-app.ts +++ b/apps/segment/src/saleor-app.ts @@ -1,35 +1,34 @@ -import { APL, FileAPL, SaleorCloudAPL, UpstashAPL } from "@saleor/app-sdk/APL"; +import { APL, FileAPL, SaleorCloudAPL } from "@saleor/app-sdk/APL"; import { SaleorApp } from "@saleor/app-sdk/saleor-app"; -const aplType = process.env.APL ?? "file"; +import { env } from "./env"; export let apl: APL; -switch (aplType) { - case "upstash": - apl = new UpstashAPL(); - - break; +switch (env.APL) { case "file": - apl = new FileAPL(); + apl = new FileAPL({ + fileName: env.FILE_APL_PATH, + }); break; case "saleor-cloud": { - if (!process.env.REST_APL_ENDPOINT || !process.env.REST_APL_TOKEN) { + if (!env.REST_APL_ENDPOINT || !env.REST_APL_TOKEN) { throw new Error("Rest APL is not configured - missing env variables. Check saleor-app.ts"); } apl = new SaleorCloudAPL({ - resourceUrl: process.env.REST_APL_ENDPOINT, - token: process.env.REST_APL_TOKEN, + resourceUrl: env.REST_APL_ENDPOINT, + token: env.REST_APL_TOKEN, }); break; } default: { - throw new Error("Invalid APL config, "); + throw new Error("Invalid APL config"); } } + export const saleorApp = new SaleorApp({ apl, }); diff --git a/apps/segment/tsconfig.json b/apps/segment/tsconfig.json index 579e3859a..708bef2e8 100644 --- a/apps/segment/tsconfig.json +++ b/apps/segment/tsconfig.json @@ -9,13 +9,15 @@ "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "Bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, + "baseUrl": ".", "paths": { - "@/*": ["./src/*"] + "@/*": ["./src/*"], + "@/generated/*": ["generated/*"] } }, "include": [ diff --git a/apps/segment/turbo.json b/apps/segment/turbo.json index 8f6dff1a6..8b41ddd05 100644 --- a/apps/segment/turbo.json +++ b/apps/segment/turbo.json @@ -11,7 +11,10 @@ "PORT", "REST_APL_ENDPOINT", "REST_APL_TOKEN", - "SECRET_KEY" + "SECRET_KEY", + "NEXT_PUBLIC_SENTRY_DSN", + "FILE_APL_PATH", + "MANIFEST_APP_ID" ] } } diff --git a/apps/segment/vitest.config.ts b/apps/segment/vitest.config.ts index 5ae704ed2..1fb268a0e 100644 --- a/apps/segment/vitest.config.ts +++ b/apps/segment/vitest.config.ts @@ -12,6 +12,7 @@ export default defineConfig({ css: false, alias: { "@/": new URL("./src/", import.meta.url).pathname, + "@/generated": new URL("./generated/", import.meta.url).pathname, }, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e9dcfb4d6..0eeaae224 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -210,7 +210,7 @@ importers: version: 10.43.1(@trpc/server@10.43.1) '@trpc/next': specifier: 10.43.1 - version: 10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@trpc/server': specifier: 10.43.1 version: 10.43.1 @@ -252,7 +252,7 @@ importers: version: 6.2.1 next: specifier: 14.2.3 - version: 14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -475,7 +475,7 @@ importers: version: 20.0.3 next: specifier: 14.2.3 - version: 14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) p-ratelimit: specifier: 1.0.1 version: 1.0.1 @@ -647,7 +647,7 @@ importers: version: 2.12.6(graphql@16.7.1) next: specifier: 14.2.3 - version: 14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) node-fetch: specifier: ^3.2.6 version: 3.2.6 @@ -849,7 +849,7 @@ importers: version: 20.0.3 next: specifier: 14.2.3 - version: 14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -1042,7 +1042,7 @@ importers: version: 2.12.6(graphql@16.7.1) next: specifier: 14.2.3 - version: 14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -1134,6 +1134,9 @@ importers: '@saleor/apps-logger': specifier: workspace:* version: link:../../packages/logger + '@saleor/apps-otel': + specifier: workspace:* + version: link:../../packages/otel '@saleor/apps-shared': specifier: workspace:* version: link:../../packages/shared @@ -1146,15 +1149,33 @@ importers: '@saleor/react-hook-form-macaw': specifier: workspace:* version: link:../../packages/react-hook-form-macaw + '@saleor/sentry-utils': + specifier: workspace:* + version: link:../../packages/sentry-utils + '@saleor/webhook-utils': + specifier: workspace:* + version: link:../../packages/webhook-utils '@segment/analytics-node': specifier: ^1.1.0 version: 1.3.0 + '@sentry/cli': + specifier: ../../node_modules/@sentry/cli + version: link:../../node_modules/@sentry/cli + '@sentry/nextjs': + specifier: ../../node_modules/@sentry/nextjs + version: link:../../node_modules/@sentry/nextjs + '@sentry/node': + specifier: ../../node_modules/@sentry/node + version: link:../../node_modules/@sentry/node + '@t3-oss/env-nextjs': + specifier: 0.11.1 + version: 0.11.1(typescript@5.5.4)(zod@3.21.4) '@trpc/client': specifier: 10.43.1 version: 10.43.1(@trpc/server@10.43.1) '@trpc/next': specifier: 10.43.1 - version: 10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@trpc/server': specifier: 10.43.1 version: 10.43.1 @@ -1178,7 +1199,7 @@ importers: version: 2.12.6(graphql@16.7.1) next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -1239,13 +1260,13 @@ importers: version: 18.2.5 eslint: specifier: ../../node_modules/eslint - version: 8.57.0 + version: link:../../node_modules/eslint eslint-config-saleor: specifier: workspace:* version: link:../../packages/eslint-config-saleor eslint-plugin-node: specifier: 11.1.0 - version: 11.1.0(eslint@8.57.0) + version: 11.1.0(eslint@node_modules+eslint) graphql-config: specifier: 5.0.3 version: 5.0.3(@types/node@20.12.3)(graphql@16.7.1)(typescript@5.5.4) @@ -1401,7 +1422,7 @@ importers: version: 6.2.1 next: specifier: 14.2.3 - version: 14.2.3(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) nodemailer: specifier: ^6.9.1 version: 6.9.1 @@ -1552,7 +1573,7 @@ importers: version: 12.1.1(eslint@node_modules+eslint) next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) typescript: specifier: 5.5.4 version: 5.5.4 @@ -1760,7 +1781,7 @@ importers: version: link:../eslint-config-saleor next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -1821,7 +1842,7 @@ importers: version: link:../eslint-config-saleor next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) typescript: specifier: 5.5.4 version: 5.5.4 @@ -1852,7 +1873,7 @@ importers: version: link:../eslint-config-saleor next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -1885,7 +1906,7 @@ importers: version: 6.1.0(modern-errors@7.0.1) next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) semver: specifier: 7.5.1 version: 7.5.1 @@ -20510,13 +20531,24 @@ snapshots: react-dom: 18.2.0(react@18.2.0) react-ssr-prepass: 1.5.0(react@18.2.0) - '@trpc/next@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@trpc/next@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@tanstack/react-query': 4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@trpc/client': 10.43.1(@trpc/server@10.43.1) '@trpc/react-query': 10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@trpc/server': 10.43.1 - next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-ssr-prepass: 1.5.0(react@18.2.0) + + '@trpc/next@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/react-query@10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.43.1)(next@14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@tanstack/react-query': 4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@trpc/client': 10.43.1(@trpc/server@10.43.1) + '@trpc/react-query': 10.43.1(@tanstack/react-query@4.29.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.43.1(@trpc/server@10.43.1))(@trpc/server@10.43.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@trpc/server': 10.43.1 + next: 14.2.3(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-ssr-prepass: 1.5.0(react@18.2.0) @@ -23267,12 +23299,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-es@3.0.1(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - eslint-plugin-es@3.0.1(eslint@node_modules+eslint): dependencies: eslint: link:node_modules/eslint @@ -23363,16 +23389,6 @@ snapshots: transitivePeerDependencies: - typescript - eslint-plugin-node@11.1.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - eslint-plugin-es: 3.0.1(eslint@8.57.0) - eslint-utils: 2.1.0 - ignore: 5.2.4 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 6.3.1 - eslint-plugin-node@11.1.0(eslint@node_modules+eslint): dependencies: eslint: link:node_modules/eslint @@ -25914,7 +25930,7 @@ snapshots: neverthrow@6.2.1: {} - next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@node_modules+@opentelemetry+api)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@next/env': 14.2.3 '@swc/helpers': 0.5.5 @@ -25935,7 +25951,7 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.3 '@next/swc-win32-ia32-msvc': 14.2.3 '@next/swc-win32-x64-msvc': 14.2.3 - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': link:node_modules/@opentelemetry/api transitivePeerDependencies: - '@babel/core' - babel-plugin-macros