diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index ba13fac..fa02998 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -15,6 +15,8 @@ env: WORKSPACES: create-db create-pg create-postgres CREATE_DB_WORKER_URL: ${{ secrets.CREATE_DB_WORKER_URL }} CLAIM_DB_WORKER_URL: ${{ secrets.CLAIM_DB_WORKER_URL }} + POSTHOG_API_HOST: ${{ secrets.POSTHOG_API_HOST }} + POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} jobs: preview: @@ -50,7 +52,8 @@ jobs: - name: ๐Ÿ”– Create unique preview tag run: | - echo "PRE_TAG=pr${{ github.event.number }}-${{ github.event.pull_request.head.ref }}-${{ github.run_id }}" >> $GITHUB_ENV + SAFE_REF=$(echo "${{ github.event.pull_request.head.ref }}" | tr '/' '-') + echo "PRE_TAG=pr${{ github.event.number }}-${SAFE_REF}-${{ github.run_id }}" >> $GITHUB_ENV # โ€” CF Worker preview deploys commented out; we will use pre-built URLs # - name: โ˜๏ธ Deploy create-db-worker (preview) @@ -73,6 +76,12 @@ jobs: run: echo "//registry.npmjs.org/:_authToken=${{ secrets.CREATE_DB_TOKEN_NPM }}" > ~/.npmrc - name: ๐Ÿš€ Bump & publish CLI previews + env: + WORKSPACES: create-db create-pg create-postgres + POSTHOG_API_HOST: ${{ secrets.POSTHOG_API_HOST }} + POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} + CREATE_DB_WORKER_URL: ${{ env.CREATE_DB_WORKER_URL }} + CLAIM_DB_WORKER_URL: ${{ env.CLAIM_DB_WORKER_URL }} run: | # Resolve URLs with fallback CREATE_DB_WORKER_URL="${{ steps.deploy-db.outputs.deployment-url || secrets.CREATE_DB_WORKER_URL }}" @@ -82,14 +91,18 @@ jobs: echo "CREATE_DB_WORKER_URL=$CREATE_DB_WORKER_URL" >> $GITHUB_ENV echo "CLAIM_DB_WORKER_URL=$CLAIM_DB_WORKER_URL" >> $GITHUB_ENV - export CREATE_DB_WORKER_URL - export CLAIM_DB_WORKER_URL echo "Using CREATE_DB_WORKER_URL=$CREATE_DB_WORKER_URL" echo "Using CLAIM_DB_WORKER_URL=$CLAIM_DB_WORKER_URL" + echo "Using POSTHOG_API_HOST=${POSTHOG_API_HOST}" for pkg in $WORKSPACES; do cd "$pkg" + export CREATE_DB_WORKER_URL + export CLAIM_DB_WORKER_URL + export POSTHOG_API_HOST="${POSTHOG_API_HOST}" + export POSTHOG_API_KEY="${POSTHOG_API_KEY}" + npm version prerelease \ --preid "$PRE_TAG" \ --no-git-tag-version diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9944ae3..c4030d4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,8 @@ concurrency: ${{ github.workflow }}-${{ github.ref }} env: WORKSPACES: create-db create-pg create-postgres + POSTHOG_API_HOST: ${{ secrets.POSTHOG_API_HOST }} + POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} jobs: release: @@ -44,10 +46,13 @@ jobs: run: | echo "Using CREATE_DB_WORKER_URL=${CREATE_DB_WORKER_URL}" echo "Using CLAIM_DB_WORKER_URL=${CLAIM_DB_WORKER_URL}" + echo "Using POSTHOG_API_HOST=${POSTHOG_API_HOST}" for pkg in $WORKSPACES; do echo "Publishing $pkg to npm..." cd "$pkg" + export POSTHOG_API_HOST="${{ secrets.POSTHOG_API_HOST }}" + export POSTHOG_API_KEY="${{ secrets.POSTHOG_API_KEY }}" # pnpm publish --access public || echo "Publish failed for $pkg" # First try to publish if ! pnpm publish --access public; then @@ -61,6 +66,8 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.CREATE_DB_TOKEN_NPM }} CREATE_DB_WORKER_URL: ${{ secrets.CREATE_DB_WORKER_URL }} CLAIM_DB_WORKER_URL: ${{ secrets.CLAIM_DB_WORKER_URL }} + POSTHOG_API_HOST: ${{ secrets.POSTHOG_API_HOST }} + POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} - name: ๐Ÿงน Cleanup npm auth run: rm -f ~/.npmrc diff --git a/create-db/README.md b/create-db/README.md index b3ebf69..20d6483 100644 --- a/create-db/README.md +++ b/create-db/README.md @@ -2,8 +2,6 @@ `create-db` is an open-source CLI tool that provisions [**temporary Prisma Postgres databases**](https://www.prisma.io/postgres?utm_source=create_db_npm_docs) with a single command. -![Demo Gif](demo.gif) - Each database is available for **24 hours** by default. To keep the database permanently, you can **claim it for free** using the URL displayed in the CLI output. This tool is designed for developers who need a fast way to test, prototype, or integrate Prisma Postgres without manual setup or creating an account. diff --git a/create-db/analytics.js b/create-db/analytics.js new file mode 100644 index 0000000..197c4b6 --- /dev/null +++ b/create-db/analytics.js @@ -0,0 +1,50 @@ +import { randomUUID } from "crypto"; + +class EventCaptureError extends Error { + constructor(event, status) { + super(`Failed to submit PostHog event '${event}': ${status}`); + } +} + +class PosthogEventCapture { + async capture(eventName, properties = {}) { + const POSTHOG_CAPTURE_URL = process.env.POSTHOG_API_HOST + ? process.env.POSTHOG_API_HOST + "/capture" + : "https://proxyhog.prisma-data.net/capture"; + const POSTHOG_KEY = process.env.POSTHOG_API_KEY || "phc_cmc85avbWyuJ2JyKdGPdv7dxXli8xLdWDBPbvIXWJfs"; + + const payload = { + api_key: POSTHOG_KEY, + event: eventName, + distinct_id: randomUUID(), + properties: { + $process_person_profile: false, + ...properties, + }, + }; + + try { + const response = await fetch(POSTHOG_CAPTURE_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }); + + if (!response.ok) { + throw new EventCaptureError(eventName, response.statusText); + } + } catch (error) { + // Silently fail analytics to not disrupt user experience + if (process.env.NODE_ENV === "development") { + console.error("Analytics error:", error.message); + } + } + } +} + +// Create a singleton instance +const analytics = new PosthogEventCapture(); + +export { analytics, EventCaptureError }; diff --git a/create-db/demo.gif b/create-db/demo.gif deleted file mode 100644 index b9fcbd0..0000000 Binary files a/create-db/demo.gif and /dev/null differ diff --git a/create-db/index.js b/create-db/index.js index d7ea13b..b5fd1b4 100755 --- a/create-db/index.js +++ b/create-db/index.js @@ -1,5 +1,8 @@ #!/usr/bin/env node +import dotenv from "dotenv"; +dotenv.config(); + import { select, spinner, @@ -7,13 +10,10 @@ import { outro, log, cancel, - confirm, } from "@clack/prompts"; import chalk from "chalk"; -import dotenv from "dotenv"; import terminalLink from "terminal-link"; - -dotenv.config(); +import { analytics } from "./analytics.js"; const CREATE_DB_WORKER_URL = process.env.CREATE_DB_WORKER_URL || "https://create-db-temp.prisma.io"; @@ -265,6 +265,17 @@ async function promptForRegion(defaultRegion) { process.exit(0); } + // Track region selection event + try { + await analytics.capture("create_db:region_selected", { + command: CLI_NAME, + region: region, + "selection-method": "interactive" + }); + } catch (error) { + // Silently fail analytics + } + return region; } @@ -284,6 +295,19 @@ async function createDatabase(name, region) { s.stop( "We're experiencing a high volume of requests. Please try again later." ); + + // Track database creation failure + try { + await analytics.capture("create_db:database_creation_failed", { + command: CLI_NAME, + region: region, + "error-type": "rate_limit", + "status-code": 429, + }); + } catch (error) { + // Silently fail analytics + } + process.exit(1); } @@ -293,6 +317,18 @@ async function createDatabase(name, region) { s.stop( `Error creating database: ${result.error.message || "Unknown error"}` ); + + // Track database creation failure + try { + await analytics.capture("create_db:database_creation_failed", { + command: CLI_NAME, + region: region, + "error-type": "api_error", + "error-message": result.error.message, + }); + } catch (error) { + // Silently fail analytics + } process.exit(1); } @@ -362,6 +398,23 @@ async function createDatabase(name, region) { async function main() { try { + const rawArgs = process.argv.slice(2); + try { + await analytics.capture("create_db:cli_command_ran", { + command: CLI_NAME, + "full-command": `${CLI_NAME} ${rawArgs.join(' ')}`.trim(), + "has-region-flag": rawArgs.includes('--region') || rawArgs.includes('-r'), + "has-interactive-flag": rawArgs.includes('--interactive') || rawArgs.includes('-i'), + "has-help-flag": rawArgs.includes('--help') || rawArgs.includes('-h'), + "has-list-regions-flag": rawArgs.includes('--list-regions'), + "node-version": process.version, + platform: process.platform, + arch: process.arch + }); + } catch (error) { + // Silently fail analytics + } + // Parse command line arguments const { flags } = await parseArgs(); @@ -386,6 +439,17 @@ async function main() { // Apply command line flags if (flags.region) { region = flags.region; + + // Track region selection via flag + try { + await analytics.capture("create_db:region_selected", { + command: CLI_NAME, + region: region, + "selection-method": "flag" + }); + } catch (error) { + // Silently fail analytics + } } if (flags.interactive) { chooseRegionPrompt = true; diff --git a/create-db/package.json b/create-db/package.json index 8bbeb0d..ad48c9a 100644 --- a/create-db/package.json +++ b/create-db/package.json @@ -1,6 +1,6 @@ { "name": "create-db", - "version": "0.0.12", + "version": "0.0.14", "description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.", "main": "index.js", "author": "", @@ -39,6 +39,6 @@ "files": [ "index.js", "README.md", - "demo.gif" + "analytics.js" ] } diff --git a/create-pg/package.json b/create-pg/package.json index 6fce2ad..55e3ed3 100644 --- a/create-pg/package.json +++ b/create-pg/package.json @@ -1,6 +1,6 @@ { "name": "create-pg", - "version": "0.0.12", + "version": "0.0.14", "description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.", "main": "index.js", "author": "", diff --git a/create-postgres/package.json b/create-postgres/package.json index 2a7f0fb..a4016a7 100644 --- a/create-postgres/package.json +++ b/create-postgres/package.json @@ -1,6 +1,6 @@ { "name": "create-postgres", - "version": "0.0.12", + "version": "0.0.14", "description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.", "main": "index.js", "author": "", diff --git a/package.json b/package.json index 93adb95..8db2339 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "create-db-monorepo", - "version": "0.0.2", + "version": "0.0.10", "private": true, "scripts": { "changeset": "changeset",