itube-specs 0.0.445 → 0.0.446

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.
@@ -41,7 +41,7 @@ import type { IPasswordForm } from '../../types';
41
41
  import { validateEmail } from '../../runtime';
42
42
  import { AuthorizationApiService } from '~/services/api/authorization.service';
43
43
 
44
- import { initRecaptcha, getRecaptchaToken } from '../../composables/use-recaptcha';
44
+ const { initRecaptcha, getRecaptchaToken } = useRecaptcha();
45
45
 
46
46
  const {t} = useI18n();
47
47
 
@@ -76,7 +76,7 @@ import type { IRegistrateForm } from '../../types';
76
76
  import { validateEmail, validatePassword, validateUsername } from '../../runtime';
77
77
  import { AuthorizationApiService } from '~/services/api/authorization.service';
78
78
 
79
- import { initRecaptcha, getRecaptchaToken } from '../../composables/use-recaptcha';
79
+ const { initRecaptcha, getRecaptchaToken } = useRecaptcha();
80
80
 
81
81
  defineProps<{
82
82
  additionalText?: string;
@@ -115,7 +115,7 @@ import { reportFormsScheme } from '../../lib/report-forms-scheme';
115
115
  import { EReportFormsSubjects, validateEmail, validatePhone } from '../../runtime';
116
116
  import type { InputTypes, IReportForm, IReportRequest } from '../../types';
117
117
 
118
- import { initRecaptcha, getRecaptchaToken } from '../../composables/use-recaptcha';
118
+ const { initRecaptcha, getRecaptchaToken } = useRecaptcha();
119
119
 
120
120
  const reasonValue = ref('');
121
121
  const errorRadio = ref(false);
@@ -1,75 +1,81 @@
1
- // composables/useRecaptcha.ts
2
- import { useRuntimeConfig } from '#imports';
3
-
4
- let recaptchaLoaded = false;
5
- let siteKey: string | null = null;
6
-
7
- async function loadRecaptchaScript(): Promise<void> {
8
- // Всё только на клиенте (SSR-safe)
9
- if (process.server) return;
1
+ // composables/useRecaptcha.ts (или use-recaptcha.ts для auto-import как useRecaptcha)
10
2
 
11
- if (recaptchaLoaded) return;
3
+ import { useRuntimeConfig } from '#imports';
12
4
 
13
- siteKey = useRuntimeConfig().public.recaptchaSiteKey;
5
+ export function useRecaptcha() {
6
+ let recaptchaLoaded = false;
7
+ let siteKey: string | null = null;
14
8
 
15
- if (!siteKey) {
16
- console.warn('reCAPTCHA siteKey не задан — защита отключена');
17
- return;
18
- }
9
+ async function loadRecaptchaScript(): Promise<void> {
10
+ // SSR-safe: только на клиенте
11
+ if (process.server) return;
19
12
 
20
- const useRecaptchaNet = true; // true = recaptcha.net (для регионов с блокировкой Google)
21
- const domain = useRecaptchaNet ? 'recaptcha.net' : 'www.google.com';
13
+ if (recaptchaLoaded) return;
22
14
 
23
- const script = document.createElement('script');
24
- script.src = `https://${domain}/recaptcha/api.js?render=${siteKey}&hl=ru`;
25
- script.async = true;
26
- script.defer = true;
27
- document.head.appendChild(script);
15
+ siteKey = useRuntimeConfig().public.recaptchaSiteKey;
28
16
 
29
- // Polling до готовности grecaptcha (надёжно и без ошибок listener)
30
- const maxAttempts = 100; // ~10 сек
31
- let attempts = 0;
32
-
33
- while (typeof (window as any).grecaptcha === 'undefined' || !(window as any).grecaptcha.execute) {
34
- if (attempts >= maxAttempts) {
35
- throw new Error('reCAPTCHA не загрузился (таймаут)');
17
+ if (!siteKey) {
18
+ console.warn('reCAPTCHA siteKey не задан защита отключена');
19
+ return;
36
20
  }
37
- await new Promise(resolve => setTimeout(resolve, 100));
38
- attempts++;
39
- }
40
-
41
- recaptchaLoaded = true;
42
-
43
- // Опционально: скрываем бейдж (если хотите глобально)
44
- const style = document.createElement('style');
45
- style.textContent = '.grecaptcha-badge { visibility: hidden !important; }';
46
- document.head.appendChild(style);
47
21
 
48
- console.log('reCAPTCHA v3 загружен глобально');
49
- }
22
+ const useRecaptchaNet = true; // true = recaptcha.net (для регионов с блокировкой Google)
23
+ const domain = useRecaptchaNet ? 'recaptcha.net' : 'www.google.com';
24
+
25
+ const script = document.createElement('script');
26
+ script.src = `https://${domain}/recaptcha/api.js?render=${siteKey}&hl=ru`;
27
+ script.async = true;
28
+ script.defer = true;
29
+ document.head.appendChild(script);
30
+
31
+ // Polling до готовности grecaptcha
32
+ const maxAttempts = 100; // ~10 сек
33
+ let attempts = 0;
34
+
35
+ while (typeof (window as any).grecaptcha === 'undefined' || !(window as any).grecaptcha.execute) {
36
+ if (attempts >= maxAttempts) {
37
+ throw new Error('reCAPTCHA не загрузился (таймаут)');
38
+ }
39
+ await new Promise(resolve => setTimeout(resolve, 100));
40
+ attempts++;
41
+ }
50
42
 
51
- // Инициализация — вызывайте в onMounted формы (даёт время на мониторинг поведения)
52
- export async function initRecaptcha(): Promise<void> {
53
- if (process.server) return;
54
- if (recaptchaLoaded || !siteKey) return;
43
+ recaptchaLoaded = true;
55
44
 
56
- await loadRecaptchaScript();
57
- }
45
+ // Скрываем бейдж глобально (один раз)
46
+ const style = document.createElement('style');
47
+ style.textContent = '.grecaptcha-badge { visibility: hidden !important; }';
48
+ document.head.appendChild(style);
58
49
 
59
- // Получение токена — вызывайте в submit
60
- export async function getRecaptchaToken(action: string): Promise<string> {
61
- if (process.server) {
62
- throw new Error('reCAPTCHA работает только на клиенте');
50
+ console.log('reCAPTCHA v3 загружен глобально');
63
51
  }
64
52
 
65
- if (!recaptchaLoaded) {
53
+ // Инициализация: вызывать в onMounted формы (даёт время на сбор данных о поведении)
54
+ async function initRecaptcha(): Promise<void> {
55
+ if (process.server || recaptchaLoaded || !siteKey) return;
66
56
  await loadRecaptchaScript();
67
57
  }
68
58
 
69
- if (!siteKey) {
70
- throw new Error('reCAPTCHA siteKey не задан');
59
+ // Получение токена: вызывать в submit
60
+ async function getRecaptchaToken(action: string): Promise<string> {
61
+ if (process.server) {
62
+ throw new Error('reCAPTCHA работает только на клиенте');
63
+ }
64
+
65
+ if (!recaptchaLoaded) {
66
+ await loadRecaptchaScript();
67
+ }
68
+
69
+ if (!siteKey) {
70
+ throw new Error('reCAPTCHA siteKey не задан');
71
+ }
72
+
73
+ // @ts-ignore grecaptcha глобальный
74
+ return await grecaptcha.execute(siteKey, { action });
71
75
  }
72
76
 
73
- // @ts-ignore grecaptcha глобальный
74
- return await grecaptcha.execute(siteKey, { action });
77
+ return {
78
+ initRecaptcha,
79
+ getRecaptchaToken,
80
+ };
75
81
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.445",
4
+ "version": "0.0.446",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {