@posthog/wizard 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/src/lib/constants.d.ts +1 -1
  2. package/dist/src/lib/constants.js +1 -1
  3. package/dist/src/lib/constants.js.map +1 -1
  4. package/dist/src/mcp.js +12 -13
  5. package/dist/src/mcp.js.map +1 -1
  6. package/dist/src/nextjs/docs.js +0 -12
  7. package/dist/src/nextjs/docs.js.map +1 -1
  8. package/dist/src/steps/add-mcp-server-to-clients/MCPClient.d.ts +3 -0
  9. package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js +4 -1
  10. package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js.map +1 -1
  11. package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.js +1 -1
  12. package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.js.map +1 -1
  13. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.d.ts +60 -0
  14. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js +53 -0
  15. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js.map +1 -0
  16. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.d.ts +3 -0
  17. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js +3 -0
  18. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js.map +1 -1
  19. package/dist/src/steps/add-mcp-server-to-clients/defaults.d.ts +3 -1
  20. package/dist/src/steps/add-mcp-server-to-clients/defaults.js +2 -2
  21. package/dist/src/steps/add-mcp-server-to-clients/defaults.js.map +1 -1
  22. package/dist/src/steps/add-mcp-server-to-clients/index.js +35 -26
  23. package/dist/src/steps/add-mcp-server-to-clients/index.js.map +1 -1
  24. package/dist/src/steps/upload-environment-variables/providers/vercel.js +1 -1
  25. package/dist/src/steps/upload-environment-variables/providers/vercel.js.map +1 -1
  26. package/package.json +1 -1
@@ -21,6 +21,6 @@ export declare const DEFAULT_URL: string;
21
21
  export declare const ISSUES_URL = "https://github.com/posthog/wizard/issues";
22
22
  export declare const DEFAULT_HOST_URL: string;
23
23
  export declare const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = "sTMFPsFhdP1Ssg";
24
- export declare const ANALYTICS_HOST_URL = "https://internal-t.posthog.com";
24
+ export declare const ANALYTICS_HOST_URL = "https://internal-j.posthog.com";
25
25
  export declare const DUMMY_PROJECT_API_KEY = "_YOUR_POSTHOG_PROJECT_API_KEY_";
26
26
  export {};
@@ -43,6 +43,6 @@ exports.DEFAULT_HOST_URL = exports.IS_DEV
43
43
  ? 'http://localhost:8010'
44
44
  : 'https://us.i.posthog.com';
45
45
  exports.ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';
46
- exports.ANALYTICS_HOST_URL = 'https://internal-t.posthog.com';
46
+ exports.ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';
47
47
  exports.DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';
