diff --git a/apps/dev-tool/package.json b/apps/dev-tool/package.json index cd94caa5b..9e12d89cf 100644 --- a/apps/dev-tool/package.json +++ b/apps/dev-tool/package.json @@ -27,7 +27,7 @@ "@kit/shared": "workspace:*", "@kit/tsconfig": "workspace:*", "@kit/ui": "workspace:*", - "@tailwindcss/postcss": "^4.1.18", + "@tailwindcss/postcss": "^4.2.1", "@types/node": "catalog:", "@types/nodemailer": "catalog:", "@types/react": "catalog:", diff --git a/apps/e2e/package.json b/apps/e2e/package.json index 679c8b759..78ef088c1 100644 --- a/apps/e2e/package.json +++ b/apps/e2e/package.json @@ -14,7 +14,7 @@ "@playwright/test": "^1.58.2", "@supabase/supabase-js": "catalog:", "@types/node": "catalog:", - "dotenv": "17.2.4", + "dotenv": "17.3.1", "node-html-parser": "^7.0.2", "totp-generator": "^2.0.1" } diff --git a/apps/web/app/home/(user)/billing/_lib/server/user-billing.service.ts b/apps/web/app/home/(user)/billing/_lib/server/user-billing.service.ts index 0fba68f44..7ba77b38b 100644 --- a/apps/web/app/home/(user)/billing/_lib/server/user-billing.service.ts +++ b/apps/web/app/home/(user)/billing/_lib/server/user-billing.service.ts @@ -118,7 +118,7 @@ class UserBillingService { `Checkout session not created due to an error`, ); - throw new Error(`Failed to create a checkout session`); + throw new Error(`Failed to create a checkout session`, { cause: error }); } } @@ -177,6 +177,7 @@ class UserBillingService { throw new Error( `Encountered an error creating the Billing Portal session`, + { cause: error }, ); } diff --git a/apps/web/app/home/[account]/billing/_lib/server/team-billing.service.ts b/apps/web/app/home/[account]/billing/_lib/server/team-billing.service.ts index 93cb17ea8..af435f4ba 100644 --- a/apps/web/app/home/[account]/billing/_lib/server/team-billing.service.ts +++ b/apps/web/app/home/[account]/billing/_lib/server/team-billing.service.ts @@ -133,7 +133,7 @@ class TeamBillingService { `Error creating the checkout session`, ); - throw new Error(`Checkout not created`); + throw new Error(`Checkout not created`, { cause: error }); } } @@ -234,7 +234,7 @@ class TeamBillingService { `Billing Portal session was not created`, ); - throw new Error(`Error creating Billing Portal`); + throw new Error(`Error creating Billing Portal`, { cause: error }); } } diff --git a/apps/web/package.json b/apps/web/package.json index 946fe0c64..14b5a6f0b 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -69,7 +69,7 @@ "react-hook-form": "catalog:", "react-i18next": "catalog:", "recharts": "2.15.3", - "tailwind-merge": "^3.4.0", + "tailwind-merge": "^3.5.0", "tw-animate-css": "catalog:", "urlpattern-polyfill": "^10.1.0", "zod": "catalog:" diff --git a/package.json b/package.json index 15466a39a..7043f0213 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next-supabase-saas-kit-turbo", - "version": "2.24.0", + "version": "2.24.1", "private": true, "sideEffects": false, "engines": { @@ -45,10 +45,10 @@ }, "devDependencies": { "@manypkg/cli": "^0.25.1", - "@turbo/gen": "^2.7.6", + "@turbo/gen": "^2.8.11", "cross-env": "^10.0.0", "prettier": "^3.8.1", - "turbo": "2.8.5", + "turbo": "2.8.11", "typescript": "^5.9.3" } } diff --git a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts index 713a20845..e042d261f 100644 --- a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts +++ b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts @@ -101,7 +101,9 @@ export class LemonSqueezyBillingStrategyService implements BillingStrategyProvid 'Failed to create billing portal session', ); - throw new Error('Failed to create billing portal session'); + throw new Error('Failed to create billing portal session', { + cause: error, + }); } logger.info(ctx, 'Billing portal session created successfully'); @@ -138,7 +140,7 @@ export class LemonSqueezyBillingStrategyService implements BillingStrategyProvid 'Failed to cancel subscription', ); - throw new Error('Failed to cancel subscription'); + throw new Error('Failed to cancel subscription', { cause: error }); } logger.info(ctx, 'Subscription cancelled successfully'); diff --git a/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts b/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts index 72ac8d528..c95d96c65 100644 --- a/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts +++ b/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts @@ -174,7 +174,7 @@ export class StripeBillingStrategyService implements BillingStrategyProviderServ 'Failed to retrieve checkout session', ); - throw new Error('Failed to retrieve checkout session'); + throw new Error('Failed to retrieve checkout session', { cause: error }); } } @@ -218,7 +218,7 @@ export class StripeBillingStrategyService implements BillingStrategyProviderServ 'Failed to report usage', ); - throw new Error('Failed to report usage'); + throw new Error('Failed to report usage', { cause: error }); } return { @@ -277,7 +277,7 @@ export class StripeBillingStrategyService implements BillingStrategyProviderServ 'Failed to report usage', ); - throw new Error('Failed to report usage'); + throw new Error('Failed to report usage', { cause: error }); } } @@ -317,7 +317,7 @@ export class StripeBillingStrategyService implements BillingStrategyProviderServ } catch (error) { logger.error({ ...ctx, error }, 'Failed to update subscription'); - throw new Error('Failed to update subscription'); + throw new Error('Failed to update subscription', { cause: error }); } } @@ -357,7 +357,7 @@ export class StripeBillingStrategyService implements BillingStrategyProviderServ } catch (error) { logger.error({ ...ctx, error }, 'Failed to retrieve plan'); - throw new Error('Failed to retrieve plan'); + throw new Error('Failed to retrieve plan', { cause: error }); } } @@ -413,7 +413,7 @@ export class StripeBillingStrategyService implements BillingStrategyProviderServ } catch (error) { logger.error({ ...ctx, error }, 'Failed to retrieve subscription'); - throw new Error('Failed to retrieve subscription'); + throw new Error('Failed to retrieve subscription', { cause: error }); } } diff --git a/packages/billing/stripe/src/services/stripe-sdk.ts b/packages/billing/stripe/src/services/stripe-sdk.ts index 741482c98..0fb6aea60 100644 --- a/packages/billing/stripe/src/services/stripe-sdk.ts +++ b/packages/billing/stripe/src/services/stripe-sdk.ts @@ -2,7 +2,7 @@ import 'server-only'; import { StripeServerEnvSchema } from '../schema/stripe-server-env.schema'; -const STRIPE_API_VERSION = '2026-01-28.clover'; +const STRIPE_API_VERSION = '2026-02-25.clover'; /** * @description returns a Stripe instance diff --git a/packages/features/accounts/src/server/services/delete-personal-account.service.ts b/packages/features/accounts/src/server/services/delete-personal-account.service.ts index 012b91905..f0a8c489c 100644 --- a/packages/features/accounts/src/server/services/delete-personal-account.service.ts +++ b/packages/features/accounts/src/server/services/delete-personal-account.service.ts @@ -77,7 +77,7 @@ class DeletePersonalAccountService { 'Encountered an error deleting user', ); - throw new Error('Error deleting user'); + throw new Error('Error deleting user', { cause: error }); } } diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 1a8371f01..b7c653f56 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -37,7 +37,7 @@ "@kit/email-templates": "workspace:*", "@kit/prettier-config": "workspace:*", "@kit/tsconfig": "workspace:*", - "@modelcontextprotocol/sdk": "1.26.0", + "@modelcontextprotocol/sdk": "1.27.1", "@types/node": "catalog:", "postgres": "3.4.8", "tsup": "catalog:", diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index c49e95f36..99cfe6a5d 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -1,6 +1,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { resolveProjectRoot } from './resolve-root'; import { registerComponentsTools } from './tools/components'; import { registerDatabaseResources, @@ -22,30 +23,30 @@ import { registerKitStatusTool } from './tools/status/index'; import { registerKitTranslationsTools } from './tools/translations/index'; async function main() { - // Create server instance const server = new McpServer({ name: 'makerkit', version: '1.0.0', }); const transport = new StdioServerTransport(); + const rootPath = resolveProjectRoot(); - registerGetMigrationsTools(server); - registerKitStatusTool(server); - registerKitPrerequisitesTool(server); - registerKitEnvTools(server); - registerKitDevTools(server); - registerKitDbTools(server); - registerKitEmailsTools(server); - registerKitEmailTemplatesTools(server); - registerKitTranslationsTools(server); - registerDatabaseTools(server); - registerDatabaseResources(server); - registerComponentsTools(server); - registerScriptsTools(server); - registerRunChecksTool(server); - registerDepsUpgradeAdvisorTool(server); - registerPRDTools(server); + registerGetMigrationsTools(server, rootPath); + registerKitStatusTool(server, rootPath); + registerKitPrerequisitesTool(server, rootPath); + registerKitEnvTools(server, rootPath); + registerKitDevTools(server, rootPath); + registerKitDbTools(server, rootPath); + registerKitEmailsTools(server, rootPath); + registerKitEmailTemplatesTools(server, rootPath); + registerKitTranslationsTools(server, rootPath); + registerDatabaseTools(server, rootPath); + registerDatabaseResources(server, rootPath); + registerComponentsTools(server, rootPath); + registerScriptsTools(server, rootPath); + registerRunChecksTool(server, rootPath); + registerDepsUpgradeAdvisorTool(server, rootPath); + registerPRDTools(server, rootPath); registerPromptsSystem(server); await server.connect(transport); diff --git a/packages/mcp-server/src/lib/__tests__/process-utils.test.ts b/packages/mcp-server/src/lib/__tests__/process-utils.test.ts new file mode 100644 index 000000000..cff615aab --- /dev/null +++ b/packages/mcp-server/src/lib/__tests__/process-utils.test.ts @@ -0,0 +1,291 @@ +import { createServer } from 'node:net'; +import { afterAll, describe, expect, it } from 'vitest'; + +import { + IS_WINDOWS, + crossExecFileSync, + execFileAsync, + findProcessesByName, + getPortProcess, + killProcess, + spawnDetached, +} from '../process-utils'; + +const pidsToCleanup: number[] = []; + +afterAll(async () => { + for (const pid of pidsToCleanup) { + try { + await killProcess(pid); + } catch { + // already dead + } + } +}); + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +async function isCommandAvailable(cmd: string): Promise { + try { + await execFileAsync(cmd, ['--version']); + return true; + } catch { + return false; + } +} + +function sleep(ms: number) { + return new Promise((r) => setTimeout(r, ms)); +} + +// --------------------------------------------------------------------------- +// pnpm — the command that triggered this whole cross-platform fix. +// The MCP tools call pnpm for migrations, seeding, checks, and dev server. +// On Windows pnpm is a .cmd file that requires shell: true. +// --------------------------------------------------------------------------- + +describe('pnpm commands', () => { + it('pnpm --version (used by kit_prerequisites)', async () => { + const result = await execFileAsync('pnpm', ['--version']); + expect(result.stdout.trim()).toMatch(/^\d+\.\d+\.\d+/); + }); + + it('pnpm --version sync (used by migrations tool)', () => { + const result = crossExecFileSync('pnpm', ['--version'], { + encoding: 'utf8', + }); + + expect(String(result).trim()).toMatch(/^\d+\.\d+\.\d+/); + }); + + it('pnpm run with unknown script returns non-zero (used by run_checks)', async () => { + // run_checks calls: pnpm run