@enbox/auth 0.3.1
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/dist/esm/auth-manager.js +496 -0
- package/dist/esm/auth-manager.js.map +1 -0
- package/dist/esm/events.js +65 -0
- package/dist/esm/events.js.map +1 -0
- package/dist/esm/flows/dwn-discovery.js +281 -0
- package/dist/esm/flows/dwn-discovery.js.map +1 -0
- package/dist/esm/flows/dwn-registration.js +122 -0
- package/dist/esm/flows/dwn-registration.js.map +1 -0
- package/dist/esm/flows/import-identity.js +175 -0
- package/dist/esm/flows/import-identity.js.map +1 -0
- package/dist/esm/flows/local-connect.js +141 -0
- package/dist/esm/flows/local-connect.js.map +1 -0
- package/dist/esm/flows/session-restore.js +109 -0
- package/dist/esm/flows/session-restore.js.map +1 -0
- package/dist/esm/flows/wallet-connect.js +199 -0
- package/dist/esm/flows/wallet-connect.js.map +1 -0
- package/dist/esm/identity-session.js +33 -0
- package/dist/esm/identity-session.js.map +1 -0
- package/dist/esm/index.js +50 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/storage/storage.js +152 -0
- package/dist/esm/storage/storage.js.map +1 -0
- package/dist/esm/types.js +30 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/vault/vault-manager.js +95 -0
- package/dist/esm/vault/vault-manager.js.map +1 -0
- package/dist/types/auth-manager.d.ts +176 -0
- package/dist/types/auth-manager.d.ts.map +1 -0
- package/dist/types/events.d.ts +36 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/flows/dwn-discovery.d.ts +157 -0
- package/dist/types/flows/dwn-discovery.d.ts.map +1 -0
- package/dist/types/flows/dwn-registration.d.ts +39 -0
- package/dist/types/flows/dwn-registration.d.ts.map +1 -0
- package/dist/types/flows/import-identity.d.ts +35 -0
- package/dist/types/flows/import-identity.d.ts.map +1 -0
- package/dist/types/flows/local-connect.d.ts +29 -0
- package/dist/types/flows/local-connect.d.ts.map +1 -0
- package/dist/types/flows/session-restore.d.ts +27 -0
- package/dist/types/flows/session-restore.d.ts.map +1 -0
- package/dist/types/flows/wallet-connect.d.ts +44 -0
- package/dist/types/flows/wallet-connect.d.ts.map +1 -0
- package/dist/types/identity-session.d.ts +52 -0
- package/dist/types/identity-session.d.ts.map +1 -0
- package/dist/types/index.d.ts +45 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/storage/storage.d.ts +54 -0
- package/dist/types/storage/storage.d.ts.map +1 -0
- package/dist/types/types.d.ts +312 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/vault/vault-manager.d.ts +57 -0
- package/dist/types/vault/vault-manager.d.ts.map +1 -0
- package/package.json +71 -0
- package/src/auth-manager.ts +569 -0
- package/src/events.ts +66 -0
- package/src/flows/dwn-discovery.ts +300 -0
- package/src/flows/dwn-registration.ts +157 -0
- package/src/flows/import-identity.ts +217 -0
- package/src/flows/local-connect.ts +171 -0
- package/src/flows/session-restore.ts +135 -0
- package/src/flows/wallet-connect.ts +225 -0
- package/src/identity-session.ts +65 -0
- package/src/index.ts +89 -0
- package/src/storage/storage.ts +136 -0
- package/src/types.ts +388 -0
- package/src/vault/vault-manager.ts +89 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage adapter implementations for session persistence.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
import { Level } from 'level';
|
|
15
|
+
/**
|
|
16
|
+
* Browser storage adapter backed by `localStorage`.
|
|
17
|
+
*
|
|
18
|
+
* All keys are prefixed to avoid collisions with other localStorage users.
|
|
19
|
+
*/
|
|
20
|
+
export class BrowserStorage {
|
|
21
|
+
constructor(prefix = 'enbox:') {
|
|
22
|
+
this._prefix = prefix;
|
|
23
|
+
}
|
|
24
|
+
get(key) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
return globalThis.localStorage.getItem(this._prefix + key);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
set(key, value) {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
globalThis.localStorage.setItem(this._prefix + key, value);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
remove(key) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
globalThis.localStorage.removeItem(this._prefix + key);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
clear() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const keysToRemove = [];
|
|
42
|
+
for (let i = 0; i < globalThis.localStorage.length; i++) {
|
|
43
|
+
const key = globalThis.localStorage.key(i);
|
|
44
|
+
if (key === null || key === void 0 ? void 0 : key.startsWith(this._prefix)) {
|
|
45
|
+
keysToRemove.push(key);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const key of keysToRemove) {
|
|
49
|
+
globalThis.localStorage.removeItem(key);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* In-memory storage adapter for testing or environments without persistence.
|
|
56
|
+
*/
|
|
57
|
+
export class MemoryStorage {
|
|
58
|
+
constructor() {
|
|
59
|
+
this._store = new Map();
|
|
60
|
+
}
|
|
61
|
+
get(key) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
var _a;
|
|
64
|
+
return (_a = this._store.get(key)) !== null && _a !== void 0 ? _a : null;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
set(key, value) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
this._store.set(key, value);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
remove(key) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
this._store.delete(key);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
clear() {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
this._store.clear();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* LevelDB-backed storage adapter for Node / CLI environments.
|
|
85
|
+
*
|
|
86
|
+
* Uses the `level` package (v8), which selects `classic-level` (LevelDB)
|
|
87
|
+
* in Node and `browser-level` (IndexedDB) in browsers. Level auto-opens
|
|
88
|
+
* on construction and queues operations until ready, so no explicit
|
|
89
|
+
* `open()` call is required.
|
|
90
|
+
*/
|
|
91
|
+
export class LevelStorage {
|
|
92
|
+
constructor(dataPath = 'DATA/AGENT/AUTH_STORE') {
|
|
93
|
+
this._db = new Level(dataPath);
|
|
94
|
+
}
|
|
95
|
+
get(key) {
|
|
96
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
try {
|
|
98
|
+
return yield this._db.get(key);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const e = error;
|
|
102
|
+
if (e.code === 'LEVEL_NOT_FOUND') {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
set(key, value) {
|
|
110
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
yield this._db.put(key, value);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
remove(key) {
|
|
115
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
116
|
+
try {
|
|
117
|
+
yield this._db.del(key);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const e = error;
|
|
121
|
+
// Silently ignore deleting a key that doesn't exist.
|
|
122
|
+
if (e.code !== 'LEVEL_NOT_FOUND') {
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
clear() {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
yield this._db.clear();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** Close the underlying LevelDB database. */
|
|
134
|
+
close() {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
yield this._db.close();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Detect the runtime environment and return an appropriate default storage adapter.
|
|
142
|
+
*
|
|
143
|
+
* - If `localStorage` is available → `BrowserStorage`
|
|
144
|
+
* - Otherwise → `LevelStorage` (persistent on disk via LevelDB)
|
|
145
|
+
*/
|
|
146
|
+
export function createDefaultStorage() {
|
|
147
|
+
if (typeof globalThis.localStorage !== 'undefined') {
|
|
148
|
+
return new BrowserStorage();
|
|
149
|
+
}
|
|
150
|
+
return new LevelStorage();
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/storage/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;;;;;;;;;;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAI9B;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAGzB,YAAY,MAAM,GAAG,QAAQ;QAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAEK,GAAG,CAAC,GAAW;;YACnB,OAAO,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;QAC7D,CAAC;KAAA;IAEK,GAAG,CAAC,GAAW,EAAE,KAAa;;YAClC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7D,CAAC;KAAA;IAEK,MAAM,CAAC,GAAW;;YACtB,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;QACzD,CAAC;KAAA;IAEK,KAAK;;YACT,MAAM,YAAY,GAAa,EAAE,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxD,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC3C,IAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBAClC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;gBAC/B,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;KAAA;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAa;IAA1B;QACmB,WAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAiBtD,CAAC;IAfO,GAAG,CAAC,GAAW;;;YACnB,OAAO,MAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,mCAAI,IAAI,CAAC;QACtC,CAAC;KAAA;IAEK,GAAG,CAAC,GAAW,EAAE,KAAa;;YAClC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;KAAA;IAEK,MAAM,CAAC,GAAW;;YACtB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;KAAA;IAEK,KAAK;;YACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;KAAA;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IAGvB,YAAY,QAAQ,GAAG,uBAAuB;QAC5C,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,CAAiB,QAAQ,CAAC,CAAC;IACjD,CAAC;IAEK,GAAG,CAAC,GAAW;;YACnB,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,GAAG,KAA0B,CAAC;gBACrC,IAAI,CAAC,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACjC,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KAAA;IAEK,GAAG,CAAC,GAAW,EAAE,KAAa;;YAClC,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;KAAA;IAEK,MAAM,CAAC,GAAW;;YACtB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,GAAG,KAA0B,CAAC;gBACrC,qDAAqD;gBACrD,IAAI,CAAC,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACjC,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;KAAA;IAEK,KAAK;;YACT,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;KAAA;IAED,6CAA6C;IACvC,KAAK;;YACT,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;KAAA;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB;IAClC,IAAI,OAAO,UAAU,CAAC,YAAY,KAAK,WAAW,EAAE,CAAC;QACnD,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,IAAI,YAAY,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @enbox/auth
|
|
3
|
+
* Public types for the authentication and identity management SDK.
|
|
4
|
+
*/
|
|
5
|
+
// ─── Internal helpers ────────────────────────────────────────────
|
|
6
|
+
/** The insecure default password used when none is provided. */
|
|
7
|
+
export const INSECURE_DEFAULT_PASSWORD = 'insecure-static-phrase';
|
|
8
|
+
/**
|
|
9
|
+
* Storage keys used by the auth manager for session persistence.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export const STORAGE_KEYS = {
|
|
13
|
+
/** Whether a session was previously established. */
|
|
14
|
+
PREVIOUSLY_CONNECTED: 'enbox:auth:previouslyConnected',
|
|
15
|
+
/** The DID URI of the last active identity. */
|
|
16
|
+
ACTIVE_IDENTITY: 'enbox:auth:activeIdentity',
|
|
17
|
+
/** The delegate DID URI (for wallet-connected sessions). */
|
|
18
|
+
DELEGATE_DID: 'enbox:auth:delegateDid',
|
|
19
|
+
/** The connected DID (for wallet-connected sessions). */
|
|
20
|
+
CONNECTED_DID: 'enbox:auth:connectedDid',
|
|
21
|
+
/**
|
|
22
|
+
* The base URL of the local DWN server discovered via the `dwn://register`
|
|
23
|
+
* browser redirect flow. Persisted so subsequent page loads can skip the
|
|
24
|
+
* redirect and inject the endpoint directly.
|
|
25
|
+
*
|
|
26
|
+
* @see https://github.com/enboxorg/enbox/issues/589
|
|
27
|
+
*/
|
|
28
|
+
LOCAL_DWN_ENDPOINT: 'enbox:auth:localDwnEndpoint',
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkWH,oEAAoE;AAEpE,gEAAgE;AAChE,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAElE;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,oDAAoD;IACpD,oBAAoB,EAAE,gCAAgC;IAEtD,+CAA+C;IAC/C,eAAe,EAAE,2BAA2B;IAE5C,4DAA4D;IAC5D,YAAY,EAAE,wBAAwB;IAEtC,yDAAyD;IACzD,aAAa,EAAE,yBAAyB;IAExC;;;;;;OAMG;IACH,kBAAkB,EAAE,6BAA6B;CACzC,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VaultManager wraps {@link HdIdentityVault} with a high-level API
|
|
3
|
+
* and emits events on lock/unlock.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Manages the encrypted identity vault lifecycle.
|
|
17
|
+
*
|
|
18
|
+
* The vault stores the agent's DID and content encryption key (CEK),
|
|
19
|
+
* protected by a user password using PBES2-HS512+A256KW with a 210K
|
|
20
|
+
* iteration work factor. The vault supports HD key derivation from
|
|
21
|
+
* a BIP-39 mnemonic for recovery.
|
|
22
|
+
*/
|
|
23
|
+
export class VaultManager {
|
|
24
|
+
constructor(vault, emitter) {
|
|
25
|
+
this._vault = vault;
|
|
26
|
+
this._emitter = emitter;
|
|
27
|
+
}
|
|
28
|
+
/** The underlying vault instance (for advanced usage). */
|
|
29
|
+
get raw() {
|
|
30
|
+
return this._vault;
|
|
31
|
+
}
|
|
32
|
+
/** Whether the vault has been initialized (has encrypted data). */
|
|
33
|
+
isInitialized() {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
return this._vault.isInitialized();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Whether the vault is currently locked (synchronous check). */
|
|
39
|
+
get isLocked() {
|
|
40
|
+
return this._vault.isLocked();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Unlock the vault with the given password.
|
|
44
|
+
* Decrypts the CEK into memory so the agent DID can be retrieved.
|
|
45
|
+
*
|
|
46
|
+
* @throws If the password is incorrect or vault is not initialized.
|
|
47
|
+
*/
|
|
48
|
+
unlock(password) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
yield this._vault.unlock({ password });
|
|
51
|
+
this._emitter.emit('vault-unlocked', {});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Lock the vault, clearing the CEK from memory.
|
|
56
|
+
* After locking, the password must be provided again to unlock.
|
|
57
|
+
*/
|
|
58
|
+
lock() {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
yield this._vault.lock();
|
|
61
|
+
this._emitter.emit('vault-locked', {});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Change the vault password. Re-encrypts the CEK with the new password.
|
|
66
|
+
*
|
|
67
|
+
* @throws If the old password is incorrect or vault is locked.
|
|
68
|
+
*/
|
|
69
|
+
changePassword(oldPassword, newPassword) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
yield this._vault.changePassword({ oldPassword, newPassword });
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a backup of the vault.
|
|
76
|
+
*
|
|
77
|
+
* @throws If the vault is not initialized or is locked.
|
|
78
|
+
*/
|
|
79
|
+
backup() {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
return this._vault.backup();
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Restore the vault from a backup.
|
|
86
|
+
*
|
|
87
|
+
* @throws If the password doesn't match the backup's encryption.
|
|
88
|
+
*/
|
|
89
|
+
restore(backup, password) {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
yield this._vault.restore({ backup, password });
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=vault-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-manager.js","sourceRoot":"","sources":["../../../src/vault/vault-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;;;;;;;AAMH;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IAIvB,YAAY,KAAsB,EAAE,OAAyB;QAC3D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,0DAA0D;IAC1D,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,mEAAmE;IAC7D,aAAa;;YACjB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QACrC,CAAC;KAAA;IAED,iEAAiE;IACjE,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED;;;;;OAKG;IACG,MAAM,CAAC,QAAgB;;YAC3B,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;KAAA;IAED;;;OAGG;IACG,IAAI;;YACR,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACzC,CAAC;KAAA;IAED;;;;OAIG;IACG,cAAc,CAAC,WAAmB,EAAE,WAAmB;;YAC3D,MAAM,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;QACjE,CAAC;KAAA;IAED;;;;OAIG;IACG,MAAM;;YACV,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,CAAC;KAAA;IAED;;;;OAIG;IACG,OAAO,CAAC,MAA2B,EAAE,QAAgB;;YACzD,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClD,CAAC;KAAA;CACF"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuthManager — the primary entry point for `@enbox/auth`.
|
|
3
|
+
*
|
|
4
|
+
* Replaces `Enbox.connect()` (formerly `Web5.connect()`) with a composable,
|
|
5
|
+
* multi-identity-aware auth system that works in both browser and CLI environments.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { EnboxUserAgent } from '@enbox/agent';
|
|
9
|
+
import type { PortableIdentity } from '@enbox/agent';
|
|
10
|
+
import { AuthSession } from './identity-session.js';
|
|
11
|
+
import { VaultManager } from './vault/vault-manager.js';
|
|
12
|
+
import type { AuthEvent, AuthEventHandler, AuthManagerOptions, AuthState, DisconnectOptions, IdentityInfo, ImportFromPhraseOptions, ImportFromPortableOptions, LocalConnectOptions, RestoreSessionOptions, WalletConnectOptions } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* The primary entry point for authentication and identity management.
|
|
15
|
+
*
|
|
16
|
+
* `AuthManager` replaces `Enbox.connect()` (formerly `Web5.connect()`) with a composable, multi-identity-aware
|
|
17
|
+
* system. It manages vault lifecycle, identity CRUD, session persistence,
|
|
18
|
+
* and all connection flows (local DID, wallet connect, import, restore).
|
|
19
|
+
*
|
|
20
|
+
* @example Basic usage
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { AuthManager } from '@enbox/auth';
|
|
23
|
+
*
|
|
24
|
+
* const auth = await AuthManager.create({ sync: '15s' });
|
|
25
|
+
*
|
|
26
|
+
* // First time: creates a new identity
|
|
27
|
+
* // Subsequent times: restores the previous session
|
|
28
|
+
* const session = await auth.restoreSession() ?? await auth.connect();
|
|
29
|
+
*
|
|
30
|
+
* // session.agent — the authenticated Enbox agent
|
|
31
|
+
* // session.did — the connected DID URI
|
|
32
|
+
* // session.identity — metadata about the connected identity
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Wallet connect
|
|
36
|
+
* ```ts
|
|
37
|
+
* const session = await auth.walletConnect({
|
|
38
|
+
* displayName: 'My App',
|
|
39
|
+
* connectServerUrl: 'https://enbox-dwn.fly.dev/connect',
|
|
40
|
+
* permissionRequests: [{ protocolDefinition: MyProtocol.definition }],
|
|
41
|
+
* onWalletUriReady: (uri) => showQRCode(uri),
|
|
42
|
+
* validatePin: () => promptUserForPin(),
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare class AuthManager {
|
|
47
|
+
private _userAgent;
|
|
48
|
+
private _emitter;
|
|
49
|
+
private _storage;
|
|
50
|
+
private _vault;
|
|
51
|
+
private _session;
|
|
52
|
+
private _state;
|
|
53
|
+
private _isConnecting;
|
|
54
|
+
private _defaultPassword?;
|
|
55
|
+
private _defaultSync?;
|
|
56
|
+
private _defaultDwnEndpoints?;
|
|
57
|
+
private _registration?;
|
|
58
|
+
private constructor();
|
|
59
|
+
/**
|
|
60
|
+
* Create a new AuthManager instance.
|
|
61
|
+
*
|
|
62
|
+
* When a pre-built `agent` is provided, it is used as-is and
|
|
63
|
+
* `dataPath`, `agentVault`, and `localDwnStrategy` are ignored.
|
|
64
|
+
* Otherwise, a new `EnboxUserAgent` is created with the given options.
|
|
65
|
+
*
|
|
66
|
+
* @param options - Configuration options for the auth manager.
|
|
67
|
+
* @returns A ready-to-use AuthManager instance.
|
|
68
|
+
*/
|
|
69
|
+
static create(options?: AuthManagerOptions): Promise<AuthManager>;
|
|
70
|
+
/**
|
|
71
|
+
* Create or reconnect a local identity.
|
|
72
|
+
*
|
|
73
|
+
* On first use, this creates a new vault, agent DID, and user identity.
|
|
74
|
+
* On subsequent uses, it unlocks the vault and reconnects.
|
|
75
|
+
*
|
|
76
|
+
* @param options - Optional overrides for password, sync, DWN endpoints.
|
|
77
|
+
* @returns An active AuthSession.
|
|
78
|
+
* @throws If a connection attempt is already in progress.
|
|
79
|
+
*/
|
|
80
|
+
connect(options?: LocalConnectOptions): Promise<AuthSession>;
|
|
81
|
+
/**
|
|
82
|
+
* Connect to an external wallet via the OIDC/QR relay protocol.
|
|
83
|
+
*
|
|
84
|
+
* This runs the full WalletConnect flow: generates a URI for QR display,
|
|
85
|
+
* validates the PIN, imports the delegated DID, and processes grants.
|
|
86
|
+
*
|
|
87
|
+
* @param options - Wallet connect configuration.
|
|
88
|
+
* @returns An active AuthSession with delegated permissions.
|
|
89
|
+
* @throws If sync is disabled (required for wallet connect).
|
|
90
|
+
* @throws If a connection attempt is already in progress.
|
|
91
|
+
*/
|
|
92
|
+
walletConnect(options: WalletConnectOptions): Promise<AuthSession>;
|
|
93
|
+
/**
|
|
94
|
+
* Import an identity from a BIP-39 recovery phrase.
|
|
95
|
+
*
|
|
96
|
+
* This re-derives the vault and agent DID from the mnemonic,
|
|
97
|
+
* recovering the identity on this device.
|
|
98
|
+
*/
|
|
99
|
+
importFromPhrase(options: ImportFromPhraseOptions): Promise<AuthSession>;
|
|
100
|
+
/**
|
|
101
|
+
* Import an identity from a PortableIdentity JSON object.
|
|
102
|
+
*
|
|
103
|
+
* The portable identity contains the DID's private keys and metadata.
|
|
104
|
+
*/
|
|
105
|
+
importFromPortable(options: ImportFromPortableOptions): Promise<AuthSession>;
|
|
106
|
+
/**
|
|
107
|
+
* Restore a previous session from persisted storage.
|
|
108
|
+
*
|
|
109
|
+
* Returns `undefined` if no previous session exists.
|
|
110
|
+
* This replaces the manual `previouslyConnected` localStorage pattern.
|
|
111
|
+
*/
|
|
112
|
+
restoreSession(options?: RestoreSessionOptions): Promise<AuthSession | undefined>;
|
|
113
|
+
/** The current active session, or `undefined` if not connected. */
|
|
114
|
+
get session(): AuthSession | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* Disconnect the current session.
|
|
117
|
+
*
|
|
118
|
+
* @param options - Disconnect options.
|
|
119
|
+
* @param options.clearStorage - If `true`, performs a nuclear wipe:
|
|
120
|
+
* clears all persisted data (localStorage + IndexedDB). Default: `false`.
|
|
121
|
+
* @param options.timeout - Milliseconds to wait for sync to complete.
|
|
122
|
+
*/
|
|
123
|
+
disconnect(options?: DisconnectOptions): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* List all stored identities.
|
|
126
|
+
*
|
|
127
|
+
* Each identity has a DID URI, name, and optional connected DID
|
|
128
|
+
* (for wallet-connected/delegated identities).
|
|
129
|
+
*/
|
|
130
|
+
listIdentities(): Promise<IdentityInfo[]>;
|
|
131
|
+
/**
|
|
132
|
+
* Switch the active identity.
|
|
133
|
+
*
|
|
134
|
+
* Disconnects the current session (if any) and creates a new session
|
|
135
|
+
* for the specified identity.
|
|
136
|
+
*/
|
|
137
|
+
switchIdentity(didUri: string): Promise<AuthSession>;
|
|
138
|
+
/**
|
|
139
|
+
* Delete a stored identity.
|
|
140
|
+
*
|
|
141
|
+
* If the identity is currently active, it will be disconnected first.
|
|
142
|
+
*
|
|
143
|
+
* @throws If the identity is not found.
|
|
144
|
+
*/
|
|
145
|
+
deleteIdentity(didUri: string): Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Export an identity as a PortableIdentity JSON object.
|
|
148
|
+
*
|
|
149
|
+
* This can be used for backup or transferring the identity
|
|
150
|
+
* to another device.
|
|
151
|
+
*/
|
|
152
|
+
exportIdentity(didUri: string): Promise<PortableIdentity>;
|
|
153
|
+
/** Access the vault manager for lock/unlock/backup operations. */
|
|
154
|
+
get vault(): VaultManager;
|
|
155
|
+
/**
|
|
156
|
+
* Subscribe to an auth lifecycle event.
|
|
157
|
+
*
|
|
158
|
+
* @param event - The event name.
|
|
159
|
+
* @param handler - The event handler.
|
|
160
|
+
* @returns An unsubscribe function.
|
|
161
|
+
*/
|
|
162
|
+
on<E extends AuthEvent>(event: E, handler: AuthEventHandler<E>): () => void;
|
|
163
|
+
/** The current auth state. */
|
|
164
|
+
get state(): AuthState;
|
|
165
|
+
/** Whether an active session exists. */
|
|
166
|
+
get isConnected(): boolean;
|
|
167
|
+
/** Whether the vault is currently locked. */
|
|
168
|
+
get isLocked(): boolean;
|
|
169
|
+
/** Whether a connection attempt is in progress. */
|
|
170
|
+
get isConnecting(): boolean;
|
|
171
|
+
/** The underlying EnboxUserAgent (for advanced usage). */
|
|
172
|
+
get agent(): EnboxUserAgent;
|
|
173
|
+
private _setState;
|
|
174
|
+
private _guardConcurrency;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=auth-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../../src/auth-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed event emitter for auth state changes.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type { AuthEvent, AuthEventHandler, AuthEventMap } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* A minimal, type-safe event emitter for auth lifecycle events.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```ts
|
|
11
|
+
* const emitter = new AuthEventEmitter();
|
|
12
|
+
* const unsub = emitter.on('state-change', ({ previous, current }) => {
|
|
13
|
+
* console.log(`State: ${previous} → ${current}`);
|
|
14
|
+
* });
|
|
15
|
+
* emitter.emit('state-change', { previous: 'locked', current: 'unlocked' });
|
|
16
|
+
* unsub(); // stop listening
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class AuthEventEmitter {
|
|
20
|
+
private _listeners;
|
|
21
|
+
/**
|
|
22
|
+
* Subscribe to an event. Returns an unsubscribe function.
|
|
23
|
+
*/
|
|
24
|
+
on<E extends AuthEvent>(event: E, handler: AuthEventHandler<E>): () => void;
|
|
25
|
+
/**
|
|
26
|
+
* Emit an event to all registered listeners.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
emit<E extends AuthEvent>(event: E, payload: AuthEventMap[E]): void;
|
|
30
|
+
/**
|
|
31
|
+
* Remove all listeners for all events.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
removeAllListeners(): void;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAA0D;IAE5E;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAgB3E;;;OAGG;IACH,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAYnE;;;OAGG;IACH,kBAAkB,IAAI,IAAI;CAG3B"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local DWN discovery integration for browser and CLI environments.
|
|
3
|
+
*
|
|
4
|
+
* This module bridges the local DWN discovery mechanisms (implemented in
|
|
5
|
+
* `@enbox/agent`) with the `@enbox/auth` storage, session lifecycle, and
|
|
6
|
+
* event system.
|
|
7
|
+
*
|
|
8
|
+
* ## Discovery channels (browser, highest to lowest priority)
|
|
9
|
+
*
|
|
10
|
+
* 1. **URL fragment payload** — A `dwn://register` redirect just landed
|
|
11
|
+
* on the page with the endpoint in `#`. Highest priority because it's
|
|
12
|
+
* fresh and explicit.
|
|
13
|
+
* 2. **Persisted endpoint** (localStorage) — A previously discovered
|
|
14
|
+
* endpoint restored and re-validated via `GET /info`.
|
|
15
|
+
* 3. **Agent-level discovery** (transparent, runs on every `sendRequest`)
|
|
16
|
+
* — `~/.enbox/dwn.json` discovery file (Node/Bun only; skipped in
|
|
17
|
+
* browsers) and sequential port probing on `127.0.0.1:{3000,55500–55509}`.
|
|
18
|
+
* This channel works even if the browser-specific functions here
|
|
19
|
+
* return `false`.
|
|
20
|
+
*
|
|
21
|
+
* ## Discovery channels (CLI / native, all transparent)
|
|
22
|
+
*
|
|
23
|
+
* In Node/Bun environments, all discovery happens automatically inside
|
|
24
|
+
* `AgentDwnApi.getLocalDwnEndpoint()`. The browser-specific functions
|
|
25
|
+
* in this module (`checkUrlForDwnDiscoveryPayload`, `requestLocalDwnDiscovery`)
|
|
26
|
+
* are not needed — the agent reads `~/.enbox/dwn.json` and probes ports
|
|
27
|
+
* on its own.
|
|
28
|
+
*
|
|
29
|
+
* @see https://github.com/enboxorg/enbox/issues/589
|
|
30
|
+
* @module
|
|
31
|
+
*/
|
|
32
|
+
import type { EnboxUserAgent } from '@enbox/agent';
|
|
33
|
+
import type { AuthEventEmitter } from '../events.js';
|
|
34
|
+
import type { StorageAdapter } from '../types.js';
|
|
35
|
+
/**
|
|
36
|
+
* Check the current page URL for a `DwnDiscoveryPayload` in the fragment.
|
|
37
|
+
*
|
|
38
|
+
* This is called once at the start of a connection flow to detect whether
|
|
39
|
+
* the user was just redirected back from a `dwn://register` handler. If a
|
|
40
|
+
* valid payload is found, the endpoint is persisted and the fragment is
|
|
41
|
+
* cleared to prevent double-reads.
|
|
42
|
+
*
|
|
43
|
+
* @returns The discovered endpoint string, or `undefined` if no payload
|
|
44
|
+
* was found in the URL.
|
|
45
|
+
*/
|
|
46
|
+
export declare function checkUrlForDwnDiscoveryPayload(): string | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Persist a discovered local DWN endpoint in auth storage.
|
|
49
|
+
*
|
|
50
|
+
* @param storage - The auth storage adapter.
|
|
51
|
+
* @param endpoint - The local DWN server base URL.
|
|
52
|
+
*/
|
|
53
|
+
export declare function persistLocalDwnEndpoint(storage: StorageAdapter, endpoint: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Clear the persisted local DWN endpoint from auth storage.
|
|
56
|
+
*
|
|
57
|
+
* Call this when the cached endpoint is found to be stale (server no
|
|
58
|
+
* longer running).
|
|
59
|
+
*
|
|
60
|
+
* @param storage - The auth storage adapter.
|
|
61
|
+
*/
|
|
62
|
+
export declare function clearLocalDwnEndpoint(storage: StorageAdapter): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Restore a previously persisted local DWN endpoint and inject it into the
|
|
65
|
+
* agent's discovery cache.
|
|
66
|
+
*
|
|
67
|
+
* The endpoint is validated by the agent (via `GET /info`) before being
|
|
68
|
+
* accepted. If validation fails, the stale entry is removed from storage.
|
|
69
|
+
*
|
|
70
|
+
* @param agent - The running EnboxUserAgent.
|
|
71
|
+
* @param storage - The auth storage adapter.
|
|
72
|
+
* @returns `true` if an endpoint was restored and validated, `false` otherwise.
|
|
73
|
+
*/
|
|
74
|
+
export declare function restoreLocalDwnEndpoint(agent: EnboxUserAgent, storage: StorageAdapter): Promise<boolean>;
|
|
75
|
+
/**
|
|
76
|
+
* Run the full local DWN discovery sequence for a browser connection flow.
|
|
77
|
+
*
|
|
78
|
+
* This function handles the **receiving** side of local DWN discovery in
|
|
79
|
+
* the browser. It does NOT trigger the `dwn://register` redirect — use
|
|
80
|
+
* {@link requestLocalDwnDiscovery} for that.
|
|
81
|
+
*
|
|
82
|
+
* The discovery channels, from highest to lowest priority:
|
|
83
|
+
*
|
|
84
|
+
* 1. **URL fragment payload** — A `dwn://register` redirect just landed on
|
|
85
|
+
* this page with the DWN endpoint in `#`. This is the highest-priority
|
|
86
|
+
* signal because it's fresh and explicit.
|
|
87
|
+
*
|
|
88
|
+
* 2. **Persisted endpoint** (localStorage) — A previously discovered
|
|
89
|
+
* endpoint is restored and re-validated via `GET /info`.
|
|
90
|
+
*
|
|
91
|
+
* 3. **Agent-level discovery** (transparent) — Even if this function
|
|
92
|
+
* returns `false`, the agent's `LocalDwnDiscovery` will independently
|
|
93
|
+
* try the discovery file (`~/.enbox/dwn.json`) and port probing on
|
|
94
|
+
* every `sendRequest()` call. Those channels are not available in
|
|
95
|
+
* browsers (no filesystem access, CORS may block probes), but they
|
|
96
|
+
* work transparently in Node/Bun CLI environments.
|
|
97
|
+
*
|
|
98
|
+
* When an `emitter` is provided, this function emits:
|
|
99
|
+
* - `'local-dwn-available'` with the endpoint when discovery succeeds.
|
|
100
|
+
* - `'local-dwn-unavailable'` when no local DWN could be reached.
|
|
101
|
+
*
|
|
102
|
+
* @param agent - The running EnboxUserAgent.
|
|
103
|
+
* @param storage - The auth storage adapter.
|
|
104
|
+
* @param emitter - Optional event emitter for local DWN status notifications.
|
|
105
|
+
* @returns `true` if a local DWN endpoint was discovered and injected.
|
|
106
|
+
*/
|
|
107
|
+
export declare function applyLocalDwnDiscovery(agent: EnboxUserAgent, storage: StorageAdapter, emitter?: AuthEventEmitter): Promise<boolean>;
|
|
108
|
+
/**
|
|
109
|
+
* Initiate the `dwn://register` flow by opening the register URL.
|
|
110
|
+
*
|
|
111
|
+
* This asks the operating system to route `dwn://register?callback=<url>`
|
|
112
|
+
* to the registered handler (electrobun-dwn), which will redirect the
|
|
113
|
+
* user's browser back to `callbackUrl` with the local DWN endpoint
|
|
114
|
+
* encoded in the URL fragment.
|
|
115
|
+
*
|
|
116
|
+
* **Important:** There is no reliable cross-browser API to detect whether
|
|
117
|
+
* a `dwn://` handler is installed. If no handler is registered, this call
|
|
118
|
+
* will silently fail or show an OS-level error dialog. Use
|
|
119
|
+
* {@link probeLocalDwn} first to check if a local DWN is already
|
|
120
|
+
* reachable via port probing — if it is, you can skip the register flow
|
|
121
|
+
* entirely and call {@link applyLocalDwnDiscovery} instead.
|
|
122
|
+
*
|
|
123
|
+
* @param callbackUrl - The URL to redirect back to. Defaults to the
|
|
124
|
+
* current page URL (without its fragment) if running in a browser.
|
|
125
|
+
* @returns `true` if the register URL was opened, `false` if no
|
|
126
|
+
* callback URL could be determined (e.g. no `globalThis.location`).
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* // Check if local DWN is already available via direct probe.
|
|
131
|
+
* const alreadyAvailable = await probeLocalDwn();
|
|
132
|
+
* if (!alreadyAvailable) {
|
|
133
|
+
* // No local DWN found — trigger the dwn://register flow.
|
|
134
|
+
* requestLocalDwnDiscovery();
|
|
135
|
+
* // The page will reload with the endpoint in the URL fragment.
|
|
136
|
+
* }
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function requestLocalDwnDiscovery(callbackUrl?: string): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Probe whether a local DWN server is reachable via direct HTTP fetch.
|
|
142
|
+
*
|
|
143
|
+
* Attempts `GET http://127.0.0.1:{port}/info` on the well-known port
|
|
144
|
+
* candidates and returns the endpoint URL of the first server that
|
|
145
|
+
* responds with a valid `@enbox/dwn-server` identity.
|
|
146
|
+
*
|
|
147
|
+
* This is useful in browsers to check if a local DWN is available
|
|
148
|
+
* *before* triggering the `dwn://register` redirect flow — if the
|
|
149
|
+
* server is already reachable (CORS permitting), the redirect is
|
|
150
|
+
* unnecessary.
|
|
151
|
+
*
|
|
152
|
+
* @returns The local DWN endpoint URL, or `undefined` if no server
|
|
153
|
+
* was found. Returns `undefined` (rather than throwing) on CORS
|
|
154
|
+
* errors or network failures.
|
|
155
|
+
*/
|
|
156
|
+
export declare function probeLocalDwn(): Promise<string | undefined>;
|
|
157
|
+
//# sourceMappingURL=dwn-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dwn-discovery.d.ts","sourceRoot":"","sources":["../../../src/flows/dwn-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAInD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,GAAG,SAAS,CAkBnE;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAclB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,OAAO,CAAC,CA2BlB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAuBtE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsBjE"}
|