@posthog/wizard 0.2.2

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 (72) hide show
  1. package/LICENSE +47 -0
  2. package/README.md +34 -0
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +28 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/src/lib/constants.d.ts +20 -0
  7. package/dist/src/lib/constants.js +34 -0
  8. package/dist/src/lib/constants.js.map +1 -0
  9. package/dist/src/nextjs/docs.d.ts +8 -0
  10. package/dist/src/nextjs/docs.js +235 -0
  11. package/dist/src/nextjs/docs.js.map +1 -0
  12. package/dist/src/nextjs/nextjs-wizard.d.ts +9 -0
  13. package/dist/src/nextjs/nextjs-wizard.js +331 -0
  14. package/dist/src/nextjs/nextjs-wizard.js.map +1 -0
  15. package/dist/src/nextjs/prompts.d.ts +12 -0
  16. package/dist/src/nextjs/prompts.js +64 -0
  17. package/dist/src/nextjs/prompts.js.map +1 -0
  18. package/dist/src/nextjs/utils.d.ts +9 -0
  19. package/dist/src/nextjs/utils.js +80 -0
  20. package/dist/src/nextjs/utils.js.map +1 -0
  21. package/dist/src/run.d.ts +8 -0
  22. package/dist/src/run.js +69 -0
  23. package/dist/src/run.js.map +1 -0
  24. package/dist/src/telemetry.d.ts +2 -0
  25. package/dist/src/telemetry.js +13 -0
  26. package/dist/src/telemetry.js.map +1 -0
  27. package/dist/src/utils/analytics.d.ts +4 -0
  28. package/dist/src/utils/analytics.js +10 -0
  29. package/dist/src/utils/analytics.js.map +1 -0
  30. package/dist/src/utils/bash.d.ts +2 -0
  31. package/dist/src/utils/bash.js +54 -0
  32. package/dist/src/utils/bash.js.map +1 -0
  33. package/dist/src/utils/clack-utils.d.ts +177 -0
  34. package/dist/src/utils/clack-utils.js +628 -0
  35. package/dist/src/utils/clack-utils.js.map +1 -0
  36. package/dist/src/utils/clack.d.ts +2 -0
  37. package/dist/src/utils/clack.js +9 -0
  38. package/dist/src/utils/clack.js.map +1 -0
  39. package/dist/src/utils/debug.d.ts +2 -0
  40. package/dist/src/utils/debug.js +22 -0
  41. package/dist/src/utils/debug.js.map +1 -0
  42. package/dist/src/utils/environment.d.ts +1 -0
  43. package/dist/src/utils/environment.js +12 -0
  44. package/dist/src/utils/environment.js.map +1 -0
  45. package/dist/src/utils/file-utils.d.ts +2 -0
  46. package/dist/src/utils/file-utils.js +38 -0
  47. package/dist/src/utils/file-utils.js.map +1 -0
  48. package/dist/src/utils/logging.d.ts +9 -0
  49. package/dist/src/utils/logging.js +50 -0
  50. package/dist/src/utils/logging.js.map +1 -0
  51. package/dist/src/utils/package-json.d.ts +25 -0
  52. package/dist/src/utils/package-json.js +27 -0
  53. package/dist/src/utils/package-json.js.map +1 -0
  54. package/dist/src/utils/package-manager.d.ts +19 -0
  55. package/dist/src/utils/package-manager.js +188 -0
  56. package/dist/src/utils/package-manager.js.map +1 -0
  57. package/dist/src/utils/query.d.ts +6 -0
  58. package/dist/src/utils/query.js +27 -0
  59. package/dist/src/utils/query.js.map +1 -0
  60. package/dist/src/utils/semver.d.ts +5 -0
  61. package/dist/src/utils/semver.js +25 -0
  62. package/dist/src/utils/semver.js.map +1 -0
  63. package/dist/src/utils/string.d.ts +1 -0
  64. package/dist/src/utils/string.js +9 -0
  65. package/dist/src/utils/string.js.map +1 -0
  66. package/dist/src/utils/types.d.ts +30 -0
  67. package/dist/src/utils/types.js +3 -0
  68. package/dist/src/utils/types.js.map +1 -0
  69. package/dist/src/utils/vendor/is-unicorn-supported.d.ts +1 -0
  70. package/dist/src/utils/vendor/is-unicorn-supported.js +24 -0
  71. package/dist/src/utils/vendor/is-unicorn-supported.js.map +1 -0
  72. package/package.json +135 -0
