humanbehavior-js 0.4.14 → 0.4.16

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.
@@ -70,6 +70,28 @@ class AutoInstallationWizard {
70
70
  this.apiKey = apiKey;
71
71
  this.projectRoot = projectRoot;
72
72
  }
73
+ /**
74
+ * Simple version comparison utility
75
+ */
76
+ compareVersions(version1, version2) {
77
+ const v1Parts = version1.split('.').map(Number);
78
+ const v2Parts = version2.split('.').map(Number);
79
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
80
+ const v1 = v1Parts[i] || 0;
81
+ const v2 = v2Parts[i] || 0;
82
+ if (v1 > v2)
83
+ return 1;
84
+ if (v1 < v2)
85
+ return -1;
86
+ }
87
+ return 0;
88
+ }
89
+ isVersionGte(version, target) {
90
+ return this.compareVersions(version, target) >= 0;
91
+ }
92
+ getMajorVersion(version) {
93
+ return parseInt(version.split('.')[0]) || 0;
94
+ }
73
95
  /**
74
96
  * Main installation method - detects framework and auto-installs
75
97
  */
@@ -119,91 +141,146 @@ class AutoInstallationWizard {
119
141
  }
120
142
  const packageJson = JSON.parse(fs__namespace.readFileSync(packageJsonPath, 'utf8'));
121
143
  const dependencies = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies);
122
- // Detect framework
144
+ // Detect framework with version information
123
145
  let framework = {
124
146
  name: 'vanilla',
125
147
  type: 'vanilla',
126
- projectRoot: this.projectRoot
148
+ projectRoot: this.projectRoot,
149
+ features: {}
127
150
  };
128
151
  if (dependencies.nuxt) {
152
+ const nuxtVersion = dependencies.nuxt;
153
+ const isNuxt3 = this.isVersionGte(nuxtVersion, '3.0.0');
129
154
  framework = {
130
155
  name: 'nuxt',
131
156
  type: 'nuxt',
157
+ version: nuxtVersion,
158
+ majorVersion: this.getMajorVersion(nuxtVersion),
132
159
  hasTypeScript: !!dependencies.typescript,
133
160
  hasRouter: true,
134
- projectRoot: this.projectRoot
161
+ projectRoot: this.projectRoot,
162
+ features: {
163
+ hasNuxt3: isNuxt3
164
+ }
135
165
  };
136
166
  }
137
167
  else if (dependencies.next) {
168
+ const nextVersion = dependencies.next;
169
+ const isNext13 = this.isVersionGte(nextVersion, '13.0.0');
138
170
  framework = {
139
171
  name: 'nextjs',
140
172
  type: 'nextjs',
173
+ version: nextVersion,
174
+ majorVersion: this.getMajorVersion(nextVersion),
141
175
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/node'],
142
176
  hasRouter: true,
143
- projectRoot: this.projectRoot
177
+ projectRoot: this.projectRoot,
178
+ features: {
179
+ hasNextAppRouter: isNext13
180
+ }
144
181
  };
145
182
  }
146
183
  else if (dependencies['@remix-run/react'] || dependencies['@remix-run/dev']) {
184
+ const remixVersion = dependencies['@remix-run/react'] || dependencies['@remix-run/dev'];
147
185
  framework = {
148
186
  name: 'remix',
149
187
  type: 'remix',
188
+ version: remixVersion,
189
+ majorVersion: this.getMajorVersion(remixVersion),
150
190
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
151
191
  hasRouter: true,
152
- projectRoot: this.projectRoot
192
+ projectRoot: this.projectRoot,
193
+ features: {}
153
194
  };
154
195
  }
155
196
  else if (dependencies.react) {
197
+ const reactVersion = dependencies.react;
198
+ const isReact18 = this.isVersionGte(reactVersion, '18.0.0');
156
199
  framework = {
157
200
  name: 'react',
158
201
  type: 'react',
202
+ version: reactVersion,
203
+ majorVersion: this.getMajorVersion(reactVersion),
159
204
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
160
205
  hasRouter: !!dependencies['react-router-dom'] || !!dependencies['react-router'],
161
- projectRoot: this.projectRoot
206
+ projectRoot: this.projectRoot,
207
+ features: {
208
+ hasReact18: isReact18
209
+ }
162
210
  };
163
211
  }
164
212
  else if (dependencies.vue) {
213
+ const vueVersion = dependencies.vue;
214
+ const isVue3 = this.isVersionGte(vueVersion, '3.0.0');
165
215
  framework = {
166
216
  name: 'vue',
167
217
  type: 'vue',
218
+ version: vueVersion,
219
+ majorVersion: this.getMajorVersion(vueVersion),
168
220
  hasTypeScript: !!dependencies.typescript || !!dependencies['@vue/cli-service'],
169
221
  hasRouter: !!dependencies['vue-router'],
170
- projectRoot: this.projectRoot
222
+ projectRoot: this.projectRoot,
223
+ features: {
224
+ hasVue3: isVue3
225
+ }
171
226
  };
172
227
  }