48
48
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":";;;AAQA,8DAeC;AAOD,sDAKC;AAnCD,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,gCAAiB,CAAA;IACjB,2CAA4B,CAAA;IAC5B,8BAAe,CAAA;AACjB,CAAC,EANW,WAAW,2BAAX,WAAW,QAMtB;AAED,SAAgB,yBAAyB,CAAC,IAAY;IACpD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,SAAS,CAAC;QACnB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,OAAO,CAAC;QACjB,KAAK,WAAW,CAAC,WAAW;YAC1B,OAAO,cAAc,CAAC;QACxB,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,QAAQ,CAAC;QAClB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,OAAO,CAAC;QACjB;YACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAOD,SAAgB,qBAAqB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,EAAE,yBAAyB,CAAC,IAAI,CAAC;QACrC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC,CAAC;AACN,CAAC;AAOY,QAAA,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAC3B,CAAC;AAEW,QAAA,KAAK,GAAG,KAAK,CAAC;AAEd,QAAA,WAAW,GAAG,cAAM;IAC/B,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,wBAAwB,CAAC;AAChB,QAAA,UAAU,GAAG,0CAA0C,CAAC;AACxD,QAAA,gBAAgB,GAAG,cAAM;IACpC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,0BAA0B,CAAC;AAClB,QAAA,0CAA0C,GAAG,gBAAgB,CAAC;AAC9D,QAAA,kBAAkB,GAAG,gCAAgC,CAAC;AACtD,QAAA,qBAAqB,GAAG,gCAAgC,CAAC","sourcesContent":["export enum Integration {\n nextjs = 'nextjs',\n react = 'react',\n svelte = 'svelte',\n reactNative = 'react-native',\n astro = 'astro',\n}\n\nexport function getIntegrationDescription(type: string): string {\n switch (type) {\n case Integration.nextjs:\n return 'Next.js';\n case Integration.react:\n return 'React';\n case Integration.reactNative:\n return 'React Native';\n case Integration.svelte:\n return 'Svelte';\n case Integration.astro:\n return 'Astro';\n default:\n throw new Error(`Unknown integration ${type}`);\n }\n}\n\ntype IntegrationChoice = {\n name: string;\n value: string;\n};\n\nexport function getIntegrationChoices(): IntegrationChoice[] {\n return Object.keys(Integration).map((type: string) => ({\n name: getIntegrationDescription(type),\n value: type,\n }));\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\nexport const IS_DEV = ['test', 'development'].includes(\n process.env.NODE_ENV ?? '',\n);\n\nexport const DEBUG = false;\n\nexport const DEFAULT_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.i.posthog.com';\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-t.posthog.com';\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":";;;AAQA,8DAeC;AAOD,sDAKC;AAnCD,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,gCAAiB,CAAA;IACjB,2CAA4B,CAAA;IAC5B,8BAAe,CAAA;AACjB,CAAC,EANW,WAAW,2BAAX,WAAW,QAMtB;AAED,SAAgB,yBAAyB,CAAC,IAAY;IACpD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,SAAS,CAAC;QACnB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,OAAO,CAAC;QACjB,KAAK,WAAW,CAAC,WAAW;YAC1B,OAAO,cAAc,CAAC;QACxB,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,QAAQ,CAAC;QAClB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,OAAO,CAAC;QACjB;YACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAOD,SAAgB,qBAAqB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,EAAE,yBAAyB,CAAC,IAAI,CAAC;QACrC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC,CAAC;AACN,CAAC;AAOY,QAAA,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAC3B,CAAC;AAEW,QAAA,KAAK,GAAG,KAAK,CAAC;AAEd,QAAA,WAAW,GAAG,cAAM;IAC/B,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,wBAAwB,CAAC;AAChB,QAAA,UAAU,GAAG,0CAA0C,CAAC;AACxD,QAAA,gBAAgB,GAAG,cAAM;IACpC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,0BAA0B,CAAC;AAClB,QAAA,0CAA0C,GAAG,gBAAgB,CAAC;AAC9D,QAAA,kBAAkB,GAAG,gCAAgC,CAAC;AACtD,QAAA,qBAAqB,GAAG,gCAAgC,CAAC","sourcesContent":["export enum Integration {\n nextjs = 'nextjs',\n react = 'react',\n svelte = 'svelte',\n reactNative = 'react-native',\n astro = 'astro',\n}\n\nexport function getIntegrationDescription(type: string): string {\n switch (type) {\n case Integration.nextjs:\n return 'Next.js';\n case Integration.react:\n return 'React';\n case Integration.reactNative:\n return 'React Native';\n case Integration.svelte:\n return 'Svelte';\n case Integration.astro:\n return 'Astro';\n default:\n throw new Error(`Unknown integration ${type}`);\n }\n}\n\ntype IntegrationChoice = {\n name: string;\n value: string;\n};\n\nexport function getIntegrationChoices(): IntegrationChoice[] {\n return Object.keys(Integration).map((type: string) => ({\n name: getIntegrationDescription(type),\n value: type,\n }));\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\nexport const IS_DEV = ['test', 'development'].includes(\n process.env.NODE_ENV ?? '',\n);\n\nexport const DEBUG = false;\n\nexport const DEFAULT_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.i.posthog.com';\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';\n"]}
package/dist/src/mcp.js CHANGED
@@ -12,31 +12,30 @@ const opn_1 = __importDefault(require("opn"));
12
12
  const urls_1 = require("./utils/urls");
13
13
  const helper_functions_1 = require("./lib/helper-functions");
14
14
  const runMCPInstall = async (options) => {
15
- clack_1.default.intro('Installing the PostHog MCP server.');
15
+ clack_1.default.intro(chalk_1.default.bgGreenBright('Installing the PostHog MCP server'));
16
16
  await (0, add_mcp_server_to_clients_1.addMCPServerToClientsStep)({
17
17
  cloudRegion: options.region,
18
18
  askPermission: false,
19
19
  });
20
- clack_1.default.outro(`${chalk_1.default.green('You might need to restart your MCP clients to see the changes.')}
21
-
22
- Get started with some prompts like:
23
-
24
- - What feature flags do I have active?
25
- - Add a new feature flag for our homepage redesign
26
- - What are my most common errors?
27
- `);
20
+ clack_1.default.log.message(`${chalk_1.default.greenBright('You might need to restart your MCP clients to see the changes.')}`);
21
+ clack_1.default.log.message(`Get started with some prompts like:
22
+ - What feature flags do I have active?
23
+ - Add a new feature flag for our homepage redesign
24
+ - What are my most common errors?`);
25
+ clack_1.default.log.message(`Check out our MCP Server documentation:
26
+ ${chalk_1.default.blueBright(`https://posthog.com/docs/model-context-protocol`)}`);
28
27
  };
29
28
  exports.runMCPInstall = runMCPInstall;
30
29
  const runMCPRemove = async () => {
30
+ clack_1.default.intro(chalk_1.default.bgRed('Removing the PostHog MCP server'));
31
31
  const results = await (0, add_mcp_server_to_clients_1.removeMCPServerFromClientsStep)({});
32
32
  if (results.length === 0) {
33
33
  clack_1.default.outro(`No PostHog MCP servers found to remove.`);
34
34
  return;
35
35
  }
36
- clack_1.default.outro(`PostHog MCP server removed from:
37
- ${results.map((c) => `- ${c}`).join('\n ')}
38
-
39
- ${chalk_1.default.green('You might need to restart your MCP clients to see the changes.')}`);
36
+ clack_1.default.log.success(`PostHog MCP server removed from:`);
37
+ results.map((c) => clack_1.default.log.message(`- ${c}`));
38
+ clack_1.default.outro(`${chalk_1.default.green('You might need to restart your MCP clients to see the changes.\n\n')}`);
40
39
  };
41
40
  exports.runMCPRemove = runMCPRemove;
42
41
  const getPersonalApiKey = async (options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/mcp.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,iFAG2C;AAC3C,0DAAkC;AAClC,qDAA4C;AAE5C,8CAAsB;AACtB,uCAAqD;AACrD,6DAA+C;AAExC,MAAM,aAAa,GAAG,KAAK,EAAE,OAGnC,EAAE,EAAE;IACH,eAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAElD,MAAM,IAAA,qDAAyB,EAAC;QAC9B,WAAW,EAAE,OAAO,CAAC,MAAM;QAC3B,aAAa,EAAE,KAAK;KACrB,CAAC,CAAC;IAEH,eAAK,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,KAAK,CACxB,gEAAgE,CACjE;;;;;;;CAOF,CAAC,CAAC;AACH,CAAC,CAAC;AArBW,QAAA,aAAa,iBAqBxB;AAEK,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;IACrC,MAAM,OAAO,GAAG,MAAM,IAAA,0DAA8B,EAAC,EAAE,CAAC,CAAC;IAEzD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,eAAK,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IAED,eAAK,CAAC,KAAK,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;;IAEzC,eAAK,CAAC,KAAK,CACX,gEAAgE,CACjE,EAAE,CAAC,CAAC;AACP,CAAC,CAAC;AAdW,QAAA,YAAY,gBAcvB;AAEK,MAAM,iBAAiB,GAAG,KAAK,EAAE,OAEvC,EAAmB,EAAE;IACpB,MAAM,QAAQ,GAAG,IAAA,4BAAqB,EAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE5D,MAAM,SAAS,GAAG,GAAG,QAAQ,2CAA2C,CAAC;IAEzE,MAAM,OAAO,GAAG,eAAK,CAAC,OAAO,EAAE,CAAC;IAChC,OAAO,CAAC,KAAK,CACX,oEAAoE,CACrE,CAAC;IAEF,MAAM,IAAA,wBAAK,EAAC,IAAI,CAAC,CAAC;IAElB,OAAO,CAAC,IAAI,CACV,8IAA8I,eAAK,CAAC,IAAI,CACtJ,SAAS,CACV,EAAE,CACJ,CAAC;IAEF,IAAA,aAAG,EAAC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACzC,iGAAiG;IACnG,CAAC,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,eAAK,CAAC,QAAQ,CAAC;QAC1C,OAAO,EAAE,iCAAiC;QAC1C,QAAQ,CAAC,KAAK;YACZ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,oBAAoB,CAAC;YAEpD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,OAAO,6FAA6F,CAAC;YACvG,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAA,mBAAK,EAAC,+CAA+C,CAAC,CAAC;QAC7D,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,cAAwB,CAAC;AAClC,CAAC,CAAC;AAzCW,QAAA,iBAAiB,qBAyC5B","sourcesContent":["import chalk from 'chalk';\nimport {\n addMCPServerToClientsStep,\n removeMCPServerFromClientsStep,\n} from './steps/add-mcp-server-to-clients';\nimport clack from './utils/clack';\nimport { abort } from './utils/clack-utils';\nimport type { CloudRegion } from './utils/types';\nimport opn from 'opn';\nimport { getCloudUrlFromRegion } from './utils/urls';\nimport { sleep } from './lib/helper-functions';\n\nexport const runMCPInstall = async (options: {\n signup: boolean;\n region?: CloudRegion;\n}) => {\n clack.intro('Installing the PostHog MCP server.');\n\n await addMCPServerToClientsStep({\n cloudRegion: options.region,\n askPermission: false,\n });\n\n clack.outro(`${chalk.green(\n 'You might need to restart your MCP clients to see the changes.',\n )}\n\nGet started with some prompts like:\n\n - What feature flags do I have active?\n - Add a new feature flag for our homepage redesign\n - What are my most common errors?\n`);\n};\n\nexport const runMCPRemove = async () => {\n const results = await removeMCPServerFromClientsStep({});\n\n if (results.length === 0) {\n clack.outro(`No PostHog MCP servers found to remove.`);\n return;\n }\n\n clack.outro(`PostHog MCP server removed from:\n ${results.map((c) => `- ${c}`).join('\\n ')}\n \n ${chalk.green(\n 'You might need to restart your MCP clients to see the changes.',\n )}`);\n};\n\nexport const getPersonalApiKey = async (options: {\n cloudRegion: CloudRegion;\n}): Promise<string> => {\n const cloudUrl = getCloudUrlFromRegion(options.cloudRegion);\n\n const urlToOpen = `${cloudUrl}/settings/user-api-keys?preset=mcp_server`;\n\n const spinner = clack.spinner();\n spinner.start(\n `Opening your project settings so you can get a Personal API key...`,\n );\n\n await sleep(1500);\n\n spinner.stop(\n `Opened your project settings. If the link didn't open automatically, open the following URL in your browser to get a Personal API key: \\n\\n${chalk.cyan(\n urlToOpen,\n )}`,\n );\n\n opn(urlToOpen, { wait: false }).catch(() => {\n // opn throws in environments that don't have a browser (e.g. remote shells) so we just noop here\n });\n\n const personalApiKey = await clack.password({\n message: 'Paste in your Personal API key:',\n validate(value) {\n if (value.length === 0) return `Value is required!`;\n\n if (!value.startsWith('phx_')) {\n return `That doesn't look right, are you sure you copied the right key? It should start with 'phx_'`;\n }\n },\n });\n\n if (!personalApiKey) {\n await abort('Unable to proceed without a personal API key.');\n return '';\n }\n\n return personalApiKey as string;\n};\n"]}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport {\n addMCPServerToClientsStep,\n removeMCPServerFromClientsStep,\n} from './steps/add-mcp-server-to-clients';\nimport clack from './utils/clack';\nimport { abort } from './utils/clack-utils';\nimport type { CloudRegion } from './utils/types';\nimport opn from 'opn';\nimport { getCloudUrlFromRegion } from './utils/urls';\nimport { sleep } from './lib/helper-functions';\n\nexport const runMCPInstall = async (options: {\n signup: boolean;\n region?: CloudRegion;\n}) => {\n clack.intro(chalk.bgGreenBright('Installing the PostHog MCP server'));\n\n await addMCPServerToClientsStep({\n cloudRegion: options.region,\n askPermission: false,\n });\n\n clack.log.message(\n `${chalk.greenBright(\n 'You might need to restart your MCP clients to see the changes.',\n )}`,\n );\n\n clack.log.message(`Get started with some prompts like:\n- What feature flags do I have active?\n- Add a new feature flag for our homepage redesign\n- What are my most common errors?`);\n\n clack.log.message(`Check out our MCP Server documentation:\n${chalk.blueBright(`https://posthog.com/docs/model-context-protocol`)}`);\n};\n\nexport const runMCPRemove = async () => {\n clack.intro(chalk.bgRed('Removing the PostHog MCP server'));\n const results = await removeMCPServerFromClientsStep({});\n\n if (results.length === 0) {\n clack.outro(`No PostHog MCP servers found to remove.`);\n return;\n }\n\n clack.log.success(`PostHog MCP server removed from:`);\n results.map((c) => clack.log.message(`- ${c}`));\n clack.outro(\n `${chalk.green(\n 'You might need to restart your MCP clients to see the changes.\\n\\n',\n )}`,\n );\n};\n\nexport const getPersonalApiKey = async (options: {\n cloudRegion: CloudRegion;\n}): Promise<string> => {\n const cloudUrl = getCloudUrlFromRegion(options.cloudRegion);\n\n const urlToOpen = `${cloudUrl}/settings/user-api-keys?preset=mcp_server`;\n\n const spinner = clack.spinner();\n spinner.start(\n `Opening your project settings so you can get a Personal API key...`,\n );\n\n await sleep(1500);\n\n spinner.stop(\n `Opened your project settings. If the link didn't open automatically, open the following URL in your browser to get a Personal API key: \\n\\n${chalk.cyan(\n urlToOpen,\n )}`,\n );\n\n opn(urlToOpen, { wait: false }).catch(() => {\n // opn throws in environments that don't have a browser (e.g. remote shells) so we just noop here\n });\n\n const personalApiKey = await clack.password({\n message: 'Paste in your Personal API key:',\n validate(value) {\n if (value.length === 0) return `Value is required!`;\n\n if (!value.startsWith('phx_')) {\n return `That doesn't look right, are you sure you copied the right key? It should start with 'phx_'`;\n }\n },\n });\n\n if (!personalApiKey) {\n await abort('Unable to proceed without a personal API key.');\n return '';\n }\n\n return personalApiKey as string;\n};\n"]}
@@ -112,10 +112,6 @@ const nextConfig = {
112
112
  source: "/ingest/:path*",
113
113
  destination: "${host}/:path*",
114
114
  },
115
- {
116
- source: "/ingest/flags",
117
- destination: "${host}/flags",
118
- },
119
115
  ];
120
116
  },
121
117
  // This is required to support PostHog trailing slash API requests
@@ -206,10 +202,6 @@ const nextConfig = {
206
202
  source: "/ingest/:path*",
207
203
  destination: "${host}/:path*",
208
204
  },
209
- {
210
- source: "/ingest/flags",
211
- destination: "${host}/flags",
212
- },
213
205
  ];
214
206
  },
215
207
  // This is required to support PostHog trailing slash API requests
@@ -268,10 +260,6 @@ const nextConfig = {
268
260
  source: "/ingest/:path*",
269
261
  destination: "${host}/:path*",
270
262
  },
271
- {
272
- source: "/ingest/flags",
273
- destination: "${host}/flags",
274
- },
275
263
  ];
276
264
  },
277
265
  // This is required to support PostHog trailing slash API requests
@@ -1 +1 @@
1
- {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/nextjs/docs.ts"],"names":[],"mappings":";;;AAAA,wCAAwE;AAEjE,MAAM,sBAAsB,GAAG,CAAC,EACrC,IAAI,EACJ,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO;;wBAGL,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KACtC;;;;;;;;;;;;;;;;;;;;kBAoBgB,IAAA,wBAAiB,EAAC,IAAI,CAAC;;;;;;;;;;;;;;;;eAgB1B,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA2BxC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAsC/B,IAAA,2BAAoB,EAAC,IAAI,CAAC;;;;wBAI1B,IAAI;;;;wBAIJ,IAAI;;;;;;;;mDAQuB,CAAC;AACpD,CAAC,CAAC;AAjIW,QAAA,sBAAsB,0BAiIjC;AAEK,MAAM,wBAAwB,GAAG,CAAC,EACvC,IAAI,EACJ,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO;;aAEI,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;mCAElD,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KACtC;;;;;;;;;;;;;;;;;kBAiBgB,IAAA,wBAAiB,EAAC,IAAI,CAAC;;;;;;;;;;;;;;;;gBAgBzB,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAsC/B,IAAA,2BAAoB,EAAC,IAAI,CAAC;;;;wBAI1B,IAAI;;;;wBAIJ,IAAI;;;;;;;;mDAQuB,CAAC;AACpD,CAAC,CAAC;AApGW,QAAA,wBAAwB,4BAoGnC;AAEK,MAAM,mBAAmB,GAAG,CAAC,EAClC,IAAI,EACJ,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO;;+BAEsB,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;gDAKlE,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IACrC;2CAEE,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IACrC;;;;;;;;;;;cAWY,IAAA,wBAAiB,EAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;wBAwBb,IAAA,2BAAoB,EAAC,IAAI,CAAC;;;;wBAI1B,IAAI;;;;wBAIJ,IAAI;;;;;;;;mDAQuB,CAAC;AACpD,CAAC,CAAC;AAtEW,QAAA,mBAAmB,uBAsE9B","sourcesContent":["import { getAssetHostFromHost, getUiHostFromHost } from '../utils/urls';\n\nexport const getNextjsAppRouterDocs = ({\n host,\n language,\n}: {\n host: string;\n language: 'typescript' | 'javascript';\n}) => {\n return `\n==============================\nFILE: PostHogProvider.${\n language === 'typescript' ? 'tsx' : 'jsx'\n } (put it somewhere where client files are, like the components folder)\nLOCATION: Wherever other providers are, or the components folder\n==============================\nChanges:\n- Create a PostHogProvider component that will be imported into the layout file.\n- Make sure to include the defaults: '2025-05-24' option in the init call.\n\nExample:\n--------------------------------------------------\n\"use client\"\n\nimport posthog from \"posthog-js\"\nimport { PostHogProvider as PHProvider, usePostHog } from \"posthog-js/react\"\nimport { Suspense, useEffect } from \"react\"\nimport { usePathname, useSearchParams } from \"next/navigation\"\n\nexport function PostHogProvider({ children }: { children: React.ReactNode }) {\n useEffect(() => {\n posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n api_host: \"/ingest\",\n ui_host: \"${getUiHostFromHost(host)}\",\n defaults: '2025-05-24',\n capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this\n debug: process.env.NODE_ENV === \"development\",\n })\n }, [])\n\n return (\n <PHProvider client={posthog}>\n {children}\n </PHProvider>\n )\n}\n--------------------------------------------------\n\n==============================\nFILE: layout.${language === 'typescript' ? 'tsx' : 'jsx'}\nLOCATION: Wherever the root layout is\n==============================\nChanges:\n- Import the PostHogProvider from the providers file and wrap the app in it.\n\nExample:\n--------------------------------------------------\n// other imports\nimport { PostHogProvider } from \"LOCATION_OF_POSTHOG_PROVIDER\"\n\nexport default function RootLayout({ children }) {\n return (\n <html lang=\"en\">\n <body>\n <PostHogProvider>\n {/* other providers */}\n {children}\n {/* other providers */}\n </PostHogProvider>\n </body>\n </html>\n )\n}\n--------------------------------------------------\n\n==============================\nFILE: posthog.${language === 'typescript' ? 'ts' : 'js'}\nLOCATION: Wherever works best given the project structure\n==============================\nChanges:\n- Initialize the PostHog Node.js client\n\nExample:\n--------------------------------------------------\nimport { PostHog } from \"posthog-node\"\n\n// NOTE: This is a Node.js client, so you can use it for sending events from the server side to PostHog.\nexport default function PostHogClient() {\n const posthogClient = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n host: process.env.NEXT_PUBLIC_POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 0,\n })\n return posthogClient\n}\n--------------------------------------------------\n\n==============================\nFILE: next.config.{js,ts,mjs,cjs}\nLOCATION: Wherever the root next config is\n==============================\nChanges:\n- Add rewrites to the Next.js config to support PostHog, if there are existing rewrites, add the PostHog rewrites to them.\n- Add skipTrailingSlashRedirect to the Next.js config to support PostHog trailing slash API requests.\n- This can be of type js, ts, mjs, cjs etc. You should adapt the file according to what extension it uses, and if it does not exist yet use '.js'.\n\nExample:\n--------------------------------------------------\nconst nextConfig = {\n // other config\n async rewrites() {\n return [\n {\n source: \"/ingest/static/:path*\",\n destination: \"${getAssetHostFromHost(host)}/static/:path*\",\n },\n {\n source: \"/ingest/:path*\",\n destination: \"${host}/:path*\",\n },\n {\n source: \"/ingest/flags\",\n destination: \"${host}/flags\",\n },\n ];\n },\n // This is required to support PostHog trailing slash API requests\n skipTrailingSlashRedirect: true,\n}\nmodule.exports = nextConfig\n--------------------------------------------------`;\n};\n\nexport const getNextjsPagesRouterDocs = ({\n host,\n language,\n}: {\n host: string;\n language: 'typescript' | 'javascript';\n}) => {\n return `\n==============================\nFILE: _app.${language === 'typescript' ? 'tsx' : 'jsx'}\nLOCATION: Wherever the root _app.${\n language === 'typescript' ? 'tsx' : 'jsx'\n } file is\n==============================\nChanges:\n- Initialize PostHog in _app.js.\n- Wrap the application in PostHogProvider.\n- Make sure to include the defaults: '2025-05-24' option in the init call.\n\nExample:\n--------------------------------------------------\nimport { useEffect } from \"react\"\nimport posthog from \"posthog-js\"\nimport { PostHogProvider } from \"posthog-js/react\"\n\nexport default function App({ Component, pageProps }) {\n useEffect(() => {\n posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {\n api_host: \"/ingest\",\n ui_host: \"${getUiHostFromHost(host)}\",\n defaults: '2025-05-24',\n capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this\n debug: process.env.NODE_ENV === \"development\",\n })\n }, [])\n\n return (\n <PostHogProvider client={posthog}>\n <Component {...pageProps} />\n </PostHogProvider>\n )\n}\n--------------------------------------------------\n\n==============================\nFILE: posthog.${language === 'typescript' ? 'ts' : 'js'}\nLOCATION: Wherever works best given the project structure\n==============================\nChanges:\n- Initialize the PostHog Node.js client\n\nExample:\n--------------------------------------------------\nimport { PostHog } from \"posthog-node\"\n\n// NOTE: This is a Node.js client, so you can use it for sending events from the server side to PostHog.\nexport default function PostHogClient() {\n const posthogClient = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n host: process.env.NEXT_PUBLIC_POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 0,\n })\n return posthogClient\n}\n--------------------------------------------------\n\n==============================\nFILE: next.config.{js,ts,mjs,cjs}\nLOCATION: Wherever the root next config is\n==============================\nChanges:\n- Add rewrites to the Next.js config to support PostHog, if there are existing rewrites, add the PostHog rewrites to them.\n- Add skipTrailingSlashRedirect to the Next.js config to support PostHog trailing slash API requests.\n- This can be of type js, ts, mjs, cjs etc. You should adapt the file according to what extension it uses, and if it does not exist yet use '.js'.\n\nExample:\n--------------------------------------------------\nconst nextConfig = {\n // other config\n async rewrites() {\n return [\n {\n source: \"/ingest/static/:path*\",\n destination: \"${getAssetHostFromHost(host)}/static/:path*\",\n },\n {\n source: \"/ingest/:path*\",\n destination: \"${host}/:path*\",\n },\n {\n source: \"/ingest/flags\",\n destination: \"${host}/flags\",\n },\n ];\n },\n // This is required to support PostHog trailing slash API requests\n skipTrailingSlashRedirect: true,\n}\nmodule.exports = nextConfig\n--------------------------------------------------`;\n};\n\nexport const getModernNextjsDocs = ({\n host,\n language,\n}: {\n host: string;\n language: 'typescript' | 'javascript';\n}) => {\n return `\n==============================\nFILE: instrumentation-client.${language === 'typescript' ? 'ts' : 'js'}\nLOCATION: in the root of the application or inside an src folder.\n==============================\nChanges:\n- Create or update the instrumentation-client.${\n language === 'typescript' ? 'ts' : 'js'\n } file to use the PostHog client. If the file does not exist yet, create it.\n- Do *not* import instrumentation-client.${\n language === 'typescript' ? 'ts' : 'js'\n } in any other file; Next.js will automatically handle it.\n- Do not modify any other pages/components in the Next.js application; the PostHog client will be automatically initialized and handle all pageview tasks on its own.\n- Make sure to include the defaults: '2025-05-24' option in the init call.\n\nExample:\n--------------------------------------------------\n\nimport posthog from \"posthog-js\"\n\nposthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n api_host: \"/ingest\",\n ui_host: \"${getUiHostFromHost(host)}\",\n defaults: '2025-05-24',\n capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this\n debug: process.env.NODE_ENV === \"development\",\n});\n--------------------------------------------------\n\n==============================\nFILE: next.config.{js,ts,mjs,cjs}\nLOCATION: Wherever the root next config is\n==============================\nChanges:\n- Add rewrites to the Next.js config to support PostHog, if there are existing rewrites, add the PostHog rewrites to them.\n- Add skipTrailingSlashRedirect to the Next.js config to support PostHog trailing slash API requests.\n- This can be of type js, ts, mjs, cjs etc. You should adapt the file according to what extension it uses, and if it does not exist yet use '.js'.\n\nExample:\n--------------------------------------------------\nconst nextConfig = {\n // other config\n async rewrites() {\n return [\n {\n source: \"/ingest/static/:path*\",\n destination: \"${getAssetHostFromHost(host)}/static/:path*\",\n },\n {\n source: \"/ingest/:path*\",\n destination: \"${host}/:path*\",\n },\n {\n source: \"/ingest/flags\",\n destination: \"${host}/flags\",\n },\n ];\n },\n // This is required to support PostHog trailing slash API requests\n skipTrailingSlashRedirect: true,\n}\nmodule.exports = nextConfig\n--------------------------------------------------`;\n};\n"]}
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/nextjs/docs.ts"],"names":[],"mappings":";;;AAAA,wCAAwE;AAEjE,MAAM,sBAAsB,GAAG,CAAC,EACrC,IAAI,EACJ,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO;;wBAGL,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KACtC;;;;;;;;;;;;;;;;;;;;kBAoBgB,IAAA,wBAAiB,EAAC,IAAI,CAAC;;;;;;;;;;;;;;;;eAgB1B,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA2BxC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAsC/B,IAAA,2BAAoB,EAAC,IAAI,CAAC;;;;wBAI1B,IAAI;;;;;;;;mDAQuB,CAAC;AACpD,CAAC,CAAC;AA7HW,QAAA,sBAAsB,0BA6HjC;AAEK,MAAM,wBAAwB,GAAG,CAAC,EACvC,IAAI,EACJ,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO;;aAEI,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;mCAElD,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KACtC;;;;;;;;;;;;;;;;;kBAiBgB,IAAA,wBAAiB,EAAC,IAAI,CAAC;;;;;;;;;;;;;;;;gBAgBzB,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAsC/B,IAAA,2BAAoB,EAAC,IAAI,CAAC;;;;wBAI1B,IAAI;;;;;;;;mDAQuB,CAAC;AACpD,CAAC,CAAC;AAhGW,QAAA,wBAAwB,4BAgGnC;AAEK,MAAM,mBAAmB,GAAG,CAAC,EAClC,IAAI,EACJ,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO;;+BAEsB,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;gDAKlE,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IACrC;2CAEE,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IACrC;;;;;;;;;;;cAWY,IAAA,wBAAiB,EAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;wBAwBb,IAAA,2BAAoB,EAAC,IAAI,CAAC;;;;wBAI1B,IAAI;;;;;;;;mDAQuB,CAAC;AACpD,CAAC,CAAC;AAlEW,QAAA,mBAAmB,uBAkE9B","sourcesContent":["import { getAssetHostFromHost, getUiHostFromHost } from '../utils/urls';\n\nexport const getNextjsAppRouterDocs = ({\n host,\n language,\n}: {\n host: string;\n language: 'typescript' | 'javascript';\n}) => {\n return `\n==============================\nFILE: PostHogProvider.${\n language === 'typescript' ? 'tsx' : 'jsx'\n } (put it somewhere where client files are, like the components folder)\nLOCATION: Wherever other providers are, or the components folder\n==============================\nChanges:\n- Create a PostHogProvider component that will be imported into the layout file.\n- Make sure to include the defaults: '2025-05-24' option in the init call.\n\nExample:\n--------------------------------------------------\n\"use client\"\n\nimport posthog from \"posthog-js\"\nimport { PostHogProvider as PHProvider, usePostHog } from \"posthog-js/react\"\nimport { Suspense, useEffect } from \"react\"\nimport { usePathname, useSearchParams } from \"next/navigation\"\n\nexport function PostHogProvider({ children }: { children: React.ReactNode }) {\n useEffect(() => {\n posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n api_host: \"/ingest\",\n ui_host: \"${getUiHostFromHost(host)}\",\n defaults: '2025-05-24',\n capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this\n debug: process.env.NODE_ENV === \"development\",\n })\n }, [])\n\n return (\n <PHProvider client={posthog}>\n {children}\n </PHProvider>\n )\n}\n--------------------------------------------------\n\n==============================\nFILE: layout.${language === 'typescript' ? 'tsx' : 'jsx'}\nLOCATION: Wherever the root layout is\n==============================\nChanges:\n- Import the PostHogProvider from the providers file and wrap the app in it.\n\nExample:\n--------------------------------------------------\n// other imports\nimport { PostHogProvider } from \"LOCATION_OF_POSTHOG_PROVIDER\"\n\nexport default function RootLayout({ children }) {\n return (\n <html lang=\"en\">\n <body>\n <PostHogProvider>\n {/* other providers */}\n {children}\n {/* other providers */}\n </PostHogProvider>\n </body>\n </html>\n )\n}\n--------------------------------------------------\n\n==============================\nFILE: posthog.${language === 'typescript' ? 'ts' : 'js'}\nLOCATION: Wherever works best given the project structure\n==============================\nChanges:\n- Initialize the PostHog Node.js client\n\nExample:\n--------------------------------------------------\nimport { PostHog } from \"posthog-node\"\n\n// NOTE: This is a Node.js client, so you can use it for sending events from the server side to PostHog.\nexport default function PostHogClient() {\n const posthogClient = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n host: process.env.NEXT_PUBLIC_POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 0,\n })\n return posthogClient\n}\n--------------------------------------------------\n\n==============================\nFILE: next.config.{js,ts,mjs,cjs}\nLOCATION: Wherever the root next config is\n==============================\nChanges:\n- Add rewrites to the Next.js config to support PostHog, if there are existing rewrites, add the PostHog rewrites to them.\n- Add skipTrailingSlashRedirect to the Next.js config to support PostHog trailing slash API requests.\n- This can be of type js, ts, mjs, cjs etc. You should adapt the file according to what extension it uses, and if it does not exist yet use '.js'.\n\nExample:\n--------------------------------------------------\nconst nextConfig = {\n // other config\n async rewrites() {\n return [\n {\n source: \"/ingest/static/:path*\",\n destination: \"${getAssetHostFromHost(host)}/static/:path*\",\n },\n {\n source: \"/ingest/:path*\",\n destination: \"${host}/:path*\",\n },\n ];\n },\n // This is required to support PostHog trailing slash API requests\n skipTrailingSlashRedirect: true,\n}\nmodule.exports = nextConfig\n--------------------------------------------------`;\n};\n\nexport const getNextjsPagesRouterDocs = ({\n host,\n language,\n}: {\n host: string;\n language: 'typescript' | 'javascript';\n}) => {\n return `\n==============================\nFILE: _app.${language === 'typescript' ? 'tsx' : 'jsx'}\nLOCATION: Wherever the root _app.${\n language === 'typescript' ? 'tsx' : 'jsx'\n } file is\n==============================\nChanges:\n- Initialize PostHog in _app.js.\n- Wrap the application in PostHogProvider.\n- Make sure to include the defaults: '2025-05-24' option in the init call.\n\nExample:\n--------------------------------------------------\nimport { useEffect } from \"react\"\nimport posthog from \"posthog-js\"\nimport { PostHogProvider } from \"posthog-js/react\"\n\nexport default function App({ Component, pageProps }) {\n useEffect(() => {\n posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {\n api_host: \"/ingest\",\n ui_host: \"${getUiHostFromHost(host)}\",\n defaults: '2025-05-24',\n capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this\n debug: process.env.NODE_ENV === \"development\",\n })\n }, [])\n\n return (\n <PostHogProvider client={posthog}>\n <Component {...pageProps} />\n </PostHogProvider>\n )\n}\n--------------------------------------------------\n\n==============================\nFILE: posthog.${language === 'typescript' ? 'ts' : 'js'}\nLOCATION: Wherever works best given the project structure\n==============================\nChanges:\n- Initialize the PostHog Node.js client\n\nExample:\n--------------------------------------------------\nimport { PostHog } from \"posthog-node\"\n\n// NOTE: This is a Node.js client, so you can use it for sending events from the server side to PostHog.\nexport default function PostHogClient() {\n const posthogClient = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n host: process.env.NEXT_PUBLIC_POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 0,\n })\n return posthogClient\n}\n--------------------------------------------------\n\n==============================\nFILE: next.config.{js,ts,mjs,cjs}\nLOCATION: Wherever the root next config is\n==============================\nChanges:\n- Add rewrites to the Next.js config to support PostHog, if there are existing rewrites, add the PostHog rewrites to them.\n- Add skipTrailingSlashRedirect to the Next.js config to support PostHog trailing slash API requests.\n- This can be of type js, ts, mjs, cjs etc. You should adapt the file according to what extension it uses, and if it does not exist yet use '.js'.\n\nExample:\n--------------------------------------------------\nconst nextConfig = {\n // other config\n async rewrites() {\n return [\n {\n source: \"/ingest/static/:path*\",\n destination: \"${getAssetHostFromHost(host)}/static/:path*\",\n },\n {\n source: \"/ingest/:path*\",\n destination: \"${host}/:path*\",\n },\n ];\n },\n // This is required to support PostHog trailing slash API requests\n skipTrailingSlashRedirect: true,\n}\nmodule.exports = nextConfig\n--------------------------------------------------`;\n};\n\nexport const getModernNextjsDocs = ({\n host,\n language,\n}: {\n host: string;\n language: 'typescript' | 'javascript';\n}) => {\n return `\n==============================\nFILE: instrumentation-client.${language === 'typescript' ? 'ts' : 'js'}\nLOCATION: in the root of the application or inside an src folder.\n==============================\nChanges:\n- Create or update the instrumentation-client.${\n language === 'typescript' ? 'ts' : 'js'\n } file to use the PostHog client. If the file does not exist yet, create it.\n- Do *not* import instrumentation-client.${\n language === 'typescript' ? 'ts' : 'js'\n } in any other file; Next.js will automatically handle it.\n- Do not modify any other pages/components in the Next.js application; the PostHog client will be automatically initialized and handle all pageview tasks on its own.\n- Make sure to include the defaults: '2025-05-24' option in the init call.\n\nExample:\n--------------------------------------------------\n\nimport posthog from \"posthog-js\"\n\nposthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {\n api_host: \"/ingest\",\n ui_host: \"${getUiHostFromHost(host)}\",\n defaults: '2025-05-24',\n capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this\n debug: process.env.NODE_ENV === \"development\",\n});\n--------------------------------------------------\n\n==============================\nFILE: next.config.{js,ts,mjs,cjs}\nLOCATION: Wherever the root next config is\n==============================\nChanges:\n- Add rewrites to the Next.js config to support PostHog, if there are existing rewrites, add the PostHog rewrites to them.\n- Add skipTrailingSlashRedirect to the Next.js config to support PostHog trailing slash API requests.\n- This can be of type js, ts, mjs, cjs etc. You should adapt the file according to what extension it uses, and if it does not exist yet use '.js'.\n\nExample:\n--------------------------------------------------\nconst nextConfig = {\n // other config\n async rewrites() {\n return [\n {\n source: \"/ingest/static/:path*\",\n destination: \"${getAssetHostFromHost(host)}/static/:path*\",\n },\n {\n source: \"/ingest/:path*\",\n destination: \"${host}/:path*\",\n },\n ];\n },\n // This is required to support PostHog trailing slash API requests\n skipTrailingSlashRedirect: true,\n}\nmodule.exports = nextConfig\n--------------------------------------------------`;\n};\n"]}
@@ -17,6 +17,9 @@ export declare abstract class DefaultMCPClient extends MCPClient {
17
17
  addServer(apiKey: string): Promise<{
18
18
  success: boolean;
19
19
  }>;
20
+ _addServerType(apiKey: string, type: 'sse' | 'streamable-http'): Promise<{
21
+ success: boolean;
22
+ }>;
20
23
  removeServer(): Promise<{
21
24
  success: boolean;
22
25
  }>;
@@ -62,13 +62,16 @@ class DefaultMCPClient extends MCPClient {
62
62
  }
63
63
  }
64
64
  async addServer(apiKey) {
65
+ return this._addServerType(apiKey, 'sse');
66
+ }
67
+ async _addServerType(apiKey, type) {
65
68
  try {
66
69
  const configPath = await this.getConfigPath();
67
70
  const configDir = path.dirname(configPath);
68
71
  await fs.promises.mkdir(configDir, { recursive: true });
69
72
  const newServerConfig = {
70
73
  mcpServers: {
71
- posthog: (0, defaults_1.getDefaultServerConfig)(apiKey),
74
+ posthog: (0, defaults_1.getDefaultServerConfig)(apiKey, type),
72
75
  },
73
76
  };
74
77
  let existingConfig = {};
@@ -1 +1 @@
1
- {"version":3,"file":"MCPClient.js","sourceRoot":"","sources":["../../../../src/steps/add-mcp-server-to-clients/MCPClient.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { getDefaultServerConfig } from './defaults';\nimport { merge } from 'lodash';\n\nexport abstract class MCPClient {\n name: string;\n abstract getConfigPath(): Promise<string>;\n abstract isServerInstalled(): Promise<boolean>;\n abstract addServer(apiKey: string): Promise<{ success: boolean }>;\n abstract removeServer(): Promise<{ success: boolean }>;\n abstract isClientSupported(): Promise<boolean>;\n}\n\nexport abstract class DefaultMCPClient extends MCPClient {\n name = 'Default';\n\n constructor() {\n super();\n }\n async isServerInstalled(): Promise<boolean> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return false;\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = JSON.parse(configContent);\n\n return 'mcpServers' in config && 'posthog' in config.mcpServers;\n } catch {\n return false;\n }\n }\n\n async addServer(apiKey: string): Promise<{ success: boolean }> {\n try {\n const configPath = await this.getConfigPath();\n const configDir = path.dirname(configPath);\n\n await fs.promises.mkdir(configDir, { recursive: true });\n\n const newServerConfig = {\n mcpServers: {\n posthog: getDefaultServerConfig(apiKey),\n },\n };\n\n let existingConfig = {};\n\n if (fs.existsSync(configPath)) {\n const existingContent = await fs.promises.readFile(configPath, 'utf8');\n existingConfig = JSON.parse(existingContent);\n }\n\n const mergedConfig = merge({}, existingConfig, newServerConfig);\n\n await fs.promises.writeFile(\n configPath,\n JSON.stringify(mergedConfig, null, 2),\n 'utf8',\n );\n\n return { success: true };\n } catch {\n //\n }\n return { success: false };\n }\n\n async removeServer(): Promise<{ success: boolean }> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return { success: false };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = JSON.parse(configContent);\n\n if ('mcpServers' in config && 'posthog' in config.mcpServers) {\n delete config.mcpServers.posthog;\n\n await fs.promises.writeFile(\n configPath,\n JSON.stringify(config, null, 2),\n 'utf8',\n );\n\n return { success: true };\n }\n } catch {\n //\n }\n\n return { success: false };\n }\n}\n"]}
1
+ {"version":3,"file":"MCPClient.js","sourceRoot":"","sources":["../../../../src/steps/add-mcp-server-to-clients/MCPClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAC7B,yCAAoD;AACpD,mCAA+B;AAE/B,MAAsB,SAAS;IAC7B,IAAI,CAAS;CAMd;AAPD,8BAOC;AAED,MAAsB,gBAAiB,SAAQ,SAAS;IACtD,IAAI,GAAG,SAAS,CAAC;IAEjB;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IACD,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAE9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAEzC,OAAO,YAAY,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAc;QAC5B,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,MAAc,EACd,IAA+B;QAE/B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAE3C,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAExD,MAAM,eAAe,GAAG;gBACtB,UAAU,EAAE;oBACV,OAAO,EAAE,IAAA,iCAAsB,EAAC,MAAM,EAAE,IAAI,CAAC;iBAC9C;aACF,CAAC;YAEF,IAAI,cAAc,GAAG,EAAE,CAAC;YAExB,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,MAAM,eAAe,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;gBACvE,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAC/C,CAAC;YAED,MAAM,YAAY,GAAG,IAAA,cAAK,EAAC,EAAE,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;YAEhE,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CACzB,UAAU,EACV,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,EACrC,MAAM,CACP,CAAC;YAEF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,EAAE;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAE9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC5B,CAAC;YAED,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAEzC,IAAI,YAAY,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBAC7D,OAAO,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;gBAEjC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CACzB,UAAU,EACV,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAC/B,MAAM,CACP,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,EAAE;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF;AA7FD,4CA6FC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { getDefaultServerConfig } from './defaults';\nimport { merge } from 'lodash';\n\nexport abstract class MCPClient {\n name: string;\n abstract getConfigPath(): Promise<string>;\n abstract isServerInstalled(): Promise<boolean>;\n abstract addServer(apiKey: string): Promise<{ success: boolean }>;\n abstract removeServer(): Promise<{ success: boolean }>;\n abstract isClientSupported(): Promise<boolean>;\n}\n\nexport abstract class DefaultMCPClient extends MCPClient {\n name = 'Default';\n\n constructor() {\n super();\n }\n async isServerInstalled(): Promise<boolean> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return false;\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = JSON.parse(configContent);\n\n return 'mcpServers' in config && 'posthog' in config.mcpServers;\n } catch {\n return false;\n }\n }\n\n async addServer(apiKey: string): Promise<{ success: boolean }> {\n return this._addServerType(apiKey, 'sse');\n }\n\n async _addServerType(\n apiKey: string,\n type: 'sse' | 'streamable-http',\n ): Promise<{ success: boolean }> {\n try {\n const configPath = await this.getConfigPath();\n const configDir = path.dirname(configPath);\n\n await fs.promises.mkdir(configDir, { recursive: true });\n\n const newServerConfig = {\n mcpServers: {\n posthog: getDefaultServerConfig(apiKey, type),\n },\n };\n\n let existingConfig = {};\n\n if (fs.existsSync(configPath)) {\n const existingContent = await fs.promises.readFile(configPath, 'utf8');\n existingConfig = JSON.parse(existingContent);\n }\n\n const mergedConfig = merge({}, existingConfig, newServerConfig);\n\n await fs.promises.writeFile(\n configPath,\n JSON.stringify(mergedConfig, null, 2),\n 'utf8',\n );\n\n return { success: true };\n } catch {\n //\n }\n return { success: false };\n }\n\n async removeServer(): Promise<{ success: boolean }> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return { success: false };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = JSON.parse(configContent);\n\n if ('mcpServers' in config && 'posthog' in config.mcpServers) {\n delete config.mcpServers.posthog;\n\n await fs.promises.writeFile(\n configPath,\n JSON.stringify(config, null, 2),\n 'utf8',\n );\n\n return { success: true };\n }\n } catch {\n //\n }\n\n return { success: false };\n }\n}\n"]}
@@ -268,7 +268,7 @@ describe('ClaudeMCPClient', () => {
268
268
  it('should call getDefaultServerConfig with the provided API key', async () => {
269
269
  existsSyncMock.mockReturnValue(false);
270
270
  await client.addServer(mockApiKey);
271
- expect(getDefaultServerConfigMock).toHaveBeenCalledWith(mockApiKey);
271
+ expect(getDefaultServerConfigMock).toHaveBeenCalledWith(mockApiKey, 'sse');
272
272
  });
273
273
  });
274
274
  describe('removeServer', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"claude.test.js","sourceRoot":"","sources":["../../../../../../src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.ts"],"names":[],"mappings":"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","sourcesContent":["// We use the ClaudeMCPClient as a reference to test the DefaultMCPClient\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { ClaudeMCPClient } from '../claude';\nimport { getDefaultServerConfig } from '../../defaults';\n\njest.mock('fs', () => ({\n promises: {\n mkdir: jest.fn(),\n readFile: jest.fn(),\n writeFile: jest.fn(),\n },\n existsSync: jest.fn(),\n}));\n\njest.mock('os', () => ({\n homedir: jest.fn(),\n}));\n\njest.mock('../../defaults', () => ({\n DefaultMCPClientConfig: {\n parse: jest.fn(),\n },\n getDefaultServerConfig: jest.fn(),\n}));\n\ndescribe('ClaudeMCPClient', () => {\n let client: ClaudeMCPClient;\n const mockHomeDir = '/mock/home';\n const mockApiKey = 'test-api-key';\n const mockServerConfig = {\n command: 'npx',\n args: ['-y', 'mcp-remote@latest'],\n env: { POSTHOG_AUTH_HEADER: `Bearer ${mockApiKey}` },\n };\n\n const mkdirMock = fs.promises.mkdir as jest.Mock;\n const readFileMock = fs.promises.readFile as jest.Mock;\n const writeFileMock = fs.promises.writeFile as jest.Mock;\n const existsSyncMock = fs.existsSync as jest.Mock;\n const homedirMock = os.homedir as jest.Mock;\n const getDefaultServerConfigMock = getDefaultServerConfig as jest.Mock;\n\n const originalPlatform = process.platform;\n\n beforeEach(() => {\n client = new ClaudeMCPClient();\n jest.clearAllMocks();\n homedirMock.mockReturnValue(mockHomeDir);\n getDefaultServerConfigMock.mockReturnValue(mockServerConfig);\n\n // Mock the Zod schema parse method\n const { DefaultMCPClientConfig } = require('../../defaults');\n DefaultMCPClientConfig.parse.mockImplementation((data: any) => data);\n });\n\n afterEach(() => {\n Object.defineProperty(process, 'platform', {\n value: originalPlatform,\n writable: true,\n });\n });\n\n describe('constructor', () => {\n it('should set the correct name', () => {\n expect(client.name).toBe('Claude Desktop');\n });\n });\n\n describe('isClientSupported', () => {\n it('should return true for macOS', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(true);\n });\n\n it('should return true for Windows', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'win32',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(true);\n });\n\n it('should return false for Linux', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'linux',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(false);\n });\n\n it('should return false for other platforms', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'freebsd',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(false);\n });\n });\n\n describe('getConfigPath', () => {\n it('should return correct path for macOS', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n\n const configPath = await client.getConfigPath();\n expect(configPath).toBe(\n path.join(\n mockHomeDir,\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json',\n ),\n );\n });\n\n it('should return correct path for Windows', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'win32',\n writable: true,\n });\n\n const mockAppData = 'C:\\\\Users\\\\Test\\\\AppData\\\\Roaming';\n process.env.APPDATA = mockAppData;\n\n const configPath = await client.getConfigPath();\n expect(configPath).toBe(\n path.join(mockAppData, 'Claude', 'claude_desktop_config.json'),\n );\n });\n\n it('should throw error for unsupported platform', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'linux',\n writable: true,\n });\n\n await expect(client.getConfigPath()).rejects.toThrow(\n 'Unsupported platform: linux',\n );\n });\n });\n\n describe('isServerInstalled', () => {\n beforeEach(() => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n });\n\n it('should return false when config file does not exist', async () => {\n existsSyncMock.mockReturnValue(false);\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n\n it('should return false when config file exists but posthog server is not configured', async () => {\n existsSyncMock.mockReturnValue(true);\n const configData = {\n mcpServers: {\n otherServer: mockServerConfig,\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configData));\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n\n it('should return true when posthog server is configured', async () => {\n existsSyncMock.mockReturnValue(true);\n const configData = {\n mcpServers: {\n posthog: mockServerConfig,\n otherServer: mockServerConfig,\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configData));\n\n const result = await client.isServerInstalled();\n expect(result).toBe(true);\n });\n\n it('should return false when config file is invalid JSON', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockResolvedValue('invalid json');\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n\n it('should return false when readFile throws an error', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockRejectedValue(new Error('File read error'));\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n });\n\n describe('addServer', () => {\n beforeEach(() => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n });\n\n it('should create config directory and add server when config file does not exist', async () => {\n existsSyncMock.mockReturnValue(false);\n\n await client.addServer(mockApiKey);\n\n const expectedConfigPath = path.join(\n mockHomeDir,\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json',\n );\n const expectedConfigDir = path.dirname(expectedConfigPath);\n\n expect(mkdirMock).toHaveBeenCalledWith(expectedConfigDir, {\n recursive: true,\n });\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expectedConfigPath,\n JSON.stringify(\n {\n mcpServers: {\n posthog: mockServerConfig,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should merge with existing config when config file exists', async () => {\n existsSyncMock.mockReturnValue(true);\n const existingConfig = {\n mcpServers: {\n existingServer: {\n command: 'existing',\n args: [],\n env: {},\n },\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(existingConfig));\n\n await client.addServer(mockApiKey);\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expect.any(String),\n JSON.stringify(\n {\n mcpServers: {\n existingServer: existingConfig.mcpServers.existingServer,\n posthog: mockServerConfig,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should not overwrite existing config when it is invalid', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockResolvedValue(\n JSON.stringify({\n invalidKey: {\n existingServer: {\n command: 'existing',\n args: [],\n env: {},\n },\n },\n x: 'y',\n }),\n );\n\n await client.addServer(mockApiKey);\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expect.any(String),\n JSON.stringify(\n {\n invalidKey: {\n existingServer: {\n command: 'existing',\n args: [],\n env: {},\n },\n },\n x: 'y',\n mcpServers: {\n posthog: mockServerConfig,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should call getDefaultServerConfig with the provided API key', async () => {\n existsSyncMock.mockReturnValue(false);\n\n await client.addServer(mockApiKey);\n\n expect(getDefaultServerConfigMock).toHaveBeenCalledWith(mockApiKey);\n });\n });\n\n describe('removeServer', () => {\n beforeEach(() => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n });\n\n it('should do nothing when config file does not exist', async () => {\n existsSyncMock.mockReturnValue(false);\n\n await client.removeServer();\n\n expect(readFileMock).not.toHaveBeenCalled();\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n\n it('should remove posthog server from config', async () => {\n existsSyncMock.mockReturnValue(true);\n const configWithPosthog = {\n mcpServers: {\n posthog: mockServerConfig,\n otherServer: {\n command: 'other',\n args: [],\n env: {},\n },\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configWithPosthog));\n\n await client.removeServer();\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expect.any(String),\n JSON.stringify(\n {\n mcpServers: {\n otherServer: configWithPosthog.mcpServers.otherServer,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should do nothing when posthog server is not in config', async () => {\n existsSyncMock.mockReturnValue(true);\n const configWithoutPosthog = {\n mcpServers: {\n otherServer: {\n command: 'other',\n args: [],\n env: {},\n },\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configWithoutPosthog));\n\n await client.removeServer();\n\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n\n it('should handle invalid JSON gracefully', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockResolvedValue('invalid json');\n\n await client.removeServer();\n\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n\n it('should handle file read errors gracefully', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockRejectedValue(new Error('File read error'));\n\n await client.removeServer();\n\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n });\n});\n"]}
1
+ {"version":3,"file":"claude.test.js","sourceRoot":"","sources":["../../../../../../src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.ts"],"names":[],"mappings":"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","sourcesContent":["// We use the ClaudeMCPClient as a reference to test the DefaultMCPClient\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { ClaudeMCPClient } from '../claude';\nimport { getDefaultServerConfig } from '../../defaults';\n\njest.mock('fs', () => ({\n promises: {\n mkdir: jest.fn(),\n readFile: jest.fn(),\n writeFile: jest.fn(),\n },\n existsSync: jest.fn(),\n}));\n\njest.mock('os', () => ({\n homedir: jest.fn(),\n}));\n\njest.mock('../../defaults', () => ({\n DefaultMCPClientConfig: {\n parse: jest.fn(),\n },\n getDefaultServerConfig: jest.fn(),\n}));\n\ndescribe('ClaudeMCPClient', () => {\n let client: ClaudeMCPClient;\n const mockHomeDir = '/mock/home';\n const mockApiKey = 'test-api-key';\n const mockServerConfig = {\n command: 'npx',\n args: ['-y', 'mcp-remote@latest'],\n env: { POSTHOG_AUTH_HEADER: `Bearer ${mockApiKey}` },\n };\n\n const mkdirMock = fs.promises.mkdir as jest.Mock;\n const readFileMock = fs.promises.readFile as jest.Mock;\n const writeFileMock = fs.promises.writeFile as jest.Mock;\n const existsSyncMock = fs.existsSync as jest.Mock;\n const homedirMock = os.homedir as jest.Mock;\n const getDefaultServerConfigMock = getDefaultServerConfig as jest.Mock;\n\n const originalPlatform = process.platform;\n\n beforeEach(() => {\n client = new ClaudeMCPClient();\n jest.clearAllMocks();\n homedirMock.mockReturnValue(mockHomeDir);\n getDefaultServerConfigMock.mockReturnValue(mockServerConfig);\n\n // Mock the Zod schema parse method\n const { DefaultMCPClientConfig } = require('../../defaults');\n DefaultMCPClientConfig.parse.mockImplementation((data: any) => data);\n });\n\n afterEach(() => {\n Object.defineProperty(process, 'platform', {\n value: originalPlatform,\n writable: true,\n });\n });\n\n describe('constructor', () => {\n it('should set the correct name', () => {\n expect(client.name).toBe('Claude Desktop');\n });\n });\n\n describe('isClientSupported', () => {\n it('should return true for macOS', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(true);\n });\n\n it('should return true for Windows', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'win32',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(true);\n });\n\n it('should return false for Linux', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'linux',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(false);\n });\n\n it('should return false for other platforms', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'freebsd',\n writable: true,\n });\n await expect(client.isClientSupported()).resolves.toBe(false);\n });\n });\n\n describe('getConfigPath', () => {\n it('should return correct path for macOS', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n\n const configPath = await client.getConfigPath();\n expect(configPath).toBe(\n path.join(\n mockHomeDir,\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json',\n ),\n );\n });\n\n it('should return correct path for Windows', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'win32',\n writable: true,\n });\n\n const mockAppData = 'C:\\\\Users\\\\Test\\\\AppData\\\\Roaming';\n process.env.APPDATA = mockAppData;\n\n const configPath = await client.getConfigPath();\n expect(configPath).toBe(\n path.join(mockAppData, 'Claude', 'claude_desktop_config.json'),\n );\n });\n\n it('should throw error for unsupported platform', async () => {\n Object.defineProperty(process, 'platform', {\n value: 'linux',\n writable: true,\n });\n\n await expect(client.getConfigPath()).rejects.toThrow(\n 'Unsupported platform: linux',\n );\n });\n });\n\n describe('isServerInstalled', () => {\n beforeEach(() => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n });\n\n it('should return false when config file does not exist', async () => {\n existsSyncMock.mockReturnValue(false);\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n\n it('should return false when config file exists but posthog server is not configured', async () => {\n existsSyncMock.mockReturnValue(true);\n const configData = {\n mcpServers: {\n otherServer: mockServerConfig,\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configData));\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n\n it('should return true when posthog server is configured', async () => {\n existsSyncMock.mockReturnValue(true);\n const configData = {\n mcpServers: {\n posthog: mockServerConfig,\n otherServer: mockServerConfig,\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configData));\n\n const result = await client.isServerInstalled();\n expect(result).toBe(true);\n });\n\n it('should return false when config file is invalid JSON', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockResolvedValue('invalid json');\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n\n it('should return false when readFile throws an error', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockRejectedValue(new Error('File read error'));\n\n const result = await client.isServerInstalled();\n expect(result).toBe(false);\n });\n });\n\n describe('addServer', () => {\n beforeEach(() => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n });\n\n it('should create config directory and add server when config file does not exist', async () => {\n existsSyncMock.mockReturnValue(false);\n\n await client.addServer(mockApiKey);\n\n const expectedConfigPath = path.join(\n mockHomeDir,\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json',\n );\n const expectedConfigDir = path.dirname(expectedConfigPath);\n\n expect(mkdirMock).toHaveBeenCalledWith(expectedConfigDir, {\n recursive: true,\n });\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expectedConfigPath,\n JSON.stringify(\n {\n mcpServers: {\n posthog: mockServerConfig,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should merge with existing config when config file exists', async () => {\n existsSyncMock.mockReturnValue(true);\n const existingConfig = {\n mcpServers: {\n existingServer: {\n command: 'existing',\n args: [],\n env: {},\n },\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(existingConfig));\n\n await client.addServer(mockApiKey);\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expect.any(String),\n JSON.stringify(\n {\n mcpServers: {\n existingServer: existingConfig.mcpServers.existingServer,\n posthog: mockServerConfig,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should not overwrite existing config when it is invalid', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockResolvedValue(\n JSON.stringify({\n invalidKey: {\n existingServer: {\n command: 'existing',\n args: [],\n env: {},\n },\n },\n x: 'y',\n }),\n );\n\n await client.addServer(mockApiKey);\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expect.any(String),\n JSON.stringify(\n {\n invalidKey: {\n existingServer: {\n command: 'existing',\n args: [],\n env: {},\n },\n },\n x: 'y',\n mcpServers: {\n posthog: mockServerConfig,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should call getDefaultServerConfig with the provided API key', async () => {\n existsSyncMock.mockReturnValue(false);\n\n await client.addServer(mockApiKey);\n\n expect(getDefaultServerConfigMock).toHaveBeenCalledWith(\n mockApiKey,\n 'sse',\n );\n });\n });\n\n describe('removeServer', () => {\n beforeEach(() => {\n Object.defineProperty(process, 'platform', {\n value: 'darwin',\n writable: true,\n });\n });\n\n it('should do nothing when config file does not exist', async () => {\n existsSyncMock.mockReturnValue(false);\n\n await client.removeServer();\n\n expect(readFileMock).not.toHaveBeenCalled();\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n\n it('should remove posthog server from config', async () => {\n existsSyncMock.mockReturnValue(true);\n const configWithPosthog = {\n mcpServers: {\n posthog: mockServerConfig,\n otherServer: {\n command: 'other',\n args: [],\n env: {},\n },\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configWithPosthog));\n\n await client.removeServer();\n\n expect(writeFileMock).toHaveBeenCalledWith(\n expect.any(String),\n JSON.stringify(\n {\n mcpServers: {\n otherServer: configWithPosthog.mcpServers.otherServer,\n },\n },\n null,\n 2,\n ),\n 'utf8',\n );\n });\n\n it('should do nothing when posthog server is not in config', async () => {\n existsSyncMock.mockReturnValue(true);\n const configWithoutPosthog = {\n mcpServers: {\n otherServer: {\n command: 'other',\n args: [],\n env: {},\n },\n },\n };\n readFileMock.mockResolvedValue(JSON.stringify(configWithoutPosthog));\n\n await client.removeServer();\n\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n\n it('should handle invalid JSON gracefully', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockResolvedValue('invalid json');\n\n await client.removeServer();\n\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n\n it('should handle file read errors gracefully', async () => {\n existsSyncMock.mockReturnValue(true);\n readFileMock.mockRejectedValue(new Error('File read error'));\n\n await client.removeServer();\n\n expect(writeFileMock).not.toHaveBeenCalled();\n });\n });\n});\n"]}
@@ -0,0 +1,60 @@
1
+ import { DefaultMCPClient } from '../MCPClient';
2
+ import { DefaultMCPClientConfig } from '../defaults';
3
+ import { z } from 'zod';
4
+ export declare const ClaudeCodeMCPConfig: z.ZodObject<{
5
+ mcpServers: z.ZodRecord<z.ZodString, z.ZodObject<{
6
+ command: z.ZodOptional<z.ZodString>;
7
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
8
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ command?: string | undefined;
11
+ args?: string[] | undefined;
12
+ env?: Record<string, string> | undefined;
13
+ }, {
14
+ command?: string | undefined;
15
+ args?: string[] | undefined;
16
+ env?: Record<string, string> | undefined;
17
+ }>>;
18
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
19
+ mcpServers: z.ZodRecord<z.ZodString, z.ZodObject<{
20
+ command: z.ZodOptional<z.ZodString>;
21
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
22
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ command?: string | undefined;
25
+ args?: string[] | undefined;
26
+ env?: Record<string, string> | undefined;
27
+ }, {
28
+ command?: string | undefined;
29
+ args?: string[] | undefined;
30
+ env?: Record<string, string> | undefined;
31
+ }>>;
32
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
33
+ mcpServers: z.ZodRecord<z.ZodString, z.ZodObject<{
34
+ command: z.ZodOptional<z.ZodString>;
35
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
36
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
37
+ }, "strip", z.ZodTypeAny, {
38
+ command?: string | undefined;
39
+ args?: string[] | undefined;
40
+ env?: Record<string, string> | undefined;
41
+ }, {
42
+ command?: string | undefined;
43
+ args?: string[] | undefined;
44
+ env?: Record<string, string> | undefined;
45
+ }>>;
46
+ }, z.ZodTypeAny, "passthrough">>;
47
+ export type ClaudeCodeMCPConfig = z.infer<typeof DefaultMCPClientConfig>;
48
+ export declare class ClaudeCodeMCPClient extends DefaultMCPClient {
49
+ name: string;
50
+ constructor();
51
+ isClientSupported(): Promise<boolean>;
52
+ isServerInstalled(): Promise<boolean>;
53
+ getConfigPath(): Promise<string>;
54
+ addServer(apiKey: string): Promise<{
55
+ success: boolean;
56
+ }>;
57
+ removeServer(): Promise<{
58
+ success: boolean;
59
+ }>;
60
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClaudeCodeMCPClient = exports.ClaudeCodeMCPConfig = void 0;
4
+ const MCPClient_1 = require("../MCPClient");
5
+ const defaults_1 = require("../defaults");
6
+ const child_process_1 = require("child_process");
7
+ exports.ClaudeCodeMCPConfig = defaults_1.DefaultMCPClientConfig;
8
+ class ClaudeCodeMCPClient extends MCPClient_1.DefaultMCPClient {
9
+ name = 'Claude Code';
10
+ constructor() {
11
+ super();
12
+ }
13
+ isClientSupported() {
14
+ try {
15
+ (0, child_process_1.execSync)('claude --version', { stdio: 'ignore' });
16
+ return Promise.resolve(true);
17
+ }
18
+ catch {
19
+ return Promise.resolve(false);
20
+ }
21
+ }
22
+ isServerInstalled() {
23
+ try {
24
+ // check if posthog in output
25
+ const output = (0, child_process_1.execSync)('claude mcp list', {
26
+ stdio: 'pipe',
27
+ });
28
+ if (output.toString().includes('posthog')) {
29
+ return Promise.resolve(true);
30
+ }
31
+ }
32
+ catch {
33
+ //
34
+ }
35
+ return Promise.resolve(false);
36
+ }
37
+ getConfigPath() {
38
+ throw new Error('Not implemented');
39
+ }
40
+ addServer(apiKey) {
41
+ const config = (0, defaults_1.getDefaultServerConfig)(apiKey, 'sse');
42
+ const command = `claude mcp add-json posthog -s user '${JSON.stringify(config)}'`;
43
+ (0, child_process_1.execSync)(command);
44
+ return Promise.resolve({ success: true });
45
+ }
46
+ removeServer() {
47
+ const command = `claude mcp remove --scope user posthog`;
48
+ (0, child_process_1.execSync)(command);
49
+ return Promise.resolve({ success: true });
50
+ }
51
+ }
52
+ exports.ClaudeCodeMCPClient = ClaudeCodeMCPClient;
53
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../../../src/steps/add-mcp-server-to-clients/clients/claude-code.ts"],"names":[],"mappings":";;;AAAA,4CAAgD;AAChD,0CAA6E;AAE7E,iDAAyC;AAE5B,QAAA,mBAAmB,GAAG,iCAAsB,CAAC;AAI1D,MAAa,mBAAoB,SAAQ,4BAAgB;IACvD,IAAI,GAAG,aAAa,CAAC;IAErB;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC;YACH,IAAA,wBAAQ,EAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAClD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC;YACH,6BAA6B;YAC7B,MAAM,MAAM,GAAG,IAAA,wBAAQ,EAAC,iBAAiB,EAAE;gBACzC,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1C,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,EAAE;QACJ,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,aAAa;QACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,MAAM,MAAM,GAAG,IAAA,iCAAsB,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAErD,MAAM,OAAO,GAAG,wCAAwC,IAAI,CAAC,SAAS,CACpE,MAAM,CACP,GAAG,CAAC;QAEL,IAAA,wBAAQ,EAAC,OAAO,CAAC,CAAC;QAElB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY;QACV,MAAM,OAAO,GAAG,wCAAwC,CAAC;QAEzD,IAAA,wBAAQ,EAAC,OAAO,CAAC,CAAC;QAElB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;CACF;AAxDD,kDAwDC","sourcesContent":["import { DefaultMCPClient } from '../MCPClient';\nimport { DefaultMCPClientConfig, getDefaultServerConfig } from '../defaults';\nimport { z } from 'zod';\nimport { execSync } from 'child_process';\n\nexport const ClaudeCodeMCPConfig = DefaultMCPClientConfig;\n\nexport type ClaudeCodeMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class ClaudeCodeMCPClient extends DefaultMCPClient {\n name = 'Claude Code';\n\n constructor() {\n super();\n }\n\n isClientSupported(): Promise<boolean> {\n try {\n execSync('claude --version', { stdio: 'ignore' });\n return Promise.resolve(true);\n } catch {\n return Promise.resolve(false);\n }\n }\n\n isServerInstalled(): Promise<boolean> {\n try {\n // check if posthog in output\n const output = execSync('claude mcp list', {\n stdio: 'pipe',\n });\n\n if (output.toString().includes('posthog')) {\n return Promise.resolve(true);\n }\n } catch {\n //\n }\n\n return Promise.resolve(false);\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n addServer(apiKey: string): Promise<{ success: boolean }> {\n const config = getDefaultServerConfig(apiKey, 'sse');\n\n const command = `claude mcp add-json posthog -s user '${JSON.stringify(\n config,\n )}'`;\n\n execSync(command);\n\n return Promise.resolve({ success: true });\n }\n\n removeServer(): Promise<{ success: boolean }> {\n const command = `claude mcp remove --scope user posthog`;\n\n execSync(command);\n\n return Promise.resolve({ success: true });\n }\n}\n"]}
@@ -50,4 +50,7 @@ export declare class CursorMCPClient extends DefaultMCPClient {
50
50
  constructor();
51
51
  isClientSupported(): Promise<boolean>;
52
52
  getConfigPath(): Promise<string>;
53
+ addServer(apiKey: string): Promise<{
54
+ success: boolean;
55
+ }>;
53
56
  }
@@ -50,6 +50,9 @@ class CursorMCPClient extends MCPClient_1.DefaultMCPClient {
50
50
  async getConfigPath() {
51
51
  return Promise.resolve(path.join(os.homedir(), '.cursor', 'mcp.json'));
52
52
  }
53
+ async addServer(apiKey) {
54
+ return this._addServerType(apiKey, 'sse');
55
+ }
53
56
  }
54
57
  exports.CursorMCPClient = CursorMCPClient;
55
58
  //# sourceMappingURL=cursor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../../../src/steps/add-mcp-server-to-clients/clients/cursor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAAgD;AAChD,2CAA6B;AAC7B,uCAAyB;AACzB,0CAAqD;AAGxC,QAAA,eAAe,GAAG,iCAAsB,CAAC;AAItD,MAAa,eAAgB,SAAQ,4BAAgB;IACnD,IAAI,GAAG,QAAQ,CAAC;IAEhB;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,OAAO,CAAC,OAAO,CACpB,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAC9D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IACzE,CAAC;CACF;AAhBD,0CAgBC","sourcesContent":["import { DefaultMCPClient } from '../MCPClient';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { DefaultMCPClientConfig } from '../defaults';\nimport { z } from 'zod';\n\nexport const CursorMCPConfig = DefaultMCPClientConfig;\n\nexport type CursorMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CursorMCPClient extends DefaultMCPClient {\n name = 'Cursor';\n\n constructor() {\n super();\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'win32',\n );\n }\n\n async getConfigPath(): Promise<string> {\n return Promise.resolve(path.join(os.homedir(), '.cursor', 'mcp.json'));\n }\n}\n"]}
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../../../src/steps/add-mcp-server-to-clients/clients/cursor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAAgD;AAChD,2CAA6B;AAC7B,uCAAyB;AACzB,0CAAqD;AAGxC,QAAA,eAAe,GAAG,iCAAsB,CAAC;AAItD,MAAa,eAAgB,SAAQ,4BAAgB;IACnD,IAAI,GAAG,QAAQ,CAAC;IAEhB;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,OAAO,CAAC,OAAO,CACpB,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAC9D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAc;QAC5B,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;CACF;AApBD,0CAoBC","sourcesContent":["import { DefaultMCPClient } from '../MCPClient';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { DefaultMCPClientConfig } from '../defaults';\nimport { z } from 'zod';\n\nexport const CursorMCPConfig = DefaultMCPClientConfig;\n\nexport type CursorMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CursorMCPClient extends DefaultMCPClient {\n name = 'Cursor';\n\n constructor() {\n super();\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'win32',\n );\n }\n\n async getConfigPath(): Promise<string> {\n return Promise.resolve(path.join(os.homedir(), '.cursor', 'mcp.json'));\n }\n\n async addServer(apiKey: string): Promise<{ success: boolean }> {\n return this._addServerType(apiKey, 'sse');\n }\n}\n"]}
@@ -42,10 +42,12 @@ export declare const DefaultMCPClientConfig: z.ZodObject<{
42
42
  env?: Record<string, string> | undefined;
43
43
  }>>;
44
44
  }, z.ZodTypeAny, "passthrough">>;
45
- export declare const getDefaultServerConfig: (apiKey: string) => {
45
+ type MCPServerType = 'sse' | 'streamable-http';
46
+ export declare const getDefaultServerConfig: (apiKey: string, type: MCPServerType) => {
46
47
  command: string;
47
48
  args: string[];
48
49
  env: {
49
50
  POSTHOG_AUTH_HEADER: string;
50
51
  };
51
52
  };
53
+ export {};
@@ -14,12 +14,12 @@ exports.DefaultMCPClientConfig = zod_1.default
14
14
  })),
15
15
  })
16
16
  .passthrough();
17
- const getDefaultServerConfig = (apiKey) => ({
17
+ const getDefaultServerConfig = (apiKey, type) => ({
18
18
  command: 'npx',
19
19
  args: [
20
20
  '-y',
21
21
  'mcp-remote@latest',
22
- 'https://mcp.posthog.com/mcp',
22
+ `https://mcp.posthog.com/${type === 'sse' ? 'sse' : 'mcp'}`,
23
23
  '--header',
24
24
  `Authorization:\${POSTHOG_AUTH_HEADER}`,
25
25
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../../src/steps/add-mcp-server-to-clients/defaults.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAoB;AAEP,QAAA,sBAAsB,GAAG,aAAC;KACpC,MAAM,CAAC;IACN,UAAU,EAAE,aAAC,CAAC,MAAM,CAClB,aAAC,CAAC,MAAM,EAAE,EACV,aAAC,CAAC,MAAM,CAAC;QACP,OAAO,EAAE,aAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC9B,IAAI,EAAE,aAAC,CAAC,KAAK,CAAC,aAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACpC,GAAG,EAAE,aAAC,CAAC,MAAM,CAAC,aAAC,CAAC,MAAM,EAAE,EAAE,aAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KACjD,CAAC,CACH;CACF,CAAC;KACD,WAAW,EAAE,CAAC;AAEV,MAAM,sBAAsB,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;IACzD,OAAO,EAAE,KAAK;IACd,IAAI,EAAE;QACJ,IAAI;QACJ,mBAAmB;QACnB,6BAA6B;QAC7B,UAAU;QACV,uCAAuC;KACxC;IACD,GAAG,EAAE;QACH,mBAAmB,EAAE,UAAU,MAAM,EAAE;KACxC;CACF,CAAC,CAAC;AAZU,QAAA,sBAAsB,0BAYhC","sourcesContent":["import z from 'zod';\n\nexport const DefaultMCPClientConfig = z\n .object({\n mcpServers: z.record(\n z.string(),\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n ),\n })\n .passthrough();\n\nexport const getDefaultServerConfig = (apiKey: string) => ({\n command: 'npx',\n args: [\n '-y',\n 'mcp-remote@latest',\n 'https://mcp.posthog.com/mcp',\n '--header',\n `Authorization:\\${POSTHOG_AUTH_HEADER}`,\n ],\n env: {\n POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`,\n },\n});\n"]}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../../src/steps/add-mcp-server-to-clients/defaults.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAoB;AAEP,QAAA,sBAAsB,GAAG,aAAC;KACpC,MAAM,CAAC;IACN,UAAU,EAAE,aAAC,CAAC,MAAM,CAClB,aAAC,CAAC,MAAM,EAAE,EACV,aAAC,CAAC,MAAM,CAAC;QACP,OAAO,EAAE,aAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC9B,IAAI,EAAE,aAAC,CAAC,KAAK,CAAC,aAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACpC,GAAG,EAAE,aAAC,CAAC,MAAM,CAAC,aAAC,CAAC,MAAM,EAAE,EAAE,aAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KACjD,CAAC,CACH;CACF,CAAC;KACD,WAAW,EAAE,CAAC;AAIV,MAAM,sBAAsB,GAAG,CACpC,MAAc,EACd,IAAmB,EACnB,EAAE,CAAC,CAAC;IACJ,OAAO,EAAE,KAAK;IACd,IAAI,EAAE;QACJ,IAAI;QACJ,mBAAmB;QACnB,2BAA2B,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE;QAC3D,UAAU;QACV,uCAAuC;KACxC;IACD,GAAG,EAAE;QACH,mBAAmB,EAAE,UAAU,MAAM,EAAE;KACxC;CACF,CAAC,CAAC;AAfU,QAAA,sBAAsB,0BAehC","sourcesContent":["import z from 'zod';\n\nexport const DefaultMCPClientConfig = z\n .object({\n mcpServers: z.record(\n z.string(),\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n ),\n })\n .passthrough();\n\ntype MCPServerType = 'sse' | 'streamable-http';\n\nexport const getDefaultServerConfig = (\n apiKey: string,\n type: MCPServerType,\n) => ({\n command: 'npx',\n args: [\n '-y',\n 'mcp-remote@latest',\n `https://mcp.posthog.com/${type === 'sse' ? 'sse' : 'mcp'}`,\n '--header',\n `Authorization:\\${POSTHOG_AUTH_HEADER}`,\n ],\n env: {\n POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`,\n },\n});\n"]}
@@ -7,12 +7,18 @@ exports.removeMCPServer = exports.addMCPServer = exports.getInstalledClients = e
7
7
  const telemetry_1 = require("../../telemetry");
8
8
  const analytics_1 = require("../../utils/analytics");
9
9
  const clack_1 = __importDefault(require("../../utils/clack"));
10
+ const chalk_1 = __importDefault(require("chalk"));
10
11
  const clack_utils_1 = require("../../utils/clack-utils");
11
12
  const cursor_1 = require("./clients/cursor");
12
13
  const claude_1 = require("./clients/claude");
13
14
  const mcp_1 = require("../../mcp");
15
+ const claude_code_1 = require("./clients/claude-code");
14
16
  const getSupportedClients = async () => {
15
- const allClients = [new cursor_1.CursorMCPClient(), new claude_1.ClaudeMCPClient()];
17
+ const allClients = [
18
+ new cursor_1.CursorMCPClient(),
19
+ new claude_1.ClaudeMCPClient(),
20
+ new claude_code_1.ClaudeCodeMCPClient(),
21
+ ];
16
22
  const supportedClients = [];
17
23
  for (const client of allClients) {
18
24
  if (await client.isClientSupported()) {
@@ -26,7 +32,7 @@ const addMCPServerToClientsStep = async ({ integration, cloudRegion, askPermissi
26
32
  const region = cloudRegion ?? (await (0, clack_utils_1.askForCloudRegion)());
27
33
  const hasPermission = askPermission
28
34
  ? await (0, clack_utils_1.abortIfCancelled)(clack_1.default.select({
29
- message: 'Would you like to install the PostHog MCP server to use PostHog in your editor?',
35
+ message: 'Would you like to install the MCP server to use PostHog in your editor?',
30
36
  options: [
31
37
  { value: true, label: 'Yes' },
32
38
  { value: false, label: 'No' },
@@ -36,11 +42,21 @@ const addMCPServerToClientsStep = async ({ integration, cloudRegion, askPermissi
36
42
  if (!hasPermission) {
37
43
  return [];
38
44
  }
39
- const clients = await (0, exports.getSupportedClients)();
45
+ const supportedClients = await (0, exports.getSupportedClients)();
46
+ const { multiselect } = await import('@clack/prompts');
47
+ const selectedClientNames = await (0, clack_utils_1.abortIfCancelled)(multiselect({
48
+ message: `Select which MCP clients to install the MCP server to: ${chalk_1.default.dim('(Toggle: Space, Confirm: Enter, Toggle All: A, Cancel: CTRL + C)')}`,
49
+ options: supportedClients.map((client) => ({
50
+ value: client.name,
51
+ label: client.name,
52
+ })),
53
+ initialValues: supportedClients.map((client) => client.name),
54
+ required: true,
55
+ }), integration);
56
+ const clients = supportedClients.filter((client) => selectedClientNames.includes(client.name));
40
57
  const installedClients = await (0, exports.getInstalledClients)();
41
58
  if (installedClients.length > 0) {
42
- clack_1.default.log.warn(`The PostHog MCP server is already configured for:
43
-
59
+ clack_1.default.log.warn(`The MCP server is already configured for:
44
60
  ${installedClients.map((c) => `- ${c.name}`).join('\n ')}`);
45
61
  const reinstall = await (0, clack_utils_1.abortIfCancelled)(clack_1.default.select({
46
62
  message: 'Would you like to reinstall it?',
@@ -72,7 +88,7 @@ const addMCPServerToClientsStep = async ({ integration, cloudRegion, askPermissi
72
88
  await (0, telemetry_1.traceStep)('adding mcp servers', async () => {
73
89
  await (0, exports.addMCPServer)(clients, personalApiKey);
74
90
  });
75
- clack_1.default.log.success(`Added the PostHog MCP server to:
91
+ clack_1.default.log.success(`Added the MCP server to:
76
92
  ${clients.map((c) => `- ${c.name}`).join('\n ')} `);
77
93
  analytics_1.analytics.capture('wizard interaction', {
78
94
  action: 'added mcp servers',
@@ -91,33 +107,26 @@ const removeMCPServerFromClientsStep = async ({ integration, }) => {
91
107
  });
92
108
  return [];
93
109
  }
94
- const removeServers = await (0, clack_utils_1.abortIfCancelled)(clack_1.default.select({
95
- message: `Found the PostHog MCP server in ${installedClients.length} clients. Would you like to remove it?`,
96
- options: [
97
- {
98
- value: true,
99
- label: 'Yes',
100
- hint: `Remove PostHog MCP server`,
101
- },
102
- {
103
- value: false,
104
- label: 'No',
105
- hint: 'Keep the MCP server configuration',
106
- },
107
- ],
110
+ const { multiselect } = await import('@clack/prompts');
111
+ const selectedClientNames = await (0, clack_utils_1.abortIfCancelled)(multiselect({
112
+ message: `Select which clients to remove the MCP server from: ${chalk_1.default.dim('(Toggle: Space, Confirm: Enter, Toggle All: A, Cancel: CTRL + C)')}`,
113
+ options: installedClients.map((client) => ({
114
+ value: client.name,
115
+ label: client.name,
116
+ })),
117
+ initialValues: installedClients.map((client) => client.name),
108
118
  }), integration);
109
- if (!removeServers) {
119
+ const clientsToRemove = installedClients.filter((client) => selectedClientNames.includes(client.name));
120
+ if (clientsToRemove.length === 0) {
110
121
  analytics_1.analytics.capture('wizard interaction', {
111
- action: 'declined to remove mcp servers',
112
- clients: installedClients.map((c) => c.name),
122
+ action: 'no mcp servers selected for removal',
113
123
  integration,
114
124
  });
115
- await (0, clack_utils_1.abort)('The MCP server was not removed.');
116
125
  return [];
117
126
  }
118
127
  const results = await (0, telemetry_1.traceStep)('removing mcp servers', async () => {
119
- await (0, exports.removeMCPServer)(installedClients);
120
- return installedClients.map((c) => c.name);
128
+ await (0, exports.removeMCPServer)(clientsToRemove);
129
+ return clientsToRemove.map((c) => c.name);
121
130
  });
122
131
  analytics_1.analytics.capture('wizard interaction', {
123
132
  action: 'removed mcp servers',
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/steps/add-mcp-server-to-clients/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Integration } from '../../lib/constants';\nimport { traceStep } from '../../telemetry';\nimport { analytics } from '../../utils/analytics';\nimport clack from '../../utils/clack';\nimport {\n abort,\n abortIfCancelled,\n askForCloudRegion,\n} from '../../utils/clack-utils';\nimport { MCPClient } from './MCPClient';\nimport { CursorMCPClient } from './clients/cursor';\nimport { ClaudeMCPClient } from './clients/claude';\nimport { getPersonalApiKey } from '../../mcp';\nimport type { CloudRegion } from '../../utils/types';\n\nexport const getSupportedClients = async (): Promise<MCPClient[]> => {\n const allClients = [new CursorMCPClient(), new ClaudeMCPClient()];\n const supportedClients: MCPClient[] = [];\n\n for (const client of allClients) {\n if (await client.isClientSupported()) {\n supportedClients.push(client);\n }\n }\n\n return supportedClients;\n};\n\nexport const addMCPServerToClientsStep = async ({\n integration,\n cloudRegion,\n askPermission = true,\n}: {\n integration?: Integration;\n cloudRegion?: CloudRegion;\n askPermission?: boolean;\n}): Promise<string[]> => {\n const region = cloudRegion ?? (await askForCloudRegion());\n\n const hasPermission = askPermission\n ? await abortIfCancelled(\n clack.select({\n message:\n 'Would you like to install the PostHog MCP server to use PostHog in your editor?',\n options: [\n { value: true, label: 'Yes' },\n { value: false, label: 'No' },\n ],\n }),\n integration,\n )\n : true;\n\n if (!hasPermission) {\n return [];\n }\n\n const clients = await getSupportedClients();\n\n const installedClients = await getInstalledClients();\n\n if (installedClients.length > 0) {\n clack.log.warn(\n `The PostHog MCP server is already configured for:\n\n ${installedClients.map((c) => `- ${c.name}`).join('\\n ')}`,\n );\n\n const reinstall = await abortIfCancelled(\n clack.select({\n message: 'Would you like to reinstall it?',\n options: [\n {\n value: true,\n label: 'Yes',\n hint: 'Reinstall the MCP server',\n },\n {\n value: false,\n label: 'No',\n hint: 'Keep the existing installation',\n },\n ],\n }),\n integration,\n );\n\n if (!reinstall) {\n analytics.capture('wizard interaction', {\n action: 'declined to reinstall mcp servers',\n clients: installedClients.map((c) => c.name),\n integration,\n });\n\n return [];\n }\n\n await removeMCPServer(installedClients);\n clack.log.info('Removed existing installation.');\n }\n\n const personalApiKey = await getPersonalApiKey({ cloudRegion: region });\n\n await traceStep('adding mcp servers', async () => {\n await addMCPServer(clients, personalApiKey);\n });\n\n clack.log.success(\n `Added the PostHog MCP server to:\n ${clients.map((c) => `- ${c.name}`).join('\\n ')} `,\n );\n\n analytics.capture('wizard interaction', {\n action: 'added mcp servers',\n clients: clients.map((c) => c.name),\n integration,\n });\n\n return clients.map((c) => c.name);\n};\n\nexport const removeMCPServerFromClientsStep = async ({\n integration,\n}: {\n integration?: Integration;\n}): Promise<string[]> => {\n const installedClients = await getInstalledClients();\n\n if (installedClients.length === 0) {\n analytics.capture('wizard interaction', {\n action: 'no mcp servers to remove',\n integration,\n });\n return [];\n }\n\n const removeServers: boolean = await abortIfCancelled(\n clack.select({\n message: `Found the PostHog MCP server in ${installedClients.length} clients. Would you like to remove it?`,\n options: [\n {\n value: true,\n label: 'Yes',\n hint: `Remove PostHog MCP server`,\n },\n {\n value: false,\n label: 'No',\n hint: 'Keep the MCP server configuration',\n },\n ],\n }),\n integration,\n );\n\n if (!removeServers) {\n analytics.capture('wizard interaction', {\n action: 'declined to remove mcp servers',\n clients: installedClients.map((c) => c.name),\n integration,\n });\n\n await abort('The MCP server was not removed.');\n return [];\n }\n\n const results = await traceStep('removing mcp servers', async () => {\n await removeMCPServer(installedClients);\n\n return installedClients.map((c) => c.name);\n });\n\n analytics.capture('wizard interaction', {\n action: 'removed mcp servers',\n clients: results,\n integration,\n });\n\n return results;\n};\n\nexport const getInstalledClients = async (): Promise<MCPClient[]> => {\n const clients = await getSupportedClients();\n\n const installedClients: MCPClient[] = [];\n\n for (const client of clients) {\n if (await client.isServerInstalled()) {\n installedClients.push(client);\n }\n }\n\n return installedClients;\n};\n\nexport const addMCPServer = async (\n clients: MCPClient[],\n personalApiKey: string,\n): Promise<void> => {\n for (const client of clients) {\n await client.addServer(personalApiKey);\n }\n};\n\nexport const removeMCPServer = async (clients: MCPClient[]): Promise<void> => {\n for (const client of clients) {\n await client.removeServer();\n }\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/steps/add-mcp-server-to-clients/index.ts"],"names":[],"mappings":";;;;;;AACA,+CAA4C;AAC5C,qDAAkD;AAClD,8DAAsC;AACtC,kDAA0B;AAC1B,yDAA8E;AAE9E,6CAAmD;AACnD,6CAAmD;AACnD,mCAA8C;AAE9C,uDAA4D;AAErD,MAAM,mBAAmB,GAAG,KAAK,IAA0B,EAAE;IAClE,MAAM,UAAU,GAAG;QACjB,IAAI,wBAAe,EAAE;QACrB,IAAI,wBAAe,EAAE;QACrB,IAAI,iCAAmB,EAAE;KAC1B,CAAC;IACF,MAAM,gBAAgB,GAAgB,EAAE,CAAC;IAEzC,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QAChC,IAAI,MAAM,MAAM,CAAC,iBAAiB,EAAE,EAAE,CAAC;YACrC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC,CAAC;AAfW,QAAA,mBAAmB,uBAe9B;AAEK,MAAM,yBAAyB,GAAG,KAAK,EAAE,EAC9C,WAAW,EACX,WAAW,EACX,aAAa,GAAG,IAAI,GAKrB,EAAqB,EAAE;IACtB,MAAM,MAAM,GAAG,WAAW,IAAI,CAAC,MAAM,IAAA,+BAAiB,GAAE,CAAC,CAAC;IAE1D,MAAM,aAAa,GAAG,aAAa;QACjC,CAAC,CAAC,MAAM,IAAA,8BAAgB,EACpB,eAAK,CAAC,MAAM,CAAC;YACX,OAAO,EACL,yEAAyE;YAC3E,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;gBAC7B,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;aAC9B;SACF,CAAC,EACF,WAAW,CACZ;QACH,CAAC,CAAC,IAAI,CAAC;IAET,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,IAAA,2BAAmB,GAAE,CAAC;IAErD,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACvD,MAAM,mBAAmB,GAAG,MAAM,IAAA,8BAAgB,EAChD,WAAW,CAAC;QACV,OAAO,EAAE,0DAA0D,eAAK,CAAC,GAAG,CAC1E,kEAAkE,CACnE,EAAE;QACH,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACzC,KAAK,EAAE,MAAM,CAAC,IAAI;YAClB,KAAK,EAAE,MAAM,CAAC,IAAI;SACnB,CAAC,CAAC;QACH,aAAa,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5D,QAAQ,EAAE,IAAI;KACf,CAAC,EACF,WAAW,CACZ,CAAC;IAEF,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACjD,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAC1C,CAAC;IAEF,MAAM,gBAAgB,GAAG,MAAM,IAAA,2BAAmB,GAAE,CAAC;IAErD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,eAAK,CAAC,GAAG,CAAC,IAAI,CACZ;IACF,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CACxD,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,IAAA,8BAAgB,EACtC,eAAK,CAAC,MAAM,CAAC;YACX,OAAO,EAAE,iCAAiC;YAC1C,OAAO,EAAE;gBACP;oBACE,KAAK,EAAE,IAAI;oBACX,KAAK,EAAE,KAAK;oBACZ,IAAI,EAAE,0BAA0B;iBACjC;gBACD;oBACE,KAAK,EAAE,KAAK;oBACZ,KAAK,EAAE,IAAI;oBACX,IAAI,EAAE,gCAAgC;iBACvC;aACF;SACF,CAAC,EACF,WAAW,CACZ,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,qBAAS,CAAC,OAAO,CAAC,oBAAoB,EAAE;gBACtC,MAAM,EAAE,mCAAmC;gBAC3C,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC5C,WAAW;aACZ,CAAC,CAAC;YAEH,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAA,uBAAe,EAAC,gBAAgB,CAAC,CAAC;QACxC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,IAAA,uBAAiB,EAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IAExE,MAAM,IAAA,qBAAS,EAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,IAAA,oBAAY,EAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,eAAK,CAAC,GAAG,CAAC,OAAO,CACf;IACA,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAClD,CAAC;IAEF,qBAAS,CAAC,OAAO,CAAC,oBAAoB,EAAE;QACtC,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACnC,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC,CAAC;AA9GW,QAAA,yBAAyB,6BA8GpC;AAEK,MAAM,8BAA8B,GAAG,KAAK,EAAE,EACnD,WAAW,GAGZ,EAAqB,EAAE;IACtB,MAAM,gBAAgB,GAAG,MAAM,IAAA,2BAAmB,GAAE,CAAC;IAErD,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,qBAAS,CAAC,OAAO,CAAC,oBAAoB,EAAE;YACtC,MAAM,EAAE,0BAA0B;YAClC,WAAW;SACZ,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACvD,MAAM,mBAAmB,GAAG,MAAM,IAAA,8BAAgB,EAChD,WAAW,CAAC;QACV,OAAO,EAAE,uDAAuD,eAAK,CAAC,GAAG,CACvE,kEAAkE,CACnE,EAAE;QACH,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACzC,KAAK,EAAE,MAAM,CAAC,IAAI;YAClB,KAAK,EAAE,MAAM,CAAC,IAAI;SACnB,CAAC,CAAC;QACH,aAAa,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;KAC7D,CAAC,EACF,WAAW,CACZ,CAAC;IAEF,MAAM,eAAe,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACzD,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAC1C,CAAC;IAEF,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,qBAAS,CAAC,OAAO,CAAC,oBAAoB,EAAE;YACtC,MAAM,EAAE,qCAAqC;YAC7C,WAAW;SACZ,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,IAAA,qBAAS,EAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,IAAA,uBAAe,EAAC,eAAe,CAAC,CAAC;QACvC,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,qBAAS,CAAC,OAAO,CAAC,oBAAoB,EAAE;QACtC,MAAM,EAAE,qBAAqB;QAC7B,OAAO,EAAE,OAAO;QAChB,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAtDW,QAAA,8BAA8B,kCAsDzC;AAEK,MAAM,mBAAmB,GAAG,KAAK,IAA0B,EAAE;IAClE,MAAM,OAAO,GAAG,MAAM,IAAA,2BAAmB,GAAE,CAAC;IAE5C,MAAM,gBAAgB,GAAgB,EAAE,CAAC;IAEzC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,MAAM,CAAC,iBAAiB,EAAE,EAAE,CAAC;YACrC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC,CAAC;AAZW,QAAA,mBAAmB,uBAY9B;AAEK,MAAM,YAAY,GAAG,KAAK,EAC/B,OAAoB,EACpB,cAAsB,EACP,EAAE;IACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;AACH,CAAC,CAAC;AAPW,QAAA,YAAY,gBAOvB;AAEK,MAAM,eAAe,GAAG,KAAK,EAAE,OAAoB,EAAiB,EAAE;IAC3E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC,CAAC;AAJW,QAAA,eAAe,mBAI1B","sourcesContent":["import type { Integration } from '../../lib/constants';\nimport { traceStep } from '../../telemetry';\nimport { analytics } from '../../utils/analytics';\nimport clack from '../../utils/clack';\nimport chalk from 'chalk';\nimport { abortIfCancelled, askForCloudRegion } from '../../utils/clack-utils';\nimport { MCPClient } from './MCPClient';\nimport { CursorMCPClient } from './clients/cursor';\nimport { ClaudeMCPClient } from './clients/claude';\nimport { getPersonalApiKey } from '../../mcp';\nimport type { CloudRegion } from '../../utils/types';\nimport { ClaudeCodeMCPClient } from './clients/claude-code';\n\nexport const getSupportedClients = async (): Promise<MCPClient[]> => {\n const allClients = [\n new CursorMCPClient(),\n new ClaudeMCPClient(),\n new ClaudeCodeMCPClient(),\n ];\n const supportedClients: MCPClient[] = [];\n\n for (const client of allClients) {\n if (await client.isClientSupported()) {\n supportedClients.push(client);\n }\n }\n\n return supportedClients;\n};\n\nexport const addMCPServerToClientsStep = async ({\n integration,\n cloudRegion,\n askPermission = true,\n}: {\n integration?: Integration;\n cloudRegion?: CloudRegion;\n askPermission?: boolean;\n}): Promise<string[]> => {\n const region = cloudRegion ?? (await askForCloudRegion());\n\n const hasPermission = askPermission\n ? await abortIfCancelled(\n clack.select({\n message:\n 'Would you like to install the MCP server to use PostHog in your editor?',\n options: [\n { value: true, label: 'Yes' },\n { value: false, label: 'No' },\n ],\n }),\n integration,\n )\n : true;\n\n if (!hasPermission) {\n return [];\n }\n\n const supportedClients = await getSupportedClients();\n\n const { multiselect } = await import('@clack/prompts');\n const selectedClientNames = await abortIfCancelled(\n multiselect({\n message: `Select which MCP clients to install the MCP server to: ${chalk.dim(\n '(Toggle: Space, Confirm: Enter, Toggle All: A, Cancel: CTRL + C)',\n )}`,\n options: supportedClients.map((client) => ({\n value: client.name,\n label: client.name,\n })),\n initialValues: supportedClients.map((client) => client.name),\n required: true,\n }),\n integration,\n );\n\n const clients = supportedClients.filter((client) =>\n selectedClientNames.includes(client.name),\n );\n\n const installedClients = await getInstalledClients();\n\n if (installedClients.length > 0) {\n clack.log.warn(\n `The MCP server is already configured for:\n ${installedClients.map((c) => `- ${c.name}`).join('\\n ')}`,\n );\n\n const reinstall = await abortIfCancelled(\n clack.select({\n message: 'Would you like to reinstall it?',\n options: [\n {\n value: true,\n label: 'Yes',\n hint: 'Reinstall the MCP server',\n },\n {\n value: false,\n label: 'No',\n hint: 'Keep the existing installation',\n },\n ],\n }),\n integration,\n );\n\n if (!reinstall) {\n analytics.capture('wizard interaction', {\n action: 'declined to reinstall mcp servers',\n clients: installedClients.map((c) => c.name),\n integration,\n });\n\n return [];\n }\n\n await removeMCPServer(installedClients);\n clack.log.info('Removed existing installation.');\n }\n\n const personalApiKey = await getPersonalApiKey({ cloudRegion: region });\n\n await traceStep('adding mcp servers', async () => {\n await addMCPServer(clients, personalApiKey);\n });\n\n clack.log.success(\n `Added the MCP server to:\n ${clients.map((c) => `- ${c.name}`).join('\\n ')} `,\n );\n\n analytics.capture('wizard interaction', {\n action: 'added mcp servers',\n clients: clients.map((c) => c.name),\n integration,\n });\n\n return clients.map((c) => c.name);\n};\n\nexport const removeMCPServerFromClientsStep = async ({\n integration,\n}: {\n integration?: Integration;\n}): Promise<string[]> => {\n const installedClients = await getInstalledClients();\n\n if (installedClients.length === 0) {\n analytics.capture('wizard interaction', {\n action: 'no mcp servers to remove',\n integration,\n });\n return [];\n }\n\n const { multiselect } = await import('@clack/prompts');\n const selectedClientNames = await abortIfCancelled(\n multiselect({\n message: `Select which clients to remove the MCP server from: ${chalk.dim(\n '(Toggle: Space, Confirm: Enter, Toggle All: A, Cancel: CTRL + C)',\n )}`,\n options: installedClients.map((client) => ({\n value: client.name,\n label: client.name,\n })),\n initialValues: installedClients.map((client) => client.name),\n }),\n integration,\n );\n\n const clientsToRemove = installedClients.filter((client) =>\n selectedClientNames.includes(client.name),\n );\n\n if (clientsToRemove.length === 0) {\n analytics.capture('wizard interaction', {\n action: 'no mcp servers selected for removal',\n integration,\n });\n return [];\n }\n\n const results = await traceStep('removing mcp servers', async () => {\n await removeMCPServer(clientsToRemove);\n return clientsToRemove.map((c) => c.name);\n });\n\n analytics.capture('wizard interaction', {\n action: 'removed mcp servers',\n clients: results,\n integration,\n });\n\n return results;\n};\n\nexport const getInstalledClients = async (): Promise<MCPClient[]> => {\n const clients = await getSupportedClients();\n\n const installedClients: MCPClient[] = [];\n\n for (const client of clients) {\n if (await client.isServerInstalled()) {\n installedClients.push(client);\n }\n }\n\n return installedClients;\n};\n\nexport const addMCPServer = async (\n clients: MCPClient[],\n personalApiKey: string,\n): Promise<void> => {\n for (const client of clients) {\n await client.addServer(personalApiKey);\n }\n};\n\nexport const removeMCPServer = async (clients: MCPClient[]): Promise<void> => {\n for (const client of clients) {\n await client.removeServer();\n }\n};\n"]}
@@ -86,7 +86,7 @@ class VercelEnvironmentProvider extends EnvironmentProvider_1.EnvironmentProvide
86
86
  CI: '1', // hint to CLI that it's a non-interactive env
87
87
  },
88
88
  });
89
- const output = (result.stdout + result.stderr).toLowerCase();
89
+ const output = (String(result.stdout) + String(result.stderr)).toLowerCase();
90
90
  if (output.includes('log in to vercel') ||
91
91
  output.includes('vercel login') ||
92
92
  result.status !== 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../../../src/steps/upload-environment-variables/providers/vercel.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync, spawn, spawnSync } from 'child_process';\nimport { EnvironmentProvider } from '../EnvironmentProvider';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { WizardOptions } from '../../../utils/types';\nimport clack from '../../../utils/clack';\nimport chalk from 'chalk';\nimport { analytics } from '../../../utils/analytics';\n\nexport class VercelEnvironmentProvider extends EnvironmentProvider {\n name = 'Vercel';\n environments = ['production', 'preview', 'development'];\n\n constructor(options: WizardOptions) {\n super(options);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async detect(): Promise<boolean> {\n const vercelDetected =\n this.hasVercelCli() && this.isProjectLinked() && this.isAuthenticated();\n\n analytics.setTag('vercel-detected', vercelDetected);\n\n return vercelDetected;\n }\n\n hasDotVercelDir(): boolean {\n const dotVercelDir = path.join(this.options.installDir, '.vercel');\n return fs.existsSync(dotVercelDir);\n }\n\n hasVercelCli(): boolean {\n try {\n execSync('vercel --version', { stdio: 'ignore' });\n analytics.setTag('vercel-cli-installed', true);\n return true;\n } catch {\n analytics.setTag('vercel-cli-installed', false);\n return false;\n }\n }\n\n isProjectLinked(): boolean {\n const isProjectLinked = fs.existsSync(\n path.join(this.options.installDir, '.vercel', 'project.json'),\n );\n\n analytics.setTag('vercel-project-linked', isProjectLinked);\n\n return isProjectLinked;\n }\n\n isAuthenticated(): boolean {\n const result = spawnSync('vercel', ['whoami'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'], // suppress prompts\n env: {\n ...process.env,\n FORCE_COLOR: '0', // avoid ANSI formatting\n CI: '1', // hint to CLI that it's a non-interactive env\n },\n });\n\n const output = (result.stdout + result.stderr).toLowerCase();\n\n if (\n output.includes('log in to vercel') ||\n output.includes('vercel login') ||\n result.status !== 0\n ) {\n analytics.setTag('vercel-authenticated', false);\n return false;\n }\n\n analytics.setTag('vercel-authenticated', true);\n\n return true;\n }\n\n async uploadEnvironmentVariable(\n key: string,\n value: string,\n environment: string,\n ): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const proc = spawn('vercel', ['env', 'add', key, environment], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stderr = '';\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.stdin.write(value);\n proc.stdin.end();\n\n proc.on('close', (code) => {\n if (\n stderr.includes('already exists') ||\n stderr.includes('already been added') ||\n stderr.includes('vercel env rm')\n ) {\n reject(\n new Error(\n `❌ Environment variable ${chalk.cyan(key)} already exists in ${\n this.name\n }. Please upload it manually.`,\n ),\n );\n } else if (code === 0) {\n resolve();\n } else {\n reject(\n new Error(\n `❌ Failed to upload environment variable ${chalk.cyan(key)} to ${\n this.name\n }. Please upload it manually.`,\n ),\n );\n }\n });\n });\n }\n\n async uploadEnvVars(\n vars: Record<string, string>,\n ): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(vars)) {\n const spinner = clack.spinner();\n\n spinner.start(`Uploading ${chalk.cyan(key)} to ${this.name}...`);\n await Promise.all(\n this.environments.map((environment) =>\n this.uploadEnvironmentVariable(key, value, environment),\n ),\n )\n .then(() => {\n spinner.stop(`✅ Uploaded ${chalk.cyan(key)} to ${this.name}`);\n results[key] = true;\n })\n .catch((err) => {\n spinner.stop(\n err instanceof Error\n ? err.message\n : `❌ Failed to upload environment variables to ${this.name}. Please upload it manually.`,\n );\n results[key] = false;\n });\n }\n\n return results;\n }\n}\n"]}
1
+ {"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../../../src/steps/upload-environment-variables/providers/vercel.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync, spawn, spawnSync } from 'child_process';\nimport { EnvironmentProvider } from '../EnvironmentProvider';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { WizardOptions } from '../../../utils/types';\nimport clack from '../../../utils/clack';\nimport chalk from 'chalk';\nimport { analytics } from '../../../utils/analytics';\n\nexport class VercelEnvironmentProvider extends EnvironmentProvider {\n name = 'Vercel';\n environments = ['production', 'preview', 'development'];\n\n constructor(options: WizardOptions) {\n super(options);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async detect(): Promise<boolean> {\n const vercelDetected =\n this.hasVercelCli() && this.isProjectLinked() && this.isAuthenticated();\n\n analytics.setTag('vercel-detected', vercelDetected);\n\n return vercelDetected;\n }\n\n hasDotVercelDir(): boolean {\n const dotVercelDir = path.join(this.options.installDir, '.vercel');\n return fs.existsSync(dotVercelDir);\n }\n\n hasVercelCli(): boolean {\n try {\n execSync('vercel --version', { stdio: 'ignore' });\n analytics.setTag('vercel-cli-installed', true);\n return true;\n } catch {\n analytics.setTag('vercel-cli-installed', false);\n return false;\n }\n }\n\n isProjectLinked(): boolean {\n const isProjectLinked = fs.existsSync(\n path.join(this.options.installDir, '.vercel', 'project.json'),\n );\n\n analytics.setTag('vercel-project-linked', isProjectLinked);\n\n return isProjectLinked;\n }\n\n isAuthenticated(): boolean {\n const result = spawnSync('vercel', ['whoami'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'], // suppress prompts\n env: {\n ...process.env,\n FORCE_COLOR: '0', // avoid ANSI formatting\n CI: '1', // hint to CLI that it's a non-interactive env\n },\n });\n\n const output = (\n String(result.stdout) + String(result.stderr)\n ).toLowerCase();\n\n if (\n output.includes('log in to vercel') ||\n output.includes('vercel login') ||\n result.status !== 0\n ) {\n analytics.setTag('vercel-authenticated', false);\n return false;\n }\n\n analytics.setTag('vercel-authenticated', true);\n\n return true;\n }\n\n async uploadEnvironmentVariable(\n key: string,\n value: string,\n environment: string,\n ): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const proc = spawn('vercel', ['env', 'add', key, environment], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stderr = '';\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.stdin.write(value);\n proc.stdin.end();\n\n proc.on('close', (code) => {\n if (\n stderr.includes('already exists') ||\n stderr.includes('already been added') ||\n stderr.includes('vercel env rm')\n ) {\n reject(\n new Error(\n `❌ Environment variable ${chalk.cyan(key)} already exists in ${\n this.name\n }. Please upload it manually.`,\n ),\n );\n } else if (code === 0) {\n resolve();\n } else {\n reject(\n new Error(\n `❌ Failed to upload environment variable ${chalk.cyan(key)} to ${\n this.name\n }. Please upload it manually.`,\n ),\n );\n }\n });\n });\n }\n\n async uploadEnvVars(\n vars: Record<string, string>,\n ): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(vars)) {\n const spinner = clack.spinner();\n\n spinner.start(`Uploading ${chalk.cyan(key)} to ${this.name}...`);\n await Promise.all(\n this.environments.map((environment) =>\n this.uploadEnvironmentVariable(key, value, environment),\n ),\n )\n .then(() => {\n spinner.stop(`✅ Uploaded ${chalk.cyan(key)} to ${this.name}`);\n results[key] = true;\n })\n .catch((err) => {\n spinner.stop(\n err instanceof Error\n ? err.message\n : `❌ Failed to upload environment variables to ${this.name}. Please upload it manually.`,\n );\n results[key] = false;\n });\n }\n\n return results;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/wizard",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "homepage": "https://github.com/posthog/wizard",
5
5
  "repository": "https://github.com/posthog/wizard",
6
6
  "description": "The PostHog wizard helps you to configure your project",