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.
@@ -67,6 +67,28 @@ class AutoInstallationWizard {
67
67
  this.apiKey = apiKey;
68
68
  this.projectRoot = projectRoot;
69
69
  }
70
+ /**
71
+ * Simple version comparison utility
72
+ */
73
+ compareVersions(version1, version2) {
74
+ const v1Parts = version1.split('.').map(Number);
75
+ const v2Parts = version2.split('.').map(Number);
76
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
77
+ const v1 = v1Parts[i] || 0;
78
+ const v2 = v2Parts[i] || 0;
79
+ if (v1 > v2)
80
+ return 1;
81
+ if (v1 < v2)
82
+ return -1;
83
+ }
84
+ return 0;
85
+ }
86
+ isVersionGte(version, target) {
87
+ return this.compareVersions(version, target) >= 0;
88
+ }
89
+ getMajorVersion(version) {
90
+ return parseInt(version.split('.')[0]) || 0;
91
+ }
70
92
  /**
71
93
  * Main installation method - detects framework and auto-installs
72
94
  */
@@ -116,73 +138,146 @@ class AutoInstallationWizard {
116
138
  }
117
139
  const packageJson = JSON.parse(fs__namespace.readFileSync(packageJsonPath, 'utf8'));
118
140
  const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
119
- // Detect framework
141
+ // Detect framework with version information
120
142
  let framework = {
121
143
  name: 'vanilla',
122
144
  type: 'vanilla',
123
- projectRoot: this.projectRoot
145
+ projectRoot: this.projectRoot,
146
+ features: {}
124
147
  };
125
148
  if (dependencies.nuxt) {
149
+ const nuxtVersion = dependencies.nuxt;
150
+ const isNuxt3 = this.isVersionGte(nuxtVersion, '3.0.0');
126
151
  framework = {
127
152
  name: 'nuxt',
128
153
  type: 'nuxt',
154
+ version: nuxtVersion,
155
+ majorVersion: this.getMajorVersion(nuxtVersion),
129
156
  hasTypeScript: !!dependencies.typescript,
130
157
  hasRouter: true,
131
- projectRoot: this.projectRoot
158
+ projectRoot: this.projectRoot,
159
+ features: {
160
+ hasNuxt3: isNuxt3
161
+ }
132
162
  };
133
163
  }
134
164
  else if (dependencies.next) {
165
+ const nextVersion = dependencies.next;
166
+ const isNext13 = this.isVersionGte(nextVersion, '13.0.0');
135
167
  framework = {
136
168
  name: 'nextjs',
137
169
  type: 'nextjs',
170
+ version: nextVersion,
171
+ majorVersion: this.getMajorVersion(nextVersion),
138
172
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
139
173
  hasRouter: true,
140
- projectRoot: this.projectRoot
174
+ projectRoot: this.projectRoot,
175
+ features: {
176
+ hasNextAppRouter: isNext13
177
+ }
141
178
  };
142
179
  }
143
180
  else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
181
+ const remixVersion = dependencies['@remix-run/react'] || dependencies['@remix-run/dev'];
144
182
  framework = {
145
183
  name: 'remix',
146
184
  type: 'remix',
185
+ version: remixVersion,
186
+ majorVersion: this.getMajorVersion(remixVersion),
147
187
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
148
188
  hasRouter: true,
149
- projectRoot: this.projectRoot
189
+ projectRoot: this.projectRoot,
190
+ features: {}
150
191
  };
151
192
  }
152
193
  else if (dependencies.react) {
194
+ const reactVersion = dependencies.react;
195
+ const isReact18 = this.isVersionGte(reactVersion, '18.0.0');
153
196
  framework = {
154
197
  name: 'react',
155
198
  type: 'react',
199
+ version: reactVersion,
200
+ majorVersion: this.getMajorVersion(reactVersion),
156
201
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
157
202
  hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
158
- projectRoot: this.projectRoot
203
+ projectRoot: this.projectRoot,
204
+ features: {
205
+ hasReact18: isReact18
206
+ }
159
207
  };
160
208
  }
