@angular-helpers/browser-web-apis 21.9.0 → 21.11.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.
@@ -1,22 +1,66 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, inject, DestroyRef, PLATFORM_ID, signal, computed, isSignal, effect, ElementRef, makeEnvironmentProviders } from '@angular/core';
2
+ import { InjectionToken, isDevMode, inject, Injectable, DestroyRef, PLATFORM_ID, signal, computed, isSignal, effect, ElementRef, makeEnvironmentProviders } from '@angular/core';
3
3
  import { isPlatformBrowser, isPlatformServer } from '@angular/common';
4
4
  import { Observable, fromEvent, Subject, of, map as map$1 } from 'rxjs';
5
5
  import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
6
  import { filter, map, distinctUntilChanged } from 'rxjs/operators';
7
7
  import { Router } from '@angular/router';
8
8
 
9
+ const LEVEL_RANK = {
10
+ debug: 10,
11
+ info: 20,
12
+ warn: 30,
13
+ error: 40,
14
+ silent: 100,
15
+ };
16
+ /**
17
+ * Global log level for `BROWSER_API_LOGGER`. Defaults to `'debug'` in dev mode and
18
+ * `'warn'` in production. Override via `provideBrowserApiLogLevel('silent')` etc.
19
+ */
20
+ const BROWSER_API_LOG_LEVEL = new InjectionToken('BROWSER_API_LOG_LEVEL', {
21
+ providedIn: 'root',
22
+ factory: () => (isDevMode() ? 'debug' : 'warn'),
23
+ });
9
24
  const BROWSER_API_LOGGER = new InjectionToken('BROWSER_API_LOGGER', {
10
25
  providedIn: 'root',
11
- factory: () => ({
12
- // oxlint-disable-next-line no-console
13
- info: (message) => console.info(message),
14
- // oxlint-disable-next-line no-console
15
- warn: (message) => console.warn(message),
16
- // oxlint-disable-next-line no-console
17
- error: (message, error) => console.error(message, error),
18
- }),
26
+ factory: () => {
27
+ const level = inject(BROWSER_API_LOG_LEVEL);
28
+ return createLevelGatedLogger(level);
29
+ },
19
30
  });
31
+ function createLevelGatedLogger(level) {
32
+ const min = LEVEL_RANK[level];
33
+ return {
34
+ debug: (message) => {
35
+ if (LEVEL_RANK.debug < min)
36
+ return;
37
+ // oxlint-disable-next-line no-console
38
+ console.debug(message);
39
+ },
40
+ info: (message) => {
41
+ if (LEVEL_RANK.info < min)
42
+ return;
43
+ // oxlint-disable-next-line no-console
44
+ console.info(message);
45
+ },
46
+ warn: (message) => {
47
+ if (LEVEL_RANK.warn < min)
48
+ return;
49
+ // oxlint-disable-next-line no-console
50
+ console.warn(message);
51
+ },
52
+ error: (message, error) => {
53
+ if (LEVEL_RANK.error < min)
54
+ return;
55
+ // oxlint-disable-next-line no-console
56
+ console.error(message, error);
57
+ },
58
+ };
59
+ }
60
+ /** Log level helper provider. Overrides the default `BROWSER_API_LOG_LEVEL`. */
61
+ function provideBrowserApiLogLevel(level) {
62
+ return { provide: BROWSER_API_LOG_LEVEL, useValue: level };
63
+ }
20
64
 
21
65
  const BROWSER_CAPABILITIES = [
22
66
  { id: 'permissions', label: 'Permissions API', requiresSecureContext: false },
@@ -56,6 +100,9 @@ const BROWSER_CAPABILITIES = [
56
100
  { id: 'webNfc', label: 'Web NFC API', requiresSecureContext: true },
57
101
  { id: 'paymentRequest', label: 'Payment Request API', requiresSecureContext: true },
58
102
  { id: 'credentialManagement', label: 'Credential Management API', requiresSecureContext: true },
103
+ { id: 'webLocks', label: 'Web Locks API', requiresSecureContext: true },
104
+ { id: 'storageManager', label: 'Storage Manager API', requiresSecureContext: true },
105
+ { id: 'compressionStreams', label: 'Compression Streams API', requiresSecureContext: false },
59
106
  ];
60
107
  class BrowserCapabilityService {
61
108
  getCapabilities() {
@@ -140,6 +187,14 @@ class BrowserCapabilityService {
140
187
  return typeof window !== 'undefined' && 'PaymentRequest' in window;
141
188
  case 'credentialManagement':
142
189
  return typeof navigator !== 'undefined' && 'credentials' in navigator;
190
+ case 'webLocks':
191
+ return typeof navigator !== 'undefined' && 'locks' in navigator;
192
+ case 'storageManager':
193
+ return (typeof navigator !== 'undefined' &&
194
+ 'storage' in navigator &&
195
+ typeof navigator.storage.estimate === 'function');
196
+ case 'compressionStreams':
197
+ return (typeof CompressionStream !== 'undefined' && typeof DecompressionStream !== 'undefined');
143
198
  default:
144
199
  return false;
145
200
  }
@@ -256,6 +311,9 @@ class BrowserApiBaseService {
256
311
  logInfo(message) {
257
312
  this.logger.info(`[${this.getApiName()}] ${message}`);
258
313
  }
314
+ logDebug(message) {
315
+ this.logger.debug?.(`[${this.getApiName()}] ${message}`);
316
+ }
259
317
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
260
318
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService });
261
319
  }
@@ -3087,6 +3145,222 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
3087
3145
  type: Injectable
3088
3146
  }] });
3089
3147
 
