@inputdev/sdk 1.0.0 → 1.0.2
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/README.md +19 -26
- package/inputdev-sdk.prod.js +495 -0
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -17,12 +17,16 @@ Un SDK moderne et intelligent qui facilite l'intégration de formulaires avec vo
|
|
|
17
17
|
|
|
18
18
|
### **CDN (recommandé)**
|
|
19
19
|
```html
|
|
20
|
-
|
|
20
|
+
<!-- UNPKG -->
|
|
21
|
+
<script src="https://unpkg.com/@inputdev/sdk@latest/inputdev-sdk.prod.js"></script>
|
|
22
|
+
|
|
23
|
+
<!-- JSDelivr -->
|
|
24
|
+
<script src="https://cdn.jsdelivr.net/npm/@inputdev/sdk@latest/inputdev-sdk.prod.js"></script>
|
|
21
25
|
```
|
|
22
26
|
|
|
23
27
|
### **NPM**
|
|
24
28
|
```bash
|
|
25
|
-
npm install inputdev
|
|
29
|
+
npm install @inputdev/sdk
|
|
26
30
|
```
|
|
27
31
|
|
|
28
32
|
## 📖 **Utilisation rapide**
|
|
@@ -211,7 +215,7 @@ document.addEventListener('inputdev:error', (event) => {
|
|
|
211
215
|
|
|
212
216
|
### **React**
|
|
213
217
|
```jsx
|
|
214
|
-
import { InputDevSDK } from 'inputdev
|
|
218
|
+
import { InputDevSDK } from '@inputdev/sdk';
|
|
215
219
|
|
|
216
220
|
const dev = new InputDevSDK();
|
|
217
221
|
|
|
@@ -227,7 +231,7 @@ const handleSubmit = async (data) => {
|
|
|
227
231
|
|
|
228
232
|
### **Vanilla JS**
|
|
229
233
|
```html
|
|
230
|
-
<script src="inputdev-sdk.
|
|
234
|
+
<script src="https://unpkg.com/@inputdev/sdk@latest/inputdev-sdk.prod.js"></script>
|
|
231
235
|
<script>
|
|
232
236
|
const dev = new InputDevSDK();
|
|
233
237
|
|
|
@@ -259,10 +263,8 @@ MIT License - libre pour usage commercial et personnel
|
|
|
259
263
|
|
|
260
264
|
## 🔗 **Liens utiles**
|
|
261
265
|
|
|
262
|
-
- 📖 **Documentation complète** : [docs.inputdev.com](https://
|
|
263
|
-
|
|
264
|
-
- 🐛 **Issues** : [GitHub Issues](https://github.com/inputdev/sdk/issues)
|
|
265
|
-
- 💬 **Support** : [Discord](https://discord.gg/inputdev)
|
|
266
|
+
- 📖 **Documentation complète** : [docs.inputdev.com](https://inputdev.pages.dev/documentation)
|
|
267
|
+
|
|
266
268
|
|
|
267
269
|
---
|
|
268
270
|
|
|
@@ -329,29 +331,19 @@ document.addEventListener('inputdev:error', (event) => {
|
|
|
329
331
|
| SRV_001 | Erreur serveur | Erreur interne du serveur |
|
|
330
332
|
| SRV_004 | Trop de requêtes | Rate limit dépassé (10 req/min par clé) |
|
|
331
333
|
|
|
332
|
-
## Configuration
|
|
334
|
+
## Configuration
|
|
333
335
|
|
|
334
|
-
###
|
|
336
|
+
### Configuration actuelle
|
|
335
337
|
|
|
336
|
-
|
|
337
|
-
// Mettre à jour la configuration
|
|
338
|
-
dev.updateConfig({
|
|
339
|
-
apiEndpoint: 'https://votre-serveur-personnalisé.com/submit',
|
|
340
|
-
timeout: 15000,
|
|
341
|
-
retries: 3
|
|
342
|
-
});
|
|
338
|
+
Le SDK utilise une configuration de production optimisée :
|
|
343
339
|
|
|
344
|
-
|
|
340
|
+
```javascript
|
|
341
|
+
// Voir la configuration actuelle (lecture seule)
|
|
345
342
|
console.log(dev.getConfig());
|
|
346
343
|
```
|
|
347
344
|
|
|
348
|
-
### Options de configuration
|
|
349
345
|
|
|
350
|
-
|
|
351
|
-
|--------|--------|-------------|
|
|
352
|
-
| `apiEndpoint` | `https://votre-serveur.com/submit` | URL de l'API InputDev |
|
|
353
|
-
| `timeout` | `10000` | Timeout en millisecondes |
|
|
354
|
-
| `retries` | `2` | Nombre de tentatives en cas d'échec |
|
|
346
|
+
**Note :** La configuration est optimisée pour la production et n'est pas modifiable pour garantir la sécurité et la stabilité.
|
|
355
347
|
|
|
356
348
|
## Exemples pratiques
|
|
357
349
|
|
|
@@ -381,7 +373,7 @@ console.log(dev.getConfig());
|
|
|
381
373
|
<button type="submit">Envoyer</button>
|
|
382
374
|
</form>
|
|
383
375
|
|
|
384
|
-
<script src="https://
|
|
376
|
+
<script src="https://unpkg.com/@inputdev/sdk@latest/inputdev-sdk.prod.js"></script>
|
|
385
377
|
```
|
|
386
378
|
|
|
387
379
|
### Formulaire avec validation personnalisée
|
|
@@ -399,7 +391,7 @@ document.addEventListener('inputdev:error', (event) => {
|
|
|
399
391
|
|
|
400
392
|
### Intégration React
|
|
401
393
|
```jsx
|
|
402
|
-
import {
|
|
394
|
+
import { InputDevSDK } from "@inputdev/sdk";
|
|
403
395
|
|
|
404
396
|
function ContactForm() {
|
|
405
397
|
const [formData, setFormData] = useState({
|
|
@@ -407,6 +399,7 @@ function ContactForm() {
|
|
|
407
399
|
message: ''
|
|
408
400
|
});
|
|
409
401
|
const [loading, setLoading] = useState(false);
|
|
402
|
+
const dev = new InputDevSDK();
|
|
410
403
|
|
|
411
404
|
const handleSubmit = async (e) => {
|
|
412
405
|
e.preventDefault();
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InputDev SDK - Version Production Simplifiée
|
|
3
|
+
* Backend de formulaires sans code
|
|
4
|
+
*
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
* @author InputDev
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
(function(global) {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
// Configuration de production (non modifiable)
|
|
13
|
+
const CONFIG = {
|
|
14
|
+
apiEndpoint: 'https://server-g4xx.onrender.com/inputdev/submit',
|
|
15
|
+
timeout: 10000
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Codes d'erreur
|
|
19
|
+
const ERROR_CODES = {
|
|
20
|
+
API_001: 'Clé API invalide',
|
|
21
|
+
API_003: 'Clé API désactivée',
|
|
22
|
+
DOM_001: 'Domaine non autorisé',
|
|
23
|
+
QUO_001: 'Quota de soumissions épuisé',
|
|
24
|
+
STO_001: 'Quota de stockage épuisé',
|
|
25
|
+
SRV_001: 'Erreur serveur',
|
|
26
|
+
SRV_004: 'Trop de requêtes'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* SDK InputDev - Version simplifiée
|
|
31
|
+
*/
|
|
32
|
+
class InputDevSDK {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.messagesEnabled = true;
|
|
35
|
+
this.logsEnabled = true;
|
|
36
|
+
this.init();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
init() {
|
|
40
|
+
// Log de démarrage pour vérifier que le SDK est bien chargé
|
|
41
|
+
if (this.logsEnabled) {
|
|
42
|
+
console.log('%c🚀 INPUTDEV SDK CHARGÉ', 'color: #8b5cf6; font-weight: bold; font-size: 12px;');
|
|
43
|
+
console.log('⏱️ Timeout:', CONFIG.timeout + 'ms');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Masquer les logs XHR du navigateur pour réduire le bruit
|
|
47
|
+
this.hideXHRLogs();
|
|
48
|
+
|
|
49
|
+
this.setupAutoFormHandling();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
hideXHRLogs() {
|
|
53
|
+
// Masquer les logs XHR/Fetch du navigateur dans la console
|
|
54
|
+
const originalFetch = window.fetch;
|
|
55
|
+
window.fetch = function(...args) {
|
|
56
|
+
const result = originalFetch.apply(this, args);
|
|
57
|
+
|
|
58
|
+
// Masquer les logs de fetch dans la console et les erreurs non critiques
|
|
59
|
+
result.catch(() => {});
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Masquer les erreurs de favicon et autres erreurs non critiques
|
|
65
|
+
const originalError = console.error;
|
|
66
|
+
console.error = function(...args) {
|
|
67
|
+
// Filtrer les erreurs de favicon et autres erreurs non critiques
|
|
68
|
+
const message = args[0];
|
|
69
|
+
if (typeof message === 'string' && (
|
|
70
|
+
message.includes('favicon.ico') ||
|
|
71
|
+
message.includes('404') && message.includes('File not found')
|
|
72
|
+
)) {
|
|
73
|
+
return; // Ignorer ces erreurs
|
|
74
|
+
}
|
|
75
|
+
return originalError.apply(console, args);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Désactive/active les messages
|
|
81
|
+
*/
|
|
82
|
+
disableMessages() {
|
|
83
|
+
this.messagesEnabled = false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
enableMessages() {
|
|
87
|
+
this.messagesEnabled = true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Désactive/active les logs
|
|
92
|
+
*/
|
|
93
|
+
disableLogs() {
|
|
94
|
+
this.logsEnabled = false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
enableLogs() {
|
|
98
|
+
this.logsEnabled = true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setupAutoFormHandling() {
|
|
102
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
103
|
+
const forms = document.querySelectorAll('form[data-inputdev], form[data-inputdev-silence]');
|
|
104
|
+
|
|
105
|
+
forms.forEach(form => {
|
|
106
|
+
// Ajouter la validation automatique des emails
|
|
107
|
+
this.setupEmailValidation(form);
|
|
108
|
+
|
|
109
|
+
form.addEventListener('submit', (e) => {
|
|
110
|
+
e.preventDefault();
|
|
111
|
+
|
|
112
|
+
// Vérifier si c'est un formulaire silencieux
|
|
113
|
+
const isSilent = form.hasAttribute('data-inputdev-silence');
|
|
114
|
+
const apiKey = isSilent ? form.getAttribute('data-inputdev-silence') : form.getAttribute('data-inputdev');
|
|
115
|
+
|
|
116
|
+
// Convertir FormData en objet
|
|
117
|
+
const data = {};
|
|
118
|
+
for (let [key, value] of new FormData(form).entries()) {
|
|
119
|
+
data[key] = value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const submitButton = form.querySelector('button[type="submit"], input[type="submit"]');
|
|
123
|
+
if (submitButton) {
|
|
124
|
+
submitButton.disabled = true;
|
|
125
|
+
const originalText = submitButton.textContent || submitButton.value;
|
|
126
|
+
submitButton.textContent = 'Envoi en cours...';
|
|
127
|
+
|
|
128
|
+
setTimeout(() => {
|
|
129
|
+
submitButton.disabled = false;
|
|
130
|
+
submitButton.textContent = originalText;
|
|
131
|
+
}, 3000);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.submit(apiKey, isSilent ? 'silence' : undefined, data)
|
|
135
|
+
.then(response => {
|
|
136
|
+
this.handleSuccess(form, response);
|
|
137
|
+
})
|
|
138
|
+
.catch(error => {
|
|
139
|
+
this.handleError(form, error);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
setupEmailValidation(form) {
|
|
147
|
+
const emailInputs = form.querySelectorAll('input[type="email"]');
|
|
148
|
+
|
|
149
|
+
emailInputs.forEach(input => {
|
|
150
|
+
// Ajouter un écouteur pour la validation en temps réel
|
|
151
|
+
input.addEventListener('blur', () => {
|
|
152
|
+
this.validateEmail(input);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
input.addEventListener('input', () => {
|
|
156
|
+
// Retirer le style d'erreur quand l'utilisateur tape
|
|
157
|
+
if (input.classList.contains('inputdev-email-error')) {
|
|
158
|
+
input.classList.remove('inputdev-email-error');
|
|
159
|
+
this.removeEmailError(input);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
validateEmail(emailInput) {
|
|
166
|
+
const email = emailInput.value.trim();
|
|
167
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
168
|
+
|
|
169
|
+
if (!email) {
|
|
170
|
+
// Champ vide - pas d'erreur
|
|
171
|
+
this.removeEmailError(emailInput);
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!emailRegex.test(email)) {
|
|
176
|
+
// Email invalide
|
|
177
|
+
this.showEmailError(emailInput);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Email valide
|
|
182
|
+
this.removeEmailError(emailInput);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
showEmailError(emailInput) {
|
|
187
|
+
emailInput.classList.add('inputdev-email-error');
|
|
188
|
+
|
|
189
|
+
// Ajouter un style CSS si pas déjà présent
|
|
190
|
+
if (!document.getElementById('inputdev-email-styles')) {
|
|
191
|
+
const style = document.createElement('style');
|
|
192
|
+
style.id = 'inputdev-email-styles';
|
|
193
|
+
style.textContent = `
|
|
194
|
+
.inputdev-email-error {
|
|
195
|
+
border: 2px solid #ef4444 !important;
|
|
196
|
+
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1) !important;
|
|
197
|
+
outline: none !important;
|
|
198
|
+
}
|
|
199
|
+
.inputdev-email-error-message {
|
|
200
|
+
color: #ef4444;
|
|
201
|
+
font-size: 12px;
|
|
202
|
+
margin-top: 4px;
|
|
203
|
+
display: block;
|
|
204
|
+
}
|
|
205
|
+
`;
|
|
206
|
+
document.head.appendChild(style);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Retirer l'ancien message d'erreur s'il existe
|
|
210
|
+
this.removeEmailError(emailInput);
|
|
211
|
+
|
|
212
|
+
// Ajouter le message d'erreur
|
|
213
|
+
const errorDiv = document.createElement('div');
|
|
214
|
+
errorDiv.className = 'inputdev-email-error-message';
|
|
215
|
+
errorDiv.innerHTML = '<span style="text-decoration: underline; font-weight: bold;">InputDev SDK</span> : <span style="font-weight: bold;">Veuillez entrer une adresse email valide</span>';
|
|
216
|
+
errorDiv.setAttribute('data-inputdev-error-for', emailInput.id || emailInput.name);
|
|
217
|
+
|
|
218
|
+
// Insérer après l'input
|
|
219
|
+
emailInput.parentNode.insertBefore(errorDiv, emailInput.nextSibling);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
removeEmailError(emailInput) {
|
|
223
|
+
emailInput.classList.remove('inputdev-email-error');
|
|
224
|
+
|
|
225
|
+
// Retirer le message d'erreur
|
|
226
|
+
const errorMessage = emailInput.parentNode.querySelector(`[data-inputdev-error-for="${emailInput.id || emailInput.name}"]`);
|
|
227
|
+
if (errorMessage) {
|
|
228
|
+
errorMessage.remove();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
validateEmailsInData(data) {
|
|
233
|
+
const errors = [];
|
|
234
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
235
|
+
|
|
236
|
+
// Parcourir toutes les propriétés de l'objet data
|
|
237
|
+
for (const [key, value] of Object.entries(data)) {
|
|
238
|
+
// Vérifier si le nom de la clé contient "email" (insensible à la casse)
|
|
239
|
+
if (key.toLowerCase().includes('email') && typeof value === 'string') {
|
|
240
|
+
const email = value.trim();
|
|
241
|
+
if (email && !emailRegex.test(email)) {
|
|
242
|
+
errors.push(`L'email "${key}" est invalide: ${email}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
valid: errors.length === 0,
|
|
249
|
+
errors: errors
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
logEmailValidationError(errors) {
|
|
254
|
+
// Afficher les erreurs de validation email dans la console
|
|
255
|
+
console.warn('%c📧 VALIDATION EMAIL', 'color: #f97316; font-weight: bold; font-size: 14px;');
|
|
256
|
+
console.warn('%cErreurs trouvées:', 'color: #f97316; font-weight: bold; font-size: 12px;');
|
|
257
|
+
errors.forEach((error, index) => {
|
|
258
|
+
console.warn('%c• ' + error, 'color: #f97316; font-size: 11px;');
|
|
259
|
+
});
|
|
260
|
+
console.warn('%c💡 Corrigez les emails avant de soumettre à nouveau', 'color: #6b7280; font-size: 11px;');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async submit(apiKey, silence, data) {
|
|
264
|
+
if (!apiKey || typeof apiKey !== 'string') {
|
|
265
|
+
throw new Error('Clé API invalide');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Gérer le paramètre silence
|
|
269
|
+
if (typeof silence === 'object') {
|
|
270
|
+
// Cas: submit(apiKey, data) - ancienne signature
|
|
271
|
+
data = silence;
|
|
272
|
+
silence = undefined;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (!data || typeof data !== 'object') {
|
|
276
|
+
throw new Error('Données invalides');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Validation des emails dans les données JSON
|
|
280
|
+
const emailValidation = this.validateEmailsInData(data);
|
|
281
|
+
if (!emailValidation.valid) {
|
|
282
|
+
// Afficher l'erreur dans la console
|
|
283
|
+
this.logEmailValidationError(emailValidation.errors);
|
|
284
|
+
throw new Error('EMAIL_INVALID: ' + emailValidation.errors.join(', '));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Désactiver temporairement les logs si mode silencieux
|
|
288
|
+
const originalLogsEnabled = this.logsEnabled;
|
|
289
|
+
if (silence === 'silence') {
|
|
290
|
+
this.logsEnabled = false;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const url = `${CONFIG.apiEndpoint}/${apiKey}`;
|
|
294
|
+
|
|
295
|
+
// Log automatique de la soumission
|
|
296
|
+
this.logInfo('📤 Envoi du formulaire...', {
|
|
297
|
+
apiKey: '***masqué***',
|
|
298
|
+
data
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
const controller = new AbortController();
|
|
303
|
+
const timeoutId = setTimeout(() => controller.abort(), CONFIG.timeout);
|
|
304
|
+
|
|
305
|
+
const response = await fetch(url, {
|
|
306
|
+
method: 'POST',
|
|
307
|
+
headers: {
|
|
308
|
+
'Content-Type': 'application/json',
|
|
309
|
+
},
|
|
310
|
+
body: JSON.stringify({ data }),
|
|
311
|
+
signal: controller.signal
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
clearTimeout(timeoutId);
|
|
315
|
+
const result = await response.json();
|
|
316
|
+
|
|
317
|
+
// Log automatique de la réponse brute du backend
|
|
318
|
+
this.logInfo('📨 Réponse du backend:', {
|
|
319
|
+
status: response.status,
|
|
320
|
+
statusText: response.statusText,
|
|
321
|
+
result: result
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
if (!response.ok) {
|
|
325
|
+
const errorCode = result.error?.code || 'SRV_001';
|
|
326
|
+
const errorMessage = result.error?.message || ERROR_CODES[errorCode] || 'Erreur inconnue';
|
|
327
|
+
|
|
328
|
+
// Log détaillé de l'erreur
|
|
329
|
+
this.logError(`❌ Erreur ${errorCode}`, {
|
|
330
|
+
code: errorCode,
|
|
331
|
+
message: errorMessage,
|
|
332
|
+
status: response.status,
|
|
333
|
+
fullResponse: result
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Message spécial pour l'erreur de domaine
|
|
337
|
+
if (errorCode === 'DOM_001') {
|
|
338
|
+
this.logDomainError();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Message spécial pour l'erreur de clé désactivée
|
|
342
|
+
if (errorCode === 'API_003') {
|
|
343
|
+
this.logApiKeyDisabledError();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
throw new Error(`${errorCode}: ${errorMessage}`);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Log de succès avec détails
|
|
350
|
+
this.logSuccess('✅ Formulaire envoyé avec succès !', {
|
|
351
|
+
submissionId: result.submissionId,
|
|
352
|
+
message: result.message,
|
|
353
|
+
response: result
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
return result;
|
|
357
|
+
} catch (error) {
|
|
358
|
+
// Log automatique de l'erreur
|
|
359
|
+
this.logError('💥 Erreur lors de la soumission:', {
|
|
360
|
+
error: error.message,
|
|
361
|
+
stack: error.stack,
|
|
362
|
+
apiKey: '***masqué***'
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// Message spécial pour l'erreur de domaine
|
|
366
|
+
if (this.extractErrorCode(error.message) === 'DOM_001') {
|
|
367
|
+
this.logDomainError();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Message spécial pour l'erreur de clé désactivée
|
|
371
|
+
if (this.extractErrorCode(error.message) === 'API_003') {
|
|
372
|
+
this.logApiKeyDisabledError();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
throw error;
|
|
376
|
+
} finally {
|
|
377
|
+
// Restaurer l'état des logs
|
|
378
|
+
this.logsEnabled = originalLogsEnabled;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
handleSuccess(form, response) {
|
|
383
|
+
form.reset();
|
|
384
|
+
|
|
385
|
+
// Log automatique du succès
|
|
386
|
+
this.logSuccess('🎉 Formulaire traité avec succès !', {
|
|
387
|
+
form: form.tagName + (form.id ? '#' + form.id : ''),
|
|
388
|
+
submissionId: response.submissionId,
|
|
389
|
+
message: response.message,
|
|
390
|
+
timestamp: new Date().toISOString(),
|
|
391
|
+
response: response
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
const event = new CustomEvent('inputdev:success', {
|
|
395
|
+
detail: { form, response }
|
|
396
|
+
});
|
|
397
|
+
document.dispatchEvent(event);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
handleError(form, error) {
|
|
401
|
+
// Message spécial pour l'erreur de domaine
|
|
402
|
+
if (this.extractErrorCode(error.message) === 'DOM_001') {
|
|
403
|
+
this.logDomainError();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Message spécial pour l'erreur de clé désactivée
|
|
407
|
+
if (this.extractErrorCode(error.message) === 'API_003') {
|
|
408
|
+
this.logApiKeyDisabledError();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const event = new CustomEvent('inputdev:error', {
|
|
412
|
+
detail: { form, error }
|
|
413
|
+
});
|
|
414
|
+
document.dispatchEvent(event);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
logSuccess(message, data) {
|
|
418
|
+
// Forcer l'affichage avec console.log direct - texte en vert sans contour
|
|
419
|
+
if (this.logsEnabled) {
|
|
420
|
+
console.log('%c🟢 INPUTDEV SUCCESS: ' + message, 'color: #10b981; font-weight: bold; font-size: 12px;');
|
|
421
|
+
console.log('📊 Détails:', data);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
logError(message, error) {
|
|
426
|
+
// Forcer l'affichage avec console.error direct - texte en rouge sans contour
|
|
427
|
+
if (this.logsEnabled) {
|
|
428
|
+
console.error('%c🔴 INPUTDEV ERROR: ' + message, 'color: #ef4444; font-weight: bold; font-size: 12px;');
|
|
429
|
+
console.error('📊 Détails:', error);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
logInfo(message, data) {
|
|
434
|
+
// Forcer l'affichage avec console.info direct - texte en bleu sans contour
|
|
435
|
+
if (this.logsEnabled) {
|
|
436
|
+
console.info('%c🔵 INPUTDEV INFO: ' + message, 'color: #3b82f6; font-weight: bold; font-size: 12px;');
|
|
437
|
+
console.info('📊 Détails:', data);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
logDomainError() {
|
|
442
|
+
// Message spécial pour l'erreur de domaine DOM_001
|
|
443
|
+
if (this.logsEnabled) {
|
|
444
|
+
console.warn('%c⚠️ DOMAINE NON AUTORISÉ (DOM_001)', 'color: #f97316; font-weight: bold; font-size: 14px;');
|
|
445
|
+
console.warn('%c🔧 SOLUTIONS DISPONIBLES:', 'color: #f97316; font-weight: bold; font-size: 12px;');
|
|
446
|
+
console.warn('%c📍 LOCALHOST: Activez le mode TEST pour votre clé API', 'color: #f97316; font-size: 11px;');
|
|
447
|
+
console.warn('%c🌐 PRODUCTION: Seul le domaine configuré est accepté', 'color: #f97316; font-size: 11px;');
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
logApiKeyDisabledError() {
|
|
452
|
+
// Message spécial pour l'erreur de clé désactivée API_003
|
|
453
|
+
if (this.logsEnabled) {
|
|
454
|
+
console.warn('%c🔑 CLÉ API DÉSACTIVÉE (API_003)', 'color: #f97316; font-weight: bold; font-size: 14px;');
|
|
455
|
+
console.warn('%c🔧 ACTION REQUISE:', 'color: #f97316; font-weight: bold; font-size: 12px;');
|
|
456
|
+
console.warn('%c👤 Veuillez vous rendre dans votre compte et activer la clé', 'color: #f97316; font-size: 11px;');
|
|
457
|
+
console.warn('%c⚠️ La clé a été désactivée manuellement ou automatiquement', 'color: #f97316; font-size: 11px;');
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
extractErrorCode(errorMessage) {
|
|
462
|
+
const match = errorMessage.match(/^([A-Z_0-9]+):/);
|
|
463
|
+
return match ? match[1] : 'UNKNOWN';
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
getErrorMessage(errorMessage) {
|
|
467
|
+
const errorCode = this.extractErrorCode(errorMessage);
|
|
468
|
+
const cleanMessage = errorMessage.replace(/^[A-Z_0-9]+:\s*/, '');
|
|
469
|
+
return ERROR_CODES[errorCode] || cleanMessage;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Méthodes pour compatibilité (ne font rien)
|
|
473
|
+
updateConfig() {
|
|
474
|
+
this.logError('⚠️ La configuration n\'est pas modifiable en production');
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
getConfig() {
|
|
478
|
+
return { ...CONFIG };
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Créer l'instance globale
|
|
483
|
+
const inputDevSDK = new InputDevSDK();
|
|
484
|
+
|
|
485
|
+
// Exporter
|
|
486
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
487
|
+
module.exports = { dev: inputDevSDK, InputDevSDK };
|
|
488
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
489
|
+
define(function() { return { dev: inputDevSDK, InputDevSDK }; });
|
|
490
|
+
} else {
|
|
491
|
+
global.dev = inputDevSDK;
|
|
492
|
+
global.InputDevSDK = InputDevSDK;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
})(typeof window !== 'undefined' ? window : this);
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inputdev/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Backend de formulaires sans code - SDK JavaScript",
|
|
5
|
-
"main": "inputdev-sdk.js",
|
|
5
|
+
"main": "inputdev-sdk.prod.js",
|
|
6
6
|
"types": "inputdev-sdk.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "webpack --mode=production",
|
|
@@ -33,14 +33,13 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://inputdev.dev",
|
|
35
35
|
"files": [
|
|
36
|
-
"inputdev-sdk.js",
|
|
37
|
-
"inputdev-sdk.min.js",
|
|
36
|
+
"inputdev-sdk.prod.js",
|
|
38
37
|
"inputdev-sdk.d.ts",
|
|
39
38
|
"README.md",
|
|
40
39
|
"LICENSE"
|
|
41
40
|
],
|
|
42
|
-
"browser": "inputdev-sdk.js",
|
|
43
|
-
"module": "inputdev-sdk.js",
|
|
44
|
-
"unpkg": "inputdev-sdk.
|
|
45
|
-
"jsdelivr": "inputdev-sdk.
|
|
41
|
+
"browser": "inputdev-sdk.prod.js",
|
|
42
|
+
"module": "inputdev-sdk.prod.js",
|
|
43
|
+
"unpkg": "inputdev-sdk.prod.js",
|
|
44
|
+
"jsdelivr": "inputdev-sdk.prod.js"
|
|
46
45
|
}
|