173
228
  else if (dependencies['@angular/core']) {
229
+ const angularVersion = dependencies['@angular/core'];
230
+ const isAngular17 = this.isVersionGte(angularVersion, '17.0.0');
174
231
  framework = {
175
232
  name: 'angular',
176
233
  type: 'angular',
234
+ version: angularVersion,
235
+ majorVersion: this.getMajorVersion(angularVersion),
177
236
  hasTypeScript: true,
178
237
  hasRouter: true,
179
- projectRoot: this.projectRoot
238
+ projectRoot: this.projectRoot,
239
+ features: {
240
+ hasAngularStandalone: isAngular17
241
+ }
180
242
  };
181
243
  }
182
244
  else if (dependencies.svelte) {
245
+ const svelteVersion = dependencies.svelte;
246
+ const isSvelteKit = !!dependencies['@sveltejs/kit'];
183
247
  framework = {
184
248
  name: 'svelte',
185
249
  type: 'svelte',
250
+ version: svelteVersion,
251
+ majorVersion: this.getMajorVersion(svelteVersion),
186
252
  hasTypeScript: !!dependencies.typescript || !!dependencies['svelte-check'],
187
253
  hasRouter: !!dependencies['svelte-routing'] || !!dependencies['@sveltejs/kit'],
188
- projectRoot: this.projectRoot
254
+ projectRoot: this.projectRoot,
255
+ features: {
256
+ hasSvelteKit: isSvelteKit
257
+ }
189
258
  };
190
259
  }
191
260
  else if (dependencies.astro) {
261
+ const astroVersion = dependencies.astro;
192
262
  framework = {
193
263
  name: 'astro',
194
264
  type: 'astro',
265
+ version: astroVersion,
266
+ majorVersion: this.getMajorVersion(astroVersion),
195
267
  hasTypeScript: !!dependencies.typescript || !!dependencies['@astrojs/ts-plugin'],
196
268
  hasRouter: true,
197
- projectRoot: this.projectRoot
269
+ projectRoot: this.projectRoot,
270
+ features: {}
198
271
  };
199
272
  }
200
273
  else if (dependencies.gatsby) {
274
+ const gatsbyVersion = dependencies.gatsby;
201
275
  framework = {
202
276
  name: 'gatsby',
203
277
  type: 'gatsby',
278
+ version: gatsbyVersion,
279
+ majorVersion: this.getMajorVersion(gatsbyVersion),
204
280
  hasTypeScript: !!dependencies.typescript || !!dependencies['@types/react'],
205
281
  hasRouter: true,
206
- projectRoot: this.projectRoot
282
+ projectRoot: this.projectRoot,
283
+ features: {}
207
284
  };
208
285
  }
209
286
  // Detect bundler
@@ -827,7 +904,7 @@ export const onClientEntry = () => {
827
904
  return null;
828
905
  }