161
209
  else if (dependencies.vue) {
210
+ const vueVersion = dependencies.vue;
211
+ const isVue3 = this.isVersionGte(vueVersion, '3.0.0');
162
212
  framework = {
163
213
  name: 'vue',
164
214
  type: 'vue',
215
+ version: vueVersion,
216
+ majorVersion: this.getMajorVersion(vueVersion),
165
217
  hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
166
218
  hasRouter: !!dependencies['vue-router'],
167
- projectRoot: this.projectRoot
219
+ projectRoot: this.projectRoot,
220
+ features: {
221
+ hasVue3: isVue3
222
+ }
168
223
  };
169
224
  }
170
225
  else if (dependencies['@angular/core']) {
226
+ const angularVersion = dependencies['@angular/core'];
227
+ const isAngular17 = this.isVersionGte(angularVersion, '17.0.0');
171
228
  framework = {
172
229
  name: 'angular',
173
230
  type: 'angular',
231
+ version: angularVersion,
232
+ majorVersion: this.getMajorVersion(angularVersion),
174
233
  hasTypeScript: true,
175
234
  hasRouter: true,
176
- projectRoot: this.projectRoot
235
+ projectRoot: this.projectRoot,
236
+ features: {
237
+ hasAngularStandalone: isAngular17
238
+ }
177
239
  };
178
240
  }
179
241
  else if (dependencies.svelte) {
242
+ const svelteVersion = dependencies.svelte;
243
+ const isSvelteKit = !!dependencies['@sveltejs/kit'];
180
244
  framework = {
181
245
  name: 'svelte',
182
246
  type: 'svelte',
247
+ version: svelteVersion,
248
+ majorVersion: this.getMajorVersion(svelteVersion),
183
249
  hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
184
250
  hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
185
- projectRoot: this.projectRoot
251
+ projectRoot: this.projectRoot,
252
+ features: {
253
+ hasSvelteKit: isSvelteKit
254
+ }
255
+ };
256
+ }
257
+ else if (dependencies.astro) {
258
+ const astroVersion = dependencies.astro;
259
+ framework = {
260
+ name: 'astro',
261
+ type: 'astro',
262
+ version: astroVersion,
263
+ majorVersion: this.getMajorVersion(astroVersion),
264
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
265
+ hasRouter: true,
266
+ projectRoot: this.projectRoot,
267
+ features: {}
268
+ };
269
+ }
270
+ else if (dependencies.gatsby) {
271
+ const gatsbyVersion = dependencies.gatsby;
272
+ framework = {
273
+ name: 'gatsby',
274
+ type: 'gatsby',
275
+ version: gatsbyVersion,
276
+ majorVersion: this.getMajorVersion(gatsbyVersion),
277
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
278
+ hasRouter: true,
279
+ projectRoot: this.projectRoot,
280
+ features: {}
186
281
  };
187
282
  }
188
283
  // Detect bundler
