humanbehavior-js 0.3.7 → 0.3.9

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.
Files changed (56) hide show
  1. package/WIZARD_USAGE_GUIDE.md +381 -0
  2. package/dist/cjs/angular/index.cjs +53 -0
  3. package/dist/cjs/angular/index.cjs.map +1 -0
  4. package/dist/cjs/{index.js → index.cjs} +5 -4
  5. package/dist/cjs/index.cjs.map +1 -0
  6. package/dist/cjs/install-wizard.cjs +1157 -0
  7. package/dist/cjs/install-wizard.cjs.map +1 -0
  8. package/dist/cjs/react/index.cjs +14387 -0
  9. package/dist/cjs/react/index.cjs.map +1 -0
  10. package/dist/cjs/remix/index.cjs +57 -0
  11. package/dist/cjs/remix/index.cjs.map +1 -0
  12. package/dist/cjs/svelte/index.cjs +13 -0
  13. package/dist/cjs/svelte/index.cjs.map +1 -0
  14. package/dist/cjs/vue/index.cjs +16 -0
  15. package/dist/cjs/vue/index.cjs.map +1 -0
  16. package/dist/cli/auto-install.js +1172 -0
  17. package/dist/cli/auto-install.js.map +1 -0
  18. package/dist/esm/angular/index.js +49 -0
  19. package/dist/esm/angular/index.js.map +1 -0
  20. package/dist/esm/index.js +5 -1
  21. package/dist/esm/index.js.map +1 -1
  22. package/dist/esm/install-wizard.js +1134 -0
  23. package/dist/esm/install-wizard.js.map +1 -0
  24. package/dist/esm/react/index.js +14113 -70
  25. package/dist/esm/react/index.js.map +1 -1
  26. package/dist/esm/remix/index.js +47 -0
  27. package/dist/esm/remix/index.js.map +1 -0
  28. package/dist/esm/svelte/index.js +11 -0
  29. package/dist/esm/svelte/index.js.map +1 -0
  30. package/dist/esm/vue/index.js +14 -0
  31. package/dist/esm/vue/index.js.map +1 -0
  32. package/dist/index.min.js +1 -1
  33. package/dist/index.min.js.map +1 -1
  34. package/dist/types/angular/index.d.ts +240 -0
  35. package/dist/types/index.d.ts +1 -1
  36. package/dist/types/install-wizard.d.ts +126 -0
  37. package/dist/types/react/index.d.ts +212 -3
  38. package/dist/types/remix/index.d.ts +10 -0
  39. package/dist/types/svelte/index.d.ts +216 -0
  40. package/dist/types/vue/index.d.ts +10 -0
  41. package/package.json +40 -7
  42. package/readme.md +70 -1
  43. package/rollup.config.js +263 -13
  44. package/src/angular/index.ts +54 -0
  45. package/src/cli/auto-install.ts +227 -0
  46. package/src/index.ts +5 -2
  47. package/src/install-wizard.ts +1304 -0
  48. package/src/react/AutoInstallWizard.tsx +557 -0
  49. package/src/react/browser.ts +8 -0
  50. package/src/react/index.tsx +2 -4
  51. package/src/remix/index.ts +16 -0
  52. package/src/svelte/index.ts +8 -0
  53. package/src/vue/index.ts +18 -0
  54. package/dist/cjs/index.js.map +0 -1
  55. package/dist/cjs/react/index.js +0 -346
  56. package/dist/cjs/react/index.js.map +0 -1
