humanbehavior-js 0.4.13 → 0.4.15

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.
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
- import * as readline from 'readline';
3
+ import * as clack from '@clack/prompts';
4
4
 
5
5
  /******************************************************************************
6
6
  Copyright (c) Microsoft Corporation.
@@ -46,6 +46,28 @@ class AutoInstallationWizard {
46
46
  this.apiKey = apiKey;
47
47
  this.projectRoot = projectRoot;
48
48
  }
49
+ /**
50
+ * Simple version comparison utility
51
+ */
52
+ compareVersions(version1, version2) {
53
+ const v1Parts = version1.split('.').map(Number);
54
+ const v2Parts = version2.split('.').map(Number);
55
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
56
+ const v1 = v1Parts[i] || 0;
57
+ const v2 = v2Parts[i] || 0;
58
+ if (v1 > v2)
59
+ return 1;
60
+ if (v1 < v2)
61
+ return -1;
62
+ }
63
+ return 0;
64
+ }
65
+ isVersionGte(version, target) {
66
+ return this.compareVersions(version, target) >= 0;
67
+ }
68
+ getMajorVersion(version) {
69
+ return parseInt(version.split('.')[0]) || 0;
70
+ }
49
71
  /**
50
72
  * Main installation method - detects framework and auto-installs
51
73
  */
@@ -95,73 +117,146 @@ class AutoInstallationWizard {
95
117
  }
96
118
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
97
119
  const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
98
- // Detect framework
120
+ // Detect framework with version information
99
121
  let framework = {
100
122
  name: 'vanilla',
101
123
  type: 'vanilla',
102
- projectRoot: this.projectRoot
124
+ projectRoot: this.projectRoot,
125
+ features: {}
103
126
  };
104
127
  if (dependencies.nuxt) {
128
+ const nuxtVersion = dependencies.nuxt;
129
+ const isNuxt3 = this.isVersionGte(nuxtVersion, '3.0.0');
105
130
  framework = {
106
131
  name: 'nuxt',
107
132
  type: 'nuxt',
133
+ version: nuxtVersion,
134
+ majorVersion: this.getMajorVersion(nuxtVersion),
108
135
  hasTypeScript: !!dependencies.typescript,
109
136
  hasRouter: true,
110
- projectRoot: this.projectRoot
137
+ projectRoot: this.projectRoot,
138
+ features: {
139
+ hasNuxt3: isNuxt3
140
+ }
111
141
  };
112
142
  }
113
143
  else if (dependencies.next) {
144
+ const nextVersion = dependencies.next;
145
+ const isNext13 = this.isVersionGte(nextVersion, '13.0.0');
114
146
  framework = {
115
147
  name: 'nextjs',
116
148
  type: 'nextjs',
149
+ version: nextVersion,
150
+ majorVersion: this.getMajorVersion(nextVersion),
117
151
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
118
152
  hasRouter: true,
119
- projectRoot: this.projectRoot
153
+ projectRoot: this.projectRoot,
154
+ features: {
155
+ hasNextAppRouter: isNext13
156
+ }
120
157
  };
121
158
  }
122
159
  else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
160
+ const remixVersion = dependencies['@remix-run/react'] || dependencies['@remix-run/dev'];
123
161
  framework = {
124
162
  name: 'remix',
125
163
  type: 'remix',
164
+ version: remixVersion,
165
+ majorVersion: this.getMajorVersion(remixVersion),
126
166
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
127
167
  hasRouter: true,
128
- projectRoot: this.projectRoot
168
+ projectRoot: this.projectRoot,
169
+ features: {}
129
170
  };
130
171
  }
131
172
  else if (dependencies.react) {
173
+ const reactVersion = dependencies.react;
174
+ const isReact18 = this.isVersionGte(reactVersion, '18.0.0');
132
175
  framework = {
133
176
  name: 'react',
134
177
  type: 'react',
178
+ version: reactVersion,
179
+ majorVersion: this.getMajorVersion(reactVersion),
135
180
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
136
181
  hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
137
- projectRoot: this.projectRoot
182
+ projectRoot: this.projectRoot,
183
+ features: {
184
+ hasReact18: isReact18
185
+ }
138
186
  };
139
187
  }
140
188
  else if (dependencies.vue) {
189
+ const vueVersion = dependencies.vue;
190
+ const isVue3 = this.isVersionGte(vueVersion, '3.0.0');
141
191
  framework = {
142
192
  name: 'vue',
143
193
  type: 'vue',
194
+ version: vueVersion,
195
+ majorVersion: this.getMajorVersion(vueVersion),
144
196
  hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
145
197
  hasRouter: !!dependencies['vue-router'],
146
- projectRoot: this.projectRoot
198
+ projectRoot: this.projectRoot,
199
+ features: {
200
+ hasVue3: isVue3
201
+ }
147
202
  };
148
203
  }
149
204
  else if (dependencies['@angular/core']) {
205
+ const angularVersion = dependencies['@angular/core'];
206
+ const isAngular17 = this.isVersionGte(angularVersion, '17.0.0');
150
207
  framework = {
151
208
  name: 'angular',
152
209
  type: 'angular',
210
+ version: angularVersion,
211
+ majorVersion: this.getMajorVersion(angularVersion),
153
212
  hasTypeScript: true,
154
213
  hasRouter: true,
155
- projectRoot: this.projectRoot
214
+ projectRoot: this.projectRoot,
215
+ features: {
216
+ hasAngularStandalone: isAngular17
217
+ }
156
218
  };
157
219
  }
158
220
  else if (dependencies.svelte) {
221
+ const svelteVersion = dependencies.svelte;
222
+ const isSvelteKit = !!dependencies['@sveltejs/kit'];
159
223
  framework = {
160
224
  name: 'svelte',
161
225
  type: 'svelte',
226
+ version: svelteVersion,
227
+ majorVersion: this.getMajorVersion(svelteVersion),
162
228
  hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
163
229
  hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
164
- projectRoot: this.projectRoot
230
+ projectRoot: this.projectRoot,
231
+ features: {
232
+ hasSvelteKit: isSvelteKit
233
+ }
234
+ };
235
+ }
236
+ else if (dependencies.astro) {
237
+ const astroVersion = dependencies.astro;
238
+ framework = {
239
+ name: 'astro',
240
+ type: 'astro',
241
+ version: astroVersion,
242
+ majorVersion: this.getMajorVersion(astroVersion),
243
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
244
+ hasRouter: true,
245
+ projectRoot: this.projectRoot,
246
+ features: {}
247
+ };
248
+ }
249
+ else if (dependencies.gatsby) {
250
+ const gatsbyVersion = dependencies.gatsby;
251
+ framework = {
252
+ name: 'gatsby',
253
+ type: 'gatsby',
254
+ version: gatsbyVersion,
255
+ majorVersion: this.getMajorVersion(gatsbyVersion),
256
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
257
+ hasRouter: true,
258
+ projectRoot: this.projectRoot,
259
+ features: {}
165
260
  };
166
261
  }
167
262
  // Detect bundler