@@ -0,0 +1,331 @@
1
+ "use strict";
2
+ /* eslint-disable max-lines */
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.runNextjsWizard = runNextjsWizard;
41
+ exports.detectNextJs = detectNextJs;
42
+ exports.addOrUpdateEnvironmentVariables = addOrUpdateEnvironmentVariables;
43
+ exports.getDotGitignore = getDotGitignore;
44
+ const chalk_1 = __importDefault(require("chalk"));
45
+ const fs = __importStar(require("fs"));
46
+ const zod_1 = require("zod");
47
+ const clack_utils_1 = require("../utils/clack-utils");
48
+ const telemetry_1 = require("../telemetry");
49
+ const package_json_1 = require("../utils/package-json");
50
+ const utils_1 = require("./utils");
51
+ const prompts_1 = require("./prompts");
52
+ const query_1 = require("../utils/query");
53
+ const clack_1 = __importDefault(require("../utils/clack"));
54
+ const fast_glob_1 = __importDefault(require("fast-glob"));
55
+ const path_1 = __importDefault(require("path"));
56
+ const constants_1 = require("../lib/constants");
57
+ const docs_1 = require("./docs");
58
+ const analytics_1 = require("../utils/analytics");
59
+ async function runNextjsWizard(options) {
60
+ const { telemetryEnabled, forceInstall } = options;
61
+ (0, clack_utils_1.printWelcome)({
62
+ wizardName: 'PostHog Next.js Wizard',
63
+ telemetryEnabled,
64
+ });
65
+ const aiConsent = await askForAIConsent();
66
+ if (!aiConsent) {
67
+ await (0, clack_utils_1.abort)('The Next.js wizard requires AI to get setup right now. Please view the docs to setup Next.js manually instead: https://posthog.com/docs/libraries/next-js', 0);
68
+ }
69
+ const typeScriptDetected = (0, clack_utils_1.isUsingTypeScript)();
70
+ await (0, clack_utils_1.confirmContinueIfNoOrDirtyGitRepo)();
71
+ const packageJson = await (0, clack_utils_1.getPackageDotJson)();
72
+ await (0, clack_utils_1.ensurePackageIsInstalled)(packageJson, 'next', 'Next.js');
73
+ const nextVersion = (0, package_json_1.getPackageVersion)('next', packageJson);
74
+ analytics_1.Analytics.setTag('nextjs-version', (0, utils_1.getNextJsVersionBucket)(nextVersion));
75
+ const { projectApiKey, wizardHash, host } = await (0, clack_utils_1.getOrAskForProjectData)(options);
76
+ const sdkAlreadyInstalled = (0, package_json_1.hasPackageInstalled)('posthog-js', packageJson);
77
+ analytics_1.Analytics.setTag('sdk-already-installed', sdkAlreadyInstalled);
78
+ const { packageManager: packageManagerFromInstallStep } = await (0, clack_utils_1.installPackage)({
79
+ packageName: 'posthog-js',
80
+ packageNameDisplayLabel: 'posthog-js',
81
+ alreadyInstalled: !!packageJson?.dependencies?.['posthog-js'],
82
+ forceInstall,
83
+ askBeforeUpdating: false,
84
+ });
85
+ await (0, clack_utils_1.installPackage)({
86
+ packageName: 'posthog-node',
87
+ packageNameDisplayLabel: 'posthog-node',
88
+ packageManager: packageManagerFromInstallStep,
89
+ alreadyInstalled: !!packageJson?.dependencies?.['posthog-node'],
90
+ forceInstall,
91
+ askBeforeUpdating: false,
92
+ });
93
+ const router = await (0, utils_1.getNextJsRouter)();
94
+ const relevantFiles = await getRelevantFilesForNextJs();
95
+ const installationDocumentation = getInstallationDocumentation({
96
+ router,
97
+ host,
98
+ language: typeScriptDetected ? 'typescript' : 'javascript',
99
+ });
100
+ clack_1.default.log.info(`Reviewing PostHog documentation for ${(0, utils_1.getNextJsRouterName)(router)}`);
101
+ const filesToChange = await getFilesToChange({
102
+ relevantFiles,
103
+ installationDocumentation,
104
+ wizardHash,
105
+ });
106
+ const changes = [];
107
+ for (const filePath of filesToChange) {
108
+ const fileChangeSpinner = clack_1.default.spinner();
109
+ try {
110
+ let oldContent = undefined;
111
+ try {
112
+ oldContent = await fs.promises.readFile(path_1.default.join(constants_1.INSTALL_DIR, filePath), 'utf8');
113
+ }
114
+ catch (readError) {
115
+ if (readError.code !== 'ENOENT') {
116
+ await (0, clack_utils_1.abort)(`Error reading file ${filePath}`);
117
+ continue;
118
+ }
119
+ }
120
+ fileChangeSpinner.start(`${oldContent ? 'Updating' : 'Creating'} file ${filePath}`);
121
+ const unchangedFiles = filesToChange.filter((filePath) => !changes.some((change) => change.filePath === filePath));
122
+ const newContent = await generateFileChanges({
123
+ filePath,
124
+ content: oldContent,
125
+ changedFiles: changes,
126
+ unchangedFiles,
127
+ installationDocumentation,
128
+ wizardHash,
129
+ });
130
+ if (newContent !== oldContent) {
131
+ await updateFile({ filePath, oldContent, newContent });
132
+ changes.push({ filePath, oldContent, newContent });
133
+ }
134
+ fileChangeSpinner.stop(`${oldContent ? 'Updated' : 'Created'} file ${filePath}`);
135
+ }
136
+ catch (error) {
137
+ await (0, clack_utils_1.abort)(`Error processing file ${filePath}`);
138
+ }
139
+ }
140
+ await addOrUpdateEnvironmentVariables({
141
+ projectApiKey,
142
+ host,
143
+ });
144
+ const packageManagerForOutro = packageManagerFromInstallStep ?? (await (0, clack_utils_1.getPackageManager)());
145
+ await (0, clack_utils_1.runPrettierIfInstalled)();
146
+ clack_1.default.outro(`
147
+ ${chalk_1.default.green('Successfully installed PostHog!')} ${`\n\n${aiConsent
148
+ ? `Note: This uses experimental AI to setup your project. It might have got it wrong, pleaes check!\n`
149
+ : ``}You should validate your setup by (re)starting your dev environment (e.g. ${chalk_1.default.cyan(`${packageManagerForOutro.runScriptCommand} dev`)})`}
150
+
151
+ ${chalk_1.default.dim(`If you encounter any issues, let us know here: ${constants_1.ISSUES_URL}`)}`);
152
+ }
153
+ async function askForAIConsent() {
154
+ return await (0, telemetry_1.traceStep)('ask-for-ai-consent', async () => {
155
+ const aiConsent = await (0, clack_utils_1.abortIfCancelled)(clack_1.default.select({
156
+ message: 'Use AI to setup PostHog automatically? ✨',
157
+ options: [
158
+ {
159
+ label: 'Yes',
160
+ value: true,
161
+ hint: 'We will use AI to help you setup PostHog quickly',
162
+ },
163
+ {
164
+ label: 'No',
165
+ value: false,
166
+ hint: 'Continue without AI assistance',
167
+ },
168
+ ],
169
+ initialValue: true,
170
+ }));
171
+ return aiConsent;
172
+ });
173
+ }
174
+ async function getRelevantFilesForNextJs() {
175
+ const filterPatterns = ['**/*.{tsx,ts,jsx,js,mjs,cjs}'];
176
+ const ignorePatterns = [
177
+ 'node_modules',
178
+ 'dist',
179
+ 'build',
180
+ 'public',
181
+ 'static',
182
+ 'next-env.d.*',
183
+ ];
184
+ const filteredFiles = await (0, fast_glob_1.default)(filterPatterns, {
185
+ cwd: constants_1.INSTALL_DIR,
186
+ ignore: ignorePatterns,
187
+ });
188
+ return filteredFiles;
189
+ }
190
+ async function detectNextJs() {
191
+ const packageJson = await (0, clack_utils_1.getPackageDotJson)();
192
+ const hasNextInstalled = (0, package_json_1.hasPackageInstalled)('next', packageJson);
193
+ if (hasNextInstalled)
194
+ return constants_1.Integration.nextjs;
195
+ return undefined;
196
+ }
197
+ function getInstallationDocumentation({ router, host, language, }) {
198
+ if (router === utils_1.NextJsRouter.PAGES_ROUTER) {
199
+ return (0, docs_1.getNextjsPagesRouterDocs)({ host, language });
200
+ }
201
+ return (0, docs_1.getNextjsAppRouterDocs)({ host, language });
202
+ }
203
+ async function getFilesToChange({ relevantFiles, installationDocumentation, wizardHash, }) {
204
+ const filterFilesSpinner = clack_1.default.spinner();
205
+ filterFilesSpinner.start('Selecting files to change...');
206
+ const filterFilesResponseSchmea = zod_1.z.object({
207
+ files: zod_1.z.array(zod_1.z.string()),
208
+ });
209
+ const filterFilesPrompt = await prompts_1.filterFilesPromptTemplate.format({
210
+ documentation: installationDocumentation,
211
+ file_list: relevantFiles.join('\n'),
212
+ });
213
+ const filterFilesResponse = await (0, query_1.query)({
214
+ message: filterFilesPrompt,
215
+ schema: filterFilesResponseSchmea,
216
+ wizardHash,
217
+ });
218
+ const filesToChange = filterFilesResponse.files;
219
+ filterFilesSpinner.stop(`Found ${filesToChange.length} files to change`);
220
+ return filesToChange;
221
+ }
222
+ async function generateFileChanges({ filePath, content, changedFiles, unchangedFiles, installationDocumentation, wizardHash, }) {
223
+ const generateFileChangesPrompt = await prompts_1.generateFileChangesPromptTemplate.format({
224
+ file_path: filePath,
225
+ file_content: content,
226
+ changed_files: changedFiles
227
+ .map((change) => `${change.filePath}\n${change.oldContent}`)
228
+ .join('\n'),
229
+ unchanged_files: unchangedFiles,
230
+ documentation: installationDocumentation,
231
+ });
232
+ const response = await (0, query_1.query)({
233
+ message: generateFileChangesPrompt,
234
+ schema: zod_1.z.object({
235
+ newContent: zod_1.z.string(),
236
+ }),
237
+ wizardHash: wizardHash,
238
+ });
239
+ return response.newContent;
240
+ }
241
+ async function updateFile(change) {
242
+ const dir = path_1.default.dirname(path_1.default.join(constants_1.INSTALL_DIR, change.filePath));
243
+ await fs.promises.mkdir(dir, { recursive: true });
244
+ await fs.promises.writeFile(path_1.default.join(constants_1.INSTALL_DIR, change.filePath), change.newContent);
245
+ }
246
+ async function addOrUpdateEnvironmentVariables({ projectApiKey, host, }) {
247
+ const envVarContent = `# Posthog\nNEXT_PUBLIC_POSTHOG_KEY=${projectApiKey}\nNEXT_PUBLIC_POSTHOG_HOST=${host}\n`;
248
+ const dotEnvLocalFilePath = path_1.default.join(constants_1.INSTALL_DIR, '.env.local');
249
+ const dotEnvFilePath = path_1.default.join(constants_1.INSTALL_DIR, '.env');
250
+ const targetEnvFilePath = fs.existsSync(dotEnvLocalFilePath)
251
+ ? dotEnvLocalFilePath
252
+ : dotEnvFilePath;
253
+ const dotEnvFileExists = fs.existsSync(targetEnvFilePath);
254
+ const relativeEnvFilePath = path_1.default.relative(constants_1.INSTALL_DIR, targetEnvFilePath);
255
+ if (dotEnvFileExists) {
256
+ const dotEnvFileContent = fs.readFileSync(targetEnvFilePath, 'utf8');
257
+ const hasProjectApiKey = dotEnvFileContent.includes(`NEXT_PUBLIC_POSTHOG_KEY=${projectApiKey}`);
258
+ const hasHost = dotEnvFileContent.includes(`NEXT_PUBLIC_POSTHOG_HOST=${host}`);
259
+ if (hasProjectApiKey && hasHost) {
260
+ clack_1.default.log.success(`${chalk_1.default.bold.cyan(relativeEnvFilePath)} already has the necessary environment variables.`);
261
+ }
262
+ else {
263
+ try {
264
+ const newContent = dotEnvFileContent
265
+ .replace(/^NEXT_PUBLIC_POSTHOG_KEY=.*$/m, `NEXT_PUBLIC_POSTHOG_KEY=${projectApiKey}`)
266
+ .replace(/^NEXT_PUBLIC_POSTHOG_HOST=.*$/m, `NEXT_PUBLIC_POSTHOG_HOST=${host}`);
267
+ await fs.promises.writeFile(targetEnvFilePath, newContent, {
268
+ encoding: 'utf8',
269
+ flag: 'w',
270
+ });
271
+ clack_1.default.log.success(`Updated environment variables in ${chalk_1.default.bold.cyan(relativeEnvFilePath)}`);
272
+ }
273
+ catch (error) {
274
+ clack_1.default.log.warning(`Failed to update environment variables in ${chalk_1.default.bold.cyan(relativeEnvFilePath)}. Please update them manually. Error: ${error.message}`);
275
+ }
276
+ }
277
+ }
278
+ else {
279
+ try {
280
+ await fs.promises.writeFile(targetEnvFilePath, envVarContent, {
281
+ encoding: 'utf8',
282
+ flag: 'w',
283
+ });
284
+ clack_1.default.log.success(`Created ${chalk_1.default.bold.cyan(relativeEnvFilePath)} with environment variables for PostHog.`);
285
+ }
286
+ catch (error) {
287
+ clack_1.default.log.warning(`Failed to create ${chalk_1.default.bold.cyan(relativeEnvFilePath)} with environment variables for PostHog. Please add them manually. Error: ${error.message}`);
288
+ }
289
+ }
290
+ const gitignorePath = getDotGitignore();
291
+ if (gitignorePath) {
292
+ const gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
293
+ const envFiles = ['.env', '.env.local'];
294
+ const missingEnvFiles = envFiles;
295
+ if (missingEnvFiles.length > 0) {
296
+ try {
297
+ const newGitignoreContent = `${gitignoreContent}\n${missingEnvFiles.join('\n')}`;
298
+ await fs.promises.writeFile(gitignorePath, newGitignoreContent, {
299
+ encoding: 'utf8',
300
+ flag: 'w',
301
+ });
302
+ clack_1.default.log.success(`Updated ${chalk_1.default.bold.cyan('.gitignore')} to include environment files.`);
303
+ }
304
+ catch (error) {
305
+ clack_1.default.log.warning(`Failed to update ${chalk_1.default.bold.cyan('.gitignore')} to include environment files. Error: ${error.message}`);
306
+ }
307
+ }
308
+ }
309
+ else {
310
+ try {
311
+ const newGitignoreContent = `.env\n.env.local\n`;
312
+ await fs.promises.writeFile(path_1.default.join(constants_1.INSTALL_DIR, '.gitignore'), newGitignoreContent, {
313
+ encoding: 'utf8',
314
+ flag: 'w',
315
+ });
316
+ clack_1.default.log.success(`Created ${chalk_1.default.bold.cyan('.gitignore')} with environment files.`);
317
+ }
318
+ catch (error) {
319
+ clack_1.default.log.warning(`Failed to create ${chalk_1.default.bold.cyan('.gitignore')} with environment files. Error: ${error.message}`);
320
+ }
321
+ }
322
+ }
323
+ function getDotGitignore() {
324
+ const gitignorePath = path_1.default.join(constants_1.INSTALL_DIR, '.gitignore');
325
+ const gitignoreExists = fs.existsSync(gitignorePath);
326
+ if (gitignoreExists) {
327
+ return gitignorePath;
328
+ }
329
+ return undefined;
330
+ }
331
+ //# sourceMappingURL=nextjs-wizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs-wizard.js","sourceRoot":"","sources":["../../../src/nextjs/nextjs-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\n\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport { z } from 'zod';\nimport {\n abort,\n abortIfCancelled,\n confirmContinueIfNoOrDirtyGitRepo,\n ensurePackageIsInstalled,\n getOrAskForProjectData,\n getPackageDotJson,\n getPackageManager,\n installPackage,\n isUsingTypeScript,\n printWelcome,\n runPrettierIfInstalled,\n} from '../utils/clack-utils';\nimport type { WizardOptions } from '../utils/types';\nimport { traceStep, } from '../telemetry';\nimport { getPackageVersion, hasPackageInstalled } from '../utils/package-json';\nimport {\n getNextJsRouter,\n getNextJsRouterName,\n getNextJsVersionBucket,\n NextJsRouter,\n} from './utils';\nimport {\n filterFilesPromptTemplate,\n generateFileChangesPromptTemplate,\n} from './prompts';\nimport { query } from '../utils/query';\nimport clack from '../utils/clack';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport { INSTALL_DIR, Integration, ISSUES_URL } from '../lib/constants';\nimport { getNextjsAppRouterDocs, getNextjsPagesRouterDocs } from './docs';\nimport { Analytics } from '../utils/analytics';\n\n\nexport async function runNextjsWizard(\n options: WizardOptions,\n): Promise<void> {\n const { telemetryEnabled, forceInstall } = options;\n\n printWelcome({\n wizardName: 'PostHog Next.js Wizard',\n telemetryEnabled,\n });\n\n const aiConsent = await askForAIConsent();\n\n if (!aiConsent) {\n await abort(\n 'The Next.js wizard requires AI to get setup right now. Please view the docs to setup Next.js manually instead: https://posthog.com/docs/libraries/next-js',\n 0,\n );\n }\n\n const typeScriptDetected = isUsingTypeScript();\n\n await confirmContinueIfNoOrDirtyGitRepo();\n\n const packageJson = await getPackageDotJson();\n\n await ensurePackageIsInstalled(packageJson, 'next', 'Next.js');\n\n const nextVersion = getPackageVersion('next', packageJson);\n\n Analytics.setTag('nextjs-version', getNextJsVersionBucket(nextVersion));\n\n const { projectApiKey, wizardHash, host } = await getOrAskForProjectData(\n options,\n );\n\n const sdkAlreadyInstalled = hasPackageInstalled('posthog-js', packageJson);\n\n Analytics.setTag('sdk-already-installed', sdkAlreadyInstalled);\n\n const { packageManager: packageManagerFromInstallStep } =\n await installPackage({\n packageName: 'posthog-js',\n packageNameDisplayLabel: 'posthog-js',\n alreadyInstalled: !!packageJson?.dependencies?.['posthog-js'],\n forceInstall,\n askBeforeUpdating: false,\n });\n\n await installPackage({\n packageName: 'posthog-node',\n packageNameDisplayLabel: 'posthog-node',\n packageManager: packageManagerFromInstallStep,\n alreadyInstalled: !!packageJson?.dependencies?.['posthog-node'],\n forceInstall,\n askBeforeUpdating: false,\n });\n\n const router = await getNextJsRouter();\n\n const relevantFiles = await getRelevantFilesForNextJs();\n\n const installationDocumentation = getInstallationDocumentation({\n router,\n host,\n language: typeScriptDetected ? 'typescript' : 'javascript',\n });\n\n clack.log.info(\n `Reviewing PostHog documentation for ${getNextJsRouterName(router)}`,\n );\n\n const filesToChange = await getFilesToChange({\n relevantFiles,\n installationDocumentation,\n wizardHash,\n });\n\n const changes: FileChange[] = [];\n\n for (const filePath of filesToChange) {\n const fileChangeSpinner = clack.spinner();\n\n try {\n let oldContent = undefined;\n try {\n oldContent = await fs.promises.readFile(\n path.join(INSTALL_DIR, filePath),\n 'utf8',\n );\n } catch (readError) {\n if (readError.code !== 'ENOENT') {\n await abort(`Error reading file ${filePath}`);\n continue;\n }\n }\n\n fileChangeSpinner.start(\n `${oldContent ? 'Updating' : 'Creating'} file ${filePath}`,\n );\n\n const unchangedFiles = filesToChange.filter(\n (filePath) => !changes.some((change) => change.filePath === filePath),\n );\n\n const newContent = await generateFileChanges({\n filePath,\n content: oldContent,\n changedFiles: changes,\n unchangedFiles,\n installationDocumentation,\n wizardHash,\n });\n\n if (newContent !== oldContent) {\n await updateFile({ filePath, oldContent, newContent });\n changes.push({ filePath, oldContent, newContent });\n }\n\n fileChangeSpinner.stop(\n `${oldContent ? 'Updated' : 'Created'} file ${filePath}`,\n );\n } catch (error) {\n await abort(`Error processing file ${filePath}`);\n }\n }\n\n await addOrUpdateEnvironmentVariables({\n projectApiKey,\n host,\n });\n\n const packageManagerForOutro =\n packageManagerFromInstallStep ?? (await getPackageManager());\n\n await runPrettierIfInstalled();\n\n clack.outro(`\n${chalk.green('Successfully installed PostHog!')} ${`\\n\\n${aiConsent\n ? `Note: This uses experimental AI to setup your project. It might have got it wrong, pleaes check!\\n`\n : ``\n }You should validate your setup by (re)starting your dev environment (e.g. ${chalk.cyan(\n `${packageManagerForOutro.runScriptCommand} dev`,\n )})`}\n\n${chalk.dim(`If you encounter any issues, let us know here: ${ISSUES_URL}`)}`);\n}\n\nasync function askForAIConsent() {\n return await traceStep('ask-for-ai-consent', async () => {\n const aiConsent = await abortIfCancelled(\n clack.select({\n message: 'Use AI to setup PostHog automatically? ✨',\n options: [\n {\n label: 'Yes',\n value: true,\n hint: 'We will use AI to help you setup PostHog quickly',\n },\n {\n label: 'No',\n value: false,\n hint: 'Continue without AI assistance',\n },\n ],\n initialValue: true,\n }),\n );\n\n return aiConsent;\n });\n}\n\nasync function getRelevantFilesForNextJs() {\n const filterPatterns = ['**/*.{tsx,ts,jsx,js,mjs,cjs}'];\n const ignorePatterns = [\n 'node_modules',\n 'dist',\n 'build',\n 'public',\n 'static',\n 'next-env.d.*',\n ];\n\n const filteredFiles = await fg(filterPatterns, {\n cwd: INSTALL_DIR,\n ignore: ignorePatterns,\n });\n\n return filteredFiles;\n}\n\nexport async function detectNextJs(): Promise<Integration.nextjs | undefined> {\n const packageJson = await getPackageDotJson();\n\n const hasNextInstalled = hasPackageInstalled('next', packageJson);\n\n if (hasNextInstalled) return Integration.nextjs;\n\n return undefined;\n}\n\nfunction getInstallationDocumentation({\n router,\n host,\n language,\n}: {\n router: NextJsRouter;\n host: string;\n language: 'typescript' | 'javascript';\n}) {\n if (router === NextJsRouter.PAGES_ROUTER) {\n return getNextjsPagesRouterDocs({ host, language });\n }\n\n return getNextjsAppRouterDocs({ host, language });\n}\n\nasync function getFilesToChange({\n relevantFiles,\n installationDocumentation,\n wizardHash,\n}: {\n relevantFiles: string[];\n installationDocumentation: string;\n wizardHash: string;\n}) {\n const filterFilesSpinner = clack.spinner();\n\n filterFilesSpinner.start('Selecting files to change...');\n\n const filterFilesResponseSchmea = z.object({\n files: z.array(z.string()),\n });\n\n const filterFilesPrompt = await filterFilesPromptTemplate.format({\n documentation: installationDocumentation,\n file_list: relevantFiles.join('\\n'),\n });\n\n const filterFilesResponse = await query({\n message: filterFilesPrompt,\n schema: filterFilesResponseSchmea,\n wizardHash,\n });\n\n const filesToChange = filterFilesResponse.files;\n\n filterFilesSpinner.stop(`Found ${filesToChange.length} files to change`);\n\n return filesToChange;\n}\n\nasync function generateFileChanges({\n filePath,\n content,\n changedFiles,\n unchangedFiles,\n installationDocumentation,\n wizardHash,\n}: {\n filePath: string;\n content: string | undefined;\n changedFiles: FileChange[];\n unchangedFiles: string[];\n installationDocumentation: string;\n wizardHash: string;\n}) {\n const generateFileChangesPrompt =\n await generateFileChangesPromptTemplate.format({\n file_path: filePath,\n file_content: content,\n changed_files: changedFiles\n .map((change) => `${change.filePath}\\n${change.oldContent}`)\n .join('\\n'),\n unchanged_files: unchangedFiles,\n documentation: installationDocumentation,\n });\n\n const response = await query({\n message: generateFileChangesPrompt,\n schema: z.object({\n newContent: z.string(),\n }),\n wizardHash: wizardHash,\n });\n\n return response.newContent;\n}\n\nasync function updateFile(change: FileChange) {\n const dir = path.dirname(path.join(INSTALL_DIR, change.filePath));\n await fs.promises.mkdir(dir, { recursive: true });\n await fs.promises.writeFile(\n path.join(INSTALL_DIR, change.filePath),\n change.newContent,\n );\n}\n\ntype FileChange = {\n filePath: string;\n oldContent?: string;\n newContent: string;\n};\n\nexport async function addOrUpdateEnvironmentVariables({\n projectApiKey,\n host,\n}: {\n projectApiKey: string;\n host: string;\n}): Promise<void> {\n const envVarContent = `# Posthog\\nNEXT_PUBLIC_POSTHOG_KEY=${projectApiKey}\\nNEXT_PUBLIC_POSTHOG_HOST=${host}\\n`;\n\n const dotEnvLocalFilePath = path.join(INSTALL_DIR, '.env.local');\n const dotEnvFilePath = path.join(INSTALL_DIR, '.env');\n const targetEnvFilePath = fs.existsSync(dotEnvLocalFilePath)\n ? dotEnvLocalFilePath\n : dotEnvFilePath;\n\n const dotEnvFileExists = fs.existsSync(targetEnvFilePath);\n\n const relativeEnvFilePath = path.relative(INSTALL_DIR, targetEnvFilePath);\n\n if (dotEnvFileExists) {\n const dotEnvFileContent = fs.readFileSync(targetEnvFilePath, 'utf8');\n\n const hasProjectApiKey = dotEnvFileContent.includes(\n `NEXT_PUBLIC_POSTHOG_KEY=${projectApiKey}`,\n );\n const hasHost = dotEnvFileContent.includes(\n `NEXT_PUBLIC_POSTHOG_HOST=${host}`,\n );\n\n if (hasProjectApiKey && hasHost) {\n clack.log.success(\n `${chalk.bold.cyan(\n relativeEnvFilePath,\n )} already has the necessary environment variables.`,\n );\n } else {\n try {\n const newContent = dotEnvFileContent\n .replace(\n /^NEXT_PUBLIC_POSTHOG_KEY=.*$/m,\n `NEXT_PUBLIC_POSTHOG_KEY=${projectApiKey}`,\n )\n .replace(\n /^NEXT_PUBLIC_POSTHOG_HOST=.*$/m,\n `NEXT_PUBLIC_POSTHOG_HOST=${host}`,\n );\n await fs.promises.writeFile(targetEnvFilePath, newContent, {\n encoding: 'utf8',\n flag: 'w',\n });\n clack.log.success(\n `Updated environment variables in ${chalk.bold.cyan(\n relativeEnvFilePath,\n )}`,\n );\n } catch (error) {\n clack.log.warning(\n `Failed to update environment variables in ${chalk.bold.cyan(\n relativeEnvFilePath,\n )}. Please update them manually. Error: ${error.message}`,\n );\n }\n }\n } else {\n try {\n await fs.promises.writeFile(targetEnvFilePath, envVarContent, {\n encoding: 'utf8',\n flag: 'w',\n });\n clack.log.success(\n `Created ${chalk.bold.cyan(\n relativeEnvFilePath,\n )} with environment variables for PostHog.`,\n );\n } catch (error) {\n clack.log.warning(\n `Failed to create ${chalk.bold.cyan(\n relativeEnvFilePath,\n )} with environment variables for PostHog. Please add them manually. Error: ${error.message\n }`,\n );\n }\n }\n\n const gitignorePath = getDotGitignore();\n\n if (gitignorePath) {\n const gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');\n const envFiles = ['.env', '.env.local'];\n const missingEnvFiles = envFiles\n\n if (missingEnvFiles.length > 0) {\n try {\n const newGitignoreContent = `${gitignoreContent}\\n${missingEnvFiles.join(\n '\\n',\n )}`;\n await fs.promises.writeFile(gitignorePath, newGitignoreContent, {\n encoding: 'utf8',\n flag: 'w',\n });\n clack.log.success(\n `Updated ${chalk.bold.cyan(\n '.gitignore',\n )} to include environment files.`,\n );\n } catch (error) {\n clack.log.warning(\n `Failed to update ${chalk.bold.cyan(\n '.gitignore',\n )} to include environment files. Error: ${error.message}`,\n );\n }\n }\n } else {\n try {\n const newGitignoreContent = `.env\\n.env.local\\n`;\n await fs.promises.writeFile(\n path.join(INSTALL_DIR, '.gitignore'),\n newGitignoreContent,\n {\n encoding: 'utf8',\n flag: 'w',\n },\n );\n clack.log.success(\n `Created ${chalk.bold.cyan('.gitignore')} with environment files.`,\n );\n } catch (error) {\n clack.log.warning(\n `Failed to create ${chalk.bold.cyan(\n '.gitignore',\n )} with environment files. Error: ${error.message}`,\n );\n }\n }\n}\n\nexport function getDotGitignore() {\n const gitignorePath = path.join(INSTALL_DIR, '.gitignore');\n const gitignoreExists = fs.existsSync(gitignorePath);\n\n if (gitignoreExists) {\n return gitignorePath;\n }\n\n return undefined;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { PromptTemplate } from "@langchain/core/prompts";
2
+ export declare const filterFilesPromptTemplate: PromptTemplate<{
3
+ documentation: any;
4
+ file_list: any;
5
+ }, any>;
6
+ export declare const generateFileChangesPromptTemplate: PromptTemplate<{
7
+ documentation: any;
8
+ file_content: any;
9
+ file_path: any;
10
+ changed_files: any;
11
+ unchanged_files: any;
12
+ }, any>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFileChangesPromptTemplate = exports.filterFilesPromptTemplate = void 0;
4
+ const prompts_1 = require("@langchain/core/prompts");
5
+ exports.filterFilesPromptTemplate = new prompts_1.PromptTemplate({
6
+ inputVariables: ['documentation', 'file_list'],
7
+ template: `You are a PostHog installation wizard, a master AI programming assistant that implements PostHog for Next.js projects.
8
+ Given the following list of Next.js file paths from a project, determine which files are likely to require modifications
9
+ to integrate PostHog. Use the installation documentation as a reference for what files might need modifications, do not include files that are unlikely to require modification based on the documentation.
10
+
11
+ - If you would like to create a new file, you can include the file path in your response.
12
+ - If you would like to modify an existing file, you can include the file path in your response.
13
+
14
+ You should return all files that you think will be required to look at or modify to integrate PostHog. You should return them in the order you would like to see them processed, with new files first, followed by the files that you want to update to integrate PostHog.
15
+
16
+ Rules:
17
+ - Only return files that you think will be required to look at or modify to integrate PostHog.
18
+ - Do not return files that are unlikely to require modification based on the documentation.
19
+ - If you are unsure, return the file, since it's better to have more files than less.
20
+ - If you create a new file, it should not conflict with any existing files.
21
+ - If the user is using TypeScript, you should return .ts and .tsx files.
22
+ - You should implement both posthog-js and posthog-node.
23
+ - The file structure of the project may be different than the documentation, you should follow the file structure of the project.
24
+
25
+ Installation documentation:
26
+ {documentation}
27
+
28
+ All current files in the repository:
29
+
30
+ {file_list}`
31
+ });
32
+ exports.generateFileChangesPromptTemplate = new prompts_1.PromptTemplate({
33
+ inputVariables: ['file_content', 'documentation', 'file_path', 'changed_files', 'unchanged_files'],
34
+ template: `You are a PostHog installation wizard, a master AI programming assistant that implements PostHog for Next.js projects.
35
+
36
+ Your task is to update the file to integrate PostHog according to the documentation.
37
+ Do not return a diff — you should return the complete updated file content.
38
+
39
+ Rules:
40
+ - Preserve the existing code formatting and style.
41
+ - Only make the changes required by the documentation.
42
+ - If no changes are needed, return the file as-is.
43
+ - If the current file is empty, and you think it should be created, you can add the contents of the new file.
44
+ - The file structure of the project may be different than the documentation, you should follow the file structure of the project.
45
+
46
+ CONTEXT
47
+ ---
48
+
49
+ Documentation for integrating PostHog with Next.js:
50
+ {documentation}
51
+
52
+ The file you are updating is:
53
+ {file_path}
54
+
55
+ Here are the changes you have already made to the project:
56
+ {changed_files}
57
+
58
+ Here are the files that have not been changed yet:
59
+ {unchanged_files}
60
+
61
+ Below is the current file contents:
62
+ {file_content}`
63
+ });
64
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/nextjs/prompts.ts"],"names":[],"mappings":";;;AAAA,qDAAyD;AAE5C,QAAA,yBAAyB,GAAG,IAAI,wBAAc,CAAC;IAC1D,cAAc,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;IAC9C,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;YAuBA;CACX,CAAC,CAAA;AAEW,QAAA,iCAAiC,GAAG,IAAI,wBAAc,CAAC;IAClE,cAAc,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,CAAC;IAClG,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;eA4BG;CACd,CAAC,CAAA","sourcesContent":["import { PromptTemplate } from \"@langchain/core/prompts\";\n\nexport const filterFilesPromptTemplate = new PromptTemplate({\n inputVariables: ['documentation', 'file_list'],\n template: `You are a PostHog installation wizard, a master AI programming assistant that implements PostHog for Next.js projects.\nGiven the following list of Next.js file paths from a project, determine which files are likely to require modifications \nto integrate PostHog. Use the installation documentation as a reference for what files might need modifications, do not include files that are unlikely to require modification based on the documentation.\n\n- If you would like to create a new file, you can include the file path in your response.\n- If you would like to modify an existing file, you can include the file path in your response.\n\nYou should return all files that you think will be required to look at or modify to integrate PostHog. You should return them in the order you would like to see them processed, with new files first, followed by the files that you want to update to integrate PostHog.\n\nRules:\n- Only return files that you think will be required to look at or modify to integrate PostHog.\n- Do not return files that are unlikely to require modification based on the documentation.\n- If you are unsure, return the file, since it's better to have more files than less.\n- If you create a new file, it should not conflict with any existing files.\n- If the user is using TypeScript, you should return .ts and .tsx files.\n- You should implement both posthog-js and posthog-node.\n- The file structure of the project may be different than the documentation, you should follow the file structure of the project.\n\nInstallation documentation:\n{documentation}\n\nAll current files in the repository:\n\n{file_list}`\n})\n\nexport const generateFileChangesPromptTemplate = new PromptTemplate({\n inputVariables: ['file_content', 'documentation', 'file_path', 'changed_files', 'unchanged_files'],\n template: `You are a PostHog installation wizard, a master AI programming assistant that implements PostHog for Next.js projects.\n\nYour task is to update the file to integrate PostHog according to the documentation.\nDo not return a diff — you should return the complete updated file content.\n\nRules:\n- Preserve the existing code formatting and style.\n- Only make the changes required by the documentation.\n- If no changes are needed, return the file as-is.\n- If the current file is empty, and you think it should be created, you can add the contents of the new file.\n- The file structure of the project may be different than the documentation, you should follow the file structure of the project.\n\nCONTEXT\n---\n\nDocumentation for integrating PostHog with Next.js:\n{documentation}\n\nThe file you are updating is:\n{file_path}\n\nHere are the changes you have already made to the project:\n{changed_files}\n\nHere are the files that have not been changed yet:\n{unchanged_files}\n\nBelow is the current file contents:\n{file_content}`\n})\n"]}
@@ -0,0 +1,9 @@
1
+ export declare function getNextJsVersionBucket(version: string | undefined): string;
2
+ export declare enum NextJsRouter {
3
+ APP_ROUTER = "app-router",
4
+ PAGES_ROUTER = "pages-router"
5
+ }
6
+ export declare const IGNORE_PATTERNS: string[];
7
+ export declare function getNextJsRouter(): Promise<NextJsRouter>;
8
+ export declare const getNextJsRouterName: (router: NextJsRouter) => "app router" | "pages router";
9
+ export declare const getAssetHostFromHost: (host: string) => string;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getAssetHostFromHost = exports.getNextJsRouterName = exports.IGNORE_PATTERNS = exports.NextJsRouter = void 0;
7
+ exports.getNextJsVersionBucket = getNextJsVersionBucket;
8
+ exports.getNextJsRouter = getNextJsRouter;
9
+ const semver_1 = require("semver");
10
+ const fast_glob_1 = __importDefault(require("fast-glob"));
11
+ const clack_utils_1 = require("../utils/clack-utils");
12
+ const clack_1 = __importDefault(require("../utils/clack"));
13
+ const constants_1 = require("../lib/constants");
14
+ function getNextJsVersionBucket(version) {
15
+ if (!version) {
16
+ return 'none';
17
+ }
18
+ try {
19
+ const minVer = (0, semver_1.minVersion)(version);
20
+ if (!minVer) {
21
+ return 'invalid';
22
+ }
23
+ const majorVersion = (0, semver_1.major)(minVer);
24
+ if (majorVersion >= 11) {
25
+ return `${majorVersion}.x`;
26
+ }
27
+ return '<11.0.0';
28
+ }
29
+ catch {
30
+ return 'unknown';
31
+ }
32
+ }
33
+ var NextJsRouter;
34
+ (function (NextJsRouter) {
35
+ NextJsRouter["APP_ROUTER"] = "app-router";
36
+ NextJsRouter["PAGES_ROUTER"] = "pages-router";
37
+ })(NextJsRouter || (exports.NextJsRouter = NextJsRouter = {}));
38
+ exports.IGNORE_PATTERNS = [
39
+ '**/node_modules/**',
40
+ '**/dist/**',
41
+ '**/build/**',
42
+ '**/public/**',
43
+ ];
44
+ async function getNextJsRouter() {
45
+ const pagesMatches = await (0, fast_glob_1.default)('**/pages/_app.@(ts|tsx|js|jsx)', { dot: true, cwd: constants_1.INSTALL_DIR, ignore: exports.IGNORE_PATTERNS });
46
+ const hasPagesDir = pagesMatches.length > 0;
47
+ const appMatches = await (0, fast_glob_1.default)('**/app/layout.@(ts|tsx|js|jsx)', { dot: true, cwd: constants_1.INSTALL_DIR, ignore: exports.IGNORE_PATTERNS });
48
+ const hasAppDir = appMatches.length > 0;
49
+ if (hasPagesDir && !hasAppDir) {
50
+ clack_1.default.log.info(`Detected ${(0, exports.getNextJsRouterName)(NextJsRouter.PAGES_ROUTER)} 📃`);
51
+ return NextJsRouter.PAGES_ROUTER;
52
+ }
53
+ if (hasAppDir && !hasPagesDir) {
54
+ clack_1.default.log.info(`Detected ${(0, exports.getNextJsRouterName)(NextJsRouter.APP_ROUTER)} 📱`);
55
+ return NextJsRouter.APP_ROUTER;
56
+ }
57
+ const result = await (0, clack_utils_1.abortIfCancelled)(clack_1.default.select({
58
+ message: 'What router are you using?',
59
+ options: [
60
+ { label: (0, exports.getNextJsRouterName)(NextJsRouter.APP_ROUTER), value: NextJsRouter.APP_ROUTER },
61
+ { label: (0, exports.getNextJsRouterName)(NextJsRouter.PAGES_ROUTER), value: NextJsRouter.PAGES_ROUTER },
62
+ ],
63
+ }));
64
+ return result;
65
+ }
66
+ const getNextJsRouterName = (router) => {
67
+ return router === NextJsRouter.APP_ROUTER ? 'app router' : 'pages router';
68
+ };
69
+ exports.getNextJsRouterName = getNextJsRouterName;
70
+ const getAssetHostFromHost = (host) => {
71
+ if (host.includes('us.i.posthog.com')) {
72
+ return 'https://us-assets.i.posthog.com';
73
+ }
74
+ if (host.includes('eu.i.posthog.com')) {
75
+ return 'https://eu-assets.i.posthog.com';
76
+ }
77
+ return host;
78
+ };
79
+ exports.getAssetHostFromHost = getAssetHostFromHost;
80
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/nextjs/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { major, minVersion } from 'semver';\nimport fg from 'fast-glob';\nimport { abortIfCancelled } from '../utils/clack-utils';\nimport clack from '../utils/clack';\nimport { INSTALL_DIR } from '../lib/constants';\n\nexport function getNextJsVersionBucket(version: string | undefined) {\n if (!version) {\n return 'none';\n }\n\n try {\n const minVer = minVersion(version);\n if (!minVer) {\n return 'invalid';\n }\n const majorVersion = major(minVer);\n if (majorVersion >= 11) {\n return `${majorVersion}.x`;\n }\n return '<11.0.0';\n } catch {\n return 'unknown';\n }\n}\n\nexport enum NextJsRouter {\n APP_ROUTER = 'app-router',\n PAGES_ROUTER = 'pages-router',\n}\n\nexport const IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/public/**',\n]\nexport async function getNextJsRouter(): Promise<NextJsRouter> {\n const pagesMatches = await fg('**/pages/_app.@(ts|tsx|js|jsx)', { dot: true, cwd: INSTALL_DIR, ignore: IGNORE_PATTERNS });\n\n const hasPagesDir = pagesMatches.length > 0;\n\n const appMatches = await fg('**/app/layout.@(ts|tsx|js|jsx)', { dot: true, cwd: INSTALL_DIR, ignore: IGNORE_PATTERNS });\n\n const hasAppDir = appMatches.length > 0;\n\n if (hasPagesDir && !hasAppDir) {\n clack.log.info(`Detected ${getNextJsRouterName(NextJsRouter.PAGES_ROUTER)} 📃`);\n return NextJsRouter.PAGES_ROUTER;\n }\n\n if (hasAppDir && !hasPagesDir) {\n clack.log.info(`Detected ${getNextJsRouterName(NextJsRouter.APP_ROUTER)} 📱`);\n return NextJsRouter.APP_ROUTER;\n }\n\n const result: NextJsRouter = await abortIfCancelled(\n clack.select({\n message: 'What router are you using?',\n options: [\n { label: getNextJsRouterName(NextJsRouter.APP_ROUTER), value: NextJsRouter.APP_ROUTER },\n { label: getNextJsRouterName(NextJsRouter.PAGES_ROUTER), value: NextJsRouter.PAGES_ROUTER },\n ],\n })\n );\n\n return result;\n}\n\nexport const getNextJsRouterName = (router: NextJsRouter) => {\n return router === NextJsRouter.APP_ROUTER ? 'app router' : 'pages router';\n}\n\nexport const getAssetHostFromHost = (host: string) => {\n if (host.includes('us.i.posthog.com')) {\n return 'https://us-assets.i.posthog.com';\n }\n\n if (host.includes('eu.i.posthog.com')) {\n return 'https://eu-assets.i.posthog.com';\n }\n\n return host;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { Integration } from './lib/constants';
2
+ type Args = {
3
+ integration?: Integration;
4
+ debug?: boolean;
5
+ forceInstall?: boolean;
6
+ };
7
+ export declare function run(argv: Args): Promise<void>;
8
+ export {};
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.run = run;
7
+ const clack_utils_1 = require("./utils/clack-utils");
8
+ const nextjs_wizard_1 = require("./nextjs/nextjs-wizard");
9
+ const constants_1 = require("./lib/constants");
10
+ const node_fs_1 = require("node:fs");
11
+ const environment_1 = require("./utils/environment");
12
+ const clack_1 = __importDefault(require("./utils/clack"));
13
+ async function run(argv) {
14
+ const finalArgs = {
15
+ ...argv,
16
+ ...(0, environment_1.readEnvironment)(),
17
+ };
18
+ clack_1.default.intro(`PostHog Wizard ${tryGetWizardVersion()}`);
19
+ const integration = finalArgs.integration ?? await getIntegrationForSetup();
20
+ const wizardOptions = {
21
+ debug: finalArgs.debug ?? false,
22
+ forceInstall: finalArgs.forceInstall ?? false,
23
+ telemetryEnabled: false,
24
+ };
25
+ switch (integration) {
26
+ case constants_1.Integration.nextjs:
27
+ await (0, nextjs_wizard_1.runNextjsWizard)(wizardOptions);
28
+ break;
29
+ default:
30
+ clack_1.default.log.error('No setup wizard selected!');
31
+ }
32
+ }
33
+ function tryGetWizardVersion() {
34
+ let version = process.env.npm_package_version;
35
+ if (!version) {
36
+ try {
37
+ const wizardPkgJson = JSON.parse((0, node_fs_1.readFileSync)('../package.json', 'utf-8'));
38
+ version = wizardPkgJson.version;
39
+ }
40
+ catch {
41
+ // ignore
42
+ }
43
+ }
44
+ return version ?? '';
45
+ }
46
+ async function detectIntegration() {
47
+ const detectors = [
48
+ nextjs_wizard_1.detectNextJs
49
+ ];
50
+ for (const detector of detectors) {
51
+ const integration = await detector();
52
+ if (integration) {
53
+ return integration;
54
+ }
55
+ }
56
+ }
57
+ async function getIntegrationForSetup() {
58
+ const detectedIntegration = await detectIntegration();
59
+ if (detectedIntegration) {
60
+ clack_1.default.log.success(`Detected integration: ${(0, constants_1.getIntegrationDescription)(detectedIntegration)}`);
61
+ return detectedIntegration;
62
+ }
63
+ const integration = await (0, clack_utils_1.abortIfCancelled)(clack_1.default.select({
64
+ message: 'What do you want to set up?',
65
+ options: [{ value: constants_1.Integration.nextjs, label: 'Next.js' }],
66
+ }));
67
+ return integration;
68
+ }
69
+ //# sourceMappingURL=run.js.map