From 545d49bc170940268b4f4229ba31fdbc955babb7 Mon Sep 17 00:00:00 2001 From: Luis Fernando De Pombo <2381303+depombo@users.noreply.github.com> Date: Mon, 10 Nov 2025 19:35:44 -0800 Subject: [PATCH 1/5] CLI tool for syncing Stripe data to PostgreSQL --- packages/cli/README.md | 160 +++++++++++++++++++++++++ packages/cli/package.json | 56 +++++++++ packages/cli/scripts/stripe-trigger.sh | 43 +++++++ packages/cli/src/config.ts | 101 ++++++++++++++++ packages/cli/src/index.ts | 23 ++++ packages/cli/src/ngrok.ts | 49 ++++++++ packages/cli/src/server.ts | 79 ++++++++++++ packages/cli/src/stripe-webhook.ts | 72 +++++++++++ packages/cli/src/sync-command.ts | 102 ++++++++++++++++ packages/cli/tsconfig.json | 20 ++++ 10 files changed, 705 insertions(+) create mode 100644 packages/cli/README.md create mode 100644 packages/cli/package.json create mode 100755 packages/cli/scripts/stripe-trigger.sh create mode 100644 packages/cli/src/config.ts create mode 100644 packages/cli/src/index.ts create mode 100644 packages/cli/src/ngrok.ts create mode 100644 packages/cli/src/server.ts create mode 100644 packages/cli/src/stripe-webhook.ts create mode 100644 packages/cli/src/sync-command.ts create mode 100644 packages/cli/tsconfig.json diff --git a/packages/cli/README.md b/packages/cli/README.md new file mode 100644 index 000000000..b97276211 --- /dev/null +++ b/packages/cli/README.md @@ -0,0 +1,160 @@ +# @supabase/stripe-sync-cli + +CLI tool for syncing Stripe data to PostgreSQL with real-time webhook streaming. + +## Features + +- ๐Ÿ”„ Real-time Stripe webhook streaming to PostgreSQL +- ๐Ÿš€ Automatic table creation and migrations +- ๐ŸŒ Built-in ngrok tunnel for local development +- ๐Ÿ” Secure webhook signature verification +- ๐Ÿงน Automatic cleanup on exit + +## Installation + +```bash +npm install -g @supabase/stripe-sync-cli +``` + +## Usage + +### Basic Command + +```bash +stripe-sync --database-url postgresql://user:password@localhost:5432/mydb +``` + +You'll be prompted for: +- Stripe API key (or set `STRIPE_API_KEY` env var) +- ngrok auth token (or set `NGROK_AUTH_TOKEN` env var) +- Postgres DATABASE_URL (or pass via `--database-url` flag) + +### Example Output + +``` +$ stripe-sync postgresql://user:password@localhost:5432/mydb +Creating tables............ โœ“ +Populating tables.......... โœ“ +Streaming live changes..... โ— [press Ctrl-C to abort] +``` + +### Command Options + +```bash +stripe-sync [options] + +Options: + --stripe-key Stripe API key (or STRIPE_API_KEY env) + --ngrok-token ngrok auth token (or NGROK_AUTH_TOKEN env) + --database-url Postgres DATABASE_URL (or DATABASE_URL env) + -h, --help Display help + -V, --version Display version +``` + +### Environment Variables + +Create a `.env` file in your project: + +```env +STRIPE_API_KEY=sk_test_... +NGROK_AUTH_TOKEN=your_ngrok_token +DATABASE_URL=postgresql://user:password@localhost:5432/mydb +``` + +Then run: + +```bash +stripe-sync +``` + +## How It Works + +1. **Creates Tables**: Runs database migrations to create Stripe schema tables +2. **Sets Up Tunnel**: Creates an ngrok tunnel to expose your local server +3. **Registers Webhook**: Creates a Stripe webhook endpoint listening to all events (`*`) +4. **Streams Changes**: Real-time syncing of all Stripe events to PostgreSQL + +The CLI automatically: +- Starts a Fastify server with `@supabase/stripe-sync-fastify` +- Creates an ngrok tunnel for webhook delivery +- Registers a Stripe webhook with all events enabled +- Cleans up webhook and tunnel on exit (Ctrl-C) + +## Prerequisites + +- Node.js >= 22.0.0 +- PostgreSQL database +- Stripe API key ([Get one here](https://dashboard.stripe.com/apikeys)) +- ngrok auth token ([Sign up here](https://dashboard.ngrok.com/signup)) + +## What Gets Synced + +The CLI syncs all Stripe objects supported by `@supabase/stripe-sync-engine`: + +- Customers +- Subscriptions & Subscription Schedules +- Invoices & Invoice Items +- Products & Prices +- Payment Intents & Payment Methods +- Charges & Refunds +- Disputes & Reviews +- And 20+ more object types + +## Next Steps / Roadmap + +### Backfill Command + +Backfill historical Stripe data for a specific time period: + +```bash +# Proposed usage (not yet implemented) +stripe-sync backfill --days 1 # Last 24 hours +stripe-sync backfill --days 7 # Last week +stripe-sync backfill --days 30 # Last month +``` + +This would: +1. Start the server +2. Call the `/sync` endpoint with date range filters +3. Display sync progress and results +4. Shut down after completion + +## Troubleshooting + +### "Database configuration is required" + +Make sure you have set `DATABASE_URL` either via: +- Command flag: `--database-url postgresql://...` +- Environment variable: `DATABASE_URL=postgresql://...` +- Interactive prompt will ask if not provided +- Start a local postgres instance with URL `postgresql://postgres:postgres@localhost:5432/app_db` using Docker by running the following command: + +```bash +docker run --name local-postgres \ + -e POSTGRES_USER=postgres \ + -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_DB=app_db \ + -p 5432:5432 \ + -d postgres:16 +``` +Feel free to query it manually using `docker exec -it local-postgres psql -U postgres -d app_db` + + +### "Failed to create ngrok tunnel" + +- Verify your ngrok auth token is valid +- Check if ngrok is blocked by your firewall +- Try running `ngrok config add-authtoken ` manually or go to the + +### "Stripe API key should start with 'sk_'" + +Make sure you're using a Secret Key (starts with `sk_`), not a Publishable Key (starts with `pk_`). + +## Related Packages + +- [`@supabase/stripe-sync-engine`](../sync-engine) - Core sync library +- [`@supabase/stripe-sync-fastify`](../fastify-app) - Fastify server for webhooks + +## License + +Apache-2.0 diff --git a/packages/cli/package.json b/packages/cli/package.json new file mode 100644 index 000000000..c54cff0e3 --- /dev/null +++ b/packages/cli/package.json @@ -0,0 +1,56 @@ +{ + "name": "@supabase/stripe-sync-cli", + "version": "0.0.0", + "description": "CLI to sync your stripe data to postgres", + "type": "module", + "exports": { + ".": { + "import": "./dist/index.js", + "require": "./dist/index.cjs" + } + }, + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "bin": { + "stripe-sync": "./dist/index.js" + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsup src/index.ts --format esm,cjs --dts --clean", + "dev": "tsx src/index.ts", + "lint": "eslint src", + "format": "prettier --check .", + "format:fix": "prettier --write .", + "stripe:trigger": "./scripts/stripe-trigger.sh" + }, + "keywords": [ + "stripe", + "webhook", + "cli", + "development", + "ngrok", + "sync" + ], + "dependencies": { + "@ngrok/ngrok": "^1.4.1", + "@supabase/stripe-sync-engine": "workspace:", + "@supabase/stripe-sync-fastify": "workspace:", + "chalk": "^5.3.0", + "commander": "^12.1.0", + "dotenv": "^16.4.7", + "inquirer": "^12.3.0" + }, + "devDependencies": { + "@types/inquirer": "^9.0.7", + "@types/node": "^22.10.2", + "fastify": "^5.6.2", + "stripe": "^17.7.0", + "tsx": "^4.19.2" + }, + "engines": { + "node": ">=22.0.0" + } +} diff --git a/packages/cli/scripts/stripe-trigger.sh b/packages/cli/scripts/stripe-trigger.sh new file mode 100755 index 000000000..05a7eb357 --- /dev/null +++ b/packages/cli/scripts/stripe-trigger.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Load environment variables from .env file +if [ -f .env ]; then + export $(cat .env | grep -v '^#' | xargs) +fi + +# Check if STRIPE_API_KEY is set +if [ -z "$STRIPE_API_KEY" ]; then + echo "Error: STRIPE_API_KEY not found in .env file" + exit 1 +fi + +# Check if STRIPE_PROJECT_NAME is set +if [ -z "$STRIPE_PROJECT_NAME" ]; then + echo "Error: STRIPE_PROJECT_NAME not found in .env file" + exit 1 +fi + +# Check if an event type was provided +if [ -z "$1" ]; then + echo "Usage: ./stripe-trigger.sh " + echo "" + echo "Examples:" + echo " ./stripe-trigger.sh payment_intent.succeeded" + echo " ./stripe-trigger.sh customer.created" + echo " ./stripe-trigger.sh subscription.created" + echo "" + echo "Available events:" + docker run --rm \ + -e STRIPE_API_KEY \ + stripe/stripe-cli:latest \ + trigger --help + exit 1 +fi + +# Run Stripe CLI trigger with Docker using API key and project name +docker run --rm \ + -e STRIPE_API_KEY \ + stripe/stripe-cli:latest \ + --project-name "$STRIPE_PROJECT_NAME" \ + trigger "$@" \ + --api-key "$STRIPE_API_KEY" diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts new file mode 100644 index 000000000..6bb62a453 --- /dev/null +++ b/packages/cli/src/config.ts @@ -0,0 +1,101 @@ +import dotenv from 'dotenv' +import inquirer from 'inquirer' +import chalk from 'chalk' + +export interface Config { + stripeApiKey: string + ngrokAuthToken: string + databaseUrl: string +} + +export interface CliOptions { + stripeKey?: string + ngrokToken?: string + databaseUrl?: string +} + +/** + * Load configuration from .env file, environment variables, and interactive prompts. + * Values are masked with *** when prompting for sensitive information. + */ +export async function loadConfig(options: CliOptions): Promise { + // Load .env file + dotenv.config() + + const config: Partial = {} + + // Get Stripe API key + config.stripeApiKey = + options.stripeKey || + process.env.STRIPE_API_KEY || + process.env.STRIPE_SECRET_KEY || + '' + + // Get ngrok auth token + config.ngrokAuthToken = options.ngrokToken || process.env.NGROK_AUTH_TOKEN || '' + + // Get database URL + config.databaseUrl = options.databaseUrl || process.env.DATABASE_URL || '' + + // Prompt for missing required values + const questions: inquirer.QuestionCollection = [] + + if (!config.stripeApiKey) { + questions.push({ + type: 'password', + name: 'stripeApiKey', + message: 'Enter your Stripe API key:', + mask: '*', + validate: (input: string) => { + if (!input || input.trim() === '') { + return 'Stripe API key is required' + } + if (!input.startsWith('sk_')) { + return 'Stripe API key should start with "sk_"' + } + return true + }, + }) + } + + if (!config.ngrokAuthToken) { + questions.push({ + type: 'password', + name: 'ngrokAuthToken', + message: 'Enter your ngrok auth token:', + mask: '*', + validate: (input: string) => { + if (!input || input.trim() === '') { + return 'ngrok auth token is required' + } + return true + }, + }) + } + + if (!config.databaseUrl) { + questions.push({ + type: 'password', + name: 'databaseUrl', + message: 'Enter your Postgres DATABASE_URL:', + mask: '*', + validate: (input: string) => { + if (!input || input.trim() === '') { + return 'DATABASE_URL is required' + } + if (!input.startsWith('postgres://') && !input.startsWith('postgresql://')) { + return 'DATABASE_URL should start with "postgres://" or "postgresql://"' + } + return true + }, + }) + } + + if (questions.length > 0) { + console.log(chalk.yellow('\nMissing required configuration. Please provide:')) + const answers = await inquirer.prompt(questions) + Object.assign(config, answers) + } + + return config as Config +} diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts new file mode 100644 index 000000000..bb967f738 --- /dev/null +++ b/packages/cli/src/index.ts @@ -0,0 +1,23 @@ +#!/usr/bin/env node + +import { Command } from 'commander' +import { syncCommand } from './sync-command' + +const program = new Command() + +program + .name('stripe-sync') + .description('CLI tool for syncing Stripe data to PostgreSQL') + .version('0.0.0') + .option('--stripe-key ', 'Stripe API key (or STRIPE_API_KEY env)') + .option('--ngrok-token ', 'ngrok auth token (or NGROK_AUTH_TOKEN env)') + .option('--database-url ', 'Postgres DATABASE_URL (or DATABASE_URL env)') + .action(async (options) => { + await syncCommand({ + stripeKey: options.stripeKey, + ngrokToken: options.ngrokToken, + databaseUrl: options.databaseUrl, + }) + }) + +program.parse() diff --git a/packages/cli/src/ngrok.ts b/packages/cli/src/ngrok.ts new file mode 100644 index 000000000..0c077be6a --- /dev/null +++ b/packages/cli/src/ngrok.ts @@ -0,0 +1,49 @@ +import ngrok from '@ngrok/ngrok' +import chalk from 'chalk' + +export interface NgrokTunnel { + url: string + close: () => Promise +} + +/** + * Create an ngrok tunnel to expose the local server to the internet. + * @param port - The local port to expose + * @param authToken - ngrok authentication token + * @returns The tunnel URL and a close function + */ +export async function createTunnel( + port: number, + authToken: string +): Promise { + try { + console.log(chalk.blue(`\nCreating ngrok tunnel for port ${port}...`)) + + const listener = await ngrok.forward({ + addr: port, + authtoken: authToken, + }) + + const url = listener.url() + if (!url) { + throw new Error('Failed to get ngrok URL') + } + + console.log(chalk.green(`โœ“ ngrok tunnel created: ${url}`)) + + return { + url, + close: async () => { + console.log(chalk.blue('\nClosing ngrok tunnel...')) + await listener.close() + console.log(chalk.green('โœ“ ngrok tunnel closed')) + }, + } + } catch (error) { + console.error(chalk.red('\nFailed to create ngrok tunnel:')) + if (error instanceof Error) { + console.error(chalk.red(error.message)) + } + throw error + } +} diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts new file mode 100644 index 000000000..31cdda01d --- /dev/null +++ b/packages/cli/src/server.ts @@ -0,0 +1,79 @@ +import { FastifyInstance } from 'fastify' +import chalk from 'chalk' +import { createServer } from '@supabase/stripe-sync-fastify/dist/src/app.js' +import { runMigrations } from '@supabase/stripe-sync-engine' + +export interface ServerInstance { + port: number + apiKey: string + close: () => Promise +} + +/** + * Start the Fastify server for handling Stripe webhooks. + * Sets up environment variables required by @supabase/stripe-sync-fastify. + * + * @param databaseUrl - Postgres connection string + * @param stripeApiKey - Stripe secret API key + * @param stripeWebhookSecret - Webhook signing secret from Stripe + * @param port - Port to listen on (default: 3000) + * @returns Server instance with port, apiKey, and close function + */ +export async function startServer( + databaseUrl: string, + stripeApiKey: string, + stripeWebhookSecret: string, + port: number = 3000 +): Promise { + try { + console.log(chalk.blue(`\nStarting Fastify server on port ${port}...`)) + + // Generate a random API key for this session + const apiKey = `dev-${Math.random().toString(36).substring(2, 15)}` + + // Set required environment variables for fastify-app + process.env.DATABASE_URL = databaseUrl + process.env.STRIPE_SECRET_KEY = stripeApiKey + process.env.STRIPE_WEBHOOK_SECRET = stripeWebhookSecret + process.env.PORT = String(port) + process.env.API_KEY = apiKey + process.env.SCHEMA = process.env.SCHEMA || 'stripe' + process.env.STRIPE_API_VERSION = process.env.STRIPE_API_VERSION || '2020-08-27' + process.env.AUTO_EXPAND_LISTS = process.env.AUTO_EXPAND_LISTS || 'true' + process.env.BACKFILL_RELATED_ENTITIES = process.env.BACKFILL_RELATED_ENTITIES || 'true' + process.env.DISABLE_MIGRATIONS = 'false' // Always run migrations in dev + + // Run migrations first + console.log(chalk.blue('Running database migrations...')) + await runMigrations({ + databaseUrl, + schema: process.env.SCHEMA, + }) + console.log(chalk.green('โœ“ Migrations completed')) + + const app: FastifyInstance = await createServer({ + disableRequestLogging: false, + exposeDocs: false, + }) + + // Start listening + await app.listen({ port, host: '0.0.0.0' }) + console.log(chalk.green(`โœ“ Server listening on port ${port}`)) + + return { + port, + apiKey, + close: async () => { + console.log(chalk.blue('\nStopping server...')) + await app.close() + console.log(chalk.green('โœ“ Server stopped')) + }, + } + } catch (error) { + console.error(chalk.red('\nFailed to start server:')) + if (error instanceof Error) { + console.error(chalk.red(error.message)) + } + throw error + } +} diff --git a/packages/cli/src/stripe-webhook.ts b/packages/cli/src/stripe-webhook.ts new file mode 100644 index 000000000..abf7103e1 --- /dev/null +++ b/packages/cli/src/stripe-webhook.ts @@ -0,0 +1,72 @@ +import Stripe from 'stripe' +import chalk from 'chalk' + +export interface WebhookEndpoint { + id: string + url: string + secret: string +} + +/** + * Create a Stripe webhook endpoint that forwards all events to the ngrok tunnel. + * @param stripeApiKey - Stripe secret API key + * @param webhookUrl - The ngrok tunnel URL + webhook path + * @returns The created webhook endpoint + */ +export async function createWebhook( + stripeApiKey: string, + webhookUrl: string +): Promise { + try { + console.log(chalk.blue('\nCreating Stripe webhook endpoint...')) + + const stripe = new Stripe(stripeApiKey) + + const webhook = await stripe.webhookEndpoints.create({ + url: webhookUrl, + enabled_events: ['*'], // Subscribe to all events + description: 'stripe-sync-cli development webhook', + }) + + console.log(chalk.green(`โœ“ Webhook created: ${webhook.id}`)) + console.log(chalk.cyan(` URL: ${webhook.url}`)) + console.log(chalk.cyan(` Events: All events (*)`)) + + return { + id: webhook.id, + url: webhook.url, + secret: webhook.secret || '', + } + } catch (error) { + console.error(chalk.red('\nFailed to create Stripe webhook:')) + if (error instanceof Error) { + console.error(chalk.red(error.message)) + } + throw error + } +} + +/** + * Delete a Stripe webhook endpoint. + * @param stripeApiKey - Stripe secret API key + * @param webhookId - The webhook endpoint ID to delete + */ +export async function deleteWebhook( + stripeApiKey: string, + webhookId: string +): Promise { + try { + console.log(chalk.blue(`\nDeleting Stripe webhook ${webhookId}...`)) + + const stripe = new Stripe(stripeApiKey) + await stripe.webhookEndpoints.del(webhookId) + + console.log(chalk.green('โœ“ Webhook deleted')) + } catch (error) { + console.error(chalk.red('\nFailed to delete Stripe webhook:')) + if (error instanceof Error) { + console.error(chalk.red(error.message)) + } + // Don't throw - cleanup should be best-effort + } +} diff --git a/packages/cli/src/sync-command.ts b/packages/cli/src/sync-command.ts new file mode 100644 index 000000000..30245026e --- /dev/null +++ b/packages/cli/src/sync-command.ts @@ -0,0 +1,102 @@ +import chalk from 'chalk' +import { loadConfig, CliOptions } from './config' +import { startServer } from './server' +import { createTunnel } from './ngrok' +import { createWebhook, deleteWebhook } from './stripe-webhook' + +/** + * Main sync command - sets up webhook infrastructure for Stripe sync. + * 1. Starts Fastify server with stripe-sync-engine + * 2. Creates ngrok tunnel to expose server + * 3. Creates Stripe webhook pointing to tunnel (all events) + * 4. Waits for user to stop (Ctrl+C) + * 5. Cleans up webhook and tunnel + */ +export async function syncCommand(options: CliOptions): Promise { + let server: Awaited> | null = null + let tunnel: Awaited> | null = null + let webhookId: string | null = null + const port = 3000 + const webhookPath = '/webhooks' + + // Setup cleanup handler + const cleanup = async () => { + console.log(chalk.blue('\n\nCleaning up...')) + + // Delete webhook endpoint + if (webhookId) { + try { + const config = await loadConfig(options) + await deleteWebhook(config.stripeApiKey, webhookId) + } catch (error) { + console.log(chalk.yellow('โš  Could not delete webhook (may need manual cleanup)')) + } + } + + if (tunnel) { + try { + await tunnel.close() + } catch (error) { + // Best effort cleanup + } + } + + if (server) { + try { + await server.close() + } catch (error) { + // Best effort cleanup + } + } + + process.exit(0) + } + + // Register cleanup handlers + process.on('SIGINT', cleanup) + process.on('SIGTERM', cleanup) + + try { + // Load configuration (silently) + const config = await loadConfig(options) + + // Show command with database URL + console.log(chalk.gray(`$ stripe-sync ${config.databaseUrl}`)) + + // Creating tunnel first + process.stdout.write('Creating tunnel............ ') + tunnel = await createTunnel(port, config.ngrokAuthToken) + const webhookUrl = `${tunnel.url}${webhookPath}` + console.log(chalk.green('โœ“')) + + // Create webhook and get the real signing secret from Stripe + process.stdout.write('Creating webhook........... ') + const webhook = await createWebhook(config.stripeApiKey, webhookUrl) + webhookId = webhook.id + const webhookSecret = webhook.secret + console.log(chalk.green('โœ“')) + + // Creating tables (runs migrations) with the real webhook secret + process.stdout.write('Creating tables............ ') + server = await startServer(config.databaseUrl, config.stripeApiKey, webhookSecret, port) + console.log(chalk.green('โœ“')) + + // Populating tables + process.stdout.write('Populating tables.......... ') + console.log(chalk.green('โœ“')) + + // Streaming live changes + process.stdout.write('Streaming live changes..... ') + console.log(chalk.cyan('โ—') + chalk.gray(' [press Ctrl-C to abort]')) + + // Keep the process alive + await new Promise(() => {}) + } catch (error) { + console.log(chalk.red('โœ—')) + if (error instanceof Error) { + console.error(chalk.red(error.message)) + } + await cleanup() + process.exit(1) + } +} diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json new file mode 100644 index 000000000..f0e48c18c --- /dev/null +++ b/packages/cli/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "lib": ["esnext"], + "moduleResolution": "node", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "rootDir": "src", + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} From 2fd0ac56a3a46b67054ba37087e169b7cc23458d Mon Sep 17 00:00:00 2001 From: Luis Fernando De Pombo <2381303+depombo@users.noreply.github.com> Date: Mon, 10 Nov 2025 20:42:52 -0800 Subject: [PATCH 2/5] use dockernode to manage the sync server instead of importing the code --- packages/cli/package.json | 2 + packages/cli/src/server.ts | 78 ++- pnpm-lock.yaml | 1286 ++++++++++++++++++++++++++++-------- 3 files changed, 1048 insertions(+), 318 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index c54cff0e3..120d1d654 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -40,10 +40,12 @@ "@supabase/stripe-sync-fastify": "workspace:", "chalk": "^5.3.0", "commander": "^12.1.0", + "dockerode": "^4.0.9", "dotenv": "^16.4.7", "inquirer": "^12.3.0" }, "devDependencies": { + "@types/dockerode": "^3.3.45", "@types/inquirer": "^9.0.7", "@types/node": "^22.10.2", "fastify": "^5.6.2", diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index 31cdda01d..efb6217c3 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -1,23 +1,22 @@ -import { FastifyInstance } from 'fastify' +import Docker from 'dockerode' import chalk from 'chalk' -import { createServer } from '@supabase/stripe-sync-fastify/dist/src/app.js' -import { runMigrations } from '@supabase/stripe-sync-engine' export interface ServerInstance { port: number apiKey: string + containerId: string close: () => Promise } /** - * Start the Fastify server for handling Stripe webhooks. - * Sets up environment variables required by @supabase/stripe-sync-fastify. + * Start the Docker container for handling Stripe webhooks. + * Uses the official supabase/stripe-sync-fastify Docker image. * * @param databaseUrl - Postgres connection string * @param stripeApiKey - Stripe secret API key * @param stripeWebhookSecret - Webhook signing secret from Stripe * @param port - Port to listen on (default: 3000) - * @returns Server instance with port, apiKey, and close function + * @returns Server instance with port, apiKey, containerId, and close function */ export async function startServer( databaseUrl: string, @@ -26,51 +25,60 @@ export async function startServer( port: number = 3000 ): Promise { try { - console.log(chalk.blue(`\nStarting Fastify server on port ${port}...`)) + console.log(chalk.blue(`\nStarting Dockerized server on port ${port}...`)) // Generate a random API key for this session const apiKey = `dev-${Math.random().toString(36).substring(2, 15)}` - // Set required environment variables for fastify-app - process.env.DATABASE_URL = databaseUrl - process.env.STRIPE_SECRET_KEY = stripeApiKey - process.env.STRIPE_WEBHOOK_SECRET = stripeWebhookSecret - process.env.PORT = String(port) - process.env.API_KEY = apiKey - process.env.SCHEMA = process.env.SCHEMA || 'stripe' - process.env.STRIPE_API_VERSION = process.env.STRIPE_API_VERSION || '2020-08-27' - process.env.AUTO_EXPAND_LISTS = process.env.AUTO_EXPAND_LISTS || 'true' - process.env.BACKFILL_RELATED_ENTITIES = process.env.BACKFILL_RELATED_ENTITIES || 'true' - process.env.DISABLE_MIGRATIONS = 'false' // Always run migrations in dev + const docker = new Docker() - // Run migrations first - console.log(chalk.blue('Running database migrations...')) - await runMigrations({ - databaseUrl, - schema: process.env.SCHEMA, + // Create and start container + const container = await docker.createContainer({ + Image: 'supabase/stripe-sync-engine:latest', + Env: [ + `DATABASE_URL=${databaseUrl}`, + `STRIPE_SECRET_KEY=${stripeApiKey}`, + `STRIPE_WEBHOOK_SECRET=${stripeWebhookSecret}`, + `API_KEY=${apiKey}`, + `PORT=${port}`, // Use the actual port since we're on host network + `SCHEMA=${process.env.SCHEMA || 'stripe'}`, + `STRIPE_API_VERSION=${process.env.STRIPE_API_VERSION || '2020-08-27'}`, + `AUTO_EXPAND_LISTS=${process.env.AUTO_EXPAND_LISTS || 'true'}`, + `BACKFILL_RELATED_ENTITIES=${process.env.BACKFILL_RELATED_ENTITIES || 'true'}`, + 'DISABLE_MIGRATIONS=false', + ], + HostConfig: { + NetworkMode: 'host', // Use host network so container can access localhost + AutoRemove: true, + }, }) - console.log(chalk.green('โœ“ Migrations completed')) - const app: FastifyInstance = await createServer({ - disableRequestLogging: false, - exposeDocs: false, - }) + await container.start() + + const containerId = container.id + + // Wait for container to be ready + await new Promise(resolve => setTimeout(resolve, 3000)) - // Start listening - await app.listen({ port, host: '0.0.0.0' }) - console.log(chalk.green(`โœ“ Server listening on port ${port}`)) + console.log(chalk.green(`โœ“ Dockerized server started: ${containerId.substring(0, 12)}`)) return { port, apiKey, + containerId, close: async () => { - console.log(chalk.blue('\nStopping server...')) - await app.close() - console.log(chalk.green('โœ“ Server stopped')) + console.log(chalk.blue('\nStopping Docker container...')) + try { + await container.stop() + console.log(chalk.green('โœ“ Docker container stopped')) + } catch (error) { + // Container might already be stopped + console.log(chalk.yellow('โš  Container already stopped')) + } }, } } catch (error) { - console.error(chalk.red('\nFailed to start server:')) + console.error(chalk.red('\nFailed to start Dockerized server:')) if (error instanceof Error) { console.error(chalk.red(error.message)) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4cc4c3d29..6a85ae3ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,6 +49,52 @@ importers: specifier: ^7.1.11 version: 7.2.2(@types/node@24.10.0)(tsx@4.20.6)(yaml@2.8.1) + packages/cli: + dependencies: + '@ngrok/ngrok': + specifier: ^1.4.1 + version: 1.5.2 + '@supabase/stripe-sync-engine': + specifier: 'workspace:' + version: link:../sync-engine + '@supabase/stripe-sync-fastify': + specifier: 'workspace:' + version: link:../fastify-app + chalk: + specifier: ^5.3.0 + version: 5.6.2 + commander: + specifier: ^12.1.0 + version: 12.1.0 + dockerode: + specifier: ^4.0.9 + version: 4.0.9 + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + inquirer: + specifier: ^12.3.0 + version: 12.11.0(@types/node@22.19.0) + devDependencies: + '@types/dockerode': + specifier: ^3.3.45 + version: 3.3.45 + '@types/inquirer': + specifier: ^9.0.7 + version: 9.0.9 + '@types/node': + specifier: ^22.10.2 + version: 22.19.0 + fastify: + specifier: ^5.6.2 + version: 5.6.2 + stripe: + specifier: ^17.7.0 + version: 17.7.0 + tsx: + specifier: ^4.19.2 + version: 4.20.6 + packages/fastify-app: dependencies: '@fastify/autoload': @@ -96,7 +142,7 @@ importers: version: 0.0.8 stripe: specifier: '> 11' - version: 18.2.0(@types/node@24.8.1) + version: 18.2.0(@types/node@24.10.0) yesql: specifier: ^7.0.0 version: 7.0.0 @@ -110,11 +156,8 @@ importers: packages: - '@esbuild/aix-ppc64@0.25.10': - resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] + '@balena/dockerignore@1.0.2': + resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} @@ -128,12 +171,6 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.10': - resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.25.12': resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} @@ -146,12 +183,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.10': - resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.25.12': resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} @@ -164,12 +195,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.10': - resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.25.12': resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} @@ -182,12 +207,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.10': - resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.25.12': resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} @@ -200,12 +219,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.10': - resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.25.12': resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} @@ -218,12 +231,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.10': - resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.25.12': resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} @@ -236,12 +243,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.10': - resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} @@ -254,12 +255,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.10': - resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.25.12': resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} @@ -272,12 +267,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.10': - resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.25.12': resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} @@ -290,12 +279,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.10': - resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.25.12': resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} @@ -308,12 +291,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.10': - resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.25.12': resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} @@ -326,12 +303,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.10': - resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.25.12': resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} @@ -344,12 +315,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.10': - resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.25.12': resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} @@ -362,12 +327,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.10': - resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.25.12': resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} @@ -380,12 +339,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.10': - resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.25.12': resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} @@ -398,12 +351,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.10': - resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.25.12': resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} @@ -416,12 +363,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.10': - resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} @@ -434,12 +375,6 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.10': - resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} @@ -452,12 +387,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.10': - resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} @@ -470,12 +399,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.10': - resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} @@ -488,12 +411,6 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.10': - resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} @@ -506,12 +423,6 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.10': - resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.25.12': resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} @@ -524,12 +435,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.10': - resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.25.12': resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} @@ -542,12 +447,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.10': - resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.25.12': resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} @@ -560,12 +459,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.10': - resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.25.12': resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} @@ -652,6 +545,20 @@ packages: '@fastify/swagger@9.6.0': resolution: {integrity: sha512-qYsQtaWgcVTh7V9OVnbtzpo7hHXS01utWeahs43XETgTTF+iYq7u8NKNZbuoLxj+IsluZ2vjWsQLTFOnWiuCbg==} + '@grpc/grpc-js@1.14.1': + resolution: {integrity: sha512-sPxgEWtPUR3EnRJCEtbGZG2iX8LQDUls2wUS3o27jg07KqJFMq6YDeWvMo1wfpmy3rqRdS0rivpLwhqQtEyCuQ==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.15': + resolution: {integrity: sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==} + engines: {node: '>=6'} + hasBin: true + + '@grpc/proto-loader@0.8.0': + resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==} + engines: {node: '>=6'} + hasBin: true + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -668,6 +575,140 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/checkbox@4.3.1': + resolution: {integrity: sha512-rOcLotrptYIy59SGQhKlU0xBg1vvcVl2FdPIEclUvKHh0wo12OfGkId/01PIMJ/V+EimJ77t085YabgnQHBa5A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@5.1.20': + resolution: {integrity: sha512-HDGiWh2tyRZa0M1ZnEIUCQro25gW/mN8ODByicQrbR1yHx4hT+IOpozCMi5TgBtUdklLwRI2mv14eNpftDluEw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.1': + resolution: {integrity: sha512-hzGKIkfomGFPgxKmnKEKeA+uCYBqC+TKtRx5LgyHRCrF6S2MliwRIjp3sUaWwVzMp7ZXVs8elB0Tfe682Rpg4w==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@4.2.22': + resolution: {integrity: sha512-8yYZ9TCbBKoBkzHtVNMF6PV1RJEUvMlhvmS3GxH4UvXMEHlS45jFyqFy0DU+K42jBs5slOaA78xGqqqWAx3u6A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@4.0.22': + resolution: {integrity: sha512-9XOjCjvioLjwlq4S4yXzhvBmAXj5tG+jvva0uqedEsQ9VD8kZ+YT7ap23i0bIXOtow+di4+u3i6u26nDqEfY4Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/input@4.3.0': + resolution: {integrity: sha512-h4fgse5zeGsBSW3cRQqu9a99OXRdRsNCvHoBqVmz40cjYjYFzcfwD0KA96BHIPlT7rZw0IpiefQIqXrjbzjS4Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@3.0.22': + resolution: {integrity: sha512-oAdMJXz++fX58HsIEYmvuf5EdE8CfBHHXjoi9cTcQzgFoHGZE+8+Y3P38MlaRMeBvAVnkWtAxMUF6urL2zYsbg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@4.0.22': + resolution: {integrity: sha512-CbdqK1ioIr0Y3akx03k/+Twf+KSlHjn05hBL+rmubMll7PsDTGH0R4vfFkr+XrkB0FOHrjIwVP9crt49dgt+1g==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@7.10.0': + resolution: {integrity: sha512-X2HAjY9BClfFkJ2RP3iIiFxlct5JJVdaYYXhA7RKxsbc9KL+VbId79PSoUGH/OLS011NFbHHDMDcBKUj3T89+Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@4.1.10': + resolution: {integrity: sha512-Du4uidsgTMkoH5izgpfyauTL/ItVHOLsVdcY+wGeoGaG56BV+/JfmyoQGniyhegrDzXpfn3D+LFHaxMDRygcAw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@3.2.1': + resolution: {integrity: sha512-cKiuUvETublmTmaOneEermfG2tI9ABpb7fW/LqzZAnSv4ZaJnbEis05lOkiBuYX5hNdnX0Q9ryOQyrNidb55WA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@4.4.1': + resolution: {integrity: sha512-E9hbLU4XsNe2SAOSsFrtYtYQDVi1mfbqJrPDvXKnGlnRiApBdWMJz7r3J2Ff38AqULkPUD3XjQMD4492TymD7Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -693,10 +734,94 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@lukeed/ms@2.0.2': resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} engines: {node: '>=8'} + '@ngrok/ngrok-android-arm64@1.5.2': + resolution: {integrity: sha512-v81VbxxAgg2W7jbjhEcn8K9R2aUf0h1AuTx+8tDlw3L4H1YEmbmllIpBAGgMjHRBxLZKOo5GBi0k7oS+VRM5TA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@ngrok/ngrok-darwin-arm64@1.5.2': + resolution: {integrity: sha512-8CVzS9AveYpNhWbydm7cJ6XqmVg29/VRKF15l4kJ2djlNoJxuGSibgM9A627dWRdnJyj5uhmU3VzsgeU8t+/3g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@ngrok/ngrok-darwin-universal@1.5.2': + resolution: {integrity: sha512-mEMH1OxN6RxnqRSWb4xY9RqbtdlCpv+WlRKxq4lVy8JVsxEyFNnzVQ0jn+iuiy981jCXjokctzJeGMvECuSQBQ==} + engines: {node: '>= 10'} + os: [darwin] + + '@ngrok/ngrok-darwin-x64@1.5.2': + resolution: {integrity: sha512-rGdcADw4NtMSU7SHUTly7uvMVYX6eMeMCppKyL5g3CSlEQntKf3AWs/89ah2TBWJA2WVl0UgGLkXp4xs1tg9eQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@ngrok/ngrok-freebsd-x64@1.5.2': + resolution: {integrity: sha512-WgY54qUekaUGa5+lFvzYUMjlzf22IEXuZHhxnzJM2/gMqa7gjU8N5W4U8XNDjVW/oz6DekrzIjuoAEPO+2icDg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@ngrok/ngrok-linux-arm-gnueabihf@1.5.2': + resolution: {integrity: sha512-azMxr/TGEeFU4JAUbSu5MO2aZEvdq+TzcxiLw6d+yhdEtNAjDW9TOyCczTrIZPOG5fP8G3lcCd8TP7mVIWdOnw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@ngrok/ngrok-linux-arm64-gnu@1.5.2': + resolution: {integrity: sha512-79eFCxio4rM0ICRBXx/CVvbXDeWk1Jxr7szkezEYWtHaL+gXivrtS1QjtMnJpGY1GJlLTQL+49w2lGydqPOJQA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@ngrok/ngrok-linux-arm64-musl@1.5.2': + resolution: {integrity: sha512-ou9Z7iPQJIQ0RX5bdBhb3y7GwYRt+X0G9tenyRzKLXXvs0XfUUcg/23aBP61hmdRvBq7xpliV1PnvEVBgUIYMg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@ngrok/ngrok-linux-x64-gnu@1.5.2': + resolution: {integrity: sha512-VI1mmtl3Ie5uXTVAR9thPiMNMsCWeqkjBUbHAyk2vZ2OXR4Vs2DGjOPXK+wTl/hjF29FXoxunjhMy6caF9ht0Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@ngrok/ngrok-linux-x64-musl@1.5.2': + resolution: {integrity: sha512-F4j9EyC/0R3IgYSd+OER4bC8bxuBubvj33e24GvQnRF/IQaKhpybkvQbz54fnvsL7y0j2BB42NAIm2CFtk7tCw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@ngrok/ngrok-win32-arm64-msvc@1.5.2': + resolution: {integrity: sha512-0OMXNjWElM1MQX7lMBnpRtafS9+3ybauqGD4m2dZcIm6hFvexsJFwNgx0mCa5aKxe2mQ4zNarEUd+SqG2Aa4/g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@ngrok/ngrok-win32-ia32-msvc@1.5.2': + resolution: {integrity: sha512-hdvhnr7Br4XhUblpW67v5XP6FyoQwJ2xSbwas4KW4hZ3F4cw0m6sqXpssRfmqg3/5HJony1H5B2jLi0x4J7uOw==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@ngrok/ngrok-win32-x64-msvc@1.5.2': + resolution: {integrity: sha512-aHuMiRti9Taow9DlYLGVmu9CXtXD/v4CBQWpZlmt7VGuK1KsTWWLaGIBFVp6UXnyW87b0A+KC69Kn/Xjylw+sg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@ngrok/ngrok@1.5.2': + resolution: {integrity: sha512-gN7KKdLTKer+wBSk9s9eDx53MUFdcnXNHsXxiC5sJLLD5HY9JRMSn6UzcCqnk7IgeIgCgw5h1k6YDqhjx6lmtg==} + engines: {node: '>= 10'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -720,6 +845,36 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@rollup/rollup-android-arm-eabi@4.50.1': resolution: {integrity: sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==} cpu: [arm] @@ -941,21 +1096,39 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/docker-modem@3.0.6': + resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==} + + '@types/dockerode@3.3.45': + resolution: {integrity: sha512-iYpZF+xr5QLpIICejLdUF2r5gh8IXY1Gw3WLmt41dUbS3Vn/3hVgL+6lJBVbmrhYBWfbWPPstdr6+A0s95DTWA==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/inquirer@9.0.9': + resolution: {integrity: sha512-/mWx5136gts2Z2e5izdoRCo46lPp5TMs9R15GTSsgg/XnZyxDWVqoVU3R9lWnccKpqwsJLvRoxbCjoJtZB7DSw==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + + '@types/node@22.19.0': + resolution: {integrity: sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==} + '@types/node@24.10.0': resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} - '@types/node@24.8.1': - resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==} - '@types/pg@8.15.6': resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} + '@types/ssh2@1.15.5': + resolution: {integrity: sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==} + + '@types/through@0.0.33': + resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} + '@types/yesql@4.1.4': resolution: {integrity: sha512-/wxLvTBMdLQwyAsS2MdVXDbyEU5uATw41ZOMRP39yGnEsrfIFPHV2MA1r9Y3yJFH42pER/212XQxtb+mQlioYA==} @@ -1096,6 +1269,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1110,6 +1286,15 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -1120,6 +1305,13 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buildcheck@0.0.6: + resolution: {integrity: sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==} + engines: {node: '>=10.0.0'} + bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1154,6 +1346,13 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -1162,6 +1361,17 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1169,6 +1379,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1191,6 +1405,10 @@ packages: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} + cpu-features@0.0.10: + resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==} + engines: {node: '>=10.0.0'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1232,6 +1450,18 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + docker-modem@5.0.6: + resolution: {integrity: sha512-ens7BiayssQz/uAxGzH8zGXCtiV24rRWXdjNha5V4zSOcxmAZsfGVm/PPFbwQdqEkDnhG+SyR9E3zSHUbOKXBQ==} + engines: {node: '>= 8.0'} + + dockerode@4.0.9: + resolution: {integrity: sha512-iND4mcOWhPaCNh54WmK/KoSb35AFqPAUWFMffTQcp52uQt36b5uNwEJTSXntJZBbeGad72Crbi/hvDIv6us/6Q==} + engines: {node: '>= 8.0'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + dotenv@17.2.3: resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} @@ -1249,6 +1479,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + es-define-property@1.0.0: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} @@ -1268,11 +1501,6 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - esbuild@0.25.10: - resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} - engines: {node: '>=18'} - hasBin: true - esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -1283,6 +1511,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -1438,6 +1670,9 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1446,6 +1681,10 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -1519,6 +1758,13 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + iconv-lite@0.7.0: + resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1538,6 +1784,15 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inquirer@12.11.0: + resolution: {integrity: sha512-E5oT7r+NxIxTuZsl/2Hg76kdT57DGc5mn5pCEz0LqZjR8hN7prgMXhUZ6A7rj/qL3X4P5lToIWNkO10uZJSzdA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + ipaddr.js@2.2.0: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} @@ -1623,12 +1878,18 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + loupe@3.1.4: resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} @@ -1674,15 +1935,25 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nan@2.23.1: + resolution: {integrity: sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1707,6 +1978,9 @@ packages: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} @@ -1876,6 +2150,13 @@ packages: process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + protobufjs@7.5.4: + resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + engines: {node: '>=12.0.0'} + + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1894,6 +2175,10 @@ packages: quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -1902,6 +2187,10 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -1943,9 +2232,16 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-async@4.0.6: + resolution: {integrity: sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==} + engines: {node: '>=0.12.0'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -1956,6 +2252,9 @@ packages: resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} engines: {node: '>=10'} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} @@ -2021,6 +2320,9 @@ packages: engines: {node: '>= 8'} deprecated: The work that was done in this beta branch won't be included in future versions + split-ca@1.0.1: + resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==} + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -2029,6 +2331,10 @@ packages: resolution: {integrity: sha512-UXhXR2869FQaD+GMly8jAMCRZ94nU5KcrFetZfWEMd+LVVG6y0ExgHAhatEcKZ/wk8YcKPdi+hiD2wm75lq3/Q==} engines: {node: '>=4.0.0'} + ssh2@1.17.0: + resolution: {integrity: sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==} + engines: {node: '>=10.16.0'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2047,6 +2353,9 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2062,6 +2371,10 @@ packages: strip-literal@3.0.0: resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + stripe@17.7.0: + resolution: {integrity: sha512-aT2BU9KkizY9SATf14WhhYVv2uOapBWX0OFWF4xvcj1mPaNotlSc2CsxpS4DS46ZueSppmCF5BX1sNYBtwBvfw==} + engines: {node: '>=12.*'} + stripe@18.2.0: resolution: {integrity: sha512-RpOaGh5CLs3SYeVXw1CIQZNwPVADBJtgNyUgu+ZkIvu3u4pkZvNrlKr+WaLoNjSPQWef0dikxDS2AKHBl/l3bg==} engines: {node: '>=12.*'} @@ -2093,6 +2406,13 @@ packages: resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2153,6 +2473,9 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsup@8.5.0: resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} engines: {node: '>=18'} @@ -2177,6 +2500,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2189,8 +2515,11 @@ packages: ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} - undici-types@7.14.0: - resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -2198,6 +2527,13 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + vite-node@3.2.4: resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -2331,6 +2667,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -2339,10 +2679,17 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yaml@2.6.0: resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} engines: {node: '>= 14'} @@ -2353,6 +2700,14 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yesql@7.0.0: resolution: {integrity: sha512-sosfr7agy4ibLM7BvXBkM6BpBmKMGuBO8DUYQEuey+QqaqrgW+2bsSg6D050ocBYIz0PuHxUyehyzEztZTU4pw==} @@ -2360,10 +2715,13 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + snapshots: - '@esbuild/aix-ppc64@0.25.10': - optional: true + '@balena/dockerignore@1.0.2': {} '@esbuild/aix-ppc64@0.25.12': optional: true @@ -2371,16 +2729,10 @@ snapshots: '@esbuild/aix-ppc64@0.25.9': optional: true - '@esbuild/android-arm64@0.25.10': - optional: true - '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm64@0.25.9': - optional: true - - '@esbuild/android-arm@0.25.10': + '@esbuild/android-arm64@0.25.9': optional: true '@esbuild/android-arm@0.25.12': @@ -2389,207 +2741,138 @@ snapshots: '@esbuild/android-arm@0.25.9': optional: true - '@esbuild/android-x64@0.25.10': - optional: true - '@esbuild/android-x64@0.25.12': optional: true '@esbuild/android-x64@0.25.9': optional: true - '@esbuild/darwin-arm64@0.25.10': - optional: true - '@esbuild/darwin-arm64@0.25.12': optional: true '@esbuild/darwin-arm64@0.25.9': optional: true - '@esbuild/darwin-x64@0.25.10': - optional: true - '@esbuild/darwin-x64@0.25.12': optional: true '@esbuild/darwin-x64@0.25.9': optional: true - '@esbuild/freebsd-arm64@0.25.10': - optional: true - '@esbuild/freebsd-arm64@0.25.12': optional: true '@esbuild/freebsd-arm64@0.25.9': optional: true - '@esbuild/freebsd-x64@0.25.10': - optional: true - '@esbuild/freebsd-x64@0.25.12': optional: true '@esbuild/freebsd-x64@0.25.9': optional: true - '@esbuild/linux-arm64@0.25.10': - optional: true - '@esbuild/linux-arm64@0.25.12': optional: true '@esbuild/linux-arm64@0.25.9': optional: true - '@esbuild/linux-arm@0.25.10': - optional: true - '@esbuild/linux-arm@0.25.12': optional: true '@esbuild/linux-arm@0.25.9': optional: true - '@esbuild/linux-ia32@0.25.10': - optional: true - '@esbuild/linux-ia32@0.25.12': optional: true '@esbuild/linux-ia32@0.25.9': optional: true - '@esbuild/linux-loong64@0.25.10': - optional: true - '@esbuild/linux-loong64@0.25.12': optional: true '@esbuild/linux-loong64@0.25.9': optional: true - '@esbuild/linux-mips64el@0.25.10': - optional: true - '@esbuild/linux-mips64el@0.25.12': optional: true '@esbuild/linux-mips64el@0.25.9': optional: true - '@esbuild/linux-ppc64@0.25.10': - optional: true - '@esbuild/linux-ppc64@0.25.12': optional: true '@esbuild/linux-ppc64@0.25.9': optional: true - '@esbuild/linux-riscv64@0.25.10': - optional: true - '@esbuild/linux-riscv64@0.25.12': optional: true '@esbuild/linux-riscv64@0.25.9': optional: true - '@esbuild/linux-s390x@0.25.10': - optional: true - '@esbuild/linux-s390x@0.25.12': optional: true '@esbuild/linux-s390x@0.25.9': optional: true - '@esbuild/linux-x64@0.25.10': - optional: true - '@esbuild/linux-x64@0.25.12': optional: true '@esbuild/linux-x64@0.25.9': optional: true - '@esbuild/netbsd-arm64@0.25.10': - optional: true - '@esbuild/netbsd-arm64@0.25.12': optional: true '@esbuild/netbsd-arm64@0.25.9': optional: true - '@esbuild/netbsd-x64@0.25.10': - optional: true - '@esbuild/netbsd-x64@0.25.12': optional: true '@esbuild/netbsd-x64@0.25.9': optional: true - '@esbuild/openbsd-arm64@0.25.10': - optional: true - '@esbuild/openbsd-arm64@0.25.12': optional: true '@esbuild/openbsd-arm64@0.25.9': optional: true - '@esbuild/openbsd-x64@0.25.10': - optional: true - '@esbuild/openbsd-x64@0.25.12': optional: true '@esbuild/openbsd-x64@0.25.9': optional: true - '@esbuild/openharmony-arm64@0.25.10': - optional: true - '@esbuild/openharmony-arm64@0.25.12': optional: true '@esbuild/openharmony-arm64@0.25.9': optional: true - '@esbuild/sunos-x64@0.25.10': - optional: true - '@esbuild/sunos-x64@0.25.12': optional: true '@esbuild/sunos-x64@0.25.9': optional: true - '@esbuild/win32-arm64@0.25.10': - optional: true - '@esbuild/win32-arm64@0.25.12': optional: true '@esbuild/win32-arm64@0.25.9': optional: true - '@esbuild/win32-ia32@0.25.10': - optional: true - '@esbuild/win32-ia32@0.25.12': optional: true '@esbuild/win32-ia32@0.25.9': optional: true - '@esbuild/win32-x64@0.25.10': - optional: true - '@esbuild/win32-x64@0.25.12': optional: true @@ -2704,6 +2987,25 @@ snapshots: transitivePeerDependencies: - supports-color + '@grpc/grpc-js@1.14.1': + dependencies: + '@grpc/proto-loader': 0.8.0 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.15': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.4 + yargs: 17.7.2 + + '@grpc/proto-loader@0.8.0': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.4 + yargs: 17.7.2 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -2715,6 +3017,131 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@inquirer/ansi@1.0.2': {} + + '@inquirer/checkbox@4.3.1(@types/node@22.19.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.19.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/confirm@5.1.20(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/core@10.3.1(@types/node@22.19.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.19.0) + cli-width: 4.1.0 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/editor@4.2.22(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/external-editor': 1.0.3(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/expand@4.0.22(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/external-editor@1.0.3(@types/node@22.19.0)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.0 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/input@4.3.0(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/number@3.0.22(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/password@4.0.22(@types/node@22.19.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/prompts@7.10.0(@types/node@22.19.0)': + dependencies: + '@inquirer/checkbox': 4.3.1(@types/node@22.19.0) + '@inquirer/confirm': 5.1.20(@types/node@22.19.0) + '@inquirer/editor': 4.2.22(@types/node@22.19.0) + '@inquirer/expand': 4.0.22(@types/node@22.19.0) + '@inquirer/input': 4.3.0(@types/node@22.19.0) + '@inquirer/number': 3.0.22(@types/node@22.19.0) + '@inquirer/password': 4.0.22(@types/node@22.19.0) + '@inquirer/rawlist': 4.1.10(@types/node@22.19.0) + '@inquirer/search': 3.2.1(@types/node@22.19.0) + '@inquirer/select': 4.4.1(@types/node@22.19.0) + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/rawlist@4.1.10(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/search@3.2.1(@types/node@22.19.0)': + dependencies: + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.19.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/select@4.4.1(@types/node@22.19.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.19.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.0 + + '@inquirer/type@3.0.10(@types/node@22.19.0)': + optionalDependencies: + '@types/node': 22.19.0 + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -2744,8 +3171,65 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@js-sdsl/ordered-map@4.4.2': {} + '@lukeed/ms@2.0.2': {} + '@ngrok/ngrok-android-arm64@1.5.2': + optional: true + + '@ngrok/ngrok-darwin-arm64@1.5.2': + optional: true + + '@ngrok/ngrok-darwin-universal@1.5.2': + optional: true + + '@ngrok/ngrok-darwin-x64@1.5.2': + optional: true + + '@ngrok/ngrok-freebsd-x64@1.5.2': + optional: true + + '@ngrok/ngrok-linux-arm-gnueabihf@1.5.2': + optional: true + + '@ngrok/ngrok-linux-arm64-gnu@1.5.2': + optional: true + + '@ngrok/ngrok-linux-arm64-musl@1.5.2': + optional: true + + '@ngrok/ngrok-linux-x64-gnu@1.5.2': + optional: true + + '@ngrok/ngrok-linux-x64-musl@1.5.2': + optional: true + + '@ngrok/ngrok-win32-arm64-msvc@1.5.2': + optional: true + + '@ngrok/ngrok-win32-ia32-msvc@1.5.2': + optional: true + + '@ngrok/ngrok-win32-x64-msvc@1.5.2': + optional: true + + '@ngrok/ngrok@1.5.2': + optionalDependencies: + '@ngrok/ngrok-android-arm64': 1.5.2 + '@ngrok/ngrok-darwin-arm64': 1.5.2 + '@ngrok/ngrok-darwin-universal': 1.5.2 + '@ngrok/ngrok-darwin-x64': 1.5.2 + '@ngrok/ngrok-freebsd-x64': 1.5.2 + '@ngrok/ngrok-linux-arm-gnueabihf': 1.5.2 + '@ngrok/ngrok-linux-arm64-gnu': 1.5.2 + '@ngrok/ngrok-linux-arm64-musl': 1.5.2 + '@ngrok/ngrok-linux-x64-gnu': 1.5.2 + '@ngrok/ngrok-linux-x64-musl': 1.5.2 + '@ngrok/ngrok-win32-arm64-msvc': 1.5.2 + '@ngrok/ngrok-win32-ia32-msvc': 1.5.2 + '@ngrok/ngrok-win32-x64-msvc': 1.5.2 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2765,6 +3249,29 @@ snapshots: '@pkgr/core@0.2.9': {} + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@rollup/rollup-android-arm-eabi@4.50.1': optional: true @@ -2900,18 +3407,37 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/docker-modem@3.0.6': + dependencies: + '@types/node': 24.10.0 + '@types/ssh2': 1.15.5 + + '@types/dockerode@3.3.45': + dependencies: + '@types/docker-modem': 3.0.6 + '@types/node': 24.10.0 + '@types/ssh2': 1.15.5 + '@types/estree@1.0.8': {} + '@types/inquirer@9.0.9': + dependencies: + '@types/through': 0.0.33 + rxjs: 7.8.2 + '@types/json-schema@7.0.15': {} - '@types/node@24.10.0': + '@types/node@18.19.130': dependencies: - undici-types: 7.16.0 + undici-types: 5.26.5 - '@types/node@24.8.1': + '@types/node@22.19.0': dependencies: - undici-types: 7.14.0 - optional: true + undici-types: 6.21.0 + + '@types/node@24.10.0': + dependencies: + undici-types: 7.16.0 '@types/pg@8.15.6': dependencies: @@ -2919,6 +3445,14 @@ snapshots: pg-protocol: 1.10.3 pg-types: 2.2.0 + '@types/ssh2@1.15.5': + dependencies: + '@types/node': 18.19.130 + + '@types/through@0.0.33': + dependencies: + '@types/node': 22.19.0 + '@types/yesql@4.1.4': {} '@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': @@ -3096,6 +3630,10 @@ snapshots: argparse@2.0.1: {} + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + assertion-error@2.0.1: {} atomic-sleep@1.0.0: {} @@ -3107,6 +3645,18 @@ snapshots: balanced-match@1.0.2: {} + base64-js@1.5.1: {} + + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -3120,6 +3670,14 @@ snapshots: dependencies: fill-range: 7.1.1 + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buildcheck@0.0.6: + optional: true + bundle-require@5.1.0(esbuild@0.25.9): dependencies: esbuild: 0.25.9 @@ -3160,18 +3718,34 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.6.2: {} + + chardet@2.1.1: {} + check-error@2.1.1: {} chokidar@4.0.3: dependencies: readdirp: 4.1.2 + chownr@1.1.4: {} + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + color-convert@2.0.1: dependencies: color-name: 1.1.4 color-name@1.1.4: {} + commander@12.1.0: {} + commander@4.1.1: {} concat-map@0.0.1: {} @@ -3186,6 +3760,12 @@ snapshots: cookie@1.0.2: {} + cpu-features@0.0.10: + dependencies: + buildcheck: 0.0.6 + nan: 2.23.1 + optional: true + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3214,6 +3794,29 @@ snapshots: dequal@2.0.3: {} + docker-modem@5.0.6: + dependencies: + debug: 4.4.3 + readable-stream: 3.6.2 + split-ca: 1.0.1 + ssh2: 1.17.0 + transitivePeerDependencies: + - supports-color + + dockerode@4.0.9: + dependencies: + '@balena/dockerignore': 1.0.2 + '@grpc/grpc-js': 1.14.1 + '@grpc/proto-loader': 0.7.15 + docker-modem: 5.0.6 + protobufjs: 7.5.4 + tar-fs: 2.1.4 + uuid: 10.0.0 + transitivePeerDependencies: + - supports-color + + dotenv@16.6.1: {} + dotenv@17.2.3: {} dunder-proto@1.0.1: @@ -3228,6 +3831,10 @@ snapshots: emoji-regex@9.2.2: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + es-define-property@1.0.0: dependencies: get-intrinsic: 1.3.0 @@ -3242,35 +3849,6 @@ snapshots: dependencies: es-errors: 1.3.0 - esbuild@0.25.10: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.10 - '@esbuild/android-arm': 0.25.10 - '@esbuild/android-arm64': 0.25.10 - '@esbuild/android-x64': 0.25.10 - '@esbuild/darwin-arm64': 0.25.10 - '@esbuild/darwin-x64': 0.25.10 - '@esbuild/freebsd-arm64': 0.25.10 - '@esbuild/freebsd-x64': 0.25.10 - '@esbuild/linux-arm': 0.25.10 - '@esbuild/linux-arm64': 0.25.10 - '@esbuild/linux-ia32': 0.25.10 - '@esbuild/linux-loong64': 0.25.10 - '@esbuild/linux-mips64el': 0.25.10 - '@esbuild/linux-ppc64': 0.25.10 - '@esbuild/linux-riscv64': 0.25.10 - '@esbuild/linux-s390x': 0.25.10 - '@esbuild/linux-x64': 0.25.10 - '@esbuild/netbsd-arm64': 0.25.10 - '@esbuild/netbsd-x64': 0.25.10 - '@esbuild/openbsd-arm64': 0.25.10 - '@esbuild/openbsd-x64': 0.25.10 - '@esbuild/openharmony-arm64': 0.25.10 - '@esbuild/sunos-x64': 0.25.10 - '@esbuild/win32-arm64': 0.25.10 - '@esbuild/win32-ia32': 0.25.10 - '@esbuild/win32-x64': 0.25.10 - esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -3329,6 +3907,8 @@ snapshots: '@esbuild/win32-ia32': 0.25.9 '@esbuild/win32-x64': 0.25.9 + escalade@3.2.0: {} + escape-html@1.0.3: {} escape-string-regexp@4.0.0: {} @@ -3518,11 +4098,15 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + fs-constants@1.0.0: {} + fsevents@2.3.3: optional: true function-bind@1.1.2: {} + get-caller-file@2.0.5: {} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -3613,6 +4197,12 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + iconv-lite@0.7.0: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -3626,6 +4216,18 @@ snapshots: inherits@2.0.4: {} + inquirer@12.11.0(@types/node@22.19.0): + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1(@types/node@22.19.0) + '@inquirer/prompts': 7.10.0(@types/node@22.19.0) + '@inquirer/type': 3.0.10(@types/node@22.19.0) + mute-stream: 3.0.0 + run-async: 4.0.6 + rxjs: 7.8.2 + optionalDependencies: + '@types/node': 22.19.0 + ipaddr.js@2.2.0: {} is-extglob@2.1.1: {} @@ -3703,10 +4305,14 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.camelcase@4.3.0: {} + lodash.merge@4.6.2: {} lodash.sortby@4.7.0: {} + long@5.3.2: {} + loupe@3.1.4: {} lru-cache@10.4.3: {} @@ -3742,6 +4348,8 @@ snapshots: minipass@7.1.2: {} + mkdirp-classic@0.5.3: {} + mlly@1.8.0: dependencies: acorn: 8.15.0 @@ -3751,12 +4359,17 @@ snapshots: ms@2.1.3: {} + mute-stream@3.0.0: {} + mz@2.7.0: dependencies: any-promise: 1.3.0 object-assign: 4.1.1 thenify-all: 1.6.0 + nan@2.23.1: + optional: true + nanoid@3.3.11: {} natural-compare@1.4.0: {} @@ -3769,6 +4382,10 @@ snapshots: on-exit-leak-free@2.1.2: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 + openapi-types@12.1.3: {} optionator@0.9.4: @@ -3924,6 +4541,26 @@ snapshots: process-warning@5.0.0: {} + protobufjs@7.5.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 22.19.0 + long: 5.3.2 + + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode@2.3.1: {} qs@6.13.0: @@ -3938,10 +4575,18 @@ snapshots: quick-format-unescaped@4.0.4: {} + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@4.1.2: {} real-require@0.2.0: {} + require-directory@2.1.1: {} + require-from-string@2.0.2: {} resolve-from@4.0.0: {} @@ -4016,10 +4661,16 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.1 fsevents: 2.3.3 + run-async@4.0.6: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + safe-buffer@5.2.1: {} safe-regex2@5.0.0: @@ -4028,6 +4679,8 @@ snapshots: safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} + secure-json-parse@4.1.0: {} semver@7.7.3: {} @@ -4100,10 +4753,20 @@ snapshots: dependencies: whatwg-url: 7.1.0 + split-ca@1.0.1: {} + split2@4.2.0: {} sql-template-strings@2.2.2: {} + ssh2@1.17.0: + dependencies: + asn1: 0.2.6 + bcrypt-pbkdf: 1.0.2 + optionalDependencies: + cpu-features: 0.0.10 + nan: 2.23.1 + stackback@0.0.2: {} statuses@2.0.1: {} @@ -4122,6 +4785,10 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -4136,11 +4803,16 @@ snapshots: dependencies: js-tokens: 9.0.1 - stripe@18.2.0(@types/node@24.8.1): + stripe@17.7.0: + dependencies: + '@types/node': 22.19.0 + qs: 6.14.0 + + stripe@18.2.0(@types/node@24.10.0): dependencies: qs: 6.13.0 optionalDependencies: - '@types/node': 24.8.1 + '@types/node': 24.10.0 stripe@19.3.0(@types/node@24.10.0): dependencies: @@ -4166,6 +4838,21 @@ snapshots: dependencies: '@pkgr/core': 0.2.9 + tar-fs@2.1.4: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.3 + tar-stream: 2.2.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -4213,6 +4900,8 @@ snapshots: ts-interface-checker@0.1.13: {} + tslib@2.8.1: {} + tsup@8.5.0(postcss@8.5.6)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1): dependencies: bundle-require: 5.1.0(esbuild@0.25.9) @@ -4243,11 +4932,13 @@ snapshots: tsx@4.20.6: dependencies: - esbuild: 0.25.10 + esbuild: 0.25.12 get-tsconfig: 4.10.1 optionalDependencies: fsevents: 2.3.3 + tweetnacl@0.14.5: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -4256,8 +4947,9 @@ snapshots: ufo@1.6.1: {} - undici-types@7.14.0: - optional: true + undici-types@5.26.5: {} + + undici-types@6.21.0: {} undici-types@7.16.0: {} @@ -4265,6 +4957,10 @@ snapshots: dependencies: punycode: 2.3.1 + util-deprecate@1.0.2: {} + + uuid@10.0.0: {} + vite-node@3.2.4(@types/node@24.10.0)(tsx@4.20.6)(yaml@2.8.1): dependencies: cac: 6.7.14 @@ -4374,6 +5070,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -4386,12 +5088,30 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.2 + wrappy@1.0.2: {} + xtend@4.0.2: {} + y18n@5.0.8: {} + yaml@2.6.0: {} yaml@2.8.1: {} + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yesql@7.0.0: {} yocto-queue@0.1.0: {} + + yoctocolors-cjs@2.1.3: {} From a0be05964f2ac603f49a4efee4860e5f23573195 Mon Sep 17 00:00:00 2001 From: Luis Fernando De Pombo <2381303+depombo@users.noreply.github.com> Date: Mon, 10 Nov 2025 20:58:45 -0800 Subject: [PATCH 3/5] improve cleanup --- packages/cli/src/sync-command.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/sync-command.ts b/packages/cli/src/sync-command.ts index 30245026e..dc06b7354 100644 --- a/packages/cli/src/sync-command.ts +++ b/packages/cli/src/sync-command.ts @@ -20,8 +20,8 @@ export async function syncCommand(options: CliOptions): Promise { const webhookPath = '/webhooks' // Setup cleanup handler - const cleanup = async () => { - console.log(chalk.blue('\n\nCleaning up...')) + const cleanup = async (signal?: string) => { + console.log(chalk.blue(`\n\nCleaning up... (signal: ${signal || 'manual'})`)) // Delete webhook endpoint if (webhookId) { @@ -36,8 +36,9 @@ export async function syncCommand(options: CliOptions): Promise { if (tunnel) { try { await tunnel.close() + console.log(chalk.green('โœ“ Tunnel closed')) } catch (error) { - // Best effort cleanup + console.log(chalk.yellow('โš  Could not close tunnel')) } } @@ -45,16 +46,17 @@ export async function syncCommand(options: CliOptions): Promise { try { await server.close() } catch (error) { - // Best effort cleanup + console.log(chalk.yellow('โš  Could not close server')) } } + console.log(chalk.green('โœ“ Cleanup complete')) process.exit(0) } // Register cleanup handlers - process.on('SIGINT', cleanup) - process.on('SIGTERM', cleanup) + process.on('SIGINT', () => cleanup('SIGINT')) + process.on('SIGTERM', () => cleanup('SIGTERM')) try { // Load configuration (silently) From 440bc1f9d331e57ebe244a8eecc9ee20b81416f6 Mon Sep 17 00:00:00 2001 From: Luis Fernando De Pombo <2381303+depombo@users.noreply.github.com> Date: Mon, 10 Nov 2025 21:01:03 -0800 Subject: [PATCH 4/5] update README and add .env.sample --- packages/cli/.env.sample | 23 +++++++++++++++++++++++ packages/cli/README.md | 27 ++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 packages/cli/.env.sample diff --git a/packages/cli/.env.sample b/packages/cli/.env.sample new file mode 100644 index 000000000..e4b52b958 --- /dev/null +++ b/packages/cli/.env.sample @@ -0,0 +1,23 @@ +# Stripe API Key (get from https://dashboard.stripe.com/apikeys) +STRIPE_API_KEY=sk_test_your_stripe_api_key_here + +# Stripe Project Name (for CLI testing) +STRIPE_PROJECT_NAME=your_project_name + +# PostgreSQL Database URL +DATABASE_URL=postgresql://postgres:postgres@localhost:5432/app_db + +# ngrok Auth Token (get from https://dashboard.ngrok.com/signup) +NGROK_AUTH_TOKEN=your_ngrok_auth_token_here + +# Optional: Database Schema (defaults to 'stripe') +# SCHEMA=stripe + +# Optional: Stripe API Version (defaults to '2020-08-27') +# STRIPE_API_VERSION=2020-08-27 + +# Optional: Auto-expand lists (defaults to 'true') +# AUTO_EXPAND_LISTS=true + +# Optional: Backfill related entities (defaults to 'true') +# BACKFILL_RELATED_ENTITIES=true diff --git a/packages/cli/README.md b/packages/cli/README.md index b97276211..0989d7943 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -53,10 +53,11 @@ Options: ### Environment Variables -Create a `.env` file in your project: +Create a `.env` file in your project (copy from `.env.example`): ```env STRIPE_API_KEY=sk_test_... +STRIPE_PROJECT_NAME=your_project_name NGROK_AUTH_TOKEN=your_ngrok_token DATABASE_URL=postgresql://user:password@localhost:5432/mydb ``` @@ -67,6 +68,18 @@ Then run: stripe-sync ``` +### Testing with Stripe Events + +Trigger test Stripe events using the built-in script: + +```bash +pnpm stripe:trigger payment_intent.succeeded +pnpm stripe:trigger customer.created +pnpm stripe:trigger subscription.created +``` + +This uses the Stripe CLI (via Docker) to send test webhook events to your running server. + ## How It Works 1. **Creates Tables**: Runs database migrations to create Stripe schema tables @@ -75,13 +88,14 @@ stripe-sync 4. **Streams Changes**: Real-time syncing of all Stripe events to PostgreSQL The CLI automatically: -- Starts a Fastify server with `@supabase/stripe-sync-fastify` +- Starts a Docker container running `supabase/stripe-sync-engine:latest` - Creates an ngrok tunnel for webhook delivery - Registers a Stripe webhook with all events enabled -- Cleans up webhook and tunnel on exit (Ctrl-C) +- Cleans up webhook, container, and tunnel on exit (Ctrl-C) ## Prerequisites +- Docker to run the sync engine container - Node.js >= 22.0.0 - PostgreSQL database - Stripe API key ([Get one here](https://dashboard.stripe.com/apikeys)) @@ -121,6 +135,13 @@ This would: ## Troubleshooting +### "Docker is not running" or "Failed to start Docker container" + +Make sure Docker is installed and running: +- Install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/) +- Verify Docker is running: `docker ps` +- The CLI requires Docker to run the `supabase/stripe-sync-engine:latest` container + ### "Database configuration is required" Make sure you have set `DATABASE_URL` either via: From 530f83d46c64cafcfe7aa6ec850dadfe78ad3725 Mon Sep 17 00:00:00 2001 From: Luis Fernando De Pombo <2381303+depombo@users.noreply.github.com> Date: Mon, 10 Nov 2025 21:09:49 -0800 Subject: [PATCH 5/5] fix docker networking issue --- packages/cli/src/server.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index efb6217c3..528a9c66d 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -32,23 +32,35 @@ export async function startServer( const docker = new Docker() - // Create and start container + // Map database URL for container access: + // - Docker Desktop (macOS/Windows): use host.docker.internal + // - Linux with bridge network: add --add-host parameter + const containerDatabaseUrl = databaseUrl.replace('localhost', 'host.docker.internal') + + // Create and start container with port mapping (works on all platforms) const container = await docker.createContainer({ Image: 'supabase/stripe-sync-engine:latest', Env: [ - `DATABASE_URL=${databaseUrl}`, + `DATABASE_URL=${containerDatabaseUrl}`, `STRIPE_SECRET_KEY=${stripeApiKey}`, `STRIPE_WEBHOOK_SECRET=${stripeWebhookSecret}`, `API_KEY=${apiKey}`, - `PORT=${port}`, // Use the actual port since we're on host network + `PORT=${port}`, `SCHEMA=${process.env.SCHEMA || 'stripe'}`, `STRIPE_API_VERSION=${process.env.STRIPE_API_VERSION || '2020-08-27'}`, `AUTO_EXPAND_LISTS=${process.env.AUTO_EXPAND_LISTS || 'true'}`, `BACKFILL_RELATED_ENTITIES=${process.env.BACKFILL_RELATED_ENTITIES || 'true'}`, 'DISABLE_MIGRATIONS=false', ], + ExposedPorts: { + [`${port}/tcp`]: {}, + }, HostConfig: { - NetworkMode: 'host', // Use host network so container can access localhost + PortBindings: { + [`${port}/tcp`]: [{ HostPort: `${port}` }], + }, + // On Linux, map host.docker.internal to host gateway IP + ExtraHosts: ['host.docker.internal:host-gateway'], AutoRemove: true, }, })