@@ -195,13 +290,18 @@ class AutoInstallationWizard {
195
290
  */
196
291
  installPackage() {
197
292
  return __awaiter(this, void 0, void 0, function* () {
198
- var _a, _b;
293
+ var _a, _b, _c, _d;
199
294
  const { execSync } = yield import('child_process');
200
- const command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
295
+ // Build base command
296
+ let command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
201
297
  ? 'yarn add humanbehavior-js'
202
298
  : ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
203
299
  ? 'pnpm add humanbehavior-js'
204
300
  : 'npm install humanbehavior-js';
301
+ // Add legacy peer deps flag for npm to handle dependency conflicts
302
+ 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') {
303
+ command += ' --legacy-peer-deps';
304
+ }
205
305
  try {
206
306
  execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
207
307
  }
@@ -227,6 +327,12 @@ class AutoInstallationWizard {
227
327
  case 'nuxt':
228
328
  modifications.push(...yield this.generateNuxtModifications());
229
329
  break;
330
+ case 'astro':
331
+ modifications.push(...yield this.generateAstroModifications());
332
+ break;
333
+ case 'gatsby':
334
+ modifications.push(...yield this.generateGatsbyModifications());
335
+ break;
230
336
  case 'remix':
231
337
  modifications.push(...yield this.generateRemixModifications());
232
338
  break;
@@ -338,6 +444,84 @@ export function Providers({ children }: { children: React.ReactNode }) {
338
444
  return modifications;
339
445
  });
340
446
  }
447
+ /**
448
+ * Generate Astro-specific modifications
449
+ */
450
+ generateAstroModifications() {
451
+ return __awaiter(this, void 0, void 0, function* () {
452
+ const modifications = [];
453
+ // Create Astro component for HumanBehavior
454
+ const astroComponentPath = path.join(this.projectRoot, 'src', 'components', 'HumanBehavior.astro');
455
+ const astroComponentContent = `---
456
+ // This component will only run on the client side
457
+ ---
458
+
459
+ <script>
460
+ import { HumanBehaviorTracker } from 'humanbehavior-js';
461
+
462
+ // Get API key from environment variable
463
+ const apiKey = import.meta.env.PUBLIC_HUMANBEHAVIOR_API_KEY;
464
+
465
+ console.log('HumanBehavior: API key found:', apiKey ? 'Yes' : 'No');
466
+
467
+ if (apiKey) {
468
+ try {
469
+ const tracker = HumanBehaviorTracker.init(apiKey);
470
+ console.log('HumanBehavior: Tracker initialized successfully');
471
+
472
+ // Test event to verify tracking is working
473
+ setTimeout(() => {
474
+ tracker.customEvent('astro_page_view', {
475
+ page: window.location.pathname,
476
+ framework: 'astro'
477
+ }).then(() => {
478
+ console.log('HumanBehavior: Test event sent successfully');
479
+ }).catch((error) => {
480
+ console.error('HumanBehavior: Failed to send test event:', error);
481
+ });
482
+ }, 1000);
483
+
484
+ } catch (error) {
485
+ console.error('HumanBehavior: Failed to initialize tracker:', error);
486
+ }
487
+ } else {
488
+ console.error('HumanBehavior: No API key found');
489
+ }
490
+ </script>`;
491
+ modifications.push({
492
+ filePath: astroComponentPath,
493
+ action: 'create',
494
+ content: astroComponentContent,
495
+ description: 'Created Astro component for HumanBehavior SDK'
496
+ });
497
+ // Find and update layout file
498
+ const layoutFiles = [
499
+ path.join(this.projectRoot, 'src', 'layouts', 'Layout.astro'),
500
+ path.join(this.projectRoot, 'src', 'layouts', 'layout.astro'),
501
+ path.join(this.projectRoot, 'src', 'layouts', 'BaseLayout.astro')
502
+ ];
503
+ let layoutFile = null;
504
+ for (const file of layoutFiles) {
505
+ if (fs.existsSync(file)) {
506
+ layoutFile = file;
507
+ break;
508
+ }
509
+ }
510
+ if (layoutFile) {
511
+ const content = fs.readFileSync(layoutFile, 'utf8');
512
+ const modifiedContent = this.injectAstroLayout(content);
513
+ modifications.push({
514
+ filePath: layoutFile,
515
+ action: 'modify',
516
+ content: modifiedContent,
517
+ description: 'Added HumanBehavior component to Astro layout'
518
+ });
519
+ }
520
+ // Add environment variable
521
+ modifications.push(this.createEnvironmentModification(this.framework));
522
+ return modifications;
523
+ });
524
+ }
341
525
  /**
342
526
  * Generate Nuxt-specific modifications
343
527
  */
@@ -558,6 +742,50 @@ export default defineNuxtPlugin(() => {
558
742
  return modifications;
559
743
  });
560
744
  }
745
+ /**
746
+ * Generate Gatsby-specific modifications
747
+ */
748
+ generateGatsbyModifications() {
749
+ return __awaiter(this, void 0, void 0, function* () {
750
+ const modifications = [];
751
+ // Modify or create gatsby-browser.js for Gatsby
752
+ const gatsbyBrowserFile = path.join(this.projectRoot, 'gatsby-browser.js');
753
+ if (fs.existsSync(gatsbyBrowserFile)) {
754
+ const content = fs.readFileSync(gatsbyBrowserFile, 'utf8');
755
+ const modifiedContent = this.injectGatsbyBrowser(content);
756
+ modifications.push({
757
+ filePath: gatsbyBrowserFile,
758
+ action: 'modify',
759
+ content: modifiedContent,
760
+ description: 'Added HumanBehavior initialization to Gatsby browser'
761
+ });
762
+ }
763
+ else {
764
+ // Create gatsby-browser.js if it doesn't exist
765
+ modifications.push({
766
+ filePath: gatsbyBrowserFile,
767
+ action: 'create',
768
+ content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
769
+
770
+ export const onClientEntry = () => {
771
+ console.log('Gatsby browser entry point loaded');
772
+ const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
773
+ console.log('API Key found:', apiKey ? 'Yes' : 'No');
774
+ if (apiKey) {
775
+ const tracker = HumanBehaviorTracker.init(apiKey);
776
+ console.log('HumanBehavior SDK initialized for Gatsby');
777
+ } else {
778
+ console.log('No API key found in environment variables');
779
+ }
780
+ };`,
781
+ description: 'Created gatsby-browser.js with HumanBehavior initialization'
782
+ });
783
+ }
784
+ // Create or append to environment file
785
+ modifications.push(this.createEnvironmentModification(this.framework));
786
+ return modifications;
787
+ });
788
+ }
561
789
  /**
562
790
  * Apply modifications to the codebase
563
791
  */
@@ -652,7 +880,7 @@ export default defineNuxtPlugin(() => {
652
880
  return null;
653
881
  }
654
882
  injectReactProvider(content, filePath) {
655
- var _a;
883
+ var _a, _b, _c;
656
884
  filePath.endsWith('.tsx') || filePath.endsWith('.ts');
657
885
  // Check if already has HumanBehaviorProvider
658
886
  if (content.includes('HumanBehaviorProvider')) {
@@ -664,14 +892,39 @@ export default defineNuxtPlugin(() => {
664
892
  ? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
665
893
  : 'process.env.HUMANBEHAVIOR_API_KEY!';
666
894
  const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
667
- // Simple injection - in production, you'd want more sophisticated parsing
895
+ // Enhanced parsing for React 18+ features
896
+ const hasReact18 = (_c = (_b = this.framework) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.hasReact18;
897
+ // Handle different React patterns
668
898
  if (content.includes('function App()') || content.includes('const App =')) {
669
- return content.replace(/(function App\(\)|const App =)/, `${importStatement}\n\n$1`).replace(/return \(([\s\S]*?)\);/, `return (
899
+ // Add import statement
900
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
901
+ // If no React import found, add it at the top
902
+ if (!modifiedContent.includes(importStatement)) {
903
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
904
+ }
905
+ // Wrap the App component return with HumanBehaviorProvider
906
+ modifiedContent = modifiedContent.replace(/(return\s*\([\s\S]*?\)\s*;)/, `return (
670
907
  <HumanBehaviorProvider apiKey={${envVar}}>
671
908
  $1
672
909
  </HumanBehaviorProvider>
673
910
  );`);
911
+ return modifiedContent;
674
912
  }
913
+ // Handle React 18+ createRoot pattern
914
+ if (hasReact18 && content.includes('createRoot')) {
915
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
916
+ if (!modifiedContent.includes(importStatement)) {
917
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
918
+ }
919
+ // Wrap the root render with HumanBehaviorProvider
920
+ modifiedContent = modifiedContent.replace(/(root\.render\s*\([\s\S]*?\)\s*;)/, `root.render(
921
+ <HumanBehaviorProvider apiKey={${envVar}}>
922
+ $1
923
+ </HumanBehaviorProvider>
924
+ );`);
925
+ return modifiedContent;
926
+ }
927
+ // Fallback: simple injection
675
928
  return `${importStatement}\n\n${content}`;
676
929
  }
677
930
  injectNextJSAppRouter(content) {
@@ -768,21 +1021,51 @@ export default function App()`);
768
1021
  return modifiedContent;
769
1022
  }
770
1023
  injectVuePlugin(content) {
1024
+ var _a, _b;
771
1025
  if (content.includes('HumanBehaviorPlugin')) {
772
1026
  return content;
773
1027
  }
774
1028
  const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
775
- const pluginUsage = `app.use(HumanBehaviorPlugin, {
1029
+ // Enhanced Vue 3 support with version detection
1030
+ const hasVue3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasVue3;
1031
+ if (hasVue3) {
1032
+ // Vue 3 with Composition API
1033
+ const pluginUsage = `app.use(HumanBehaviorPlugin, {
776
1034
  apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
777
1035
  });`;
778
- // Handle both Vue 2 and Vue 3 patterns
779
- if (content.includes('createApp')) {
780
- // Vue 3
781
- return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/app\.mount\(/, `${pluginUsage}\n\napp.mount(`);
1036
+ let modifiedContent = content;
1037
+ // Add import statement
1038
+ if (!content.includes(importStatement)) {
1039
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1040
+ // If no Vue import found, add it at the top
1041
+ if (!modifiedContent.includes(importStatement)) {
1042
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1043
+ }
1044
+ }
1045
+ // Handle createApp pattern
1046
+ if (content.includes('createApp')) {
1047
+ modifiedContent = modifiedContent.replace(/(app\.mount\(.*?\))/, `${pluginUsage}\n\n$1`);
1048
+ }
1049
+ return modifiedContent;
782
1050
  }
783
1051
  else {
784
- // Vue 2
785
- return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/new Vue\(/, `${pluginUsage}\n\nnew Vue(`);
1052
+ // Vue 2 with Options API
1053
+ const pluginUsage = `Vue.use(HumanBehaviorPlugin, {
1054
+ apiKey: process.env.VUE_APP_HUMANBEHAVIOR_API_KEY
1055
+ });`;
1056
+ let modifiedContent = content;
1057
+ // Add import statement
1058
+ if (!content.includes(importStatement)) {
1059
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1060
+ if (!modifiedContent.includes(importStatement)) {
1061
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1062
+ }
1063
+ }
1064
+ // Handle new Vue pattern
1065
+ if (content.includes('new Vue')) {
1066
+ modifiedContent = modifiedContent.replace(/(new Vue\(.*?\))/, `${pluginUsage}\n\n$1`);
1067
+ }
1068
+ return modifiedContent;
786
1069
  }
787
1070
  }
788
1071
  injectAngularModule(content) {
@@ -863,17 +1146,99 @@ if (typeof window !== 'undefined') {
863
1146
  </script>`;
864
1147
  return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
865
1148
  }
1149
+ /**
1150
+ * Inject Astro layout with HumanBehavior component
1151
+ */
1152
+ injectAstroLayout(content) {
1153
+ // Check if HumanBehavior component is already imported
1154
+ if (content.includes('HumanBehavior') || content.includes('humanbehavior-js')) {
1155
+ return content; // Already has HumanBehavior
1156
+ }
1157
+ // Add import inside frontmatter if not present
1158
+ let modifiedContent = content;
1159
+ if (!content.includes('import HumanBehavior')) {
1160
+ const importStatement = 'import HumanBehavior from \'../components/HumanBehavior.astro\';';
1161
+ const frontmatterEndIndex = content.indexOf('---', 3);
1162
+ if (frontmatterEndIndex !== -1) {
1163
+ // Insert import inside frontmatter, before the closing ---
1164
+ modifiedContent = content.slice(0, frontmatterEndIndex) + '\n' + importStatement + '\n' + content.slice(frontmatterEndIndex);
1165
+ }
1166
+ else {
1167
+ // No frontmatter, add at the very beginning
1168
+ modifiedContent = '---\n' + importStatement + '\n---\n\n' + content;
1169
+ }
1170
+ }
1171
+ // Find the closing </body> tag and add HumanBehavior component before it
1172
+ const bodyCloseIndex = modifiedContent.lastIndexOf('</body>');
1173
+ if (bodyCloseIndex === -1) {
1174
+ // No body tag found, append to end
1175
+ return modifiedContent + '\n\n<HumanBehavior />';
1176
+ }
1177
+ // Add component before closing body tag
1178
+ return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
1179
+ }
866
1180
  injectNuxtConfig(content) {
1181
+ var _a, _b;
867
1182
  if (content.includes('humanBehaviorApiKey')) {
868
1183
  return content;
869
1184
  }
870
- // Add runtime config by inserting it after the opening brace
871
- return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
1185
+ // Enhanced Nuxt 3 support with version detection
1186
+ const hasNuxt3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasNuxt3;
1187
+ if (hasNuxt3) {
1188
+ // Nuxt 3 with runtime config
1189
+ return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
872
1190
  runtimeConfig: {
873
1191
  public: {
874
1192
  humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
875
1193
  }
876
1194
  },`);
1195
+ }
1196
+ else {
1197
+ // Nuxt 2 with env config
1198
+ return content.replace(/export default \{/, `export default {
1199
+ env: {
1200
+ humanBehaviorApiKey: process.env.HUMANBEHAVIOR_API_KEY
1201
+ },`);
1202
+ }
1203
+ }
1204
+ injectGatsbyLayout(content) {
1205
+ if (content.includes('HumanBehavior')) {
1206
+ return content;
1207
+ }
1208
+ const importStatement = `import HumanBehavior from './HumanBehavior';`;
1209
+ const componentUsage = `<HumanBehavior apiKey={process.env.GATSBY_HUMANBEHAVIOR_API_KEY || ''} />`;
1210
+ // Add import at the top
1211
+ let modifiedContent = content.replace(/import.*from.*['"]\./, `${importStatement}\n$&`);
1212
+ // Add component before closing body tag
1213
+ modifiedContent = modifiedContent.replace(/(\s*<\/body>)/, `\n ${componentUsage}\n$1`);
1214
+ return modifiedContent;
1215
+ }
1216
+ injectGatsbyBrowser(content) {
1217
+ if (content.includes('HumanBehaviorTracker')) {
1218
+ return content;
1219
+ }
1220
+ const importStatement = `import { HumanBehaviorTracker } from 'humanbehavior-js';`;
1221
+ const initCode = `
1222
+ // Initialize HumanBehavior SDK
1223
+ export const onClientEntry = () => {
1224
+ console.log('Gatsby browser entry point loaded');
1225
+ const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
1226
+ console.log('API Key found:', apiKey ? 'Yes' : 'No');
1227
+ if (apiKey) {
1228
+ const tracker = HumanBehaviorTracker.init(apiKey);
1229
+ console.log('HumanBehavior SDK initialized for Gatsby');
1230
+ } else {
1231
+ console.log('No API key found in environment variables');
1232
+ }
1233
+ };`;
1234
+ // If the file already has content, add the import and init code
1235
+ if (content.trim()) {
1236
+ return `${importStatement}${initCode}\n\n${content}`;
1237
+ }
1238
+ else {
1239
+ // If file is empty, just return the new content
1240
+ return `${importStatement}${initCode}`;
1241
+ }
877
1242
  }
878
1243
  /**
879
1244
  * Helper method to find the best environment file for a framework
@@ -904,6 +1269,8 @@ if (typeof window !== 'undefined') {
904
1269
  nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
905
1270
  remix: 'HUMANBEHAVIOR_API_KEY',
906
1271
  vanilla: 'HUMANBEHAVIOR_API_KEY',
1272
+ astro: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
1273
+ gatsby: 'GATSBY_HUMANBEHAVIOR_API_KEY',
907
1274
  node: 'HUMANBEHAVIOR_API_KEY',
908
1275
  auto: 'HUMANBEHAVIOR_API_KEY'
909
1276
  };
@@ -927,6 +1294,8 @@ if (typeof window !== 'undefined') {
927
1294
  nuxt: '.env',
928
1295
  remix: '.env.local',
929
1296
  vanilla: '.env',
1297
+ astro: '.env',
1298
+ gatsby: '.env.development',
930
1299
  node: '.env',
931
1300
  auto: '.env'
932
1301
  };
@@ -941,6 +1310,8 @@ if (typeof window !== 'undefined') {
941
1310
  */
942
1311
  createEnvironmentModification(framework) {
943
1312
  const { filePath, envVarName } = this.findBestEnvFile(framework);
1313
+ // Clean the API key to prevent formatting issues
1314
+ const cleanApiKey = this.apiKey.trim();
944
1315
  if (fs.existsSync(filePath)) {
945
1316
  // Check if the variable already exists
946
1317
  const content = fs.readFileSync(filePath, 'utf8');
@@ -958,7 +1329,7 @@ if (typeof window !== 'undefined') {
958
1329
  return {
959
1330
  filePath,
960
1331
  action: 'append',
961
- content: `\n${envVarName}=${this.apiKey}`,
1332
+ content: `\n${envVarName}=${cleanApiKey}`,
962
1333
  description: `Added API key to existing ${path.basename(filePath)}`
963
1334
  };
964
1335
  }
@@ -968,7 +1339,7 @@ if (typeof window !== 'undefined') {
968
1339
  return {
969
1340
  filePath,
970
1341
  action: 'create',
971
- content: `${envVarName}=${this.apiKey}`,
1342
+ content: `${envVarName}=${cleanApiKey}`,
972
1343
  description: `Created ${path.basename(filePath)} with API key`
973
1344
  };
974
1345
  }
@@ -1064,6 +1435,10 @@ class DefaultAIService {
1064
1435
  framework = { name: 'nextjs', type: 'nextjs' };
1065
1436
  confidence = 0.95;
1066
1437
  }
1438
+ 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')) {
1439
+ framework = { name: 'gatsby', type: 'gatsby' };
1440
+ confidence = 0.95;
1441
+ }
1067
1442
  else if (patterns.includes('react')) {
1068
1443
  framework = { name: 'react', type: 'react' };
1069
1444
  confidence = 0.9;
@@ -1082,7 +1457,7 @@ class DefaultAIService {
1082
1457
  }
1083
1458
  // Integration strategy
1084
1459
  let integrationStrategy = 'script';
1085
- if (framework.type === 'react' || framework.type === 'nextjs') {
1460
+ if (framework.type === 'react' || framework.type === 'nextjs' || framework.type === 'gatsby') {
1086
1461
  integrationStrategy = 'provider';
1087
1462
  }
1088
1463
  else if (framework.type === 'vue') {
@@ -1877,6 +2252,10 @@ class RemoteAIService {
1877
2252
  framework = { name: 'nextjs', type: 'nextjs' };
1878
2253
  confidence = 0.95;
1879
2254
  }
2255
+ 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')) {
2256
+ framework = { name: 'gatsby', type: 'gatsby' };
2257
+ confidence = 0.95;
2258
+ }
1880
2259
  else if (patterns.includes('react')) {
1881
2260
  framework = { name: 'react', type: 'react' };
1882
2261
  confidence = 0.9;
@@ -1893,9 +2272,13 @@ class RemoteAIService {
1893
2272
  framework = { name: 'svelte', type: 'svelte' };
1894
2273
  confidence = 0.9;
1895
2274
  }
2275
+ else if (patterns.includes('astro')) {
2276
+ framework = { name: 'astro', type: 'astro' };
2277
+ confidence = 0.9;
2278
+ }
1896
2279
  // Integration strategy
1897
2280
  let integrationStrategy = 'script';
1898
- if (framework.type === 'react' || framework.type === 'nextjs') {
2281
+ if (framework.type === 'react' || framework.type === 'nextjs' || framework.type === 'gatsby') {
1899
2282
  integrationStrategy = 'provider';
1900
2283
  }
1901
2284
  else if (framework.type === 'vue') {
@@ -2138,6 +2521,8 @@ class ManualFrameworkInstallationWizard extends AutoInstallationWizard {
2138
2521
  'svelte': { name: 'svelte', type: 'svelte' },
2139
2522
  'sveltekit': { name: 'svelte', type: 'svelte' },
2140
2523
  'remix': { name: 'remix', type: 'remix' },
2524
+ 'astro': { name: 'astro', type: 'astro' },
2525
+ 'gatsby': { name: 'gatsby', type: 'gatsby' },
2141
2526
  'vanilla': { name: 'vanilla', type: 'vanilla' },
2142
2527
  'node': { name: 'node', type: 'node' },
2143
2528
  'auto': { name: 'auto-detected', type: 'auto' }
@@ -2197,67 +2582,46 @@ class ManualFrameworkInstallationWizard extends AutoInstallationWizard {
2197
2582
  class AIAutoInstallCLI {
2198
2583
  constructor(options) {
2199
2584
  this.options = options;
2200
- this.rl = readline.createInterface({
2201
- input: process.stdin,
2202
- output: process.stdout
2203
- });
2204
2585
  }
2205
2586
  run() {
2206
2587
  return __awaiter(this, void 0, void 0, function* () {
2207
- console.log('šŸ¤– AI-Enhanced HumanBehavior SDK Auto-Installation');
2208
- console.log('================================================\n');
2588
+ clack.intro('šŸ¤– AI-Enhanced HumanBehavior SDK Auto-Installation');
2209
2589
  try {
2210
2590
  // Get API key
2211
2591
  const apiKey = yield this.getApiKey();
2212
2592
  if (!apiKey) {
2213
- console.error('āŒ API key is required');
2593
+ clack.cancel('API key is required');
2214
2594
  process.exit(1);
2215
2595
  }
2216
2596
  // Get project path
2217
2597
  const projectPath = this.options.projectPath || process.cwd();
2218
- // Choose installation mode
2219
- const installationMode = yield this.chooseInstallationMode();
2598
+ // Choose framework
2599
+ const framework = yield this.chooseFramework();
2600
+ if (!framework) {
2601
+ clack.cancel('Installation cancelled.');
2602
+ process.exit(0);
2603
+ }
2220
2604
  // Confirm installation
2221
2605
  if (!this.options.yes) {
2222
- const confirmed = yield this.confirmInstallation(projectPath, installationMode);
2606
+ const confirmed = yield this.confirmInstallation(projectPath, framework);
2223
2607
  if (!confirmed) {
2224
- console.log('Installation cancelled.');
2608
+ clack.cancel('Installation cancelled.');
2225
2609
  process.exit(0);
2226
2610
  }
2227
2611
  }
2228
2612
  // Run installation
2229
- console.log('šŸ” Analyzing your project with AI...');
2230
- let result;
2231
- if (this.options.browser) {
2232
- const wizard = new AIBrowserInstallationWizard(apiKey);
2233
- result = yield wizard.install();
2234
- }
2235
- else if (installationMode === 'manual') {
2236
- // Manual AI-Enhanced framework selection
2237
- const framework = yield this.chooseFramework();
2238
- const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
2239
- result = yield wizard.install();
2240
- }
2241
- else if (installationMode.startsWith('manual:')) {
2242
- // Manual framework selection with pre-selected framework
2243
- const framework = installationMode.split(':')[1];
2244
- const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
2245
- result = yield wizard.install();
2246
- }
2247
- else {
2248
- const wizard = new AutoInstallationWizard(apiKey, projectPath);
2249
- result = yield wizard.install();
2250
- }
2613
+ const spinner = clack.spinner();
2614
+ spinner.start('šŸ” Analyzing your project with AI...');
2615
+ const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
2616
+ const result = yield wizard.install();
2617
+ spinner.stop('Analysis complete!');
2251
2618
  // Display results
2252
- this.displayResults(result, installationMode);
2619
+ this.displayResults(result, framework);
2253
2620
  }
2254
2621
  catch (error) {
2255
- console.error('āŒ Error:', error instanceof Error ? error.message : error);
2622
+ clack.cancel(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
2256
2623
  process.exit(1);
2257
2624
  }
2258
- finally {
2259
- this.rl.close();
2260
- }
2261
2625
  });
2262
2626
  }
2263
2627
  getApiKey() {
@@ -2265,262 +2629,143 @@ class AIAutoInstallCLI {
2265
2629
  if (this.options.apiKey) {
2266
2630
  return this.options.apiKey;
2267
2631
  }
2268
- return new Promise((resolve) => {
2269
- this.rl.question('Enter your HumanBehavior API key: ', (answer) => {
2270
- resolve(answer.trim());
2271
- });
2272
- });
2273
- });
2274
- }
2275
- chooseInstallationMode() {
2276
- return __awaiter(this, void 0, void 0, function* () {
2277
- if (this.options.manual && this.options.framework) {
2278
- return `manual:${this.options.framework}`;
2279
- }
2280
- if (this.options.useAI !== undefined) {
2281
- return this.options.useAI ? 'ai' : 'traditional';
2282
- }
2283
- console.log('šŸ¤– Choose installation mode:');
2284
- console.log('1. Manual AI-Enhanced (recommended) - Choose your framework and use AI for optimization');
2285
- console.log('2. Traditional - Standard framework detection and installation');
2286
- console.log('3. Browser - Browser-based AI detection and code generation\n');
2287
- return new Promise((resolve) => {
2288
- this.rl.question('Select mode (1-3, default: 1): ', (answer) => {
2289
- const choice = answer.trim() || '1';
2290
- if (choice === '1')
2291
- resolve('manual');
2292
- else if (choice === '2')
2293
- resolve('traditional');
2294
- else if (choice === '3')
2295
- resolve('browser');
2296
- else
2297
- resolve('manual');
2298
- });
2632
+ const apiKey = yield clack.text({
2633
+ message: 'Enter your HumanBehavior API key:',
2634
+ placeholder: 'hb_...',
2635
+ validate: (value) => {
2636
+ if (!value)
2637
+ return 'API key is required';
2638
+ if (!value.startsWith('hb_'))
2639
+ return 'API key should start with "hb_"';
2640
+ return undefined;
2641
+ }
2299
2642
  });
2643
+ return apiKey;
2300
2644
  });
2301
2645
  }
2302
- confirmInstallation(projectPath, installationMode) {
2646
+ confirmInstallation(projectPath, framework) {
2303
2647
  return __awaiter(this, void 0, void 0, function* () {
2304
- console.log(`šŸ“ Project path: ${projectPath}`);
2305
- console.log(`šŸ¤– Installation mode: ${this.getInstallationModeDisplay(installationMode)}`);
2306
- console.log('āš ļø This will modify your codebase to integrate HumanBehavior SDK.');
2307
- console.log(' The following changes will be made:');
2308
- console.log(' - Install humanbehavior-js package');
2309
- console.log(' - Analyze code patterns with AI (if enabled)');
2310
- console.log(' - Modify your main app file');
2311
- console.log(' - Create environment files');
2312
- console.log(' - Add AI-optimized SDK initialization code\n');
2313
- return new Promise((resolve) => {
2314
- this.rl.question('Continue with installation? (y/n): ', (answer) => {
2315
- resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
2316
- });
2648
+ const confirmed = yield clack.confirm({
2649
+ message: `Ready to install HumanBehavior SDK in ${projectPath} for ${framework}?`
2317
2650
  });
2651
+ return confirmed;
2318
2652
  });
2319
2653
  }
2320
- getInstallationModeDisplay(mode) {
2321
- if (mode === 'manual')
2322
- return 'Manual AI-Enhanced';
2323
- if (mode === 'traditional')
2324
- return 'Traditional';
2325
- if (mode.startsWith('manual:')) {
2326
- const framework = mode.split(':')[1];
2327
- return `Manual AI-Enhanced (${framework})`;
2328
- }
2329
- if (mode === 'browser')
2330
- return 'Browser';
2331
- return 'Unknown';
2332
- }
2333
2654
  chooseFramework() {
2334
2655
  return __awaiter(this, void 0, void 0, function* () {
2335
- console.log('\nšŸŽÆ Choose your framework:');
2336
- console.log('1. Vanilla JS (HTML)');
2337
- console.log('2. React');
2338
- console.log('3. Next.js');
2339
- console.log('4. Vue');
2340
- console.log('5. Nuxt');
2341
- console.log('6. Angular');
2342
- console.log('7. Svelte');
2343
- console.log('8. Remix');
2344
- console.log('9. Node.js');
2345
- console.log('10. Other (Auto-detect)\n');
2346
- return new Promise((resolve) => {
2347
- this.rl.question('Select framework (1-10, default: 1): ', (answer) => {
2348
- const choice = answer.trim() || '1';
2349
- const frameworks = ['vanilla', 'react', 'nextjs', 'vue', 'nuxt', 'angular', 'svelte', 'remix', 'node', 'auto'];
2350
- const index = parseInt(choice) - 1;
2351
- resolve(frameworks[index] || 'vanilla');
2352
- });
2656
+ const framework = yield clack.select({
2657
+ message: 'Select your framework:',
2658
+ options: [
2659
+ { label: 'React', value: 'react' },
2660
+ { label: 'Next.js', value: 'nextjs' },
2661
+ { label: 'Vue', value: 'vue' },
2662
+ { label: 'Angular', value: 'angular' },
2663
+ { label: 'Svelte', value: 'svelte' },
2664
+ { label: 'Nuxt.js', value: 'nuxt' },
2665
+ { label: 'Remix', value: 'remix' },
2666
+ { label: 'Astro', value: 'astro' },
2667
+ { label: 'Gatsby', value: 'gatsby' },
2668
+ { label: 'Vanilla JS/TS', value: 'vanilla' }
2669
+ ]
2353
2670
  });
2671
+ return framework;
2354
2672
  });
2355
2673
  }
2356
- displayResults(result, installationMode) {
2674
+ displayResults(result, framework) {
2357
2675
  if (result.success) {
2358
- console.log('\nāœ… Installation completed successfully!');
2359
- if (installationMode === 'ai' && result.aiAnalysis) {
2360
- console.log(`šŸŽÆ AI Analysis Results:`);
2361
- console.log(` Framework: ${result.aiAnalysis.framework.name} (confidence: ${Math.round(result.aiAnalysis.confidence * 100)}%)`);
2362
- console.log(` Integration Strategy: ${result.aiAnalysis.integrationStrategy}`);
2363
- console.log(` Compatibility Mode: ${result.aiAnalysis.compatibilityMode}`);
2364
- if (result.aiAnalysis.patterns.length > 0) {
2365
- console.log(` Detected Patterns: ${result.aiAnalysis.patterns.length} patterns`);
2366
- }
2367
- if (result.aiAnalysis.recommendations.length > 0) {
2368
- console.log(` AI Recommendations:`);
2369
- result.aiAnalysis.recommendations.forEach((rec) => {
2370
- console.log(` • ${rec}`);
2371
- });
2676
+ clack.outro('šŸŽ‰ Installation completed successfully!');
2677
+ // Display framework info
2678
+ clack.note(`Framework detected: ${result.framework.name} (${result.framework.type})`, 'Framework Info');
2679
+ // Display modifications
2680
+ if (result.modifications && result.modifications.length > 0) {
2681
+ const modifications = result.modifications.map((mod) => `${mod.action}: ${mod.filePath} - ${mod.description}`);
2682
+ clack.note(modifications.join('\n'), 'Files Modified');
2683
+ }
2684
+ // Display next steps
2685
+ if (result.nextSteps && result.nextSteps.length > 0) {
2686
+ clack.note(result.nextSteps.join('\n'), 'Next Steps');
2687
+ }
2688
+ // Display AI insights if available
2689
+ if (result.aiAnalysis) {
2690
+ clack.note(`Confidence: ${Math.round(result.aiAnalysis.confidence * 100)}%`, 'AI Analysis');
2691
+ if (result.aiAnalysis.recommendations && result.aiAnalysis.recommendations.length > 0) {
2692
+ clack.note(result.aiAnalysis.recommendations.join('\n'), 'AI Recommendations');
2372
2693
  }
2373
2694
  }
2374
- else {
2375
- console.log(`šŸ“¦ Framework detected: ${result.framework.name}`);
2376
- }
2377
- if (result.framework.bundler) {
2378
- console.log(`šŸ”§ Bundler: ${result.framework.bundler}`);
2379
- }
2380
- if (result.framework.packageManager) {
2381
- console.log(`šŸ“‹ Package Manager: ${result.framework.packageManager}`);
2382
- }
2383
- console.log('\nšŸ“ Changes made:');
2384
- result.modifications.forEach((mod) => {
2385
- console.log(` ${mod.action === 'create' ? 'āž•' : 'āœļø'} ${mod.description}`);
2386
- console.log(` ${mod.filePath}`);
2387
- });
2388
- console.log('\nšŸŽÆ Next steps:');
2389
- result.nextSteps.forEach((step) => {
2390
- console.log(` ${step}`);
2391
- });
2392
- if (installationMode === 'ai' && result.learningData) {
2393
- console.log('\n🧠 Learning Data:');
2394
- console.log(` Framework: ${result.learningData.framework}`);
2395
- console.log(` Patterns: ${result.learningData.patterns.length} detected`);
2396
- console.log(` Success: ${result.learningData.success ? 'Yes' : 'No'}`);
2397
- }
2398
- console.log('\nšŸš€ Your app is now ready to track user behavior!');
2399
- console.log('šŸ“Š View sessions in your HumanBehavior dashboard');
2400
2695
  }
2401
2696
  else {
2402
- console.log('\nāŒ Installation failed:');
2403
- result.errors.forEach((error) => {
2404
- console.log(` ${error}`);
2405
- });
2406
- console.log('\nšŸ’” Try running with --help for more options');
2697
+ clack.cancel('Installation failed');
2698
+ if (result.errors && result.errors.length > 0) {
2699
+ clack.note(result.errors.join('\n'), 'Errors');
2700
+ }
2407
2701
  }
2408
2702
  }
2409
2703
  }
2410
- // CLI argument parsing
2411
2704
  function parseArgs$1() {
2412
2705
  const args = process.argv.slice(2);
2413
2706
  const options = {};
2414
2707
  for (let i = 0; i < args.length; i++) {
2415
2708
  const arg = args[i];
2416
- if (arg === '--yes' || arg === '-y') {
2417
- options.yes = true;
2418
- }
2419
- else if (arg === '--dry-run' || arg === '-d') {
2420
- options.dryRun = true;
2421
- }
2422
- else if (arg === '--project' || arg === '-p') {
2423
- options.projectPath = args[i + 1];
2424
- i++;
2425
- }
2426
- else if (arg === '--traditional' || arg === '-t') {
2427
- options.useAI = false;
2428
- }
2429
- else if (arg === '--browser' || arg === '-b') {
2430
- options.browser = true;
2431
- }
2432
- else if (arg === '--manual' || arg === '-m') {
2433
- options.manual = true;
2434
- }
2435
- else if (arg === '--framework' || arg === '-f') {
2436
- options.framework = args[i + 1];
2437
- i++;
2438
- }
2439
- else if (arg === '--help' || arg === '-h') {
2440
- showHelp$1();
2441
- process.exit(0);
2442
- }
2443
- else if (!options.apiKey) {
2444
- options.apiKey = arg;
2709
+ switch (arg) {
2710
+ case '--help':
2711
+ case '-h':
2712
+ showHelp$1();
2713
+ process.exit(0);
2714
+ break;
2715
+ case '--yes':
2716
+ case '-y':
2717
+ options.yes = true;
2718
+ break;
2719
+ case '--dry-run':
2720
+ options.dryRun = true;
2721
+ break;
2722
+ case '--project':
2723
+ case '-p':
2724
+ options.projectPath = args[++i];
2725
+ break;
2726
+ case '--framework':
2727
+ case '-f':
2728
+ options.framework = args[++i];
2729
+ break;
2730
+ default:
2731
+ if (!options.apiKey && !arg.startsWith('-')) {
2732
+ options.apiKey = arg;
2733
+ }
2734
+ break;
2445
2735
  }
2446
2736
  }
2447
2737
  return options;
2448
2738
  }
2449
2739
  function showHelp$1() {
2450
2740
  console.log(`
2451
- AI-Enhanced HumanBehavior SDK Auto-Installation CLI
2741
+ šŸ¤– HumanBehavior SDK AI Auto-Installation
2452
2742
 
2453
2743
  Usage: npx humanbehavior-js ai-auto-install [api-key] [options]
2454
2744
 
2455
- This tool uses AI to intelligently detect frameworks, analyze code patterns,
2456
- and generate optimal integration code that's both future-proof and backward-compatible.
2457
-
2458
- Arguments:
2459
- api-key Your HumanBehavior API key
2460
-
2461
2745
  Options:
2462
- -y, --yes Skip all prompts and use defaults
2463
- -d, --dry-run Show what would be changed without making changes
2464
- -p, --project <path> Project directory (default: current directory)
2465
- -t, --traditional Force traditional installation mode
2466
- -b, --browser Browser-based AI installation
2467
- -m, --manual Manual framework selection
2468
- -f, --framework <f> Specify framework for manual mode
2469
- -h, --help Show this help message
2746
+ -h, --help Show this help message
2747
+ -y, --yes Skip all prompts and use defaults
2748
+ --dry-run Show what would be changed without making changes
2470
2749
 
2471
- Installation Modes:
2472
- 1. Manual AI-Enhanced (default): Choose your framework and use AI for optimization
2473
- 2. Traditional: Standard framework detection and installation
2474
- 3. Browser: Browser-based AI detection and code generation
2750
+ -p, --project <path> Specify project directory
2751
+ -f, --framework <name> Specify framework manually
2475
2752
 
2476
2753
  Examples:
2477
- npx humanbehavior-js ai-auto-install your-api-key
2478
- npx humanbehavior-js ai-auto-install your-api-key --manual --framework react
2479
- npx humanbehavior-js ai-auto-install your-api-key --traditional
2480
- npx humanbehavior-js ai-auto-install your-api-key --browser
2481
-
2482
- Supported Frameworks:
2483
- āœ… React (CRA, Vite, Webpack)
2484
- āœ… Next.js (App Router, Pages Router)
2485
- āœ… Vue (Vue CLI, Vite)
2486
- āœ… Angular
2487
- āœ… Svelte (SvelteKit, Vite)
2488
- āœ… Remix
2489
- āœ… Vanilla JS/TS
2490
- āœ… Node.js (CommonJS & ESM)
2491
-
2492
- AI Features:
2493
- šŸ” Intelligent framework detection beyond package.json
2494
- šŸ“Š Code pattern analysis and optimization
2495
- šŸ”„ Future-proof integration strategies
2496
- šŸ”™ Backward compatibility with legacy frameworks
2497
- 🧠 Learning from installation patterns
2498
- ⚔ Adaptive code generation for new frameworks
2499
- šŸ”§ Smart conflict resolution
2500
- šŸ“ˆ Performance optimization recommendations
2501
-
2502
- The AI-enhanced tool will:
2503
- 1. šŸ” Analyze your codebase with AI to detect patterns
2504
- 2. šŸŽÆ Determine optimal integration strategy
2505
- 3. šŸ“¦ Install the humanbehavior-js package
2506
- 4. āœļø Generate AI-optimized integration code
2507
- 5. šŸ”§ Apply modifications with conflict resolution
2508
- 6. 🧠 Learn from the installation for future improvements
2509
- 7. šŸš€ Make your app ready to track user behavior
2754
+ npx humanbehavior-js ai-auto-install
2755
+ npx humanbehavior-js ai-auto-install hb_your_api_key_here
2756
+ npx humanbehavior-js ai-auto-install --project ./my-app --ai
2757
+ npx humanbehavior-js ai-auto-install --framework react --yes
2510
2758
  `);
2511
2759
  }
2512
2760
  // Main execution
2513
- const options$1 = parseArgs$1();
2514
- // Check if we have enough arguments (api-key is required)
2515
- if (process.argv.length < 3 || process.argv.includes('--help') || process.argv.includes('-h')) {
2516
- showHelp$1();
2517
- process.exit(0);
2761
+ if (import.meta.url === `file://${process.argv[1]}`) {
2762
+ const options = parseArgs$1();
2763
+ const cli = new AIAutoInstallCLI(options);
2764
+ cli.run().catch((error) => {
2765
+ clack.cancel(`Unexpected error: ${error.message}`);
2766
+ process.exit(1);
2767
+ });
2518
2768
  }
2519
- const cli$1 = new AIAutoInstallCLI(options$1);
2520
- cli$1.run().catch((error) => {
2521
- console.error('āŒ Fatal error:', error);
2522
- process.exit(1);
2523
- });
2524
2769
 
2525
2770
  /**
2526
2771
  * HumanBehavior SDK Auto-Installation CLI
@@ -2533,46 +2778,46 @@ cli$1.run().catch((error) => {
2533
2778
  class AutoInstallCLI {
2534
2779
  constructor(options) {
2535
2780
  this.options = options;
2536
- this.rl = readline.createInterface({
2537
- input: process.stdin,
2538
- output: process.stdout
2539
- });
2540
2781
  }
2541
2782
  run() {
2542
2783
  return __awaiter(this, void 0, void 0, function* () {
2543
- console.log('šŸš€ HumanBehavior SDK Auto-Installation');
2544
- console.log('=====================================\n');
2784
+ clack.intro('šŸš€ HumanBehavior SDK Auto-Installation');
2545
2785
  try {
2546
2786
  // Get API key
2547
2787
  const apiKey = yield this.getApiKey();
2548
2788
  if (!apiKey) {
2549
- console.error('āŒ API key is required');
2789
+ clack.cancel('API key is required');
2550
2790
  process.exit(1);
2551
2791
  }
2552
2792
  // Get project path
2553
2793
  const projectPath = this.options.projectPath || process.cwd();
2794
+ // Choose framework
2795
+ const framework = yield this.chooseFramework();
2796
+ if (!framework) {
2797
+ clack.cancel('Installation cancelled.');
2798
+ process.exit(0);
2799
+ }
2554
2800
  // Confirm installation
2555
2801
  if (!this.options.yes) {
2556
- const confirmed = yield this.confirmInstallation(projectPath);
2802
+ const confirmed = yield this.confirmInstallation(projectPath, framework);
2557
2803
  if (!confirmed) {
2558
- console.log('Installation cancelled.');
2804
+ clack.cancel('Installation cancelled.');
2559
2805
  process.exit(0);
2560
2806
  }
2561
2807
  }
2562
- // Run auto-installation
2563
- console.log('šŸ” Detecting your project setup...');
2564
- const wizard = new AutoInstallationWizard(apiKey, projectPath);
2808
+ // Run installation
2809
+ const spinner = clack.spinner();
2810
+ spinner.start('šŸ” Analyzing your project...');
2811
+ const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
2565
2812
  const result = yield wizard.install();
2813
+ spinner.stop('Detection complete!');
2566
2814
  // Display results
2567
2815
  this.displayResults(result);
2568
2816
  }
2569
2817
  catch (error) {
2570
- console.error('āŒ Error:', error instanceof Error ? error.message : error);
2818
+ clack.cancel(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
2571
2819
  process.exit(1);
2572
2820
  }
2573
- finally {
2574
- this.rl.close();
2575
- }
2576
2821
  });
2577
2822
  }
2578
2823
  getApiKey() {
@@ -2580,139 +2825,131 @@ class AutoInstallCLI {
2580
2825
  if (this.options.apiKey) {
2581
2826
  return this.options.apiKey;
2582
2827
  }
2583
- return new Promise((resolve) => {
2584
- this.rl.question('Enter your HumanBehavior API key: ', (answer) => {
2585
- resolve(answer.trim());
2586
- });
2828
+ const apiKey = yield clack.text({
2829
+ message: 'Enter your HumanBehavior API key:',
2830
+ placeholder: 'hb_...',
2831
+ validate: (value) => {
2832
+ if (!value)
2833
+ return 'API key is required';
2834
+ if (!value.startsWith('hb_'))
2835
+ return 'API key should start with "hb_"';
2836
+ return undefined;
2837
+ }
2587
2838
  });
2839
+ return apiKey;
2588
2840
  });
2589
2841
  }
2590
- confirmInstallation(projectPath) {
2842
+ chooseFramework() {
2591
2843
  return __awaiter(this, void 0, void 0, function* () {
2592
- console.log(`šŸ“ Project path: ${projectPath}`);
2593
- console.log('āš ļø This will modify your codebase to integrate HumanBehavior SDK.');
2594
- console.log(' The following changes will be made:');
2595
- console.log(' - Install humanbehavior-js package');
2596
- console.log(' - Modify your main app file');
2597
- console.log(' - Create environment files');
2598
- console.log(' - Add SDK initialization code\n');
2599
- return new Promise((resolve) => {
2600
- this.rl.question('Continue with auto-installation? (y/n): ', (answer) => {
2601
- resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
2602
- });
2844
+ const framework = yield clack.select({
2845
+ message: 'Select your framework:',
2846
+ options: [
2847
+ { label: 'React', value: 'react' },
2848
+ { label: 'Next.js', value: 'nextjs' },
2849
+ { label: 'Vue', value: 'vue' },
2850
+ { label: 'Angular', value: 'angular' },
2851
+ { label: 'Svelte', value: 'svelte' },
2852
+ { label: 'Nuxt.js', value: 'nuxt' },
2853
+ { label: 'Remix', value: 'remix' },
2854
+ { label: 'Astro', value: 'astro' },
2855
+ { label: 'Gatsby', value: 'gatsby' },
2856
+ { label: 'Vanilla JS/TS', value: 'vanilla' }
2857
+ ]
2858
+ });
2859
+ return framework;
2860
+ });
2861
+ }
2862
+ confirmInstallation(projectPath, framework) {
2863
+ return __awaiter(this, void 0, void 0, function* () {
2864
+ const confirmed = yield clack.confirm({
2865
+ message: `Ready to install HumanBehavior SDK in ${projectPath} for ${framework}?`
2603
2866
  });
2867
+ return confirmed;
2604
2868
  });
2605
2869
  }
2606
2870
  displayResults(result) {
2607
2871
  if (result.success) {
2608
- console.log('\nāœ… Installation completed successfully!');
2609
- console.log(`šŸ“¦ Framework detected: ${result.framework.name}`);
2610
- if (result.framework.bundler) {
2611
- console.log(`šŸ”§ Bundler: ${result.framework.bundler}`);
2612
- }
2613
- if (result.framework.packageManager) {
2614
- console.log(`šŸ“‹ Package Manager: ${result.framework.packageManager}`);
2615
- }
2616
- console.log('\nšŸ“ Changes made:');
2617
- result.modifications.forEach((mod) => {
2618
- console.log(` ${mod.action === 'create' ? 'āž•' : 'āœļø'} ${mod.description}`);
2619
- console.log(` ${mod.filePath}`);
2620
- });
2621
- console.log('\nšŸŽÆ Next steps:');
2622
- result.nextSteps.forEach((step) => {
2623
- console.log(` ${step}`);
2624
- });
2625
- console.log('\nšŸš€ Your app is now ready to track user behavior!');
2626
- console.log('šŸ“Š View sessions in your HumanBehavior dashboard');
2872
+ clack.outro('šŸŽ‰ Installation completed successfully!');
2873
+ // Display framework info
2874
+ clack.note(`Framework detected: ${result.framework.name} (${result.framework.type})`, 'Framework Info');
2875
+ // Display modifications
2876
+ if (result.modifications && result.modifications.length > 0) {
2877
+ const modifications = result.modifications.map((mod) => `${mod.action}: ${mod.filePath} - ${mod.description}`);
2878
+ clack.note(modifications.join('\n'), 'Files Modified');
2879
+ }
2880
+ // Display next steps
2881
+ if (result.nextSteps && result.nextSteps.length > 0) {
2882
+ clack.note(result.nextSteps.join('\n'), 'Next Steps');
2883
+ }
2627
2884
  }
2628
2885
  else {
2629
- console.log('\nāŒ Installation failed:');
2630
- result.errors.forEach((error) => {
2631
- console.log(` ${error}`);
2632
- });
2633
- console.log('\nšŸ’” Try running with --help for more options');
2886
+ clack.cancel('Installation failed');
2887
+ if (result.errors && result.errors.length > 0) {
2888
+ clack.note(result.errors.join('\n'), 'Errors');
2889
+ }
2634
2890
  }
2635
2891
  }
2636
2892
  }
2637
- // CLI argument parsing
2638
2893
  function parseArgs() {
2639
2894
  const args = process.argv.slice(2);
2640
2895
  const options = {};
2641
2896
  for (let i = 0; i < args.length; i++) {
2642
2897
  const arg = args[i];
2643
- if (arg === '--yes' || arg === '-y') {
2644
- options.yes = true;
2645
- }
2646
- else if (arg === '--dry-run' || arg === '-d') {
2647
- options.dryRun = true;
2648
- }
2649
- else if (arg === '--project' || arg === '-p') {
2650
- options.projectPath = args[i + 1];
2651
- i++;
2652
- }
2653
- else if (arg === '--help' || arg === '-h') {
2654
- showHelp();
2655
- process.exit(0);
2656
- }
2657
- else if (!options.apiKey) {
2658
- options.apiKey = arg;
2898
+ switch (arg) {
2899
+ case '--help':
2900
+ case '-h':
2901
+ showHelp();
2902
+ process.exit(0);
2903
+ break;
2904
+ case '--yes':
2905
+ case '-y':
2906
+ options.yes = true;
2907
+ break;
2908
+ case '--dry-run':
2909
+ options.dryRun = true;
2910
+ break;
2911
+ case '--project':
2912
+ case '-p':
2913
+ options.projectPath = args[++i];
2914
+ break;
2915
+ default:
2916
+ if (!options.apiKey && !arg.startsWith('-')) {
2917
+ options.apiKey = arg;
2918
+ }
2919
+ break;
2659
2920
  }
2660
2921
  }
2661
2922
  return options;
2662
2923
  }
2663
2924
  function showHelp() {
2664
2925
  console.log(`
2665
- HumanBehavior SDK Auto-Installation CLI
2926
+ šŸš€ HumanBehavior SDK Auto-Installation
2666
2927
 
2667
- Usage: npx humanbehavior-js [api-key] [options]
2928
+ Usage: npx humanbehavior-js auto-install [api-key] [options]
2668
2929
 
2669
- This tool automatically detects your project's framework and modifies your codebase
2670
- to integrate the HumanBehavior SDK with minimal user intervention.
2671
-
2672
- Arguments:
2673
- api-key Your HumanBehavior API key
2930
+ This tool automatically detects your framework and integrates the HumanBehavior SDK.
2674
2931
 
2675
2932
  Options:
2676
- -y, --yes Skip all prompts and use defaults
2677
- -d, --dry-run Show what would be changed without making changes
2678
- -p, --project <path> Project directory (default: current directory)
2679
- -h, --help Show this help message
2933
+ -h, --help Show this help message
2934
+ -y, --yes Skip all prompts and use defaults
2935
+ --dry-run Show what would be changed without making changes
2936
+ -p, --project <path> Specify project directory
2680
2937
 
2681
2938
  Examples:
2682
- npx humanbehavior-js your-api-key
2683
- npx humanbehavior-js your-api-key --yes
2684
- npx humanbehavior-js your-api-key -p /path/to/project
2685
-
2686
- Supported Frameworks:
2687
- āœ… React (CRA, Vite, Webpack)
2688
- āœ… Next.js (App Router, Pages Router)
2689
- āœ… Vue (Vue CLI, Vite)
2690
- āœ… Angular
2691
- āœ… Svelte (SvelteKit, Vite)
2692
- āœ… Remix
2693
- āœ… Vanilla JS/TS
2694
- āœ… Node.js (CommonJS & ESM)
2695
-
2696
- The tool will:
2697
- 1. šŸ” Auto-detect your project's framework and setup
2698
- 2. šŸ“¦ Install the humanbehavior-js package
2699
- 3. āœļø Modify your codebase to integrate the SDK
2700
- 4. šŸ”§ Create environment files with your API key
2701
- 5. šŸš€ Make your app ready to track user behavior
2939
+ npx humanbehavior-js auto-install
2940
+ npx humanbehavior-js auto-install hb_your_api_key_here
2941
+ npx humanbehavior-js auto-install --project ./my-app --yes
2702
2942
  `);
2703
2943
  }
2704
2944
  // Main execution
2705
- const options = parseArgs();
2706
- // Check if we have enough arguments (api-key is required)
2707
- if (process.argv.length < 3 || process.argv.includes('--help') || process.argv.includes('-h')) {
2708
- showHelp();
2709
- process.exit(0);
2945
+ if (import.meta.url === `file://${process.argv[1]}`) {
2946
+ const options = parseArgs();
2947
+ const cli = new AutoInstallCLI(options);
2948
+ cli.run().catch((error) => {
2949
+ clack.cancel(`Unexpected error: ${error.message}`);
2950
+ process.exit(1);
2951
+ });
2710
2952
  }
2711
- const cli = new AutoInstallCLI(options);
2712
- cli.run().catch((error) => {
2713
- console.error('āŒ Fatal error:', error);
2714
- process.exit(1);
2715
- });
2716
2953
 
2717
2954
  /**
2718
2955
  * Centralized AI Service Implementation