humanbehavior-js 0.4.16 → 0.4.18

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 (89) hide show
  1. package/dist/cjs/wizard/index.cjs +6 -8
  2. package/dist/cjs/wizard/index.cjs.map +1 -1
  3. package/dist/cli/ai-auto-install.js +6 -8
  4. package/dist/cli/ai-auto-install.js.map +1 -1
  5. package/dist/esm/wizard/index.js +6 -8
  6. package/dist/esm/wizard/index.js.map +1 -1
  7. package/package/WIZARD_USAGE_GUIDE.md +381 -0
  8. package/package/canvas-recording-demo.html +143 -0
  9. package/package/clean-console-demo.html +39 -0
  10. package/package/dist/cjs/angular/index.cjs +14354 -0
  11. package/package/dist/cjs/angular/index.cjs.map +1 -0
  12. package/package/dist/cjs/index.cjs +14323 -0
  13. package/package/dist/cjs/index.cjs.map +1 -0
  14. package/package/dist/cjs/install-wizard.cjs +1530 -0
  15. package/package/dist/cjs/install-wizard.cjs.map +1 -0
  16. package/package/dist/cjs/react/index.cjs +14478 -0
  17. package/package/dist/cjs/react/index.cjs.map +1 -0
  18. package/package/dist/cjs/remix/index.cjs +14452 -0
  19. package/package/dist/cjs/remix/index.cjs.map +1 -0
  20. package/package/dist/cjs/svelte/index.cjs +14308 -0
  21. package/package/dist/cjs/svelte/index.cjs.map +1 -0
  22. package/package/dist/cjs/vue/index.cjs +14317 -0
  23. package/package/dist/cjs/vue/index.cjs.map +1 -0
  24. package/package/dist/cjs/wizard/index.cjs +3446 -0
  25. package/package/dist/cjs/wizard/index.cjs.map +1 -0
  26. package/package/dist/cli/ai-auto-install.cjs +57161 -0
  27. package/package/dist/cli/ai-auto-install.cjs.map +1 -0
  28. package/package/dist/cli/ai-auto-install.js +1969 -0
  29. package/package/dist/cli/ai-auto-install.js.map +1 -0
  30. package/package/dist/cli/auto-install.cjs +56352 -0
  31. package/package/dist/cli/auto-install.cjs.map +1 -0
  32. package/package/dist/cli/auto-install.js +1957 -0
  33. package/package/dist/cli/auto-install.js.map +1 -0
  34. package/package/dist/esm/angular/index.js +14350 -0
  35. package/package/dist/esm/angular/index.js.map +1 -0
  36. package/package/dist/esm/index.js +14309 -0
  37. package/package/dist/esm/index.js.map +1 -0
  38. package/package/dist/esm/install-wizard.js +1507 -0
  39. package/package/dist/esm/install-wizard.js.map +1 -0
  40. package/package/dist/esm/react/index.js +14472 -0
  41. package/package/dist/esm/react/index.js.map +1 -0
  42. package/package/dist/esm/remix/index.js +14448 -0
  43. package/package/dist/esm/remix/index.js.map +1 -0
  44. package/package/dist/esm/svelte/index.js +14306 -0
  45. package/package/dist/esm/svelte/index.js.map +1 -0
  46. package/package/dist/esm/vue/index.js +14315 -0
  47. package/package/dist/esm/vue/index.js.map +1 -0
  48. package/package/dist/esm/wizard/index.js +3415 -0
  49. package/package/dist/esm/wizard/index.js.map +1 -0
  50. package/package/dist/index.min.js +2 -0
  51. package/package/dist/index.min.js.map +1 -0
  52. package/package/dist/types/angular/index.d.ts +267 -0
  53. package/package/dist/types/index.d.ts +373 -0
  54. package/package/dist/types/install-wizard.d.ts +156 -0
  55. package/package/dist/types/react/index.d.ts +255 -0
  56. package/package/dist/types/remix/index.d.ts +246 -0
  57. package/package/dist/types/svelte/index.d.ts +232 -0
  58. package/package/dist/types/vue/index.d.ts +15 -0
  59. package/package/dist/types/wizard/index.d.ts +523 -0
  60. package/package/package.json +105 -0
  61. package/package/readme.md +281 -0
  62. package/package/rollup.config.js +422 -0
  63. package/package/simple-demo.html +26 -0
  64. package/package/simple-spa.html +838 -0
  65. package/package/src/angular/index.ts +79 -0
  66. package/package/src/api.ts +376 -0
  67. package/package/src/index.ts +28 -0
  68. package/package/src/react/AutoInstallWizard.tsx +557 -0
  69. package/package/src/react/browser.ts +8 -0
  70. package/package/src/react/index.tsx +308 -0
  71. package/package/src/redact.ts +521 -0
  72. package/package/src/remix/index.ts +16 -0
  73. package/package/src/svelte/index.ts +14 -0
  74. package/package/src/tracker.ts +1319 -0
  75. package/package/src/types/clack.d.ts +31 -0
  76. package/package/src/utils/logger.ts +144 -0
  77. package/package/src/vue/index.ts +29 -0
  78. package/package/src/wizard/README.md +114 -0
  79. package/package/src/wizard/ai/ai-install-wizard.ts +897 -0
  80. package/package/src/wizard/ai/manual-framework-wizard.ts +238 -0
  81. package/package/src/wizard/cli/ai-auto-install.ts +243 -0
  82. package/package/src/wizard/cli/auto-install.ts +224 -0
  83. package/package/src/wizard/core/install-wizard.ts +1744 -0
  84. package/package/src/wizard/index.ts +23 -0
  85. package/package/src/wizard/services/centralized-ai-service.ts +668 -0
  86. package/package/src/wizard/services/remote-ai-service.ts +240 -0
  87. package/package/tsconfig.json +24 -0
  88. package/package.json +1 -1
  89. package/src/wizard/cli/ai-auto-install.ts +4 -6
