|
| 1 | +/* Java (server) wizard using posthog-agent with PostHog MCP */ |
| 2 | +import fg from 'fast-glob'; |
| 3 | +import * as fs from 'node:fs'; |
| 4 | +import * as path from 'node:path'; |
| 5 | +import type { WizardRunOptions } from '@utils/types'; |
| 6 | +import type { FrameworkConfig } from '@lib/framework-config'; |
| 7 | +import { detectJavaPackageManagers } from '@lib/detection/package-manager'; |
| 8 | +import { Integration } from '@lib/constants'; |
| 9 | + |
| 10 | +type JavaContext = { |
| 11 | + buildTool?: 'maven' | 'gradle'; |
| 12 | +}; |
| 13 | + |
| 14 | +const GRADLE_FILES = [ |
| 15 | + 'build.gradle', |
| 16 | + 'build.gradle.kts', |
| 17 | + 'settings.gradle', |
| 18 | + 'settings.gradle.kts', |
| 19 | +]; |
| 20 | + |
| 21 | +const ANDROID_GRADLE_MARKERS = [ |
| 22 | + 'com.android.application', |
| 23 | + 'com.android.library', |
| 24 | + 'com.android.tools.build:gradle', |
| 25 | +]; |
| 26 | + |
| 27 | +const KMP_GRADLE_MARKERS = [ |
| 28 | + 'kotlin("multiplatform")', |
| 29 | + 'org.jetbrains.kotlin.multiplatform', |
| 30 | + 'kotlin-multiplatform', |
| 31 | +]; |
| 32 | + |
| 33 | +function readRootGradleFiles(installDir: string): string[] { |
| 34 | + return GRADLE_FILES.map((name) => path.join(installDir, name)) |
| 35 | + .filter((p) => fs.existsSync(p)) |
| 36 | + .map((p) => fs.readFileSync(p, 'utf-8')); |
| 37 | +} |
| 38 | + |
| 39 | +function getBuildTool(installDir: string): 'maven' | 'gradle' | undefined { |
| 40 | + if (fs.existsSync(path.join(installDir, 'pom.xml'))) { |
| 41 | + return 'maven'; |
| 42 | + } |
| 43 | + if (readRootGradleFiles(installDir).length > 0) { |
| 44 | + return 'gradle'; |
| 45 | + } |
| 46 | + return undefined; |
| 47 | +} |
| 48 | + |
| 49 | +export const JAVA_AGENT_CONFIG: FrameworkConfig<JavaContext> = { |
| 50 | + metadata: { |
| 51 | + name: 'Java', |
| 52 | + integration: Integration.java, |
| 53 | + docsUrl: 'https://posthog.com/docs/libraries/java', |
| 54 | + gatherContext: (options: WizardRunOptions) => { |
| 55 | + const buildTool = getBuildTool(options.installDir); |
| 56 | + return Promise.resolve({ buildTool }); |
| 57 | + }, |
| 58 | + }, |
| 59 | + |
| 60 | + detection: { |
| 61 | + packageName: 'posthog-server', |
| 62 | + packageDisplayName: 'Java', |
| 63 | + usesPackageJson: false, |
| 64 | + getVersion: () => undefined, |
| 65 | + // Maven projects (pom.xml) are unambiguously JVM backends. Gradle |
| 66 | + // projects are only claimed when they are neither Android nor KMP — |
| 67 | + // those detectors are ordered earlier, and this re-check keeps a |
| 68 | + // direct java detect() call from ever claiming their projects. |
| 69 | + detect: async (options) => { |
| 70 | + const { installDir } = options; |
| 71 | + |
| 72 | + // pubspec.yaml means Flutter — its gradle subtree is not a JVM backend. |
| 73 | + if (fs.existsSync(path.join(installDir, 'pubspec.yaml'))) { |
| 74 | + return false; |
| 75 | + } |
| 76 | + |
| 77 | + if (fs.existsSync(path.join(installDir, 'pom.xml'))) { |
| 78 | + return true; |
| 79 | + } |
| 80 | + |
| 81 | + const gradleContents = readRootGradleFiles(installDir); |
| 82 | + if (gradleContents.length === 0) { |
| 83 | + return false; |
| 84 | + } |
| 85 | + const combined = gradleContents.join('\n'); |
| 86 | + if ( |
| 87 | + [...ANDROID_GRADLE_MARKERS, ...KMP_GRADLE_MARKERS].some((marker) => |
| 88 | + combined.includes(marker), |
| 89 | + ) |
| 90 | + ) { |
| 91 | + return false; |
| 92 | + } |
| 93 | + |
| 94 | + const manifestFiles = await fg('**/AndroidManifest.xml', { |
| 95 | + cwd: installDir, |
| 96 | + ignore: ['**/build/**', '**/node_modules/**', '**/.gradle/**'], |
| 97 | + }); |
| 98 | + return manifestFiles.length === 0; |
| 99 | + }, |
| 100 | + detectPackageManager: detectJavaPackageManagers, |
| 101 | + }, |
| 102 | + |
| 103 | + environment: { |
| 104 | + uploadToHosting: false, |
| 105 | + getEnvVars: (apiKey: string, host: string) => ({ |
| 106 | + POSTHOG_API_KEY: apiKey, |
| 107 | + POSTHOG_HOST: host, |
| 108 | + }), |
| 109 | + }, |
| 110 | + |
| 111 | + analytics: { |
| 112 | + getTags: (context) => ({ |
| 113 | + buildTool: context.buildTool || 'unknown', |
| 114 | + }), |
| 115 | + }, |
| 116 | + |
| 117 | + prompts: { |
| 118 | + projectTypeDetection: |
| 119 | + 'This is a Java server project. Look for pom.xml (Maven) or build.gradle/build.gradle.kts (Gradle), src/main/java/, and the framework in use (Spring Boot, Quarkus, Micronaut, plain servlets) to confirm.', |
| 120 | + packageInstallation: |
| 121 | + 'Neither Maven nor Gradle has a single add command. Add the com.posthog:posthog-server dependency (pinned to the latest release on Maven Central) to pom.xml or build.gradle(.kts), matching the existing dependency format, then run `mvn install` or `gradle build` to resolve it.', |
| 122 | + getAdditionalContextLines: (context) => { |
| 123 | + const lines = [ |
| 124 | + `Framework docs ID: java (use posthog://docs/frameworks/java for documentation)`, |
| 125 | + 'Use the posthog-server SDK (com.posthog:posthog-server) — posthog-android is a different library and must not be used on the server.', |
| 126 | + 'Create one PostHog client per process with PostHogConfig.builder(...) and PostHog.with(config); call close() during graceful shutdown, and flush() before returning in serverless handlers.', |
| 127 | + ]; |
| 128 | + if (context.buildTool) { |
| 129 | + lines.push(`Build tool: ${context.buildTool}`); |
| 130 | + } |
| 131 | + return lines; |
| 132 | + }, |
| 133 | + }, |
| 134 | + |
| 135 | + ui: { |
| 136 | + successMessage: 'PostHog integration complete', |
| 137 | + estimatedDurationMinutes: 5, |
| 138 | + getOutroChanges: (context) => [ |
| 139 | + 'Analyzed your Java project structure', |
| 140 | + `Added the posthog-server dependency to your ${ |
| 141 | + context.buildTool === 'maven' ? 'pom.xml' : 'Gradle build' |
| 142 | + }`, |
| 143 | + 'Initialized a shared PostHog client configured from environment variables', |
| 144 | + 'Instrumented meaningful server events with posthog.capture', |
| 145 | + ], |
| 146 | + getOutroNextSteps: () => [ |
| 147 | + 'Run your Java service and trigger the instrumented code paths', |
| 148 | + 'Visit your PostHog dashboard to see incoming events', |
| 149 | + 'Use posthog.capture(distinctId, eventName, options) to track custom events', |
| 150 | + 'Keep posthog.close() in your graceful shutdown path so queued events flush', |
| 151 | + ], |
| 152 | + }, |
| 153 | +}; |
0 commit comments