@@ -216,13 +311,18 @@ class AutoInstallationWizard {
216
311
  */
217
312
  installPackage() {
218
313
  return __awaiter(this, void 0, void 0, function* () {
219
- var _a, _b;
314
+ var _a, _b, _c, _d;
220
315
  const { execSync } = yield import('child_process');
221
- const command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
316
+ // Build base command
317
+ let command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
222
318
  ? 'yarn add humanbehavior-js'
223
319
  : ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
224
320
  ? 'pnpm add humanbehavior-js'
225
321
  : 'npm install humanbehavior-js';
322
+ // Add legacy peer deps flag for npm to handle dependency conflicts
323
+ 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') {
324
+ command += ' --legacy-peer-deps';
325
+ }
226
326
  try {
227
327
  execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
228
328
  }
@@ -248,6 +348,12 @@ class AutoInstallationWizard {
248
348
  case 'nuxt':
249
349
  modifications.push(...yield this.generateNuxtModifications());
250
350
  break;
351
+ case 'astro':
352
+ modifications.push(...yield this.generateAstroModifications());
353
+ break;
354
+ case 'gatsby':
355
+ modifications.push(...yield this.generateGatsbyModifications());
356
+ break;
251
357
  case 'remix':
252
358
  modifications.push(...yield this.generateRemixModifications());
253
359
  break;
@@ -359,6 +465,84 @@ export function Providers({ children }: { children: React.ReactNode }) {
359
465
  return modifications;
360
466
  });
361
467
  }
468
+ /**
469
+ * Generate Astro-specific modifications
470
+ */
471
+ generateAstroModifications() {
472
+ return __awaiter(this, void 0, void 0, function* () {
473
+ const modifications = [];
474
+ // Create Astro component for HumanBehavior
475
+ const astroComponentPath = path__namespace.join(this.projectRoot, 'src', 'components', 'HumanBehavior.astro');
476
+ const astroComponentContent = `---
477
+ // This component will only run on the client side
478
+ ---
479
+
480
+ <script>
481
+ import { HumanBehaviorTracker } from 'humanbehavior-js';
482
+
483
+ // Get API key from environment variable
484
+ const apiKey = import.meta.env.PUBLIC_HUMANBEHAVIOR_API_KEY;
485
+
486
+ console.log('HumanBehavior: API key found:', apiKey ? 'Yes' : 'No');
487
+
488
+ if (apiKey) {
489
+ try {
490
+ const tracker = HumanBehaviorTracker.init(apiKey);
491
+ console.log('HumanBehavior: Tracker initialized successfully');
492
+
493
+ // Test event to verify tracking is working
494
+ setTimeout(() => {
495
+ tracker.customEvent('astro_page_view', {
496
+ page: window.location.pathname,
497
+ framework: 'astro'
498
+ }).then(() => {
499
+ console.log('HumanBehavior: Test event sent successfully');
500
+ }).catch((error) => {
501
+ console.error('HumanBehavior: Failed to send test event:', error);
502
+ });
503
+ }, 1000);
504
+
505
+ } catch (error) {
506
+ console.error('HumanBehavior: Failed to initialize tracker:', error);
507
+ }
508
+ } else {
509
+ console.error('HumanBehavior: No API key found');
510
+ }
511
+ </script>`;
512
+ modifications.push({
513
+ filePath: astroComponentPath,
514
+ action: 'create',
515
+ content: astroComponentContent,
516
+ description: 'Created Astro component for HumanBehavior SDK'
517
+ });
518
+ // Find and update layout file
519
+ const layoutFiles = [
520
+ path__namespace.join(this.projectRoot, 'src', 'layouts', 'Layout.astro'),
521
+ path__namespace.join(this.projectRoot, 'src', 'layouts', 'layout.astro'),
522
+ path__namespace.join(this.projectRoot, 'src', 'layouts', 'BaseLayout.astro')
523
+ ];
524
+ let layoutFile = null;
525
+ for (const file of layoutFiles) {
526
+ if (fs__namespace.existsSync(file)) {
527
+ layoutFile = file;
528
+ break;
529
+ }
530
+ }
531
+ if (layoutFile) {
532
+ const content = fs__namespace.readFileSync(layoutFile, 'utf8');
533
+ const modifiedContent = this.injectAstroLayout(content);
534
+ modifications.push({
535
+ filePath: layoutFile,
536
+ action: 'modify',
537
+ content: modifiedContent,
538
+ description: 'Added HumanBehavior component to Astro layout'
539
+ });
540
+ }
541
+ // Add environment variable
542
+ modifications.push(this.createEnvironmentModification(this.framework));
543
+ return modifications;
544
+ });
545
+ }
362
546
  /**
363
547
  * Generate Nuxt-specific modifications
364
548
  */
@@ -579,6 +763,50 @@ export default defineNuxtPlugin(() => {
579
763
  return modifications;
580
764
  });
581
765
  }
766
+ /**
767
+ * Generate Gatsby-specific modifications
768
+ */
769
+ generateGatsbyModifications() {
770
+ return __awaiter(this, void 0, void 0, function* () {
771
+ const modifications = [];
772
+ // Modify or create gatsby-browser.js for Gatsby
773
+ const gatsbyBrowserFile = path__namespace.join(this.projectRoot, 'gatsby-browser.js');
774
+ if (fs__namespace.existsSync(gatsbyBrowserFile)) {
775
+ const content = fs__namespace.readFileSync(gatsbyBrowserFile, 'utf8');
776
+ const modifiedContent = this.injectGatsbyBrowser(content);
777
+ modifications.push({
778
+ filePath: gatsbyBrowserFile,
779
+ action: 'modify',
780
+ content: modifiedContent,
781
+ description: 'Added HumanBehavior initialization to Gatsby browser'
782
+ });
783
+ }
784
+ else {
785
+ // Create gatsby-browser.js if it doesn't exist
786
+ modifications.push({
787
+ filePath: gatsbyBrowserFile,
788
+ action: 'create',
789
+ content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
790
+
791
+ export const onClientEntry = () => {
792
+ console.log('Gatsby browser entry point loaded');
793
+ const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
794
+ console.log('API Key found:', apiKey ? 'Yes' : 'No');
795
+ if (apiKey) {
796
+ const tracker = HumanBehaviorTracker.init(apiKey);
797
+ console.log('HumanBehavior SDK initialized for Gatsby');
798
+ } else {
799
+ console.log('No API key found in environment variables');
800
+ }
801
+ };`,
802
+ description: 'Created gatsby-browser.js with HumanBehavior initialization'
803
+ });
804
+ }
805
+ // Create or append to environment file
806
+ modifications.push(this.createEnvironmentModification(this.framework));
807
+ return modifications;
808
+ });
809
+ }
582
810
  /**
583
811
  * Apply modifications to the codebase
584
812
  */
@@ -673,7 +901,7 @@ export default defineNuxtPlugin(() => {
673
901
  return null;
674
902
  }
675
903
  injectReactProvider(content, filePath) {
676
- var _a;
904
+ var _a, _b, _c;
677
905
  filePath.endsWith('.tsx') || filePath.endsWith('.ts');
678
906
  // Check if already has HumanBehaviorProvider
679
907
  if (content.includes('HumanBehaviorProvider')) {
@@ -685,14 +913,39 @@ export default defineNuxtPlugin(() => {
685
913
  ? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
686
914
  : 'process.env.HUMANBEHAVIOR_API_KEY!';
687
915
  const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
688
- // Simple injection - in production, you'd want more sophisticated parsing
916
+ // Enhanced parsing for React 18+ features
917
+ const hasReact18 = (_c = (_b = this.framework) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.hasReact18;
918
+ // Handle different React patterns
689
919
  if (content.includes('function App()') || content.includes('const App =')) {
690
- return content.replace(/(function App\(\)|const App =)/, `${importStatement}\n\n$1`).replace(/return \(([\s\S]*?)\);/, `return (
920
+ // Add import statement
921
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
922
+ // If no React import found, add it at the top
923
+ if (!modifiedContent.includes(importStatement)) {
924
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
925
+ }
926
+ // Wrap the App component return with HumanBehaviorProvider
927
+ modifiedContent = modifiedContent.replace(/(return\s*\([\s\S]*?\)\s*;)/, `return (
691
928
  <HumanBehaviorProvider apiKey={${envVar}}>
692
929
  $1
693
930
  </HumanBehaviorProvider>
694
931
  );`);
932
+ return modifiedContent;
695
933
  }
934
+ // Handle React 18+ createRoot pattern
935
+ if (hasReact18 && content.includes('createRoot')) {
936
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
937
+ if (!modifiedContent.includes(importStatement)) {
938
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
939
+ }
940
+ // Wrap the root render with HumanBehaviorProvider
941
+ modifiedContent = modifiedContent.replace(/(root\.render\s*\([\s\S]*?\)\s*;)/, `root.render(
942
+ <HumanBehaviorProvider apiKey={${envVar}}>
943
+ $1
944
+ </HumanBehaviorProvider>
945
+ );`);
946
+ return modifiedContent;
947
+ }
948
+ // Fallback: simple injection
696
949
  return `${importStatement}\n\n${content}`;
697
950
  }
698
951
  injectNextJSAppRouter(content) {
@@ -789,21 +1042,51 @@ export default function App()`);
789
1042
  return modifiedContent;
790
1043
  }
791
1044
  injectVuePlugin(content) {
1045
+ var _a, _b;
792
1046
  if (content.includes('HumanBehaviorPlugin')) {
793
1047
  return content;
794
1048
  }
795
1049
  const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
796
- const pluginUsage = `app.use(HumanBehaviorPlugin, {
1050
+ // Enhanced Vue 3 support with version detection
1051
+ const hasVue3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasVue3;
1052
+ if (hasVue3) {
1053
+ // Vue 3 with Composition API
1054
+ const pluginUsage = `app.use(HumanBehaviorPlugin, {
797
1055
  apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
798
1056
  });`;
799
- // Handle both Vue 2 and Vue 3 patterns
800
- if (content.includes('createApp')) {
801
- // Vue 3
802
- return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/app\.mount\(/, `${pluginUsage}\n\napp.mount(`);
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 no Vue import found, add it at the top
1062
+ if (!modifiedContent.includes(importStatement)) {
1063
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1064
+ }
1065
+ }
1066
+ // Handle createApp pattern
1067
+ if (content.includes('createApp')) {
1068
+ modifiedContent = modifiedContent.replace(/(app\.mount\(.*?\))/, `${pluginUsage}\n\n$1`);
1069
+ }
1070
+ return modifiedContent;
803
1071
  }
804
1072
  else {
805
- // Vue 2
806
- return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/new Vue\(/, `${pluginUsage}\n\nnew Vue(`);
1073
+ // Vue 2 with Options API
1074
+ const pluginUsage = `Vue.use(HumanBehaviorPlugin, {
1075
+ apiKey: process.env.VUE_APP_HUMANBEHAVIOR_API_KEY
1076
+ });`;
1077
+ let modifiedContent = content;
1078
+ // Add import statement
1079
+ if (!content.includes(importStatement)) {
1080
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1081
+ if (!modifiedContent.includes(importStatement)) {
1082
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1083
+ }
1084
+ }
1085
+ // Handle new Vue pattern
1086
+ if (content.includes('new Vue')) {
1087
+ modifiedContent = modifiedContent.replace(/(new Vue\(.*?\))/, `${pluginUsage}\n\n$1`);
1088
+ }
1089
+ return modifiedContent;
807
1090
  }
808
1091
  }
809
1092
  injectAngularModule(content) {
@@ -884,17 +1167,99 @@ if (typeof window !== 'undefined') {
884
1167
  </script>`;
885
1168
  return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
886
1169
  }
1170
+ /**
1171
+ * Inject Astro layout with HumanBehavior component
1172
+ */
1173
+ injectAstroLayout(content) {
1174
+ // Check if HumanBehavior component is already imported
1175
+ if (content.includes('HumanBehavior') || content.includes('humanbehavior-js')) {
1176
+ return content; // Already has HumanBehavior
1177
+ }
1178
+ // Add import inside frontmatter if not present
1179
+ let modifiedContent = content;
1180
+ if (!content.includes('import HumanBehavior')) {
1181
+ const importStatement = 'import HumanBehavior from \'../components/HumanBehavior.astro\';';
1182
+ const frontmatterEndIndex = content.indexOf('---', 3);
1183
+ if (frontmatterEndIndex !== -1) {
1184
+ // Insert import inside frontmatter, before the closing ---
1185
+ modifiedContent = content.slice(0, frontmatterEndIndex) + '\n' + importStatement + '\n' + content.slice(frontmatterEndIndex);
1186
+ }
1187
+ else {
1188
+ // No frontmatter, add at the very beginning
1189
+ modifiedContent = '---\n' + importStatement + '\n---\n\n' + content;
1190
+ }
1191
+ }
1192
+ // Find the closing </body> tag and add HumanBehavior component before it
1193
+ const bodyCloseIndex = modifiedContent.lastIndexOf('</body>');
1194
+ if (bodyCloseIndex === -1) {
1195
+ // No body tag found, append to end
1196
+ return modifiedContent + '\n\n<HumanBehavior />';
1197
+ }
1198
+ // Add component before closing body tag
1199
+ return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
1200
+ }
887
1201
  injectNuxtConfig(content) {
1202
+ var _a, _b;
888
1203
  if (content.includes('humanBehaviorApiKey')) {
889
1204
  return content;
890
1205
  }
891
- // Add runtime config by inserting it after the opening brace
892
- return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
1206
+ // Enhanced Nuxt 3 support with version detection
1207
+ const hasNuxt3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasNuxt3;
1208
+ if (hasNuxt3) {
1209
+ // Nuxt 3 with runtime config
1210
+ return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
893
1211
  runtimeConfig: {
894
1212
  public: {
895
1213
  humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
896
1214
  }
897
1215
  },`);
1216
+ }
1217
+ else {
1218
+ // Nuxt 2 with env config
1219
+ return content.replace(/export default \{/, `export default {
1220
+ env: {
1221
+ humanBehaviorApiKey: process.env.HUMANBEHAVIOR_API_KEY
1222
+ },`);
1223
+ }
1224
+ }
1225
+ injectGatsbyLayout(content) {
1226
+ if (content.includes('HumanBehavior')) {
1227
+ return content;
1228
+ }
1229
+ const importStatement = `import HumanBehavior from './HumanBehavior';`;
1230
+ const componentUsage = `<HumanBehavior apiKey={process.env.GATSBY_HUMANBEHAVIOR_API_KEY || ''} />`;
1231
+ // Add import at the top
1232
+ let modifiedContent = content.replace(/import.*from.*['"]\./, `${importStatement}\n$&`);
1233
+ // Add component before closing body tag
1234
+ modifiedContent = modifiedContent.replace(/(\s*<\/body>)/, `\n ${componentUsage}\n$1`);
1235
+ return modifiedContent;
1236
+ }
1237
+ injectGatsbyBrowser(content) {
1238
+ if (content.includes('HumanBehaviorTracker')) {
1239
+ return content;
1240
+ }
1241
+ const importStatement = `import { HumanBehaviorTracker } from 'humanbehavior-js';`;
1242
+ const initCode = `
1243
+ // Initialize HumanBehavior SDK
1244
+ export const onClientEntry = () => {
1245
+ console.log('Gatsby browser entry point loaded');
1246
+ const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
1247
+ console.log('API Key found:', apiKey ? 'Yes' : 'No');
1248
+ if (apiKey) {
1249
+ const tracker = HumanBehaviorTracker.init(apiKey);
1250
+ console.log('HumanBehavior SDK initialized for Gatsby');
1251
+ } else {
1252
+ console.log('No API key found in environment variables');
1253
+ }
1254
+ };`;
1255
+ // If the file already has content, add the import and init code
1256
+ if (content.trim()) {
1257
+ return `${importStatement}${initCode}\n\n${content}`;
1258
+ }
1259
+ else {
1260
+ // If file is empty, just return the new content
1261
+ return `${importStatement}${initCode}`;
1262
+ }
898
1263
  }
899
1264
  /**
900
1265
  * Helper method to find the best environment file for a framework
@@ -925,6 +1290,8 @@ if (typeof window !== 'undefined') {
925
1290
  nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
926
1291
  remix: 'HUMANBEHAVIOR_API_KEY',
927
1292
  vanilla: 'HUMANBEHAVIOR_API_KEY',
1293
+ astro: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
1294
+ gatsby: 'GATSBY_HUMANBEHAVIOR_API_KEY',
928
1295
  node: 'HUMANBEHAVIOR_API_KEY',
929
1296
  auto: 'HUMANBEHAVIOR_API_KEY'
930
1297
  };
@@ -948,6 +1315,8 @@ if (typeof window !== 'undefined') {
948
1315
  nuxt: '.env',
949
1316
  remix: '.env.local',
950
1317
  vanilla: '.env',
1318
+ astro: '.env',
1319
+ gatsby: '.env.development',
951
1320
  node: '.env',
952
1321
  auto: '.env'
953
1322
  };
@@ -962,6 +1331,8 @@ if (typeof window !== 'undefined') {
962
1331
  */
963
1332
  createEnvironmentModification(framework) {
964
1333
  const { filePath, envVarName } = this.findBestEnvFile(framework);
1334
+ // Clean the API key to prevent formatting issues
1335
+ const cleanApiKey = this.apiKey.trim();
965
1336
  if (fs__namespace.existsSync(filePath)) {
966
1337
  // Check if the variable already exists
967
1338
  const content = fs__namespace.readFileSync(filePath, 'utf8');
@@ -979,7 +1350,7 @@ if (typeof window !== 'undefined') {
979
1350
  return {
980
1351
  filePath,
981
1352
  action: 'append',
982
- content: `\n${envVarName}=${this.apiKey}`,
1353
+ content: `\n${envVarName}=${cleanApiKey}`,
983
1354
  description: `Added API key to existing ${path__namespace.basename(filePath)}`
984
1355
  };
985
1356
  }
@@ -989,7 +1360,7 @@ if (typeof window !== 'undefined') {
989
1360
  return {
990
1361
  filePath,
991
1362
  action: 'create',
992
- content: `${envVarName}=${this.apiKey}`,
1363
+ content: `${envVarName}=${cleanApiKey}`,
993
1364
  description: `Created ${path__namespace.basename(filePath)} with API key`
994
1365
  };
995
1366
  }