From 7fa164834945b20bc80b9ad94f1b5655fa237bfd Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Thu, 7 Sep 2023 13:59:45 +0200 Subject: [PATCH] add ts-reset and adjust codebase --- apps/cms-v2/package.json | 1 + apps/cms-v2/reset.d.ts | 1 + .../src/modules/configuration/app-config.ts | 2 +- .../providers/builder.io/builder-io.client.ts | 29 ++++-- apps/crm/package.json | 1 + apps/crm/reset.d.ts | 1 + apps/crm/src/lib/app-bridge-persistence.ts | 2 +- .../mailchimp-config-settings-manager.test.ts | 14 ++- .../src/pages/api/auth/mailchimp/callback.ts | 60 +++++++++--- apps/data-importer/package.json | 1 + apps/data-importer/reset.d.ts | 1 + apps/emails-and-messages/package.json | 1 + apps/emails-and-messages/reset.d.ts | 1 + apps/invoices/package.json | 1 + apps/invoices/reset.d.ts | 1 + .../scripts/migrations/migration-utils.ts | 41 -------- .../scripts/migrations/v1-to-v2/const.ts | 4 - .../scripts/migrations/v1-to-v2/readme.MD | 3 - .../migrations/v1-to-v2/restore-migration.ts | 46 --------- .../migrations/v1-to-v2/run-migration.ts | 67 ------------- .../scripts/migrations/v1-to-v2/run-report.ts | 61 ------------ apps/invoices/src/fixtures/mock-address.ts | 4 +- .../app-configuration-router.ts | 7 +- .../schema-v1/app-config-v1.ts | 23 ----- .../schema-v1/app-configurator.ts | 43 --------- .../app-configuration/schema-v2/app-config.ts | 2 +- .../config-v1-to-v2-migration.service.test.ts | 95 ------------------- .../config-v1-to-v2-migration.service.ts | 54 ----------- .../config-v1-to-v2-transformer.test.ts | 72 -------------- .../schema-v2/config-v1-to-v2-transformer.ts | 29 ------ .../invoice-generator/invoice-generator.ts | 4 +- .../microinvoice-invoice-generator.ts | 7 +- .../src/modules/shop-info/shop-address.ts | 10 ++ .../pages/api/webhooks/invoice-requested.ts | 29 +++--- apps/klaviyo/package.json | 1 + apps/klaviyo/reset.d.ts | 1 + .../pages/api/webhooks/customer-created.ts | 7 +- .../pages/api/webhooks/fulfillment-created.ts | 5 +- .../src/pages/api/webhooks/order-created.ts | 5 +- .../pages/api/webhooks/order-fully-paid.ts | 5 +- apps/products-feed/package.json | 1 + apps/products-feed/reset.d.ts | 1 + .../app-configuration/app-config.test.ts | 1 - .../modules/app-configuration/app-config.ts | 2 +- .../metadata-cache/cache-configurator.ts | 8 +- apps/search/package.json | 1 + apps/search/reset.d.ts | 1 + apps/search/src/lib/useWebhooksStatus.tsx | 4 +- .../modules/configuration/configuration.ts | 2 +- .../handlers/webhooks-status-handler.test.ts | 11 ++- apps/segment/package.json | 1 + apps/segment/reset.d.ts | 1 + .../src/modules/configuration/app-config.ts | 2 +- apps/slack/package.json | 1 + apps/slack/reset.d.ts | 1 + apps/slack/src/hooks/useAppApi.ts | 2 +- apps/taxes/package.json | 1 + apps/taxes/reset.d.ts | 1 + packages/e2e/package.json | 1 + packages/eslint-config-saleor/package.json | 1 + packages/react-hook-form-macaw/package.json | 1 + packages/shared/package.json | 1 + packages/trpc/package.json | 1 + packages/ui/package.json | 1 + pnpm-lock.yaml | 55 +++++++++++ 65 files changed, 228 insertions(+), 617 deletions(-) create mode 100644 apps/cms-v2/reset.d.ts create mode 100644 apps/crm/reset.d.ts create mode 100644 apps/data-importer/reset.d.ts create mode 100644 apps/emails-and-messages/reset.d.ts create mode 100644 apps/invoices/reset.d.ts delete mode 100644 apps/invoices/scripts/migrations/migration-utils.ts delete mode 100644 apps/invoices/scripts/migrations/v1-to-v2/const.ts delete mode 100644 apps/invoices/scripts/migrations/v1-to-v2/readme.MD delete mode 100644 apps/invoices/scripts/migrations/v1-to-v2/restore-migration.ts delete mode 100644 apps/invoices/scripts/migrations/v1-to-v2/run-migration.ts delete mode 100644 apps/invoices/scripts/migrations/v1-to-v2/run-report.ts delete mode 100644 apps/invoices/src/modules/app-configuration/schema-v1/app-config-v1.ts delete mode 100644 apps/invoices/src/modules/app-configuration/schema-v1/app-configurator.ts delete mode 100644 apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.test.ts delete mode 100644 apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.ts delete mode 100644 apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.test.ts delete mode 100644 apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.ts create mode 100644 apps/invoices/src/modules/shop-info/shop-address.ts create mode 100644 apps/klaviyo/reset.d.ts create mode 100644 apps/products-feed/reset.d.ts create mode 100644 apps/search/reset.d.ts create mode 100644 apps/segment/reset.d.ts create mode 100644 apps/slack/reset.d.ts create mode 100644 apps/taxes/reset.d.ts diff --git a/apps/cms-v2/package.json b/apps/cms-v2/package.json index 1d87586..ed60c74 100644 --- a/apps/cms-v2/package.json +++ b/apps/cms-v2/package.json @@ -57,6 +57,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/qs": "^6.9.7", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", diff --git a/apps/cms-v2/reset.d.ts b/apps/cms-v2/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/cms-v2/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/cms-v2/src/modules/configuration/app-config.ts b/apps/cms-v2/src/modules/configuration/app-config.ts index 643b70f..e27686b 100644 --- a/apps/cms-v2/src/modules/configuration/app-config.ts +++ b/apps/cms-v2/src/modules/configuration/app-config.ts @@ -19,7 +19,7 @@ export class AppConfig { connections: [], }; - constructor(initialData?: RootConfig.Shape) { + constructor(initialData?: RootConfig.Shape | unknown) { if (initialData) { this.rootData = RootConfig.Schema.parse(initialData); } diff --git a/apps/cms-v2/src/modules/providers/builder.io/builder-io.client.ts b/apps/cms-v2/src/modules/providers/builder.io/builder-io.client.ts index 2059d20..ad4a287 100644 --- a/apps/cms-v2/src/modules/providers/builder.io/builder-io.client.ts +++ b/apps/cms-v2/src/modules/providers/builder.io/builder-io.client.ts @@ -2,6 +2,7 @@ import { BuilderIoProviderConfig } from "@/modules/configuration"; import { WebhookProductVariantFragment } from "../../../../generated/graphql"; import { createLogger } from "@saleor/apps-shared"; import { FieldsMapper } from "../fields-mapper"; +import { z } from "zod"; // https://www.builder.io/c/docs/write-api export class BuilderIoClient { @@ -43,7 +44,7 @@ export class BuilderIoClient { private async updateProductVariantCall( builderIoEntryId: string, - variant: WebhookProductVariantFragment + variant: WebhookProductVariantFragment, ) { try { const response = await fetch(this.endpoint + `/${builderIoEntryId}`, { @@ -71,13 +72,13 @@ export class BuilderIoClient { { entriesToUpdate, }, - "Trying to update variants in builder.io with following IDs" + "Trying to update variants in builder.io with following IDs", ); return Promise.all( entriesToUpdate.map((id) => { return this.updateProductVariantCall(id, variant); - }) + }), ); } @@ -94,7 +95,7 @@ export class BuilderIoClient { return Promise.all( entriesToUpdate.map((id) => { return this.updateProductVariantCall(id, variant); - }) + }), ); } } @@ -112,8 +113,8 @@ export class BuilderIoClient { "Content-Type": "application/json", Authorization: `Bearer ${this.config.privateApiKey}`, }, - }) - ) + }), + ), ); } @@ -127,15 +128,23 @@ export class BuilderIoClient { variantID: variantId, variantFieldMapping: this.config.productVariantFieldsMapping.variantId, }, - "Trying to fetch variant from Builder.io" + "Trying to fetch variant from Builder.io", ); + const expectedSchema = z.object({ + results: z.array( + z.object({ + id: z.string(), + }), + ), + }); + return fetch( - `https://cdn.builder.io/api/v3/content/${this.config.modelName}?apiKey=${this.config.publicApiKey}&query.data.${this.config.productVariantFieldsMapping.variantId}.$eq=${variantId}&limit=10&includeUnpublished=false&cacheSeconds=0` + `https://cdn.builder.io/api/v3/content/${this.config.modelName}?apiKey=${this.config.publicApiKey}&query.data.${this.config.productVariantFieldsMapping.variantId}.$eq=${variantId}&limit=10&includeUnpublished=false&cacheSeconds=0`, ) - .then((res) => res.json()) + .then((res) => expectedSchema.parse(res.json())) .then((data) => { - return data.results.map((result: any) => result.id) as string[]; + return data.results.map((result) => result.id) as string[]; }) .catch((err) => { this.logger.error(err, "Failed to fetch builder.io entry id"); diff --git a/apps/crm/package.json b/apps/crm/package.json index d480ab9..f46b16f 100644 --- a/apps/crm/package.json +++ b/apps/crm/package.json @@ -51,6 +51,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/mailchimp__mailchimp_marketing": "^3.0.7", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", diff --git a/apps/crm/reset.d.ts b/apps/crm/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/crm/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/crm/src/lib/app-bridge-persistence.ts b/apps/crm/src/lib/app-bridge-persistence.ts index 7877699..3f39ccd 100644 --- a/apps/crm/src/lib/app-bridge-persistence.ts +++ b/apps/crm/src/lib/app-bridge-persistence.ts @@ -23,7 +23,7 @@ export const AppBridgePersistence = { } try { - return JSON.parse(storageItem as string); + return JSON.parse(storageItem as string) as AppBridgeStorageState; } catch (e) { return null; } diff --git a/apps/crm/src/modules/mailchimp/mailchimp-config-settings-manager.test.ts b/apps/crm/src/modules/mailchimp/mailchimp-config-settings-manager.test.ts index df5bafc..f101055 100644 --- a/apps/crm/src/modules/mailchimp/mailchimp-config-settings-manager.test.ts +++ b/apps/crm/src/modules/mailchimp/mailchimp-config-settings-manager.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { MailchimpConfigSettingsManagerV1 } from "./mailchimp-config-settings-manager"; +import { MailchimpConfigSettingsManagerV1, MailchimpConfigType } from "./mailchimp-config-settings-manager"; import { Client } from "urql"; import { SettingsManager, SettingsValue } from "@saleor/app-sdk/settings-manager"; @@ -70,9 +70,11 @@ describe("MailchimpConfigSettingsManagerV1", () => { dc: "us41", }); - const parsedSetValue = JSON.parse(valueHasBeenSet!); + const parsedSetValue = JSON.parse(valueHasBeenSet!) as { + config: MailchimpConfigType + }; - expect(parsedSetValue.config.customerCreateEvent.enabled).toBe(false); + expect(parsedSetValue.config.customerCreateEvent?.enabled).toBe(false); }); it("Calls settings manager with default customerCreateEvent setting to be disabled", async () => { @@ -90,9 +92,11 @@ describe("MailchimpConfigSettingsManagerV1", () => { dc: "us41", }); - const parsedSetValue = JSON.parse(valueHasBeenSet!); + const parsedSetValue = JSON.parse(valueHasBeenSet!) as { + config: MailchimpConfigType + }; - expect(parsedSetValue.config.customerCreateEvent.enabled).toBe(false); + expect(parsedSetValue.config.customerCreateEvent?.enabled).toBe(false); }); it(".get returns null if data doesnt match schema", async () => { diff --git a/apps/crm/src/pages/api/auth/mailchimp/callback.ts b/apps/crm/src/pages/api/auth/mailchimp/callback.ts index ae5fcdf..0de2ea5 100644 --- a/apps/crm/src/pages/api/auth/mailchimp/callback.ts +++ b/apps/crm/src/pages/api/auth/mailchimp/callback.ts @@ -1,6 +1,8 @@ import { NextApiHandler } from "next"; import { MailchimpClientOAuth } from "../../../../modules/mailchimp/mailchimp-client"; import { createLogger } from "@saleor/apps-shared"; +import { z } from "zod"; +import * as Sentry from "@sentry/nextjs"; export const getBaseUrl = (headers: { [name: string]: string | string[] | undefined }): string => { const { host, "x-forwarded-proto": protocol = "http" } = headers; @@ -8,6 +10,17 @@ export const getBaseUrl = (headers: { [name: string]: string | string[] | undefi return `${protocol}://${host}`; }; +const tokenResponseSchema = z.object({ + access_token: z.string().min(1), +}); + +const metadataResponseSchema = z.object({ + dc: z.string().min(1), + login: z.object({ + email: z.string().min(1), + }), +}); + const handler: NextApiHandler = async (req, res) => { const baseUrl = getBaseUrl(req.headers); @@ -28,25 +41,46 @@ const handler: NextApiHandler = async (req, res) => { }), }); - const { access_token } = await tokenResponse.json(); + let accessToken: string; - logger.debug({ access_token }, "Received mailchimp access_token"); + try { + const tokenResponseJson = await tokenResponse.json(); + const parsedTokenResponse = tokenResponseSchema.parse(tokenResponseJson); - const metadataResponse = await fetch("https://login.mailchimp.com/oauth2/metadata", { - headers: { - Authorization: `OAuth ${access_token}`, - }, - }); + accessToken = parsedTokenResponse.access_token; + } catch { + Sentry.captureException( + "Mailchimp token response doesnt contain access_token or can't be fetched", + ); - const metadata = await metadataResponse.json(); + return res.status(500).end(); + } - const mc = new MailchimpClientOAuth(metadata.dc, access_token); + logger.debug({ access_token: accessToken }, "Received mailchimp access_token"); - await mc.ping(); + try { + const metadataResponse = await fetch("https://login.mailchimp.com/oauth2/metadata", { + headers: { + Authorization: `OAuth ${accessToken}`, + }, + }); - return res.redirect( - `/configuration/mailchimp/oauth-success?token=${access_token}&email=${metadata.login.email}&dc=${metadata.dc}` - ); // todo maybe move to cookie + const metadataJson = await metadataResponse.json(); + + const parsedMetadata = metadataResponseSchema.parse(metadataJson); + + const mc = new MailchimpClientOAuth(parsedMetadata.dc, accessToken); + + await mc.ping(); + + return res.redirect( + `/configuration/mailchimp/oauth-success?token=${accessToken}&email=${parsedMetadata.login.email}&dc=${parsedMetadata.dc}`, + ); + } catch { + Sentry.captureException("Mailchimp oauth metadata cant be fetched or is malformed"); + + return res.status(500).end(); + } }; export default handler; diff --git a/apps/data-importer/package.json b/apps/data-importer/package.json index 74a1410..e2a6c0f 100644 --- a/apps/data-importer/package.json +++ b/apps/data-importer/package.json @@ -49,6 +49,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/dot-object": "^2.1.2", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", diff --git a/apps/data-importer/reset.d.ts b/apps/data-importer/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/data-importer/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/emails-and-messages/package.json b/apps/emails-and-messages/package.json index 974079c..1505407 100644 --- a/apps/emails-and-messages/package.json +++ b/apps/emails-and-messages/package.json @@ -61,6 +61,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/html-to-text": "^9.0.0", "@types/mjml": "^4.7.0", "@types/nodemailer": "^6.4.7", diff --git a/apps/emails-and-messages/reset.d.ts b/apps/emails-and-messages/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/emails-and-messages/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/invoices/package.json b/apps/invoices/package.json index 8febb94..34a518b 100644 --- a/apps/invoices/package.json +++ b/apps/invoices/package.json @@ -50,6 +50,7 @@ "@graphql-codegen/typescript-operations": "4.0.1", "@graphql-codegen/typescript-urql": "3.7.3", "@graphql-typed-document-node/core": "3.2.0", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "@types/rimraf": "^3.0.2", diff --git a/apps/invoices/reset.d.ts b/apps/invoices/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/invoices/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/invoices/scripts/migrations/migration-utils.ts b/apps/invoices/scripts/migrations/migration-utils.ts deleted file mode 100644 index d24106e..0000000 --- a/apps/invoices/scripts/migrations/migration-utils.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-disable turbo/no-undeclared-env-vars */ - -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 = createGraphQLClient({ - saleorApiUrl: apiUrl, - token: appToken, - }); - - return createSettingsManager(client); -}; - -export const safeParse = (json?: string) => { - if (!json) return null; - - try { - return JSON.parse(json); - } catch (e) { - return null; - } -}; - -export const verifyRequiredEnvs = () => { - const requiredEnvs = ["SALEOR_CLOUD_TOKEN", "SALEOR_CLOUD_RESOURCE_URL", "SECRET_KEY"]; - - if (!requiredEnvs.every((env) => process.env[env])) { - throw new Error(`Missing envs: ${requiredEnvs.join(" | ")}`); - } -}; - -export const fetchCloudAplEnvs = () => { - const saleorAPL = new SaleorCloudAPL({ - token: process.env.SALEOR_CLOUD_TOKEN!, - resourceUrl: process.env.SALEOR_CLOUD_RESOURCE_URL!, - }); - - return saleorAPL.getAll(); -}; diff --git a/apps/invoices/scripts/migrations/v1-to-v2/const.ts b/apps/invoices/scripts/migrations/v1-to-v2/const.ts deleted file mode 100644 index 6488ecf..0000000 --- a/apps/invoices/scripts/migrations/v1-to-v2/const.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const MigrationV1toV2Consts = { - appConfigV2metadataKey: "app-config-v2", - appConfigV1metadataKey: "app-config", -}; diff --git a/apps/invoices/scripts/migrations/v1-to-v2/readme.MD b/apps/invoices/scripts/migrations/v1-to-v2/readme.MD deleted file mode 100644 index 8bc8029..0000000 --- a/apps/invoices/scripts/migrations/v1-to-v2/readme.MD +++ /dev/null @@ -1,3 +0,0 @@ -Run `npx tsx run-report.ts` to print report (dry-run) -Run `npx tsx run-migration.ts` to migrate -Run `npx tsx restore-migration.ts` to restore migration (remove metadata v2) \ No newline at end of file diff --git a/apps/invoices/scripts/migrations/v1-to-v2/restore-migration.ts b/apps/invoices/scripts/migrations/v1-to-v2/restore-migration.ts deleted file mode 100644 index d0d11ee..0000000 --- a/apps/invoices/scripts/migrations/v1-to-v2/restore-migration.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable turbo/no-undeclared-env-vars */ - -import * as dotenv from "dotenv"; -import { fetchCloudAplEnvs, verifyRequiredEnvs } from "../migration-utils"; -import { RemoveMetadataDocument } from "../../../generated/graphql"; -import { MigrationV1toV2Consts } from "./const"; -import { createGraphQLClient } from "@saleor/apps-shared"; - -dotenv.config(); - -const runMigration = async () => { - verifyRequiredEnvs(); - - const allEnvs = await fetchCloudAplEnvs(); - - const results = await Promise.all( - allEnvs.map((env) => { - const client = createGraphQLClient({ - saleorApiUrl: env.saleorApiUrl, - token: env.token, - }); - - return client - .mutation(RemoveMetadataDocument, { - id: env.appId, - keys: [MigrationV1toV2Consts.appConfigV2metadataKey], - }) - .toPromise() - .then((r) => { - if (r.error) { - console.error("❌ Error removing metadata", r.error.message); - throw r.error.message; - } - - return r; - }) - .catch((e) => { - console.error("❌ Error removing metadata", e); - }); - }) - ); - - console.log(results); -}; - -runMigration(); diff --git a/apps/invoices/scripts/migrations/v1-to-v2/run-migration.ts b/apps/invoices/scripts/migrations/v1-to-v2/run-migration.ts deleted file mode 100644 index 350f194..0000000 --- a/apps/invoices/scripts/migrations/v1-to-v2/run-migration.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-disable turbo/no-undeclared-env-vars */ - -import * as dotenv from "dotenv"; -import { - fetchCloudAplEnvs, - getMetadataManagerForEnv, - safeParse, - verifyRequiredEnvs, -} from "../migration-utils"; -import { ConfigV1ToV2Transformer } from "../../../src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer"; -import { AppConfigV2MetadataManager } from "../../../src/modules/app-configuration/schema-v2/app-config-v2-metadata-manager"; -import { AppConfigV2 } from "../../../src/modules/app-configuration/schema-v2/app-config"; -import { MigrationV1toV2Consts } from "./const"; - -dotenv.config(); - -const runMigration = async () => { - verifyRequiredEnvs(); - - const allEnvs = await fetchCloudAplEnvs(); - - const results = await Promise.all( - allEnvs.map((env) => { - const metadataManager = getMetadataManagerForEnv(env.saleorApiUrl, env.token); - - return Promise.all([ - metadataManager.get(MigrationV1toV2Consts.appConfigV1metadataKey, env.saleorApiUrl), - metadataManager.get(MigrationV1toV2Consts.appConfigV2metadataKey), - ]) - .then(([v1, v2]) => { - if (v2 && v2 !== "undefined") { - console.log("▶️ v2 already exists for ", env.saleorApiUrl); - return; - } - - if (!v1) { - console.log("🚫 v1 does not exist for ", env.saleorApiUrl); - - return new AppConfigV2MetadataManager(metadataManager) - .set(new AppConfigV2().serialize()) - .then((r) => { - console.log(`✅ created empty config for ${env.saleorApiUrl}`); - }) - .catch((e) => { - console.log( - `🚫 failed to create empty config for ${env.saleorApiUrl}. Env may not exist.`, - e.message - ); - }); - } - - const v2Config = new ConfigV1ToV2Transformer().transform(JSON.parse(v1)); - - return new AppConfigV2MetadataManager(metadataManager) - .set(v2Config.serialize()) - .then((r) => { - console.log(`✅ migrated ${env.saleorApiUrl}`); - }); - }) - .catch((e) => { - console.error("🚫 Failed to migrate ", env.saleorApiUrl, e); - }); - }) - ); -}; - -runMigration(); diff --git a/apps/invoices/scripts/migrations/v1-to-v2/run-report.ts b/apps/invoices/scripts/migrations/v1-to-v2/run-report.ts deleted file mode 100644 index 0514084..0000000 --- a/apps/invoices/scripts/migrations/v1-to-v2/run-report.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable turbo/no-undeclared-env-vars */ - -import * as dotenv from "dotenv"; -import { - fetchCloudAplEnvs, - getMetadataManagerForEnv, - safeParse, - verifyRequiredEnvs, -} from "../migration-utils"; -import { MigrationV1toV2Consts } from "./const"; - -dotenv.config(); - -const runReport = async () => { - verifyRequiredEnvs(); - - const allEnvs = await fetchCloudAplEnvs().catch((r) => { - console.error(r); - - process.exit(1); - }); - - const results = await Promise.all( - allEnvs.map((env) => { - const metadataManager = getMetadataManagerForEnv(env.saleorApiUrl, env.token); - - return Promise.all([ - metadataManager.get(MigrationV1toV2Consts.appConfigV1metadataKey, env.saleorApiUrl), - metadataManager.get(MigrationV1toV2Consts.appConfigV2metadataKey), - ]) - .then(([v1, v2]) => { - return { - schemaV1: safeParse(v1), - schemaV2: safeParse(v2), - }; - }) - .then((metadata) => ({ - metadata: metadata, - env: env.saleorApiUrl, - })); - }) - ); - - const report = results.map((r: any) => ({ - env: r.env, - hasV1: !!r.metadata.schemaV1, - hasV2: !!r.metadata.schemaV2, - })); - - const notMigratedCount = report.reduce((acc: number, curr: any) => { - if (!curr.hasV2) { - return acc + 1; - } - return acc; - }, 0); - - console.table(report); - console.log(`Envs left to migrate: ${notMigratedCount}`); -}; - -runReport(); diff --git a/apps/invoices/src/fixtures/mock-address.ts b/apps/invoices/src/fixtures/mock-address.ts index cb6fdee..da03a81 100644 --- a/apps/invoices/src/fixtures/mock-address.ts +++ b/apps/invoices/src/fixtures/mock-address.ts @@ -1,6 +1,6 @@ -import { SellerShopConfig } from "../modules/app-configuration/schema-v1/app-config-v1"; +import { ShopAddress } from "../modules/shop-info/shop-address"; -export const getMockAddress = (): SellerShopConfig["address"] => { +export const getMockAddress = (): ShopAddress => { return { city: "Wrocław", cityArea: "", diff --git a/apps/invoices/src/modules/app-configuration/app-configuration-router.ts b/apps/invoices/src/modules/app-configuration/app-configuration-router.ts index b904812..ec0a87d 100644 --- a/apps/invoices/src/modules/app-configuration/app-configuration-router.ts +++ b/apps/invoices/src/modules/app-configuration/app-configuration-router.ts @@ -3,11 +3,10 @@ import { z } from "zod"; import { protectedClientProcedure } from "../trpc/protected-client-procedure"; import { router } from "../trpc/trpc-server"; import { createSettingsManager } from "./metadata-manager"; +import { AppConfigV2 } from "./schema-v2/app-config"; +import { AddressV2Schema } from "./schema-v2/app-config-schema.v2"; import { AppConfigV2MetadataManager } from "./schema-v2/app-config-v2-metadata-manager"; import { GetAppConfigurationV2Service } from "./schema-v2/get-app-configuration.v2.service"; -import { ConfigV1ToV2MigrationService } from "./schema-v2/config-v1-to-v2-migration.service"; -import { AddressV2Schema } from "./schema-v2/app-config-schema.v2"; -import { AppConfigV2 } from "./schema-v2/app-config"; const UpsertAddressSchema = z.object({ address: AddressV2Schema, @@ -47,7 +46,7 @@ export const appConfigurationRouter = router({ .input( z.object({ channelSlug: z.string(), - }) + }), ) .mutation(async ({ ctx, input }) => { const appConfigV2 = diff --git a/apps/invoices/src/modules/app-configuration/schema-v1/app-config-v1.ts b/apps/invoices/src/modules/app-configuration/schema-v1/app-config-v1.ts deleted file mode 100644 index c68a044..0000000 --- a/apps/invoices/src/modules/app-configuration/schema-v1/app-config-v1.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SellerAddress } from "../address"; - -/** - * @deprecated - * Remove when SchemaV1 is migrated to SchemaV2 - */ -export interface SellerShopConfig { - address: SellerAddress; -} - -/** - * @deprecated - * Remove when SchemaV1 is migrated to SchemaV2 - */ -export type ShopConfigPerChannelSlug = Record; - -/** - * @deprecated - * Remove when SchemaV1 is migrated to SchemaV2 - */ -export type AppConfigV1 = { - shopConfigPerChannel: ShopConfigPerChannelSlug; -}; diff --git a/apps/invoices/src/modules/app-configuration/schema-v1/app-configurator.ts b/apps/invoices/src/modules/app-configuration/schema-v1/app-configurator.ts deleted file mode 100644 index adbdd07..0000000 --- a/apps/invoices/src/modules/app-configuration/schema-v1/app-configurator.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { AppConfigV1 } from "./app-config-v1"; -import { SettingsManager } from "@saleor/app-sdk/settings-manager"; - -/** - * @deprecated - * Remove when SchemaV1 is migrated to SchemaV2 - */ -export interface AppConfigurator { - setConfig(config: AppConfigV1): Promise; - getConfig(): Promise; -} - -/** - * @deprecated - * Remove when SchemaV1 is migrated to SchemaV2 - */ -export class PrivateMetadataAppConfiguratorV1 implements AppConfigurator { - private metadataKey = "app-config"; - - constructor(private metadataManager: SettingsManager, private saleorApiUrl: string) {} - - getConfig(): Promise { - return this.metadataManager.get(this.metadataKey, this.saleorApiUrl).then((data) => { - if (!data) { - return data; - } - - try { - return JSON.parse(data); - } catch (e) { - throw new Error("Invalid metadata value, cant be parsed"); - } - }); - } - - setConfig(config: AppConfigV1): Promise { - return this.metadataManager.set({ - key: this.metadataKey, - value: JSON.stringify(config), - domain: this.saleorApiUrl, - }); - } -} diff --git a/apps/invoices/src/modules/app-configuration/schema-v2/app-config.ts b/apps/invoices/src/modules/app-configuration/schema-v2/app-config.ts index 4218762..5f12598 100644 --- a/apps/invoices/src/modules/app-configuration/schema-v2/app-config.ts +++ b/apps/invoices/src/modules/app-configuration/schema-v2/app-config.ts @@ -4,7 +4,7 @@ import { z } from "zod"; export class AppConfigV2 { private rootData: AppConfigV2Shape = { channelsOverrides: {} }; - constructor(initialData?: AppConfigV2Shape) { + constructor(initialData?: AppConfigV2Shape | unknown) { if (initialData) { this.rootData = AppConfigV2Schema.parse(initialData); } diff --git a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.test.ts b/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.test.ts deleted file mode 100644 index 0187e6d..0000000 --- a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { ConfigV1ToV2MigrationService } from "./config-v1-to-v2-migration.service"; -import { SimpleGraphqlClient } from "../metadata-manager"; -import { getMockAddress } from "../../../fixtures/mock-address"; -import { AppConfigV2 } from "./app-config"; - -describe("config-v1-to-v2-migration.service", () => { - const mockClient: SimpleGraphqlClient = { - mutation: vi.fn(), - query: vi.fn(), - }; - - let service: ConfigV1ToV2MigrationService; - - beforeEach(() => { - vi.resetAllMocks(); - - service = new ConfigV1ToV2MigrationService(mockClient, "https://example.com/graphql/"); - - vi.spyOn(service.configMetadataManager, "set").mockImplementationOnce(async () => - Promise.resolve() - ); - }); - - it("Returns a pure V2 config if V1 config is not present", async () => { - vi.spyOn(service.metadataV1AppConfigurator, "getConfig").mockImplementationOnce(async () => - Promise.resolve(undefined) - ); - - const migrationResult = await service.migrate(); - - expect(migrationResult.getChannelsOverrides()).toEqual({}); - expect(service.configMetadataManager.set).toHaveBeenCalledWith(migrationResult.serialize()); - }); - - it("Returns a migrated V2 config from V1 if V1 config is present", async () => { - vi.spyOn(service.metadataV1AppConfigurator, "getConfig").mockImplementationOnce(async () => - Promise.resolve({ - shopConfigPerChannel: { - "default-channel": { - address: getMockAddress(), - }, - }, - }) - ); - - const migrationResult = await service.migrate(); - - expect(migrationResult.getChannelsOverrides()).toEqual( - expect.objectContaining({ - "default-channel": expect.objectContaining(getMockAddress()), - }) - ); - }); - - it("Runs a beforeSave callback and saves modified state in metadata - missing v1 config scenario", async () => { - vi.spyOn(service.metadataV1AppConfigurator, "getConfig").mockImplementationOnce(async () => - Promise.resolve(undefined) - ); - - const beforeSaveCb = vi.fn().mockImplementationOnce((config: AppConfigV2) => { - config.upsertOverride("test", getMockAddress()); - }); - - const migrationResult = await service.migrate(beforeSaveCb); - - expect(migrationResult.getChannelsOverrides()).toEqual({ - test: expect.objectContaining(getMockAddress()), - }); - expect(service.configMetadataManager.set).toHaveBeenCalledWith(migrationResult.serialize()); - expect(beforeSaveCb).toHaveBeenCalledWith(migrationResult); - }); - - it("Runs a beforeSave callback and saves modified state in metadata - present v1 config scenario", async () => { - vi.spyOn(service.metadataV1AppConfigurator, "getConfig").mockImplementationOnce(async () => - Promise.resolve({ - shopConfigPerChannel: { - "default-channel": { - address: getMockAddress(), - }, - }, - }) - ); - - const beforeSaveCb = vi.fn().mockImplementationOnce((config: AppConfigV2) => { - config.removeOverride("default-channel"); - }); - - const migrationResult = await service.migrate(beforeSaveCb); - - expect(migrationResult.getChannelsOverrides()).toEqual({}); - expect(service.configMetadataManager.set).toHaveBeenCalledWith(migrationResult.serialize()); - expect(beforeSaveCb).toHaveBeenCalledWith(migrationResult); - }); -}); diff --git a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.ts b/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.ts deleted file mode 100644 index 1e59c2b..0000000 --- a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-migration.service.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { PrivateMetadataAppConfiguratorV1 } from "../schema-v1/app-configurator"; -import { createSettingsManager, SimpleGraphqlClient } from "../metadata-manager"; -import { AppConfigV2 } from "./app-config"; -import { ConfigV1ToV2Transformer } from "./config-v1-to-v2-transformer"; -import { AppConfigV2MetadataManager } from "./app-config-v2-metadata-manager"; -import { SettingsManager } from "@saleor/app-sdk/settings-manager"; - -export class ConfigV1ToV2MigrationService { - settingsManager: SettingsManager; - configMetadataManager: AppConfigV2MetadataManager; - metadataV1AppConfigurator: PrivateMetadataAppConfiguratorV1; - - constructor(private client: SimpleGraphqlClient, private saleorApiUrl: string) { - this.settingsManager = createSettingsManager(client); - this.configMetadataManager = new AppConfigV2MetadataManager(this.settingsManager); - this.metadataV1AppConfigurator = new PrivateMetadataAppConfiguratorV1( - this.settingsManager, - this.saleorApiUrl - ); - } - - async migrate(beforeSave?: (config: AppConfigV2) => void): Promise { - const v1Config = await this.metadataV1AppConfigurator.getConfig(); - - /** - * If no v1 config, it means clean install - return pure config - */ - if (!v1Config) { - const pureConfig = new AppConfigV2(); - - if (beforeSave) { - beforeSave(pureConfig); - } - - await this.configMetadataManager.set(pureConfig.serialize()); - - return pureConfig; - } - - /** - * Otherwise, transform v1 config to v2 and save it - */ - const transformer = new ConfigV1ToV2Transformer(); - const appConfigV2FromV1 = transformer.transform(v1Config); - - if (beforeSave) { - beforeSave(appConfigV2FromV1); - } - - await this.configMetadataManager.set(appConfigV2FromV1.serialize()); - - return appConfigV2FromV1; - } -} diff --git a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.test.ts b/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.test.ts deleted file mode 100644 index 8c02d7a..0000000 --- a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { ConfigV1ToV2Transformer } from "./config-v1-to-v2-transformer"; -import { getMockAddress } from "../../../fixtures/mock-address"; - -describe("ConfigV1ToV2Transformer", function () { - it("Returns empty V2 instance if config is null", () => { - // @ts-expect-error - const v2 = new ConfigV1ToV2Transformer().transform(null); - - expect(v2.serialize()).toMatchInlineSnapshot('"{\\"channelsOverrides\\":{}}"'); - }); - - it("Maps V1 address overrides to V2 - single channel override", () => { - const v2 = new ConfigV1ToV2Transformer().transform({ - shopConfigPerChannel: { - "default-channel": { - address: getMockAddress(), - }, - }, - }); - - expect(v2.getChannelsOverrides()).toEqual( - expect.objectContaining({ - "default-channel": getMockAddress(), - }) - ); - }); - - it("Maps V1 address overrides to V2 - multiple channels override", () => { - const v2 = new ConfigV1ToV2Transformer().transform({ - shopConfigPerChannel: { - "default-channel": { - address: getMockAddress(), - }, - "custom-channel": { - address: getMockAddress(), - }, - }, - }); - - expect(v2.getChannelsOverrides()).toEqual( - expect.objectContaining({ - "default-channel": getMockAddress(), - "custom-channel": getMockAddress(), - }) - ); - }); - - it("Falls back to empty string for address property if not set", () => { - const addressMock = getMockAddress(); - - // @ts-expect-error - delete addressMock.city; - - const v2 = new ConfigV1ToV2Transformer().transform({ - shopConfigPerChannel: { - "default-channel": { - address: addressMock, - }, - }, - }); - - expect(v2.getChannelsOverrides()).toEqual( - expect.objectContaining({ - "default-channel": { - ...getMockAddress(), - city: "", - }, - }) - ); - }); -}); diff --git a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.ts b/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.ts deleted file mode 100644 index af7e9bc..0000000 --- a/apps/invoices/src/modules/app-configuration/schema-v2/config-v1-to-v2-transformer.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AppConfigV1 } from "../schema-v1/app-config-v1"; -import { AppConfigV2 } from "./app-config"; - -export class ConfigV1ToV2Transformer { - transform(v1Config: AppConfigV1): AppConfigV2 { - const configV2 = new AppConfigV2(); - - if (!v1Config || !v1Config.shopConfigPerChannel) { - return configV2; - } - - Object.entries(v1Config.shopConfigPerChannel).forEach(([channelSlug, channelConfigV1]) => { - const addressV1 = channelConfigV1.address; - - configV2.upsertOverride(channelSlug, { - city: addressV1.city ?? "", - country: addressV1.country ?? "", - streetAddress2: addressV1.streetAddress2 ?? "", - postalCode: addressV1.postalCode ?? "", - companyName: addressV1.companyName ?? "", - streetAddress1: addressV1.streetAddress1 ?? "", - countryArea: addressV1.countryArea ?? "", - cityArea: addressV1.cityArea ?? "", - }); - }); - - return configV2; - } -} diff --git a/apps/invoices/src/modules/invoices/invoice-generator/invoice-generator.ts b/apps/invoices/src/modules/invoices/invoice-generator/invoice-generator.ts index 377b01d..d1467f0 100644 --- a/apps/invoices/src/modules/invoices/invoice-generator/invoice-generator.ts +++ b/apps/invoices/src/modules/invoices/invoice-generator/invoice-generator.ts @@ -1,11 +1,11 @@ import { OrderPayloadFragment } from "../../../../generated/graphql"; -import { SellerShopConfig } from "../../app-configuration/schema-v1/app-config-v1"; +import { ShopAddress } from "../../shop-info/shop-address"; export interface InvoiceGenerator { generate(input: { order: OrderPayloadFragment; invoiceNumber: string; filename: string; - companyAddressData: SellerShopConfig["address"]; + companyAddressData: ShopAddress; }): Promise; } diff --git a/apps/invoices/src/modules/invoices/invoice-generator/microinvoice/microinvoice-invoice-generator.ts b/apps/invoices/src/modules/invoices/invoice-generator/microinvoice/microinvoice-invoice-generator.ts index 5ebe27f..db55476 100644 --- a/apps/invoices/src/modules/invoices/invoice-generator/microinvoice/microinvoice-invoice-generator.ts +++ b/apps/invoices/src/modules/invoices/invoice-generator/microinvoice/microinvoice-invoice-generator.ts @@ -1,14 +1,13 @@ -import { InvoiceGenerator } from "../invoice-generator"; -import { Order, OrderPayloadFragment } from "../../../../../generated/graphql"; -import { SellerShopConfig } from "../../../app-configuration/schema-v1/app-config-v1"; +import { OrderPayloadFragment } from "../../../../../generated/graphql"; import { AddressV2Shape } from "../../../app-configuration/schema-v2/app-config-schema.v2"; +import { InvoiceGenerator } from "../invoice-generator"; const Microinvoice = require("microinvoice"); export class MicroinvoiceInvoiceGenerator implements InvoiceGenerator { constructor( private settings = { locale: "en-US", - } + }, ) {} async generate(input: { order: OrderPayloadFragment; diff --git a/apps/invoices/src/modules/shop-info/shop-address.ts b/apps/invoices/src/modules/shop-info/shop-address.ts new file mode 100644 index 0000000..2b151e3 --- /dev/null +++ b/apps/invoices/src/modules/shop-info/shop-address.ts @@ -0,0 +1,10 @@ +export type ShopAddress = { + city: string; + cityArea: string; + companyName: string; + country: string; + countryArea: string; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +}; diff --git a/apps/invoices/src/pages/api/webhooks/invoice-requested.ts b/apps/invoices/src/pages/api/webhooks/invoice-requested.ts index 376cb9e..ef0421a 100644 --- a/apps/invoices/src/pages/api/webhooks/invoice-requested.ts +++ b/apps/invoices/src/pages/api/webhooks/invoice-requested.ts @@ -1,30 +1,25 @@ +import { SALEOR_API_URL_HEADER } from "@saleor/app-sdk/const"; import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { createGraphQLClient, createLogger } from "@saleor/apps-shared"; import { gql } from "urql"; -import { saleorApp } from "../../../saleor-app"; import { InvoiceRequestedPayloadFragment, OrderPayloadFragment, } from "../../../../generated/graphql"; -import { SaleorInvoiceUploader } from "../../../modules/invoices/invoice-uploader/saleor-invoice-uploader"; +import { AddressV2Shape } from "../../../modules/app-configuration/schema-v2/app-config-schema.v2"; +import { GetAppConfigurationV2Service } from "../../../modules/app-configuration/schema-v2/get-app-configuration.v2.service"; import { InvoiceCreateNotifier } from "../../../modules/invoices/invoice-create-notifier/invoice-create-notifier"; +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 { MicroinvoiceInvoiceGenerator } from "../../../modules/invoices/invoice-generator/microinvoice/microinvoice-invoice-generator"; import { InvoiceNumberGenerationStrategy, InvoiceNumberGenerator, } from "../../../modules/invoices/invoice-number-generator/invoice-number-generator"; -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 { 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 { SaleorInvoiceUploader } from "../../../modules/invoices/invoice-uploader/saleor-invoice-uploader"; import { ShopInfoFetcher } from "../../../modules/shop-info/shop-info-fetcher"; -import { z } from "zod"; -import { - AddressV2Schema, - AddressV2Shape, -} from "../../../modules/app-configuration/schema-v2/app-config-schema.v2"; -import { ConfigV1ToV2MigrationService } from "../../../modules/app-configuration/schema-v2/config-v1-to-v2-migration.service"; import { shopInfoQueryToAddressShape } from "../../../modules/shop-info/shop-info-query-to-address-shape"; +import { saleorApp } from "../../../saleor-app"; import * as Sentry from "@sentry/nextjs"; import { AppConfigV2 } from "../../../modules/app-configuration/schema-v2/app-config"; @@ -156,7 +151,7 @@ const invoiceNumberGenerator = new InvoiceNumberGenerator(); export const handler: NextWebhookApiHandler = async ( req, res, - context + context, ) => { const { authData, payload, baseUrl } = context; const logger = createLogger({ domain: authData.saleorApiUrl, url: baseUrl }); @@ -176,7 +171,7 @@ export const handler: NextWebhookApiHandler = a */ const invoiceName = invoiceNumberGenerator.generateFromOrder( order as OrderPayloadFragment, - InvoiceNumberGenerationStrategy.localizedDate("en-US") // todo connect locale -> where from? + InvoiceNumberGenerationStrategy.localizedDate("en-US"), // todo connect locale -> where from? ); Sentry.addBreadcrumb({ @@ -270,7 +265,7 @@ export const handler: NextWebhookApiHandler = a await new InvoiceCreateNotifier(client).notifyInvoiceCreated( orderId, invoiceName, - uploadedFileUrl + uploadedFileUrl, ); Sentry.addBreadcrumb({ diff --git a/apps/klaviyo/package.json b/apps/klaviyo/package.json index b4ba545..854ee26 100644 --- a/apps/klaviyo/package.json +++ b/apps/klaviyo/package.json @@ -43,6 +43,7 @@ "@graphql-codegen/typescript-operations": "4.0.1", "@graphql-codegen/typescript-urql": "3.7.3", "@graphql-typed-document-node/core": "3.2.0", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "autoprefixer": "^10.4.7", diff --git a/apps/klaviyo/reset.d.ts b/apps/klaviyo/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/klaviyo/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/klaviyo/src/pages/api/webhooks/customer-created.ts b/apps/klaviyo/src/pages/api/webhooks/customer-created.ts index f91543f..862688b 100644 --- a/apps/klaviyo/src/pages/api/webhooks/customer-created.ts +++ b/apps/klaviyo/src/pages/api/webhooks/customer-created.ts @@ -56,13 +56,13 @@ export const customerCreatedWebhook = new SaleorAsyncWebhook = async ( req, res, - context + context, ) => { console.debug("customerCreatedWebhook handler called"); @@ -94,7 +94,8 @@ const handler: NextWebhookApiHandler = as const klaviyoResponse = await klaviyoClient.send(klaviyoMetric, userEmail, payload); if (klaviyoResponse.status !== 200) { - const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || ""; + const klaviyoMessage = + ` Message: ${((await klaviyoResponse.json()) as { message: string })?.message}.` || ""; console.debug("Klaviyo returned error: ", klaviyoMessage); diff --git a/apps/klaviyo/src/pages/api/webhooks/fulfillment-created.ts b/apps/klaviyo/src/pages/api/webhooks/fulfillment-created.ts index 7a07858..b970d18 100644 --- a/apps/klaviyo/src/pages/api/webhooks/fulfillment-created.ts +++ b/apps/klaviyo/src/pages/api/webhooks/fulfillment-created.ts @@ -68,7 +68,7 @@ export const fulfillmentCreatedWebhook = const handler: NextWebhookApiHandler = async ( req, res, - context + context, ) => { console.debug("fulfillmentCreatedWebhook handler called"); @@ -98,7 +98,8 @@ const handler: NextWebhookApiHandler = const klaviyoResponse = await klaviyoClient.send(klaviyoMetric, userEmail, payload); if (klaviyoResponse.status !== 200) { - const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || ""; + const klaviyoMessage = + ` Message: ${((await klaviyoResponse.json()) as { message: string })?.message}.` || ""; console.debug("Klaviyo returned error: ", klaviyoMessage); diff --git a/apps/klaviyo/src/pages/api/webhooks/order-created.ts b/apps/klaviyo/src/pages/api/webhooks/order-created.ts index 9f76718..84e9eb1 100644 --- a/apps/klaviyo/src/pages/api/webhooks/order-created.ts +++ b/apps/klaviyo/src/pages/api/webhooks/order-created.ts @@ -38,7 +38,7 @@ export const orderCreatedWebhook = new SaleorAsyncWebhook = async ( req, res, - context + context, ) => { console.debug("orderCreatedWebhook handler called"); @@ -69,7 +69,8 @@ const handler: NextWebhookApiHandler = async const klaviyoResponse = await klaviyoClient.send(klaviyoMetric, userEmail, payload); if (klaviyoResponse.status !== 200) { - const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || ""; + const klaviyoMessage = + ` Message: ${((await klaviyoResponse.json()) as { message: string })?.message}.` || ""; console.debug("Klaviyo returned error: ", klaviyoMessage); return res.status(500).json({ diff --git a/apps/klaviyo/src/pages/api/webhooks/order-fully-paid.ts b/apps/klaviyo/src/pages/api/webhooks/order-fully-paid.ts index 9b4b645..60653d8 100644 --- a/apps/klaviyo/src/pages/api/webhooks/order-fully-paid.ts +++ b/apps/klaviyo/src/pages/api/webhooks/order-fully-paid.ts @@ -38,7 +38,7 @@ export const orderFullyPaidWebhook = new SaleorAsyncWebhook = async ( req, res, - context + context, ) => { console.debug("orderFullyPaidWebhook handler called"); @@ -70,7 +70,8 @@ const handler: NextWebhookApiHandler = asy const klaviyoResponse = await klaviyoClient.send(klaviyoMetric, userEmail, payload); if (klaviyoResponse.status !== 200) { - const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || ""; + const klaviyoMessage = + ` Message: ${((await klaviyoResponse.json()) as { message: string })?.message}.` || ""; console.debug("Klaviyo returned error: ", klaviyoMessage); diff --git a/apps/products-feed/package.json b/apps/products-feed/package.json index 047f75e..cd9b8a8 100644 --- a/apps/products-feed/package.json +++ b/apps/products-feed/package.json @@ -56,6 +56,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "eslint": "8.46.0", diff --git a/apps/products-feed/reset.d.ts b/apps/products-feed/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/products-feed/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/products-feed/src/modules/app-configuration/app-config.test.ts b/apps/products-feed/src/modules/app-configuration/app-config.test.ts index 2506583..ed2e625 100644 --- a/apps/products-feed/src/modules/app-configuration/app-config.test.ts +++ b/apps/products-feed/src/modules/app-configuration/app-config.test.ts @@ -94,7 +94,6 @@ describe("AppConfig", function () { expect( () => new AppConfig({ - // @ts-expect-error foo: "bar", }), ).toThrow(); diff --git a/apps/products-feed/src/modules/app-configuration/app-config.ts b/apps/products-feed/src/modules/app-configuration/app-config.ts index 712ad96..a870d09 100644 --- a/apps/products-feed/src/modules/app-configuration/app-config.ts +++ b/apps/products-feed/src/modules/app-configuration/app-config.ts @@ -72,7 +72,7 @@ export class AppConfig { imageSize: imageSizeFieldSchema.parse(undefined), }; - constructor(initialData?: RootConfig) { + constructor(initialData?: RootConfig | unknown) { if (initialData) { try { this.rootData = rootAppConfigSchema.parse(initialData); diff --git a/apps/products-feed/src/modules/metadata-cache/cache-configurator.ts b/apps/products-feed/src/modules/metadata-cache/cache-configurator.ts index a272717..fbb6685 100644 --- a/apps/products-feed/src/modules/metadata-cache/cache-configurator.ts +++ b/apps/products-feed/src/modules/metadata-cache/cache-configurator.ts @@ -1,9 +1,13 @@ import { SettingsManager } from "@saleor/app-sdk/settings-manager"; +import { z } from "zod"; export class CacheConfigurator { private metadataKeyPrefix = "cursor-cache-"; - constructor(private metadataManager: SettingsManager, private saleorApiUrl: string) {} + constructor( + private metadataManager: SettingsManager, + private saleorApiUrl: string, + ) {} private constructKey(channel: string) { return this.metadataKeyPrefix + channel; @@ -16,7 +20,7 @@ export class CacheConfigurator { } try { - return JSON.parse(data); + return z.array(z.string()).parse(JSON.parse(data)); } catch (e) { throw new Error("Invalid metadata value, can't be parsed"); } diff --git a/apps/search/package.json b/apps/search/package.json index a02e851..aa0a977 100644 --- a/apps/search/package.json +++ b/apps/search/package.json @@ -52,6 +52,7 @@ "@graphql-codegen/typescript-operations": "4.0.1", "@graphql-codegen/typescript-urql": "3.7.3", "@graphql-typed-document-node/core": "3.2.0", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "@vitejs/plugin-react": "4.0.4", diff --git a/apps/search/reset.d.ts b/apps/search/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/search/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/search/src/lib/useWebhooksStatus.tsx b/apps/search/src/lib/useWebhooksStatus.tsx index 80eda6f..1b60d1c 100644 --- a/apps/search/src/lib/useWebhooksStatus.tsx +++ b/apps/search/src/lib/useWebhooksStatus.tsx @@ -7,7 +7,9 @@ export const useWebhooksStatus = () => { const fetch: typeof window.fetch = useAuthenticatedFetch(); const fetchFn = useCallback(() => { - return fetch("/api/webhooks-status").then((resp) => resp.json()); + return fetch("/api/webhooks-status").then( + (resp) => resp.json() as unknown as WebhooksStatusResponse, + ); /** * fetch from SDK is not wrapped with memo todo */ diff --git a/apps/search/src/modules/configuration/configuration.ts b/apps/search/src/modules/configuration/configuration.ts index 2323d25..198c1c3 100644 --- a/apps/search/src/modules/configuration/configuration.ts +++ b/apps/search/src/modules/configuration/configuration.ts @@ -27,7 +27,7 @@ export class AppConfig { }, }; - constructor(initialData?: AppConfigRootSchemaFields) { + constructor(initialData?: AppConfigRootSchemaFields | unknown) { if (initialData) { this.rootData = AppConfigRootSchema.parse(initialData); } diff --git a/apps/search/src/test/handlers/webhooks-status-handler.test.ts b/apps/search/src/test/handlers/webhooks-status-handler.test.ts index 9527dc8..7cf2a58 100644 --- a/apps/search/src/test/handlers/webhooks-status-handler.test.ts +++ b/apps/search/src/test/handlers/webhooks-status-handler.test.ts @@ -1,4 +1,4 @@ -import { NextProtectedApiHandler } from "@saleor/app-sdk/handlers/next"; +import { NextProtectedApiHandler, ProtectedHandlerContext } from "@saleor/app-sdk/handlers/next"; import { SettingsManager } from "@saleor/app-sdk/settings-manager"; import { createMocks } from "node-mocks-http"; import { Client, OperationResult } from "urql"; @@ -8,11 +8,12 @@ import { IWebhookActivityTogglerService } from "../../domain/WebhookActivityTogg import { SearchProvider } from "../../lib/searchProvider"; import { webhooksStatusHandlerFactory } from "../../pages/api/webhooks-status"; import { AppConfig } from "../../modules/configuration/configuration"; +import { NextApiRequest, NextApiResponse } from "next"; /** * Context provided from ProtectedApiHandler to handler body */ -const mockWebhookContext = { +const mockWebhookContext: ProtectedHandlerContext = { authData: { appId: "app-id", domain: "domain.saleor.io", @@ -20,6 +21,10 @@ const mockWebhookContext = { saleorApiUrl: "https://domain.saleor.io/graphql", }, baseUrl: "localhost:3000", + user: { + email: "", + userPermissions: [], + }, }; const appWebhooksResponseData: Pick, "data"> = { @@ -90,6 +95,7 @@ describe("webhooksStatusHandler", () => { it("Disables webhooks if Algolia settings are not saved in Saleor Metadata", async function () { const { req, res } = createMocks({}); + // @ts-expect-error - mock doesnt contain next-specific fields await handler(req, res, mockWebhookContext); expect(webhooksTogglerServiceMock.disableOwnWebhooks).toHaveBeenCalled(); @@ -113,6 +119,7 @@ describe("webhooksStatusHandler", () => { const { req, res } = createMocks({}); + // @ts-expect-error - mock doesnt contain next-specific fields await handler(req, res, mockWebhookContext); expect(webhooksTogglerServiceMock.disableOwnWebhooks).toHaveBeenCalled(); diff --git a/apps/segment/package.json b/apps/segment/package.json index 3e0d956..f4f6e93 100644 --- a/apps/segment/package.json +++ b/apps/segment/package.json @@ -54,6 +54,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "eslint": "8.46.0", diff --git a/apps/segment/reset.d.ts b/apps/segment/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/segment/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/segment/src/modules/configuration/app-config.ts b/apps/segment/src/modules/configuration/app-config.ts index 17b22c6..d64e929 100644 --- a/apps/segment/src/modules/configuration/app-config.ts +++ b/apps/segment/src/modules/configuration/app-config.ts @@ -4,7 +4,7 @@ import { RootConfig } from "./schemas/root-config.schema"; export class AppConfig { private rootData: RootConfig.Shape = null; - constructor(initialData?: RootConfig.Shape) { + constructor(initialData?: RootConfig.Shape | unknown) { if (initialData) { this.rootData = RootConfig.Schema.parse(initialData); } diff --git a/apps/slack/package.json b/apps/slack/package.json index 68fcca9..3b289d1 100644 --- a/apps/slack/package.json +++ b/apps/slack/package.json @@ -45,6 +45,7 @@ "@graphql-codegen/typescript-operations": "4.0.1", "@graphql-codegen/typescript-urql": "3.7.3", "@graphql-typed-document-node/core": "3.2.0", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "@typescript-eslint/eslint-plugin": "^5.36.2", diff --git a/apps/slack/reset.d.ts b/apps/slack/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/slack/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/apps/slack/src/hooks/useAppApi.ts b/apps/slack/src/hooks/useAppApi.ts index 786bc0e..9e22a0d 100644 --- a/apps/slack/src/hooks/useAppApi.ts +++ b/apps/slack/src/hooks/useAppApi.ts @@ -40,7 +40,7 @@ export const useAppApi = ({ url, options, skip }: UseFetchProps) => { const json = await res.json(); - setData(json); + setData(json as D); } catch (e) { setError(e as unknown); } finally { diff --git a/apps/taxes/package.json b/apps/taxes/package.json index bde127a..2cf3d55 100644 --- a/apps/taxes/package.json +++ b/apps/taxes/package.json @@ -55,6 +55,7 @@ "@graphql-typed-document-node/core": "3.2.0", "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "@vitejs/plugin-react": "4.0.4", diff --git a/apps/taxes/reset.d.ts b/apps/taxes/reset.d.ts new file mode 100644 index 0000000..e186b1f --- /dev/null +++ b/apps/taxes/reset.d.ts @@ -0,0 +1 @@ +import "@total-typescript/ts-reset"; \ No newline at end of file diff --git a/packages/e2e/package.json b/packages/e2e/package.json index 6c482f3..30b262e 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -10,6 +10,7 @@ "devDependencies": { "@playwright/test": "^1.35.1", "@saleor/app-sdk": "0.43.1", + "@total-typescript/ts-reset": "^0.5.1", "dotenv": "^16.3.1", "eslint-config-saleor": "workspace:*", "zod": "3.21.4" diff --git a/packages/eslint-config-saleor/package.json b/packages/eslint-config-saleor/package.json index 14245c0..95f28e9 100644 --- a/packages/eslint-config-saleor/package.json +++ b/packages/eslint-config-saleor/package.json @@ -2,6 +2,7 @@ "name": "eslint-config-saleor", "version": "0.4.5", "devDependencies": { + "@total-typescript/ts-reset": "^0.5.1", "eslint": "8.46.0", "eslint-config-next": "13.4.8", "eslint-config-prettier": "8.8.0", diff --git a/packages/react-hook-form-macaw/package.json b/packages/react-hook-form-macaw/package.json index 38a0cf3..31c8fb7 100644 --- a/packages/react-hook-form-macaw/package.json +++ b/packages/react-hook-form-macaw/package.json @@ -21,6 +21,7 @@ "@storybook/react": "^7.0.12", "@storybook/react-vite": "^7.0.12", "@storybook/testing-library": "^0.0.14-next.2", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "@vanilla-extract/vite-plugin": "^3.8.1", diff --git a/packages/shared/package.json b/packages/shared/package.json index 168b424..ed9dbcc 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -17,6 +17,7 @@ "@material-ui/lab": "4.0.0-alpha.61", "@saleor/app-sdk": "0.43.1", "@saleor/macaw-ui": "0.8.0-pre.127", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "@types/semver": "^7.5.0", diff --git a/packages/trpc/package.json b/packages/trpc/package.json index 0df251f..9a20c4b 100644 --- a/packages/trpc/package.json +++ b/packages/trpc/package.json @@ -6,6 +6,7 @@ }, "devDependencies": { "@saleor/app-sdk": "0.41.1", + "@total-typescript/ts-reset": "^0.5.1", "eslint": "8.46.0", "eslint-config-saleor": "workspace:*", "next": "13.4.8", diff --git a/packages/ui/package.json b/packages/ui/package.json index 8150a0e..65a44b3 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -11,6 +11,7 @@ "devDependencies": { "@saleor/app-sdk": "0.43.1", "@saleor/macaw-ui": "0.8.0-pre.127", + "@total-typescript/ts-reset": "^0.5.1", "@types/react": "18.2.5", "@types/react-dom": "18.2.5", "eslint-config-saleor": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 781c002..1f95d22 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -176,6 +176,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/qs': specifier: ^6.9.7 version: 6.9.7 @@ -312,6 +315,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/mailchimp__mailchimp_marketing': specifier: ^3.0.7 version: 3.0.7 @@ -442,6 +448,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/dot-object': specifier: ^2.1.2 version: 2.1.2 @@ -605,6 +614,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/html-to-text': specifier: ^9.0.0 version: 9.0.0 @@ -741,6 +753,9 @@ importers: '@graphql-typed-document-node/core': specifier: 3.2.0 version: 3.2.0(graphql@16.7.1) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -868,6 +883,9 @@ importers: '@graphql-typed-document-node/core': specifier: 3.2.0 version: 3.2.0(graphql@16.7.1) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1025,6 +1043,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1158,6 +1179,9 @@ importers: '@graphql-typed-document-node/core': specifier: 3.2.0 version: 3.2.0(graphql@16.7.1) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1309,6 +1333,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1427,6 +1454,9 @@ importers: '@graphql-typed-document-node/core': specifier: 3.2.0 version: 3.2.0(graphql@16.7.1) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1584,6 +1614,9 @@ importers: '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1611,6 +1644,9 @@ importers: '@saleor/app-sdk': specifier: 0.43.1 version: 0.43.1(graphql@16.7.1)(next@13.4.8)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 dotenv: specifier: ^16.3.1 version: 16.3.1 @@ -1623,6 +1659,9 @@ importers: packages/eslint-config-saleor: devDependencies: + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 eslint: specifier: 8.46.0 version: 8.46.0 @@ -1681,6 +1720,9 @@ importers: '@storybook/testing-library': specifier: ^0.0.14-next.2 version: 0.0.14-next.2 + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1748,6 +1790,9 @@ importers: '@saleor/macaw-ui': specifier: 0.8.0-pre.127 version: 0.8.0-pre.127(@types/react-dom@18.2.5)(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -1821,6 +1866,9 @@ importers: '@saleor/app-sdk': specifier: 0.43.1 version: 0.43.1(graphql@16.7.1)(next@13.4.8)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 eslint: specifier: 8.46.0 version: 8.46.0 @@ -1849,6 +1897,9 @@ importers: '@saleor/macaw-ui': specifier: 0.8.0-pre.127 version: 0.8.0-pre.127(@types/react-dom@18.2.5)(@types/react@18.2.5)(react-dom@18.2.0)(react@18.2.0) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 '@types/react': specifier: 18.2.5 version: 18.2.5 @@ -10675,6 +10726,10 @@ packages: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} + /@total-typescript/ts-reset@0.5.1: + resolution: {integrity: sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==} + dev: true + /@trpc/client@10.34.0(@trpc/server@10.34.0): resolution: {integrity: sha512-nqtDTIqSY/9syo2EjSy4WWWXPU9GsamEh9Tsg698gLAh1nhgFc5+/YYeb+Ne1pbvWGZ5/3t9Dcz3h4wMyyJ9gQ==} peerDependencies: