@angular-helpers/browser-web-apis 21.0.0
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 +291 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# @angular-helpers/browser-web-apis
|
|
2
|
+
|
|
3
|
+
Sistema de servicios Angular para acceso formalizado a Browser Web APIs con seguridad integrada.
|
|
4
|
+
|
|
5
|
+
## 🚀 Características
|
|
6
|
+
|
|
7
|
+
- **🔐 Seguridad Integrada**: Prevención de ReDoS con Web Workers
|
|
8
|
+
- **📱 Browser APIs**: Acceso unificado a APIs del navegador
|
|
9
|
+
- **⚡ Tree Shakable**: Solo incluye lo que usas
|
|
10
|
+
- **🛡️ Type Safe**: TypeScript completo
|
|
11
|
+
- **🔧 Modular**: Habilita solo lo que necesitas
|
|
12
|
+
- **📊 Reactive**: Signals y Observables
|
|
13
|
+
- **🔄 Lifecycle**: Gestión automática con destroyRef
|
|
14
|
+
|
|
15
|
+
## 📦 Servicios Disponibles
|
|
16
|
+
|
|
17
|
+
### � Media & Device APIs
|
|
18
|
+
- **CameraService** - Acceso a cámara con gestión de permisos
|
|
19
|
+
- **MediaDevicesService** - Enumeración y gestión de dispositivos multimedia
|
|
20
|
+
- **GeolocationService** - API de geolocalización
|
|
21
|
+
- **NotificationService** - Sistema de notificaciones
|
|
22
|
+
|
|
23
|
+
### 🌐 Web APIs
|
|
24
|
+
- **WebWorkerService** - Gestión de Web Workers
|
|
25
|
+
- **WebSocketService** - Conexiones WebSocket
|
|
26
|
+
- **WebStorageService** - LocalStorage y SessionStorage
|
|
27
|
+
- **WebShareService** - API de compartir nativa
|
|
28
|
+
- **ClipboardService** - Portapapeles del sistema
|
|
29
|
+
|
|
30
|
+
### 🔐 Seguridad
|
|
31
|
+
- **RegexSecurityService** - Prevención de ReDoS con Web Workers
|
|
32
|
+
- **PermissionsService** - Gestión centralizada de permisos
|
|
33
|
+
|
|
34
|
+
### 🔧 Utilidades
|
|
35
|
+
- **CameraPermissionHelperService** - Helper para permisos de cámara
|
|
36
|
+
- **BrowserApiBaseService** - Clase base para servicios de APIs
|
|
37
|
+
- **MediaDeviceBaseService** - Clase base para dispositivos multimedia
|
|
38
|
+
|
|
39
|
+
## �️ Instalación
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @angular-helpers/browser-web-apis
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## � Configuración Rápida
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { provideBrowserWebApis } from '@angular-helpers/browser-web-apis';
|
|
49
|
+
|
|
50
|
+
bootstrapApplication(AppComponent, {
|
|
51
|
+
providers: [
|
|
52
|
+
provideBrowserWebApis({
|
|
53
|
+
enableCamera: true,
|
|
54
|
+
enableGeolocation: true,
|
|
55
|
+
enableRegexSecurity: true
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 📖 Uso por Servicio
|
|
62
|
+
|
|
63
|
+
### 📷 CameraService
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { CameraService } from '@angular-helpers/browser-web-apis';
|
|
67
|
+
|
|
68
|
+
export class PhotoComponent {
|
|
69
|
+
constructor(private cameraService: CameraService) {}
|
|
70
|
+
|
|
71
|
+
async takePhoto() {
|
|
72
|
+
try {
|
|
73
|
+
const stream = await this.cameraService.startCamera({
|
|
74
|
+
video: true,
|
|
75
|
+
audio: false
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Usar stream para video/foto
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('Error accessing camera:', error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async stopCamera() {
|
|
85
|
+
await this.cameraService.stopCamera();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 🔐 RegexSecurityService (Prevención de ReDoS)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { RegexSecurityService } from '@angular-helpers/browser-web-apis';
|
|
94
|
+
|
|
95
|
+
export class SecurityComponent {
|
|
96
|
+
constructor(private regexSecurity: RegexSecurityService) {}
|
|
97
|
+
|
|
98
|
+
async testPattern() {
|
|
99
|
+
const pattern = '(.+)+'; // Patrón potencialmente peligroso
|
|
100
|
+
const text = 'some text to test';
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const result = await this.regexSecurity.testRegex(pattern, text, {
|
|
104
|
+
timeout: 5000,
|
|
105
|
+
safeMode: true
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
console.log('Match:', result.match);
|
|
109
|
+
console.log('Execution time:', result.executionTime);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error('Regex test failed:', error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async analyzeSecurity() {
|
|
116
|
+
const analysis = await this.regexSecurity.analyzePatternSecurity('(.+)+');
|
|
117
|
+
|
|
118
|
+
console.log('Risk level:', analysis.risk);
|
|
119
|
+
console.log('Warnings:', analysis.warnings);
|
|
120
|
+
console.log('Recommendations:', analysis.recommendations);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 🔨 Builder Pattern para Regex Seguro
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { RegexSecurityService, RegexSecurityBuilder } from '@angular-helpers/browser-web-apis';
|
|
129
|
+
|
|
130
|
+
export class RegexBuilderComponent {
|
|
131
|
+
constructor(private regexSecurity: RegexSecurityService) {}
|
|
132
|
+
|
|
133
|
+
async buildSafeRegex() {
|
|
134
|
+
const builder = RegexSecurityService.builder()
|
|
135
|
+
.startOfLine()
|
|
136
|
+
.characterSet('a-zA-Z0-9')
|
|
137
|
+
.quantifier('+')
|
|
138
|
+
.characterSet('@')
|
|
139
|
+
.characterSet('a-zA-Z0-9.-')
|
|
140
|
+
.quantifier('+')
|
|
141
|
+
.characterSet('.')
|
|
142
|
+
.characterSet('a-z')
|
|
143
|
+
.quantifier('{2,4}')
|
|
144
|
+
.endOfLine()
|
|
145
|
+
.timeout(3000)
|
|
146
|
+
.safeMode();
|
|
147
|
+
|
|
148
|
+
const emailPattern = builder.build().pattern;
|
|
149
|
+
const result = await builder.execute('test@example.com', this.regexSecurity);
|
|
150
|
+
|
|
151
|
+
console.log('Valid email:', result.match);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 🌍 GeolocationService
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { GeolocationService } from '@angular-helpers/browser-web-apis';
|
|
160
|
+
|
|
161
|
+
export class LocationComponent {
|
|
162
|
+
constructor(private geolocation: GeolocationService) {}
|
|
163
|
+
|
|
164
|
+
async getCurrentLocation() {
|
|
165
|
+
try {
|
|
166
|
+
const position = await this.geolocation.getCurrentPosition({
|
|
167
|
+
enableHighAccuracy: true,
|
|
168
|
+
timeout: 10000,
|
|
169
|
+
maximumAge: 60000
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
console.log('Position:', position.coords);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error('Error getting location:', error);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
watchPosition() {
|
|
179
|
+
const watchId = this.geolocation.watchPosition(position => {
|
|
180
|
+
console.log('New position:', position.coords);
|
|
181
|
+
}, error => {
|
|
182
|
+
console.error('Watch error:', error);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 🔔 NotificationService
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { NotificationService } from '@angular-helpers/browser-web-apis';
|
|
192
|
+
|
|
193
|
+
export class NotificationComponent {
|
|
194
|
+
constructor(private notificationService: NotificationService) {}
|
|
195
|
+
|
|
196
|
+
async showNotification() {
|
|
197
|
+
try {
|
|
198
|
+
await this.notificationService.requestPermission();
|
|
199
|
+
|
|
200
|
+
this.notificationService.showNotification({
|
|
201
|
+
title: 'New Message',
|
|
202
|
+
body: 'You have a new message',
|
|
203
|
+
icon: '/assets/icon.png',
|
|
204
|
+
tag: 'message'
|
|
205
|
+
});
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.error('Notification error:', error);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 🌐 WebSocketService
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { WebSocketService } from '@angular-helpers/browser-web-apis';
|
|
217
|
+
|
|
218
|
+
export class ChatComponent {
|
|
219
|
+
constructor(private webSocketService: WebSocketService) {}
|
|
220
|
+
|
|
221
|
+
connect() {
|
|
222
|
+
this.webSocketService.connect('ws://localhost:8080')
|
|
223
|
+
.subscribe({
|
|
224
|
+
next: (message) => console.log('Received:', message),
|
|
225
|
+
error: (error) => console.error('WebSocket error:', error),
|
|
226
|
+
complete: () => console.log('WebSocket disconnected')
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
sendMessage(message: string) {
|
|
231
|
+
this.webSocketService.send(message);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 💾 WebStorageService
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { WebStorageService } from '@angular-helpers/browser-web-apis';
|
|
240
|
+
|
|
241
|
+
export class SettingsComponent {
|
|
242
|
+
constructor(private storageService: WebStorageService) {}
|
|
243
|
+
|
|
244
|
+
saveSettings() {
|
|
245
|
+
this.storageService.setItem('userSettings', {
|
|
246
|
+
theme: 'dark',
|
|
247
|
+
language: 'es',
|
|
248
|
+
notifications: true
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
- `showProgressNotification(title, current, total)` - Notificación con progreso
|
|
252
|
+
|
|
253
|
+
### ClipboardService
|
|
254
|
+
- `writeText(text)` - Escribir texto
|
|
255
|
+
- `readText()` - Leer texto
|
|
256
|
+
- `copyImage(blob)` - Copiar imagen
|
|
257
|
+
- `pasteImage()` - Pegar imagen
|
|
258
|
+
|
|
259
|
+
### MediaDevicesService
|
|
260
|
+
- `getUserMedia(constraints)` - Obtener media
|
|
261
|
+
- `getDisplayMedia(constraints?)` - Screen sharing
|
|
262
|
+
- `refreshDevices()` - Actualizar dispositivos
|
|
263
|
+
- `getDevicesByKind(kind)` - Dispositivos por tipo
|
|
264
|
+
|
|
265
|
+
### PermissionsService
|
|
266
|
+
- `query(descriptor)` - Consultar permiso
|
|
267
|
+
- `request(descriptor)` - Solicitar permiso
|
|
268
|
+
- `isGranted(permission)` - Verificar concedido
|
|
269
|
+
- `isDenied(permission)` - Verificar denegado
|
|
270
|
+
- `observePermission(permission)` - Observar cambios
|
|
271
|
+
|
|
272
|
+
## 🌐 Soporte de Navegadores
|
|
273
|
+
|
|
274
|
+
Los servicios verifican automáticamente el soporte del navegador:
|
|
275
|
+
|
|
276
|
+
- **Chrome**: Soporte completo
|
|
277
|
+
- **Firefox**: Soporte completo
|
|
278
|
+
- **Safari**: Soporte parcial
|
|
279
|
+
- **Edge**: Soporte completo
|
|
280
|
+
- **Móvil**: Soporte variable
|
|
281
|
+
|
|
282
|
+
## 📝 Notas
|
|
283
|
+
|
|
284
|
+
- Requiere contexto seguro (HTTPS)
|
|
285
|
+
- Algunas APIs necesitan interacción del usuario
|
|
286
|
+
- Los permisos varían según el navegador
|
|
287
|
+
- Considera siempre el manejo de errores
|
|
288
|
+
|
|
289
|
+
## 📄 Licencia
|
|
290
|
+
|
|
291
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@angular-helpers/browser-web-apis",
|
|
3
|
+
"version": "21.0.0",
|
|
4
|
+
"description": "Sistema de servicios Angular para acceso formalizado a Browser Web APIs (cámara, permisos, geolocalización, etc.)",
|
|
5
|
+
"main": "dist/browser-web-apis/browser-web-apis.d.ts",
|
|
6
|
+
"types": "dist/browser-web-apis/browser-web-apis.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "ng-packagr -p ng-package.json",
|
|
12
|
+
"build:watch": "ng-packagr -p ng-package.json --watch",
|
|
13
|
+
"test": "vitest",
|
|
14
|
+
"test:watch": "vitest --watch",
|
|
15
|
+
"test:coverage": "vitest --coverage",
|
|
16
|
+
"clean": "rm -rf dist",
|
|
17
|
+
"lint": "eslint src/**/*.ts",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"angular",
|
|
22
|
+
"typescript",
|
|
23
|
+
"browser",
|
|
24
|
+
"web-apis",
|
|
25
|
+
"camera",
|
|
26
|
+
"permissions",
|
|
27
|
+
"geolocation",
|
|
28
|
+
"media",
|
|
29
|
+
"sensors"
|
|
30
|
+
],
|
|
31
|
+
"author": "",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@angular/core": "^21.0.0",
|
|
38
|
+
"@angular/common": "^21.0.0",
|
|
39
|
+
"@angular/platform-browser": "^21.0.0",
|
|
40
|
+
"@angular/ssr": "^21.0.0",
|
|
41
|
+
"rxjs": "^7.0.0"
|
|
42
|
+
}
|
|
43
|
+
}
|