3148
+ /**
3149
+ * Service wrapping `navigator.locks` (Web Locks API). Coordinates exclusive or
3150
+ * shared access to a named resource across tabs and workers.
3151
+ *
3152
+ * ```ts
3153
+ * const locks = inject(WebLocksService);
3154
+ * await locks.acquire('user-cache', async () => {
3155
+ * // critical section — no other tab is in this block at the same time
3156
+ * });
3157
+ * ```
3158
+ */
3159
+ class WebLocksService extends BrowserApiBaseService {
3160
+ getApiName() {
3161
+ return 'web-locks';
3162
+ }
3163
+ isSupported() {
3164
+ if (!this.isBrowserEnvironment())
3165
+ return false;
3166
+ return !!navigator.locks;
3167
+ }
3168
+ /**
3169
+ * Acquire a lock and run the callback while holding it. The lock is released
3170
+ * automatically when the callback resolves or rejects.
3171
+ */
3172
+ acquire(name, callback, options = {}) {
3173
+ this.ensureSupported();
3174
+ const nav = navigator;
3175
+ if (Object.keys(options).length === 0) {
3176
+ return nav.locks.request(name, () => callback());
3177
+ }
3178
+ return nav.locks.request(name, options, () => callback());
3179
+ }
3180
+ /**
3181
+ * Query the current lock state. Useful for diagnostics and tests; do not gate
3182
+ * critical-section logic on this — it's a snapshot, not a reservation.
3183
+ */
3184
+ query() {
3185
+ this.ensureSupported();
3186
+ return navigator.locks.query();
3187
+ }
3188
+ ensureSupported() {
3189
+ super.ensureSupported();
3190
+ if (!this.isSupported()) {
3191
+ throw new Error('Web Locks API not supported in this browser');
3192
+ }
3193
+ }
3194
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: WebLocksService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
3195
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: WebLocksService });
3196
+ }
3197
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: WebLocksService, decorators: [{
3198
+ type: Injectable
3199
+ }] });
3200
+
3201
+ /**
3202
+ * Service wrapping `navigator.storage` (StorageManager API). Exposes:
3203
+ * - `estimate()`: how much origin storage is in use vs available
3204
+ * - `persist()`: ask the browser to make storage persistent (eviction-protected)
3205
+ * - `persisted()`: check whether storage is currently persistent
3206
+ */
3207
+ class StorageManagerService extends BrowserApiBaseService {
3208
+ getApiName() {
3209
+ return 'storage-manager';
3210
+ }
3211
+ isSupported() {
3212
+ if (!this.isBrowserEnvironment())
3213
+ return false;
3214
+ const sm = navigator.storage;
3215
+ return !!sm && typeof sm.estimate === 'function';
3216
+ }
3217
+ async estimate() {
3218
+ this.ensureSupported();
3219
+ const sm = navigator.storage;
3220
+ const result = await sm.estimate();
3221
+ return {
3222
+ usage: result.usage ?? 0,
3223
+ quota: result.quota ?? 0,
3224
+ usageDetails: result
3225
+ .usageDetails,
3226
+ };
3227
+ }
3228
+ async persist() {
3229
+ this.ensureSupported();
3230
+ const sm = navigator.storage;
3231
+ if (typeof sm.persist !== 'function')
3232
+ return false;
3233
+ return sm.persist();
3234
+ }
3235
+ async persisted() {
3236
+ this.ensureSupported();
3237
+ const sm = navigator.storage;
3238
+ if (typeof sm.persisted !== 'function')
3239
+ return false;
3240
+ return sm.persisted();
3241
+ }
3242
+ ensureSupported() {
3243
+ super.ensureSupported();
3244
+ if (!this.isSupported()) {
3245
+ throw new Error('StorageManager API not supported in this browser');
3246
+ }
3247
+ }
3248
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: StorageManagerService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
3249
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: StorageManagerService });
3250
+ }
3251
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: StorageManagerService, decorators: [{
3252
+ type: Injectable
3253
+ }] });
3254
+
3255
+ /**
3256
+ * Service wrapping `CompressionStream` and `DecompressionStream`.
3257
+ *
3258
+ * ```ts
3259
+ * const cmp = inject(CompressionService);
3260
+ * const compressed = await cmp.compress(jsonBytes, 'gzip');
3261
+ * const original = await cmp.decompress(compressed, 'gzip');
3262
+ * ```
3263
+ */
3264
+ class CompressionService extends BrowserApiBaseService {
3265
+ getApiName() {
3266
+ return 'compression-streams';
3267
+ }
3268
+ isSupported() {
3269
+ if (!this.isBrowserEnvironment())
3270
+ return false;
3271
+ const g = globalThis;
3272
+ return typeof g.CompressionStream === 'function' && typeof g.DecompressionStream === 'function';
3273
+ }
3274
+ /** Compress a `Uint8Array`/`ArrayBuffer` using the given format. */
3275
+ async compress(data, format = 'gzip') {
3276
+ this.ensureSupported();
3277
+ const g = globalThis;
3278
+ const stream = new g.CompressionStream(format);
3279
+ return this.runStream(data, stream);
3280
+ }
3281
+ /** Decompress a `Uint8Array`/`ArrayBuffer` using the given format. */
3282
+ async decompress(data, format = 'gzip') {
3283
+ this.ensureSupported();
3284
+ const g = globalThis;
3285
+ const stream = new g.DecompressionStream(format);
3286
+ return this.runStream(data, stream);
3287
+ }
3288
+ /** Convenience: compress a UTF-8 string and return the compressed bytes. */
3289
+ async compressString(value, format = 'gzip') {
3290
+ return this.compress(new TextEncoder().encode(value), format);
3291
+ }
3292
+ /** Convenience: decompress bytes into a UTF-8 string. */
3293
+ async decompressString(data, format = 'gzip') {
3294
+ const bytes = await this.decompress(data, format);
3295
+ return new TextDecoder().decode(bytes);
3296
+ }
3297
+ ensureSupported() {
3298
+ super.ensureSupported();
3299
+ if (!this.isSupported()) {
3300
+ throw new Error('Compression Streams API not supported in this browser');
3301
+ }
3302
+ }
3303
+ async runStream(data, stream) {
3304
+ const writer = stream.writable.getWriter();
3305
+ const writePromise = writer.write(data instanceof Uint8Array ? data : new Uint8Array(data));
3306
+ const closePromise = writer.close();
3307
+ const reader = stream.readable.getReader();
3308
+ const chunks = [];
3309
+ let total = 0;
3310
+ while (true) {
3311
+ const { done, value } = await reader.read();
3312
+ if (done)
3313
+ break;
3314
+ const chunk = value;
3315
+ chunks.push(chunk);
3316
+ total += chunk.byteLength;
3317
+ }
3318
+ await writePromise;
3319
+ await closePromise;
3320
+ const result = new Uint8Array(total);
3321
+ let offset = 0;
3322
+ for (const chunk of chunks) {
3323
+ result.set(chunk, offset);
3324
+ offset += chunk.byteLength;
3325
+ }
3326
+ return result;
3327
+ }
3328
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CompressionService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
3329
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CompressionService });
3330
+ }
3331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CompressionService, decorators: [{
3332
+ type: Injectable
3333
+ }] });
3334
+
3335
+ /**
3336
+ * When set to `true`, suppresses the one-time runtime warning that experimental
3337
+ * services emit on first use. Default is `false` (warnings emitted).
3338
+ */
3339
+ const BROWSER_API_EXPERIMENTAL_SILENT = new InjectionToken('BROWSER_API_EXPERIMENTAL_SILENT', {
3340
+ providedIn: 'root',
3341
+ factory: () => false,
3342
+ });
3343
+ const warned = new Set();
3344
+ /**
3345
+ * Emit a one-time runtime warning explaining that the API is experimental and
3346
+ * subject to breaking changes. No-op after the first call for a given key, or if
3347
+ * the consumer has provided `BROWSER_API_EXPERIMENTAL_SILENT` as `true`.
3348
+ */
3349
+ function warnExperimental(key, context) {
3350
+ if (context.silent)
3351
+ return;
3352
+ if (warned.has(key))
3353
+ return;
3354
+ warned.add(key);
3355
+ context.logger.warn(`[browser-web-apis:experimental] "${key}" is part of the experimental surface ` +
3356
+ 'and may change without a major bump. Provide BROWSER_API_EXPERIMENTAL_SILENT=true ' +
3357
+ 'to suppress this warning.');
3358
+ }
3359
+ /** Test-only: reset the in-memory dedup set. */
3360
+ function resetExperimentalWarnings() {
3361
+ warned.clear();
3362
+ }
3363
+
3090
3364
  // Common types for browser APIs