@@ -0,0 +1,1957 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import * as clack from '@clack/prompts';
5
+
6
+ /******************************************************************************
7
+ Copyright (c) Microsoft Corporation.
8
+
9
+ Permission to use, copy, modify, and/or distribute this software for any
10
+ purpose with or without fee is hereby granted.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
13
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
15
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18
+ PERFORMANCE OF THIS SOFTWARE.
19
+ ***************************************************************************** */
20
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
21
+
22
+
23
+ function __awaiter(thisArg, _arguments, P, generator) {
24
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
25
+ return new (P || (P = Promise))(function (resolve, reject) {
26
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
27
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
28
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
29
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
30
+ });
31
+ }
32
+
33
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
34
+ var e = new Error(message);
35
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
36
+ };
37
+
38
+ /**
39
+ * HumanBehavior SDK Auto-Installation Wizard
40
+ *
41
+ * This wizard automatically detects the user's framework and modifies their codebase
42
+ * to integrate the SDK with minimal user intervention.
43
+ */
44
+ class AutoInstallationWizard {
45
+ constructor(apiKey, projectRoot = process.cwd()) {
46
+ this.framework = null;
47
+ this.apiKey = apiKey;
48
+ this.projectRoot = projectRoot;
49
+ }
50
+ /**
51
+ * Simple version comparison utility
52
+ */
53
+ compareVersions(version1, version2) {
54
+ const v1Parts = version1.split('.').map(Number);
55
+ const v2Parts = version2.split('.').map(Number);
56
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
57
+ const v1 = v1Parts[i] || 0;
58
+ const v2 = v2Parts[i] || 0;
59
+ if (v1 > v2)
60
+ return 1;
61
+ if (v1 < v2)
62
+ return -1;
63
+ }
64
+ return 0;
65
+ }
66
+ isVersionGte(version, target) {
67
+ return this.compareVersions(version, target) >= 0;
68
+ }
69
+ getMajorVersion(version) {
70
+ return parseInt(version.split('.')[0]) || 0;
71
+ }
72
+ /**
73
+ * Main installation method - detects framework and auto-installs
74
+ */
75
+ install() {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ try {
78
+ // Step 1: Detect framework
79
+ this.framework = yield this.detectFramework();
80
+ // Step 2: Install package
81
+ yield this.installPackage();
82
+ // Step 3: Generate and apply code modifications
83
+ const modifications = yield this.generateModifications();
84
+ yield this.applyModifications(modifications);
85
+ // Step 4: Generate next steps
86
+ const nextSteps = this.generateNextSteps();
87
+ return {
88
+ success: true,
89
+ framework: this.framework,
90
+ modifications,
91
+ errors: [],
92
+ nextSteps
93
+ };
94
+ }
95
+ catch (error) {
96
+ return {
97
+ success: false,
98
+ framework: this.framework || { name: 'unknown', type: 'vanilla' },
99
+ modifications: [],
100
+ errors: [error instanceof Error ? error.message : 'Unknown error'],
101
+ nextSteps: []
102
+ };
103
+ }
104
+ });
105
+ }
106
+ /**
107
+ * Detect the current framework and project setup
108
+ */
109
+ detectFramework() {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ const packageJsonPath = path.join(this.projectRoot, 'package.json');
112
+ if (!fs.existsSync(packageJsonPath)) {
113
+ return {
114
+ name: 'vanilla',
115
+ type: 'vanilla',
116
+ projectRoot: this.projectRoot
117
+ };
118
+ }
119
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
120
+ const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
121
+ // Detect framework with version information
122
+ let framework = {
123
+ name: 'vanilla',
124
+ type: 'vanilla',
125
+ projectRoot: this.projectRoot,
126
+ features: {}
127
+ };
128
+ if (dependencies.nuxt) {
129
+ const nuxtVersion = dependencies.nuxt;
130
+ const isNuxt3 = this.isVersionGte(nuxtVersion, '3.0.0');
131
+ framework = {
132
+ name: 'nuxt',
133
+ type: 'nuxt',
134
+ version: nuxtVersion,
135
+ majorVersion: this.getMajorVersion(nuxtVersion),
136
+ hasTypeScript: !!dependencies.typescript,
137
+ hasRouter: true,
138
+ projectRoot: this.projectRoot,
139
+ features: {
140
+ hasNuxt3: isNuxt3
141
+ }
142
+ };
143
+ }
144
+ else if (dependencies.next) {
145
+ const nextVersion = dependencies.next;
146
+ const isNext13 = this.isVersionGte(nextVersion, '13.0.0');
147
+ framework = {
148
+ name: 'nextjs',
149
+ type: 'nextjs',
150
+ version: nextVersion,
151
+ majorVersion: this.getMajorVersion(nextVersion),
152
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
153
+ hasRouter: true,
154
+ projectRoot: this.projectRoot,
155
+ features: {
156
+ hasNextAppRouter: isNext13
157
+ }
158
+ };
159
+ }
160
+ else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
161
+ const remixVersion = dependencies['@remix-run/react'] || dependencies['@remix-run/dev'];
162
+ framework = {
163
+ name: 'remix',
164
+ type: 'remix',
165
+ version: remixVersion,
166
+ majorVersion: this.getMajorVersion(remixVersion),
167
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
168
+ hasRouter: true,
169
+ projectRoot: this.projectRoot,
170
+ features: {}
171
+ };
172
+ }
173
+ else if (dependencies.react) {
174
+ const reactVersion = dependencies.react;
175
+ const isReact18 = this.isVersionGte(reactVersion, '18.0.0');
176
+ framework = {
177
+ name: 'react',
178
+ type: 'react',
179
+ version: reactVersion,
180
+ majorVersion: this.getMajorVersion(reactVersion),
181
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
182
+ hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
183
+ projectRoot: this.projectRoot,
184
+ features: {
185
+ hasReact18: isReact18
186
+ }
187
+ };
188
+ }
189
+ else if (dependencies.vue) {
190
+ const vueVersion = dependencies.vue;
191
+ const isVue3 = this.isVersionGte(vueVersion, '3.0.0');
192
+ framework = {
193
+ name: 'vue',
194
+ type: 'vue',
195
+ version: vueVersion,
196
+ majorVersion: this.getMajorVersion(vueVersion),
197
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
198
+ hasRouter: !!dependencies['vue-router'],
199
+ projectRoot: this.projectRoot,
200
+ features: {
201
+ hasVue3: isVue3
202
+ }
203
+ };
204
+ }
205
+ else if (dependencies['@angular/core']) {
206
+ const angularVersion = dependencies['@angular/core'];
207
+ const isAngular17 = this.isVersionGte(angularVersion, '17.0.0');
208
+ framework = {
209
+ name: 'angular',
210
+ type: 'angular',
211
+ version: angularVersion,
212
+ majorVersion: this.getMajorVersion(angularVersion),
213
+ hasTypeScript: true,
214
+ hasRouter: true,
215
+ projectRoot: this.projectRoot,
216
+ features: {
217
+ hasAngularStandalone: isAngular17
218
+ }
219
+ };
220
+ }
221
+ else if (dependencies.svelte) {
222
+ const svelteVersion = dependencies.svelte;
223
+ const isSvelteKit = !!dependencies['@sveltejs/kit'];
224
+ framework = {
225
+ name: 'svelte',
226
+ type: 'svelte',
227
+ version: svelteVersion,
228
+ majorVersion: this.getMajorVersion(svelteVersion),
229
+ hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
230
+ hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
231
+ projectRoot: this.projectRoot,
232
+ features: {
233
+ hasSvelteKit: isSvelteKit
234
+ }
235
+ };
236
+ }
237
+ else if (dependencies.astro) {
238
+ const astroVersion = dependencies.astro;
239
+ framework = {
240
+ name: 'astro',
241
+ type: 'astro',
242
+ version: astroVersion,
243
+ majorVersion: this.getMajorVersion(astroVersion),
244
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
245
+ hasRouter: true,
246
+ projectRoot: this.projectRoot,
247
+ features: {}
248
+ };
249
+ }
250
+ else if (dependencies.gatsby) {
251
+ const gatsbyVersion = dependencies.gatsby;
252
+ framework = {
253
+ name: 'gatsby',
254
+ type: 'gatsby',
255
+ version: gatsbyVersion,
256
+ majorVersion: this.getMajorVersion(gatsbyVersion),
257
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
258
+ hasRouter: true,
259
+ projectRoot: this.projectRoot,
260
+ features: {}
261
+ };
262
+ }
263
+ // Detect bundler
264
+ if (dependencies.vite) {
265
+ framework.bundler = 'vite';
266
+ }
267
+ else if (dependencies.webpack) {
268
+ framework.bundler = 'webpack';
269
+ }
270
+ else if (dependencies.esbuild) {
271
+ framework.bundler = 'esbuild';
272
+ }
273
+ else if (dependencies.rollup) {
274
+ framework.bundler = 'rollup';
275
+ }
276
+ // Detect package manager
277
+ if (fs.existsSync(path.join(this.projectRoot, 'yarn.lock'))) {
278
+ framework.packageManager = 'yarn';
279
+ }
280
+ else if (fs.existsSync(path.join(this.projectRoot, 'pnpm-lock.yaml'))) {
281
+ framework.packageManager = 'pnpm';
282
+ }
283
+ else {
284
+ framework.packageManager = 'npm';
285
+ }
286
+ return framework;
287
+ });
288
+ }
289
+ /**
290
+ * Install the SDK package
291
+ */
292
+ installPackage() {
293
+ return __awaiter(this, void 0, void 0, function* () {
294
+ var _a, _b, _c, _d;
295
+ const { execSync } = yield import('child_process');
296
+ // Build base command
297
+ let command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
298
+ ? 'yarn add humanbehavior-js'
299
+ : ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
300
+ ? 'pnpm add humanbehavior-js'
301
+ : 'npm install humanbehavior-js';
302
+ // Add legacy peer deps flag for npm to handle dependency conflicts
303
+ if (((_c = this.framework) === null || _c === void 0 ? void 0 : _c.packageManager) !== 'yarn' && ((_d = this.framework) === null || _d === void 0 ? void 0 : _d.packageManager) !== 'pnpm') {
304
+ command += ' --legacy-peer-deps';
305
+ }
306
+ try {
307
+ execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
308
+ }
309
+ catch (error) {
310
+ throw new Error(`Failed to install humanbehavior-js: ${error}`);
311
+ }
312
+ });
313
+ }
314
+ /**
315
+ * Generate code modifications based on framework
316
+ */
317
+ generateModifications() {
318
+ return __awaiter(this, void 0, void 0, function* () {
319
+ var _a;
320
+ const modifications = [];
321
+ switch ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type) {
322
+ case 'react':
323
+ modifications.push(...yield this.generateReactModifications());
324
+ break;
325
+ case 'nextjs':
326
+ modifications.push(...yield this.generateNextJSModifications());
327
+ break;
328
+ case 'nuxt':
329
+ modifications.push(...yield this.generateNuxtModifications());
330
+ break;
331
+ case 'astro':
332
+ modifications.push(...yield this.generateAstroModifications());
333
+ break;
334
+ case 'gatsby':
335
+ modifications.push(...yield this.generateGatsbyModifications());
336
+ break;
337
+ case 'remix':
338
+ modifications.push(...yield this.generateRemixModifications());
339
+ break;
340
+ case 'vue':
341
+ modifications.push(...yield this.generateVueModifications());
342
+ break;
343
+ case 'angular':
344
+ modifications.push(...yield this.generateAngularModifications());
345
+ break;
346
+ case 'svelte':
347
+ modifications.push(...yield this.generateSvelteModifications());
348
+ break;
349
+ default:
350
+ modifications.push(...yield this.generateVanillaModifications());
351
+ }
352
+ return modifications;
353
+ });
354
+ }
355
+ /**
356
+ * Generate React-specific modifications
357
+ */
358
+ generateReactModifications() {
359
+ return __awaiter(this, void 0, void 0, function* () {
360
+ const modifications = [];
361
+ // Find main App component or index file
362
+ const appFile = this.findReactAppFile();
363
+ if (appFile) {
364
+ const content = fs.readFileSync(appFile, 'utf8');
365
+ const modifiedContent = this.injectReactProvider(content, appFile);
366
+ modifications.push({
367
+ filePath: appFile,
368
+ action: 'modify',
369
+ content: modifiedContent,
370
+ description: 'Added HumanBehaviorProvider to React app'
371
+ });
372
+ }
373
+ // Create or append to environment file
374
+ modifications.push(this.createEnvironmentModification(this.framework));
375
+ return modifications;
376
+ });
377
+ }
378
+ /**
379
+ * Generate Next.js-specific modifications
380
+ */
381
+ generateNextJSModifications() {
382
+ return __awaiter(this, void 0, void 0, function* () {
383
+ const modifications = [];
384
+ // Check for App Router
385
+ const appLayoutFile = path.join(this.projectRoot, 'src', 'app', 'layout.tsx');
386
+ const pagesLayoutFile = path.join(this.projectRoot, 'src', 'pages', '_app.tsx');
387
+ if (fs.existsSync(appLayoutFile)) {
388
+ // Create providers.tsx file for App Router
389
+ modifications.push({
390
+ filePath: path.join(this.projectRoot, 'src', 'app', 'providers.tsx'),
391
+ action: 'create',
392
+ content: `'use client';
393
+
394
+ import { HumanBehaviorProvider } from 'humanbehavior-js/react';
395
+
396
+ export function Providers({ children }: { children: React.ReactNode }) {
397
+ return (
398
+ <HumanBehaviorProvider apiKey={process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY}>
399
+ {children}
400
+ </HumanBehaviorProvider>
401
+ );
402
+ }`,
403
+ description: 'Created providers.tsx file for Next.js App Router'
404
+ });
405
+ // Modify layout.tsx to use the provider
406
+ const content = fs.readFileSync(appLayoutFile, 'utf8');
407
+ const modifiedContent = this.injectNextJSAppRouter(content);
408
+ modifications.push({
409
+ filePath: appLayoutFile,
410
+ action: 'modify',
411
+ content: modifiedContent,
412
+ description: 'Added Providers wrapper to Next.js App Router layout'
413
+ });
414
+ }
415
+ else if (fs.existsSync(pagesLayoutFile)) {
416
+ // Create providers.tsx file for Pages Router
417
+ modifications.push({
418
+ filePath: path.join(this.projectRoot, 'src', 'components', 'providers.tsx'),
419
+ action: 'create',
420
+ content: `'use client';
421
+
422
+ import { HumanBehaviorProvider } from 'humanbehavior-js/react';
423
+
424
+ export function Providers({ children }: { children: React.ReactNode }) {
425
+ return (
426
+ <HumanBehaviorProvider apiKey={process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY}>
427
+ {children}
428
+ </HumanBehaviorProvider>
429
+ );
430
+ }`,
431
+ description: 'Created providers.tsx file for Pages Router'
432
+ });
433
+ // Modify _app.tsx to use the provider
434
+ const content = fs.readFileSync(pagesLayoutFile, 'utf8');
435
+ const modifiedContent = this.injectNextJSPagesRouter(content);
436
+ modifications.push({
437
+ filePath: pagesLayoutFile,
438
+ action: 'modify',
439
+ content: modifiedContent,
440
+ description: 'Added Providers wrapper to Next.js Pages Router'
441
+ });
442
+ }
443
+ // Create or append to environment file
444
+ modifications.push(this.createEnvironmentModification(this.framework));
445
+ return modifications;
446
+ });
447
+ }
448
+ /**
449
+ * Generate Astro-specific modifications
450
+ */
451
+ generateAstroModifications() {
452
+ return __awaiter(this, void 0, void 0, function* () {
453
+ const modifications = [];
454
+ // Create Astro component for HumanBehavior
455
+ const astroComponentPath = path.join(this.projectRoot, 'src', 'components', 'HumanBehavior.astro');
456
+ const astroComponentContent = `---
457
+ // This component will only run on the client side
458
+ ---
459
+
460
+ <script>
461
+ import { HumanBehaviorTracker } from 'humanbehavior-js';
462
+
463
+ // Get API key from environment variable
464
+ const apiKey = import.meta.env.PUBLIC_HUMANBEHAVIOR_API_KEY;
465
+
466
+ console.log('HumanBehavior: API key found:', apiKey ? 'Yes' : 'No');
467
+
468
+ if (apiKey) {
469
+ try {
470
+ const tracker = HumanBehaviorTracker.init(apiKey);
471
+ console.log('HumanBehavior: Tracker initialized successfully');
472
+
473
+ // Test event to verify tracking is working
474
+ setTimeout(() => {
475
+ tracker.customEvent('astro_page_view', {
476
+ page: window.location.pathname,
477
+ framework: 'astro'
478
+ }).then(() => {
479
+ console.log('HumanBehavior: Test event sent successfully');
480
+ }).catch((error) => {
481
+ console.error('HumanBehavior: Failed to send test event:', error);
482
+ });
483
+ }, 1000);
484
+
485
+ } catch (error) {
486
+ console.error('HumanBehavior: Failed to initialize tracker:', error);
487
+ }
488
+ } else {
489
+ console.error('HumanBehavior: No API key found');
490
+ }
491
+ </script>`;
492
+ modifications.push({
493
+ filePath: astroComponentPath,
494
+ action: 'create',
495
+ content: astroComponentContent,
496
+ description: 'Created Astro component for HumanBehavior SDK'
497
+ });
498
+ // Find and update layout file
499
+ const layoutFiles = [
500
+ path.join(this.projectRoot, 'src', 'layouts', 'Layout.astro'),
501
+ path.join(this.projectRoot, 'src', 'layouts', 'layout.astro'),
502
+ path.join(this.projectRoot, 'src', 'layouts', 'BaseLayout.astro')
503
+ ];
504
+ let layoutFile = null;
505
+ for (const file of layoutFiles) {
506
+ if (fs.existsSync(file)) {
507
+ layoutFile = file;
508
+ break;
509
+ }
510
+ }
511
+ if (layoutFile) {
512
+ const content = fs.readFileSync(layoutFile, 'utf8');
513
+ const modifiedContent = this.injectAstroLayout(content);
514
+ modifications.push({
515
+ filePath: layoutFile,
516
+ action: 'modify',
517
+ content: modifiedContent,
518
+ description: 'Added HumanBehavior component to Astro layout'
519
+ });
520
+ }
521
+ // Add environment variable
522
+ modifications.push(this.createEnvironmentModification(this.framework));
523
+ return modifications;
524
+ });
525
+ }
526
+ /**
527
+ * Generate Nuxt-specific modifications
528
+ */
529
+ generateNuxtModifications() {
530
+ return __awaiter(this, void 0, void 0, function* () {
531
+ const modifications = [];
532
+ // Create plugin file for Nuxt (in app directory)
533
+ const pluginFile = path.join(this.projectRoot, 'app', 'plugins', 'humanbehavior.client.ts');
534
+ modifications.push({
535
+ filePath: pluginFile,
536
+ action: 'create',
537
+ content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
538
+
539
+ export default defineNuxtPlugin(() => {
540
+ const config = useRuntimeConfig();
541
+
542
+ // Initialize HumanBehavior SDK (client-side only)
543
+ if (typeof window !== 'undefined') {
544
+ const apiKey = config.public.humanBehaviorApiKey;
545
+ console.log('HumanBehavior: API key:', apiKey ? 'present' : 'missing');
546
+
547
+ if (apiKey) {
548
+ try {
549
+ const tracker = HumanBehaviorTracker.init(apiKey);
550
+ console.log('HumanBehavior: Tracker initialized successfully');
551
+ } catch (error) {
552
+ console.error('HumanBehavior: Failed to initialize tracker:', error);
553
+ }
554
+ } else {
555
+ console.error('HumanBehavior: No API key found in runtime config');
556
+ }
557
+ }
558
+ });`,
559
+ description: 'Created Nuxt plugin for HumanBehavior SDK in app directory'
560
+ });
561
+ // Create environment configuration
562
+ const nuxtConfigFile = path.join(this.projectRoot, 'nuxt.config.ts');
563
+ if (fs.existsSync(nuxtConfigFile)) {
564
+ const content = fs.readFileSync(nuxtConfigFile, 'utf8');
565
+ const modifiedContent = this.injectNuxtConfig(content);
566
+ modifications.push({
567
+ filePath: nuxtConfigFile,
568
+ action: 'modify',
569
+ content: modifiedContent,
570
+ description: 'Added HumanBehavior runtime config to Nuxt config'
571
+ });
572
+ }
573
+ // Create or append to environment file
574
+ modifications.push(this.createEnvironmentModification(this.framework));
575
+ return modifications;
576
+ });
577
+ }
578
+ /**
579
+ * Generate Remix-specific modifications
580
+ */
581
+ generateRemixModifications() {
582
+ return __awaiter(this, void 0, void 0, function* () {
583
+ const modifications = [];
584
+ // Find root.tsx file
585
+ const rootFile = path.join(this.projectRoot, 'app', 'root.tsx');
586
+ if (fs.existsSync(rootFile)) {
587
+ const content = fs.readFileSync(rootFile, 'utf8');
588
+ const modifiedContent = this.injectRemixProvider(content);
589
+ modifications.push({
590
+ filePath: rootFile,
591
+ action: 'modify',
592
+ content: modifiedContent,
593
+ description: 'Added HumanBehaviorProvider to Remix root component'
594
+ });
595
+ }
596
+ // Create or append to environment file
597
+ modifications.push(this.createEnvironmentModification(this.framework));
598
+ return modifications;
599
+ });
600
+ }
601
+ /**
602
+ * Generate Vue-specific modifications
603
+ */
604
+ generateVueModifications() {
605
+ return __awaiter(this, void 0, void 0, function* () {
606
+ const modifications = [];
607
+ // Find main.js or main.ts
608
+ const mainFile = this.findVueMainFile();
609
+ if (mainFile) {
610
+ const content = fs.readFileSync(mainFile, 'utf8');
611
+ const modifiedContent = this.injectVuePlugin(content);
612
+ modifications.push({
613
+ filePath: mainFile,
614
+ action: 'modify',
615
+ content: modifiedContent,
616
+ description: 'Added HumanBehaviorPlugin to Vue app'
617
+ });
618
+ }
619
+ // Create or append to environment file
620
+ modifications.push(this.createEnvironmentModification(this.framework));
621
+ return modifications;
622
+ });
623
+ }
624
+ /**
625
+ * Generate Angular-specific modifications
626
+ */
627
+ generateAngularModifications() {
628
+ return __awaiter(this, void 0, void 0, function* () {
629
+ const modifications = [];
630
+ // Check for modern Angular (standalone components) vs legacy (NgModule)
631
+ const appModuleFile = path.join(this.projectRoot, 'src', 'app', 'app.module.ts');
632
+ const appComponentFile = path.join(this.projectRoot, 'src', 'app', 'app.ts');
633
+ const mainFile = path.join(this.projectRoot, 'src', 'main.ts');
634
+ const isModernAngular = fs.existsSync(appComponentFile) && !fs.existsSync(appModuleFile);
635
+ if (isModernAngular) {
636
+ // Modern Angular 17+ with standalone components
637
+ if (fs.existsSync(mainFile)) {
638
+ const content = fs.readFileSync(mainFile, 'utf8');
639
+ const modifiedContent = this.injectAngularStandaloneInit(content);
640
+ modifications.push({
641
+ filePath: mainFile,
642
+ action: 'modify',
643
+ content: modifiedContent,
644
+ description: 'Added HumanBehavior initialization to Angular main.ts'
645
+ });
646
+ }
647
+ }
648
+ else if (fs.existsSync(appModuleFile)) {
649
+ // Legacy Angular with NgModule
650
+ const content = fs.readFileSync(appModuleFile, 'utf8');
651
+ const modifiedContent = this.injectAngularModule(content);
652
+ modifications.push({
653
+ filePath: appModuleFile,
654
+ action: 'modify',
655
+ content: modifiedContent,
656
+ description: 'Added HumanBehaviorModule to Angular app'
657
+ });
658
+ }
659
+ // Handle Angular environment file (legacy structure)
660
+ const envFile = path.join(this.projectRoot, 'src', 'environments', 'environment.ts');
661
+ if (fs.existsSync(envFile)) {
662
+ const content = fs.readFileSync(envFile, 'utf8');
663
+ if (!content.includes('humanBehaviorApiKey')) {
664
+ const modifiedContent = content.replace(/export const environment = {([\s\S]*?)};/, `export const environment = {
665
+ $1,
666
+ humanBehaviorApiKey: process.env['HUMANBEHAVIOR_API_KEY'] || ''
667
+ };`);
668
+ modifications.push({
669
+ filePath: envFile,
670
+ action: 'modify',
671
+ content: modifiedContent,
672
+ description: 'Added API key to Angular environment'
673
+ });
674
+ }
675
+ }
676
+ // Create or append to environment file
677
+ modifications.push(this.createEnvironmentModification(this.framework));
678
+ return modifications;
679
+ });
680
+ }
681
+ /**
682
+ * Generate Svelte-specific modifications
683
+ */
684
+ generateSvelteModifications() {
685
+ return __awaiter(this, void 0, void 0, function* () {
686
+ const modifications = [];
687
+ // Check for SvelteKit
688
+ const svelteConfigFile = path.join(this.projectRoot, 'svelte.config.js');
689
+ const isSvelteKit = fs.existsSync(svelteConfigFile);
690
+ if (isSvelteKit) {
691
+ // SvelteKit - create layout file
692
+ const layoutFile = path.join(this.projectRoot, 'src', 'routes', '+layout.svelte');
693
+ if (fs.existsSync(layoutFile)) {
694
+ const content = fs.readFileSync(layoutFile, 'utf8');
695
+ const modifiedContent = this.injectSvelteKitLayout(content);
696
+ modifications.push({
697
+ filePath: layoutFile,
698
+ action: 'modify',
699
+ content: modifiedContent,
700
+ description: 'Added HumanBehavior store to SvelteKit layout'
701
+ });
702
+ }
703
+ }
704
+ else {
705
+ // Regular Svelte - modify main file
706
+ const mainFile = this.findSvelteMainFile();
707
+ if (mainFile) {
708
+ const content = fs.readFileSync(mainFile, 'utf8');
709
+ const modifiedContent = this.injectSvelteStore(content);
710
+ modifications.push({
711
+ filePath: mainFile,
712
+ action: 'modify',
713
+ content: modifiedContent,
714
+ description: 'Added HumanBehavior store to Svelte app'
715
+ });
716
+ }
717
+ }
718
+ // Create or append to environment file
719
+ modifications.push(this.createEnvironmentModification(this.framework));
720
+ return modifications;
721
+ });
722
+ }
723
+ /**
724
+ * Generate vanilla JS/TS modifications
725
+ */
726
+ generateVanillaModifications() {
727
+ return __awaiter(this, void 0, void 0, function* () {
728
+ const modifications = [];
729
+ // Find HTML file to inject script
730
+ const htmlFile = this.findHTMLFile();
731
+ if (htmlFile) {
732
+ const content = fs.readFileSync(htmlFile, 'utf8');
733
+ const modifiedContent = this.injectVanillaScript(content);
734
+ modifications.push({
735
+ filePath: htmlFile,
736
+ action: 'modify',
737
+ content: modifiedContent,
738
+ description: 'Added HumanBehavior CDN script to HTML file'
739
+ });
740
+ }
741
+ // Create or append to environment file
742
+ modifications.push(this.createEnvironmentModification(this.framework));
743
+ return modifications;
744
+ });
745
+ }
746
+ /**
747
+ * Generate Gatsby-specific modifications
748
+ */
749
+ generateGatsbyModifications() {
750
+ return __awaiter(this, void 0, void 0, function* () {
751
+ const modifications = [];
752
+ // Modify or create gatsby-browser.js for Gatsby
753
+ const gatsbyBrowserFile = path.join(this.projectRoot, 'gatsby-browser.js');
754
+ if (fs.existsSync(gatsbyBrowserFile)) {
755
+ const content = fs.readFileSync(gatsbyBrowserFile, 'utf8');
756
+ const modifiedContent = this.injectGatsbyBrowser(content);
757
+ modifications.push({
758
+ filePath: gatsbyBrowserFile,
759
+ action: 'modify',
760
+ content: modifiedContent,
761
+ description: 'Added HumanBehavior initialization to Gatsby browser'
762
+ });
763
+ }
764
+ else {
765
+ // Create gatsby-browser.js if it doesn't exist
766
+ modifications.push({
767
+ filePath: gatsbyBrowserFile,
768
+ action: 'create',
769
+ content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
770
+
771
+ export const onClientEntry = () => {
772
+ console.log('Gatsby browser entry point loaded');
773
+ const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
774
+ console.log('API Key found:', apiKey ? 'Yes' : 'No');
775
+ if (apiKey) {
776
+ const tracker = HumanBehaviorTracker.init(apiKey);
777
+ console.log('HumanBehavior SDK initialized for Gatsby');
778
+ } else {
779
+ console.log('No API key found in environment variables');
780
+ }
781
+ };`,
782
+ description: 'Created gatsby-browser.js with HumanBehavior initialization'
783
+ });
784
+ }
785
+ // Create or append to environment file
786
+ modifications.push(this.createEnvironmentModification(this.framework));
787
+ return modifications;
788
+ });
789
+ }
790
+ /**
791
+ * Apply modifications to the codebase
792
+ */
793
+ applyModifications(modifications) {
794
+ return __awaiter(this, void 0, void 0, function* () {
795
+ for (const modification of modifications) {
796
+ try {
797
+ const dir = path.dirname(modification.filePath);
798
+ if (!fs.existsSync(dir)) {
799
+ fs.mkdirSync(dir, { recursive: true });
800
+ }
801
+ switch (modification.action) {
802
+ case 'create':
803
+ fs.writeFileSync(modification.filePath, modification.content);
804
+ break;
805
+ case 'modify':
806
+ fs.writeFileSync(modification.filePath, modification.content);
807
+ break;
808
+ case 'append':
809
+ fs.appendFileSync(modification.filePath, '\n' + modification.content);
810
+ break;
811
+ }
812
+ }
813
+ catch (error) {
814
+ throw new Error(`Failed to apply modification to ${modification.filePath}: ${error}`);
815
+ }
816
+ }
817
+ });
818
+ }
819
+ /**
820
+ * Generate next steps for the user
821
+ */
822
+ generateNextSteps() {
823
+ var _a, _b;
824
+ const steps = [
825
+ '✅ SDK installed and configured automatically!',
826
+ '🚀 Your app is now tracking user behavior',
827
+ '📊 View sessions in your HumanBehavior dashboard',
828
+ '🔧 Customize tracking in your code as needed'
829
+ ];
830
+ if (((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type) === 'react' || ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.type) === 'nextjs') {
831
+ steps.push('💡 Use the useHumanBehavior() hook to track custom events');
832
+ }
833
+ return steps;
834
+ }
835
+ // Helper methods for file detection and content injection
836
+ findReactAppFile() {
837
+ const possibleFiles = [
838
+ 'src/App.jsx', 'src/App.js', 'src/App.tsx', 'src/App.ts',
839
+ 'src/index.js', 'src/index.tsx', 'src/main.js', 'src/main.tsx'
840
+ ];
841
+ for (const file of possibleFiles) {
842
+ const fullPath = path.join(this.projectRoot, file);
843
+ if (fs.existsSync(fullPath)) {
844
+ return fullPath;
845
+ }
846
+ }
847
+ return null;
848
+ }
849
+ findVueMainFile() {
850
+ const possibleFiles = [
851
+ 'src/main.js', 'src/main.ts', 'src/main.jsx', 'src/main.tsx'
852
+ ];
853
+ for (const file of possibleFiles) {
854
+ const fullPath = path.join(this.projectRoot, file);
855
+ if (fs.existsSync(fullPath)) {
856
+ return fullPath;
857
+ }
858
+ }
859
+ return null;
860
+ }
861
+ findSvelteMainFile() {
862
+ const possibleFiles = [
863
+ 'src/main.js', 'src/main.ts', 'src/main.svelte'
864
+ ];
865
+ for (const file of possibleFiles) {
866
+ const fullPath = path.join(this.projectRoot, file);
867
+ if (fs.existsSync(fullPath)) {
868
+ return fullPath;
869
+ }
870
+ }
871
+ return null;
872
+ }
873
+ findHTMLFile() {
874
+ const possibleFiles = ['index.html', 'public/index.html', 'dist/index.html'];
875
+ for (const file of possibleFiles) {
876
+ const fullPath = path.join(this.projectRoot, file);
877
+ if (fs.existsSync(fullPath)) {
878
+ return fullPath;
879
+ }
880
+ }
881
+ return null;
882
+ }
883
+ injectReactProvider(content, filePath) {
884
+ var _a, _b, _c;
885
+ filePath.endsWith('.tsx') || filePath.endsWith('.ts');
886
+ // Check if already has HumanBehaviorProvider
887
+ if (content.includes('HumanBehaviorProvider')) {
888
+ return content;
889
+ }
890
+ // Determine the correct environment variable syntax based on bundler
891
+ const isVite = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.bundler) === 'vite';
892
+ const envVar = isVite
893
+ ? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
894
+ : 'process.env.HUMANBEHAVIOR_API_KEY!';
895
+ const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
896
+ // Enhanced parsing for React 18+ features
897
+ const hasReact18 = (_c = (_b = this.framework) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.hasReact18;
898
+ // Handle different React patterns
899
+ if (content.includes('function App()') || content.includes('const App =')) {
900
+ // Add import statement
901
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
902
+ // If no React import found, add it at the top
903
+ if (!modifiedContent.includes(importStatement)) {
904
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
905
+ }
906
+ // Wrap the App component return with HumanBehaviorProvider
907
+ modifiedContent = modifiedContent.replace(/(return\s*\([\s\S]*?\)\s*;)/, `return (
908
+ <HumanBehaviorProvider apiKey={${envVar}}>
909
+ $1
910
+ </HumanBehaviorProvider>
911
+ );`);
912
+ return modifiedContent;
913
+ }
914
+ // Handle React 18+ createRoot pattern
915
+ if (hasReact18 && content.includes('createRoot')) {
916
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
917
+ if (!modifiedContent.includes(importStatement)) {
918
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
919
+ }
920
+ // Wrap the root render with HumanBehaviorProvider
921
+ modifiedContent = modifiedContent.replace(/(root\.render\s*\([\s\S]*?\)\s*;)/, `root.render(
922
+ <HumanBehaviorProvider apiKey={${envVar}}>
923
+ $1
924
+ </HumanBehaviorProvider>
925
+ );`);
926
+ return modifiedContent;
927
+ }
928
+ // Fallback: simple injection
929
+ return `${importStatement}\n\n${content}`;
930
+ }
931
+ injectNextJSAppRouter(content) {
932
+ if (content.includes('Providers')) {
933
+ return content;
934
+ }
935
+ const importStatement = `import { Providers } from './providers';`;
936
+ // First, add the import statement
937
+ let modifiedContent = content.replace(/export default function RootLayout/, `${importStatement}\n\nexport default function RootLayout`);
938
+ // Then wrap the body content with Providers
939
+ // Use a more specific approach to handle the body content
940
+ modifiedContent = modifiedContent.replace(/<body([^>]*)>([\s\S]*?)<\/body>/, (match, bodyAttrs, bodyContent) => {
941
+ // Trim whitespace and newlines from bodyContent
942
+ const trimmedContent = bodyContent.trim();
943
+ return `<body${bodyAttrs}>
944
+ <Providers>
945
+ ${trimmedContent}
946
+ </Providers>
947
+ </body>`;
948
+ });
949
+ return modifiedContent;
950
+ }
951
+ injectNextJSPagesRouter(content) {
952
+ if (content.includes('Providers')) {
953
+ return content;
954
+ }
955
+ const importStatement = `import { Providers } from '../components/providers';`;
956
+ return content.replace(/function MyApp/, `${importStatement}\n\nfunction MyApp`).replace(/return \(([\s\S]*?)\);/, `return (
957
+ <Providers>
958
+ $1
959
+ </Providers>
960
+ );`);
961
+ }
962
+ injectRemixProvider(content) {
963
+ if (content.includes('HumanBehaviorProvider')) {
964
+ return content;
965
+ }
966
+ const importStatement = `import { HumanBehaviorProvider, createHumanBehaviorLoader } from 'humanbehavior-js/remix';`;
967
+ const useLoaderDataImport = `import { useLoaderData } from "@remix-run/react";`;
968
+ // Add imports more robustly
969
+ let modifiedContent = content;
970
+ // Add HumanBehaviorProvider import - find the last import and add after it
971
+ if (!content.includes('HumanBehaviorProvider')) {
972
+ const lastImportIndex = modifiedContent.lastIndexOf('import');
973
+ if (lastImportIndex !== -1) {
974
+ const nextLineIndex = modifiedContent.indexOf('\n', lastImportIndex);
975
+ if (nextLineIndex !== -1) {
976
+ modifiedContent = modifiedContent.slice(0, nextLineIndex + 1) +
977
+ importStatement + '\n' +
978
+ modifiedContent.slice(nextLineIndex + 1);
979
+ }
980
+ else {
981
+ modifiedContent = modifiedContent + '\n' + importStatement;
982
+ }
983
+ }
984
+ else {
985
+ modifiedContent = importStatement + '\n' + modifiedContent;
986
+ }
987
+ }
988
+ // Add useLoaderData import - find the last import and add after it
989
+ if (!content.includes('useLoaderData')) {
990
+ const lastImportIndex = modifiedContent.lastIndexOf('import');
991
+ if (lastImportIndex !== -1) {
992
+ const nextLineIndex = modifiedContent.indexOf('\n', lastImportIndex);
993
+ if (nextLineIndex !== -1) {
994
+ modifiedContent = modifiedContent.slice(0, nextLineIndex + 1) +
995
+ useLoaderDataImport + '\n' +
996
+ modifiedContent.slice(nextLineIndex + 1);
997
+ }
998
+ else {
999
+ modifiedContent = modifiedContent + '\n' + useLoaderDataImport;
1000
+ }
1001
+ }
1002
+ else {
1003
+ modifiedContent = useLoaderDataImport + '\n' + modifiedContent;
1004
+ }
1005
+ }
1006
+ // Add loader function before the App component
1007
+ if (!content.includes('export const loader')) {
1008
+ modifiedContent = modifiedContent.replace(/export default function App\(\)/, `export const loader = createHumanBehaviorLoader();
1009
+
1010
+ export default function App()`);
1011
+ }
1012
+ // Wrap the App component content with HumanBehaviorProvider
1013
+ modifiedContent = modifiedContent.replace(/export default function App\(\) \{[\s\S]*?return \(([\s\S]*?)\);[\s\S]*?\}/, `export default function App() {
1014
+ const data = useLoaderData<typeof loader>();
1015
+
1016
+ return (
1017
+ <HumanBehaviorProvider apiKey={data.ENV.HUMANBEHAVIOR_API_KEY}>
1018
+ $1
1019
+ </HumanBehaviorProvider>
1020
+ );
1021
+ }`);
1022
+ return modifiedContent;
1023
+ }
1024
+ injectVuePlugin(content) {
1025
+ var _a, _b;
1026
+ if (content.includes('HumanBehaviorPlugin')) {
1027
+ return content;
1028
+ }
1029
+ const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
1030
+ // Enhanced Vue 3 support with version detection
1031
+ const hasVue3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasVue3;
1032
+ if (hasVue3) {
1033
+ // Vue 3 with Composition API
1034
+ const pluginUsage = `app.use(HumanBehaviorPlugin, {
1035
+ apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
1036
+ });`;
1037
+ let modifiedContent = content;
1038
+ // Add import statement
1039
+ if (!content.includes(importStatement)) {
1040
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1041
+ // If no Vue import found, add it at the top
1042
+ if (!modifiedContent.includes(importStatement)) {
1043
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1044
+ }
1045
+ }
1046
+ // Handle createApp pattern
1047
+ if (content.includes('createApp')) {
1048
+ modifiedContent = modifiedContent.replace(/(app\.mount\(.*?\))/, `${pluginUsage}\n\n$1`);
1049
+ }
1050
+ return modifiedContent;
1051
+ }
1052
+ else {
1053
+ // Vue 2 with Options API
1054
+ const pluginUsage = `Vue.use(HumanBehaviorPlugin, {
1055
+ apiKey: process.env.VUE_APP_HUMANBEHAVIOR_API_KEY
1056
+ });`;
1057
+ let modifiedContent = content;
1058
+ // Add import statement
1059
+ if (!content.includes(importStatement)) {
1060
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1061
+ if (!modifiedContent.includes(importStatement)) {
1062
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1063
+ }
1064
+ }
1065
+ // Handle new Vue pattern
1066
+ if (content.includes('new Vue')) {
1067
+ modifiedContent = modifiedContent.replace(/(new Vue\(.*?\))/, `${pluginUsage}\n\n$1`);
1068
+ }
1069
+ return modifiedContent;
1070
+ }
1071
+ }
1072
+ injectAngularModule(content) {
1073
+ if (content.includes('HumanBehaviorModule')) {
1074
+ return content;
1075
+ }
1076
+ const importStatement = `import { HumanBehaviorModule } from 'humanbehavior-js/angular';`;
1077
+ const environmentImport = `import { environment } from '../environments/environment';`;
1078
+ // Add environment import if not present
1079
+ let modifiedContent = content;
1080
+ if (!content.includes('environment')) {
1081
+ modifiedContent = content.replace(/import.*from.*['"]@angular/, `${environmentImport}\n$&`);
1082
+ }
1083
+ return modifiedContent.replace(/imports:\s*\[([\s\S]*?)\]/, `imports: [
1084
+ $1,
1085
+ HumanBehaviorModule.forRoot({
1086
+ apiKey: environment.humanBehaviorApiKey
1087
+ })
1088
+ ]`).replace(/import.*from.*['"]@angular/, `$&\n${importStatement}`);
1089
+ }
1090
+ injectAngularStandaloneInit(content) {
1091
+ if (content.includes('initializeHumanBehavior')) {
1092
+ return content;
1093
+ }
1094
+ const importStatement = `import { initializeHumanBehavior } from 'humanbehavior-js/angular';`;
1095
+ // Add import at the top
1096
+ let modifiedContent = content.replace(/import.*from.*['"]@angular/, `${importStatement}\n$&`);
1097
+ // Add initialization after bootstrapApplication
1098
+ modifiedContent = modifiedContent.replace(/(bootstrapApplication\([^}]+\}?\)(?:\s*\.catch[^;]+;)?)/, `$1
1099
+
1100
+ // Initialize HumanBehavior SDK (client-side only)
1101
+ if (typeof window !== 'undefined') {
1102
+ const tracker = initializeHumanBehavior(
1103
+ '${this.apiKey}'
1104
+ );
1105
+ }`);
1106
+ return modifiedContent;
1107
+ }
1108
+ injectSvelteStore(content) {
1109
+ if (content.includes('humanBehaviorStore')) {
1110
+ return content;
1111
+ }
1112
+ const importStatement = `import { humanBehaviorStore } from 'humanbehavior-js/svelte';`;
1113
+ const initCode = `humanBehaviorStore.init(process.env.PUBLIC_HUMANBEHAVIOR_API_KEY || '');`;
1114
+ return `${importStatement}\n${initCode}\n\n${content}`;
1115
+ }
1116
+ injectSvelteKitLayout(content) {
1117
+ if (content.includes('humanBehaviorStore')) {
1118
+ return content;
1119
+ }
1120
+ const importStatement = `import { humanBehaviorStore } from 'humanbehavior-js/svelte';`;
1121
+ const envImport = `import { PUBLIC_HUMANBEHAVIOR_API_KEY } from '$env/static/public';`;
1122
+ const initCode = `humanBehaviorStore.init(PUBLIC_HUMANBEHAVIOR_API_KEY || '');`;
1123
+ // Add to script section - handle different script tag patterns
1124
+ if (content.includes('<script lang="ts">')) {
1125
+ return content.replace(/<script lang="ts">/, `<script lang="ts">\n\t${envImport}\n\t${importStatement}\n\t${initCode}`);
1126
+ }
1127
+ else if (content.includes('<script>')) {
1128
+ return content.replace(/<script>/, `<script>\n\t${envImport}\n\t${importStatement}\n\t${initCode}`);
1129
+ }
1130
+ else if (content.includes('<script context="module">')) {
1131
+ return content.replace(/<script\s+context="module">/, `<script context="module">\n\t${envImport}\n\t${importStatement}\n\t${initCode}`);
1132
+ }
1133
+ else {
1134
+ // If no script tag found, add one at the beginning
1135
+ return content.replace(/<svelte:head>/, `<script lang="ts">\n\t${envImport}\n\t${importStatement}\n\t${initCode}\n</script>\n\n<svelte:head>`);
1136
+ }
1137
+ }
1138
+ injectVanillaScript(content) {
1139
+ if (content.includes('humanbehavior-js')) {
1140
+ return content;
1141
+ }
1142
+ const cdnScript = `<script src="https://unpkg.com/humanbehavior-js@latest/dist/index.min.js"></script>`;
1143
+ const initScript = `<script>
1144
+ // Initialize HumanBehavior SDK
1145
+ // Note: For vanilla HTML, the API key must be hardcoded since env vars aren't available
1146
+ const tracker = HumanBehaviorTracker.init('${this.apiKey}');
1147
+ </script>`;
1148
+ return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
1149
+ }
1150
+ /**
1151
+ * Inject Astro layout with HumanBehavior component
1152
+ */
1153
+ injectAstroLayout(content) {
1154
+ // Check if HumanBehavior component is already imported
1155
+ if (content.includes('HumanBehavior') || content.includes('humanbehavior-js')) {
1156
+ return content; // Already has HumanBehavior
1157
+ }
1158
+ // Add import inside frontmatter if not present
1159
+ let modifiedContent = content;
1160
+ if (!content.includes('import HumanBehavior')) {
1161
+ const importStatement = 'import HumanBehavior from \'../components/HumanBehavior.astro\';';
1162
+ const frontmatterEndIndex = content.indexOf('---', 3);
1163
+ if (frontmatterEndIndex !== -1) {
1164
+ // Insert import inside frontmatter, before the closing ---
1165
+ modifiedContent = content.slice(0, frontmatterEndIndex) + '\n' + importStatement + '\n' + content.slice(frontmatterEndIndex);
1166
+ }
1167
+ else {
1168
+ // No frontmatter, add at the very beginning
1169
+ modifiedContent = '---\n' + importStatement + '\n---\n\n' + content;
1170
+ }
1171
+ }
1172
+ // Find the closing </body> tag and add HumanBehavior component before it
1173
+ const bodyCloseIndex = modifiedContent.lastIndexOf('</body>');
1174
+ if (bodyCloseIndex === -1) {
1175
+ // No body tag found, append to end
1176
+ return modifiedContent + '\n\n<HumanBehavior />';
1177
+ }
1178
+ // Add component before closing body tag
1179
+ return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
1180
+ }
1181
+ injectNuxtConfig(content) {
1182
+ var _a, _b;
1183
+ if (content.includes('humanBehaviorApiKey')) {
1184
+ return content;
1185
+ }
1186
+ // Enhanced Nuxt 3 support with version detection
1187
+ const hasNuxt3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasNuxt3;
1188
+ if (hasNuxt3) {
1189
+ // Nuxt 3 with runtime config
1190
+ return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
1191
+ runtimeConfig: {
1192
+ public: {
1193
+ humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
1194
+ }
1195
+ },`);
1196
+ }
1197
+ else {
1198
+ // Nuxt 2 with env config
1199
+ return content.replace(/export default \{/, `export default {
1200
+ env: {
1201
+ humanBehaviorApiKey: process.env.HUMANBEHAVIOR_API_KEY
1202
+ },`);
1203
+ }
1204
+ }
1205
+ injectGatsbyLayout(content) {
1206
+ if (content.includes('HumanBehavior')) {
1207
+ return content;
1208
+ }
1209
+ const importStatement = `import HumanBehavior from './HumanBehavior';`;
1210
+ const componentUsage = `<HumanBehavior apiKey={process.env.GATSBY_HUMANBEHAVIOR_API_KEY || ''} />`;
1211
+ // Add import at the top
1212
+ let modifiedContent = content.replace(/import.*from.*['"]\./, `${importStatement}\n$&`);
1213
+ // Add component before closing body tag
1214
+ modifiedContent = modifiedContent.replace(/(\s*<\/body>)/, `\n ${componentUsage}\n$1`);
1215
+ return modifiedContent;
1216
+ }
1217
+ injectGatsbyBrowser(content) {
1218
+ if (content.includes('HumanBehaviorTracker')) {
1219
+ return content;
1220
+ }
1221
+ const importStatement = `import { HumanBehaviorTracker } from 'humanbehavior-js';`;
1222
+ const initCode = `
1223
+ // Initialize HumanBehavior SDK
1224
+ export const onClientEntry = () => {
1225
+ console.log('Gatsby browser entry point loaded');
1226
+ const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
1227
+ console.log('API Key found:', apiKey ? 'Yes' : 'No');
1228
+ if (apiKey) {
1229
+ const tracker = HumanBehaviorTracker.init(apiKey);
1230
+ console.log('HumanBehavior SDK initialized for Gatsby');
1231
+ } else {
1232
+ console.log('No API key found in environment variables');
1233
+ }
1234
+ };`;
1235
+ // If the file already has content, add the import and init code
1236
+ if (content.trim()) {
1237
+ return `${importStatement}${initCode}\n\n${content}`;
1238
+ }
1239
+ else {
1240
+ // If file is empty, just return the new content
1241
+ return `${importStatement}${initCode}`;
1242
+ }
1243
+ }
1244
+ /**
1245
+ * Helper method to find the best environment file for a framework
1246
+ */
1247
+ findBestEnvFile(framework) {
1248
+ const possibleEnvFiles = [
1249
+ '.env.local',
1250
+ '.env.development.local',
1251
+ '.env.development',
1252
+ '.env.local.development',
1253
+ '.env',
1254
+ '.env.production',
1255
+ '.env.staging'
1256
+ ];
1257
+ // Framework-specific environment variable names
1258
+ const getEnvVarName = (framework) => {
1259
+ // Handle React+Vite specifically
1260
+ if (framework.type === 'react' && framework.bundler === 'vite') {
1261
+ return 'VITE_HUMANBEHAVIOR_API_KEY';
1262
+ }
1263
+ // Framework-specific mappings
1264
+ const envVarNames = {
1265
+ react: 'HUMANBEHAVIOR_API_KEY',
1266
+ nextjs: 'NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
1267
+ vue: 'VITE_HUMANBEHAVIOR_API_KEY',
1268
+ svelte: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
1269
+ angular: 'HUMANBEHAVIOR_API_KEY',
1270
+ nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
1271
+ remix: 'HUMANBEHAVIOR_API_KEY',
1272
+ vanilla: 'HUMANBEHAVIOR_API_KEY',
1273
+ astro: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
1274
+ gatsby: 'GATSBY_HUMANBEHAVIOR_API_KEY',
1275
+ node: 'HUMANBEHAVIOR_API_KEY',
1276
+ auto: 'HUMANBEHAVIOR_API_KEY'
1277
+ };
1278
+ return envVarNames[framework.type] || 'HUMANBEHAVIOR_API_KEY';
1279
+ };
1280
+ const envVarName = getEnvVarName(framework);
1281
+ // Check for existing files
1282
+ for (const envFile of possibleEnvFiles) {
1283
+ const fullPath = path.join(this.projectRoot, envFile);
1284
+ if (fs.existsSync(fullPath)) {
1285
+ return { filePath: fullPath, envVarName };
1286
+ }
1287
+ }
1288
+ // Framework-specific default file creation
1289
+ const defaultFiles = {
1290
+ react: '.env.local',
1291
+ nextjs: '.env.local',
1292
+ vue: '.env.local',
1293
+ svelte: '.env',
1294
+ angular: '.env',
1295
+ nuxt: '.env',
1296
+ remix: '.env.local',
1297
+ vanilla: '.env',
1298
+ astro: '.env',
1299
+ gatsby: '.env.development',
1300
+ node: '.env',
1301
+ auto: '.env'
1302
+ };
1303
+ const defaultFile = defaultFiles[framework.type] || '.env';
1304
+ return {
1305
+ filePath: path.join(this.projectRoot, defaultFile),
1306
+ envVarName
1307
+ };
1308
+ }
1309
+ /**
1310
+ * Helper method to create or append to environment files
1311
+ */
1312
+ createEnvironmentModification(framework) {
1313
+ const { filePath, envVarName } = this.findBestEnvFile(framework);
1314
+ // Clean the API key to prevent formatting issues
1315
+ const cleanApiKey = this.apiKey.trim();
1316
+ if (fs.existsSync(filePath)) {
1317
+ // Check if the variable already exists
1318
+ const content = fs.readFileSync(filePath, 'utf8');
1319
+ if (content.includes(envVarName)) {
1320
+ // Variable exists, don't modify
1321
+ return {
1322
+ filePath,
1323
+ action: 'modify',
1324
+ content: content, // No change
1325
+ description: `API key already exists in ${path.basename(filePath)}`
1326
+ };
1327
+ }
1328
+ else {
1329
+ // Append to existing file
1330
+ return {
1331
+ filePath,
1332
+ action: 'append',
1333
+ content: `\n${envVarName}=${cleanApiKey}`,
1334
+ description: `Added API key to existing ${path.basename(filePath)}`
1335
+ };
1336
+ }
1337
+ }
1338
+ else {
1339
+ // Create new file
1340
+ return {
1341
+ filePath,
1342
+ action: 'create',
1343
+ content: `${envVarName}=${cleanApiKey}`,
1344
+ description: `Created ${path.basename(filePath)} with API key`
1345
+ };
1346
+ }
1347
+ }
1348
+ }
1349
+
1350
+ /**
1351
+ * Remote AI Service Implementation
1352
+ *
1353
+ * This connects to your deployed Lambda function via API Gateway
1354
+ */
1355
+ class RemoteAIService {
1356
+ constructor(config) {
1357
+ this.config = Object.assign({ timeout: 10000 }, config);
1358
+ }
1359
+ /**
1360
+ * Analyze code patterns using your deployed AI service
1361
+ */
1362
+ analyzeCodePatterns(codeSamples) {
1363
+ return __awaiter(this, void 0, void 0, function* () {
1364
+ try {
1365
+ const response = yield fetch(`${this.config.apiEndpoint}/analyze`, {
1366
+ method: 'POST',
1367
+ headers: {
1368
+ 'Content-Type': 'application/json',
1369
+ },
1370
+ body: JSON.stringify({ codeSamples }),
1371
+ signal: AbortSignal.timeout(this.config.timeout || 10000)
1372
+ });
1373
+ if (!response.ok) {
1374
+ throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
1375
+ }
1376
+ const result = yield response.json();
1377
+ return result.analysis;
1378
+ }
1379
+ catch (error) {
1380
+ console.warn('Remote AI service failed, falling back to heuristic analysis:', error);
1381
+ return this.performHeuristicAnalysis(codeSamples);
1382
+ }
1383
+ });
1384
+ }
1385
+ /**
1386
+ * Resolve conflicts using your deployed AI service
1387
+ */
1388
+ resolveConflicts(conflicts, framework) {
1389
+ return __awaiter(this, void 0, void 0, function* () {
1390
+ try {
1391
+ const response = yield fetch(`${this.config.apiEndpoint}/resolve-conflicts`, {
1392
+ method: 'POST',
1393
+ headers: {
1394
+ 'Content-Type': 'application/json',
1395
+ },
1396
+ body: JSON.stringify({ conflicts, framework }),
1397
+ signal: AbortSignal.timeout(this.config.timeout || 10000)
1398
+ });
1399
+ if (!response.ok) {
1400
+ throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
1401
+ }
1402
+ const result = yield response.json();
1403
+ return result.resolutions || [];
1404
+ }
1405
+ catch (error) {
1406
+ console.warn('Remote AI conflict resolution failed, using heuristic approach:', error);
1407
+ return this.resolveConflictsHeuristic(conflicts, framework);
1408
+ }
1409
+ });
1410
+ }
1411
+ /**
1412
+ * Generate optimizations using your deployed AI service
1413
+ */
1414
+ generateOptimizations(framework, patterns) {
1415
+ return __awaiter(this, void 0, void 0, function* () {
1416
+ try {
1417
+ const response = yield fetch(`${this.config.apiEndpoint}/optimize`, {
1418
+ method: 'POST',
1419
+ headers: {
1420
+ 'Content-Type': 'application/json',
1421
+ },
1422
+ body: JSON.stringify({ framework, patterns }),
1423
+ signal: AbortSignal.timeout(this.config.timeout || 10000)
1424
+ });
1425
+ if (!response.ok) {
1426
+ throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
1427
+ }
1428
+ const result = yield response.json();
1429
+ return result.optimizations || [];
1430
+ }
1431
+ catch (error) {
1432
+ console.warn('Remote AI optimization generation failed, using heuristic approach:', error);
1433
+ return this.generateOptimizationsHeuristic(framework, patterns);
1434
+ }
1435
+ });
1436
+ }
1437
+ /**
1438
+ * Heuristic analysis fallback
1439
+ */
1440
+ performHeuristicAnalysis(codeSamples) {
1441
+ const patterns = codeSamples.join(' ').toLowerCase();
1442
+ // Framework detection
1443
+ let framework = { name: 'vanilla', type: 'vanilla' };
1444
+ let confidence = 0.5;
1445
+ if (patterns.includes('nuxt') || patterns.includes('nuxtjs') || patterns.includes('defineNuxtConfig') || patterns.includes('nuxt.config') || patterns.includes('@nuxt/') || patterns.includes('useNuxtApp') || patterns.includes('useRuntimeConfig') || patterns.includes('useSeoMeta') || patterns.includes('useHead') || patterns.includes('useLazyFetch') || patterns.includes('useFetch') || patterns.includes('useAsyncData') || patterns.includes('#app')) {
1446
+ framework = { name: 'nuxt', type: 'nuxt' };
1447
+ confidence = 0.95;
1448
+ }
1449
+ else if (patterns.includes('next') || patterns.includes('nextjs') || patterns.includes('next/link') || patterns.includes('next/image') || patterns.includes('next/navigation') || patterns.includes('next/router') || patterns.includes('getserverSideProps') || patterns.includes('getstaticProps') || patterns.includes('getstaticPaths') || patterns.includes('app/layout') || patterns.includes('app/page') || patterns.includes('pages/')) {
1450
+ framework = { name: 'nextjs', type: 'nextjs' };
1451
+ confidence = 0.95;
1452
+ }
1453
+ else if (patterns.includes('gatsby') || patterns.includes('gatsby-browser') || patterns.includes('gatsby-ssr') || patterns.includes('gatsby-node') || patterns.includes('gatsby-config') || patterns.includes('useStaticQuery') || patterns.includes('graphql')) {
1454
+ framework = { name: 'gatsby', type: 'gatsby' };
1455
+ confidence = 0.95;
1456
+ }
1457
+ else if (patterns.includes('react')) {
1458
+ framework = { name: 'react', type: 'react' };
1459
+ confidence = 0.9;
1460
+ }
1461
+ else if (patterns.includes('vue')) {
1462
+ framework = { name: 'vue', type: 'vue' };
1463
+ confidence = 0.9;
1464
+ }
1465
+ else if (patterns.includes('angular')) {
1466
+ framework = { name: 'angular', type: 'angular' };
1467
+ confidence = 0.9;
1468
+ }
1469
+ else if (patterns.includes('svelte')) {
1470
+ framework = { name: 'svelte', type: 'svelte' };
1471
+ confidence = 0.9;
1472
+ }
1473
+ else if (patterns.includes('astro')) {
1474
+ framework = { name: 'astro', type: 'astro' };
1475
+ confidence = 0.9;
1476
+ }
1477
+ // Integration strategy
1478
+ let integrationStrategy = 'script';
1479
+ if (framework.type === 'react' || framework.type === 'nextjs' || framework.type === 'gatsby') {
1480
+ integrationStrategy = 'provider';
1481
+ }
1482
+ else if (framework.type === 'vue') {
1483
+ integrationStrategy = 'plugin';
1484
+ }
1485
+ else if (framework.type === 'angular') {
1486
+ integrationStrategy = 'module';
1487
+ }
1488
+ // Compatibility mode
1489
+ let compatibilityMode = 'modern';
1490
+ if (patterns.includes('require(') || patterns.includes('var ')) {
1491
+ compatibilityMode = 'legacy';
1492
+ }
1493
+ return {
1494
+ framework,
1495
+ confidence,
1496
+ patterns: codeSamples,
1497
+ conflicts: [],
1498
+ recommendations: [],
1499
+ integrationStrategy,
1500
+ compatibilityMode
1501
+ };
1502
+ }
1503
+ /**
1504
+ * Heuristic conflict resolution
1505
+ */
1506
+ resolveConflictsHeuristic(conflicts, framework) {
1507
+ const resolutions = [];
1508
+ for (const conflict of conflicts) {
1509
+ switch (conflict) {
1510
+ case 'existing_humanbehavior_code':
1511
+ resolutions.push('update_existing_integration');
1512
+ break;
1513
+ case 'existing_provider':
1514
+ resolutions.push('merge_providers');
1515
+ break;
1516
+ case 'module_system_conflict':
1517
+ resolutions.push('hybrid_module_support');
1518
+ break;
1519
+ default:
1520
+ resolutions.push('skip_conflict');
1521
+ }
1522
+ }
1523
+ return resolutions;
1524
+ }
1525
+ /**
1526
+ * Heuristic optimization generation
1527
+ */
1528
+ generateOptimizationsHeuristic(framework, patterns) {
1529
+ const optimizations = [];
1530
+ switch (framework.type) {
1531
+ case 'react':
1532
+ optimizations.push('Use React.memo for performance optimization');
1533
+ optimizations.push('Implement error boundaries for better error tracking');
1534
+ optimizations.push('Consider using React.lazy for code splitting');
1535
+ break;
1536
+ case 'vue':
1537
+ optimizations.push('Use Vue 3 Composition API for better performance');
1538
+ optimizations.push('Implement proper error handling in components');
1539
+ optimizations.push('Consider using Vue Router for navigation tracking');
1540
+ break;
1541
+ case 'angular':
1542
+ optimizations.push('Use Angular standalone components for better tree-shaking');
1543
+ optimizations.push('Implement proper error handling with ErrorHandler');
1544
+ optimizations.push('Consider using Angular signals for state management');
1545
+ break;
1546
+ default:
1547
+ optimizations.push('Enable performance tracking');
1548
+ optimizations.push('Implement error tracking');
1549
+ optimizations.push('Consider progressive enhancement');
1550
+ }
1551
+ return optimizations;
1552
+ }
1553
+ }
1554
+
1555
+ /**
1556
+ * Manual Framework Installation Wizard
1557
+ *
1558
+ * This wizard allows users to manually specify their framework instead of auto-detection.
1559
+ * Useful when auto-detection fails or users want more control.
1560
+ */
1561
+ class ManualFrameworkInstallationWizard extends AutoInstallationWizard {
1562
+ constructor(apiKey, projectRoot = process.cwd(), framework) {
1563
+ super(apiKey, projectRoot);
1564
+ this.selectedFramework = framework.toLowerCase();
1565
+ this.framework = this.createFrameworkInfo(this.selectedFramework);
1566
+ }
1567
+ /**
1568
+ * Manual installation with user-specified framework
1569
+ */
1570
+ install() {
1571
+ return __awaiter(this, void 0, void 0, function* () {
1572
+ try {
1573
+ // Step 1: Handle framework selection
1574
+ if (this.selectedFramework === 'auto') {
1575
+ // Use full AI detection for "Other" option
1576
+ this.framework = yield this.runFullDetection();
1577
+ }
1578
+ else {
1579
+ // Set framework based on user selection
1580
+ this.framework = this.createFrameworkInfo(this.selectedFramework);
1581
+ if (!this.framework) {
1582
+ this.framework = { name: 'unknown', type: 'vanilla' };
1583
+ }
1584
+ // Step 2: Run full detection logic to find entry points, file names, etc.
1585
+ const detectedFramework = yield this.runFullDetection();
1586
+ // Step 3: Merge manual framework with detected details
1587
+ this.framework = Object.assign(Object.assign({}, detectedFramework), { name: this.framework.name, type: this.framework.type });
1588
+ }
1589
+ // Step 4: Install package
1590
+ yield this.installPackage();
1591
+ // Step 5: Generate and apply code modifications
1592
+ const modifications = yield this.generateModifications();
1593
+ yield this.applyModifications(modifications);
1594
+ // Step 6: Generate next steps
1595
+ const nextSteps = this.generateManualNextSteps();
1596
+ return {
1597
+ success: true,
1598
+ framework: this.framework,
1599
+ modifications,
1600
+ errors: [],
1601
+ nextSteps,
1602
+ selectedFramework: this.selectedFramework,
1603
+ manualMode: true
1604
+ };
1605
+ }
1606
+ catch (error) {
1607
+ return {
1608
+ success: false,
1609
+ framework: this.framework || { name: 'unknown', type: 'vanilla' },
1610
+ modifications: [],
1611
+ errors: [error instanceof Error ? error.message : 'Unknown error'],
1612
+ nextSteps: [],
1613
+ selectedFramework: this.selectedFramework,
1614
+ manualMode: true
1615
+ };
1616
+ }
1617
+ });
1618
+ }
1619
+ /**
1620
+ * Run full detection logic to find entry points, file names, bundler, etc.
1621
+ */
1622
+ runFullDetection() {
1623
+ return __awaiter(this, void 0, void 0, function* () {
1624
+ if (this.selectedFramework === 'auto') {
1625
+ // Use AI service for auto-detection
1626
+ const aiService = new RemoteAIService({
1627
+ apiEndpoint: 'https://ik3zxh4790.execute-api.us-east-1.amazonaws.com/prod'
1628
+ });
1629
+ // Use AI service directly for detection
1630
+ const projectFiles = yield this.scanProjectFiles();
1631
+ const codeSamples = yield this.extractCodeSamples(projectFiles);
1632
+ const aiAnalysis = yield aiService.analyzeCodePatterns(codeSamples);
1633
+ return aiAnalysis.framework;
1634
+ }
1635
+ else {
1636
+ // Use traditional detection for manual frameworks
1637
+ const tempWizard = new AutoInstallationWizard(this.apiKey, this.projectRoot);
1638
+ const detected = yield tempWizard.detectFramework();
1639
+ return detected;
1640
+ }
1641
+ });
1642
+ }
1643
+ /**
1644
+ * Scan project files for analysis
1645
+ */
1646
+ scanProjectFiles() {
1647
+ return __awaiter(this, void 0, void 0, function* () {
1648
+ const files = [];
1649
+ const scanDir = (dir, depth = 0) => {
1650
+ if (depth > 3)
1651
+ return; // Limit depth
1652
+ try {
1653
+ const items = fs.readdirSync(dir);
1654
+ for (const item of items) {
1655
+ const fullPath = path.join(dir, item);
1656
+ const stat = fs.statSync(fullPath);
1657
+ if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
1658
+ scanDir(fullPath, depth + 1);
1659
+ }
1660
+ else if (stat.isFile() && this.isRelevantFile(item)) {
1661
+ files.push(fullPath);
1662
+ }
1663
+ }
1664
+ }
1665
+ catch (error) {
1666
+ // Skip inaccessible directories
1667
+ }
1668
+ };
1669
+ scanDir(this.projectRoot);
1670
+ return files;
1671
+ });
1672
+ }
1673
+ /**
1674
+ * Check if file is relevant for analysis
1675
+ */
1676
+ isRelevantFile(filename) {
1677
+ const relevantExtensions = [
1678
+ '.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte', '.html',
1679
+ '.json', '.config.js', '.config.ts', '.babelrc', '.eslintrc'
1680
+ ];
1681
+ const relevantNames = [
1682
+ 'package.json', 'tsconfig.json', 'vite.config', 'webpack.config',
1683
+ 'next.config', 'nuxt.config', 'angular.json', 'svelte.config'
1684
+ ];
1685
+ return relevantExtensions.some(ext => filename.endsWith(ext)) ||
1686
+ relevantNames.some(name => filename.includes(name));
1687
+ }
1688
+ /**
1689
+ * Extract code samples for AI analysis
1690
+ */
1691
+ extractCodeSamples(files) {
1692
+ return __awaiter(this, void 0, void 0, function* () {
1693
+ const samples = [];
1694
+ for (const file of files.slice(0, 20)) { // Limit to 20 files
1695
+ try {
1696
+ const content = fs.readFileSync(file, 'utf8');
1697
+ const relativePath = path.relative(this.projectRoot, file);
1698
+ samples.push(`File: ${relativePath}\n${content.substring(0, 1000)}`);
1699
+ }
1700
+ catch (error) {
1701
+ // Skip unreadable files
1702
+ }
1703
+ }
1704
+ return samples;
1705
+ });
1706
+ }
1707
+ /**
1708
+ * Create framework info based on user selection
1709
+ */
1710
+ createFrameworkInfo(framework) {
1711
+ const frameworkMap = {
1712
+ 'react': { name: 'react', type: 'react' },
1713
+ 'nextjs': { name: 'nextjs', type: 'nextjs' },
1714
+ 'next': { name: 'nextjs', type: 'nextjs' },
1715
+ 'vue': { name: 'vue', type: 'vue' },
1716
+ 'nuxt': { name: 'nuxt', type: 'nuxt' },
1717
+ 'nuxtjs': { name: 'nuxt', type: 'nuxt' },
1718
+ 'angular': { name: 'angular', type: 'angular' },
1719
+ 'svelte': { name: 'svelte', type: 'svelte' },
1720
+ 'sveltekit': { name: 'svelte', type: 'svelte' },
1721
+ 'remix': { name: 'remix', type: 'remix' },
1722
+ 'astro': { name: 'astro', type: 'astro' },
1723
+ 'gatsby': { name: 'gatsby', type: 'gatsby' },
1724
+ 'vanilla': { name: 'vanilla', type: 'vanilla' },
1725
+ 'node': { name: 'node', type: 'node' },
1726
+ 'auto': { name: 'auto-detected', type: 'auto' }
1727
+ };
1728
+ return frameworkMap[framework] || { name: framework, type: 'vanilla' };
1729
+ }
1730
+ /**
1731
+ * Override framework detection to use manual selection
1732
+ */
1733
+ detectFramework() {
1734
+ return __awaiter(this, void 0, void 0, function* () {
1735
+ return this.framework || { name: 'unknown', type: 'vanilla' };
1736
+ });
1737
+ }
1738
+ /**
1739
+ * Generate next steps with manual mode info
1740
+ */
1741
+ generateManualNextSteps() {
1742
+ var _a;
1743
+ return [
1744
+ '✅ Manual framework installation completed!',
1745
+ `🎯 Selected framework: ${((_a = this.framework) === null || _a === void 0 ? void 0 : _a.name) || 'unknown'}`,
1746
+ `🔧 Integration strategy: ${this.getIntegrationStrategy()}`,
1747
+ '🚀 Your app is now ready to track user behavior',
1748
+ '📊 View sessions in your HumanBehavior dashboard'
1749
+ ];
1750
+ }
1751
+ /**
1752
+ * Get integration strategy based on framework
1753
+ */
1754
+ getIntegrationStrategy() {
1755
+ var _a;
1756
+ if (!((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type))
1757
+ return 'script';
1758
+ switch (this.framework.type) {
1759
+ case 'react':
1760
+ case 'nextjs':
1761
+ return 'provider';
1762
+ case 'vue':
1763
+ return 'plugin';
1764
+ case 'angular':
1765
+ return 'module';
1766
+ default:
1767
+ return 'script';
1768
+ }
1769
+ }
1770
+ }
1771
+
1772
+ /**
1773
+ * HumanBehavior SDK Auto-Installation CLI
1774
+ *
1775
+ * Usage: npx humanbehavior-js auto-install [api-key]
1776
+ *
1777
+ * This tool automatically detects the user's framework and modifies their codebase
1778
+ * to integrate the SDK with minimal user intervention.
1779
+ */
1780
+ class AutoInstallCLI {
1781
+ constructor(options) {
1782
+ this.options = options;
1783
+ }
1784
+ run() {
1785
+ return __awaiter(this, void 0, void 0, function* () {
1786
+ clack.intro('🚀 HumanBehavior SDK Auto-Installation');
1787
+ try {
1788
+ // Get API key
1789
+ const apiKey = yield this.getApiKey();
1790
+ if (!apiKey) {
1791
+ clack.cancel('API key is required');
1792
+ process.exit(1);
1793
+ }
1794
+ // Get project path
1795
+ const projectPath = this.options.projectPath || process.cwd();
1796
+ // Choose framework
1797
+ const framework = yield this.chooseFramework();
1798
+ if (!framework) {
1799
+ clack.cancel('Installation cancelled.');
1800
+ process.exit(0);
1801
+ }
1802
+ // Confirm installation
1803
+ if (!this.options.yes) {
1804
+ const confirmed = yield this.confirmInstallation(projectPath, framework);
1805
+ if (!confirmed) {
1806
+ clack.cancel('Installation cancelled.');
1807
+ process.exit(0);
1808
+ }
1809
+ }
1810
+ // Run installation
1811
+ const spinner = clack.spinner();
1812
+ spinner.start('🔍 Analyzing your project...');
1813
+ const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
1814
+ const result = yield wizard.install();
1815
+ spinner.stop('Detection complete!');
1816
+ // Display results
1817
+ this.displayResults(result);
1818
+ }
1819
+ catch (error) {
1820
+ clack.cancel(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
1821
+ process.exit(1);
1822
+ }
1823
+ });
1824
+ }
1825
+ getApiKey() {
1826
+ return __awaiter(this, void 0, void 0, function* () {
1827
+ if (this.options.apiKey) {
1828
+ return this.options.apiKey;
1829
+ }
1830
+ const apiKey = yield clack.text({
1831
+ message: 'Enter your HumanBehavior API key:',
1832
+ placeholder: 'hb_...',
1833
+ validate: (value) => {
1834
+ if (!value)
1835
+ return 'API key is required';
1836
+ if (!value.startsWith('hb_'))
1837
+ return 'API key should start with "hb_"';
1838
+ return undefined;
1839
+ }
1840
+ });
1841
+ return apiKey;
1842
+ });
1843
+ }
1844
+ chooseFramework() {
1845
+ return __awaiter(this, void 0, void 0, function* () {
1846
+ const framework = yield clack.select({
1847
+ message: 'Select your framework:',
1848
+ options: [
1849
+ { label: 'React', value: 'react' },
1850
+ { label: 'Next.js', value: 'nextjs' },
1851
+ { label: 'Vue', value: 'vue' },
1852
+ { label: 'Angular', value: 'angular' },
1853
+ { label: 'Svelte', value: 'svelte' },
1854
+ { label: 'Nuxt.js', value: 'nuxt' },
1855
+ { label: 'Remix', value: 'remix' },
1856
+ { label: 'Astro', value: 'astro' },
1857
+ { label: 'Gatsby', value: 'gatsby' },
1858
+ { label: 'Vanilla JS/TS', value: 'vanilla' }
1859
+ ]
1860
+ });
1861
+ return framework;
1862
+ });
1863
+ }
1864
+ confirmInstallation(projectPath, framework) {
1865
+ return __awaiter(this, void 0, void 0, function* () {
1866
+ const confirmed = yield clack.confirm({
1867
+ message: `Ready to install HumanBehavior SDK in ${projectPath} for ${framework}?`
1868
+ });
1869
+ return confirmed;
1870
+ });
1871
+ }
1872
+ displayResults(result) {
1873
+ if (result.success) {
1874
+ clack.outro('🎉 Installation completed successfully!');
1875
+ // Display framework info
1876
+ clack.note(`Framework detected: ${result.framework.name} (${result.framework.type})`, 'Framework Info');
1877
+ // Display modifications
1878
+ if (result.modifications && result.modifications.length > 0) {
1879
+ const modifications = result.modifications.map((mod) => `${mod.action}: ${mod.filePath} - ${mod.description}`);
1880
+ clack.note(modifications.join('\n'), 'Files Modified');
1881
+ }
1882
+ // Display next steps
1883
+ if (result.nextSteps && result.nextSteps.length > 0) {
1884
+ clack.note(result.nextSteps.join('\n'), 'Next Steps');
1885
+ }
1886
+ }
1887
+ else {
1888
+ clack.cancel('Installation failed');
1889
+ if (result.errors && result.errors.length > 0) {
1890
+ clack.note(result.errors.join('\n'), 'Errors');
1891
+ }
1892
+ }
1893
+ }
1894
+ }
1895
+ function parseArgs() {
1896
+ const args = process.argv.slice(2);
1897
+ const options = {};
1898
+ for (let i = 0; i < args.length; i++) {
1899
+ const arg = args[i];
1900
+ switch (arg) {
1901
+ case '--help':
1902
+ case '-h':
1903
+ showHelp();
1904
+ process.exit(0);
1905
+ break;
1906
+ case '--yes':
1907
+ case '-y':
1908
+ options.yes = true;
1909
+ break;
1910
+ case '--dry-run':
1911
+ options.dryRun = true;
1912
+ break;
1913
+ case '--project':
1914
+ case '-p':
1915
+ options.projectPath = args[++i];
1916
+ break;
1917
+ default:
1918
+ if (!options.apiKey && !arg.startsWith('-')) {
1919
+ options.apiKey = arg;
1920
+ }
1921
+ break;
1922
+ }
1923
+ }
1924
+ return options;
1925
+ }
1926
+ function showHelp() {
1927
+ console.log(`
1928
+ 🚀 HumanBehavior SDK Auto-Installation
1929
+
1930
+ Usage: npx humanbehavior-js auto-install [api-key] [options]
1931
+
1932
+ This tool automatically detects your framework and integrates the HumanBehavior SDK.
1933
+
1934
+ Options:
1935
+ -h, --help Show this help message
1936
+ -y, --yes Skip all prompts and use defaults
1937
+ --dry-run Show what would be changed without making changes
1938
+ -p, --project <path> Specify project directory
1939
+
1940
+ Examples:
1941
+ npx humanbehavior-js auto-install
1942
+ npx humanbehavior-js auto-install hb_your_api_key_here
1943
+ npx humanbehavior-js auto-install --project ./my-app --yes
1944
+ `);
1945
+ }
1946
+ // Main execution
1947
+ if (import.meta.url === `file://${process.argv[1]}`) {
1948
+ const options = parseArgs();
1949
+ const cli = new AutoInstallCLI(options);
1950
+ cli.run().catch((error) => {
1951
+ clack.cancel(`Unexpected error: ${error.message}`);
1952
+ process.exit(1);
1953
+ });
1954
+ }
1955
+
1956
+ export { AutoInstallCLI };
1957
+ //# sourceMappingURL=auto-install.js.map