@private.me/xbind 3.0.1 → 3.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 +55 -14
- package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1920 -1
- package/dist-standalone/_deps/shared/cjs/errors.js +729 -1
- package/dist-standalone/_deps/shared/cjs/index.js +463 -1
- package/dist-standalone/_deps/shared/cjs/types.js +315 -1
- package/dist-standalone/_deps/shared/errors.js +244 -1
- package/dist-standalone/_deps/shared/index.js +72 -1
- package/dist-standalone/_deps/shared/types.js +86 -1
- package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
- package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
- package/dist-standalone/_deps/ux-helpers/index.js +1 -1
- package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
- package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
- package/dist-standalone/_deps/ux-helpers/search.js +1 -1
- package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
- package/dist-standalone/_deps/xchange/errors.js +1 -1
- package/dist-standalone/_deps/xchange/index.js +1 -1
- package/dist-standalone/_deps/xchange/invite-client.js +1 -1
- package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
- package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
- package/dist-standalone/_deps/xchange/xchange.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
- package/dist-standalone/_deps/xregistry/discovery.js +1 -1
- package/dist-standalone/_deps/xregistry/errors.js +1 -1
- package/dist-standalone/_deps/xregistry/index.js +1 -1
- package/dist-standalone/_deps/xregistry/registry.js +1 -1
- package/dist-standalone/_deps/xregistry/schema.js +1 -1
- package/dist-standalone/_deps/xregistry/types.js +1 -1
- package/dist-standalone/agent-call.js +659 -1
- package/dist-standalone/agent-sdk.js +328 -1
- package/dist-standalone/agent.js +1800 -1
- package/dist-standalone/approval.js +193 -1
- package/dist-standalone/async-iterators.js +382 -1
- package/dist-standalone/auth.js +219 -1
- package/dist-standalone/auto-accept.js +229 -1
- package/dist-standalone/backup-config.js +201 -1
- package/dist-standalone/backup.js +326 -1
- package/dist-standalone/batch-operations.js +388 -1
- package/dist-standalone/cancellation.js +477 -1
- package/dist-standalone/checkpoint.js +186 -1
- package/dist-standalone/circuit-breaker.js +468 -1
- package/dist-standalone/cjs/agent-call.js +701 -1
- package/dist-standalone/cjs/agent-sdk.js +332 -1
- package/dist-standalone/cjs/agent.js +1837 -1
- package/dist-standalone/cjs/approval.js +199 -1
- package/dist-standalone/cjs/async-iterators.js +392 -1
- package/dist-standalone/cjs/auth.js +225 -1
- package/dist-standalone/cjs/auto-accept.js +233 -1
- package/dist-standalone/cjs/backup-config.js +207 -1
- package/dist-standalone/cjs/backup.js +330 -1
- package/dist-standalone/cjs/batch-operations.js +397 -1
- package/dist-standalone/cjs/cancellation.js +490 -1
- package/dist-standalone/cjs/checkpoint.js +193 -1
- package/dist-standalone/cjs/circuit-breaker.js +476 -1
- package/dist-standalone/cjs/cli/init.js +492 -1
- package/dist-standalone/cjs/config-validation.js +522 -1
- package/dist-standalone/cjs/connect.js +312 -1
- package/dist-standalone/cjs/connection-pool.js +506 -1
- package/dist-standalone/cjs/correlation-id.js +339 -1
- package/dist-standalone/cjs/crypto-utils.js +176 -1
- package/dist-standalone/cjs/debug-mode.js +534 -1
- package/dist-standalone/cjs/did-document.js +101 -1
- package/dist-standalone/cjs/did-privateme.js +130 -1
- package/dist-standalone/cjs/did-web.js +201 -1
- package/dist-standalone/cjs/discovery.js +462 -1
- package/dist-standalone/cjs/dual-mode.js +251 -1
- package/dist-standalone/cjs/email-templates.js +313 -1
- package/dist-standalone/cjs/email-transport.js +239 -1
- package/dist-standalone/cjs/envelope.js +538 -1
- package/dist-standalone/cjs/errors.js +913 -1
- package/dist-standalone/cjs/event-emitter.js +461 -1
- package/dist-standalone/cjs/gateway-state.js +55 -1
- package/dist-standalone/cjs/gateway-transport.js +120 -1
- package/dist-standalone/cjs/graceful-degradation.js +403 -1
- package/dist-standalone/cjs/guardrails.js +223 -1
- package/dist-standalone/cjs/health-check.js +336 -1
- package/dist-standalone/cjs/http-compat.js +272 -1
- package/dist-standalone/cjs/http-status-map.js +571 -1
- package/dist-standalone/cjs/identity.js +645 -1
- package/dist-standalone/cjs/index.js +406 -1
- package/dist-standalone/cjs/invitation.js +421 -1
- package/dist-standalone/cjs/invite.js +328 -1
- package/dist-standalone/cjs/key-agreement.js +335 -1
- package/dist-standalone/cjs/lazy-init.js +300 -1
- package/dist-standalone/cjs/logger.js +291 -1
- package/dist-standalone/cjs/mdns-discovery.js +202 -1
- package/dist-standalone/cjs/nonce-store.js +80 -1
- package/dist-standalone/cjs/pairing-manager.js +223 -1
- package/dist-standalone/cjs/plugin-system.js +264 -1
- package/dist-standalone/cjs/plugins/logging.js +168 -1
- package/dist-standalone/cjs/plugins/metrics.js +181 -1
- package/dist-standalone/cjs/plugins/validation.js +302 -1
- package/dist-standalone/cjs/policy.js +320 -1
- package/dist-standalone/cjs/progress-callbacks.js +583 -1
- package/dist-standalone/cjs/redis-nonce-store.js +76 -1
- package/dist-standalone/cjs/registry-middleware.js +50 -1
- package/dist-standalone/cjs/retry-strategies.js +544 -1
- package/dist-standalone/cjs/retry-transport.js +102 -1
- package/dist-standalone/cjs/runtime/browser.js +533 -1
- package/dist-standalone/cjs/runtime/edge.js +526 -1
- package/dist-standalone/cjs/runtime/react-native.js +394 -1
- package/dist-standalone/cjs/security-policy.js +245 -1
- package/dist-standalone/cjs/serialization.js +1040 -1
- package/dist-standalone/cjs/split-channel.js +225 -1
- package/dist-standalone/cjs/subscription-proof.js +230 -1
- package/dist-standalone/cjs/succession.js +148 -1
- package/dist-standalone/cjs/timeouts.js +412 -1
- package/dist-standalone/cjs/trace-context.js +424 -1
- package/dist-standalone/cjs/trace-spans.js +495 -1
- package/dist-standalone/cjs/transport.js +63 -1
- package/dist-standalone/cjs/trust-registry.js +991 -1
- package/dist-standalone/cjs/types/error-response.js +56 -1
- package/dist-standalone/cjs/vault-auth.js +178 -1
- package/dist-standalone/cjs/vault-store-loader.js +194 -1
- package/dist-standalone/cjs/verify.js +25 -1
- package/dist-standalone/cjs/version-info.js +543 -1
- package/dist-standalone/cjs/xfetch.js +340 -1
- package/dist-standalone/cli/init.js +455 -1
- package/dist-standalone/cli/setup.js +514 -1
- package/dist-standalone/cli/types.js +27 -1
- package/dist-standalone/cli/xbind.js +148 -1
- package/dist-standalone/config-validation.js +513 -1
- package/dist-standalone/connect.js +274 -1
- package/dist-standalone/connection-pool.js +500 -1
- package/dist-standalone/correlation-id.js +326 -1
- package/dist-standalone/crypto-utils.js +157 -1
- package/dist-standalone/debug-mode.js +510 -1
- package/dist-standalone/did-document.js +96 -1
- package/dist-standalone/did-privateme.js +121 -1
- package/dist-standalone/did-web.js +196 -1
- package/dist-standalone/discovery.js +458 -1
- package/dist-standalone/dual-mode.js +247 -1
- package/dist-standalone/email-templates.js +309 -1
- package/dist-standalone/email-transport.js +232 -1
- package/dist-standalone/envelope.js +525 -1
- package/dist-standalone/errors.js +896 -1
- package/dist-standalone/event-emitter.js +456 -1
- package/dist-standalone/gateway-state.js +51 -1
- package/dist-standalone/gateway-transport.js +116 -1
- package/dist-standalone/graceful-degradation.js +396 -1
- package/dist-standalone/guardrails.js +216 -1
- package/dist-standalone/health-check.js +332 -1
- package/dist-standalone/http-compat.js +267 -1
- package/dist-standalone/http-status-map.js +561 -1
- package/dist-standalone/identity.js +619 -1
- package/dist-standalone/index.js +78 -1
- package/dist-standalone/invitation.js +415 -1
- package/dist-standalone/invite.js +324 -1
- package/dist-standalone/key-agreement.js +325 -1
- package/dist-standalone/lazy-init.js +295 -1
- package/dist-standalone/logger.js +285 -1
- package/dist-standalone/mdns-discovery.js +195 -1
- package/dist-standalone/nonce-store.js +76 -1
- package/dist-standalone/pairing-manager.js +219 -1
- package/dist-standalone/plugin-system.js +257 -1
- package/dist-standalone/plugins/logging.js +163 -1
- package/dist-standalone/plugins/metrics.js +176 -1
- package/dist-standalone/plugins/validation.js +297 -1
- package/dist-standalone/policy.js +315 -1
- package/dist-standalone/progress-callbacks.js +576 -1
- package/dist-standalone/redis-nonce-store.js +72 -1
- package/dist-standalone/registry-middleware.js +47 -1
- package/dist-standalone/retry-strategies.js +534 -1
- package/dist-standalone/retry-transport.js +98 -1
- package/dist-standalone/runtime/browser.js +516 -1
- package/dist-standalone/runtime/edge.js +511 -1
- package/dist-standalone/runtime/react-native.js +383 -1
- package/dist-standalone/security-policy.js +239 -1
- package/dist-standalone/serialization.js +1031 -1
- package/dist-standalone/split-channel.js +219 -1
- package/dist-standalone/subscription-proof.js +224 -1
- package/dist-standalone/succession.js +142 -1
- package/dist-standalone/timeouts.js +398 -1
- package/dist-standalone/trace-context.js +414 -1
- package/dist-standalone/trace-spans.js +488 -1
- package/dist-standalone/transport.js +59 -1
- package/dist-standalone/trust-registry.js +950 -1
- package/dist-standalone/types/error-response.js +52 -1
- package/dist-standalone/vault-auth.js +174 -1
- package/dist-standalone/vault-store-loader.js +187 -1
- package/dist-standalone/verify.js +16 -1
- package/dist-standalone/version-info.js +530 -1
- package/dist-standalone/xfetch.js +335 -1
- package/package.json +4 -13
- package/share1.dat +0 -0
- package/dist-standalone/_deps/mldsa-wasm/LICENSE +0 -24
- package/dist-standalone/_deps/mldsa-wasm/package.json +0 -46
- package/dist-standalone/_deps/shared/cjs/package.json +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/package.json +0 -1
- package/dist-standalone/_deps/xchange/cjs/package.json +0 -1
- package/dist-standalone/_deps/xregistry/cjs/package.json +0 -1
- package/dist-standalone/cjs/package.json +0 -3
- package/dist-standalone/package.json +0 -10
|
@@ -1 +1,516 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Browser Runtime Compatibility Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides polyfills and runtime detection for browser environments.
|
|
5
|
+
* Ensures xBind works seamlessly in Chrome, Firefox, Safari, and service workers.
|
|
6
|
+
*
|
|
7
|
+
* @module runtime/browser
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
import { ok, err } from"../_deps/shared/index.js";
|
|
11
|
+
/**
|
|
12
|
+
* Detect the current runtime environment.
|
|
13
|
+
*
|
|
14
|
+
* @returns The detected runtime environment type
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { detectRuntime } from '@private.me/xbind/runtime/browser';
|
|
19
|
+
*
|
|
20
|
+
* const runtime = detectRuntime();
|
|
21
|
+
* console.log('Running in:', runtime);
|
|
22
|
+
* // => 'browser' | 'node' | 'service-worker' | 'web-worker' | 'unknown'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function detectRuntime() {
|
|
26
|
+
// Service Worker context
|
|
27
|
+
if (typeof self !== 'undefined' && 'ServiceWorkerGlobalScope' in self) {
|
|
28
|
+
return 'service-worker';
|
|
29
|
+
}
|
|
30
|
+
// Web Worker context
|
|
31
|
+
if (typeof self !== 'undefined' && 'WorkerGlobalScope' in self && 'importScripts' in self) {
|
|
32
|
+
return 'web-worker';
|
|
33
|
+
}
|
|
34
|
+
// Browser context (window and document available)
|
|
35
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
36
|
+
return 'browser';
|
|
37
|
+
}
|
|
38
|
+
// Node.js context (process and global available)
|
|
39
|
+
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
|
|
40
|
+
return 'node';
|
|
41
|
+
}
|
|
42
|
+
return 'unknown';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if running in a browser environment.
|
|
46
|
+
*
|
|
47
|
+
* @returns True if running in browser, service worker, or web worker
|
|
48
|
+
*/
|
|
49
|
+
export function isBrowser() {
|
|
50
|
+
const runtime = detectRuntime();
|
|
51
|
+
return runtime === 'browser' || runtime === 'service-worker' || runtime === 'web-worker';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if running in Node.js environment.
|
|
55
|
+
*
|
|
56
|
+
* @returns True if running in Node.js
|
|
57
|
+
*/
|
|
58
|
+
export function isNode() {
|
|
59
|
+
return detectRuntime() === 'node';
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if running in a service worker.
|
|
63
|
+
*
|
|
64
|
+
* @returns True if running in service worker context
|
|
65
|
+
*/
|
|
66
|
+
export function isServiceWorker() {
|
|
67
|
+
return detectRuntime() === 'service-worker';
|
|
68
|
+
}
|
|
69
|
+
/* ── Crypto Compatibility ── */
|
|
70
|
+
/**
|
|
71
|
+
* Browser-compatible random bytes generator.
|
|
72
|
+
* Uses Web Crypto API's getRandomValues.
|
|
73
|
+
*
|
|
74
|
+
* @param length - Number of random bytes to generate
|
|
75
|
+
* @returns Uint8Array of cryptographically secure random bytes
|
|
76
|
+
*
|
|
77
|
+
* @throws {Error} If Web Crypto API is not available
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { getRandomBytes } from '@private.me/xbind/runtime/browser';
|
|
82
|
+
*
|
|
83
|
+
* const nonce = getRandomBytes(16);
|
|
84
|
+
* console.log('Random nonce:', nonce);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export function getRandomBytes(length) {
|
|
88
|
+
if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
|
|
89
|
+
throw new Error('Web Crypto API not available - secure random generation impossible');
|
|
90
|
+
}
|
|
91
|
+
const bytes = new Uint8Array(length);
|
|
92
|
+
crypto.getRandomValues(bytes);
|
|
93
|
+
return bytes;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Generate a cryptographically secure random UUID.
|
|
97
|
+
* Uses Web Crypto API's randomUUID if available, falls back to manual generation.
|
|
98
|
+
*
|
|
99
|
+
* @returns UUID v4 string (e.g., "550e8400-e29b-41d4-a716-446655440000")
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* import { generateUUID } from '@private.me/xbind/runtime/browser';
|
|
104
|
+
*
|
|
105
|
+
* const id = generateUUID();
|
|
106
|
+
* console.log('Generated UUID:', id);
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export function generateUUID() {
|
|
110
|
+
// Use native randomUUID if available (modern browsers)
|
|
111
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
112
|
+
return crypto.randomUUID();
|
|
113
|
+
}
|
|
114
|
+
// Fallback: manual UUID v4 generation
|
|
115
|
+
const bytes = getRandomBytes(16);
|
|
116
|
+
// Set version (4) and variant (RFC 4122)
|
|
117
|
+
const byte6 = bytes[6];
|
|
118
|
+
const byte8 = bytes[8];
|
|
119
|
+
if (byte6 !== undefined)
|
|
120
|
+
bytes[6] = (byte6 & 0x0f) | 0x40; // Version 4
|
|
121
|
+
if (byte8 !== undefined)
|
|
122
|
+
bytes[8] = (byte8 & 0x3f) | 0x80; // Variant 10
|
|
123
|
+
// Format as UUID string
|
|
124
|
+
const hex = Array.from(bytes)
|
|
125
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
126
|
+
.join('');
|
|
127
|
+
return [
|
|
128
|
+
hex.slice(0, 8),
|
|
129
|
+
hex.slice(8, 12),
|
|
130
|
+
hex.slice(12, 16),
|
|
131
|
+
hex.slice(16, 20),
|
|
132
|
+
hex.slice(20, 32),
|
|
133
|
+
].join('-');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* LocalStorage-based implementation of BrowserStorage.
|
|
137
|
+
* Suitable for browser environments with persistent storage needs.
|
|
138
|
+
*/
|
|
139
|
+
export class LocalStorageAdapter {
|
|
140
|
+
prefix;
|
|
141
|
+
/**
|
|
142
|
+
* Create a new LocalStorage adapter.
|
|
143
|
+
*
|
|
144
|
+
* @param prefix - Key prefix to avoid collisions (default: 'xbind:')
|
|
145
|
+
*/
|
|
146
|
+
constructor(prefix = 'xbind:') {
|
|
147
|
+
this.prefix = prefix;
|
|
148
|
+
if (typeof localStorage === 'undefined') {
|
|
149
|
+
throw new Error('localStorage not available in this environment');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async setItem(key, value) {
|
|
153
|
+
const fullKey = this.prefix + key;
|
|
154
|
+
const serialized = JSON.stringify(value);
|
|
155
|
+
localStorage.setItem(fullKey, serialized);
|
|
156
|
+
}
|
|
157
|
+
async getItem(key) {
|
|
158
|
+
const fullKey = this.prefix + key;
|
|
159
|
+
const raw = localStorage.getItem(fullKey);
|
|
160
|
+
if (raw === null) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
return JSON.parse(raw);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async removeItem(key) {
|
|
171
|
+
const fullKey = this.prefix + key;
|
|
172
|
+
localStorage.removeItem(fullKey);
|
|
173
|
+
}
|
|
174
|
+
async clear() {
|
|
175
|
+
const keys = Object.keys(localStorage).filter(k => k.startsWith(this.prefix));
|
|
176
|
+
keys.forEach(k => localStorage.removeItem(k));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* IndexedDB-based implementation of BrowserStorage.
|
|
181
|
+
* Suitable for larger datasets and service workers.
|
|
182
|
+
*/
|
|
183
|
+
export class IndexedDBAdapter {
|
|
184
|
+
dbName;
|
|
185
|
+
storeName;
|
|
186
|
+
version;
|
|
187
|
+
db = null;
|
|
188
|
+
/**
|
|
189
|
+
* Create a new IndexedDB adapter.
|
|
190
|
+
*
|
|
191
|
+
* @param dbName - Database name (default: 'xbind-storage')
|
|
192
|
+
* @param storeName - Object store name (default: 'keyval')
|
|
193
|
+
* @param version - Database version (default: 1)
|
|
194
|
+
*/
|
|
195
|
+
constructor(dbName = 'xbind-storage', storeName = 'keyval', version = 1) {
|
|
196
|
+
this.dbName = dbName;
|
|
197
|
+
this.storeName = storeName;
|
|
198
|
+
this.version = version;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Initialize the database connection.
|
|
202
|
+
* Called automatically by storage operations.
|
|
203
|
+
*/
|
|
204
|
+
async ensureDB() {
|
|
205
|
+
if (this.db) {
|
|
206
|
+
return this.db;
|
|
207
|
+
}
|
|
208
|
+
return new Promise((resolve, reject) => {
|
|
209
|
+
const request = indexedDB.open(this.dbName, this.version);
|
|
210
|
+
request.onerror = () => reject(request.error);
|
|
211
|
+
request.onsuccess = () => {
|
|
212
|
+
this.db = request.result;
|
|
213
|
+
resolve(request.result);
|
|
214
|
+
};
|
|
215
|
+
request.onupgradeneeded = (event) => {
|
|
216
|
+
const db = event.target.result;
|
|
217
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
218
|
+
db.createObjectStore(this.storeName);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
async setItem(key, value) {
|
|
224
|
+
const db = await this.ensureDB();
|
|
225
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
226
|
+
const store = tx.objectStore(this.storeName);
|
|
227
|
+
return new Promise((resolve, reject) => {
|
|
228
|
+
const request = store.put(value, key);
|
|
229
|
+
request.onerror = () => reject(request.error);
|
|
230
|
+
request.onsuccess = () => resolve();
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
async getItem(key) {
|
|
234
|
+
const db = await this.ensureDB();
|
|
235
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
236
|
+
const store = tx.objectStore(this.storeName);
|
|
237
|
+
return new Promise((resolve, reject) => {
|
|
238
|
+
const request = store.get(key);
|
|
239
|
+
request.onerror = () => reject(request.error);
|
|
240
|
+
request.onsuccess = () => {
|
|
241
|
+
const value = request.result;
|
|
242
|
+
resolve(value === undefined ? null : value);
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
async removeItem(key) {
|
|
247
|
+
const db = await this.ensureDB();
|
|
248
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
249
|
+
const store = tx.objectStore(this.storeName);
|
|
250
|
+
return new Promise((resolve, reject) => {
|
|
251
|
+
const request = store.delete(key);
|
|
252
|
+
request.onerror = () => reject(request.error);
|
|
253
|
+
request.onsuccess = () => resolve();
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
async clear() {
|
|
257
|
+
const db = await this.ensureDB();
|
|
258
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
259
|
+
const store = tx.objectStore(this.storeName);
|
|
260
|
+
return new Promise((resolve, reject) => {
|
|
261
|
+
const request = store.clear();
|
|
262
|
+
request.onerror = () => reject(request.error);
|
|
263
|
+
request.onsuccess = () => resolve();
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Close the database connection.
|
|
268
|
+
* Should be called when storage is no longer needed.
|
|
269
|
+
*/
|
|
270
|
+
close() {
|
|
271
|
+
if (this.db) {
|
|
272
|
+
this.db.close();
|
|
273
|
+
this.db = null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* In-memory storage implementation for testing and ephemeral use cases.
|
|
279
|
+
*/
|
|
280
|
+
export class MemoryStorageAdapter {
|
|
281
|
+
store = new Map();
|
|
282
|
+
async setItem(key, value) {
|
|
283
|
+
this.store.set(key, value);
|
|
284
|
+
}
|
|
285
|
+
async getItem(key) {
|
|
286
|
+
const value = this.store.get(key);
|
|
287
|
+
return value === undefined ? null : value;
|
|
288
|
+
}
|
|
289
|
+
async removeItem(key) {
|
|
290
|
+
this.store.delete(key);
|
|
291
|
+
}
|
|
292
|
+
async clear() {
|
|
293
|
+
this.store.clear();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Check if WebAssembly is supported in the current environment.
|
|
298
|
+
*
|
|
299
|
+
* @returns True if WebAssembly is supported
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```typescript
|
|
303
|
+
* import { isWasmSupported } from '@private.me/xbind/runtime/browser';
|
|
304
|
+
*
|
|
305
|
+
* if (isWasmSupported()) {
|
|
306
|
+
* console.log('WASM is supported - using post-quantum crypto');
|
|
307
|
+
* } else {
|
|
308
|
+
* console.log('WASM not supported - falling back to classical crypto');
|
|
309
|
+
* }
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
export function isWasmSupported() {
|
|
313
|
+
try {
|
|
314
|
+
if (typeof WebAssembly === 'undefined') {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
// Test instantiation with minimal WASM module
|
|
318
|
+
const module = new WebAssembly.Module(new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]));
|
|
319
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
const instance = new WebAssembly.Instance(module);
|
|
323
|
+
return instance instanceof WebAssembly.Instance;
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Load and instantiate a WebAssembly module from a URL.
|
|
331
|
+
*
|
|
332
|
+
* @param url - URL to WASM module
|
|
333
|
+
* @param importObject - Optional imports for WASM module
|
|
334
|
+
* @returns Result containing the WASM instance or error
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```typescript
|
|
338
|
+
* import { loadWasmModule } from '@private.me/xbind/runtime/browser';
|
|
339
|
+
*
|
|
340
|
+
* const result = await loadWasmModule('/mldsa.wasm');
|
|
341
|
+
* if (!result.ok) {
|
|
342
|
+
* console.error('Failed to load WASM:', result.error);
|
|
343
|
+
* return;
|
|
344
|
+
* }
|
|
345
|
+
*
|
|
346
|
+
* const instance = result.value;
|
|
347
|
+
* // Use WASM exports...
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
export async function loadWasmModule(url, importObject) {
|
|
351
|
+
if (!isWasmSupported()) {
|
|
352
|
+
return err('WASM_NOT_SUPPORTED');
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
// Use streaming compilation if available (faster)
|
|
356
|
+
if (typeof WebAssembly.instantiateStreaming !== 'undefined') {
|
|
357
|
+
const response = await fetch(url);
|
|
358
|
+
const result = await WebAssembly.instantiateStreaming(response, importObject);
|
|
359
|
+
return ok(result.instance);
|
|
360
|
+
}
|
|
361
|
+
// Fallback: fetch as ArrayBuffer then compile
|
|
362
|
+
const response = await fetch(url);
|
|
363
|
+
const buffer = await response.arrayBuffer();
|
|
364
|
+
const result = await WebAssembly.instantiate(buffer, importObject);
|
|
365
|
+
return ok(result.instance);
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
console.error('WASM load failed:', error);
|
|
369
|
+
return err('WASM_LOAD_FAILED');
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Detect browser capabilities and feature support.
|
|
374
|
+
*
|
|
375
|
+
* @returns Object describing available browser features
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* import { detectCapabilities } from '@private.me/xbind/runtime/browser';
|
|
380
|
+
*
|
|
381
|
+
* const caps = await detectCapabilities();
|
|
382
|
+
*
|
|
383
|
+
* if (!caps.webCrypto) {
|
|
384
|
+
* throw new Error('WebCrypto required for xBind');
|
|
385
|
+
* }
|
|
386
|
+
*
|
|
387
|
+
* if (!caps.ed25519) {
|
|
388
|
+
* console.warn('Ed25519 not supported - using polyfill');
|
|
389
|
+
* }
|
|
390
|
+
*
|
|
391
|
+
* if (caps.serviceWorker) {
|
|
392
|
+
* console.log('Service workers supported - can run in background');
|
|
393
|
+
* }
|
|
394
|
+
* ```
|
|
395
|
+
*/
|
|
396
|
+
export async function detectCapabilities() {
|
|
397
|
+
// Basic feature detection
|
|
398
|
+
const capabilities = {
|
|
399
|
+
webCrypto: typeof crypto !== 'undefined' && !!crypto.subtle,
|
|
400
|
+
subtleCrypto: typeof crypto !== 'undefined' && !!crypto.subtle,
|
|
401
|
+
ed25519: false,
|
|
402
|
+
x25519: false,
|
|
403
|
+
wasm: isWasmSupported(),
|
|
404
|
+
indexedDB: typeof indexedDB !== 'undefined',
|
|
405
|
+
localStorage: typeof localStorage !== 'undefined',
|
|
406
|
+
serviceWorker: typeof navigator !== 'undefined' && 'serviceWorker' in navigator,
|
|
407
|
+
webWorker: typeof Worker !== 'undefined',
|
|
408
|
+
fetch: typeof fetch !== 'undefined',
|
|
409
|
+
textEncoding: typeof TextEncoder !== 'undefined' && typeof TextDecoder !== 'undefined',
|
|
410
|
+
};
|
|
411
|
+
// Test Ed25519 support (async)
|
|
412
|
+
if (capabilities.subtleCrypto) {
|
|
413
|
+
try {
|
|
414
|
+
await crypto.subtle.generateKey({ name: 'Ed25519' }, true, ['sign', 'verify']);
|
|
415
|
+
capabilities.ed25519 = true;
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
capabilities.ed25519 = false;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
// Test X25519 support (async)
|
|
422
|
+
if (capabilities.subtleCrypto) {
|
|
423
|
+
try {
|
|
424
|
+
await crypto.subtle.generateKey({ name: 'X25519' }, true, ['deriveBits']);
|
|
425
|
+
capabilities.x25519 = true;
|
|
426
|
+
}
|
|
427
|
+
catch {
|
|
428
|
+
capabilities.x25519 = false;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return capabilities;
|
|
432
|
+
}
|
|
433
|
+
/* ── Polyfills ── */
|
|
434
|
+
/**
|
|
435
|
+
* Install Node.js compatibility shims for browser environments.
|
|
436
|
+
* Only installs missing APIs - does not override existing implementations.
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* ```typescript
|
|
440
|
+
* import { installNodePolyfills } from '@private.me/xbind/runtime/browser';
|
|
441
|
+
*
|
|
442
|
+
* // Install polyfills at application startup
|
|
443
|
+
* installNodePolyfills();
|
|
444
|
+
*
|
|
445
|
+
* // Now Node.js-style code works in browser
|
|
446
|
+
* import { randomBytes } from 'crypto'; // Works!
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
export function installNodePolyfills() {
|
|
450
|
+
// Only install in browser environments
|
|
451
|
+
if (!isBrowser()) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// Polyfill process.env
|
|
455
|
+
if (typeof globalThis.process === 'undefined') {
|
|
456
|
+
globalThis.process = {
|
|
457
|
+
env: {},
|
|
458
|
+
versions: {},
|
|
459
|
+
nextTick: (fn) => Promise.resolve().then(fn),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
// Polyfill Buffer (minimal implementation)
|
|
463
|
+
if (typeof globalThis.Buffer === 'undefined') {
|
|
464
|
+
globalThis.Buffer = {
|
|
465
|
+
from: (data, encoding) => {
|
|
466
|
+
if (data instanceof Uint8Array)
|
|
467
|
+
return data;
|
|
468
|
+
if (encoding === 'base64') {
|
|
469
|
+
const binary = atob(data);
|
|
470
|
+
return new Uint8Array(binary.split('').map(c => c.charCodeAt(0)));
|
|
471
|
+
}
|
|
472
|
+
return new TextEncoder().encode(data);
|
|
473
|
+
},
|
|
474
|
+
alloc: (size) => new Uint8Array(size),
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
// Polyfill global
|
|
478
|
+
if (typeof globalThis.global === 'undefined') {
|
|
479
|
+
globalThis.global = globalThis;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Default service worker configuration.
|
|
484
|
+
*/
|
|
485
|
+
export const DEFAULT_SERVICE_WORKER_CONFIG = {
|
|
486
|
+
wasmCacheStrategy: 'cache-first',
|
|
487
|
+
wasmCacheMaxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
488
|
+
enableBackgroundSync: true,
|
|
489
|
+
};
|
|
490
|
+
/**
|
|
491
|
+
* Initialize xBind for service worker environment.
|
|
492
|
+
* Sets up caching strategies and background sync handlers.
|
|
493
|
+
*
|
|
494
|
+
* @param config - Service worker configuration
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* // In your service worker (sw.js):
|
|
499
|
+
* import { initServiceWorker } from '@private.me/xbind/runtime/browser';
|
|
500
|
+
*
|
|
501
|
+
* initServiceWorker({
|
|
502
|
+
* wasmCacheStrategy: 'cache-first',
|
|
503
|
+
* wasmCacheMaxAge: 24 * 60 * 60 * 1000,
|
|
504
|
+
* enableBackgroundSync: true,
|
|
505
|
+
* });
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
508
|
+
export function initServiceWorker(config = {}) {
|
|
509
|
+
const fullConfig = { ...DEFAULT_SERVICE_WORKER_CONFIG, ...config };
|
|
510
|
+
if (!isServiceWorker()) {
|
|
511
|
+
throw new Error('initServiceWorker() must be called from service worker context');
|
|
512
|
+
}
|
|
513
|
+
// Store config for use by other service worker handlers
|
|
514
|
+
self.__xbind_sw_config = fullConfig;
|
|
515
|
+
console.log('[xBind] Service worker initialized with config:', fullConfig);
|
|
516
|
+
}
|