@@ -0,0 +1,1157 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+
6
+ function _interopNamespaceDefault(e) {
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
24
+ var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
25
+
26
+ /******************************************************************************
27
+ Copyright (c) Microsoft Corporation.
28
+
29
+ Permission to use, copy, modify, and/or distribute this software for any
30
+ purpose with or without fee is hereby granted.
31
+
32
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
33
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
34
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
35
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
36
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
37
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
38
+ PERFORMANCE OF THIS SOFTWARE.
39
+ ***************************************************************************** */
40
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
41
+
42
+
43
+ function __awaiter(thisArg, _arguments, P, generator) {
44
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
45
+ return new (P || (P = Promise))(function (resolve, reject) {
46
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
47
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
48
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
49
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
50
+ });
51
+ }
52
+
53
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
54
+ var e = new Error(message);
55
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
56
+ };
57
+
58
+ /**
59
+ * HumanBehavior SDK Auto-Installation Wizard
60
+ *
61
+ * This wizard automatically detects the user's framework and modifies their codebase
62
+ * to integrate the SDK with minimal user intervention.
63
+ */
64
+ class AutoInstallationWizard {
65
+ constructor(apiKey, projectRoot = process.cwd()) {
66
+ this.framework = null;
67
+ this.apiKey = apiKey;
68
+ this.projectRoot = projectRoot;
69
+ }
70
+ /**
71
+ * Main installation method - detects framework and auto-installs
72
+ */
73
+ install() {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ try {
76
+ // Step 1: Detect framework
77
+ this.framework = yield this.detectFramework();
78
+ // Step 2: Install package
79
+ yield this.installPackage();
80
+ // Step 3: Generate and apply code modifications
81
+ const modifications = yield this.generateModifications();
82
+ yield this.applyModifications(modifications);
83
+ // Step 4: Generate next steps
84
+ const nextSteps = this.generateNextSteps();
85
+ return {
86
+ success: true,
87
+ framework: this.framework,
88
+ modifications,
89
+ errors: [],
90
+ nextSteps
91
+ };
92
+ }
93
+ catch (error) {
94
+ return {
95
+ success: false,
96
+ framework: this.framework || { name: 'unknown', type: 'vanilla' },
97
+ modifications: [],
98
+ errors: [error instanceof Error ? error.message : 'Unknown error'],
99
+ nextSteps: []
100
+ };
101
+ }
102
+ });
103
+ }
104
+ /**
105
+ * Detect the current framework and project setup
106
+ */
107
+ detectFramework() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ const packageJsonPath = path__namespace.join(this.projectRoot, 'package.json');
110
+ if (!fs__namespace.existsSync(packageJsonPath)) {
111
+ return {
112
+ name: 'vanilla',
113
+ type: 'vanilla',
114
+ projectRoot: this.projectRoot
115
+ };
116
+ }
117
+ const packageJson = JSON.parse(fs__namespace.readFileSync(packageJsonPath, 'utf8'));
118
+ const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
119
+ // Detect framework
120
+ let framework = {
121
+ name: 'vanilla',
122
+ type: 'vanilla',
123
+ projectRoot: this.projectRoot
124
+ };
125
+ if (dependencies.nuxt) {
126
+ framework = {
127
+ name: 'nuxt',
128
+ type: 'nuxt',
129
+ hasTypeScript: !!dependencies.typescript,
130
+ hasRouter: true,
131
+ projectRoot: this.projectRoot
132
+ };
133
+ }
134
+ else if (dependencies.next) {
135
+ framework = {
136
+ name: 'nextjs',
137
+ type: 'nextjs',
138
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
139
+ hasRouter: true,
140
+ projectRoot: this.projectRoot
141
+ };
142
+ }
143
+ else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
144
+ framework = {
145
+ name: 'remix',
146
+ type: 'remix',
147
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
148
+ hasRouter: true,
149
+ projectRoot: this.projectRoot
150
+ };
151
+ }
152
+ else if (dependencies.react) {
153
+ framework = {
154
+ name: 'react',
155
+ type: 'react',
156
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
157
+ hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
158
+ projectRoot: this.projectRoot
159
+ };
160
+ }
161
+ else if (dependencies.vue) {
162
+ framework = {
163
+ name: 'vue',
164
+ type: 'vue',
165
+ hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
166
+ hasRouter: !!dependencies['vue-router'],
167
+ projectRoot: this.projectRoot
168
+ };
169
+ }
170
+ else if (dependencies['@angular/core']) {
171
+ framework = {
172
+ name: 'angular',
173
+ type: 'angular',
174
+ hasTypeScript: true,
175
+ hasRouter: true,
176
+ projectRoot: this.projectRoot
177
+ };
178
+ }
179
+ else if (dependencies.svelte) {
180
+ framework = {
181
+ name: 'svelte',
182
+ type: 'svelte',
183
+ hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
184
+ hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
185
+ projectRoot: this.projectRoot
186
+ };
187
+ }
188
+ // Detect bundler
189
+ if (dependencies.vite) {
190
+ framework.bundler = 'vite';
191
+ }
192
+ else if (dependencies.webpack) {
193
+ framework.bundler = 'webpack';
194
+ }
195
+ else if (dependencies.esbuild) {
196
+ framework.bundler = 'esbuild';
197
+ }
198
+ else if (dependencies.rollup) {
199
+ framework.bundler = 'rollup';
200
+ }
201
+ // Detect package manager
202
+ if (fs__namespace.existsSync(path__namespace.join(this.projectRoot, 'yarn.lock'))) {
203
+ framework.packageManager = 'yarn';
204
+ }
205
+ else if (fs__namespace.existsSync(path__namespace.join(this.projectRoot, 'pnpm-lock.yaml'))) {
206
+ framework.packageManager = 'pnpm';
207
+ }
208
+ else {
209
+ framework.packageManager = 'npm';
210
+ }
211
+ return framework;
212
+ });
213
+ }
214
+ /**
215
+ * Install the SDK package
216
+ */
217
+ installPackage() {
218
+ return __awaiter(this, void 0, void 0, function* () {
219
+ var _a, _b;
220
+ const { execSync } = yield import('child_process');
221
+ const command = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.packageManager) === 'yarn'
222
+ ? 'yarn add humanbehavior-js'
223
+ : ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.packageManager) === 'pnpm'
224
+ ? 'pnpm add humanbehavior-js'
225
+ : 'npm install humanbehavior-js';
226
+ try {
227
+ execSync(command, { cwd: this.projectRoot, stdio: 'inherit' });
228
+ }
229
+ catch (error) {
230
+ throw new Error(`Failed to install humanbehavior-js: ${error}`);
231
+ }
232
+ });
233
+ }
234
+ /**
235
+ * Generate code modifications based on framework
236
+ */
237
+ generateModifications() {
238
+ return __awaiter(this, void 0, void 0, function* () {
239
+ var _a;
240
+ const modifications = [];
241
+ switch ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type) {
242
+ case 'react':
243
+ modifications.push(...yield this.generateReactModifications());
244
+ break;
245
+ case 'nextjs':
246
+ modifications.push(...yield this.generateNextJSModifications());
247
+ break;
248
+ case 'nuxt':
249
+ modifications.push(...yield this.generateNuxtModifications());
250
+ break;
251
+ case 'remix':
252
+ modifications.push(...yield this.generateRemixModifications());
253
+ break;
254
+ case 'vue':
255
+ modifications.push(...yield this.generateVueModifications());
256
+ break;
257
+ case 'angular':
258
+ modifications.push(...yield this.generateAngularModifications());
259
+ break;
260
+ case 'svelte':
261
+ modifications.push(...yield this.generateSvelteModifications());
262
+ break;
263
+ default:
264
+ modifications.push(...yield this.generateVanillaModifications());
265
+ }
266
+ return modifications;
267
+ });
268
+ }
269
+ /**
270
+ * Generate React-specific modifications
271
+ */
272
+ generateReactModifications() {
273
+ return __awaiter(this, void 0, void 0, function* () {
274
+ const modifications = [];
275
+ // Find main App component or index file
276
+ const appFile = this.findReactAppFile();
277
+ if (appFile) {
278
+ const content = fs__namespace.readFileSync(appFile, 'utf8');
279
+ const modifiedContent = this.injectReactProvider(content, appFile);
280
+ modifications.push({
281
+ filePath: appFile,
282
+ action: 'modify',
283
+ content: modifiedContent,
284
+ description: 'Added HumanBehaviorProvider to React app'
285
+ });
286
+ }
287
+ // Create or append to environment file
288
+ modifications.push(this.createEnvironmentModification(this.framework));
289
+ return modifications;
290
+ });
291
+ }
292
+ /**
293
+ * Generate Next.js-specific modifications
294
+ */
295
+ generateNextJSModifications() {
296
+ return __awaiter(this, void 0, void 0, function* () {
297
+ const modifications = [];
298
+ // Check for App Router
299
+ const appLayoutFile = path__namespace.join(this.projectRoot, 'src', 'app', 'layout.tsx');
300
+ const pagesLayoutFile = path__namespace.join(this.projectRoot, 'src', 'pages', '_app.tsx');
301
+ if (fs__namespace.existsSync(appLayoutFile)) {
302
+ // Create providers.tsx file for App Router
303
+ modifications.push({
304
+ filePath: path__namespace.join(this.projectRoot, 'src', 'app', 'providers.tsx'),
305
+ action: 'create',
306
+ content: `'use client';
307
+
308
+ import { HumanBehaviorProvider } from 'humanbehavior-js/react';
309
+
310
+ export function Providers({ children }: { children: React.ReactNode }) {
311
+ return (
312
+ <HumanBehaviorProvider apiKey={process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY}>
313
+ {children}
314
+ </HumanBehaviorProvider>
315
+ );
316
+ }`,
317
+ description: 'Created providers.tsx file for Next.js App Router'
318
+ });
319
+ // Modify layout.tsx to use the provider
320
+ const content = fs__namespace.readFileSync(appLayoutFile, 'utf8');
321
+ const modifiedContent = this.injectNextJSAppRouter(content);
322
+ modifications.push({
323
+ filePath: appLayoutFile,
324
+ action: 'modify',
325
+ content: modifiedContent,
326
+ description: 'Added Providers wrapper to Next.js App Router layout'
327
+ });
328
+ }
329
+ else if (fs__namespace.existsSync(pagesLayoutFile)) {
330
+ // Create providers.tsx file for Pages Router
331
+ modifications.push({
332
+ filePath: path__namespace.join(this.projectRoot, 'src', 'components', 'providers.tsx'),
333
+ action: 'create',
334
+ content: `'use client';
335
+
336
+ import { HumanBehaviorProvider } from 'humanbehavior-js/react';
337
+
338
+ export function Providers({ children }: { children: React.ReactNode }) {
339
+ return (
340
+ <HumanBehaviorProvider apiKey={process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY}>
341
+ {children}
342
+ </HumanBehaviorProvider>
343
+ );
344
+ }`,
345
+ description: 'Created providers.tsx file for Pages Router'
346
+ });
347
+ // Modify _app.tsx to use the provider
348
+ const content = fs__namespace.readFileSync(pagesLayoutFile, 'utf8');
349
+ const modifiedContent = this.injectNextJSPagesRouter(content);
350
+ modifications.push({
351
+ filePath: pagesLayoutFile,
352
+ action: 'modify',
353
+ content: modifiedContent,
354
+ description: 'Added Providers wrapper to Next.js Pages Router'
355
+ });
356
+ }
357
+ // Create or append to environment file
358
+ modifications.push(this.createEnvironmentModification(this.framework));
359
+ return modifications;
360
+ });
361
+ }
362
+ /**
363
+ * Generate Nuxt-specific modifications
364
+ */
365
+ generateNuxtModifications() {
366
+ return __awaiter(this, void 0, void 0, function* () {
367
+ const modifications = [];
368
+ // Create plugin file for Nuxt (in app directory)
369
+ const pluginFile = path__namespace.join(this.projectRoot, 'app', 'plugins', 'humanbehavior.client.ts');
370
+ modifications.push({
371
+ filePath: pluginFile,
372
+ action: 'create',
373
+ content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
374
+
375
+ export default defineNuxtPlugin(() => {
376
+ const config = useRuntimeConfig();
377
+
378
+ // Initialize HumanBehavior SDK (client-side only)
379
+ if (typeof window !== 'undefined') {
380
+ const apiKey = config.public.humanBehaviorApiKey;
381
+ console.log('HumanBehavior: API key:', apiKey ? 'present' : 'missing');
382
+
383
+ if (apiKey) {
384
+ try {
385
+ const tracker = HumanBehaviorTracker.init(apiKey);
386
+ console.log('HumanBehavior: Tracker initialized successfully');
387
+ } catch (error) {
388
+ console.error('HumanBehavior: Failed to initialize tracker:', error);
389
+ }
390
+ } else {
391
+ console.error('HumanBehavior: No API key found in runtime config');
392
+ }
393
+ }
394
+ });`,
395
+ description: 'Created Nuxt plugin for HumanBehavior SDK in app directory'
396
+ });
397
+ // Create environment configuration
398
+ const nuxtConfigFile = path__namespace.join(this.projectRoot, 'nuxt.config.ts');
399
+ if (fs__namespace.existsSync(nuxtConfigFile)) {
400
+ const content = fs__namespace.readFileSync(nuxtConfigFile, 'utf8');
401
+ const modifiedContent = this.injectNuxtConfig(content);
402
+ modifications.push({
403
+ filePath: nuxtConfigFile,
404
+ action: 'modify',
405
+ content: modifiedContent,
406
+ description: 'Added HumanBehavior runtime config to Nuxt config'
407
+ });
408
+ }
409
+ // Create or append to environment file
410
+ modifications.push(this.createEnvironmentModification(this.framework));
411
+ return modifications;
412
+ });
413
+ }
414
+ /**
415
+ * Generate Remix-specific modifications
416
+ */
417
+ generateRemixModifications() {
418
+ return __awaiter(this, void 0, void 0, function* () {
419
+ const modifications = [];
420
+ // Find root.tsx file
421
+ const rootFile = path__namespace.join(this.projectRoot, 'app', 'root.tsx');
422
+ if (fs__namespace.existsSync(rootFile)) {
423
+ const content = fs__namespace.readFileSync(rootFile, 'utf8');
424
+ const modifiedContent = this.injectRemixProvider(content);
425
+ modifications.push({
426
+ filePath: rootFile,
427
+ action: 'modify',
428
+ content: modifiedContent,
429
+ description: 'Added HumanBehaviorProvider to Remix root component'
430
+ });
431
+ }
432
+ // Create or append to environment file
433
+ modifications.push(this.createEnvironmentModification(this.framework));
434
+ return modifications;
435
+ });
436
+ }
437
+ /**
438
+ * Generate Vue-specific modifications
439
+ */
440
+ generateVueModifications() {
441
+ return __awaiter(this, void 0, void 0, function* () {
442
+ const modifications = [];
443
+ // Find main.js or main.ts
444
+ const mainFile = this.findVueMainFile();
445
+ if (mainFile) {
446
+ const content = fs__namespace.readFileSync(mainFile, 'utf8');
447
+ const modifiedContent = this.injectVuePlugin(content);
448
+ modifications.push({
449
+ filePath: mainFile,
450
+ action: 'modify',
451
+ content: modifiedContent,
452
+ description: 'Added HumanBehaviorPlugin to Vue app'
453
+ });
454
+ }
455
+ // Create or append to environment file
456
+ modifications.push(this.createEnvironmentModification(this.framework));
457
+ return modifications;
458
+ });
459
+ }
460
+ /**
461
+ * Generate Angular-specific modifications
462
+ */
463
+ generateAngularModifications() {
464
+ return __awaiter(this, void 0, void 0, function* () {
465
+ const modifications = [];
466
+ // Check for modern Angular (standalone components) vs legacy (NgModule)
467
+ const appModuleFile = path__namespace.join(this.projectRoot, 'src', 'app', 'app.module.ts');
468
+ const appComponentFile = path__namespace.join(this.projectRoot, 'src', 'app', 'app.ts');
469
+ const mainFile = path__namespace.join(this.projectRoot, 'src', 'main.ts');
470
+ const isModernAngular = fs__namespace.existsSync(appComponentFile) && !fs__namespace.existsSync(appModuleFile);
471
+ if (isModernAngular) {
472
+ // Modern Angular 17+ with standalone components
473
+ if (fs__namespace.existsSync(mainFile)) {
474
+ const content = fs__namespace.readFileSync(mainFile, 'utf8');
475
+ const modifiedContent = this.injectAngularStandaloneInit(content);
476
+ modifications.push({
477
+ filePath: mainFile,
478
+ action: 'modify',
479
+ content: modifiedContent,
480
+ description: 'Added HumanBehavior initialization to Angular main.ts'
481
+ });
482
+ }
483
+ }
484
+ else if (fs__namespace.existsSync(appModuleFile)) {
485
+ // Legacy Angular with NgModule
486
+ const content = fs__namespace.readFileSync(appModuleFile, 'utf8');
487
+ const modifiedContent = this.injectAngularModule(content);
488
+ modifications.push({
489
+ filePath: appModuleFile,
490
+ action: 'modify',
491
+ content: modifiedContent,
492
+ description: 'Added HumanBehaviorModule to Angular app'
493
+ });
494
+ }
495
+ // Handle Angular environment file (legacy structure)
496
+ const envFile = path__namespace.join(this.projectRoot, 'src', 'environments', 'environment.ts');
497
+ if (fs__namespace.existsSync(envFile)) {
498
+ const content = fs__namespace.readFileSync(envFile, 'utf8');
499
+ if (!content.includes('humanBehaviorApiKey')) {
500
+ const modifiedContent = content.replace(/export const environment = {([\s\S]*?)};/, `export const environment = {
501
+ $1,
502
+ humanBehaviorApiKey: process.env['HUMANBEHAVIOR_API_KEY'] || ''
503
+ };`);
504
+ modifications.push({
505
+ filePath: envFile,
506
+ action: 'modify',
507
+ content: modifiedContent,
508
+ description: 'Added API key to Angular environment'
509
+ });
510
+ }
511
+ }
512
+ // Create or append to environment file
513
+ modifications.push(this.createEnvironmentModification(this.framework));
514
+ return modifications;
515
+ });
516
+ }
517
+ /**
518
+ * Generate Svelte-specific modifications
519
+ */
520
+ generateSvelteModifications() {
521
+ return __awaiter(this, void 0, void 0, function* () {
522
+ const modifications = [];
523
+ // Check for SvelteKit
524
+ const svelteConfigFile = path__namespace.join(this.projectRoot, 'svelte.config.js');
525
+ const isSvelteKit = fs__namespace.existsSync(svelteConfigFile);
526
+ if (isSvelteKit) {
527
+ // SvelteKit - create layout file
528
+ const layoutFile = path__namespace.join(this.projectRoot, 'src', 'routes', '+layout.svelte');
529
+ if (fs__namespace.existsSync(layoutFile)) {
530
+ const content = fs__namespace.readFileSync(layoutFile, 'utf8');
531
+ const modifiedContent = this.injectSvelteKitLayout(content);
532
+ modifications.push({
533
+ filePath: layoutFile,
534
+ action: 'modify',
535
+ content: modifiedContent,
536
+ description: 'Added HumanBehavior store to SvelteKit layout'
537
+ });
538
+ }
539
+ }
540
+ else {
541
+ // Regular Svelte - modify main file
542
+ const mainFile = this.findSvelteMainFile();
543
+ if (mainFile) {
544
+ const content = fs__namespace.readFileSync(mainFile, 'utf8');
545
+ const modifiedContent = this.injectSvelteStore(content);
546
+ modifications.push({
547
+ filePath: mainFile,
548
+ action: 'modify',
549
+ content: modifiedContent,
550
+ description: 'Added HumanBehavior store to Svelte app'
551
+ });
552
+ }
553
+ }
554
+ // Create or append to environment file
555
+ modifications.push(this.createEnvironmentModification(this.framework));
556
+ return modifications;
557
+ });
558
+ }
559
+ /**
560
+ * Generate vanilla JS/TS modifications
561
+ */
562
+ generateVanillaModifications() {
563
+ return __awaiter(this, void 0, void 0, function* () {
564
+ const modifications = [];
565
+ // Find HTML file to inject script
566
+ const htmlFile = this.findHTMLFile();
567
+ if (htmlFile) {
568
+ const content = fs__namespace.readFileSync(htmlFile, 'utf8');
569
+ const modifiedContent = this.injectVanillaScript(content);
570
+ modifications.push({
571
+ filePath: htmlFile,
572
+ action: 'modify',
573
+ content: modifiedContent,
574
+ description: 'Added HumanBehavior CDN script to HTML file'
575
+ });
576
+ }
577
+ // Create or append to environment file
578
+ modifications.push(this.createEnvironmentModification(this.framework));
579
+ return modifications;
580
+ });
581
+ }
582
+ /**
583
+ * Apply modifications to the codebase
584
+ */
585
+ applyModifications(modifications) {
586
+ return __awaiter(this, void 0, void 0, function* () {
587
+ for (const modification of modifications) {
588
+ try {
589
+ const dir = path__namespace.dirname(modification.filePath);
590
+ if (!fs__namespace.existsSync(dir)) {
591
+ fs__namespace.mkdirSync(dir, { recursive: true });
592
+ }
593
+ switch (modification.action) {
594
+ case 'create':
595
+ fs__namespace.writeFileSync(modification.filePath, modification.content);
596
+ break;
597
+ case 'modify':
598
+ fs__namespace.writeFileSync(modification.filePath, modification.content);
599
+ break;
600
+ case 'append':
601
+ fs__namespace.appendFileSync(modification.filePath, '\n' + modification.content);
602
+ break;
603
+ }
604
+ }
605
+ catch (error) {
606
+ throw new Error(`Failed to apply modification to ${modification.filePath}: ${error}`);
607
+ }
608
+ }
609
+ });
610
+ }
611
+ /**
612
+ * Generate next steps for the user
613
+ */
614
+ generateNextSteps() {
615
+ var _a, _b;
616
+ const steps = [
617
+ '✅ SDK installed and configured automatically!',
618
+ '🚀 Your app is now tracking user behavior',
619
+ '📊 View sessions in your HumanBehavior dashboard',
620
+ '🔧 Customize tracking in your code as needed'
621
+ ];
622
+ if (((_a = this.framework) === null || _a === void 0 ? void 0 : _a.type) === 'react' || ((_b = this.framework) === null || _b === void 0 ? void 0 : _b.type) === 'nextjs') {
623
+ steps.push('💡 Use the useHumanBehavior() hook to track custom events');
624
+ }
625
+ return steps;
626
+ }
627
+ // Helper methods for file detection and content injection
628
+ findReactAppFile() {
629
+ const possibleFiles = [
630
+ 'src/App.jsx', 'src/App.js', 'src/App.tsx', 'src/App.ts',
631
+ 'src/index.js', 'src/index.tsx', 'src/main.js', 'src/main.tsx'
632
+ ];
633
+ for (const file of possibleFiles) {
634
+ const fullPath = path__namespace.join(this.projectRoot, file);
635
+ if (fs__namespace.existsSync(fullPath)) {
636
+ return fullPath;
637
+ }
638
+ }
639
+ return null;
640
+ }
641
+ findVueMainFile() {
642
+ const possibleFiles = [
643
+ 'src/main.js', 'src/main.ts', 'src/main.jsx', 'src/main.tsx'
644
+ ];
645
+ for (const file of possibleFiles) {
646
+ const fullPath = path__namespace.join(this.projectRoot, file);
647
+ if (fs__namespace.existsSync(fullPath)) {
648
+ return fullPath;
649
+ }
650
+ }
651
+ return null;
652
+ }
653
+ findSvelteMainFile() {
654
+ const possibleFiles = [
655
+ 'src/main.js', 'src/main.ts', 'src/main.svelte'
656
+ ];
657
+ for (const file of possibleFiles) {
658
+ const fullPath = path__namespace.join(this.projectRoot, file);
659
+ if (fs__namespace.existsSync(fullPath)) {
660
+ return fullPath;
661
+ }
662
+ }
663
+ return null;
664
+ }
665
+ findHTMLFile() {
666
+ const possibleFiles = ['index.html', 'public/index.html', 'dist/index.html'];
667
+ for (const file of possibleFiles) {
668
+ const fullPath = path__namespace.join(this.projectRoot, file);
669
+ if (fs__namespace.existsSync(fullPath)) {
670
+ return fullPath;
671
+ }
672
+ }
673
+ return null;
674
+ }
675
+ injectReactProvider(content, filePath) {
676
+ var _a;
677
+ filePath.endsWith('.tsx') || filePath.endsWith('.ts');
678
+ // Check if already has HumanBehaviorProvider
679
+ if (content.includes('HumanBehaviorProvider')) {
680
+ return content;
681
+ }
682
+ // Determine the correct environment variable syntax based on bundler
683
+ const isVite = ((_a = this.framework) === null || _a === void 0 ? void 0 : _a.bundler) === 'vite';
684
+ const envVar = isVite
685
+ ? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
686
+ : 'process.env.HUMANBEHAVIOR_API_KEY!';
687
+ const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
688
+ // Simple injection - in production, you'd want more sophisticated parsing
689
+ if (content.includes('function App()') || content.includes('const App =')) {
690
+ return content.replace(/(function App\(\)|const App =)/, `${importStatement}\n\n$1`).replace(/return \(([\s\S]*?)\);/, `return (
691
+ <HumanBehaviorProvider apiKey={${envVar}}>
692
+ $1
693
+ </HumanBehaviorProvider>
694
+ );`);
695
+ }
696
+ return `${importStatement}\n\n${content}`;
697
+ }
698
+ injectNextJSAppRouter(content) {
699
+ if (content.includes('Providers')) {
700
+ return content;
701
+ }
702
+ const importStatement = `import { Providers } from './providers';`;
703
+ // First, add the import statement
704
+ let modifiedContent = content.replace(/export default function RootLayout/, `${importStatement}\n\nexport default function RootLayout`);
705
+ // Then wrap the body content with Providers
706
+ // Use a more specific approach to handle the body content
707
+ modifiedContent = modifiedContent.replace(/<body([^>]*)>([\s\S]*?)<\/body>/, (match, bodyAttrs, bodyContent) => {
708
+ // Trim whitespace and newlines from bodyContent
709
+ const trimmedContent = bodyContent.trim();
710
+ return `<body${bodyAttrs}>
711
+ <Providers>
712
+ ${trimmedContent}
713
+ </Providers>
714
+ </body>`;
715
+ });
716
+ return modifiedContent;
717
+ }
718
+ injectNextJSPagesRouter(content) {
719
+ if (content.includes('Providers')) {
720
+ return content;
721
+ }
722
+ const importStatement = `import { Providers } from '../components/providers';`;
723
+ return content.replace(/function MyApp/, `${importStatement}\n\nfunction MyApp`).replace(/return \(([\s\S]*?)\);/, `return (
724
+ <Providers>
725
+ $1
726
+ </Providers>
727
+ );`);
728
+ }
729
+ injectRemixProvider(content) {
730
+ if (content.includes('HumanBehaviorProvider')) {
731
+ return content;
732
+ }
733
+ const importStatement = `import { HumanBehaviorProvider, createHumanBehaviorLoader } from 'humanbehavior-js/remix';`;
734
+ const useLoaderDataImport = `import { useLoaderData } from "@remix-run/react";`;
735
+ // Add imports more robustly
736
+ let modifiedContent = content;
737
+ // Add HumanBehaviorProvider import - find the last import and add after it
738
+ if (!content.includes('HumanBehaviorProvider')) {
739
+ const lastImportIndex = modifiedContent.lastIndexOf('import');
740
+ if (lastImportIndex !== -1) {
741
+ const nextLineIndex = modifiedContent.indexOf('\n', lastImportIndex);
742
+ if (nextLineIndex !== -1) {
743
+ modifiedContent = modifiedContent.slice(0, nextLineIndex + 1) +
744
+ importStatement + '\n' +
745
+ modifiedContent.slice(nextLineIndex + 1);
746
+ }
747
+ else {
748
+ modifiedContent = modifiedContent + '\n' + importStatement;
749
+ }
750
+ }
751
+ else {
752
+ modifiedContent = importStatement + '\n' + modifiedContent;
753
+ }
754
+ }
755
+ // Add useLoaderData import - find the last import and add after it
756
+ if (!content.includes('useLoaderData')) {
757
+ const lastImportIndex = modifiedContent.lastIndexOf('import');
758
+ if (lastImportIndex !== -1) {
759
+ const nextLineIndex = modifiedContent.indexOf('\n', lastImportIndex);
760
+ if (nextLineIndex !== -1) {
761
+ modifiedContent = modifiedContent.slice(0, nextLineIndex + 1) +
762
+ useLoaderDataImport + '\n' +
763
+ modifiedContent.slice(nextLineIndex + 1);
764
+ }
765
+ else {
766
+ modifiedContent = modifiedContent + '\n' + useLoaderDataImport;
767
+ }
768
+ }
769
+ else {
770
+ modifiedContent = useLoaderDataImport + '\n' + modifiedContent;
771
+ }
772
+ }
773
+ // Add loader function before the App component
774
+ if (!content.includes('export const loader')) {
775
+ modifiedContent = modifiedContent.replace(/export default function App\(\)/, `export const loader = createHumanBehaviorLoader();
776
+
777
+ export default function App()`);
778
+ }
779
+ // Wrap the App component content with HumanBehaviorProvider
780
+ modifiedContent = modifiedContent.replace(/export default function App\(\) \{[\s\S]*?return \(([\s\S]*?)\);[\s\S]*?\}/, `export default function App() {
781
+ const data = useLoaderData<typeof loader>();
782
+
783
+ return (
784
+ <HumanBehaviorProvider apiKey={data.ENV.HUMANBEHAVIOR_API_KEY}>
785
+ $1
786
+ </HumanBehaviorProvider>
787
+ );
788
+ }`);
789
+ return modifiedContent;
790
+ }
791
+ injectVuePlugin(content) {
792
+ if (content.includes('HumanBehaviorPlugin')) {
793
+ return content;
794
+ }
795
+ const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
796
+ const pluginUsage = `app.use(HumanBehaviorPlugin, {
797
+ apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
798
+ });`;
799
+ // Handle both Vue 2 and Vue 3 patterns
800
+ if (content.includes('createApp')) {
801
+ // Vue 3
802
+ return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/app\.mount\(/, `${pluginUsage}\n\napp.mount(`);
803
+ }
804
+ else {
805
+ // Vue 2
806
+ return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/new Vue\(/, `${pluginUsage}\n\nnew Vue(`);
807
+ }
808
+ }
809
+ injectAngularModule(content) {
810
+ if (content.includes('HumanBehaviorModule')) {
811
+ return content;
812
+ }
813
+ const importStatement = `import { HumanBehaviorModule } from 'humanbehavior-js/angular';`;
814
+ const environmentImport = `import { environment } from '../environments/environment';`;
815
+ // Add environment import if not present
816
+ let modifiedContent = content;
817
+ if (!content.includes('environment')) {
818
+ modifiedContent = content.replace(/import.*from.*['"]@angular/, `${environmentImport}\n$&`);
819
+ }
820
+ return modifiedContent.replace(/imports:\s*\[([\s\S]*?)\]/, `imports: [
821
+ $1,
822
+ HumanBehaviorModule.forRoot({
823
+ apiKey: environment.humanBehaviorApiKey
824
+ })
825
+ ]`).replace(/import.*from.*['"]@angular/, `$&\n${importStatement}`);
826
+ }
827
+ injectAngularStandaloneInit(content) {
828
+ if (content.includes('initializeHumanBehavior')) {
829
+ return content;
830
+ }
831
+ const importStatement = `import { initializeHumanBehavior } from 'humanbehavior-js/angular';`;
832
+ // Add import at the top
833
+ let modifiedContent = content.replace(/import.*from.*['"]@angular/, `${importStatement}\n$&`);
834
+ // Add initialization after bootstrapApplication
835
+ modifiedContent = modifiedContent.replace(/(bootstrapApplication\([^}]+\}?\)(?:\s*\.catch[^;]+;)?)/, `$1
836
+
837
+ // Initialize HumanBehavior SDK (client-side only)
838
+ if (typeof window !== 'undefined') {
839
+ const tracker = initializeHumanBehavior(
840
+ '${this.apiKey}'
841
+ );
842
+ }`);
843
+ return modifiedContent;
844
+ }
845
+ injectSvelteStore(content) {
846
+ if (content.includes('humanBehaviorStore')) {
847
+ return content;
848
+ }
849
+ const importStatement = `import { humanBehaviorStore } from 'humanbehavior-js/svelte';`;
850
+ const initCode = `humanBehaviorStore.init(process.env.PUBLIC_HUMANBEHAVIOR_API_KEY || '');`;
851
+ return `${importStatement}\n${initCode}\n\n${content}`;
852
+ }
853
+ injectSvelteKitLayout(content) {
854
+ if (content.includes('humanBehaviorStore')) {
855
+ return content;
856
+ }
857
+ const importStatement = `import { humanBehaviorStore } from 'humanbehavior-js/svelte';`;
858
+ const envImport = `import { PUBLIC_HUMANBEHAVIOR_API_KEY } from '$env/static/public';`;
859
+ const initCode = `humanBehaviorStore.init(PUBLIC_HUMANBEHAVIOR_API_KEY || '');`;
860
+ // Add to script section - handle different script tag patterns
861
+ if (content.includes('<script lang="ts">')) {
862
+ return content.replace(/<script lang="ts">/, `<script lang="ts">\n\t${envImport}\n\t${importStatement}\n\t${initCode}`);
863
+ }
864
+ else if (content.includes('<script>')) {
865
+ return content.replace(/<script>/, `<script>\n\t${envImport}\n\t${importStatement}\n\t${initCode}`);
866
+ }
867
+ else if (content.includes('<script context="module">')) {
868
+ return content.replace(/<script\s+context="module">/, `<script context="module">\n\t${envImport}\n\t${importStatement}\n\t${initCode}`);
869
+ }
870
+ else {
871
+ // If no script tag found, add one at the beginning
872
+ return content.replace(/<svelte:head>/, `<script lang="ts">\n\t${envImport}\n\t${importStatement}\n\t${initCode}\n</script>\n\n<svelte:head>`);
873
+ }
874
+ }
875
+ injectVanillaScript(content) {
876
+ if (content.includes('humanbehavior-js')) {
877
+ return content;
878
+ }
879
+ const cdnScript = `<script src="https://unpkg.com/humanbehavior-js@latest/dist/index.min.js"></script>`;
880
+ const initScript = `<script>
881
+ // Initialize HumanBehavior SDK
882
+ // Note: For vanilla HTML, the API key must be hardcoded since env vars aren't available
883
+ const tracker = HumanBehaviorTracker.init('${this.apiKey}');
884
+ </script>`;
885
+ return content.replace(/<\/head>/, ` ${cdnScript}\n ${initScript}\n</head>`);
886
+ }
887
+ injectNuxtConfig(content) {
888
+ if (content.includes('humanBehaviorApiKey')) {
889
+ return content;
890
+ }
891
+ // Add runtime config by inserting it after the opening brace
892
+ return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
893
+ runtimeConfig: {
894
+ public: {
895
+ humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
896
+ }
897
+ },`);
898
+ }
899
+ /**
900
+ * Helper method to find the best environment file for a framework
901
+ */
902
+ findBestEnvFile(framework) {
903
+ const possibleEnvFiles = [
904
+ '.env.local',
905
+ '.env.development.local',
906
+ '.env.development',
907
+ '.env.local.development',
908
+ '.env',
909
+ '.env.production',
910
+ '.env.staging'
911
+ ];
912
+ // Framework-specific environment variable names
913
+ const getEnvVarName = (framework) => {
914
+ // Handle React+Vite specifically
915
+ if (framework.type === 'react' && framework.bundler === 'vite') {
916
+ return 'VITE_HUMANBEHAVIOR_API_KEY';
917
+ }
918
+ // Framework-specific mappings
919
+ const envVarNames = {
920
+ react: 'HUMANBEHAVIOR_API_KEY',
921
+ nextjs: 'NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
922
+ vue: 'VITE_HUMANBEHAVIOR_API_KEY',
923
+ svelte: 'PUBLIC_HUMANBEHAVIOR_API_KEY',
924
+ angular: 'HUMANBEHAVIOR_API_KEY',
925
+ nuxt: 'NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY',
926
+ remix: 'HUMANBEHAVIOR_API_KEY',
927
+ vanilla: 'HUMANBEHAVIOR_API_KEY',
928
+ node: 'HUMANBEHAVIOR_API_KEY'
929
+ };
930
+ return envVarNames[framework.type] || 'HUMANBEHAVIOR_API_KEY';
931
+ };
932
+ const envVarName = getEnvVarName(framework);
933
+ // Check for existing files
934
+ for (const envFile of possibleEnvFiles) {
935
+ const fullPath = path__namespace.join(this.projectRoot, envFile);
936
+ if (fs__namespace.existsSync(fullPath)) {
937
+ return { filePath: fullPath, envVarName };
938
+ }
939
+ }
940
+ // Framework-specific default file creation
941
+ const defaultFiles = {
942
+ react: '.env.local',
943
+ nextjs: '.env.local',
944
+ vue: '.env.local',
945
+ svelte: '.env',
946
+ angular: '.env',
947
+ nuxt: '.env',
948
+ remix: '.env.local',
949
+ vanilla: '.env',
950
+ node: '.env'
951
+ };
952
+ const defaultFile = defaultFiles[framework.type] || '.env';
953
+ return {
954
+ filePath: path__namespace.join(this.projectRoot, defaultFile),
955
+ envVarName
956
+ };
957
+ }
958
+ /**
959
+ * Helper method to create or append to environment files
960
+ */
961
+ createEnvironmentModification(framework) {
962
+ const { filePath, envVarName } = this.findBestEnvFile(framework);
963
+ if (fs__namespace.existsSync(filePath)) {
964
+ // Check if the variable already exists
965
+ const content = fs__namespace.readFileSync(filePath, 'utf8');
966
+ if (content.includes(envVarName)) {
967
+ // Variable exists, don't modify
968
+ return {
969
+ filePath,
970
+ action: 'modify',
971
+ content: content, // No change
972
+ description: `API key already exists in ${path__namespace.basename(filePath)}`
973
+ };
974
+ }
975
+ else {
976
+ // Append to existing file
977
+ return {
978
+ filePath,
979
+ action: 'append',
980
+ content: `\n${envVarName}=${this.apiKey}`,
981
+ description: `Added API key to existing ${path__namespace.basename(filePath)}`
982
+ };
983
+ }
984
+ }
985
+ else {
986
+ // Create new file
987
+ return {
988
+ filePath,
989
+ action: 'create',
990
+ content: `${envVarName}=${this.apiKey}`,
991
+ description: `Created ${path__namespace.basename(filePath)} with API key`
992
+ };
993
+ }
994
+ }
995
+ }
996
+ /**
997
+ * Browser-based auto-installation wizard
998
+ */
999
+ class BrowserAutoInstallationWizard {
1000
+ constructor(apiKey) {
1001
+ this.apiKey = apiKey;
1002
+ }
1003
+ install() {
1004
+ return __awaiter(this, void 0, void 0, function* () {
1005
+ try {
1006
+ // Detect framework in browser
1007
+ const framework = this.detectFramework();
1008
+ // Generate installation instructions
1009
+ const modifications = this.generateBrowserModifications(framework);
1010
+ return {
1011
+ success: true,
1012
+ framework,
1013
+ modifications,
1014
+ errors: [],
1015
+ nextSteps: [
1016
+ '✅ Framework detected automatically',
1017
+ '📋 Copy the generated code to your project',
1018
+ '🚀 Your app will be ready to track user behavior'
1019
+ ]
1020
+ };
1021
+ }
1022
+ catch (error) {
1023
+ return {
1024
+ success: false,
1025
+ framework: { name: 'unknown', type: 'vanilla' },
1026
+ modifications: [],
1027
+ errors: [error instanceof Error ? error.message : 'Unknown error'],
1028
+ nextSteps: []
1029
+ };
1030
+ }
1031
+ });
1032
+ }
1033
+ detectFramework() {
1034
+ if (typeof window !== 'undefined') {
1035
+ if (window.React) {
1036
+ return { name: 'react', type: 'react' };
1037
+ }
1038
+ if (window.Vue) {
1039
+ return { name: 'vue', type: 'vue' };
1040
+ }
1041
+ if (window.angular) {
1042
+ return { name: 'angular', type: 'angular' };
1043
+ }
1044
+ }
1045
+ return { name: 'vanilla', type: 'vanilla' };
1046
+ }
1047
+ generateBrowserModifications(framework) {
1048
+ // Return code snippets for browser environment
1049
+ const modifications = [];
1050
+ switch (framework.type) {
1051
+ case 'react':
1052
+ modifications.push({
1053
+ filePath: 'App.jsx',
1054
+ action: 'create',
1055
+ content: `import { HumanBehaviorProvider } from 'humanbehavior-js/react';
1056
+
1057
+ function App() {
1058
+ return (
1059
+ <HumanBehaviorProvider apiKey="${this.apiKey}">
1060
+ {/* Your app components */}
1061
+ </HumanBehaviorProvider>
1062
+ );
1063
+ }
1064
+
1065
+ export default App;`,
1066
+ description: 'React component with HumanBehaviorProvider'
1067
+ });
1068
+ break;
1069
+ case 'remix':
1070
+ modifications.push({
1071
+ filePath: 'app/root.tsx',
1072
+ action: 'create',
1073
+ content: `import {
1074
+ Links,
1075
+ Meta,
1076
+ Outlet,
1077
+ Scripts,
1078
+ ScrollRestoration,
1079
+ useLoaderData,
1080
+ } from "@remix-run/react";
1081
+ import { HumanBehaviorProvider } from 'humanbehavior-js/react';
1082
+ import type { LoaderFunctionArgs } from "@remix-run/node";
1083
+
1084
+ export async function loader({ request }: LoaderFunctionArgs) {
1085
+ return {
1086
+ ENV: {
1087
+ HUMANBEHAVIOR_API_KEY: process.env.HUMANBEHAVIOR_API_KEY,
1088
+ },
1089
+ };
1090
+ }
1091
+
1092
+ export function Layout({ children }: { children: React.ReactNode }) {
1093
+ return (
1094
+ <html lang="en">
1095
+ <head>
1096
+ <meta charSet="utf-8" />
1097
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
1098
+ <Meta />
1099
+ <Links />
1100
+ </head>
1101
+ <body>
1102
+ {children}
1103
+ <ScrollRestoration />
1104
+ <Scripts />
1105
+ </body>
1106
+ </html>
1107
+ );
1108
+ }
1109
+
1110
+ export default function App() {
1111
+ const data = useLoaderData<typeof loader>();
1112
+
1113
+ return (
1114
+ <HumanBehaviorProvider apiKey={data.ENV.HUMANBEHAVIOR_API_KEY}>
1115
+ <div className="min-h-screen bg-gray-50">
1116
+ {/* Your app content */}
1117
+ <Outlet />
1118
+ </div>
1119
+ </HumanBehaviorProvider>
1120
+ );
1121
+ }`,
1122
+ description: 'Remix root component with HumanBehaviorProvider'
1123
+ });
1124
+ break;
1125
+ case 'vue':
1126
+ modifications.push({
1127
+ filePath: 'main.js',
1128
+ action: 'create',
1129
+ content: `import { createApp } from 'vue';
1130
+ import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';
1131
+ import App from './App.vue';
1132
+
1133
+ const app = createApp(App);
1134
+ app.use(HumanBehaviorPlugin, {
1135
+ apiKey: '${this.apiKey}'
1136
+ });
1137
+ app.mount('#app');`,
1138
+ description: 'Vue app with HumanBehaviorPlugin'
1139
+ });
1140
+ break;
1141
+ default:
1142
+ modifications.push({
1143
+ filePath: 'humanbehavior-init.js',
1144
+ action: 'create',
1145
+ content: `import { HumanBehaviorTracker } from 'humanbehavior-js';
1146
+
1147
+ const tracker = HumanBehaviorTracker.init('${this.apiKey}');`,
1148
+ description: 'Vanilla JS initialization'
1149
+ });
1150
+ }
1151
+ return modifications;
1152
+ }
1153
+ }
1154
+
1155
+ exports.AutoInstallationWizard = AutoInstallationWizard;
1156
+ exports.BrowserAutoInstallationWizard = BrowserAutoInstallationWizard;
1157
+ //# sourceMappingURL=install-wizard.cjs.map