humanbehavior-js 0.4.13 ā 0.4.14
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 +231 -4
- package/dist/cjs/install-wizard.cjs.map +1 -1
- package/dist/cjs/wizard/index.cjs +468 -374
- 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 +355 -554
- 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 +760 -119
- package/dist/cli/auto-install.js.map +1 -1
- package/dist/esm/install-wizard.js +231 -4
- package/dist/esm/install-wizard.js.map +1 -1
- package/dist/esm/wizard/index.js +466 -373
- package/dist/esm/wizard/index.js.map +1 -1
- package/dist/types/install-wizard.d.ts +15 -1
- package/dist/types/wizard/index.d.ts +18 -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 +272 -14
- package/src/wizard/services/centralized-ai-service.ts +1 -1
- package/src/wizard/services/remote-ai-service.ts +8 -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.
|
|
@@ -165,6 +165,24 @@ class AutoInstallationWizard {
|
|
|
165
165
|
projectRoot: this.projectRoot
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
|
+
else if (dependencies.astro) {
|
|
169
|
+
framework = {
|
|
170
|
+
name: 'astro',
|
|
171
|
+
type: 'astro',
|
|
172
|
+
hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
|
|
173
|
+
hasRouter: true,
|
|
174
|
+
projectRoot: this.projectRoot
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
else if (dependencies.gatsby) {
|
|
178
|
+
framework = {
|
|
179
|
+
name: 'gatsby',
|
|
180
|
+
type: 'gatsby',
|
|
181
|
+
hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
|
|
182
|
+
hasRouter: true,
|
|
183
|
+
projectRoot: this.projectRoot
|
|
184
|
+
};
|
|
185
|
+
}
|
|
168
186
|
// Detect bundler
|
|
169
187
|
if (dependencies.vite) {
|
|
170
188
|
framework.bundler = 'vite';
|
|
@@ -196,13 +214,18 @@ class AutoInstallationWizard {
|
|
|
196
214
|
*/
|
|
197
215
|
installPackage() {
|
|
198
216
|
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
-
var _a, _b;
|
|
217
|
+
var _a, _b, _c, _d;
|
|
200
218
|
const { execSync } = yield import('child_process');
|
|
201
|
-
|
|
219
|
+
// Build base command
|
|
220
|
+
let command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
|
|
202
221
|
? 'yarn add humanbehavior-js'
|
|
203
222
|
: ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
|
|
204
223
|
? 'pnpm add humanbehavior-js'
|
|
205
224
|
: 'npm install humanbehavior-js';
|
|
225
|
+
// Add legacy peer deps flag for npm to handle dependency conflicts
|
|
226
|
+
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') {
|
|
227
|
+
command += ' --legacy-peer-deps';
|
|
228
|
+
}
|
|
206
229
|
try {
|
|
207
230
|
execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
|
|
208
231
|
}
|
|
@@ -228,6 +251,12 @@ class AutoInstallationWizard {
|
|
|
228
251
|
case 'nuxt':
|
|
229
252
|
modifications.push(...yield this.generateNuxtModifications());
|
|
230
253
|
break;
|
|
254
|
+
case 'astro':
|
|
255
|
+
modifications.push(...yield this.generateAstroModifications());
|
|
256
|
+
break;
|
|
257
|
+
case 'gatsby':
|
|
258
|
+
modifications.push(...yield this.generateGatsbyModifications());
|
|
259
|
+
break;
|
|
231
260
|
case 'remix':
|
|
232
261
|
modifications.push(...yield this.generateRemixModifications());
|
|
233
262
|
break;
|
|
@@ -339,6 +368,84 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
339
368
|
return modifications;
|
|
340
369
|
});
|
|
341
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Generate Astro-specific modifications
|
|
373
|
+
*/
|
|
374
|
+
generateAstroModifications() {
|
|
375
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
376
|
+
const modifications = [];
|
|
377
|
+
// Create Astro component for HumanBehavior
|
|
378
|
+
const astroComponentPath = path.join(this.projectRoot, 'src', 'components', 'HumanBehavior.astro');
|
|
379
|
+
const astroComponentContent = `---
|
|
380
|
+
// This component will only run on the client side
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
<script>
|
|
384
|
+
import { HumanBehaviorTracker } from 'humanbehavior-js';
|
|
385
|
+
|
|
386
|
+
// Get API key from environment variable
|
|
387
|
+
const apiKey = import.meta.env.PUBLIC_HUMANBEHAVIOR_API_KEY;
|
|
388
|
+
|
|
389
|
+
console.log('HumanBehavior: API key found:', apiKey ? 'Yes' : 'No');
|
|
390
|
+
|
|
391
|
+
if (apiKey) {
|
|
392
|
+
try {
|
|
393
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
394
|
+
console.log('HumanBehavior: Tracker initialized successfully');
|
|
395
|
+
|
|
396
|
+
// Test event to verify tracking is working
|
|
397
|
+
setTimeout(() => {
|
|
398
|
+
tracker.customEvent('astro_page_view', {
|
|
399
|
+
page: window.location.pathname,
|
|
400
|
+
framework: 'astro'
|
|
401
|
+
}).then(() => {
|
|
402
|
+
console.log('HumanBehavior: Test event sent successfully');
|
|
403
|
+
}).catch((error) => {
|
|
404
|
+
console.error('HumanBehavior: Failed to send test event:', error);
|
|
405
|
+
});
|
|
406
|
+
}, 1000);
|
|
407
|
+
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.error('HumanBehavior: Failed to initialize tracker:', error);
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
console.error('HumanBehavior: No API key found');
|
|
413
|
+
}
|
|
414
|
+
</script>`;
|
|
415
|
+
modifications.push({
|
|
416
|
+
filePath: astroComponentPath,
|
|
417
|
+
action: 'create',
|
|
418
|
+
content: astroComponentContent,
|
|
419
|
+
description: 'Created Astro component for HumanBehavior SDK'
|
|
420
|
+
});
|
|
421
|
+
// Find and update layout file
|
|
422
|
+
const layoutFiles = [
|
|
423
|
+
path.join(this.projectRoot, 'src', 'layouts', 'Layout.astro'),
|
|
424
|
+
path.join(this.projectRoot, 'src', 'layouts', 'layout.astro'),
|
|
425
|
+
path.join(this.projectRoot, 'src', 'layouts', 'BaseLayout.astro')
|
|
426
|
+
];
|
|
427
|
+
let layoutFile = null;
|
|
428
|
+
for (const file of layoutFiles) {
|
|
429
|
+
if (fs.existsSync(file)) {
|
|
430
|
+
layoutFile = file;
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (layoutFile) {
|
|
435
|
+
const content = fs.readFileSync(layoutFile, 'utf8');
|
|
436
|
+
const modifiedContent = this.injectAstroLayout(content);
|
|
437
|
+
modifications.push({
|
|
438
|
+
filePath: layoutFile,
|
|
439
|
+
action: 'modify',
|
|
440
|
+
content: modifiedContent,
|
|
441
|
+
description: 'Added HumanBehavior component to Astro layout'
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
// Add environment variable
|
|
445
|
+
modifications.push(this.createEnvironmentModification(this.framework));
|
|
446
|
+
return modifications;
|
|
447
|
+
});
|
|
448
|
+
}
|
|
342
449
|
/**
|
|
343
450
|
* Generate Nuxt-specific modifications
|
|
344
451
|
*/
|
|
@@ -559,6 +666,50 @@ export default defineNuxtPlugin(() => {
|
|
|
559
666
|
return modifications;
|
|
560
667
|
});
|
|
561
668
|
}
|
|
669
|
+
/**
|
|
670
|
+
* Generate Gatsby-specific modifications
|
|
671
|
+
*/
|
|
672
|
+
generateGatsbyModifications() {
|
|
673
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
674
|
+
const modifications = [];
|
|
675
|
+
// Modify or create gatsby-browser.js for Gatsby
|
|
676
|
+
const gatsbyBrowserFile = path.join(this.projectRoot, 'gatsby-browser.js');
|
|
677
|
+
if (fs.existsSync(gatsbyBrowserFile)) {
|
|
678
|
+
const content = fs.readFileSync(gatsbyBrowserFile, 'utf8');
|
|
679
|
+
const modifiedContent = this.injectGatsbyBrowser(content);
|
|
680
|
+
modifications.push({
|
|
681
|
+
filePath: gatsbyBrowserFile,
|
|
682
|
+
action: 'modify',
|
|
683
|
+
content: modifiedContent,
|
|
684
|
+
description: 'Added HumanBehavior initialization to Gatsby browser'
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
// Create gatsby-browser.js if it doesn't exist
|
|
689
|
+
modifications.push({
|
|
690
|
+
filePath: gatsbyBrowserFile,
|
|
691
|
+
action: 'create',
|
|
692
|
+
content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
|
|
693
|
+
|
|
694
|
+
export const onClientEntry = () => {
|
|
695
|
+
console.log('Gatsby browser entry point loaded');
|
|
696
|
+
const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
|
|
697
|
+
console.log('API Key found:', apiKey ? 'Yes' : 'No');
|
|
698
|
+
if (apiKey) {
|
|
699
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
700
|
+
console.log('HumanBehavior SDK initialized for Gatsby');
|
|
701
|
+
} else {
|
|
702
|
+
console.log('No API key found in environment variables');
|
|
703
|
+
}
|
|
704
|
+
};`,
|
|
705
|
+
description: 'Created gatsby-browser.js with HumanBehavior initialization'
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
// Create or append to environment file
|
|
709
|
+
modifications.push(this.createEnvironmentModification(this.framework));
|
|
710
|
+
return modifications;
|
|
711
|
+
});
|
|
712
|
+
}
|
|
562
713
|
/**
|
|
563
714
|
* Apply modifications to the codebase
|
|
564
715
|
*/
|
|
@@ -864,6 +1015,37 @@ if (typeof window !== 'undefined') {
|
|
|
864
1015
|
</script>`;
|
|
865
1016
|
return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
|
|
866
1017
|
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Inject Astro layout with HumanBehavior component
|
|
1020
|
+
*/
|
|
1021
|
+
injectAstroLayout(content) {
|
|
1022
|
+
// Check if HumanBehavior component is already imported
|
|
1023
|
+
if (content.includes('HumanBehavior') || content.includes('humanbehavior-js')) {
|
|
1024
|
+
return content; // Already has HumanBehavior
|
|
1025
|
+
}
|
|
1026
|
+
// Add import inside frontmatter if not present
|
|
1027
|
+
let modifiedContent = content;
|
|
1028
|
+
if (!content.includes('import HumanBehavior')) {
|
|
1029
|
+
const importStatement = 'import HumanBehavior from \'../components/HumanBehavior.astro\';';
|
|
1030
|
+
const frontmatterEndIndex = content.indexOf('---', 3);
|
|
1031
|
+
if (frontmatterEndIndex !== -1) {
|
|
1032
|
+
// Insert import inside frontmatter, before the closing ---
|
|
1033
|
+
modifiedContent = content.slice(0, frontmatterEndIndex) + '\n' + importStatement + '\n' + content.slice(frontmatterEndIndex);
|
|
1034
|
+
}
|
|
1035
|
+
else {
|
|
1036
|
+
// No frontmatter, add at the very beginning
|
|
1037
|
+
modifiedContent = '---\n' + importStatement + '\n---\n\n' + content;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
// Find the closing </body> tag and add HumanBehavior component before it
|
|
1041
|
+
const bodyCloseIndex = modifiedContent.lastIndexOf('</body>');
|
|
1042
|
+
if (bodyCloseIndex === -1) {
|
|
1043
|
+
// No body tag found, append to end
|
|
1044
|
+
return modifiedContent + '\n\n<HumanBehavior />';
|
|
1045
|
+
}
|
|
1046
|
+
// Add component before closing body tag
|
|
1047
|
+
return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
|
|
1048
|
+
}
|
|
867
1049
|
injectNuxtConfig(content) {
|
|
868
1050
|
if (content.includes('humanBehaviorApiKey')) {
|
|
869
1051
|
return content;
|
|
@@ -876,6 +1058,45 @@ if (typeof window !== 'undefined') {
|
|
|
876
1058
|
}
|
|
877
1059
|
},`);
|
|
878
1060
|
}
|
|
1061
|
+
injectGatsbyLayout(content) {
|
|
1062
|
+
if (content.includes('HumanBehavior')) {
|
|
1063
|
+
return content;
|
|
1064
|
+
}
|
|
1065
|
+
const importStatement = `import HumanBehavior from './HumanBehavior';`;
|
|
1066
|
+
const componentUsage = `<HumanBehavior apiKey={process.env.GATSBY_HUMANBEHAVIOR_API_KEY || ''} />`;
|
|
1067
|
+
// Add import at the top
|
|
1068
|
+
let modifiedContent = content.replace(/import.*from.*['"]\./, `${importStatement}\n$&`);
|
|
1069
|
+
// Add component before closing body tag
|
|
1070
|
+
modifiedContent = modifiedContent.replace(/(\s*<\/body>)/, `\n ${componentUsage}\n$1`);
|
|
1071
|
+
return modifiedContent;
|
|
1072
|
+
}
|
|
1073
|
+
injectGatsbyBrowser(content) {
|
|
1074
|
+
if (content.includes('HumanBehaviorTracker')) {
|
|
1075
|
+
return content;
|
|
1076
|
+
}
|
|
1077
|
+
const importStatement = `import { HumanBehaviorTracker } from 'humanbehavior-js';`;
|
|
1078
|
+
const initCode = `
|
|
1079
|
+
// Initialize HumanBehavior SDK
|
|
1080
|
+
export const onClientEntry = () => {
|
|
1081
|
+
console.log('Gatsby browser entry point loaded');
|
|
1082
|
+
const apiKey = process.env.GATSBY_HUMANBEHAVIOR_API_KEY;
|
|
1083
|
+
console.log('API Key found:', apiKey ? 'Yes' : 'No');
|
|
1084
|
+
if (apiKey) {
|
|
1085
|
+
const tracker = HumanBehaviorTracker.init(apiKey);
|
|
1086
|
+
console.log('HumanBehavior SDK initialized for Gatsby');
|
|
1087
|
+
} else {
|
|
1088
|
+
console.log('No API key found in environment variables');
|
|
1089
|
+
}
|
|
1090
|
+
};`;
|
|
1091
|
+
// If the file already has content, add the import and init code
|
|
1092
|
+
if (content.trim()) {
|
|
1093
|
+
return `${importStatement}${initCode}\n\n${content}`;
|
|
1094
|
+
}
|
|
1095
|
+
else {
|
|
1096
|
+
// If file is empty, just return the new content
|
|
1097
|
+
return `${importStatement}${initCode}`;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
879
1100
|
/**
|
|
880
1101
|
* Helper method to find the best environment file for a framework
|
|
881
1102
|
*/
|
|
@@ -905,6 +1126,8 @@ if (typeof window !== 'undefined') {
|
|
|
905
1126
|
nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
|
|
906
1127
|
remix: 'HUMANBEHAVIOR_API_KEY',
|
|
907
1128
|
vanilla: 'HUMANBEHAVIOR_API_KEY',
|
|
1129
|
+
astro: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
|
|
1130
|
+
gatsby: 'GATSBY_HUMANBEHAVIOR_API_KEY',
|
|
908
1131
|
node: 'HUMANBEHAVIOR_API_KEY',
|
|
909
1132
|
auto: 'HUMANBEHAVIOR_API_KEY'
|
|
910
1133
|
};
|
|
@@ -928,6 +1151,8 @@ if (typeof window !== 'undefined') {
|
|
|
928
1151
|
nuxt: '.env',
|
|
929
1152
|
remix: '.env.local',
|
|
930
1153
|
vanilla: '.env',
|
|
1154
|
+
astro: '.env',
|
|
1155
|
+
gatsby: '.env.development',
|
|
931
1156
|
node: '.env',
|
|
932
1157
|
auto: '.env'
|
|
933
1158
|
};
|
|
@@ -942,6 +1167,8 @@ if (typeof window !== 'undefined') {
|
|
|
942
1167
|
*/
|
|
943
1168
|
createEnvironmentModification(framework) {
|
|
944
1169
|
const { filePath, envVarName } = this.findBestEnvFile(framework);
|
|
1170
|
+
// Clean the API key to prevent formatting issues
|
|
1171
|
+
const cleanApiKey = this.apiKey.trim();
|
|
945
1172
|
if (fs.existsSync(filePath)) {
|
|
946
1173
|
// Check if the variable already exists
|
|
947
1174
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
@@ -959,7 +1186,7 @@ if (typeof window !== 'undefined') {
|
|
|
959
1186
|
return {
|
|
960
1187
|
filePath,
|
|
961
1188
|
action: 'append',
|
|
962
|
-
content: `\n${envVarName}=${
|
|
1189
|
+
content: `\n${envVarName}=${cleanApiKey}`,
|
|
963
1190
|
description: `Added API key to existing ${path.basename(filePath)}`
|
|
964
1191
|
};
|
|
965
1192
|
}
|
|
@@ -969,13 +1196,435 @@ if (typeof window !== 'undefined') {
|
|
|
969
1196
|
return {
|
|
970
1197
|
filePath,
|
|
971
1198
|
action: 'create',
|
|
972
|
-
content: `${envVarName}=${
|
|
1199
|
+
content: `${envVarName}=${cleanApiKey}`,
|
|
973
1200
|
description: `Created ${path.basename(filePath)} with API key`
|
|
974
1201
|
};
|
|
975
1202
|
}
|
|
976
1203
|
}
|
|
977
1204
|
}
|
|
978
1205
|
|
|
1206
|
+
/**
|
|
1207
|
+
* Remote AI Service Implementation
|
|
1208
|
+
*
|
|
1209
|
+
* This connects to your deployed Lambda function via API Gateway
|
|
1210
|
+
*/
|
|
1211
|
+
class RemoteAIService {
|
|
1212
|
+
constructor(config) {
|
|
1213
|
+
this.config = Object.assign({ timeout: 10000 }, config);
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Analyze code patterns using your deployed AI service
|
|
1217
|
+
*/
|
|
1218
|
+
analyzeCodePatterns(codeSamples) {
|
|
1219
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1220
|
+
try {
|
|
1221
|
+
const response = yield fetch(`${this.config.apiEndpoint}/analyze`, {
|
|
1222
|
+
method: 'POST',
|
|
1223
|
+
headers: {
|
|
1224
|
+
'Content-Type': 'application/json',
|
|
1225
|
+
},
|
|
1226
|
+
body: JSON.stringify({ codeSamples }),
|
|
1227
|
+
signal: AbortSignal.timeout(this.config.timeout || 10000)
|
|
1228
|
+
});
|
|
1229
|
+
if (!response.ok) {
|
|
1230
|
+
throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
|
|
1231
|
+
}
|
|
1232
|
+
const result = yield response.json();
|
|
1233
|
+
return result.analysis;
|
|
1234
|
+
}
|
|
1235
|
+
catch (error) {
|
|
1236
|
+
console.warn('Remote AI service failed, falling back to heuristic analysis:', error);
|
|
1237
|
+
return this.performHeuristicAnalysis(codeSamples);
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Resolve conflicts using your deployed AI service
|
|
1243
|
+
*/
|
|
1244
|
+
resolveConflicts(conflicts, framework) {
|
|
1245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1246
|
+
try {
|
|
1247
|
+
const response = yield fetch(`${this.config.apiEndpoint}/resolve-conflicts`, {
|
|
1248
|
+
method: 'POST',
|
|
1249
|
+
headers: {
|
|
1250
|
+
'Content-Type': 'application/json',
|
|
1251
|
+
},
|
|
1252
|
+
body: JSON.stringify({ conflicts, framework }),
|
|
1253
|
+
signal: AbortSignal.timeout(this.config.timeout || 10000)
|
|
1254
|
+
});
|
|
1255
|
+
if (!response.ok) {
|
|
1256
|
+
throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
|
|
1257
|
+
}
|
|
1258
|
+
const result = yield response.json();
|
|
1259
|
+
return result.resolutions || [];
|
|
1260
|
+
}
|
|
1261
|
+
catch (error) {
|
|
1262
|
+
console.warn('Remote AI conflict resolution failed, using heuristic approach:', error);
|
|
1263
|
+
return this.resolveConflictsHeuristic(conflicts, framework);
|
|
1264
|
+
}
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Generate optimizations using your deployed AI service
|
|
1269
|
+
*/
|
|
1270
|
+
generateOptimizations(framework, patterns) {
|
|
1271
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1272
|
+
try {
|
|
1273
|
+
const response = yield fetch(`${this.config.apiEndpoint}/optimize`, {
|
|
1274
|
+
method: 'POST',
|
|
1275
|
+
headers: {
|
|
1276
|
+
'Content-Type': 'application/json',
|
|
1277
|
+
},
|
|
1278
|
+
body: JSON.stringify({ framework, patterns }),
|
|
1279
|
+
signal: AbortSignal.timeout(this.config.timeout || 10000)
|
|
1280
|
+
});
|
|
1281
|
+
if (!response.ok) {
|
|
1282
|
+
throw new Error(`AI service returned ${response.status}: ${response.statusText}`);
|
|
1283
|
+
}
|
|
1284
|
+
const result = yield response.json();
|
|
1285
|
+
return result.optimizations || [];
|
|
1286
|
+
}
|
|
1287
|
+
catch (error) {
|
|
1288
|
+
console.warn('Remote AI optimization generation failed, using heuristic approach:', error);
|
|
1289
|
+
return this.generateOptimizationsHeuristic(framework, patterns);
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Heuristic analysis fallback
|
|
1295
|
+
*/
|
|
1296
|
+
performHeuristicAnalysis(codeSamples) {
|
|
1297
|
+
const patterns = codeSamples.join(' ').toLowerCase();
|
|
1298
|
+
// Framework detection
|
|
1299
|
+
let framework = { name: 'vanilla', type: 'vanilla' };
|
|
1300
|
+
let confidence = 0.5;
|
|
1301
|
+
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')) {
|
|
1302
|
+
framework = { name: 'nuxt', type: 'nuxt' };
|
|
1303
|
+
confidence = 0.95;
|
|
1304
|
+
}
|
|
1305
|
+
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/')) {
|
|
1306
|
+
framework = { name: 'nextjs', type: 'nextjs' };
|
|
1307
|
+
confidence = 0.95;
|
|
1308
|
+
}
|
|
1309
|
+
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')) {
|
|
1310
|
+
framework = { name: 'gatsby', type: 'gatsby' };
|
|
1311
|
+
confidence = 0.95;
|
|
1312
|
+
}
|
|
1313
|
+
else if (patterns.includes('react')) {
|
|
1314
|
+
framework = { name: 'react', type: 'react' };
|
|
1315
|
+
confidence = 0.9;
|
|
1316
|
+
}
|
|
1317
|
+
else if (patterns.includes('vue')) {
|
|
1318
|
+
framework = { name: 'vue', type: 'vue' };
|
|
1319
|
+
confidence = 0.9;
|
|
1320
|
+
}
|
|
1321
|
+
else if (patterns.includes('angular')) {
|
|
1322
|
+
framework = { name: 'angular', type: 'angular' };
|
|
1323
|
+
confidence = 0.9;
|
|
1324
|
+
}
|
|
1325
|
+
else if (patterns.includes('svelte')) {
|
|
1326
|
+
framework = { name: 'svelte', type: 'svelte' };
|
|
1327
|
+
confidence = 0.9;
|
|
1328
|
+
}
|
|
1329
|
+
else if (patterns.includes('astro')) {
|
|
1330
|
+
framework = { name: 'astro', type: 'astro' };
|
|
1331
|
+
confidence = 0.9;
|
|
1332
|
+
}
|
|
1333
|
+
// Integration strategy
|
|
1334
|
+
let integrationStrategy = 'script';
|
|
1335
|
+
if (framework.type === 'react' || framework.type === 'nextjs' || framework.type === 'gatsby') {
|
|
1336
|
+
integrationStrategy = 'provider';
|
|
1337
|
+
}
|
|
1338
|
+
else if (framework.type === 'vue') {
|
|
1339
|
+
integrationStrategy = 'plugin';
|
|
1340
|
+
}
|
|
1341
|
+
else if (framework.type === 'angular') {
|
|
1342
|
+
integrationStrategy = 'module';
|
|
1343
|
+
}
|
|
1344
|
+
// Compatibility mode
|
|
1345
|
+
let compatibilityMode = 'modern';
|
|
1346
|
+
if (patterns.includes('require(') || patterns.includes('var ')) {
|
|
1347
|
+
compatibilityMode = 'legacy';
|
|
1348
|
+
}
|
|
1349
|
+
return {
|
|
1350
|
+
framework,
|
|
1351
|
+
confidence,
|
|
1352
|
+
patterns: codeSamples,
|
|
1353
|
+
conflicts: [],
|
|
1354
|
+
recommendations: [],
|
|
1355
|
+
integrationStrategy,
|
|
1356
|
+
compatibilityMode
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Heuristic conflict resolution
|
|
1361
|
+
*/
|
|
1362
|
+
resolveConflictsHeuristic(conflicts, framework) {
|
|
1363
|
+
const resolutions = [];
|
|
1364
|
+
for (const conflict of conflicts) {
|
|
1365
|
+
switch (conflict) {
|
|
1366
|
+
case 'existing_humanbehavior_code':
|
|
1367
|
+
resolutions.push('update_existing_integration');
|
|
1368
|
+
break;
|
|
1369
|
+
case 'existing_provider':
|
|
1370
|
+
resolutions.push('merge_providers');
|
|
1371
|
+
break;
|
|
1372
|
+
case 'module_system_conflict':
|
|
1373
|
+
resolutions.push('hybrid_module_support');
|
|
1374
|
+
break;
|
|
1375
|
+
default:
|
|
1376
|
+
resolutions.push('skip_conflict');
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
return resolutions;
|
|
1380
|
+
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Heuristic optimization generation
|
|
1383
|
+
*/
|
|
1384
|
+
generateOptimizationsHeuristic(framework, patterns) {
|
|
1385
|
+
const optimizations = [];
|
|
1386
|
+
switch (framework.type) {
|
|
1387
|
+
case 'react':
|
|
1388
|
+
optimizations.push('Use React.memo for performance optimization');
|
|
1389
|
+
optimizations.push('Implement error boundaries for better error tracking');
|
|
1390
|
+
optimizations.push('Consider using React.lazy for code splitting');
|
|
1391
|
+
break;
|
|
1392
|
+
case 'vue':
|
|
1393
|
+
optimizations.push('Use Vue 3 Composition API for better performance');
|
|
1394
|
+
optimizations.push('Implement proper error handling in components');
|
|
1395
|
+
optimizations.push('Consider using Vue Router for navigation tracking');
|
|
1396
|
+
break;
|
|
1397
|
+
case 'angular':
|
|
1398
|
+
optimizations.push('Use Angular standalone components for better tree-shaking');
|
|
1399
|
+
optimizations.push('Implement proper error handling with ErrorHandler');
|
|
1400
|
+
optimizations.push('Consider using Angular signals for state management');
|
|
1401
|
+
break;
|
|
1402
|
+
default:
|
|
1403
|
+
optimizations.push('Enable performance tracking');
|
|
1404
|
+
optimizations.push('Implement error tracking');
|
|
1405
|
+
optimizations.push('Consider progressive enhancement');
|
|
1406
|
+
}
|
|
1407
|
+
return optimizations;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
/**
|
|
1412
|
+
* Manual Framework Installation Wizard
|
|
1413
|
+
*
|
|
1414
|
+
* This wizard allows users to manually specify their framework instead of auto-detection.
|
|
1415
|
+
* Useful when auto-detection fails or users want more control.
|
|
1416
|
+
*/
|
|
1417
|
+
class ManualFrameworkInstallationWizard extends AutoInstallationWizard {
|
|
1418
|
+
constructor(apiKey, projectRoot = process.cwd(), framework) {
|
|
1419
|
+
super(apiKey, projectRoot);
|
|
1420
|
+
this.selectedFramework = framework.toLowerCase();
|
|
1421
|
+
this.framework = this.createFrameworkInfo(this.selectedFramework);
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Manual installation with user-specified framework
|
|
1425
|
+
*/
|
|
1426
|
+
install() {
|
|
1427
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1428
|
+
try {
|
|
1429
|
+
// Step 1: Handle framework selection
|
|
1430
|
+
if (this.selectedFramework === 'auto') {
|
|
1431
|
+
// Use full AI detection for "Other" option
|
|
1432
|
+
this.framework = yield this.runFullDetection();
|
|
1433
|
+
}
|
|
1434
|
+
else {
|
|
1435
|
+
// Set framework based on user selection
|
|
1436
|
+
this.framework = this.createFrameworkInfo(this.selectedFramework);
|
|
1437
|
+
if (!this.framework) {
|
|
1438
|
+
this.framework = { name: 'unknown', type: 'vanilla' };
|
|
1439
|
+
}
|
|
1440
|
+
// Step 2: Run full detection logic to find entry points, file names, etc.
|
|
1441
|
+
const detectedFramework = yield this.runFullDetection();
|
|
1442
|
+
// Step 3: Merge manual framework with detected details
|
|
1443
|
+
this.framework = Object.assign(Object.assign({}, detectedFramework), { name: this.framework.name, type: this.framework.type });
|
|
1444
|
+
}
|
|
1445
|
+
// Step 4: Install package
|
|
1446
|
+
yield this.installPackage();
|
|
1447
|
+
// Step 5: Generate and apply code modifications
|
|
1448
|
+
const modifications = yield this.generateModifications();
|
|
1449
|
+
yield this.applyModifications(modifications);
|
|
1450
|
+
// Step 6: Generate next steps
|
|
1451
|
+
const nextSteps = this.generateManualNextSteps();
|
|
1452
|
+
return {
|
|
1453
|
+
success: true,
|
|
1454
|
+
framework: this.framework,
|
|
1455
|
+
modifications,
|
|
1456
|
+
errors: [],
|
|
1457
|
+
nextSteps,
|
|
1458
|
+
selectedFramework: this.selectedFramework,
|
|
1459
|
+
manualMode: true
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
catch (error) {
|
|
1463
|
+
return {
|
|
1464
|
+
success: false,
|
|
1465
|
+
framework: this.framework || { name: 'unknown', type: 'vanilla' },
|
|
1466
|
+
modifications: [],
|
|
1467
|
+
errors: [error instanceof Error ? error.message : 'Unknown error'],
|
|
1468
|
+
nextSteps: [],
|
|
1469
|
+
selectedFramework: this.selectedFramework,
|
|
1470
|
+
manualMode: true
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
* Run full detection logic to find entry points, file names, bundler, etc.
|
|
1477
|
+
*/
|
|
1478
|
+
runFullDetection() {
|
|
1479
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1480
|
+
if (this.selectedFramework === 'auto') {
|
|
1481
|
+
// Use AI service for auto-detection
|
|
1482
|
+
const aiService = new RemoteAIService({
|
|
1483
|
+
apiEndpoint: 'https://ik3zxh4790.execute-api.us-east-1.amazonaws.com/prod'
|
|
1484
|
+
});
|
|
1485
|
+
// Use AI service directly for detection
|
|
1486
|
+
const projectFiles = yield this.scanProjectFiles();
|
|
1487
|
+
const codeSamples = yield this.extractCodeSamples(projectFiles);
|
|
1488
|
+
const aiAnalysis = yield aiService.analyzeCodePatterns(codeSamples);
|
|
1489
|
+
return aiAnalysis.framework;
|
|
1490
|
+
}
|
|
1491
|
+
else {
|
|
1492
|
+
// Use traditional detection for manual frameworks
|
|
1493
|
+
const tempWizard = new AutoInstallationWizard(this.apiKey, this.projectRoot);
|
|
1494
|
+
const detected = yield tempWizard.detectFramework();
|
|
1495
|
+
return detected;
|
|
1496
|
+
}
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Scan project files for analysis
|
|
1501
|
+
*/
|
|
1502
|
+
scanProjectFiles() {
|
|
1503
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1504
|
+
const files = [];
|
|
1505
|
+
const scanDir = (dir, depth = 0) => {
|
|
1506
|
+
if (depth > 3)
|
|
1507
|
+
return; // Limit depth
|
|
1508
|
+
try {
|
|
1509
|
+
const items = fs.readdirSync(dir);
|
|
1510
|
+
for (const item of items) {
|
|
1511
|
+
const fullPath = path.join(dir, item);
|
|
1512
|
+
const stat = fs.statSync(fullPath);
|
|
1513
|
+
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
|
|
1514
|
+
scanDir(fullPath, depth + 1);
|
|
1515
|
+
}
|
|
1516
|
+
else if (stat.isFile() && this.isRelevantFile(item)) {
|
|
1517
|
+
files.push(fullPath);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
catch (error) {
|
|
1522
|
+
// Skip inaccessible directories
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
scanDir(this.projectRoot);
|
|
1526
|
+
return files;
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Check if file is relevant for analysis
|
|
1531
|
+
*/
|
|
1532
|
+
isRelevantFile(filename) {
|
|
1533
|
+
const relevantExtensions = [
|
|
1534
|
+
'.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte', '.html',
|
|
1535
|
+
'.json', '.config.js', '.config.ts', '.babelrc', '.eslintrc'
|
|
1536
|
+
];
|
|
1537
|
+
const relevantNames = [
|
|
1538
|
+
'package.json', 'tsconfig.json', 'vite.config', 'webpack.config',
|
|
1539
|
+
'next.config', 'nuxt.config', 'angular.json', 'svelte.config'
|
|
1540
|
+
];
|
|
1541
|
+
return relevantExtensions.some(ext => filename.endsWith(ext)) ||
|
|
1542
|
+
relevantNames.some(name => filename.includes(name));
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Extract code samples for AI analysis
|
|
1546
|
+
*/
|
|
1547
|
+
extractCodeSamples(files) {
|
|
1548
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1549
|
+
const samples = [];
|
|
1550
|
+
for (const file of files.slice(0, 20)) { // Limit to 20 files
|
|
1551
|
+
try {
|
|
1552
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
1553
|
+
const relativePath = path.relative(this.projectRoot, file);
|
|
1554
|
+
samples.push(`File: ${relativePath}\n${content.substring(0, 1000)}`);
|
|
1555
|
+
}
|
|
1556
|
+
catch (error) {
|
|
1557
|
+
// Skip unreadable files
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
return samples;
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
/**
|
|
1564
|
+
* Create framework info based on user selection
|
|
1565
|
+
*/
|
|
1566
|
+
createFrameworkInfo(framework) {
|
|
1567
|
+
const frameworkMap = {
|
|
1568
|
+
'react': { name: 'react', type: 'react' },
|
|
1569
|
+
'nextjs': { name: 'nextjs', type: 'nextjs' },
|
|
1570
|
+
'next': { name: 'nextjs', type: 'nextjs' },
|
|
1571
|
+
'vue': { name: 'vue', type: 'vue' },
|
|
1572
|
+
'nuxt': { name: 'nuxt', type: 'nuxt' },
|
|
1573
|
+
'nuxtjs': { name: 'nuxt', type: 'nuxt' },
|
|
1574
|
+
'angular': { name: 'angular', type: 'angular' },
|
|
1575
|
+
'svelte': { name: 'svelte', type: 'svelte' },
|
|
1576
|
+
'sveltekit': { name: 'svelte', type: 'svelte' },
|
|
1577
|
+
'remix': { name: 'remix', type: 'remix' },
|
|
1578
|
+
'astro': { name: 'astro', type: 'astro' },
|
|
1579
|
+
'gatsby': { name: 'gatsby', type: 'gatsby' },
|
|
1580
|
+
'vanilla': { name: 'vanilla', type: 'vanilla' },
|
|
1581
|
+
'node': { name: 'node', type: 'node' },
|
|
1582
|
+
'auto': { name: 'auto-detected', type: 'auto' }
|
|
1583
|
+
};
|
|
1584
|
+
return frameworkMap[framework] || { name: framework, type: 'vanilla' };
|
|
1585
|
+
}
|
|
1586
|
+
/**
|
|
1587
|
+
* Override framework detection to use manual selection
|
|
1588
|
+
*/
|
|
1589
|
+
detectFramework() {
|
|
1590
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1591
|
+
return this.framework || { name: 'unknown', type: 'vanilla' };
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Generate next steps with manual mode info
|
|
1596
|
+
*/
|
|
1597
|
+
generateManualNextSteps() {
|
|
1598
|
+
var _a;
|
|
1599
|
+
return [
|
|
1600
|
+
'ā
Manual framework installation completed!',
|
|
1601
|
+
`šÆ Selected framework: ${((_a = this.framework) === null || _a === void 0 ? void 0 : _a.name) || 'unknown'}`,
|
|
1602
|
+
`š§ Integration strategy: ${this.getIntegrationStrategy()}`,
|
|
1603
|
+
'š Your app is now ready to track user behavior',
|
|
1604
|
+
'š View sessions in your HumanBehavior dashboard'
|
|
1605
|
+
];
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Get integration strategy based on framework
|
|
1609
|
+
*/
|
|
1610
|
+
getIntegrationStrategy() {
|
|
1611
|
+
var _a;
|
|
1612
|
+
if (!((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type))
|
|
1613
|
+
return 'script';
|
|
1614
|
+
switch (this.framework.type) {
|
|
1615
|
+
case 'react':
|
|
1616
|
+
case 'nextjs':
|
|
1617
|
+
return 'provider';
|
|
1618
|
+
case 'vue':
|
|
1619
|
+
return 'plugin';
|
|
1620
|
+
case 'angular':
|
|
1621
|
+
return 'module';
|
|
1622
|
+
default:
|
|
1623
|
+
return 'script';
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
|
|
979
1628
|
/**
|
|
980
1629
|
* HumanBehavior SDK Auto-Installation CLI
|
|
981
1630
|
*
|
|
@@ -987,46 +1636,46 @@ if (typeof window !== 'undefined') {
|
|
|
987
1636
|
class AutoInstallCLI {
|
|
988
1637
|
constructor(options) {
|
|
989
1638
|
this.options = options;
|
|
990
|
-
this.rl = readline.createInterface({
|
|
991
|
-
input: process.stdin,
|
|
992
|
-
output: process.stdout
|
|
993
|
-
});
|
|
994
1639
|
}
|
|
995
1640
|
run() {
|
|
996
1641
|
return __awaiter(this, void 0, void 0, function* () {
|
|
997
|
-
|
|
998
|
-
console.log('=====================================\n');
|
|
1642
|
+
clack.intro('š HumanBehavior SDK Auto-Installation');
|
|
999
1643
|
try {
|
|
1000
1644
|
// Get API key
|
|
1001
1645
|
const apiKey = yield this.getApiKey();
|
|
1002
1646
|
if (!apiKey) {
|
|
1003
|
-
|
|
1647
|
+
clack.cancel('API key is required');
|
|
1004
1648
|
process.exit(1);
|
|
1005
1649
|
}
|
|
1006
1650
|
// Get project path
|
|
1007
1651
|
const projectPath = this.options.projectPath || process.cwd();
|
|
1652
|
+
// Choose framework
|
|
1653
|
+
const framework = yield this.chooseFramework();
|
|
1654
|
+
if (!framework) {
|
|
1655
|
+
clack.cancel('Installation cancelled.');
|
|
1656
|
+
process.exit(0);
|
|
1657
|
+
}
|
|
1008
1658
|
// Confirm installation
|
|
1009
1659
|
if (!this.options.yes) {
|
|
1010
|
-
const confirmed = yield this.confirmInstallation(projectPath);
|
|
1660
|
+
const confirmed = yield this.confirmInstallation(projectPath, framework);
|
|
1011
1661
|
if (!confirmed) {
|
|
1012
|
-
|
|
1662
|
+
clack.cancel('Installation cancelled.');
|
|
1013
1663
|
process.exit(0);
|
|
1014
1664
|
}
|
|
1015
1665
|
}
|
|
1016
|
-
// Run
|
|
1017
|
-
|
|
1018
|
-
|
|
1666
|
+
// Run installation
|
|
1667
|
+
const spinner = clack.spinner();
|
|
1668
|
+
spinner.start('š Analyzing your project...');
|
|
1669
|
+
const wizard = new ManualFrameworkInstallationWizard(apiKey, projectPath, framework);
|
|
1019
1670
|
const result = yield wizard.install();
|
|
1671
|
+
spinner.stop('Detection complete!');
|
|
1020
1672
|
// Display results
|
|
1021
1673
|
this.displayResults(result);
|
|
1022
1674
|
}
|
|
1023
1675
|
catch (error) {
|
|
1024
|
-
|
|
1676
|
+
clack.cancel(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1025
1677
|
process.exit(1);
|
|
1026
1678
|
}
|
|
1027
|
-
finally {
|
|
1028
|
-
this.rl.close();
|
|
1029
|
-
}
|
|
1030
1679
|
});
|
|
1031
1680
|
}
|
|
1032
1681
|
getApiKey() {
|
|
@@ -1034,139 +1683,131 @@ class AutoInstallCLI {
|
|
|
1034
1683
|
if (this.options.apiKey) {
|
|
1035
1684
|
return this.options.apiKey;
|
|
1036
1685
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1686
|
+
const apiKey = yield clack.text({
|
|
1687
|
+
message: 'Enter your HumanBehavior API key:',
|
|
1688
|
+
placeholder: 'hb_...',
|
|
1689
|
+
validate: (value) => {
|
|
1690
|
+
if (!value)
|
|
1691
|
+
return 'API key is required';
|
|
1692
|
+
if (!value.startsWith('hb_'))
|
|
1693
|
+
return 'API key should start with "hb_"';
|
|
1694
|
+
return undefined;
|
|
1695
|
+
}
|
|
1041
1696
|
});
|
|
1697
|
+
return apiKey;
|
|
1042
1698
|
});
|
|
1043
1699
|
}
|
|
1044
|
-
|
|
1700
|
+
chooseFramework() {
|
|
1045
1701
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1702
|
+
const framework = yield clack.select({
|
|
1703
|
+
message: 'Select your framework:',
|
|
1704
|
+
options: [
|
|
1705
|
+
{ label: 'React', value: 'react' },
|
|
1706
|
+
{ label: 'Next.js', value: 'nextjs' },
|
|
1707
|
+
{ label: 'Vue', value: 'vue' },
|
|
1708
|
+
{ label: 'Angular', value: 'angular' },
|
|
1709
|
+
{ label: 'Svelte', value: 'svelte' },
|
|
1710
|
+
{ label: 'Nuxt.js', value: 'nuxt' },
|
|
1711
|
+
{ label: 'Remix', value: 'remix' },
|
|
1712
|
+
{ label: 'Astro', value: 'astro' },
|
|
1713
|
+
{ label: 'Gatsby', value: 'gatsby' },
|
|
1714
|
+
{ label: 'Vanilla JS/TS', value: 'vanilla' }
|
|
1715
|
+
]
|
|
1057
1716
|
});
|
|
1717
|
+
return framework;
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
confirmInstallation(projectPath, framework) {
|
|
1721
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1722
|
+
const confirmed = yield clack.confirm({
|
|
1723
|
+
message: `Ready to install HumanBehavior SDK in ${projectPath} for ${framework}?`
|
|
1724
|
+
});
|
|
1725
|
+
return confirmed;
|
|
1058
1726
|
});
|
|
1059
1727
|
}
|
|
1060
1728
|
displayResults(result) {
|
|
1061
1729
|
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');
|
|
1730
|
+
clack.outro('š Installation completed successfully!');
|
|
1731
|
+
// Display framework info
|
|
1732
|
+
clack.note(`Framework detected: ${result.framework.name} (${result.framework.type})`, 'Framework Info');
|
|
1733
|
+
// Display modifications
|
|
1734
|
+
if (result.modifications && result.modifications.length > 0) {
|
|
1735
|
+
const modifications = result.modifications.map((mod) => `${mod.action}: ${mod.filePath} - ${mod.description}`);
|
|
1736
|
+
clack.note(modifications.join('\n'), 'Files Modified');
|
|
1737
|
+
}
|
|
1738
|
+
// Display next steps
|
|
1739
|
+
if (result.nextSteps && result.nextSteps.length > 0) {
|
|
1740
|
+
clack.note(result.nextSteps.join('\n'), 'Next Steps');
|
|
1741
|
+
}
|
|
1081
1742
|
}
|
|
1082
1743
|
else {
|
|
1083
|
-
|
|
1084
|
-
result.errors.
|
|
1085
|
-
|
|
1086
|
-
}
|
|
1087
|
-
console.log('\nš” Try running with --help for more options');
|
|
1744
|
+
clack.cancel('Installation failed');
|
|
1745
|
+
if (result.errors && result.errors.length > 0) {
|
|
1746
|
+
clack.note(result.errors.join('\n'), 'Errors');
|
|
1747
|
+
}
|
|
1088
1748
|
}
|
|
1089
1749
|
}
|
|
1090
1750
|
}
|
|
1091
|
-
// CLI argument parsing
|
|
1092
1751
|
function parseArgs() {
|
|
1093
1752
|
const args = process.argv.slice(2);
|
|
1094
1753
|
const options = {};
|
|
1095
1754
|
for (let i = 0; i < args.length; i++) {
|
|
1096
1755
|
const arg = args[i];
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1756
|
+
switch (arg) {
|
|
1757
|
+
case '--help':
|
|
1758
|
+
case '-h':
|
|
1759
|
+
showHelp();
|
|
1760
|
+
process.exit(0);
|
|
1761
|
+
break;
|
|
1762
|
+
case '--yes':
|
|
1763
|
+
case '-y':
|
|
1764
|
+
options.yes = true;
|
|
1765
|
+
break;
|
|
1766
|
+
case '--dry-run':
|
|
1767
|
+
options.dryRun = true;
|
|
1768
|
+
break;
|
|
1769
|
+
case '--project':
|
|
1770
|
+
case '-p':
|
|
1771
|
+
options.projectPath = args[++i];
|
|
1772
|
+
break;
|
|
1773
|
+
default:
|
|
1774
|
+
if (!options.apiKey && !arg.startsWith('-')) {
|
|
1775
|
+
options.apiKey = arg;
|
|
1776
|
+
}
|
|
1777
|
+
break;
|
|
1113
1778
|
}
|
|
1114
1779
|
}
|
|
1115
1780
|
return options;
|
|
1116
1781
|
}
|
|
1117
1782
|
function showHelp() {
|
|
1118
1783
|
console.log(`
|
|
1119
|
-
HumanBehavior SDK Auto-Installation
|
|
1120
|
-
|
|
1121
|
-
Usage: npx humanbehavior-js [api-key] [options]
|
|
1784
|
+
š HumanBehavior SDK Auto-Installation
|
|
1122
1785
|
|
|
1123
|
-
|
|
1124
|
-
to integrate the HumanBehavior SDK with minimal user intervention.
|
|
1786
|
+
Usage: npx humanbehavior-js auto-install [api-key] [options]
|
|
1125
1787
|
|
|
1126
|
-
|
|
1127
|
-
api-key Your HumanBehavior API key
|
|
1788
|
+
This tool automatically detects your framework and integrates the HumanBehavior SDK.
|
|
1128
1789
|
|
|
1129
1790
|
Options:
|
|
1130
|
-
-
|
|
1131
|
-
-
|
|
1132
|
-
-
|
|
1133
|
-
-
|
|
1791
|
+
-h, --help Show this help message
|
|
1792
|
+
-y, --yes Skip all prompts and use defaults
|
|
1793
|
+
--dry-run Show what would be changed without making changes
|
|
1794
|
+
-p, --project <path> Specify project directory
|
|
1134
1795
|
|
|
1135
1796
|
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
|
|
1797
|
+
npx humanbehavior-js auto-install
|
|
1798
|
+
npx humanbehavior-js auto-install hb_your_api_key_here
|
|
1799
|
+
npx humanbehavior-js auto-install --project ./my-app --yes
|
|
1156
1800
|
`);
|
|
1157
1801
|
}
|
|
1158
1802
|
// Main execution
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1803
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
1804
|
+
const options = parseArgs();
|
|
1805
|
+
const cli = new AutoInstallCLI(options);
|
|
1806
|
+
cli.run().catch((error) => {
|
|
1807
|
+
clack.cancel(`Unexpected error: ${error.message}`);
|
|
1808
|
+
process.exit(1);
|
|
1809
|
+
});
|
|
1164
1810
|
}
|
|
1165
|
-
const cli = new AutoInstallCLI(options);
|
|
1166
|
-
cli.run().catch((error) => {
|
|
1167
|
-
console.error('ā Fatal error:', error);
|
|
1168
|
-
process.exit(1);
|
|
1169
|
-
});
|
|
1170
1811
|
|
|
1171
1812
|
export { AutoInstallCLI };
|
|
1172
1813
|
//# sourceMappingURL=auto-install.js.map
|