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.
- package/dist/cjs/install-wizard.cjs +396 -25
- package/dist/cjs/install-wizard.cjs.map +1 -1
- package/dist/cjs/wizard/index.cjs +633 -395
- package/dist/cjs/wizard/index.cjs.map +1 -1
- package/dist/cli/ai-auto-install.cjs +57161 -0
- package/dist/cli/ai-auto-install.cjs.map +1 -0
- package/dist/cli/ai-auto-install.js +520 -575
- package/dist/cli/ai-auto-install.js.map +1 -1
- package/dist/cli/auto-install.cjs +56352 -0
- package/dist/cli/auto-install.cjs.map +1 -0
- package/dist/cli/auto-install.js +925 -140
- package/dist/cli/auto-install.js.map +1 -1
- package/dist/esm/install-wizard.js +396 -25
- package/dist/esm/install-wizard.js.map +1 -1
- package/dist/esm/wizard/index.js +631 -394
- package/dist/esm/wizard/index.js.map +1 -1
- package/dist/types/install-wizard.d.ts +31 -1
- package/dist/types/wizard/index.d.ts +44 -10
- package/package.json +3 -1
- package/rollup.config.js +5 -1
- package/src/types/clack.d.ts +31 -0
- package/src/wizard/ai/ai-install-wizard.ts +4 -1
- package/src/wizard/ai/manual-framework-wizard.ts +2 -0
- package/src/wizard/cli/ai-auto-install.ts +122 -248
- package/src/wizard/cli/auto-install.ts +116 -117
- package/src/wizard/core/install-wizard.ts +498 -60
- package/src/wizard/services/centralized-ai-service.ts +1 -1
- package/src/wizard/services/remote-ai-service.ts +18 -2
- package/tsconfig.json +1 -1
|
@@ -45,6 +45,28 @@ class AutoInstallationWizard {
|
|
|
45
45
|
this.apiKey = apiKey;
|
|
46
46
|
this.projectRoot = projectRoot;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Simple version comparison utility
|
|
50
|
+
*/
|
|
51
|
+
compareVersions(version1, version2) {
|
|
52
|
+
const v1Parts = version1.split('.').map(Number);
|
|
53
|
+
const v2Parts = version2.split('.').map(Number);
|
|
54
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
55
|
+
const v1 = v1Parts[i] || 0;
|
|
56
|
+
const v2 = v2Parts[i] || 0;
|
|
57
|
+
if (v1 > v2)
|
|
58
|
+
return 1;
|
|
59
|
+
if (v1 < v2)
|
|
60
|
+
return -1;
|
|
61
|
+
}
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
isVersionGte(version, target) {
|
|
65
|
+
return this.compareVersions(version, target) >= 0;
|
|
66
|
+
}
|
|
67
|
+
getMajorVersion(version) {
|
|
68
|
+
return parseInt(version.split('.')[0]) || 0;
|
|
69
|
+
}
|
|
48
70
|
/**
|
|
49
71
|
* Main installation method - detects framework and auto-installs
|
|
50
72
|
*/
|
|
@@ -94,73 +116,146 @@ class AutoInstallationWizard {
|
|
|
94
116
|
}
|
|
95
117
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
96
118
|
const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
|
|
97
|
-
// Detect framework
|
|
119
|
+
// Detect framework with version information
|
|
98
120
|
let framework = {
|
|
99
121
|
name: 'vanilla',
|
|
100
122
|
type: 'vanilla',
|
|
101
|
-
projectRoot: this.projectRoot
|
|
123
|
+
projectRoot: this.projectRoot,
|
|
124
|
+
features: {}
|
|
102
125
|
};
|
|
103
126
|
if (dependencies.nuxt) {
|
|
127
|
+
const nuxtVersion = dependencies.nuxt;
|
|
128
|
+
const isNuxt3 = this.isVersionGte(nuxtVersion, '3.0.0');
|
|
104
129
|
framework = {
|
|
105
130
|
name: 'nuxt',
|
|
106
131
|
type: 'nuxt',
|
|
132
|
+
version: nuxtVersion,
|
|
133
|
+
majorVersion: this.getMajorVersion(nuxtVersion),
|
|
107
134
|
hasTypeScript: !!dependencies.typescript,
|
|
108
135
|
hasRouter: true,
|
|
109
|
-
projectRoot: this.projectRoot
|
|
136
|
+
projectRoot: this.projectRoot,
|
|
137
|
+
features: {
|
|
138
|
+
hasNuxt3: isNuxt3
|
|
139
|
+
}
|
|
110
140
|
};
|
|
111
141
|
}
|
|
112
142
|
else if (dependencies.next) {
|
|
143
|
+
const nextVersion = dependencies.next;
|
|
144
|
+
const isNext13 = this.isVersionGte(nextVersion, '13.0.0');
|
|
113
145
|
framework = {
|
|
114
146
|
name: 'nextjs',
|
|
115
147
|
type: 'nextjs',
|
|
148
|
+
version: nextVersion,
|
|
149
|
+
majorVersion: this.getMajorVersion(nextVersion),
|
|
116
150
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
|
|
117
151
|
hasRouter: true,
|
|
118
|
-
projectRoot: this.projectRoot
|
|
152
|
+
projectRoot: this.projectRoot,
|
|
153
|
+
features: {
|
|
154
|
+
hasNextAppRouter: isNext13
|
|
155
|
+
}
|
|
119
156
|
};
|
|
120
157
|
}
|
|
121
158
|
else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
|
|
159
|
+
const remixVersion = dependencies['@remix-run/react'] || dependencies['@remix-run/dev'];
|
|
122
160
|
framework = {
|
|
123
161
|
name: 'remix',
|
|
124
162
|
type: 'remix',
|
|
163
|
+
version: remixVersion,
|
|
164
|
+
majorVersion: this.getMajorVersion(remixVersion),
|
|
125
165
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
126
166
|
hasRouter: true,
|
|
127
|
-
projectRoot: this.projectRoot
|
|
167
|
+
projectRoot: this.projectRoot,
|
|
168
|
+
features: {}
|
|
128
169
|
};
|
|
129
170
|
}
|
|
130
171
|
else if (dependencies.react) {
|
|
172
|
+
const reactVersion = dependencies.react;
|
|
173
|
+
const isReact18 = this.isVersionGte(reactVersion, '18.0.0');
|
|
131
174
|
framework = {
|
|
132
175
|
name: 'react',
|
|
133
176
|
type: 'react',
|
|
177
|
+
version: reactVersion,
|
|
178
|
+
majorVersion: this.getMajorVersion(reactVersion),
|
|
134
179
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
135
180
|
hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
|
|
136
|
-
projectRoot: this.projectRoot
|
|
181
|
+
projectRoot: this.projectRoot,
|
|
182
|
+
features: {
|
|
183
|
+
hasReact18: isReact18
|
|
184
|
+
}
|
|
137
185
|
};
|
|
138
186
|
}
|
|
139
187
|
else if (dependencies.vue) {
|
|
188
|
+
const vueVersion = dependencies.vue;
|
|
189
|
+
const isVue3 = this.isVersionGte(vueVersion, '3.0.0');
|
|
140
190
|
framework = {
|
|
141
191
|
name: 'vue',
|
|
142
192
|
type: 'vue',
|
|
193
|
+
version: vueVersion,
|
|
194
|
+
majorVersion: this.getMajorVersion(vueVersion),
|
|
143
195
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
|
|
144
196
|
hasRouter: !!dependencies['vue-router'],
|
|
145
|
-
projectRoot: this.projectRoot
|
|
197
|
+
projectRoot: this.projectRoot,
|
|
198
|
+
features: {
|
|
199
|
+
hasVue3: isVue3
|
|
200
|
+
}
|
|
146
201
|
};
|
|
147
202
|
}
|
|
148
203
|
else if (dependencies['@angular/core']) {
|
|
204
|
+
const angularVersion = dependencies['@angular/core'];
|
|
205
|
+
const isAngular17 = this.isVersionGte(angularVersion, '17.0.0');
|
|
149
206
|
framework = {
|
|
150
207
|
name: 'angular',
|
|
151
208
|
type: 'angular',
|
|
209
|
+
version: angularVersion,
|
|
210
|
+
majorVersion: this.getMajorVersion(angularVersion),
|
|
152
211
|
hasTypeScript: true,
|
|
153
212
|
hasRouter: true,
|
|
154
|
-
projectRoot: this.projectRoot
|
|
213
|
+
projectRoot: this.projectRoot,
|
|
214
|
+
features: {
|
|
215
|
+
hasAngularStandalone: isAngular17
|
|
216
|
+
}
|
|
155
217
|
};
|
|
156
218
|
}
|
|
157
219
|
else if (dependencies.svelte) {
|
|
220
|
+
const svelteVersion = dependencies.svelte;
|
|
221
|
+
const isSvelteKit = !!dependencies['@sveltejs/kit'];
|
|
158
222
|
framework = {
|
|
159
223
|
name: 'svelte',
|
|
160
224
|
type: 'svelte',
|
|
225
|
+
version: svelteVersion,
|
|
226
|
+
majorVersion: this.getMajorVersion(svelteVersion),
|
|
161
227
|
hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
|
|
162
228
|
hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
|
|
163
|
-
projectRoot: this.projectRoot
|
|
229
|
+
projectRoot: this.projectRoot,
|
|
230
|
+
features: {
|
|
231
|
+
hasSvelteKit: isSvelteKit
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
else if (dependencies.astro) {
|
|
236
|
+
const astroVersion = dependencies.astro;
|
|
237
|
+
framework = {
|
|
238
|
+
name: 'astro',
|
|
239
|
+
type: 'astro',
|
|
240
|
+
version: astroVersion,
|
|
241
|
+
majorVersion: this.getMajorVersion(astroVersion),
|
|
242
|
+
hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
|
|
243
|
+
hasRouter: true,
|
|
244
|
+
projectRoot: this.projectRoot,
|
|
245
|
+
features: {}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
else if (dependencies.gatsby) {
|
|
249
|
+
const gatsbyVersion = dependencies.gatsby;
|
|
250
|
+
framework = {
|
|
251
|
+
name: 'gatsby',
|
|
252
|
+
type: 'gatsby',
|
|
253
|
+
version: gatsbyVersion,
|
|
254
|
+
majorVersion: this.getMajorVersion(gatsbyVersion),
|
|
255
|
+
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
256
|
+
hasRouter: true,
|
|
257
|
+
projectRoot: this.projectRoot,
|
|
258
|
+
features: {}
|
|
164
259
|
};
|
|
165
260
|
}
|
|
166
261
|
// Detect bundler
|
|
@@ -194,13 +289,18 @@ class AutoInstallationWizard {
|
|
|
194
289
|
*/
|
|
195
290
|
installPackage() {
|
|
196
291
|
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
-
var _a, _b;
|
|
292
|
+
var _a, _b, _c, _d;
|
|
198
293
|
const { execSync } = yield import('child_process');
|
|
199
|
-
|
|
294
|
+
// Build base command
|
|
295
|
+
let command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
|
|
200
296
|
? 'yarn add humanbehavior-js'
|
|
201
297
|
: ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
|
|
202
298
|
? 'pnpm add humanbehavior-js'
|
|
203
299
|
: 'npm install humanbehavior-js';
|
|
300
|
+
// Add legacy peer deps flag for npm to handle dependency conflicts
|
|
301
|
+
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') {
|
|
302
|
+
command += ' --legacy-peer-deps';
|
|
303
|
+
}
|
|
204
304
|
try {
|
|
205
305
|
execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
|
|
206
306
|
}
|
|
@@ -226,6 +326,12 @@ class AutoInstallationWizard {
|
|
|
226
326
|
case 'nuxt':
|
|
227
327
|
modifications.push(...yield this.generateNuxtModifications());
|
|
228
328
|
break;
|
|
329
|
+
case 'astro':
|
|
330
|
+
modifications.push(...yield this.generateAstroModifications());
|
|
331
|
+
break;
|
|
332
|
+
case 'gatsby':
|
|
333
|
+
modifications.push(...yield this.generateGatsbyModifications());
|
|
334
|
+
break;
|
|
229
335
|
case 'remix':
|
|
230
336
|
modifications.push(...yield this.generateRemixModifications());
|
|
231
337
|
break;
|
|
@@ -337,6 +443,84 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
337
443
|
return modifications;
|
|
338
444
|
});
|
|
339
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* Generate Astro-specific modifications
|
|
448
|
+
*/
|
|
449
|
+
generateAstroModifications() {
|
|
450
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
451
|
+
const modifications = [];
|
|
452
|
+
// Create Astro component for HumanBehavior
|
|
453
|
+
const astroComponentPath = path.join(this.projectRoot, 'src', 'components', 'HumanBehavior.astro');
|
|
454
|
+
const astroComponentContent = `---
|
|
455
|
+
// This component will only run on the client side
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
<script>
|
|
459
|
+
import { HumanBehaviorTracker } from 'humanbehavior-js';
|
|
460
|
+
|
|
461
|
+
// Get API key from environment variable
|
|
462
|
+
const apiKey = import.meta.env.PUBLIC_HUMANBEHAVIOR_API_KEY;
|
|
463
|
+
|
|
464
|
+
console.log('HumanBehavior: API key found:', apiKey ? 'Yes' : 'No');
|
|
465
|
+
|
|
466
|
+
if (apiKey) {
|
|
467
|
+
try {
|
|
468
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
469
|
+
console.log('HumanBehavior: Tracker initialized successfully');
|
|
470
|
+
|
|
471
|
+
// Test event to verify tracking is working
|
|
472
|
+
setTimeout(() => {
|
|
473
|
+
tracker.customEvent('astro_page_view', {
|
|
474
|
+
page: window.location.pathname,
|
|
475
|
+
framework: 'astro'
|
|
476
|
+
}).then(() => {
|
|
477
|
+
console.log('HumanBehavior: Test event sent successfully');
|
|
478
|
+
}).catch((error) => {
|
|
479
|
+
console.error('HumanBehavior: Failed to send test event:', error);
|
|
480
|
+
});
|
|
481
|
+
}, 1000);
|
|
482
|
+
|
|
483
|
+
} catch (error) {
|
|
484
|
+
console.error('HumanBehavior: Failed to initialize tracker:', error);
|
|
485
|
+
}
|
|
486
|
+
} else {
|
|
487
|
+
console.error('HumanBehavior: No API key found');
|
|
488
|
+
}
|
|
489
|
+
</script>`;
|
|
490
|
+
modifications.push({
|
|
491
|
+
filePath: astroComponentPath,
|
|
492
|
+
action: 'create',
|
|
493
|
+
content: astroComponentContent,
|
|
494
|
+
description: 'Created Astro component for HumanBehavior SDK'
|
|
495
|
+
});
|
|
496
|
+
// Find and update layout file
|
|
497
|
+
const layoutFiles = [
|
|
498
|
+
path.join(this.projectRoot, 'src', 'layouts', 'Layout.astro'),
|
|
499
|
+
path.join(this.projectRoot, 'src', 'layouts', 'layout.astro'),
|
|
500
|
+
path.join(this.projectRoot, 'src', 'layouts', 'BaseLayout.astro')
|
|
501
|
+
];
|
|
502
|
+
let layoutFile = null;
|
|
503
|
+
for (const file of layoutFiles) {
|
|
504
|
+
if (fs.existsSync(file)) {
|
|
505
|
+
layoutFile = file;
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (layoutFile) {
|
|
510
|
+
const content = fs.readFileSync(layoutFile, 'utf8');
|
|
511
|
+
const modifiedContent = this.injectAstroLayout(content);
|
|
512
|
+
modifications.push({
|
|
513
|
+
filePath: layoutFile,
|
|
514
|
+
action: 'modify',
|
|
515
|
+
content: modifiedContent,
|
|
516
|
+
description: 'Added HumanBehavior component to Astro layout'
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
// Add environment variable
|
|
520
|
+
modifications.push(this.createEnvironmentModification(this.framework));
|
|
521
|
+
return modifications;
|
|
522
|
+
});
|
|
523
|
+
}
|
|
340
524
|
/**
|
|
341
525
|
* Generate Nuxt-specific modifications
|
|
342
526
|
*/
|
|
@@ -557,6 +741,50 @@ export default defineNuxtPlugin(() => {
|
|
|
557
741
|
return modifications;
|
|
558
742
|
});
|
|
559
743
|
}
|
|
744
|
+
/**
|
|
745
|
+
* Generate Gatsby-specific modifications
|
|
746
|
+
*/
|
|
747
|
+
generateGatsbyModifications() {
|
|
748
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
749
|
+
const modifications = [];
|
|
750
|
+
// Modify or create gatsby-browser.js for Gatsby
|
|
751
|
+
const gatsbyBrowserFile = path.join(this.projectRoot, 'gatsby-browser.js');
|
|
752
|
+
if (fs.existsSync(gatsbyBrowserFile)) {
|
|
753
|
+
const content = fs.readFileSync(gatsbyBrowserFile, 'utf8');
|
|
754
|
+
const modifiedContent = this.injectGatsbyBrowser(content);
|
|
755
|
+
modifications.push({
|
|
756
|
+
filePath: gatsbyBrowserFile,
|
|
757
|
+
action: 'modify',
|
|
758
|
+
content: modifiedContent,
|
|
759
|
+
description: 'Added HumanBehavior initialization to Gatsby browser'
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
// Create gatsby-browser.js if it doesn't exist
|
|
764
|
+
modifications.push({
|
|
765
|
+
filePath: gatsbyBrowserFile,
|
|
766
|
+
action: 'create',
|
|
767
|
+
content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
|
|
768
|
+
|
|
769
|
+
export const onClientEntry = () => {
|
|
770
|
+
console.log('Gatsby browser entry point loaded');
|
|
771
|
+
const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
|
|
772
|
+
console.log('API Key found:', apiKey ? 'Yes' : 'No');
|
|
773
|
+
if (apiKey) {
|
|
774
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
775
|
+
console.log('HumanBehavior SDK initialized for Gatsby');
|
|
776
|
+
} else {
|
|
777
|
+
console.log('No API key found in environment variables');
|
|
778
|
+
}
|
|
779
|
+
};`,
|
|
780
|
+
description: 'Created gatsby-browser.js with HumanBehavior initialization'
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
// Create or append to environment file
|
|
784
|
+
modifications.push(this.createEnvironmentModification(this.framework));
|
|
785
|
+
return modifications;
|
|
786
|
+
});
|
|
787
|
+
}
|
|
560
788
|
/**
|
|
561
789
|
* Apply modifications to the codebase
|
|
562
790
|
*/
|
|
@@ -651,7 +879,7 @@ export default defineNuxtPlugin(() => {
|
|
|
651
879
|
return null;
|
|
652
880
|
}
|
|
653
881
|
injectReactProvider(content, filePath) {
|
|
654
|
-
var _a;
|
|
882
|
+
var _a, _b, _c;
|
|
655
883
|
filePath.endsWith('.tsx') || filePath.endsWith('.ts');
|
|
656
884
|
// Check if already has HumanBehaviorProvider
|
|
657
885
|
if (content.includes('HumanBehaviorProvider')) {
|
|
@@ -663,14 +891,39 @@ export default defineNuxtPlugin(() => {
|
|
|
663
891
|
? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
|
|
664
892
|
: 'process.env.HUMANBEHAVIOR_API_KEY!';
|
|
665
893
|
const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
|
|
666
|
-
//
|
|
894
|
+
// Enhanced parsing for React 18+ features
|
|
895
|
+
const hasReact18 = (_c = (_b = this.framework) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.hasReact18;
|
|
896
|
+
// Handle different React patterns
|
|
667
897
|
if (content.includes('function App()') || content.includes('const App =')) {
|
|
668
|
-
|
|
898
|
+
// Add import statement
|
|
899
|
+
let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
|
|
900
|
+
// If no React import found, add it at the top
|
|
901
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
902
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
903
|
+
}
|
|
904
|
+
// Wrap the App component return with HumanBehaviorProvider
|
|
905
|
+
modifiedContent = modifiedContent.replace(/(return\s*\([\s\S]*?\)\s*;)/, `return (
|
|
669
906
|
<HumanBehaviorProvider apiKey={${envVar}}>
|
|
670
907
|
$1
|
|
671
908
|
</HumanBehaviorProvider>
|
|
672
909
|
);`);
|
|
910
|
+
return modifiedContent;
|
|
673
911
|
}
|
|
912
|
+
// Handle React 18+ createRoot pattern
|
|
913
|
+
if (hasReact18 && content.includes('createRoot')) {
|
|
914
|
+
let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
|
|
915
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
916
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
917
|
+
}
|
|
918
|
+
// Wrap the root render with HumanBehaviorProvider
|
|
919
|
+
modifiedContent = modifiedContent.replace(/(root\.render\s*\([\s\S]*?\)\s*;)/, `root.render(
|
|
920
|
+
<HumanBehaviorProvider apiKey={${envVar}}>
|
|
921
|
+
$1
|
|
922
|
+
</HumanBehaviorProvider>
|
|
923
|
+
);`);
|
|
924
|
+
return modifiedContent;
|
|
925
|
+
}
|
|
926
|
+
// Fallback: simple injection
|
|
674
927
|
return `${importStatement}\n\n${content}`;
|
|
675
928
|
}
|
|
676
929
|
injectNextJSAppRouter(content) {
|
|
@@ -767,21 +1020,51 @@ export default function App()`);
|
|
|
767
1020
|
return modifiedContent;
|
|
768
1021
|
}
|
|
769
1022
|
injectVuePlugin(content) {
|
|
1023
|
+
var _a, _b;
|
|
770
1024
|
if (content.includes('HumanBehaviorPlugin')) {
|
|
771
1025
|
return content;
|
|
772
1026
|
}
|
|
773
1027
|
const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
|
|
774
|
-
|
|
1028
|
+
// Enhanced Vue 3 support with version detection
|
|
1029
|
+
const hasVue3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasVue3;
|
|
1030
|
+
if (hasVue3) {
|
|
1031
|
+
// Vue 3 with Composition API
|
|
1032
|
+
const pluginUsage = `app.use(HumanBehaviorPlugin, {
|
|
775
1033
|
apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
|
|
776
1034
|
});`;
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
1035
|
+
let modifiedContent = content;
|
|
1036
|
+
// Add import statement
|
|
1037
|
+
if (!content.includes(importStatement)) {
|
|
1038
|
+
modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
|
|
1039
|
+
// If no Vue import found, add it at the top
|
|
1040
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
1041
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
// Handle createApp pattern
|
|
1045
|
+
if (content.includes('createApp')) {
|
|
1046
|
+
modifiedContent = modifiedContent.replace(/(app\.mount\(.*?\))/, `${pluginUsage}\n\n$1`);
|
|
1047
|
+
}
|
|
1048
|
+
return modifiedContent;
|
|
781
1049
|
}
|
|
782
1050
|
else {
|
|
783
|
-
// Vue 2
|
|
784
|
-
|
|
1051
|
+
// Vue 2 with Options API
|
|
1052
|
+
const pluginUsage = `Vue.use(HumanBehaviorPlugin, {
|
|
1053
|
+
apiKey: process.env.VUE_APP_HUMANBEHAVIOR_API_KEY
|
|
1054
|
+
});`;
|
|
1055
|
+
let modifiedContent = content;
|
|
1056
|
+
// Add import statement
|
|
1057
|
+
if (!content.includes(importStatement)) {
|
|
1058
|
+
modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
|
|
1059
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
1060
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
// Handle new Vue pattern
|
|
1064
|
+
if (content.includes('new Vue')) {
|
|
1065
|
+
modifiedContent = modifiedContent.replace(/(new Vue\(.*?\))/, `${pluginUsage}\n\n$1`);
|
|
1066
|
+
}
|
|
1067
|
+
return modifiedContent;
|
|
785
1068
|
}
|
|
786
1069
|
}
|
|
787
1070
|
injectAngularModule(content) {
|
|
@@ -862,17 +1145,99 @@ if (typeof window !== 'undefined') {
|
|
|
862
1145
|
</script>`;
|
|
863
1146
|
return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
|
|
864
1147
|
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Inject Astro layout with HumanBehavior component
|
|
1150
|
+
*/
|
|
1151
|
+
injectAstroLayout(content) {
|
|
1152
|
+
// Check if HumanBehavior component is already imported
|
|
1153
|
+
if (content.includes('HumanBehavior') || content.includes('humanbehavior-js')) {
|
|
1154
|
+
return content; // Already has HumanBehavior
|
|
1155
|
+
}
|
|
1156
|
+
// Add import inside frontmatter if not present
|
|
1157
|
+
let modifiedContent = content;
|
|
1158
|
+
if (!content.includes('import HumanBehavior')) {
|
|
1159
|
+
const importStatement = 'import HumanBehavior from \'../components/HumanBehavior.astro\';';
|
|
1160
|
+
const frontmatterEndIndex = content.indexOf('---', 3);
|
|
1161
|
+
if (frontmatterEndIndex !== -1) {
|
|
1162
|
+
// Insert import inside frontmatter, before the closing ---
|
|
1163
|
+
modifiedContent = content.slice(0, frontmatterEndIndex) + '\n' + importStatement + '\n' + content.slice(frontmatterEndIndex);
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
// No frontmatter, add at the very beginning
|
|
1167
|
+
modifiedContent = '---\n' + importStatement + '\n---\n\n' + content;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
// Find the closing </body> tag and add HumanBehavior component before it
|
|
1171
|
+
const bodyCloseIndex = modifiedContent.lastIndexOf('</body>');
|
|
1172
|
+
if (bodyCloseIndex === -1) {
|
|
1173
|
+
// No body tag found, append to end
|
|
1174
|
+
return modifiedContent + '\n\n<HumanBehavior />';
|
|
1175
|
+
}
|
|
1176
|
+
// Add component before closing body tag
|
|
1177
|
+
return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
|
|
1178
|
+
}
|
|
865
1179
|
injectNuxtConfig(content) {
|
|
1180
|
+
var _a, _b;
|
|
866
1181
|
if (content.includes('humanBehaviorApiKey')) {
|
|
867
1182
|
return content;
|
|
868
1183
|
}
|
|
869
|
-
//
|
|
870
|
-
|
|
1184
|
+
// Enhanced Nuxt 3 support with version detection
|
|
1185
|
+
const hasNuxt3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasNuxt3;
|
|
1186
|
+
if (hasNuxt3) {
|
|
1187
|
+
// Nuxt 3 with runtime config
|
|
1188
|
+
return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
|
|
871
1189
|
runtimeConfig: {
|
|
872
1190
|
public: {
|
|
873
1191
|
humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
|
|
874
1192
|
}
|
|
875
1193
|
},`);
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
// Nuxt 2 with env config
|
|
1197
|
+
return content.replace(/export default \{/, `export default {
|
|
1198
|
+
env: {
|
|
1199
|
+
humanBehaviorApiKey: process.env.HUMANBEHAVIOR_API_KEY
|
|
1200
|
+
},`);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
injectGatsbyLayout(content) {
|
|
1204
|
+
if (content.includes('HumanBehavior')) {
|
|
1205
|
+
return content;
|
|
1206
|
+
}
|
|
1207
|
+
const importStatement = `import HumanBehavior from './HumanBehavior';`;
|
|
1208
|
+
const componentUsage = `<HumanBehavior apiKey={process.env.GATSBY_HUMANBEHAVIOR_API_KEY || ''} />`;
|
|
1209
|
+
// Add import at the top
|
|
1210
|
+
let modifiedContent = content.replace(/import.*from.*['"]\./, `${importStatement}\n$&`);
|
|
1211
|
+
// Add component before closing body tag
|
|
1212
|
+
modifiedContent = modifiedContent.replace(/(\s*<\/body>)/, `\n ${componentUsage}\n$1`);
|
|
1213
|
+
return modifiedContent;
|
|
1214
|
+
}
|
|
1215
|
+
injectGatsbyBrowser(content) {
|
|
1216
|
+
if (content.includes('HumanBehaviorTracker')) {
|
|
1217
|
+
return content;
|
|
1218
|
+
}
|
|
1219
|
+
const importStatement = `import { HumanBehaviorTracker } from 'humanbehavior-js';`;
|
|
1220
|
+
const initCode = `
|
|
1221
|
+
// Initialize HumanBehavior SDK
|
|
1222
|
+
export const onClientEntry = () => {
|
|
1223
|
+
console.log('Gatsby browser entry point loaded');
|
|
1224
|
+
const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
|
|
1225
|
+
console.log('API Key found:', apiKey ? 'Yes' : 'No');
|
|
1226
|
+
if (apiKey) {
|
|
1227
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
1228
|
+
console.log('HumanBehavior SDK initialized for Gatsby');
|
|
1229
|
+
} else {
|
|
1230
|
+
console.log('No API key found in environment variables');
|
|
1231
|
+
}
|
|
1232
|
+
};`;
|
|
1233
|
+
// If the file already has content, add the import and init code
|
|
1234
|
+
if (content.trim()) {
|
|
1235
|
+
return `${importStatement}${initCode}\n\n${content}`;
|
|
1236
|
+
}
|
|
1237
|
+
else {
|
|
1238
|
+
// If file is empty, just return the new content
|
|
1239
|
+
return `${importStatement}${initCode}`;
|
|
1240
|
+
}
|
|
876
1241
|
}
|
|
877
1242
|
/**
|
|
878
1243
|
* Helper method to find the best environment file for a framework
|
|
@@ -903,6 +1268,8 @@ if (typeof window !== 'undefined') {
|
|
|
903
1268
|
nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
|
|
904
1269
|
remix: 'HUMANBEHAVIOR_API_KEY',
|
|
905
1270
|
vanilla: 'HUMANBEHAVIOR_API_KEY',
|
|
1271
|
+
astro: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
|
|
1272
|
+
gatsby: 'GATSBY_HUMANBEHAVIOR_API_KEY',
|
|
906
1273
|
node: 'HUMANBEHAVIOR_API_KEY',
|
|
907
1274
|
auto: 'HUMANBEHAVIOR_API_KEY'
|
|
908
1275
|
};
|
|
@@ -926,6 +1293,8 @@ if (typeof window !== 'undefined') {
|
|
|
926
1293
|
nuxt: '.env',
|
|
927
1294
|
remix: '.env.local',
|
|
928
1295
|
vanilla: '.env',
|
|
1296
|
+
astro: '.env',
|
|
1297
|
+
gatsby: '.env.development',
|
|
929
1298
|
node: '.env',
|
|
930
1299
|
auto: '.env'
|
|
931
1300
|
};
|
|
@@ -940,6 +1309,8 @@ if (typeof window !== 'undefined') {
|
|
|
940
1309
|
*/
|
|
941
1310
|
createEnvironmentModification(framework) {
|
|
942
1311
|
const { filePath, envVarName } = this.findBestEnvFile(framework);
|
|
1312
|
+
// Clean the API key to prevent formatting issues
|
|
1313
|
+
const cleanApiKey = this.apiKey.trim();
|
|
943
1314
|
if (fs.existsSync(filePath)) {
|
|
944
1315
|
// Check if the variable already exists
|
|
945
1316
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
@@ -957,7 +1328,7 @@ if (typeof window !== 'undefined') {
|
|
|
957
1328
|
return {
|
|
958
1329
|
filePath,
|
|
959
1330
|
action: 'append',
|
|
960
|
-
content: `\n${envVarName}=${
|
|
1331
|
+
content: `\n${envVarName}=${cleanApiKey}`,
|
|
961
1332
|
description: `Added API key to existing ${path.basename(filePath)}`
|
|
962
1333
|
};
|
|
963
1334
|
}
|
|
@@ -967,7 +1338,7 @@ if (typeof window !== 'undefined') {
|
|
|
967
1338
|
return {
|
|
968
1339
|
filePath,
|
|
969
1340
|
action: 'create',
|
|
970
|
-
content: `${envVarName}=${
|
|
1341
|
+
content: `${envVarName}=${cleanApiKey}`,
|
|
971
1342
|
description: `Created ${path.basename(filePath)} with API key`
|
|
972
1343
|
};
|
|
973
1344
|
}
|