From 95baf4dbb46739b7ab50a623f48135cc4b4aa663 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Tue, 25 Nov 2025 08:48:26 +0100 Subject: [PATCH] Make stripe available on prod --- apps/api/{ => docs}/VITEST_MIGRATION.md | 0 apps/api/package.json | 2 +- apps/api/src/config.ts | 18 +++++-- apps/api/src/middlewares/middleware.ts | 2 +- apps/api/src/secrets.ts | 23 +++++--- apps/main/.env.production | 2 +- pnpm-lock.yaml | 70 +++---------------------- 7 files changed, 43 insertions(+), 74 deletions(-) rename apps/api/{ => docs}/VITEST_MIGRATION.md (100%) diff --git a/apps/api/VITEST_MIGRATION.md b/apps/api/docs/VITEST_MIGRATION.md similarity index 100% rename from apps/api/VITEST_MIGRATION.md rename to apps/api/docs/VITEST_MIGRATION.md diff --git a/apps/api/package.json b/apps/api/package.json index 1f65b5e..049f035 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -33,7 +33,7 @@ "multer": "^2.0.2", "nodemailer": "^7.0.4", "stream-chat": "^9.8.0", - "stripe": "^19.2.0", + "stripe": "^20.0.0", "ts-node": "^10.9.2" }, "devDependencies": { diff --git a/apps/api/src/config.ts b/apps/api/src/config.ts index f5c0926..d8e4735 100644 --- a/apps/api/src/config.ts +++ b/apps/api/src/config.ts @@ -55,6 +55,17 @@ export function createConfig(secrets?: Secrets): AppConfig { // In test mode, use environment variables directly instead of secrets const isTestMode = NODE_ENV === "test"; + const isStagingMode = NODE_ENV === "staging"; + const streamChatApiSecret = isStagingMode + ? secrets!.streamChatApiSecretStaging + : secrets!.streamChatApiSecret; + const stripeSecretKey = isStagingMode + ? secrets!.stripeSecretKeyStaging + : secrets!.stripeSecretKey; + const stripeWebhookSecret = isStagingMode + ? secrets!.stripeWebhookSecretStaging + : secrets!.stripeWebhookSecret; + // Base configuration const baseConfig: AppConfig = { NODE_ENV, @@ -70,15 +81,16 @@ export function createConfig(secrets?: Secrets): AppConfig { ? validateEnvVar("SUPABASE_CA_CERT", process.env.SUPABASE_CA_CERT) : secrets!.supabaseCaCert, STREAM_CHAT_API_KEY: validateEnvVar("STREAM_CHAT_API_KEY", process.env.STREAM_CHAT_API_KEY), + // Env dependent STREAM_CHAT_API_SECRET: isTestMode ? validateEnvVar("STREAM_CHAT_API_SECRET", process.env.STREAM_CHAT_API_SECRET) - : secrets!.streamChatApiSecret, + : streamChatApiSecret, STRIPE_SECRET_KEY: isTestMode ? validateEnvVar("STRIPE_SECRET_KEY", process.env.STRIPE_SECRET_KEY) - : secrets!.stripeSecretKey, + : stripeSecretKey, STRIPE_WEBHOOK_SECRET: isTestMode ? validateEnvVar("STRIPE_WEBHOOK_SECRET", process.env.STRIPE_WEBHOOK_SECRET) - : secrets!.stripeWebhookSecret, + : stripeWebhookSecret, EMAIL_USER: validateEnvVar("EMAIL_USER", process.env.EMAIL_USER), EMAIL_CLIENT_ID: validateEnvVar("EMAIL_CLIENT_ID", process.env.EMAIL_CLIENT_ID), EMAIL_CLIENT_SECRET: isTestMode diff --git a/apps/api/src/middlewares/middleware.ts b/apps/api/src/middlewares/middleware.ts index caff54f..3625e91 100644 --- a/apps/api/src/middlewares/middleware.ts +++ b/apps/api/src/middlewares/middleware.ts @@ -194,7 +194,7 @@ export class MiddlewareManager { const stripeMiddleware = createMiddleware(async (c: Context, next: Next) => { const stripe = new Stripe(config.STRIPE_SECRET_KEY || "", { - apiVersion: "2025-10-29.clover", + apiVersion: "2025-11-17.clover", }); c.set("stripe", stripe); await next(); diff --git a/apps/api/src/secrets.ts b/apps/api/src/secrets.ts index f458c3d..4a69b8e 100644 --- a/apps/api/src/secrets.ts +++ b/apps/api/src/secrets.ts @@ -21,13 +21,18 @@ export type Secrets = { supabaseServiceRoleKey: string; supabaseConnectionString: string; supabaseCaCert: string; - streamChatApiSecret: string; - stripeSecretKey: string; - stripeWebhookSecret: string; emailClientSecret: string; emailRefreshToken: string; r2AccessKeyId: string; r2SecretAccessKey: string; + // Env dependent + streamChatApiSecret: string; + stripeSecretKey: string; + stripeWebhookSecret: string; + // Staging + streamChatApiSecretStaging: string; + stripeSecretKeyStaging: string; + stripeWebhookSecretStaging: string; }; /** @@ -39,13 +44,19 @@ export async function loadSecrets(): Promise { supabaseServiceRoleKey: await fetchSecret("supabase-service-role-key"), supabaseConnectionString: await fetchSecret("supabase-connection-string"), supabaseCaCert: await fetchSecret("supabase-ca-cert"), - streamChatApiSecret: await fetchSecret("stream-chat-api-secret"), - stripeSecretKey: await fetchSecret("stripe-secret-key"), - stripeWebhookSecret: await fetchSecret("stripe-webhook-secret"), emailClientSecret: await fetchSecret("email-client-secret"), emailRefreshToken: await fetchSecret("email-refresh-token"), r2AccessKeyId: await fetchSecret("r2-access-key-id"), r2SecretAccessKey: await fetchSecret("r2-secret-access-key"), + // Env dependent + // Staging + streamChatApiSecretStaging: await fetchSecret("stream-chat-api-secret-staging"), + stripeSecretKeyStaging: await fetchSecret("stripe-secret-key-staging"), + stripeWebhookSecretStaging: await fetchSecret("stripe-webhook-secret-staging"), + // Production + streamChatApiSecret: await fetchSecret("stream-chat-api-secret"), + stripeSecretKey: await fetchSecret("stripe-secret-key"), + stripeWebhookSecret: await fetchSecret("stripe-webhook-secret"), }; return secrets; } diff --git a/apps/main/.env.production b/apps/main/.env.production index 68144f6..5119db4 100644 --- a/apps/main/.env.production +++ b/apps/main/.env.production @@ -6,7 +6,7 @@ VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFz VITE_SUPABASE_ID=mhcafqvzbrrwvahpvvzd VITE_STREAM_CHAT_API_KEY="v4yf8rs94aa8" -VITE_STRIPE_PUBLISHABLE_KEY=pk_test_51SPKLPAto3YQ7YhIrM5ViAUXWuSwKJeHyOyOINVg9cnwxxOcbMlyhxQcDYWDSLNQJukafxbc7kqpkGI82lFezaiM00rgcALKB0 +VITE_STRIPE_PUBLISHABLE_KEY=pk_live_51Qc159AmcXPHW4mTHUTW6it2mdZ3KQTxZGXZ188DKpXuXgpirUWOj24dnb7DzbcEAu45nU1S5k66Nm4liY3IlGOW00pndRsgUM VITE_STRIPE_STANDARD_MONTHLY_PRICE_ID=price_1SPr3qAto3YQ7YhIALNeFBva VITE_API_URL=https://xablo-api-636270553187.europe-west1.run.app \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdbcfc4..822cd74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,7 +35,7 @@ importers: version: 1.19.6(hono@4.10.4) '@supabase/stripe-sync-engine': specifier: ^0.45.0 - version: 0.45.0(stripe@19.3.0(@types/node@20.19.23)) + version: 0.45.0(stripe@20.0.0(@types/node@20.19.23)) '@supabase/supabase-js': specifier: ^2.49.4 version: 2.76.1 @@ -76,8 +76,8 @@ importers: specifier: ^9.8.0 version: 9.24.0 stripe: - specifier: ^19.2.0 - version: 19.3.0(@types/node@20.19.23) + specifier: ^20.0.0 + version: 20.0.0(@types/node@20.19.23) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.19.23)(typescript@5.9.3) @@ -350,9 +350,6 @@ importers: stream-chat-react: specifier: ^13.1.0 version: 13.9.0(@emoji-mart/data@1.2.1)(@types/react@19.0.10)(emoji-mart@5.6.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(stream-chat@9.24.0)(typescript@5.9.3) - three: - specifier: ^0.172.0 - version: 0.172.0 ts-pattern: specifier: ^5.6.2 version: 5.8.0 @@ -417,9 +414,6 @@ importers: '@types/react-dom': specifier: 19.0.4 version: 19.0.4(@types/react@19.0.10) - '@types/three': - specifier: ^0.181.0 - version: 0.181.0 '@typescript-eslint/eslint-plugin': specifier: ^7.0.2 version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) @@ -1298,9 +1292,6 @@ packages: '@date-fns/tz@1.4.1': resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} - '@dimforge/rapier3d-compat@0.12.0': - resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} - '@emnapi/runtime@1.6.0': resolution: {integrity: sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==} @@ -3970,9 +3961,6 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@tweenjs/tween.js@23.1.3': - resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} - '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -4104,12 +4092,6 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - '@types/stats.js@0.17.4': - resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} - - '@types/three@0.181.0': - resolution: {integrity: sha512-MLF1ks8yRM2k71D7RprFpDb9DOX0p22DbdPqT/uAkc6AtQXjxWCVDjCy23G9t1o8HcQPk7woD2NIyiaWcWPYmA==} - '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} @@ -4125,9 +4107,6 @@ packages: '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - '@types/webxr@0.5.24': - resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} - '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -4377,9 +4356,6 @@ packages: '@vitest/utils@4.0.8': resolution: {integrity: sha512-pdk2phO5NDvEFfUTxcTP8RFYjVj/kfLSPIN5ebP2Mu9kcIMeAQTbknqcFEyBcC4z2pJlJI9aS5UQjcYfhmKAow==} - '@webgpu/types@0.1.66': - resolution: {integrity: sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA==} - abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} deprecated: Use your platform's native atob() and btoa() methods instead @@ -6541,9 +6517,6 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - meshoptimizer@0.22.0: - resolution: {integrity: sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==} - micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -7941,8 +7914,8 @@ packages: strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - stripe@19.3.0: - resolution: {integrity: sha512-3MbqRkw5LXb4LWP1LgIEYxUAYhYDDU5pcHZj4Xha6VWPnN1wrUmQ7Htsgm8wR584s0hn1aQg1lYD0Hi+F37E5g==} + stripe@20.0.0: + resolution: {integrity: sha512-EaZeWpbJOCcDytdjKSwdrL5BxzbDGNueiCfHjHXlPdBQvLqoxl6AAivC35SPzTmVXJb5duXQlXFGS45H0+e6Gg==} engines: {node: '>=16'} peerDependencies: '@types/node': '>=16' @@ -8032,9 +8005,6 @@ packages: thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} - three@0.172.0: - resolution: {integrity: sha512-6HMgMlzU97MsV7D/tY8Va38b83kz8YJX+BefKjspMNAv0Vx6dxMogHOrnRl/sbMIs3BPUKijPqDqJ/+UwJbIow==} - through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -9769,8 +9739,6 @@ snapshots: '@date-fns/tz@1.4.1': {} - '@dimforge/rapier3d-compat@0.12.0': {} - '@emnapi/runtime@1.6.0': dependencies: tslib: 2.8.1 @@ -12683,11 +12651,11 @@ snapshots: '@supabase/node-fetch': 2.6.15 tslib: 2.8.1 - '@supabase/stripe-sync-engine@0.45.0(stripe@19.3.0(@types/node@20.19.23))': + '@supabase/stripe-sync-engine@0.45.0(stripe@20.0.0(@types/node@20.19.23))': dependencies: pg: 8.16.3 pg-node-migrations: 0.0.8 - stripe: 19.3.0(@types/node@20.19.23) + stripe: 20.0.0(@types/node@20.19.23) yesql: 7.0.0 transitivePeerDependencies: - pg-native @@ -12951,8 +12919,6 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@tweenjs/tween.js@23.1.3': {} - '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -13110,18 +13076,6 @@ snapshots: '@types/stack-utils@2.0.3': {} - '@types/stats.js@0.17.4': {} - - '@types/three@0.181.0': - dependencies: - '@dimforge/rapier3d-compat': 0.12.0 - '@tweenjs/tween.js': 23.1.3 - '@types/stats.js': 0.17.4 - '@types/webxr': 0.5.24 - '@webgpu/types': 0.1.66 - fflate: 0.8.2 - meshoptimizer: 0.22.0 - '@types/tough-cookie@4.0.5': {} '@types/trusted-types@2.0.7': @@ -13133,8 +13087,6 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@types/webxr@0.5.24': {} - '@types/whatwg-mimetype@3.0.2': {} '@types/ws@8.18.1': @@ -13465,8 +13417,6 @@ snapshots: '@vitest/pretty-format': 4.0.8 tinyrainbow: 3.0.3 - '@webgpu/types@0.1.66': {} - abab@2.0.6: {} abort-controller@3.0.0: @@ -16294,8 +16244,6 @@ snapshots: merge2@1.4.1: {} - meshoptimizer@0.22.0: {} - micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.2.0 @@ -18033,7 +17981,7 @@ snapshots: dependencies: js-tokens: 9.0.1 - stripe@19.3.0(@types/node@20.19.23): + stripe@20.0.0(@types/node@20.19.23): dependencies: qs: 6.14.0 optionalDependencies: @@ -18127,8 +18075,6 @@ snapshots: dependencies: real-require: 0.2.0 - three@0.172.0: {} - through@2.3.8: {} tiny-async-pool@2.1.0: {}