Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# availability
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Provides a runtime check for the presence of the Web Crypto API (`crypto.subtle`). The check is a prerequisite for every operation in `@suaveplan/crypto-browser`: all engine methods and primitives call `assertWebCryptoAvailable()` before attempting any `crypto.subtle` call, so callers receive a structured, typed `BrowserCryptoError` rather than an opaque `TypeError: Cannot read properties of undefined (reading 'subtle')`.
The two exported helpers form a small contract: `isWebCryptoAvailable` is a pure predicate useful for conditional branching or feature-flag evaluation, while `assertWebCryptoAvailable` is the guard variant used internally throughout the package.
## Features
- `isWebCryptoAvailable(): boolean` — returns `true` when both `globalThis.crypto` and `globalThis.crypto.subtle` are defined; otherwise `false`
- `assertWebCryptoAvailable(): void` — throws `BrowserCryptoError` with code `BROWSER_CRYPTO.NOT_AVAILABLE` if the check fails
- Zero side effects — purely reads globals, never modifies them
- Works across Node 20+, Bun, Deno, and modern browsers without polyfills
## Usage: Basic Example
```ts
import { isWebCryptoAvailable } from "@suaveplan/crypto-browser/availability/availability";
if (!isWebCryptoAvailable()) {
console.warn("WebCrypto not available — using fallback cipher");
}
```
## Usage: Advanced Example
```ts
import { assertWebCryptoAvailable } from "@suaveplan/crypto-browser/availability/availability";
import { BrowserCryptoError } from "@suaveplan/crypto-browser/errors";
async function encryptUserData(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
// Guard before any crypto.subtle calls
assertWebCryptoAvailable();
// ... proceed with crypto.subtle.encrypt
return new Uint8Array();
}
// Caller can catch the specific structured error
try {
await encryptUserData(key, data);
} catch (err) {
if (err instanceof BrowserCryptoError && err.code === "BROWSER_CRYPTO.NOT_AVAILABLE") {
// Fall back to a server-side encryption endpoint
}
}
```
## API Reference
### `isWebCryptoAvailable(): boolean`
Returns `true` when `typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined'`.
| Parameter | Type | Description |
|-----------|------|-------------|
| _(none)_ | — | — |
**Returns:** `boolean` — `true` if `crypto.subtle` is accessible.
**Throws:** never.
---
### `assertWebCryptoAvailable(): void`
Calls `isWebCryptoAvailable()` and throws if the result is `false`.
| Parameter | Type | Description |
|-----------|------|-------------|
| _(none)_ | — | — |
**Returns:** `void`
**Throws:** `BrowserCryptoError` — code `BROWSER_CRYPTO.NOT_AVAILABLE` when `crypto.subtle` is absent.
## Implementation Notes
The check deliberately uses `typeof crypto !== 'undefined'` (rather than a `try/catch` or optional chaining on a possibly-unset global) to avoid triggering a `ReferenceError` in environments where `crypto` is not declared at all. Optional chaining `globalThis?.crypto?.subtle` is not used because `globalThis` itself might be unavailable in some older embedded runtimes.
Both exports are side-effect-free and tree-shakeable: `"sideEffects": false` is set on the package, so bundlers that import only `isWebCryptoAvailable` will not include `BrowserCryptoError` in the output unless it is actually used.