3091
3365
 
3092
3366
  function injectPageVisibility() {
@@ -3743,6 +4017,18 @@ function provideGamepad() {
3743
4017
  return makeEnvironmentProviders([GamepadService]);
3744
4018
  }
3745
4019
 
4020
+ function provideWebLocks() {
4021
+ return makeEnvironmentProviders([WebLocksService]);
4022
+ }
4023
+
4024
+ function provideStorageManager() {
4025
+ return makeEnvironmentProviders([StorageManagerService]);
4026
+ }
4027
+
4028
+ function provideCompression() {
4029
+ return makeEnvironmentProviders([CompressionService]);
4030
+ }
4031
+
3746
4032
  function provideMediaApis() {
3747
4033
  return makeEnvironmentProviders([PermissionsService, CameraService, MediaDevicesService]);
3748
4034
  }
@@ -3790,9 +4076,33 @@ const defaultBrowserWebApisConfig = {
3790
4076
  enableWebAudio: false,
3791
4077
  enableGamepad: false,
3792
4078
  };
4079
+ let legacyFlagsDeprecationLogged = false;
3793
4080
  function provideBrowserWebApis(config = {}) {
3794
- const mergedConfig = { ...defaultBrowserWebApisConfig, ...config };
4081
+ const { services, ...flagConfig } = config;
4082
+ // Composition-first path: only `services` provided, no flags.
4083
+ if (services && Object.keys(flagConfig).length === 0) {
4084
+ return makeEnvironmentProviders([
4085
+ PermissionsService,
4086
+ ...services.flatMap((env) => env.ɵproviders ?? []),
4087
+ ]);
4088
+ }
4089
+ // Legacy flag-bag path. Log deprecation once if any enableX is set.
4090
+ if (Object.keys(flagConfig).length > 0 && !legacyFlagsDeprecationLogged) {
4091
+ legacyFlagsDeprecationLogged = true;
4092
+ // oxlint-disable-next-line no-console
4093
+ console.warn('[browser-web-apis] provideBrowserWebApis(enableX flags) is deprecated. ' +
4094
+ 'Pass `{ services: [provideCamera(), ...] }` instead. The flag-bag form will be ' +
4095
+ 'removed in v22.');
4096
+ }
4097
+ const mergedConfig = { ...defaultBrowserWebApisConfig, ...flagConfig };
3795
4098
  const providers = [PermissionsService];
4099
+ if (services) {
4100
+ for (const env of services) {
4101
+ const inner = env.ɵproviders;
4102
+ if (inner)
4103
+ providers.push(...inner);
4104
+ }
4105
+ }
3796
4106
  const conditionalProviders = [
3797
4107
  [mergedConfig.enableCamera, CameraService],
3798
4108
  [mergedConfig.enableGeolocation, GeolocationService],
@@ -3838,4 +4148,4 @@ const version = '0.1.0';
3838
4148
  * Generated bundle index. Do not edit.
3839
4149
  */
3840
4150
 
3841
- export { BROWSER_API_LOGGER, BatteryService, BroadcastChannelService, BrowserApiBaseService, BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, ConnectionRegistryBaseService, FileSystemAccessService, FullscreenService, GamepadService, GeolocationService, IntersectionObserverService, MediaDevicesService, MediaRecorderService, MutationObserverService, NetworkInformationService, NotificationService, PageVisibilityService, PerformanceObserverService, PermissionsService, ResizeObserverService, ScreenOrientationService, ScreenWakeLockService, ServerSentEventsService, SpeechSynthesisService, VibrationService, WebAudioService, WebShareService, WebSocketClient, WebSocketService, WebStorageService, WebWorkerService, permissionGuard as createPermissionGuard, defaultBrowserWebApisConfig, injectBattery, injectClipboard, injectGamepad, injectGeolocation, injectIntersectionObserver, injectMutationObserver, injectNetworkInformation, injectPageVisibility, injectPerformanceObserver, injectResizeObserver, injectScreenOrientation, injectWakeLock, permissionGuard, provideBattery, provideBroadcastChannel, provideBrowserWebApis, provideCamera, provideClipboard, provideCommunicationApis, provideFileSystemAccess, provideFullscreen, provideGamepad, provideGeolocation, provideIntersectionObserver, provideLocationApis, provideMediaApis, provideMediaDevices, provideMediaRecorder, provideMutationObserver, provideNetworkInformation, provideNotifications, providePageVisibility, providePerformanceObserver, providePermissions, provideResizeObserver, provideScreenOrientation, provideScreenWakeLock, provideServerSentEvents, provideSpeechSynthesis, provideStorageApis, provideVibration, provideWebAudio, provideWebShare, provideWebSocket, provideWebStorage, provideWebWorker, version };
4151
+ export { BROWSER_API_EXPERIMENTAL_SILENT, BROWSER_API_LOGGER, BROWSER_API_LOG_LEVEL, BatteryService, BroadcastChannelService, BrowserApiBaseService, BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, CompressionService, ConnectionRegistryBaseService, FileSystemAccessService, FullscreenService, GamepadService, GeolocationService, IntersectionObserverService, MediaDevicesService, MediaRecorderService, MutationObserverService, NetworkInformationService, NotificationService, PageVisibilityService, PerformanceObserverService, PermissionsService, ResizeObserverService, ScreenOrientationService, ScreenWakeLockService, ServerSentEventsService, SpeechSynthesisService, StorageManagerService, VibrationService, WebAudioService, WebLocksService, WebShareService, WebSocketClient, WebSocketService, WebStorageService, WebWorkerService, permissionGuard as createPermissionGuard, defaultBrowserWebApisConfig, injectBattery, injectClipboard, injectGamepad, injectGeolocation, injectIntersectionObserver, injectMutationObserver, injectNetworkInformation, injectPageVisibility, injectPerformanceObserver, injectResizeObserver, injectScreenOrientation, injectWakeLock, permissionGuard, provideBattery, provideBroadcastChannel, provideBrowserApiLogLevel, provideBrowserWebApis, provideCamera, provideClipboard, provideCommunicationApis, provideCompression, provideFileSystemAccess, provideFullscreen, provideGamepad, provideGeolocation, provideIntersectionObserver, provideLocationApis, provideMediaApis, provideMediaDevices, provideMediaRecorder, provideMutationObserver, provideNetworkInformation, provideNotifications, providePageVisibility, providePerformanceObserver, providePermissions, provideResizeObserver, provideScreenOrientation, provideScreenWakeLock, provideServerSentEvents, provideSpeechSynthesis, provideStorageApis, provideStorageManager, provideVibration, provideWebAudio, provideWebLocks, provideWebShare, provideWebSocket, provideWebStorage, provideWebWorker, version, warnExperimental };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-helpers/browser-web-apis",
3
- "version": "21.9.0",
3
+ "version": "21.11.0",
4
4
  "description": "Sistema de servicios Angular para acceso formalizado a Browser Web APIs (cámara, permisos, geolocalización, etc.)",
5
5
  "homepage": "https://gaspar1992.github.io/angular-helpers/docs/browser-web-apis",
6
6
  "repository": {
@@ -3,7 +3,7 @@ import * as i0 from '@angular/core';
3
3
  import { DestroyRef, ElementRef, Signal, InjectionToken, EnvironmentProviders } from '@angular/core';
4
4
  import { CanActivateFn } from '@angular/router';
5
5
 
6
- type BrowserCapabilityId = 'permissions' | 'geolocation' | 'clipboard' | 'notification' | 'mediaDevices' | 'camera' | 'webWorker' | 'regexSecurity' | 'webStorage' | 'webShare' | 'battery' | 'webSocket' | 'intersectionObserver' | 'resizeObserver' | 'pageVisibility' | 'broadcastChannel' | 'networkInformation' | 'screenWakeLock' | 'screenOrientation' | 'fullscreen' | 'fileSystemAccess' | 'mediaRecorder' | 'serverSentEvents' | 'vibration' | 'speechSynthesis' | 'mutationObserver' | 'performanceObserver' | 'idleDetector' | 'eyeDropper' | 'barcodeDetector' | 'webAudio' | 'gamepad' | 'webBluetooth' | 'webUsb' | 'webNfc' | 'paymentRequest' | 'credentialManagement';
6
+ type BrowserCapabilityId = 'permissions' | 'geolocation' | 'clipboard' | 'notification' | 'mediaDevices' | 'camera' | 'webWorker' | 'regexSecurity' | 'webStorage' | 'webShare' | 'battery' | 'webSocket' | 'intersectionObserver' | 'resizeObserver' | 'pageVisibility' | 'broadcastChannel' | 'networkInformation' | 'screenWakeLock' | 'screenOrientation' | 'fullscreen' | 'fileSystemAccess' | 'mediaRecorder' | 'serverSentEvents' | 'vibration' | 'speechSynthesis' | 'mutationObserver' | 'performanceObserver' | 'idleDetector' | 'eyeDropper' | 'barcodeDetector' | 'webAudio' | 'gamepad' | 'webBluetooth' | 'webUsb' | 'webNfc' | 'paymentRequest' | 'credentialManagement' | 'webLocks' | 'storageManager' | 'compressionStreams';
7
7
  declare class BrowserCapabilityService {
8
8
  getCapabilities(): readonly [{
9
9
  readonly id: "permissions";
@@ -153,12 +153,24 @@ declare class BrowserCapabilityService {
153
153
  readonly id: "credentialManagement";
154
154
  readonly label: "Credential Management API";
155
155
  readonly requiresSecureContext: true;
156
+ }, {
157
+ readonly id: "webLocks";
158
+ readonly label: "Web Locks API";
159
+ readonly requiresSecureContext: true;
160
+ }, {
161
+ readonly id: "storageManager";
162
+ readonly label: "Storage Manager API";
163
+ readonly requiresSecureContext: true;
164
+ }, {
165
+ readonly id: "compressionStreams";
166
+ readonly label: "Compression Streams API";
167
+ readonly requiresSecureContext: false;
156
168
  }];
157
169
  isSecureContext(): boolean;
158
170
  isSupported(capability: BrowserCapabilityId): boolean;
159
171
  getAllStatuses(): {
160
- id: "permissions" | "geolocation" | "clipboard" | "notification" | "mediaDevices" | "camera" | "webWorker" | "regexSecurity" | "webStorage" | "webShare" | "battery" | "webSocket" | "intersectionObserver" | "resizeObserver" | "pageVisibility" | "broadcastChannel" | "networkInformation" | "screenWakeLock" | "screenOrientation" | "fullscreen" | "fileSystemAccess" | "mediaRecorder" | "serverSentEvents" | "vibration" | "speechSynthesis" | "mutationObserver" | "performanceObserver" | "idleDetector" | "eyeDropper" | "barcodeDetector" | "webAudio" | "gamepad" | "webBluetooth" | "webUsb" | "webNfc" | "paymentRequest" | "credentialManagement";
161
- label: "Permissions API" | "Geolocation API" | "Clipboard API" | "Notification API" | "MediaDevices API" | "Camera API" | "Web Worker API" | "Regex Security" | "Web Storage" | "Web Share" | "Battery API" | "WebSocket API" | "Intersection Observer" | "Resize Observer" | "Page Visibility API" | "Broadcast Channel API" | "Network Information API" | "Screen Wake Lock API" | "Screen Orientation API" | "Fullscreen API" | "File System Access API" | "MediaRecorder API" | "Server-Sent Events" | "Vibration API" | "Speech Synthesis API" | "Mutation Observer" | "Performance Observer" | "Idle Detection API" | "EyeDropper API" | "Barcode Detection API" | "Web Audio API" | "Gamepad API" | "Web Bluetooth API" | "WebUSB API" | "Web NFC API" | "Payment Request API" | "Credential Management API";
172
+ id: "permissions" | "geolocation" | "clipboard" | "notification" | "mediaDevices" | "camera" | "webWorker" | "regexSecurity" | "webStorage" | "webShare" | "battery" | "webSocket" | "intersectionObserver" | "resizeObserver" | "pageVisibility" | "broadcastChannel" | "networkInformation" | "screenWakeLock" | "screenOrientation" | "fullscreen" | "fileSystemAccess" | "mediaRecorder" | "serverSentEvents" | "vibration" | "speechSynthesis" | "mutationObserver" | "performanceObserver" | "idleDetector" | "eyeDropper" | "barcodeDetector" | "webAudio" | "gamepad" | "webBluetooth" | "webUsb" | "webNfc" | "paymentRequest" | "credentialManagement" | "webLocks" | "storageManager" | "compressionStreams";
173
+ label: "Permissions API" | "Geolocation API" | "Clipboard API" | "Notification API" | "MediaDevices API" | "Camera API" | "Web Worker API" | "Regex Security" | "Web Storage" | "Web Share" | "Battery API" | "WebSocket API" | "Intersection Observer" | "Resize Observer" | "Page Visibility API" | "Broadcast Channel API" | "Network Information API" | "Screen Wake Lock API" | "Screen Orientation API" | "Fullscreen API" | "File System Access API" | "MediaRecorder API" | "Server-Sent Events" | "Vibration API" | "Speech Synthesis API" | "Mutation Observer" | "Performance Observer" | "Idle Detection API" | "EyeDropper API" | "Barcode Detection API" | "Web Audio API" | "Gamepad API" | "Web Bluetooth API" | "WebUSB API" | "Web NFC API" | "Payment Request API" | "Credential Management API" | "Web Locks API" | "Storage Manager API" | "Compression Streams API";
162
174
  supported: boolean;
163
175
  secureContext: boolean;
164
176
  requiresSecureContext: boolean;
@@ -218,6 +230,7 @@ declare abstract class BrowserApiBaseService {
218
230
  protected logError(message: string, error?: unknown): void;
219
231
  protected logWarn(message: string): void;
220
232
  protected logInfo(message: string): void;
233
+ protected logDebug(message: string): void;
221
234
  static ɵfac: i0.ɵɵFactoryDeclaration<BrowserApiBaseService, never>;
222
235
  static ɵprov: i0.ɵɵInjectableDeclaration<BrowserApiBaseService>;
223
236
  }
@@ -380,12 +393,24 @@ type ErrorCallback = (error: BrowserError) => void;
380
393
  */
381
394
  type ElementInput = Element | ElementRef<Element> | Signal<Element | ElementRef<Element> | undefined>;
382
395
 
396
+ type BrowserApiLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
383
397
  interface BrowserApiLogger {
398
+ debug?(message: string): void;
384
399
  info(message: string): void;
385
400
  warn(message: string): void;
386
401
  error(message: string, error?: unknown): void;
387
402
  }
403
+ /**
404
+ * Global log level for `BROWSER_API_LOGGER`. Defaults to `'debug'` in dev mode and
405
+ * `'warn'` in production. Override via `provideBrowserApiLogLevel('silent')` etc.
406
+ */
407
+ declare const BROWSER_API_LOG_LEVEL: InjectionToken<BrowserApiLogLevel>;
388
408
  declare const BROWSER_API_LOGGER: InjectionToken<BrowserApiLogger>;
409
+ /** Log level helper provider. Overrides the default `BROWSER_API_LOG_LEVEL`. */
410
+ declare function provideBrowserApiLogLevel(level: BrowserApiLogLevel): {
411
+ provide: InjectionToken<BrowserApiLogLevel>;
412
+ useValue: BrowserApiLogLevel;
413
+ };
389
414
 
390
415
  interface StorageOptions {
391
416
  /** Optional prefix used to namespace keys (e.g. `app:` -> `app:userId`). */
@@ -1134,6 +1159,120 @@ declare class GamepadService extends BrowserApiBaseService {
1134
1159
  static ɵprov: i0.ɵɵInjectableDeclaration<GamepadService>;
1135
1160
  }
1136
1161
 
1162
+ interface LockOptionsLike {
1163
+ mode?: 'exclusive' | 'shared';
1164
+ ifAvailable?: boolean;
1165
+ steal?: boolean;
1166
+ signal?: AbortSignal;
1167
+ }
1168
+ interface LockInfoLike {
1169
+ name: string;
1170
+ mode: 'exclusive' | 'shared';
1171
+ clientId: string;
1172
+ }
1173
+ interface LockManagerSnapshot {
1174
+ held: LockInfoLike[];
1175
+ pending: LockInfoLike[];
1176
+ }
1177
+ /**
1178
+ * Service wrapping `navigator.locks` (Web Locks API). Coordinates exclusive or
1179
+ * shared access to a named resource across tabs and workers.
1180
+ *
1181
+ * ```ts
1182
+ * const locks = inject(WebLocksService);
1183
+ * await locks.acquire('user-cache', async () => {
1184
+ * // critical section — no other tab is in this block at the same time
1185
+ * });
1186
+ * ```
1187
+ */
1188
+ declare class WebLocksService extends BrowserApiBaseService {
1189
+ protected getApiName(): string;
1190
+ isSupported(): boolean;
1191
+ /**
1192
+ * Acquire a lock and run the callback while holding it. The lock is released
1193
+ * automatically when the callback resolves or rejects.
1194
+ */
1195
+ acquire<T>(name: string, callback: () => Promise<T> | T, options?: LockOptionsLike): Promise<T>;
1196
+ /**
1197
+ * Query the current lock state. Useful for diagnostics and tests; do not gate
1198
+ * critical-section logic on this — it's a snapshot, not a reservation.
1199
+ */
1200
+ query(): Promise<LockManagerSnapshot>;
1201
+ protected ensureSupported(): void;
1202
+ static ɵfac: i0.ɵɵFactoryDeclaration<WebLocksService, never>;
1203
+ static ɵprov: i0.ɵɵInjectableDeclaration<WebLocksService>;
1204
+ }
1205
+
1206
+ interface StorageQuotaEstimate {
1207
+ /** Bytes currently used by the origin (best-effort). */
1208
+ usage: number;
1209
+ /** Maximum bytes the origin may use (best-effort). */
1210
+ quota: number;
1211
+ /** Per-storage-type breakdown, when the browser provides it. */
1212
+ usageDetails?: Record<string, number>;
1213
+ }
1214
+ /**
1215
+ * Service wrapping `navigator.storage` (StorageManager API). Exposes:
1216
+ * - `estimate()`: how much origin storage is in use vs available
1217
+ * - `persist()`: ask the browser to make storage persistent (eviction-protected)
1218
+ * - `persisted()`: check whether storage is currently persistent
1219
+ */
1220
+ declare class StorageManagerService extends BrowserApiBaseService {
1221
+ protected getApiName(): string;
1222
+ isSupported(): boolean;
1223
+ estimate(): Promise<StorageQuotaEstimate>;
1224
+ persist(): Promise<boolean>;
1225
+ persisted(): Promise<boolean>;
1226
+ protected ensureSupported(): void;
1227
+ static ɵfac: i0.ɵɵFactoryDeclaration<StorageManagerService, never>;
1228
+ static ɵprov: i0.ɵɵInjectableDeclaration<StorageManagerService>;
1229
+ }
1230
+
1231
+ type CompressionFormat = 'gzip' | 'deflate' | 'deflate-raw';
1232
+ /**
1233
+ * Service wrapping `CompressionStream` and `DecompressionStream`.
1234
+ *
1235
+ * ```ts
1236
+ * const cmp = inject(CompressionService);
1237
+ * const compressed = await cmp.compress(jsonBytes, 'gzip');
1238
+ * const original = await cmp.decompress(compressed, 'gzip');
1239
+ * ```
1240
+ */
1241
+ declare class CompressionService extends BrowserApiBaseService {
1242
+ protected getApiName(): string;
1243
+ isSupported(): boolean;
1244
+ /** Compress a `Uint8Array`/`ArrayBuffer` using the given format. */
1245
+ compress(data: Uint8Array | ArrayBuffer, format?: CompressionFormat): Promise<Uint8Array>;
1246
+ /** Decompress a `Uint8Array`/`ArrayBuffer` using the given format. */
1247
+ decompress(data: Uint8Array | ArrayBuffer, format?: CompressionFormat): Promise<Uint8Array>;
1248
+ /** Convenience: compress a UTF-8 string and return the compressed bytes. */
1249
+ compressString(value: string, format?: CompressionFormat): Promise<Uint8Array>;
1250
+ /** Convenience: decompress bytes into a UTF-8 string. */
1251
+ decompressString(data: Uint8Array | ArrayBuffer, format?: CompressionFormat): Promise<string>;
1252
+ protected ensureSupported(): void;
1253
+ private runStream;
1254
+ static ɵfac: i0.ɵɵFactoryDeclaration<CompressionService, never>;
1255
+ static ɵprov: i0.ɵɵInjectableDeclaration<CompressionService>;
1256
+ }
1257
+
1258
+ /**
1259
+ * When set to `true`, suppresses the one-time runtime warning that experimental
1260
+ * services emit on first use. Default is `false` (warnings emitted).
1261
+ */
1262
+ declare const BROWSER_API_EXPERIMENTAL_SILENT: InjectionToken<boolean>;
1263
+ interface ExperimentalWarnContext {
1264
+ silent: boolean;
1265
+ logger: {
1266
+ warn: (message: string) => void;
1267
+ };
1268
+ }
1269
+ /**
1270
+ * Emit a one-time runtime warning explaining that the API is experimental and
1271
+ * subject to breaking changes. No-op after the first call for a given key, or if
1272
+ * the consumer has provided `BROWSER_API_EXPERIMENTAL_SILENT` as `true`.
1273
+ */
1274
+ declare function warnExperimental(key: string, context: ExperimentalWarnContext): void;
1275
+
1137
1276
  interface MediaDevice {
1138
1277
  deviceId: string;
1139
1278
  groupId: string;
@@ -1428,12 +1567,31 @@ declare function provideWebAudio(): EnvironmentProviders;
1428
1567
 
1429
1568
  declare function provideGamepad(): EnvironmentProviders;
1430
1569
 
1570
+ declare function provideWebLocks(): EnvironmentProviders;
1571
+
1572
+ declare function provideStorageManager(): EnvironmentProviders;
1573
+
1574
+ declare function provideCompression(): EnvironmentProviders;
1575
+
1431
1576
  declare function provideMediaApis(): EnvironmentProviders;
1432
1577
  declare function provideLocationApis(): EnvironmentProviders;
1433
1578
  declare function provideStorageApis(): EnvironmentProviders;
1434
1579
  declare function provideCommunicationApis(): EnvironmentProviders;
1435
1580
 
1436
- interface BrowserWebApisConfig {
1581
+ /**
1582
+ * Composition-first config: pass an array of `provide*()` calls and we merge them
1583
+ * into a single `EnvironmentProviders`. Preferred over the `enableX` flag bag.
1584
+ *
1585
+ * ```ts
1586
+ * provideBrowserWebApis({
1587
+ * services: [provideCamera(), provideClipboard(), provideMediaApis()],
1588
+ * })
1589
+ * ```
1590
+ */
1591
+ interface BrowserWebApisCompositionConfig {
1592
+ services?: EnvironmentProviders[];
1593
+ }
1594
+ interface BrowserWebApisConfig extends BrowserWebApisCompositionConfig {
1437
1595
  enableCamera?: boolean;
1438
1596
  enableGeolocation?: boolean;
1439
1597
  enableNotifications?: boolean;
@@ -1467,5 +1625,5 @@ declare function provideBrowserWebApis(config?: BrowserWebApisConfig): Environme
1467
1625
 
1468
1626
  declare const version = "0.1.0";
1469
1627
 
1470
- export { BROWSER_API_LOGGER, BatteryService, BroadcastChannelService, BrowserApiBaseService, BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, ConnectionRegistryBaseService, FileSystemAccessService, FullscreenService, GamepadService, GeolocationService, IntersectionObserverService, MediaDevicesService, MediaRecorderService, MutationObserverService, NetworkInformationService, NotificationService, PageVisibilityService, PerformanceObserverService, PermissionsService, ResizeObserverService, ScreenOrientationService, ScreenWakeLockService, ServerSentEventsService, SpeechSynthesisService, VibrationService, WebAudioService, WebShareService, WebSocketClient, WebSocketService, WebStorageService, WebWorkerService, permissionGuard as createPermissionGuard, defaultBrowserWebApisConfig, injectBattery, injectClipboard, injectGamepad, injectGeolocation, injectIntersectionObserver, injectMutationObserver, injectNetworkInformation, injectPageVisibility, injectPerformanceObserver, injectResizeObserver, injectScreenOrientation, injectWakeLock, permissionGuard, provideBattery, provideBroadcastChannel, provideBrowserWebApis, provideCamera, provideClipboard, provideCommunicationApis, provideFileSystemAccess, provideFullscreen, provideGamepad, provideGeolocation, provideIntersectionObserver, provideLocationApis, provideMediaApis, provideMediaDevices, provideMediaRecorder, provideMutationObserver, provideNetworkInformation, provideNotifications, providePageVisibility, providePerformanceObserver, providePermissions, provideResizeObserver, provideScreenOrientation, provideScreenWakeLock, provideServerSentEvents, provideSpeechSynthesis, provideStorageApis, provideVibration, provideWebAudio, provideWebShare, provideWebSocket, provideWebStorage, provideWebWorker, version };
1471
- export type { AudioAnalyserData, AudioContextState, BatteryInfo, BatteryManager, BatteryRef, BrowserApiLogger, BrowserCapabilityId, BrowserError, BrowserPermissions, BrowserWebApisConfig, CameraCapabilities, CameraInfo, ClipboardRef, ConnectionType, EffectiveConnectionType, ElementInput, ElementSize, ErrorCallback, EventHandler, FileOpenOptions, FileSaveOptions, GamepadRef, GamepadState, GeolocationCoordinates, GeolocationError, GeolocationOptions, GeolocationPosition$1 as GeolocationPosition, GeolocationRef, GeolocationWatchOptions, IntersectionObserverOptions, IntersectionRef, MediaDevice, MediaDeviceKind, MediaDevicesInfo, MediaStreamConstraints$1 as MediaStreamConstraints, MediaTrackConstraints$1 as MediaTrackConstraints, MutationObserverOptions, MutationRef, NetworkInformation, NetworkInformationRef, OrientationInfo, OrientationLockType, OrientationType, PageVisibilityRef, PerformanceEntryType, PerformanceObserverConfig, PerformanceObserverRef, PermissionNameExt, PermissionRequest, RecordingOptions, RecordingResult, RecordingState, ResizeObserverOptions, ResizeRef, SSEConfig, SSEConnectionState, SSEMessage, ScreenOrientationRef, SpeechOptions, SpeechState, StorageEvent, StorageNamespace, StorageOptions, StorageValue, VibrationPattern, VibrationPreset, VisibilityState, WakeLockRef, WakeLockStatus, WakeLockType, WebSocketClientConfig, WebSocketConfig, WebSocketMessage, WebSocketRequestOptions, WebSocketState, WebSocketStatus, WebSocketStatusV2, WorkerMessage, WorkerRequestOptions, WorkerStatus, WorkerTask };
1628
+ export { BROWSER_API_EXPERIMENTAL_SILENT, BROWSER_API_LOGGER, BROWSER_API_LOG_LEVEL, BatteryService, BroadcastChannelService, BrowserApiBaseService, BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, CompressionService, ConnectionRegistryBaseService, FileSystemAccessService, FullscreenService, GamepadService, GeolocationService, IntersectionObserverService, MediaDevicesService, MediaRecorderService, MutationObserverService, NetworkInformationService, NotificationService, PageVisibilityService, PerformanceObserverService, PermissionsService, ResizeObserverService, ScreenOrientationService, ScreenWakeLockService, ServerSentEventsService, SpeechSynthesisService, StorageManagerService, VibrationService, WebAudioService, WebLocksService, WebShareService, WebSocketClient, WebSocketService, WebStorageService, WebWorkerService, permissionGuard as createPermissionGuard, defaultBrowserWebApisConfig, injectBattery, injectClipboard, injectGamepad, injectGeolocation, injectIntersectionObserver, injectMutationObserver, injectNetworkInformation, injectPageVisibility, injectPerformanceObserver, injectResizeObserver, injectScreenOrientation, injectWakeLock, permissionGuard, provideBattery, provideBroadcastChannel, provideBrowserApiLogLevel, provideBrowserWebApis, provideCamera, provideClipboard, provideCommunicationApis, provideCompression, provideFileSystemAccess, provideFullscreen, provideGamepad, provideGeolocation, provideIntersectionObserver, provideLocationApis, provideMediaApis, provideMediaDevices, provideMediaRecorder, provideMutationObserver, provideNetworkInformation, provideNotifications, providePageVisibility, providePerformanceObserver, providePermissions, provideResizeObserver, provideScreenOrientation, provideScreenWakeLock, provideServerSentEvents, provideSpeechSynthesis, provideStorageApis, provideStorageManager, provideVibration, provideWebAudio, provideWebLocks, provideWebShare, provideWebSocket, provideWebStorage, provideWebWorker, version, warnExperimental };
1629
+ export type { AudioAnalyserData, AudioContextState, BatteryInfo, BatteryManager, BatteryRef, BrowserApiLogLevel, BrowserApiLogger, BrowserCapabilityId, BrowserError, BrowserPermissions, BrowserWebApisCompositionConfig, BrowserWebApisConfig, CameraCapabilities, CameraInfo, ClipboardRef, CompressionFormat, ConnectionType, EffectiveConnectionType, ElementInput, ElementSize, ErrorCallback, EventHandler, ExperimentalWarnContext, FileOpenOptions, FileSaveOptions, GamepadRef, GamepadState, GeolocationCoordinates, GeolocationError, GeolocationOptions, GeolocationPosition$1 as GeolocationPosition, GeolocationRef, GeolocationWatchOptions, IntersectionObserverOptions, IntersectionRef, MediaDevice, MediaDeviceKind, MediaDevicesInfo, MediaStreamConstraints$1 as MediaStreamConstraints, MediaTrackConstraints$1 as MediaTrackConstraints, MutationObserverOptions, MutationRef, NetworkInformation, NetworkInformationRef, OrientationInfo, OrientationLockType, OrientationType, PageVisibilityRef, PerformanceEntryType, PerformanceObserverConfig, PerformanceObserverRef, PermissionNameExt, PermissionRequest, RecordingOptions, RecordingResult, RecordingState, ResizeObserverOptions, ResizeRef, SSEConfig, SSEConnectionState, SSEMessage, ScreenOrientationRef, SpeechOptions, SpeechState, StorageEvent, StorageNamespace, StorageOptions, StorageQuotaEstimate, StorageValue, VibrationPattern, VibrationPreset, VisibilityState, WakeLockRef, WakeLockStatus, WakeLockType, WebSocketClientConfig, WebSocketConfig, WebSocketMessage, WebSocketRequestOptions, WebSocketState, WebSocketStatus, WebSocketStatusV2, WorkerMessage, WorkerRequestOptions, WorkerStatus, WorkerTask };