Skip to content

Commit 0762850

Browse files
committed
Initial migration system
1 parent d3f49ff commit 0762850

File tree

11 files changed

+1351
-16
lines changed

11 files changed

+1351
-16
lines changed

bin.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ import { runMCPInstall, runMCPRemove } from './src/mcp';
2121
import type { CloudRegion, WizardOptions } from './src/utils/types';
2222
import { runWizard } from './src/run';
2323
import { runEventSetupWizard } from './src/nextjs/event-setup';
24+
import {
25+
runMigrationWizard,
26+
getAvailableMigrationProviders,
27+
type MigrationOptions,
28+
} from './src/migrate';
2429
import {
2530
readEnvironment,
2631
isNonInteractiveEnvironment,
@@ -155,6 +160,62 @@ yargs(hideBin(process.argv))
155160
void runEventSetupWizard(wizardOptions);
156161
},
157162
)
163+
.command(
164+
'migrate',
165+
'Migrate from another analytics provider to PostHog',
166+
(yargs) => {
167+
const availableProviders = getAvailableMigrationProviders();
168+
return yargs
169+
.options({
170+
'install-dir': {
171+
describe:
172+
'Directory to run the migration in\nenv: POSTHOG_WIZARD_INSTALL_DIR',
173+
type: 'string',
174+
},
175+
'force-install': {
176+
default: false,
177+
describe:
178+
'Force install packages even if peer dependency checks fail\nenv: POSTHOG_WIZARD_FORCE_INSTALL',
179+
type: 'boolean',
180+
},
181+
from: {
182+
describe: 'Analytics provider to migrate from',
183+
choices: availableProviders,
184+
default: 'amplitude',
185+
type: 'string',
186+
},
187+
});
188+
},
189+
(argv) => {
190+
const finalArgs = {
191+
...argv,
192+
...readEnvironment(),
193+
} as any;
194+
195+
let resolvedInstallDir: string;
196+
if (finalArgs.installDir) {
197+
if (path.isAbsolute(finalArgs.installDir)) {
198+
resolvedInstallDir = finalArgs.installDir;
199+
} else {
200+
resolvedInstallDir = path.join(process.cwd(), finalArgs.installDir);
201+
}
202+
} else {
203+
resolvedInstallDir = process.cwd();
204+
}
205+
206+
const migrationOptions: MigrationOptions = {
207+
debug: finalArgs.debug ?? false,
208+
installDir: resolvedInstallDir,
209+
cloudRegion: finalArgs.region as CloudRegion | undefined,
210+
default: finalArgs.default ?? false,
211+
signup: finalArgs.signup ?? false,
212+
forceInstall: finalArgs.forceInstall ?? false,
213+
localMcp: finalArgs.localMcp ?? false,
214+
};
215+
216+
void runMigrationWizard(migrationOptions, finalArgs.from as string);
217+
},
218+
)
158219
.command('mcp <command>', 'MCP server management commands', (yargs) => {
159220
return yargs
160221
.command(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"newContent": "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { PostHogProvider } from 'posthog-js/react'\nimport './index.css'\nimport App from './App.tsx'\n\ncreateRoot(document.getElementById('root')!).render(\n <StrictMode>\n <PostHogProvider\n apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY}\n options={{\n api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,\n defaults: '2025-05-24',\n capture_exceptions: true,\n debug: import.meta.env.MODE === 'development',\n }}\n >\n <App />\n </PostHogProvider>\n </StrictMode>,\n)\n"
2+
"newContent": "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport posthog from 'posthog-js'\nimport { PostHogProvider } from 'posthog-js/react'\nimport './index.css'\nimport App from './App.tsx'\n\nposthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, {\n api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,\n defaults: '2025-05-24',\n capture_exceptions: true,\n debug: import.meta.env.MODE === 'development',\n});\n\ncreateRoot(document.getElementById('root')!).render(\n <StrictMode>\n <PostHogProvider client={posthog}>\n <App />\n </PostHogProvider>\n </StrictMode>,\n)\n"
33
}

src/lib/constants.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ export enum Integration {
66
astro = 'astro',
77
}
88

9+
export enum MigrationSource {
10+
amplitude = 'amplitude',
11+
}
12+
13+
export function getMigrationSourceDescription(source: MigrationSource): string {
14+
switch (source) {
15+
case MigrationSource.amplitude:
16+
return 'Amplitude';
17+
default:
18+
throw new Error(`Unknown migration source ${source}`);
19+
}
20+
}
21+
922
export enum FeatureFlagDefinition {
1023
NextV2 = 'wizard-next-v2',
1124
}

src/lib/prompts.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,82 @@ Here are the files that have not been changed yet:
7979
Below is the current file contents:
8080
{file_content}`,
8181
});
82+
83+
export const migrationFilterFilesPromptTemplate = new PromptTemplate({
84+
inputVariables: [
85+
'documentation',
86+
'file_list',
87+
'source_sdk',
88+
'integration_rules',
89+
],
90+
template: `You are a PostHog migration wizard, a master AI programming assistant that migrates projects from {source_sdk} to PostHog.
91+
Given the following list of file paths from a project, determine which files contain {source_sdk} code that needs to be migrated to PostHog.
92+
93+
- Look for files that import or use {source_sdk} SDK
94+
- Look for files that initialize {source_sdk}
95+
- Look for files that track events with {source_sdk}
96+
- Look for files that identify users with {source_sdk}
97+
- Look for configuration files that may reference {source_sdk}
98+
99+
You should return all files that contain {source_sdk} code that needs to be migrated. Return them in the order you would like to see them processed.
100+
101+
Rules:
102+
- Only return files that actually contain {source_sdk} code or references
103+
- Do not return files that don't use {source_sdk}
104+
- If you are unsure, return the file, since it's better to have more files than less
105+
- Include any configuration or initialization files
106+
{integration_rules}
107+
108+
Migration documentation:
109+
{documentation}
110+
111+
All current files in the repository:
112+
113+
{file_list}`,
114+
});
115+
116+
export const migrationGenerateFileChangesPromptTemplate = new PromptTemplate({
117+
inputVariables: [
118+
'file_content',
119+
'documentation',
120+
'file_path',
121+
'changed_files',
122+
'unchanged_files',
123+
'source_sdk',
124+
'integration_rules',
125+
],
126+
template: `You are a PostHog migration wizard, a master AI programming assistant that migrates projects from {source_sdk} to PostHog.
127+
128+
Your task is to migrate the file from {source_sdk} to PostHog according to the migration documentation.
129+
Do not return a diff — you should return the complete updated file content.
130+
131+
Rules:
132+
- Replace ALL {source_sdk} imports with PostHog imports
133+
- Replace ALL {source_sdk} initialization code with PostHog initialization
134+
- Replace ALL {source_sdk} tracking calls with PostHog equivalents
135+
- Replace ALL {source_sdk} identify calls with PostHog equivalents
136+
- Remove ALL {source_sdk}-specific code that has no PostHog equivalent
137+
- Preserve the existing code formatting and style
138+
- Make sure to remove any unused {source_sdk} imports after migration
139+
- If the file has no {source_sdk} code after review, return it unchanged
140+
{integration_rules}
141+
142+
143+
CONTEXT
144+
---
145+
146+
Migration documentation from {source_sdk} to PostHog:
147+
{documentation}
148+
149+
The file you are updating is:
150+
{file_path}
151+
152+
Here are the changes you have already made to the project:
153+
{changed_files}
154+
155+
Here are the files that have not been changed yet:
156+
{unchanged_files}
157+
158+
Below is the current file contents:
159+
{file_content}`,
160+
});

src/migrate/index.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
export {
2+
runMigrationWizard,
3+
checkAndOfferMigration,
4+
detectProviderInstallation,
5+
getAllInstalledProviderPackages,
6+
} from './migration-wizard';
7+
8+
export type {
9+
MigrationProviderConfig,
10+
InstalledPackage,
11+
MigrationOptions,
12+
MigrationDocsOptions,
13+
MigrationContext,
14+
MigrationOutroOptions,
15+
} from './types';
16+
17+
export {
18+
getMigrationProvider,
19+
getAvailableMigrationProviders,
20+
migrationProviders,
21+
amplitudeProvider,
22+
} from './providers';
23+
24+
export { AMPLITUDE_PACKAGES } from './providers/amplitude';
25+
26+
import { runMigrationWizard, checkAndOfferMigration } from './migration-wizard';
27+
import type { MigrationOptions } from './types';
28+
import type { WizardOptions } from '../utils/types';
29+
30+
export async function runAmplitudeMigrationWizard(
31+
options: MigrationOptions,
32+
): Promise<void> {
33+
return runMigrationWizard(options, 'amplitude');
34+
}
35+
36+
export async function checkAndOfferAmplitudeMigration(
37+
options: WizardOptions,
38+
): Promise<boolean> {
39+
return checkAndOfferMigration(options, 'amplitude');
40+
}

0 commit comments

Comments
 (0)