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
package/dist/cli/auto-install.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
-
import * as
|
|
4
|
+
import * as clack from '@clack/prompts';
|
|
5
5
|
|
|
6
6
|
/******************************************************************************
|
|
7
7
|
Copyright (c) Microsoft Corporation.
|
|
@@ -47,6 +47,28 @@ class AutoInstallationWizard {
|
|
|
47
47
|
this.apiKey = apiKey;
|
|
48
48
|
this.projectRoot = projectRoot;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Simple version comparison utility
|
|
52
|
+
*/
|
|
53
|
+
compareVersions(version1, version2) {
|
|
54
|
+
const v1Parts = version1.split('.').map(Number);
|
|
55
|
+
const v2Parts = version2.split('.').map(Number);
|
|
56
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
57
|
+
const v1 = v1Parts[i] || 0;
|
|
58
|
+
const v2 = v2Parts[i] || 0;
|
|
59
|
+
if (v1 > v2)
|
|
60
|
+
return 1;
|
|
61
|
+
if (v1 < v2)
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
isVersionGte(version, target) {
|
|
67
|
+
return this.compareVersions(version, target) >= 0;
|
|
68
|
+
}
|
|
69
|
+
getMajorVersion(version) {
|
|
70
|
+
return parseInt(version.split('.')[0]) || 0;
|
|
71
|
+
}
|
|
50
72
|
/**
|
|
51
73
|
* Main installation method - detects framework and auto-installs
|
|
52
74
|
*/
|
|
@@ -96,73 +118,146 @@ class AutoInstallationWizard {
|
|
|
96
118
|
}
|
|
97
119
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
98
120
|
const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
|
|
99
|
-
// Detect framework
|
|
121
|
+
// Detect framework with version information
|
|
100
122
|
let framework = {
|
|
101
123
|
name: 'vanilla',
|
|
102
124
|
type: 'vanilla',
|
|
103
|
-
projectRoot: this.projectRoot
|
|
125
|
+
projectRoot: this.projectRoot,
|
|
126
|
+
features: {}
|
|
104
127
|
};
|
|
105
128
|
if (dependencies.nuxt) {
|
|
129
|
+
const nuxtVersion = dependencies.nuxt;
|
|
130
|
+
const isNuxt3 = this.isVersionGte(nuxtVersion, '3.0.0');
|
|
106
131
|
framework = {
|
|
107
132
|
name: 'nuxt',
|
|
108
133
|
type: 'nuxt',
|
|
134
|
+
version: nuxtVersion,
|
|
135
|
+
majorVersion: this.getMajorVersion(nuxtVersion),
|
|
109
136
|
hasTypeScript: !!dependencies.typescript,
|
|
110
137
|
hasRouter: true,
|
|
111
|
-
projectRoot: this.projectRoot
|
|
138
|
+
projectRoot: this.projectRoot,
|
|
139
|
+
features: {
|
|
140
|
+
hasNuxt3: isNuxt3
|
|
141
|
+
}
|
|
112
142
|
};
|
|
113
143
|
}
|
|
114
144
|
else if (dependencies.next) {
|
|
145
|
+
const nextVersion = dependencies.next;
|
|
146
|
+
const isNext13 = this.isVersionGte(nextVersion, '13.0.0');
|
|
115
147
|
framework = {
|
|
116
148
|
name: 'nextjs',
|
|
117
149
|
type: 'nextjs',
|
|
150
|
+
version: nextVersion,
|
|
151
|
+
majorVersion: this.getMajorVersion(nextVersion),
|
|
118
152
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
|
|
119
153
|
hasRouter: true,
|
|
120
|
-
projectRoot: this.projectRoot
|
|
154
|
+
projectRoot: this.projectRoot,
|
|
155
|
+
features: {
|
|
156
|
+
hasNextAppRouter: isNext13
|
|
157
|
+
}
|
|
121
158
|
};
|
|
122
159
|
}
|
|
123
160
|
else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
|
|
161
|
+
const remixVersion = dependencies['@remix-run/react'] || dependencies['@remix-run/dev'];
|
|
124
162
|
framework = {
|
|
125
163
|
name: 'remix',
|
|
126
164
|
type: 'remix',
|
|
165
|
+
version: remixVersion,
|
|
166
|
+
majorVersion: this.getMajorVersion(remixVersion),
|
|
127
167
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
128
168
|
hasRouter: true,
|
|
129
|
-
projectRoot: this.projectRoot
|
|
169
|
+
projectRoot: this.projectRoot,
|
|
170
|
+
features: {}
|
|
130
171
|
};
|
|
131
172
|
}
|
|
132
173
|
else if (dependencies.react) {
|
|
174
|
+
const reactVersion = dependencies.react;
|
|
175
|
+
const isReact18 = this.isVersionGte(reactVersion, '18.0.0');
|
|
133
176
|
framework = {
|
|
134
177
|
name: 'react',
|
|
135
178
|
type: 'react',
|
|
179
|
+
version: reactVersion,
|
|
180
|
+
majorVersion: this.getMajorVersion(reactVersion),
|
|
136
181
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
137
182
|
hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
|
|
138
|
-
projectRoot: this.projectRoot
|
|
183
|
+
projectRoot: this.projectRoot,
|
|
184
|
+
features: {
|
|
185
|
+
hasReact18: isReact18
|
|
186
|
+
}
|
|
139
187
|
};
|
|
140
188
|
}
|
|
141
189
|
else if (dependencies.vue) {
|
|
190
|
+
const vueVersion = dependencies.vue;
|
|
191
|
+
const isVue3 = this.isVersionGte(vueVersion, '3.0.0');
|
|
142
192
|
framework = {
|
|
143
193
|
name: 'vue',
|
|
144
194
|
type: 'vue',
|
|
195
|
+
version: vueVersion,
|
|
196
|
+
majorVersion: this.getMajorVersion(vueVersion),
|
|
145
197
|
hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
|
|
146
198
|
hasRouter: !!dependencies['vue-router'],
|
|
147
|
-
projectRoot: this.projectRoot
|
|
199
|
+
projectRoot: this.projectRoot,
|
|
200
|
+
features: {
|
|
201
|
+
hasVue3: isVue3
|
|
202
|
+
}
|
|
148
203
|
};
|
|
149
204
|
}
|
|
150
205
|
else if (dependencies['@angular/core']) {
|
|
206
|
+
const angularVersion = dependencies['@angular/core'];
|
|
207
|
+
const isAngular17 = this.isVersionGte(angularVersion, '17.0.0');
|
|
151
208
|
framework = {
|
|
152
209
|
name: 'angular',
|
|
153
210
|
type: 'angular',
|
|
211
|
+
version: angularVersion,
|
|
212
|
+
majorVersion: this.getMajorVersion(angularVersion),
|
|
154
213
|
hasTypeScript: true,
|
|
155
214
|
hasRouter: true,
|
|
156
|
-
projectRoot: this.projectRoot
|
|
215
|
+
projectRoot: this.projectRoot,
|
|
216
|
+
features: {
|
|
217
|
+
hasAngularStandalone: isAngular17
|
|
218
|
+
}
|
|
157
219
|
};
|
|
158
220
|
}
|
|
159
221
|
else if (dependencies.svelte) {
|
|
222
|
+
const svelteVersion = dependencies.svelte;
|
|
223
|
+
const isSvelteKit = !!dependencies['@sveltejs/kit'];
|
|
160
224
|
framework = {
|
|
161
225
|
name: 'svelte',
|
|
162
226
|
type: 'svelte',
|
|
227
|
+
version: svelteVersion,
|
|
228
|
+
majorVersion: this.getMajorVersion(svelteVersion),
|
|
163
229
|
hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
|
|
164
230
|
hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
|
|
165
|
-
projectRoot: this.projectRoot
|
|
231
|
+
projectRoot: this.projectRoot,
|
|
232
|
+
features: {
|
|
233
|
+
hasSvelteKit: isSvelteKit
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
else if (dependencies.astro) {
|
|
238
|
+
const astroVersion = dependencies.astro;
|
|
239
|
+
framework = {
|
|
240
|
+
name: 'astro',
|
|
241
|
+
type: 'astro',
|
|
242
|
+
version: astroVersion,
|
|
243
|
+
majorVersion: this.getMajorVersion(astroVersion),
|
|
244
|
+
hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
|
|
245
|
+
hasRouter: true,
|
|
246
|
+
projectRoot: this.projectRoot,
|
|
247
|
+
features: {}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
else if (dependencies.gatsby) {
|
|
251
|
+
const gatsbyVersion = dependencies.gatsby;
|
|
252
|
+
framework = {
|
|
253
|
+
name: 'gatsby',
|
|
254
|
+
type: 'gatsby',
|
|
255
|
+
version: gatsbyVersion,
|
|
256
|
+
majorVersion: this.getMajorVersion(gatsbyVersion),
|
|
257
|
+
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
258
|
+
hasRouter: true,
|
|
259
|
+
projectRoot: this.projectRoot,
|
|
260
|
+
features: {}
|
|
166
261
|
};
|
|
167
262
|
}
|
|
168
263
|
// Detect bundler
|
|
@@ -196,13 +291,18 @@ class AutoInstallationWizard {
|
|
|
196
291
|
*/
|
|
197
292
|
installPackage() {
|
|
198
293
|
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
-
var _a, _b;
|
|
294
|
+
var _a, _b, _c, _d;
|
|
200
295
|
const { execSync } = yield import('child_process');
|
|
201
|
-
|
|
296
|
+
// Build base command
|
|
297
|
+
let command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
|
|
202
298
|
? 'yarn add humanbehavior-js'
|
|
203
299
|
: ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
|
|
204
300
|
? 'pnpm add humanbehavior-js'
|
|
205
301
|
: 'npm install humanbehavior-js';
|
|
302
|
+
// Add legacy peer deps flag for npm to handle dependency conflicts
|
|
303
|
+
if (((_c = this.framework) === null || _c === void 0 ? void 0 : _c.packageManager) !== 'yarn' && ((_d = this.framework) === null || _d === void 0 ? void 0 : _d.packageManager) !== 'pnpm') {
|
|
304
|
+
command += ' --legacy-peer-deps';
|
|
305
|
+
}
|
|
206
306
|
try {
|
|
207
307
|
execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
|
|
208
308
|
}
|
|
@@ -228,6 +328,12 @@ class AutoInstallationWizard {
|
|
|
228
328
|
case 'nuxt':
|
|
229
329
|
modifications.push(...yield this.generateNuxtModifications());
|
|
230
330
|
break;
|
|
331
|
+
case 'astro':
|
|
332
|
+
modifications.push(...yield this.generateAstroModifications());
|
|
333
|
+
break;
|
|
334
|
+
case 'gatsby':
|
|
335
|
+
modifications.push(...yield this.generateGatsbyModifications());
|
|
336
|
+
break;
|
|
231
337
|
case 'remix':
|
|
232
338
|
modifications.push(...yield this.generateRemixModifications());
|
|
233
339
|
break;
|
|
@@ -339,6 +445,84 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
339
445
|
return modifications;
|
|
340
446
|
});
|
|
341
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Generate Astro-specific modifications
|
|
450
|
+
*/
|
|
451
|
+
generateAstroModifications() {
|
|
452
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
453
|
+
const modifications = [];
|
|
454
|
+
// Create Astro component for HumanBehavior
|
|
455
|
+
const astroComponentPath = path.join(this.projectRoot, 'src', 'components', 'HumanBehavior.astro');
|
|
456
|
+
const astroComponentContent = `---
|
|
457
|
+
// This component will only run on the client side
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
<script>
|
|
461
|
+
import { HumanBehaviorTracker } from 'humanbehavior-js';
|
|
462
|
+
|
|
463
|
+
// Get API key from environment variable
|
|
464
|
+
const apiKey = import.meta.env.PUBLIC_HUMANBEHAVIOR_API_KEY;
|
|
465
|
+
|
|
466
|
+
console.log('HumanBehavior: API key found:', apiKey ? 'Yes' : 'No');
|
|
467
|
+
|
|
468
|
+
if (apiKey) {
|
|
469
|
+
try {
|
|
470
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
471
|
+
console.log('HumanBehavior: Tracker initialized successfully');
|
|
472
|
+
|
|
473
|
+
// Test event to verify tracking is working
|
|
474
|
+
setTimeout(() => {
|
|
475
|
+
tracker.customEvent('astro_page_view', {
|
|
476
|
+
page: window.location.pathname,
|
|
477
|
+
framework: 'astro'
|
|
478
|
+
}).then(() => {
|
|
479
|
+
console.log('HumanBehavior: Test event sent successfully');
|
|
480
|
+
}).catch((error) => {
|
|
481
|
+
console.error('HumanBehavior: Failed to send test event:', error);
|
|
482
|
+
});
|
|
483
|
+
}, 1000);
|
|
484
|
+
|
|
485
|
+
} catch (error) {
|
|
486
|
+
console.error('HumanBehavior: Failed to initialize tracker:', error);
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
console.error('HumanBehavior: No API key found');
|
|
490
|
+
}
|
|
491
|
+
</script>`;
|
|
492
|
+
modifications.push({
|
|
493
|
+
filePath: astroComponentPath,
|
|
494
|
+
action: 'create',
|
|
495
|
+
content: astroComponentContent,
|
|
496
|
+
description: 'Created Astro component for HumanBehavior SDK'
|
|
497
|
+
});
|
|
498
|
+
// Find and update layout file
|
|
499
|
+
const layoutFiles = [
|
|
500
|
+
path.join(this.projectRoot, 'src', 'layouts', 'Layout.astro'),
|
|
501
|
+
path.join(this.projectRoot, 'src', 'layouts', 'layout.astro'),
|
|
502
|
+
path.join(this.projectRoot, 'src', 'layouts', 'BaseLayout.astro')
|
|
503
|
+
];
|
|
504
|
+
let layoutFile = null;
|
|
505
|
+
for (const file of layoutFiles) {
|
|
506
|
+
if (fs.existsSync(file)) {
|
|
507
|
+
layoutFile = file;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (layoutFile) {
|
|
512
|
+
const content = fs.readFileSync(layoutFile, 'utf8');
|
|
513
|
+
const modifiedContent = this.injectAstroLayout(content);
|
|
514
|
+
modifications.push({
|
|
515
|
+
filePath: layoutFile,
|
|
516
|
+
action: 'modify',
|
|
517
|
+
content: modifiedContent,
|
|
518
|
+
description: 'Added HumanBehavior component to Astro layout'
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
// Add environment variable
|
|
522
|
+
modifications.push(this.createEnvironmentModification(this.framework));
|
|
523
|
+
return modifications;
|
|
524
|
+
});
|
|
525
|
+
}
|
|
342
526
|
/**
|
|
343
527
|
* Generate Nuxt-specific modifications
|
|
344
528
|
*/
|
|
@@ -559,6 +743,50 @@ export default defineNuxtPlugin(() => {
|
|
|
559
743
|
return modifications;
|
|
560
744
|
});
|
|
561
745
|
}
|
|
746
|
+
/**
|
|
747
|
+
* Generate Gatsby-specific modifications
|
|
748
|
+
*/
|
|
749
|
+
generateGatsbyModifications() {
|
|
750
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
751
|
+
const modifications = [];
|
|
752
|
+
// Modify or create gatsby-browser.js for Gatsby
|
|
753
|
+
const gatsbyBrowserFile = path.join(this.projectRoot, 'gatsby-browser.js');
|
|
754
|
+
if (fs.existsSync(gatsbyBrowserFile)) {
|
|
755
|
+
const content = fs.readFileSync(gatsbyBrowserFile, 'utf8');
|
|
756
|
+
const modifiedContent = this.injectGatsbyBrowser(content);
|
|
757
|
+
modifications.push({
|
|
758
|
+
filePath: gatsbyBrowserFile,
|
|
759
|
+
action: 'modify',
|
|
760
|
+
content: modifiedContent,
|
|
761
|
+
description: 'Added HumanBehavior initialization to Gatsby browser'
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
765
|
+
// Create gatsby-browser.js if it doesn't exist
|
|
766
|
+
modifications.push({
|
|
767
|
+
filePath: gatsbyBrowserFile,
|
|
768
|
+
action: 'create',
|
|
769
|
+
content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
|
|
770
|
+
|
|
771
|
+
export const onClientEntry = () => {
|
|
772
|
+
console.log('Gatsby browser entry point loaded');
|
|
773
|
+
const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
|
|
774
|
+
console.log('API Key found:', apiKey ? 'Yes' : 'No');
|
|
775
|
+
if (apiKey) {
|
|
776
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
777
|
+
console.log('HumanBehavior SDK initialized for Gatsby');
|
|
778
|
+
} else {
|
|
779
|
+
console.log('No API key found in environment variables');
|
|
780
|
+
}
|
|
781
|
+
};`,
|
|
782
|
+
description: 'Created gatsby-browser.js with HumanBehavior initialization'
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
// Create or append to environment file
|
|
786
|
+
modifications.push(this.createEnvironmentModification(this.framework));
|
|
787
|
+
return modifications;
|
|
788
|
+
});
|
|
789
|
+
}
|
|
562
790
|
/**
|
|
563
791
|
* Apply modifications to the codebase
|
|
564
792
|
*/
|
|
@@ -653,7 +881,7 @@ export default defineNuxtPlugin(() => {
|
|
|
653
881
|
return null;
|
|
654
882
|
}
|
|
655
883
|
injectReactProvider(content, filePath) {
|
|
656
|
-
var _a;
|
|
884
|
+
var _a, _b, _c;
|
|
657
885
|
filePath.endsWith('.tsx') || filePath.endsWith('.ts');
|
|
658
886
|
// Check if already has HumanBehaviorProvider
|
|
659
887
|
if (content.includes('HumanBehaviorProvider')) {
|
|
@@ -665,14 +893,39 @@ export default defineNuxtPlugin(() => {
|
|
|
665
893
|
? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
|
|
666
894
|
: 'process.env.HUMANBEHAVIOR_API_KEY!';
|
|
667
895
|
const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
|
|
668
|
-
//
|
|
896
|
+
// Enhanced parsing for React 18+ features
|
|
897
|
+
const hasReact18 = (_c = (_b = this.framework) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.hasReact18;
|
|
898
|
+
// Handle different React patterns
|
|
669
899
|
if (content.includes('function App()') || content.includes('const App =')) {
|
|
670
|
-
|
|
900
|
+
// Add import statement
|
|
901
|
+
let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
|
|
902
|
+
// If no React import found, add it at the top
|
|
903
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
904
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
905
|
+
}
|
|
906
|
+
// Wrap the App component return with HumanBehaviorProvider
|
|
907
|
+
modifiedContent = modifiedContent.replace(/(return\s*\([\s\S]*?\)\s*;)/, `return (
|
|
908
|
+
<HumanBehaviorProvider apiKey={${envVar}}>
|
|
909
|
+
$1
|
|
910
|
+
</HumanBehaviorProvider>
|
|
911
|
+
);`);
|
|
912
|
+
return modifiedContent;
|
|
913
|
+
}
|
|
914
|
+
// Handle React 18+ createRoot pattern
|
|
915
|
+
if (hasReact18 && content.includes('createRoot')) {
|
|
916
|
+
let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
|
|
917
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
918
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
919
|
+
}
|
|
920
|
+
// Wrap the root render with HumanBehaviorProvider
|
|
921
|
+
modifiedContent = modifiedContent.replace(/(root\.render\s*\([\s\S]*?\)\s*;)/, `root.render(
|
|
671
922
|
<HumanBehaviorProvider apiKey={${envVar}}>
|
|
672
923
|
$1
|
|
673
924
|
</HumanBehaviorProvider>
|
|
674
925
|
);`);
|
|
926
|
+
return modifiedContent;
|
|
675
927
|
}
|
|
928
|
+
// Fallback: simple injection
|
|
676
929
|
return `${importStatement}\n\n${content}`;
|
|
677
930
|
}
|
|
678
931
|
injectNextJSAppRouter(content) {
|
|
@@ -769,21 +1022,51 @@ export default function App()`);
|
|
|
769
1022
|
return modifiedContent;
|
|
770
1023
|
}
|
|
771
1024
|
injectVuePlugin(content) {
|
|
1025
|
+
var _a, _b;
|
|
772
1026
|
if (content.includes('HumanBehaviorPlugin')) {
|
|
773
1027
|
return content;
|
|
774
1028
|
}
|
|
775
1029
|
const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
|
|
776
|
-
|
|
1030
|
+
// Enhanced Vue 3 support with version detection
|
|
1031
|
+
const hasVue3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasVue3;
|
|
1032
|
+
if (hasVue3) {
|
|
1033
|
+
// Vue 3 with Composition API
|
|
1034
|
+
const pluginUsage = `app.use(HumanBehaviorPlugin, {
|
|
777
1035
|
apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
|
|
778
1036
|
});`;
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
1037
|
+
let modifiedContent = content;
|
|
1038
|
+
// Add import statement
|
|
1039
|
+
if (!content.includes(importStatement)) {
|
|
1040
|
+
modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
|
|
1041
|
+
// If no Vue import found, add it at the top
|
|
1042
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
1043
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
// Handle createApp pattern
|
|
1047
|
+
if (content.includes('createApp')) {
|
|
1048
|
+
modifiedContent = modifiedContent.replace(/(app\.mount\(.*?\))/, `${pluginUsage}\n\n$1`);
|
|
1049
|
+
}
|
|
1050
|
+
return modifiedContent;
|
|
783
1051
|
}
|
|
784
1052
|
else {
|
|
785
|
-
// Vue 2
|
|
786
|
-
|
|
1053
|
+
// Vue 2 with Options API
|
|
1054
|
+
const pluginUsage = `Vue.use(HumanBehaviorPlugin, {
|
|
1055
|
+
apiKey: process.env.VUE_APP_HUMANBEHAVIOR_API_KEY
|
|
1056
|
+
});`;
|
|
1057
|
+
let modifiedContent = content;
|
|
1058
|
+
// Add import statement
|
|
1059
|
+
if (!content.includes(importStatement)) {
|
|
1060
|
+
modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
|
|
1061
|
+
if (!modifiedContent.includes(importStatement)) {
|
|
1062
|
+
modifiedContent = `${importStatement}\n\n${modifiedContent}`;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
// Handle new Vue pattern
|
|
1066
|
+
if (content.includes('new Vue')) {
|
|
1067
|
+
modifiedContent = modifiedContent.replace(/(new Vue\(.*?\))/, `${pluginUsage}\n\n$1`);
|
|
1068
|
+
}
|
|
1069
|
+
return modifiedContent;
|
|
787
1070
|
}
|
|
788
1071
|
}
|
|
789
1072
|
injectAngularModule(content) {
|
|
@@ -864,17 +1147,99 @@ if (typeof window !== 'undefined') {
|
|
|
864
1147
|
</script>`;
|
|
865
1148
|
return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
|
|
866
1149
|
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Inject Astro layout with HumanBehavior component
|
|
1152
|
+
*/
|
|
1153
|
+
injectAstroLayout(content) {
|
|
1154
|
+
// Check if HumanBehavior component is already imported
|
|
1155
|
+
if (content.includes('HumanBehavior') || content.includes('humanbehavior-js')) {
|
|
1156
|
+
return content; // Already has HumanBehavior
|
|
1157
|
+
}
|
|
1158
|
+
// Add import inside frontmatter if not present
|
|
1159
|
+
let modifiedContent = content;
|
|
1160
|
+
if (!content.includes('import HumanBehavior')) {
|
|
1161
|
+
const importStatement = 'import HumanBehavior from \'../components/HumanBehavior.astro\';';
|
|
1162
|
+
const frontmatterEndIndex = content.indexOf('---', 3);
|
|
1163
|
+
if (frontmatterEndIndex !== -1) {
|
|
1164
|
+
// Insert import inside frontmatter, before the closing ---
|
|
1165
|
+
modifiedContent = content.slice(0, frontmatterEndIndex) + '\n' + importStatement + '\n' + content.slice(frontmatterEndIndex);
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
// No frontmatter, add at the very beginning
|
|
1169
|
+
modifiedContent = '---\n' + importStatement + '\n---\n\n' + content;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
// Find the closing </body> tag and add HumanBehavior component before it
|
|
1173
|
+
const bodyCloseIndex = modifiedContent.lastIndexOf('</body>');
|
|
1174
|
+
if (bodyCloseIndex === -1) {
|
|
1175
|
+
// No body tag found, append to end
|
|
1176
|
+
return modifiedContent + '\n\n<HumanBehavior />';
|
|
1177
|
+
}
|
|
1178
|
+
// Add component before closing body tag
|
|
1179
|
+
return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
|
|
1180
|
+
}
|
|
867
1181
|
injectNuxtConfig(content) {
|
|
1182
|
+
var _a, _b;
|
|
868
1183
|
if (content.includes('humanBehaviorApiKey')) {
|
|
869
1184
|
return content;
|
|
870
1185
|
}
|
|
871
|
-
//
|
|
872
|
-
|
|
1186
|
+
// Enhanced Nuxt 3 support with version detection
|
|
1187
|
+
const hasNuxt3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasNuxt3;
|
|
1188
|
+
if (hasNuxt3) {
|
|
1189
|
+
// Nuxt 3 with runtime config
|
|
1190
|
+
return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
|
|
873
1191
|
runtimeConfig: {
|
|
874
1192
|
public: {
|
|
875
1193
|
humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
|
|
876
1194
|
}
|
|
877
1195
|
},`);
|
|
1196
|
+
}
|
|
1197
|
+
else {
|
|
1198
|
+
// Nuxt 2 with env config
|
|
1199
|
+
return content.replace(/export default \{/, `export default {
|
|
1200
|
+
env: {
|
|
1201
|
+
humanBehaviorApiKey: process.env.HUMANBEHAVIOR_API_KEY
|
|
1202
|
+
},`);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
injectGatsbyLayout(content) {
|
|
1206
|
+
if (content.includes('HumanBehavior')) {
|
|
1207
|
+
return content;
|
|
1208
|
+
}
|
|
1209
|
+
const importStatement = `import HumanBehavior from './HumanBehavior';`;
|
|
1210
|
+
const componentUsage = `<HumanBehavior apiKey={process.env.GATSBY_HUMANBEHAVIOR_API_KEY || ''} />`;
|
|
1211
|
+
// Add import at the top
|
|
1212
|
+
let modifiedContent = content.replace(/import.*from.*['"]\./, `${importStatement}\n$&`);
|
|
1213
|
+
// Add component before closing body tag
|
|
1214
|
+
modifiedContent = modifiedContent.replace(/(\s*<\/body>)/, `\n ${componentUsage}\n$1`);
|
|
1215
|
+
return modifiedContent;
|
|
1216
|
+
}
|
|
1217
|
+
injectGatsbyBrowser(content) {
|
|
1218
|
+
if (content.includes('HumanBehaviorTracker')) {
|
|
1219
|
+
return content;
|
|
1220
|
+
}
|
|
1221
|
+
const importStatement = `import { HumanBehaviorTracker } from 'humanbehavior-js';`;
|
|
1222
|
+
const initCode = `
|
|
1223
|
+
// Initialize HumanBehavior SDK
|
|
1224
|
+
export const onClientEntry = () => {
|
|
1225
|
+
console.log('Gatsby browser entry point loaded');
|
|
1226
|
+
const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
|
|
1227
|
+
console.log('API Key found:', apiKey ? 'Yes' : 'No');
|
|
1228
|
+
if (apiKey) {
|
|
1229
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
1230
|
+
console.log('HumanBehavior SDK initialized for Gatsby');
|
|
1231
|
+
} else {
|
|
1232
|
+
console.log('No API key found in environment variables');
|
|
1233
|
+
}
|
|
1234
|
+
};`;
|
|
1235
|
+
// If the file already has content, add the import and init code
|
|
1236
|
+
if (content.trim()) {
|
|
1237
|
+
return `${importStatement}${initCode}\n\n${content}`;
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
// If file is empty, just return the new content
|
|
1241
|
+
return `${importStatement}${initCode}`;
|
|
1242
|
+
}
|
|
878
1243
|
}
|
|
879
1244
|
/**
|
|
880
1245
|
* Helper method to find the best environment file for a framework
|
|
@@ -905,6 +1270,8 @@ if (typeof window !== 'undefined') {
|
|
|
905
1270
|
nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
|
|
906
1271
|
remix: 'HUMANBEHAVIOR_API_KEY',
|
|
907
1272
|
vanilla: 'HUMANBEHAVIOR_API_KEY',
|
|
1273
|
+
astro: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
|
|
1274
|
+
gatsby: 'GATSBY_HUMANBEHAVIOR_API_KEY',
|
|
908
1275
|
node: 'HUMANBEHAVIOR_API_KEY',
|
|
909
1276
|
auto: 'HUMANBEHAVIOR_API_KEY'
|
|
910
1277
|
};
|
|
@@ -928,6 +1295,8 @@ if (typeof window !== 'undefined') {
|
|
|
928
1295
|
nuxt: '.env',
|
|
929
1296
|
remix: '.env.local',
|
|
930
1297
|
vanilla: '.env',
|
|
1298
|
+
astro: '.env',
|
|
1299
|
+
gatsby: '.env.development',
|
|
931
1300
|
node: '.env',
|
|
932
1301
|
auto: '.env'
|
|
933
1302
|
};
|
|
@@ -942,6 +1311,8 @@ if (typeof window !== 'undefined') {
|
|
|
942
1311
|
*/
|
|
943
1312
|
createEnvironmentModification(framework) {
|
|
944
1313
|
const { filePath, envVarName } = this.findBestEnvFile(framework);
|
|
1314
|
+
// Clean the API key to prevent formatting issues
|
|
1315
|
+
const cleanApiKey = this.apiKey.trim();
|
|
945
1316
|
if (fs.existsSync(filePath)) {
|
|
946
1317
|
// Check if the variable already exists
|
|
947
1318
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
@@ -959,7 +1330,7 @@ if (typeof window !== 'undefined') {
|
|
|
959
1330
|
return {
|
|
960
1331
|
filePath,
|
|
961
1332
|
action: 'append',
|
|
962
|
-
content: `\n${envVarName}=${
|
|
1333
|
+
content: `\n${envVarName}=${cleanApiKey}`,
|
|
963
1334
|
description: `Added API key to existing ${path.basename(filePath)}`
|
|
964
1335
|
};
|
|
965
1336
|
}
|
|
@@ -969,13 +1340,435 @@ if (typeof window !== 'undefined') {
|
|
|
969
1340
|
return {
|
|
970
1341
|
filePath,
|
|
971
1342
|
action: 'create',
|
|
972
|
-
content: `${envVarName}=${
|
|
1343
|
+
content: `${envVarName}=${cleanApiKey}`,
|
|
973
1344
|
description: `Created ${path.basename(filePath)} with API key`
|
|
974
1345
|
};
|
|
975
1346
|
}
|
|
976
1347
|
}
|
|
977
1348
|
}
|
|
978
1349
|
|
|
1350
|
+
/**
|
|
1351
|
+
* Remote AI Service Implementation
|
|
1352
|
+
*
|
|
1353
|
+
* This connects to your deployed Lambda function via API Gateway
|
|
1354
|
+
*/
|
|
1355
|
+
class RemoteAIService {
|
|
1356
|
+
constructor(config) {
|
|
1357
|
+
this.config = Object.assign({ timeout: 10000 }, config);
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Analyze code patterns using your deployed AI service
|
|
1361
|
+
*/
|
|
1362
|
+
analyzeCodePatterns(codeSamples) {
|
|
1363
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1364
|
+
try {
|
|
1365
|
+
const response = yield fetch(`${this.config.apiEndpoint}/analyze`, {
|
|
1366
|
+
method: 'POST',
|
|
1367
|
+
headers: {
|
|
1368
|
+
'Content-Type': 'application/json',
|
|
1369
|
+
},
|
|
1370
|
+
body: JSON.stringify({ codeSamples }),
|
|
1371
|
+
signal: AbortSignal.timeout(this.config.timeout || 10000)
|
|
1372
|
+
});
|
|
1373
|
+
if (!response.ok) {
|
|
1374
|
+
throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
|
|
1375
|
+
}
|
|
1376
|
+
const result = yield response.json();
|
|
1377
|
+
return result.analysis;
|
|
1378
|
+
}
|
|
1379
|
+
catch (error) {
|
|
1380
|
+
console.warn('Remote AI service failed, falling back to heuristic analysis:', error);
|
|
1381
|
+
return this.performHeuristicAnalysis(codeSamples);
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Resolve conflicts using your deployed AI service
|
|
1387
|
+
*/
|
|
1388
|
+
resolveConflicts(conflicts, framework) {
|
|
1389
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1390
|
+
try {
|
|
1391
|
+
const response = yield fetch(`${this.config.apiEndpoint}/resolve-conflicts`, {
|
|
1392
|
+
method: 'POST',
|
|
1393
|
+
headers: {
|
|
1394
|
+
'Content-Type': 'application/json',
|
|
1395
|
+
},
|
|
1396
|
+
body: JSON.stringify({ conflicts, framework }),
|
|
1397
|
+
signal: AbortSignal.timeout(this.config.timeout || 10000)
|
|
1398
|
+
});
|
|
1399
|
+
if (!response.ok) {
|
|
1400
|
+
throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
|
|
1401
|
+
}
|
|
1402
|
+
const result = yield response.json();
|
|
1403
|
+
return result.resolutions || [];
|
|
1404
|
+
}
|
|
1405
|
+
catch (error) {
|
|
1406
|
+
console.warn('Remote AI conflict resolution failed, using heuristic approach:', error);
|
|
1407
|
+
return this.resolveConflictsHeuristic(conflicts, framework);
|
|
1408
|
+
}
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Generate optimizations using your deployed AI service
|
|
1413
|
+
*/
|
|
1414
|
+
generateOptimizations(framework, patterns) {
|
|
1415
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1416
|
+
try {
|
|
1417
|
+
const response = yield fetch(`${this.config.apiEndpoint}/optimize`, {
|
|
1418
|
+
method: 'POST',
|
|
1419
|
+
headers: {
|
|
1420
|
+
'Content-Type': 'application/json',
|
|
1421
|
+
},
|
|
1422
|
+
body: JSON.stringify({ framework, patterns }),
|
|
1423
|
+
signal: AbortSignal.timeout(this.config.timeout || 10000)
|
|
1424
|
+
});
|
|
1425
|
+
if (!response.ok) {
|
|
1426
|
+
throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
|
|
1427
|
+
}
|
|
1428
|
+
const result = yield response.json();
|
|
1429
|
+
return result.optimizations || [];
|
|
1430
|
+
}
|
|
1431
|
+
catch (error) {
|
|
1432
|
+
console.warn('Remote AI optimization generation failed, using heuristic approach:', error);
|
|
1433
|
+
return this.generateOptimizationsHeuristic(framework, patterns);
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1438
|
+
* Heuristic analysis fallback
|
|
1439
|
+
*/
|
|
1440
|
+
performHeuristicAnalysis(codeSamples) {
|
|
1441
|
+
const patterns = codeSamples.join(' ').toLowerCase();
|
|
1442
|
+
// Framework detection
|
|
1443
|
+
let framework = { name: 'vanilla', type: 'vanilla' };
|
|
1444
|
+
let confidence = 0.5;
|
|
1445
|
+
if (patterns.includes('nuxt') || patterns.includes('nuxtjs') || patterns.includes('defineNuxtConfig') || patterns.includes('nuxt.config') || patterns.includes('@nuxt/') || patterns.includes('useNuxtApp') || patterns.includes('useRuntimeConfig') || patterns.includes('useSeoMeta') || patterns.includes('useHead') || patterns.includes('useLazyFetch') || patterns.includes('useFetch') || patterns.includes('useAsyncData') || patterns.includes('#app')) {
|
|
1446
|
+
framework = { name: 'nuxt', type: 'nuxt' };
|
|
1447
|
+
confidence = 0.95;
|
|
1448
|
+
}
|
|
1449
|
+
else if (patterns.includes('next') || patterns.includes('nextjs') || patterns.includes('next/link') || patterns.includes('next/image') || patterns.includes('next/navigation') || patterns.includes('next/router') || patterns.includes('getserverSideProps') || patterns.includes('getstaticProps') || patterns.includes('getstaticPaths') || patterns.includes('app/layout') || patterns.includes('app/page') || patterns.includes('pages/')) {
|
|
1450
|
+
framework = { name: 'nextjs', type: 'nextjs' };
|
|
1451
|
+
confidence = 0.95;
|
|
1452
|
+
}
|
|
1453
|
+
else if (patterns.includes('gatsby') || patterns.includes('gatsby-browser') || patterns.includes('gatsby-ssr') || patterns.includes('gatsby-node') || patterns.includes('gatsby-config') || patterns.includes('useStaticQuery') || patterns.includes('graphql')) {
|
|
1454
|
+
framework = { name: 'gatsby', type: 'gatsby' };
|
|
1455
|
+
confidence = 0.95;
|
|
1456
|
+
}
|
|
1457
|
+
else if (patterns.includes('react')) {
|
|
1458
|
+
framework = { name: 'react', type: 'react' };
|
|
1459
|
+
confidence = 0.9;
|
|
1460
|
+
}
|
|
1461
|
+
else if (patterns.includes('vue')) {
|
|
1462
|
+
framework = { name: 'vue', type: 'vue' };
|
|
1463
|
+
confidence = 0.9;
|
|
1464
|
+
}
|
|
1465
|
+
else if (patterns.includes('angular')) {
|
|
1466
|
+
framework = { name: 'angular', type: 'angular' };
|
|
1467
|
+
confidence = 0.9;
|
|
1468
|
+
}
|
|
1469
|
+
else if (patterns.includes('svelte')) {
|
|
1470
|
+
framework = { name: 'svelte', type: 'svelte' };
|
|
1471
|
+
confidence = 0.9;
|
|
1472
|
+
}
|
|
1473
|
+
else if (patterns.includes('astro')) {
|
|
1474
|
+
framework = { name: 'astro', type: 'astro' };
|
|
1475
|
+
confidence = 0.9;
|
|
1476
|
+
}
|
|
1477
|
+
// Integration strategy
|
|
1478
|
+
let integrationStrategy = 'script';
|
|
1479
|
+
if (framework.type === 'react' || framework.type === 'nextjs' || framework.type === 'gatsby') {
|
|
1480
|
+
integrationStrategy = 'provider';
|
|
1481
|
+
}
|
|
1482
|
+
else if (framework.type === 'vue') {
|
|
1483
|
+
integrationStrategy = 'plugin';
|
|
1484
|
+
}
|
|
1485
|
+
else if (framework.type === 'angular') {
|
|
1486
|
+
integrationStrategy = 'module';
|
|
1487
|
+
}
|
|
1488
|
+
// Compatibility mode
|
|
1489
|
+
let compatibilityMode = 'modern';
|
|
1490
|
+
if (patterns.includes('require(') || patterns.includes('var ')) {
|
|
1491
|
+
compatibilityMode = 'legacy';
|
|
1492
|
+
}
|
|
1493
|
+
return {
|
|
1494
|
+
framework,
|
|
1495
|
+
confidence,
|
|
1496
|
+
patterns: codeSamples,
|
|
1497
|
+
conflicts: [],
|
|
1498
|
+
recommendations: [],
|
|
1499
|
+
integrationStrategy,
|
|
1500
|
+
compatibilityMode
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Heuristic conflict resolution
|
|
1505
|
+
*/
|
|
1506
|
+
resolveConflictsHeuristic(conflicts, framework) {
|
|
1507
|
+
const resolutions = [];
|
|
1508
|
+
for (const conflict of conflicts) {
|
|
1509
|
+
switch (conflict) {
|
|
1510
|
+
case 'existing_humanbehavior_code':
|
|
1511
|
+
resolutions.push('update_existing_integration');
|
|
1512
|
+
break;
|
|
1513
|
+
case 'existing_provider':
|
|
1514
|
+
resolutions.push('merge_providers');
|
|
1515
|
+
break;
|
|
1516
|
+
case 'module_system_conflict':
|
|
1517
|
+
resolutions.push('hybrid_module_support');
|
|
1518
|
+
break;
|
|
1519
|
+
default:
|
|
1520
|
+
resolutions.push('skip_conflict');
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
return resolutions;
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Heuristic optimization generation
|
|
1527
|
+
*/
|
|
1528
|
+
generateOptimizationsHeuristic(framework, patterns) {
|
|
1529
|
+
const optimizations = [];
|
|
1530
|
+
switch (framework.type) {
|
|
1531
|
+
case 'react':
|
|
1532
|
+
optimizations.push('Use React.memo for performance optimization');
|
|
1533
|
+
optimizations.push('Implement error boundaries for better error tracking');
|
|
1534
|
+
optimizations.push('Consider using React.lazy for code splitting');
|
|
1535
|
+
break;
|
|
1536
|
+
case 'vue':
|
|
1537
|
+
optimizations.push('Use Vue 3 Composition API for better performance');
|
|
1538
|
+
optimizations.push('Implement proper error handling in components');
|
|
1539
|
+
optimizations.push('Consider using Vue Router for navigation tracking');
|
|
1540
|
+
break;
|
|
1541
|
+
case 'angular':
|
|
1542
|
+
optimizations.push('Use Angular standalone components for better tree-shaking');
|
|
1543
|
+
optimizations.push('Implement proper error handling with ErrorHandler');
|
|
1544
|
+
optimizations.push('Consider using Angular signals for state management');
|
|
1545
|
+
break;
|
|
1546
|
+
default:
|
|
1547
|
+
optimizations.push('Enable performance tracking');
|
|
1548
|
+
optimizations.push('Implement error tracking');
|
|
1549
|
+
optimizations.push('Consider progressive enhancement');
|
|
1550
|
+
}
|
|
1551
|
+
return optimizations;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
/**
|
|
1556
|
+
* Manual Framework Installation Wizard
|
|
1557
|
+
*
|
|
1558
|
+
* This wizard allows users to manually specify their framework instead of auto-detection.
|
|
1559
|
+
* Useful when auto-detection fails or users want more control.
|
|
1560
|
+
*/
|
|
1561
|
+
class ManualFrameworkInstallationWizard extends AutoInstallationWizard {
|
|
1562
|
+
constructor(apiKey, projectRoot = process.cwd(), framework) {
|
|
1563
|
+
super(apiKey, projectRoot);
|
|
1564
|
+
this.selectedFramework = framework.toLowerCase();
|
|
1565
|
+
this.framework = this.createFrameworkInfo(this.selectedFramework);
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Manual installation with user-specified framework
|
|
1569
|
+
*/
|
|
1570
|
+
install() {
|
|
1571
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1572
|
+
try {
|
|
1573
|
+
// Step 1: Handle framework selection
|
|
1574
|
+
if (this.selectedFramework === 'auto') {
|
|
1575
|
+
// Use full AI detection for "Other" option
|
|
1576
|
+
this.framework = yield this.runFullDetection();
|
|
1577
|
+
}
|
|
1578
|
+
else {
|
|
1579
|
+
// Set framework based on user selection
|
|
1580
|
+
this.framework = this.createFrameworkInfo(this.selectedFramework);
|
|
1581
|
+
if (!this.framework) {
|
|
1582
|
+
this.framework = { name: 'unknown', type: 'vanilla' };
|
|
1583
|
+
}
|
|
1584
|
+
// Step 2: Run full detection logic to find entry points, file names, etc.
|
|
1585
|
+
const detectedFramework = yield this.runFullDetection();
|
|
1586
|
+
// Step 3: Merge manual framework with detected details
|
|
1587
|
+
this.framework = Object.assign(Object.assign({}, detectedFramework), { name: this.framework.name, type: this.framework.type });
|
|
1588
|
+
}
|
|
1589
|
+
// Step 4: Install package
|
|
1590
|
+
yield this.installPackage();
|
|
1591
|
+
// Step 5: Generate and apply code modifications
|
|
1592
|
+
const modifications = yield this.generateModifications();
|
|
1593
|
+
yield this.applyModifications(modifications);
|
|
1594
|
+
// Step 6: Generate next steps
|
|
1595
|
+
const nextSteps = this.generateManualNextSteps();
|
|
1596
|
+
return {
|
|
1597
|
+
success: true,
|
|
1598
|
+
framework: this.framework,
|
|
1599
|
+
modifications,
|
|
1600
|
+
errors: [],
|
|
1601
|
+
nextSteps,
|
|
1602
|
+
selectedFramework: this.selectedFramework,
|
|
1603
|
+
manualMode: true
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
catch (error) {
|
|
1607
|
+
return {
|
|
1608
|
+
success: false,
|
|
1609
|
+
framework: this.framework || { name: 'unknown', type: 'vanilla' },
|
|
1610
|
+
modifications: [],
|
|
1611
|
+
errors: [error instanceof Error ? error.message : 'Unknown error'],
|
|
1612
|
+
nextSteps: [],
|
|
1613
|
+
selectedFramework: this.selectedFramework,
|
|
1614
|
+
manualMode: true
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Run full detection logic to find entry points, file names, bundler, etc.
|
|
1621
|
+
*/
|
|
1622
|
+
runFullDetection() {
|
|
1623
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1624
|
+
if (this.selectedFramework === 'auto') {
|
|
1625
|
+
// Use AI service for auto-detection
|
|
1626
|
+
const aiService = new RemoteAIService({
|
|
1627
|
+
apiEndpoint: 'https://ik3zxh4790.execute-api.us-east-1.amazonaws.com/prod'
|
|
1628
|
+
});
|
|
1629
|
+
// Use AI service directly for detection
|
|
1630
|
+
const projectFiles = yield this.scanProjectFiles();
|
|
1631
|
+
const codeSamples = yield this.extractCodeSamples(projectFiles);
|
|
1632
|
+
const aiAnalysis = yield aiService.analyzeCodePatterns(codeSamples);
|
|
1633
|
+
return aiAnalysis.framework;
|
|
1634
|
+
}
|
|
1635
|
+
else {
|
|
1636
|
+
// Use traditional detection for manual frameworks
|
|
1637
|
+
const tempWizard = new AutoInstallationWizard(this.apiKey, this.projectRoot);
|
|
1638
|
+
const detected = yield tempWizard.detectFramework();
|
|
1639
|
+
return detected;
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Scan project files for analysis
|
|
1645
|
+
*/
|
|
1646
|
+
scanProjectFiles() {
|
|
1647
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1648
|
+
const files = [];
|
|
1649
|
+
const scanDir = (dir, depth = 0) => {
|
|
1650
|
+
if (depth > 3)
|
|
1651
|
+
return; // Limit depth
|
|
1652
|
+
try {
|
|
1653
|
+
const items = fs.readdirSync(dir);
|
|
1654
|
+
for (const item of items) {
|
|
1655
|
+
const fullPath = path.join(dir, item);
|
|
1656
|
+
const stat = fs.statSync(fullPath);
|
|
1657
|
+
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
|
|
1658
|
+
scanDir(fullPath, depth + 1);
|
|
1659
|
+
}
|
|
1660
|
+
else if (stat.isFile() && this.isRelevantFile(item)) {
|
|
1661
|
+
files.push(fullPath);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
catch (error) {
|
|
1666
|
+
// Skip inaccessible directories
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
scanDir(this.projectRoot);
|
|
1670
|
+
return files;
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Check if file is relevant for analysis
|
|
1675
|
+
*/
|
|
1676
|
+
isRelevantFile(filename) {
|
|
1677
|
+
const relevantExtensions = [
|
|
1678
|
+
'.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte', '.html',
|
|
1679
|
+
'.json', '.config.js', '.config.ts', '.babelrc', '.eslintrc'
|
|
1680
|
+
];
|
|
1681
|
+
const relevantNames = [
|
|
1682
|
+
'package.json', 'tsconfig.json', 'vite.config', 'webpack.config',
|
|
1683
|
+
'next.config', 'nuxt.config', 'angular.json', 'svelte.config'
|
|
1684
|
+
];
|
|
1685
|
+
return relevantExtensions.some(ext => filename.endsWith(ext)) ||
|
|
1686
|
+
relevantNames.some(name => filename.includes(name));
|
|
1687
|
+
}
|
|
1688
|
+
/**
|
|
1689
|
+
* Extract code samples for AI analysis
|
|
1690
|
+
*/
|
|
1691
|
+
extractCodeSamples(files) {
|
|
1692
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1693
|
+
const samples = [];
|
|
1694
|
+
for (const file of files.slice(0, 20)) { // Limit to 20 files
|
|
1695
|
+
try {
|
|
1696
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
1697
|
+
const relativePath = path.relative(this.projectRoot, file);
|
|
1698
|
+
samples.push(`File: ${relativePath}\n${content.substring(0, 1000)}`);
|
|
1699
|
+
}
|
|
1700
|
+
catch (error) {
|
|
1701
|
+
// Skip unreadable files
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
return samples;
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
/**
|
|
1708
|
+
* Create framework info based on user selection
|
|
1709
|
+
*/
|
|
1710
|
+
createFrameworkInfo(framework) {
|
|
1711
|
+
const frameworkMap = {
|
|
1712
|
+
'react': { name: 'react', type: 'react' },
|
|
1713
|
+
'nextjs': { name: 'nextjs', type: 'nextjs' },
|
|
1714
|
+
'next': { name: 'nextjs', type: 'nextjs' },
|
|
1715
|
+
'vue': { name: 'vue', type: 'vue' },
|
|
1716
|
+
'nuxt': { name: 'nuxt', type: 'nuxt' },
|
|
1717
|
+
'nuxtjs': { name: 'nuxt', type: 'nuxt' },
|
|
1718
|
+
'angular': { name: 'angular', type: 'angular' },
|
|
1719
|
+
'svelte': { name: 'svelte', type: 'svelte' },
|
|
1720
|
+
'sveltekit': { name: 'svelte', type: 'svelte' },
|
|
1721
|
+
'remix': { name: 'remix', type: 'remix' },
|
|
1722
|
+
'astro': { name: 'astro', type: 'astro' },
|
|
1723
|
+
'gatsby': { name: 'gatsby', type: 'gatsby' },
|
|
1724
|
+
'vanilla': { name: 'vanilla', type: 'vanilla' },
|
|
1725
|
+
'node': { name: 'node', type: 'node' },
|
|
1726
|
+
'auto': { name: 'auto-detected', type: 'auto' }
|
|
1727
|
+
};
|
|
1728
|
+
return frameworkMap[framework] || { name: framework, type: 'vanilla' };
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Override framework detection to use manual selection
|
|
1732
|
+
*/
|
|
1733
|
+
detectFramework() {
|
|
1734
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1735
|
+
return this.framework || { name: 'unknown', type: 'vanilla' };
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Generate next steps with manual mode info
|
|
1740
|
+
*/
|
|
1741
|
+
generateManualNextSteps() {
|
|
1742
|
+
var _a;
|
|
1743
|
+
return [
|
|
1744
|
+
'ā
Manual framework installation completed!',
|
|
1745
|
+
`šÆ Selected framework: ${((_a = this.framework) === null || _a === void 0 ? void 0 : _a.name) || 'unknown'}`,
|
|
1746
|
+
`š§ Integration strategy: ${this.getIntegrationStrategy()}`,
|
|
1747
|
+
'š Your app is now ready to track user behavior',
|
|
1748
|
+
'š View sessions in your HumanBehavior dashboard'
|
|
1749
|
+
];
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Get integration strategy based on framework
|
|
1753
|
+
*/
|
|
1754
|
+
getIntegrationStrategy() {
|
|
1755
|
+
var _a;
|
|
1756
|
+
if (!((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type))
|
|
1757
|
+
return 'script';
|
|
1758
|
+
switch (this.framework.type) {
|
|
1759
|
+
case 'react':
|
|
1760
|
+
case 'nextjs':
|
|
1761
|
+
return 'provider';
|
|
1762
|
+
case 'vue':
|
|
1763
|
+
return 'plugin';
|
|
1764
|
+
case 'angular':
|
|
1765
|
+
return 'module';
|
|
1766
|
+
default:
|
|
1767
|
+
return 'script';
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
|
|
979
1772
|
/**
|
|
980
1773
|
* HumanBehavior SDK Auto-Installation CLI
|
|
981
1774
|
*
|
|
@@ -987,46 +1780,46 @@ if (typeof window !== 'undefined') {
|
|
|
987
1780
|
class AutoInstallCLI {
|
|
988
1781
|
constructor(options) {
|
|
989
1782
|
this.options = options;
|
|
990
|
-
this.rl = readline.createInterface({
|
|
991
|
-
input: process.stdin,
|
|
992
|
-
output: process.stdout
|
|
993
|
-
});
|
|
994
1783
|
}
|
|
995
1784
|
run() {
|
|
996
1785
|
return __awaiter(this, void 0, void 0, function* () {
|
|
997
|
-
|
|
998
|
-
console.log('=====================================\n');
|
|
1786
|
+
clack.intro('š HumanBehavior SDK Auto-Installation');
|
|
999
1787
|
try {
|
|
1000
1788
|
// Get API key
|
|
1001
1789
|
const apiKey = yield this.getApiKey();
|
|
1002
1790
|
if (!apiKey) {
|
|
1003
|
-
|
|
1791
|
+
clack.cancel('API key is required');
|
|
1004
1792
|
process.exit(1);
|
|
1005
1793
|
}
|
|
1006
1794
|
// Get project path
|
|
1007
1795
|
const projectPath = this.options.projectPath || process.cwd();
|
|
1796
|
+
// Choose framework
|
|
1797
|
+
const framework = yield this.chooseFramework();
|
|
1798
|
+
if (!framework) {
|
|
1799
|
+
clack.cancel('Installation cancelled.');
|
|
1800
|
+
process.exit(0);
|
|
1801
|
+
}
|
|
1008
1802
|
// Confirm installation
|
|
1009
1803
|
if (!this.options.yes) {
|
|
1010
|
-
const confirmed = yield this.confirmInstallation(projectPath);
|
|
1804
|
+
const confirmed = yield this.confirmInstallation(projectPath, framework);
|
|
1011
1805
|
if (!confirmed) {
|
|
1012
|
-
|
|
1806
|
+
clack.cancel('Installation cancelled.');
|
|
1013
1807
|
process.exit(0);
|
|
1014
1808
|
}
|
|
1015
1809
|
}
|
|
1016
|
-
// Run
|
|
1017
|
-
|
|
1018
|
-
|
|
1810
|
+
// Run installation
|
|
1811
|
+
const spinner = clack.spinner();
|
|
1812
|
+
spinner.start('š Analyzing your project...');
|
|
1813
|
+
const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
|
|
1019
1814
|
const result = yield wizard.install();
|
|
1815
|
+
spinner.stop('Detection complete!');
|
|
1020
1816
|
// Display results
|
|
1021
1817
|
this.displayResults(result);
|
|
1022
1818
|
}
|
|
1023
1819
|
catch (error) {
|
|
1024
|
-
|
|
1820
|
+
clack.cancel(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1025
1821
|
process.exit(1);
|
|
1026
1822
|
}
|
|
1027
|
-
finally {
|
|
1028
|
-
this.rl.close();
|
|
1029
|
-
}
|
|
1030
1823
|
});
|
|
1031
1824
|
}
|
|
1032
1825
|
getApiKey() {
|
|
@@ -1034,139 +1827,131 @@ class AutoInstallCLI {
|
|
|
1034
1827
|
if (this.options.apiKey) {
|
|
1035
1828
|
return this.options.apiKey;
|
|
1036
1829
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1830
|
+
const apiKey = yield clack.text({
|
|
1831
|
+
message: 'Enter your HumanBehavior API key:',
|
|
1832
|
+
placeholder: 'hb_...',
|
|
1833
|
+
validate: (value) => {
|
|
1834
|
+
if (!value)
|
|
1835
|
+
return 'API key is required';
|
|
1836
|
+
if (!value.startsWith('hb_'))
|
|
1837
|
+
return 'API key should start with "hb_"';
|
|
1838
|
+
return undefined;
|
|
1839
|
+
}
|
|
1041
1840
|
});
|
|
1841
|
+
return apiKey;
|
|
1042
1842
|
});
|
|
1043
1843
|
}
|
|
1044
|
-
|
|
1844
|
+
chooseFramework() {
|
|
1045
1845
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1846
|
+
const framework = yield clack.select({
|
|
1847
|
+
message: 'Select your framework:',
|
|
1848
|
+
options: [
|
|
1849
|
+
{ label: 'React', value: 'react' },
|
|
1850
|
+
{ label: 'Next.js', value: 'nextjs' },
|
|
1851
|
+
{ label: 'Vue', value: 'vue' },
|
|
1852
|
+
{ label: 'Angular', value: 'angular' },
|
|
1853
|
+
{ label: 'Svelte', value: 'svelte' },
|
|
1854
|
+
{ label: 'Nuxt.js', value: 'nuxt' },
|
|
1855
|
+
{ label: 'Remix', value: 'remix' },
|
|
1856
|
+
{ label: 'Astro', value: 'astro' },
|
|
1857
|
+
{ label: 'Gatsby', value: 'gatsby' },
|
|
1858
|
+
{ label: 'Vanilla JS/TS', value: 'vanilla' }
|
|
1859
|
+
]
|
|
1057
1860
|
});
|
|
1861
|
+
return framework;
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
confirmInstallation(projectPath, framework) {
|
|
1865
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1866
|
+
const confirmed = yield clack.confirm({
|
|
1867
|
+
message: `Ready to install HumanBehavior SDK in ${projectPath} for ${framework}?`
|
|
1868
|
+
});
|
|
1869
|
+
return confirmed;
|
|
1058
1870
|
});
|
|
1059
1871
|
}
|
|
1060
1872
|
displayResults(result) {
|
|
1061
1873
|
if (result.success) {
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
result.
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
});
|
|
1075
|
-
console.log('\nšÆ Next steps:');
|
|
1076
|
-
result.nextSteps.forEach((step) => {
|
|
1077
|
-
console.log(` ${step}`);
|
|
1078
|
-
});
|
|
1079
|
-
console.log('\nš Your app is now ready to track user behavior!');
|
|
1080
|
-
console.log('š View sessions in your HumanBehavior dashboard');
|
|
1874
|
+
clack.outro('š Installation completed successfully!');
|
|
1875
|
+
// Display framework info
|
|
1876
|
+
clack.note(`Framework detected: ${result.framework.name} (${result.framework.type})`, 'Framework Info');
|
|
1877
|
+
// Display modifications
|
|
1878
|
+
if (result.modifications && result.modifications.length > 0) {
|
|
1879
|
+
const modifications = result.modifications.map((mod) => `${mod.action}: ${mod.filePath} - ${mod.description}`);
|
|
1880
|
+
clack.note(modifications.join('\n'), 'Files Modified');
|
|
1881
|
+
}
|
|
1882
|
+
// Display next steps
|
|
1883
|
+
if (result.nextSteps && result.nextSteps.length > 0) {
|
|
1884
|
+
clack.note(result.nextSteps.join('\n'), 'Next Steps');
|
|
1885
|
+
}
|
|
1081
1886
|
}
|
|
1082
1887
|
else {
|
|
1083
|
-
|
|
1084
|
-
result.errors.
|
|
1085
|
-
|
|
1086
|
-
}
|
|
1087
|
-
console.log('\nš” Try running with --help for more options');
|
|
1888
|
+
clack.cancel('Installation failed');
|
|
1889
|
+
if (result.errors && result.errors.length > 0) {
|
|
1890
|
+
clack.note(result.errors.join('\n'), 'Errors');
|
|
1891
|
+
}
|
|
1088
1892
|
}
|
|
1089
1893
|
}
|
|
1090
1894
|
}
|
|
1091
|
-
// CLI argument parsing
|
|
1092
1895
|
function parseArgs() {
|
|
1093
1896
|
const args = process.argv.slice(2);
|
|
1094
1897
|
const options = {};
|
|
1095
1898
|
for (let i = 0; i < args.length; i++) {
|
|
1096
1899
|
const arg = args[i];
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1900
|
+
switch (arg) {
|
|
1901
|
+
case '--help':
|
|
1902
|
+
case '-h':
|
|
1903
|
+
showHelp();
|
|
1904
|
+
process.exit(0);
|
|
1905
|
+
break;
|
|
1906
|
+
case '--yes':
|
|
1907
|
+
case '-y':
|
|
1908
|
+
options.yes = true;
|
|
1909
|
+
break;
|
|
1910
|
+
case '--dry-run':
|
|
1911
|
+
options.dryRun = true;
|
|
1912
|
+
break;
|
|
1913
|
+
case '--project':
|
|
1914
|
+
case '-p':
|
|
1915
|
+
options.projectPath = args[++i];
|
|
1916
|
+
break;
|
|
1917
|
+
default:
|
|
1918
|
+
if (!options.apiKey && !arg.startsWith('-')) {
|
|
1919
|
+
options.apiKey = arg;
|
|
1920
|
+
}
|
|
1921
|
+
break;
|
|
1113
1922
|
}
|
|
1114
1923
|
}
|
|
1115
1924
|
return options;
|
|
1116
1925
|
}
|
|
1117
1926
|
function showHelp() {
|
|
1118
1927
|
console.log(`
|
|
1119
|
-
HumanBehavior SDK Auto-Installation
|
|
1120
|
-
|
|
1121
|
-
Usage: npx humanbehavior-js [api-key] [options]
|
|
1928
|
+
š HumanBehavior SDK Auto-Installation
|
|
1122
1929
|
|
|
1123
|
-
|
|
1124
|
-
to integrate the HumanBehavior SDK with minimal user intervention.
|
|
1930
|
+
Usage: npx humanbehavior-js auto-install [api-key] [options]
|
|
1125
1931
|
|
|
1126
|
-
|
|
1127
|
-
api-key Your HumanBehavior API key
|
|
1932
|
+
This tool automatically detects your framework and integrates the HumanBehavior SDK.
|
|
1128
1933
|
|
|
1129
1934
|
Options:
|
|
1130
|
-
-
|
|
1131
|
-
-
|
|
1132
|
-
-
|
|
1133
|
-
-
|
|
1935
|
+
-h, --help Show this help message
|
|
1936
|
+
-y, --yes Skip all prompts and use defaults
|
|
1937
|
+
--dry-run Show what would be changed without making changes
|
|
1938
|
+
-p, --project <path> Specify project directory
|
|
1134
1939
|
|
|
1135
1940
|
Examples:
|
|
1136
|
-
npx humanbehavior-js
|
|
1137
|
-
npx humanbehavior-js
|
|
1138
|
-
npx humanbehavior-js
|
|
1139
|
-
|
|
1140
|
-
Supported Frameworks:
|
|
1141
|
-
ā
React (CRA, Vite, Webpack)
|
|
1142
|
-
ā
Next.js (App Router, Pages Router)
|
|
1143
|
-
ā
Vue (Vue CLI, Vite)
|
|
1144
|
-
ā
Angular
|
|
1145
|
-
ā
Svelte (SvelteKit, Vite)
|
|
1146
|
-
ā
Remix
|
|
1147
|
-
ā
Vanilla JS/TS
|
|
1148
|
-
ā
Node.js (CommonJS & ESM)
|
|
1149
|
-
|
|
1150
|
-
The tool will:
|
|
1151
|
-
1. š Auto-detect your project's framework and setup
|
|
1152
|
-
2. š¦ Install the humanbehavior-js package
|
|
1153
|
-
3. āļø Modify your codebase to integrate the SDK
|
|
1154
|
-
4. š§ Create environment files with your API key
|
|
1155
|
-
5. š Make your app ready to track user behavior
|
|
1941
|
+
npx humanbehavior-js auto-install
|
|
1942
|
+
npx humanbehavior-js auto-install hb_your_api_key_here
|
|
1943
|
+
npx humanbehavior-js auto-install --project ./my-app --yes
|
|
1156
1944
|
`);
|
|
1157
1945
|
}
|
|
1158
1946
|
// Main execution
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1947
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
1948
|
+
const options = parseArgs();
|
|
1949
|
+
const cli = new AutoInstallCLI(options);
|
|
1950
|
+
cli.run().catch((error) => {
|
|
1951
|
+
clack.cancel(`Unexpected error: ${error.message}`);
|
|
1952
|
+
process.exit(1);
|
|
1953
|
+
});
|
|
1164
1954
|
}
|
|
1165
|
-
const cli = new AutoInstallCLI(options);
|
|
1166
|
-
cli.run().catch((error) => {
|
|
1167
|
-
console.error('ā Fatal error:', error);
|
|
1168
|
-
process.exit(1);
|
|
1169
|
-
});
|
|
1170
1955
|
|
|
1171
1956
|
export { AutoInstallCLI };
|
|
1172
1957
|
//# sourceMappingURL=auto-install.js.map
|