829
906
  injectReactProvider(content, filePath) {
830
- var _a;
907
+ var _a, _b, _c;
831
908
  filePath.endsWith('.tsx') || filePath.endsWith('.ts');
832
909
  // Check if already has HumanBehaviorProvider
833
910
  if (content.includes('HumanBehaviorProvider')) {
@@ -839,14 +916,39 @@ export const onClientEntry = () => {
839
916
  ? 'import.meta.env.VITE_HUMANBEHAVIOR_API_KEY!'
840
917
  : 'process.env.HUMANBEHAVIOR_API_KEY!';
841
918
  const importStatement = `import { HumanBehaviorProvider } from 'humanbehavior-js/react';`;
842
- // Simple injection - in production, you'd want more sophisticated parsing
919
+ // Enhanced parsing for React 18+ features
920
+ const hasReact18 = (_c = (_b = this.framework) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.hasReact18;
921
+ // Handle different React patterns
843
922
  if (content.includes('function App()') || content.includes('const App =')) {
844
- return content.replace(/(function App\(\)|const App =)/, `${importStatement}\n\n$1`).replace(/return \(([\s\S]*?)\);/, `return (
923
+ // Add import statement
924
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
925
+ // If no React import found, add it at the top
926
+ if (!modifiedContent.includes(importStatement)) {
927
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
928
+ }
929
+ // Wrap the App component return with HumanBehaviorProvider
930
+ modifiedContent = modifiedContent.replace(/(return\s*\([\s\S]*?\)\s*;)/, `return (
931
+ <HumanBehaviorProvider apiKey={${envVar}}>
932
+ $1
933
+ </HumanBehaviorProvider>
934
+ );`);
935
+ return modifiedContent;
936
+ }
937
+ // Handle React 18+ createRoot pattern
938
+ if (hasReact18 && content.includes('createRoot')) {
939
+ let modifiedContent = content.replace(/(import.*?from.*?['"]react['"];?)/, `$1\n${importStatement}`);
940
+ if (!modifiedContent.includes(importStatement)) {
941
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
942
+ }
943
+ // Wrap the root render with HumanBehaviorProvider
944
+ modifiedContent = modifiedContent.replace(/(root\.render\s*\([\s\S]*?\)\s*;)/, `root.render(
845
945
  <HumanBehaviorProvider apiKey={${envVar}}>
846
946
  $1
847
947
  </HumanBehaviorProvider>
848
948
  );`);
949
+ return modifiedContent;
849
950
  }
951
+ // Fallback: simple injection
850
952
  return `${importStatement}\n\n${content}`;
851
953
  }
852
954
  injectNextJSAppRouter(content) {
@@ -943,21 +1045,51 @@ export default function App()`);
943
1045
  return modifiedContent;
944
1046
  }
945
1047
  injectVuePlugin(content) {
1048
+ var _a, _b;
946
1049
  if (content.includes('HumanBehaviorPlugin')) {
947
1050
  return content;
948
1051
  }
949
1052
  const importStatement = `import { HumanBehaviorPlugin } from 'humanbehavior-js/vue';`;
950
- const pluginUsage = `app.use(HumanBehaviorPlugin, {
1053
+ // Enhanced Vue 3 support with version detection
1054
+ const hasVue3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasVue3;
1055
+ if (hasVue3) {
1056
+ // Vue 3 with Composition API
1057
+ const pluginUsage = `app.use(HumanBehaviorPlugin, {
951
1058
  apiKey: import.meta.env.VITE_HUMANBEHAVIOR_API_KEY
952
1059
  });`;
953
- // Handle both Vue 2 and Vue 3 patterns
954
- if (content.includes('createApp')) {
955
- // Vue 3
956
- return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/app\.mount\(/, `${pluginUsage}\n\napp.mount(`);
1060
+ let modifiedContent = content;
1061
+ // Add import statement
1062
+ if (!content.includes(importStatement)) {
1063
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1064
+ // If no Vue import found, add it at the top
1065
+ if (!modifiedContent.includes(importStatement)) {
1066
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1067
+ }
1068
+ }
1069
+ // Handle createApp pattern
1070
+ if (content.includes('createApp')) {
1071
+ modifiedContent = modifiedContent.replace(/(app\.mount\(.*?\))/, `${pluginUsage}\n\n$1`);
1072
+ }
1073
+ return modifiedContent;
957
1074
  }
958
1075
  else {
959
- // Vue 2
960
- return content.replace(/import.*from.*['"]vue['"]/, `$&\n${importStatement}`).replace(/new Vue\(/, `${pluginUsage}\n\nnew Vue(`);
1076
+ // Vue 2 with Options API
1077
+ const pluginUsage = `Vue.use(HumanBehaviorPlugin, {
1078
+ apiKey: process.env.VUE_APP_HUMANBEHAVIOR_API_KEY
1079
+ });`;
1080
+ let modifiedContent = content;
1081
+ // Add import statement
1082
+ if (!content.includes(importStatement)) {
1083
+ modifiedContent = content.replace(/(import.*?from.*?['"]vue['"];?)/, `$1\n${importStatement}`);
1084
+ if (!modifiedContent.includes(importStatement)) {
1085
+ modifiedContent = `${importStatement}\n\n${modifiedContent}`;
1086
+ }
1087
+ }
1088
+ // Handle new Vue pattern
1089
+ if (content.includes('new Vue')) {
1090
+ modifiedContent = modifiedContent.replace(/(new Vue\(.*?\))/, `${pluginUsage}\n\n$1`);
1091
+ }
1092
+ return modifiedContent;
961
1093
  }
962
1094
  }
963
1095
  injectAngularModule(content) {
@@ -1070,16 +1202,28 @@ if (typeof window !== 'undefined') {
1070
1202
  return modifiedContent.slice(0, bodyCloseIndex) + ' <HumanBehavior />\n' + modifiedContent.slice(bodyCloseIndex);
1071
1203
  }
1072
1204
  injectNuxtConfig(content) {
1205
+ var _a, _b;
1073
1206
  if (content.includes('humanBehaviorApiKey')) {
1074
1207
  return content;
1075
1208
  }
1076
- // Add runtime config by inserting it after the opening brace
1077
- return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
1209
+ // Enhanced Nuxt 3 support with version detection
1210
+ const hasNuxt3 = (_b = (_a = this.framework) === null || _a === void 0 ? void 0 : _a.features) === null || _b === void 0 ? void 0 : _b.hasNuxt3;
1211
+ if (hasNuxt3) {
1212
+ // Nuxt 3 with runtime config
1213
+ return content.replace(/export default defineNuxtConfig\(\{/, `export default defineNuxtConfig({
1078
1214
  runtimeConfig: {
1079
1215
  public: {
1080
1216
  humanBehaviorApiKey: process.env.NUXT_PUBLIC_HUMANBEHAVIOR_API_KEY
1081
1217
  }
1082
1218
  },`);
1219
+ }
1220
+ else {
1221
+ // Nuxt 2 with env config
1222
+ return content.replace(/export default \{/, `export default {
1223
+ env: {
1224
+ humanBehaviorApiKey: process.env.HUMANBEHAVIOR_API_KEY
1225
+ },`);
1226
+ }
1083
1227
  }
1084
1228
  injectGatsbyLayout(content) {
1085
1229
  if (content.includes('HumanBehavior')) {