@tinycloud/sdk-core 2.0.1 → 2.0.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3816 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3867 -0
- package/dist/index.d.ts +3861 -21
- package/dist/index.js +3767 -61
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/TinyCloud.d.ts +0 -271
- package/dist/TinyCloud.d.ts.map +0 -1
- package/dist/TinyCloud.js +0 -458
- package/dist/TinyCloud.js.map +0 -1
- package/dist/TinyCloud.schema.d.ts +0 -173
- package/dist/TinyCloud.schema.d.ts.map +0 -1
- package/dist/TinyCloud.schema.js +0 -136
- package/dist/TinyCloud.schema.js.map +0 -1
- package/dist/TinyCloud.schema.test.d.ts +0 -5
- package/dist/TinyCloud.schema.test.d.ts.map +0 -1
- package/dist/TinyCloud.schema.test.js +0 -286
- package/dist/TinyCloud.schema.test.js.map +0 -1
- package/dist/authorization/CapabilityKeyRegistry.d.ts +0 -317
- package/dist/authorization/CapabilityKeyRegistry.d.ts.map +0 -1
- package/dist/authorization/CapabilityKeyRegistry.js +0 -509
- package/dist/authorization/CapabilityKeyRegistry.js.map +0 -1
- package/dist/authorization/authorization.schema.d.ts +0 -233
- package/dist/authorization/authorization.schema.d.ts.map +0 -1
- package/dist/authorization/authorization.schema.js +0 -220
- package/dist/authorization/authorization.schema.js.map +0 -1
- package/dist/authorization/authorization.schema.test.d.ts +0 -5
- package/dist/authorization/authorization.schema.test.d.ts.map +0 -1
- package/dist/authorization/authorization.schema.test.js +0 -618
- package/dist/authorization/authorization.schema.test.js.map +0 -1
- package/dist/authorization/index.d.ts +0 -38
- package/dist/authorization/index.d.ts.map +0 -1
- package/dist/authorization/index.js +0 -52
- package/dist/authorization/index.js.map +0 -1
- package/dist/authorization/spaceCreation.d.ts +0 -96
- package/dist/authorization/spaceCreation.d.ts.map +0 -1
- package/dist/authorization/spaceCreation.js +0 -35
- package/dist/authorization/spaceCreation.js.map +0 -1
- package/dist/authorization/spaceCreation.schema.d.ts +0 -67
- package/dist/authorization/spaceCreation.schema.d.ts.map +0 -1
- package/dist/authorization/spaceCreation.schema.js +0 -95
- package/dist/authorization/spaceCreation.schema.js.map +0 -1
- package/dist/authorization/spaceCreation.schema.test.d.ts +0 -5
- package/dist/authorization/spaceCreation.schema.test.d.ts.map +0 -1
- package/dist/authorization/spaceCreation.schema.test.js +0 -168
- package/dist/authorization/spaceCreation.schema.test.js.map +0 -1
- package/dist/authorization/strategies.d.ts +0 -134
- package/dist/authorization/strategies.d.ts.map +0 -1
- package/dist/authorization/strategies.js +0 -15
- package/dist/authorization/strategies.js.map +0 -1
- package/dist/authorization/strategies.schema.d.ts +0 -185
- package/dist/authorization/strategies.schema.d.ts.map +0 -1
- package/dist/authorization/strategies.schema.js +0 -147
- package/dist/authorization/strategies.schema.js.map +0 -1
- package/dist/authorization/strategies.schema.test.d.ts +0 -5
- package/dist/authorization/strategies.schema.test.d.ts.map +0 -1
- package/dist/authorization/strategies.schema.test.js +0 -253
- package/dist/authorization/strategies.schema.test.js.map +0 -1
- package/dist/client-types.d.ts +0 -128
- package/dist/client-types.d.ts.map +0 -1
- package/dist/client-types.js +0 -40
- package/dist/client-types.js.map +0 -1
- package/dist/delegations/DelegationManager.d.ts +0 -164
- package/dist/delegations/DelegationManager.d.ts.map +0 -1
- package/dist/delegations/DelegationManager.js +0 -428
- package/dist/delegations/DelegationManager.js.map +0 -1
- package/dist/delegations/SharingService.d.ts +0 -341
- package/dist/delegations/SharingService.d.ts.map +0 -1
- package/dist/delegations/SharingService.js +0 -722
- package/dist/delegations/SharingService.js.map +0 -1
- package/dist/delegations/SharingService.schema.d.ts +0 -409
- package/dist/delegations/SharingService.schema.d.ts.map +0 -1
- package/dist/delegations/SharingService.schema.js +0 -222
- package/dist/delegations/SharingService.schema.js.map +0 -1
- package/dist/delegations/index.d.ts +0 -38
- package/dist/delegations/index.d.ts.map +0 -1
- package/dist/delegations/index.js +0 -42
- package/dist/delegations/index.js.map +0 -1
- package/dist/delegations/types.d.ts +0 -13
- package/dist/delegations/types.d.ts.map +0 -1
- package/dist/delegations/types.js +0 -42
- package/dist/delegations/types.js.map +0 -1
- package/dist/delegations/types.schema.d.ts +0 -1773
- package/dist/delegations/types.schema.d.ts.map +0 -1
- package/dist/delegations/types.schema.js +0 -535
- package/dist/delegations/types.schema.js.map +0 -1
- package/dist/delegations/types.schema.test.d.ts +0 -5
- package/dist/delegations/types.schema.test.d.ts.map +0 -1
- package/dist/delegations/types.schema.test.js +0 -627
- package/dist/delegations/types.schema.test.js.map +0 -1
- package/dist/ens.d.ts +0 -17
- package/dist/ens.d.ts.map +0 -1
- package/dist/ens.js +0 -10
- package/dist/ens.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/json-schema.d.ts +0 -327
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js +0 -703
- package/dist/json-schema.js.map +0 -1
- package/dist/json-schema.test.d.ts +0 -7
- package/dist/json-schema.test.d.ts.map +0 -1
- package/dist/json-schema.test.js +0 -365
- package/dist/json-schema.test.js.map +0 -1
- package/dist/notifications.d.ts +0 -33
- package/dist/notifications.d.ts.map +0 -1
- package/dist/notifications.js +0 -15
- package/dist/notifications.js.map +0 -1
- package/dist/signer.d.ts +0 -28
- package/dist/signer.d.ts.map +0 -1
- package/dist/signer.js +0 -2
- package/dist/signer.js.map +0 -1
- package/dist/space.d.ts +0 -57
- package/dist/space.d.ts.map +0 -1
- package/dist/space.js +0 -87
- package/dist/space.js.map +0 -1
- package/dist/space.schema.d.ts +0 -65
- package/dist/space.schema.d.ts.map +0 -1
- package/dist/space.schema.js +0 -65
- package/dist/space.schema.js.map +0 -1
- package/dist/space.schema.test.d.ts +0 -5
- package/dist/space.schema.test.d.ts.map +0 -1
- package/dist/space.schema.test.js +0 -148
- package/dist/space.schema.test.js.map +0 -1
- package/dist/space.test.d.ts +0 -5
- package/dist/space.test.d.ts.map +0 -1
- package/dist/space.test.js +0 -87
- package/dist/space.test.js.map +0 -1
- package/dist/spaces/Space.d.ts +0 -175
- package/dist/spaces/Space.d.ts.map +0 -1
- package/dist/spaces/Space.js +0 -84
- package/dist/spaces/Space.js.map +0 -1
- package/dist/spaces/SpaceService.d.ts +0 -291
- package/dist/spaces/SpaceService.d.ts.map +0 -1
- package/dist/spaces/SpaceService.js +0 -740
- package/dist/spaces/SpaceService.js.map +0 -1
- package/dist/spaces/index.d.ts +0 -11
- package/dist/spaces/index.d.ts.map +0 -1
- package/dist/spaces/index.js +0 -22
- package/dist/spaces/index.js.map +0 -1
- package/dist/spaces/spaces.schema.d.ts +0 -421
- package/dist/spaces/spaces.schema.d.ts.map +0 -1
- package/dist/spaces/spaces.schema.js +0 -342
- package/dist/spaces/spaces.schema.js.map +0 -1
- package/dist/spaces/spaces.schema.test.d.ts +0 -5
- package/dist/spaces/spaces.schema.test.d.ts.map +0 -1
- package/dist/spaces/spaces.schema.test.js +0 -471
- package/dist/spaces/spaces.schema.test.js.map +0 -1
- package/dist/storage.d.ts +0 -47
- package/dist/storage.d.ts.map +0 -1
- package/dist/storage.js +0 -14
- package/dist/storage.js.map +0 -1
- package/dist/storage.schema.d.ts +0 -291
- package/dist/storage.schema.d.ts.map +0 -1
- package/dist/storage.schema.js +0 -189
- package/dist/storage.schema.js.map +0 -1
- package/dist/storage.schema.test.d.ts +0 -5
- package/dist/storage.schema.test.d.ts.map +0 -1
- package/dist/storage.schema.test.js +0 -346
- package/dist/storage.schema.test.js.map +0 -1
- package/dist/userAuthorization.d.ts +0 -117
- package/dist/userAuthorization.d.ts.map +0 -1
- package/dist/userAuthorization.js +0 -3
- package/dist/userAuthorization.js.map +0 -1
- package/dist/userAuthorization.schema.d.ts +0 -260
- package/dist/userAuthorization.schema.d.ts.map +0 -1
- package/dist/userAuthorization.schema.js +0 -169
- package/dist/userAuthorization.schema.js.map +0 -1
- package/dist/userAuthorization.schema.test.d.ts +0 -5
- package/dist/userAuthorization.schema.test.d.ts.map +0 -1
- package/dist/userAuthorization.schema.test.js +0 -356
- package/dist/userAuthorization.schema.test.js.map +0 -1
- package/dist/version.d.ts +0 -32
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -59
- package/dist/version.js.map +0 -1
- package/dist/wasm-validation.d.ts +0 -291
- package/dist/wasm-validation.d.ts.map +0 -1
- package/dist/wasm-validation.js +0 -221
- package/dist/wasm-validation.js.map +0 -1
- package/dist/wasm-validation.test.d.ts +0 -5
- package/dist/wasm-validation.test.d.ts.map +0 -1
- package/dist/wasm-validation.test.js +0 -233
- package/dist/wasm-validation.test.js.map +0 -1
- package/dist/wasm.d.ts +0 -66
- package/dist/wasm.d.ts.map +0 -1
- package/dist/wasm.js +0 -10
- package/dist/wasm.js.map +0 -1
|
@@ -1,722 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SharingService - v2 sharing link service with embedded private keys.
|
|
3
|
-
*
|
|
4
|
-
* This service implements the v2 sharing specification, which embeds private keys
|
|
5
|
-
* directly in sharing links. This allows recipients to exercise delegations
|
|
6
|
-
* without requiring prior session setup.
|
|
7
|
-
*
|
|
8
|
-
* Key differences from v1 SharingLinks:
|
|
9
|
-
* - Private keys are embedded in the link (not just tokens)
|
|
10
|
-
* - Recipients can optionally sub-delegate to their own session key
|
|
11
|
-
* - Pre-configured KV service returned for immediate use
|
|
12
|
-
*
|
|
13
|
-
* @packageDocumentation
|
|
14
|
-
*/
|
|
15
|
-
import { DelegationErrorCodes } from "./types";
|
|
16
|
-
import { validateEncodedShareData } from "./SharingService.schema.js";
|
|
17
|
-
// =============================================================================
|
|
18
|
-
// Constants
|
|
19
|
-
// =============================================================================
|
|
20
|
-
/**
|
|
21
|
-
* Default actions for read-only sharing links.
|
|
22
|
-
*/
|
|
23
|
-
const DEFAULT_READ_ACTIONS = ["tinycloud.kv/get", "tinycloud.kv/metadata"];
|
|
24
|
-
/**
|
|
25
|
-
* Default expiry for sharing links (24 hours).
|
|
26
|
-
*/
|
|
27
|
-
const DEFAULT_EXPIRY_MS = 24 * 60 * 60 * 1000;
|
|
28
|
-
/**
|
|
29
|
-
* Prefix for the base64 schema.
|
|
30
|
-
*/
|
|
31
|
-
const BASE64_PREFIX = "tc1:";
|
|
32
|
-
// =============================================================================
|
|
33
|
-
// Helper Functions
|
|
34
|
-
// =============================================================================
|
|
35
|
-
/**
|
|
36
|
-
* Creates a DelegationError with the given parameters.
|
|
37
|
-
*/
|
|
38
|
-
function createError(code, message, cause, meta) {
|
|
39
|
-
return {
|
|
40
|
-
code,
|
|
41
|
-
message,
|
|
42
|
-
service: "delegation",
|
|
43
|
-
cause,
|
|
44
|
-
meta,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Base64 encode for URLs (URL-safe base64).
|
|
49
|
-
*/
|
|
50
|
-
function base64UrlEncode(data) {
|
|
51
|
-
// Use btoa for browser, Buffer for Node.js
|
|
52
|
-
let base64;
|
|
53
|
-
if (typeof btoa !== "undefined") {
|
|
54
|
-
base64 = btoa(unescape(encodeURIComponent(data)));
|
|
55
|
-
}
|
|
56
|
-
else if (typeof Buffer !== "undefined") {
|
|
57
|
-
base64 = Buffer.from(data, "utf-8").toString("base64");
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
throw new Error("No base64 encoding available");
|
|
61
|
-
}
|
|
62
|
-
// Make URL-safe
|
|
63
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Base64 decode for URLs (URL-safe base64).
|
|
67
|
-
*/
|
|
68
|
-
function base64UrlDecode(encoded) {
|
|
69
|
-
// Restore standard base64
|
|
70
|
-
let base64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
71
|
-
// Add padding if needed
|
|
72
|
-
while (base64.length % 4) {
|
|
73
|
-
base64 += "=";
|
|
74
|
-
}
|
|
75
|
-
// Decode
|
|
76
|
-
if (typeof atob !== "undefined") {
|
|
77
|
-
return decodeURIComponent(escape(atob(base64)));
|
|
78
|
-
}
|
|
79
|
-
else if (typeof Buffer !== "undefined") {
|
|
80
|
-
return Buffer.from(base64, "base64").toString("utf-8");
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
throw new Error("No base64 decoding available");
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// =============================================================================
|
|
87
|
-
// Implementation
|
|
88
|
-
// =============================================================================
|
|
89
|
-
/**
|
|
90
|
-
* SharingService - v2 sharing link service with embedded private keys.
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```typescript
|
|
94
|
-
* import { SharingService } from "@tinycloud/sdk-core/delegations";
|
|
95
|
-
*
|
|
96
|
-
* const sharing = new SharingService({
|
|
97
|
-
* hosts: ["https://node.tinycloud.xyz"],
|
|
98
|
-
* session,
|
|
99
|
-
* invoke,
|
|
100
|
-
* keyProvider,
|
|
101
|
-
* registry,
|
|
102
|
-
* delegationManager,
|
|
103
|
-
* createKVService,
|
|
104
|
-
* baseUrl: "https://share.myapp.com"
|
|
105
|
-
* });
|
|
106
|
-
*
|
|
107
|
-
* // Generate a sharing link
|
|
108
|
-
* const result = await sharing.generate({
|
|
109
|
-
* path: "/kv/documents/report.pdf",
|
|
110
|
-
* actions: ["tinycloud.kv/get"],
|
|
111
|
-
* expiry: new Date("2024-12-31")
|
|
112
|
-
* });
|
|
113
|
-
*
|
|
114
|
-
* if (result.ok) {
|
|
115
|
-
* console.log("Share this URL:", result.data.url);
|
|
116
|
-
* }
|
|
117
|
-
*
|
|
118
|
-
* // Receive a sharing link
|
|
119
|
-
* const receiveResult = await sharing.receive(shareUrl);
|
|
120
|
-
* if (receiveResult.ok) {
|
|
121
|
-
* // Use the pre-configured KV service
|
|
122
|
-
* const data = await receiveResult.data.kv.get("report.pdf");
|
|
123
|
-
* }
|
|
124
|
-
* ```
|
|
125
|
-
*/
|
|
126
|
-
export class SharingService {
|
|
127
|
-
/**
|
|
128
|
-
* Creates a new SharingService instance.
|
|
129
|
-
*/
|
|
130
|
-
constructor(config) {
|
|
131
|
-
this.hosts = config.hosts;
|
|
132
|
-
this.session = config.session;
|
|
133
|
-
this.invoke = config.invoke;
|
|
134
|
-
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
135
|
-
this.keyProvider = config.keyProvider;
|
|
136
|
-
this.registry = config.registry;
|
|
137
|
-
this.delegationManager = config.delegationManager;
|
|
138
|
-
this.createKVService = config.createKVService;
|
|
139
|
-
this.baseUrl = (config.baseUrl ?? "").replace(/\/$/, ""); // Remove trailing slash
|
|
140
|
-
this.createDelegationFn = config.createDelegation;
|
|
141
|
-
this.createDelegationWasmFn = config.createDelegationWasm;
|
|
142
|
-
this.pathPrefix = config.pathPrefix ?? "";
|
|
143
|
-
this.sessionExpiry = config.sessionExpiry;
|
|
144
|
-
this.onRootDelegationNeeded = config.onRootDelegationNeeded;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Gets the primary host URL.
|
|
148
|
-
*/
|
|
149
|
-
get host() {
|
|
150
|
-
return this.hosts[0];
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Updates the session (e.g., after re-authentication).
|
|
154
|
-
*/
|
|
155
|
-
updateSession(session) {
|
|
156
|
-
this.session = session;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Updates the service configuration.
|
|
160
|
-
* Used to add full capabilities (session, delegationManager, createDelegation, createDelegationWasm) after signIn.
|
|
161
|
-
*/
|
|
162
|
-
updateConfig(config) {
|
|
163
|
-
if (config.session !== undefined) {
|
|
164
|
-
this.session = config.session;
|
|
165
|
-
}
|
|
166
|
-
if (config.delegationManager !== undefined) {
|
|
167
|
-
this.delegationManager = config.delegationManager;
|
|
168
|
-
}
|
|
169
|
-
if (config.createDelegation !== undefined) {
|
|
170
|
-
this.createDelegationFn = config.createDelegation;
|
|
171
|
-
}
|
|
172
|
-
if (config.createDelegationWasm !== undefined) {
|
|
173
|
-
this.createDelegationWasmFn = config.createDelegationWasm;
|
|
174
|
-
}
|
|
175
|
-
if (config.sessionExpiry !== undefined) {
|
|
176
|
-
this.sessionExpiry = config.sessionExpiry;
|
|
177
|
-
}
|
|
178
|
-
if (config.onRootDelegationNeeded !== undefined) {
|
|
179
|
-
this.onRootDelegationNeeded = config.onRootDelegationNeeded;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Generate a sharing link with an embedded private key.
|
|
184
|
-
*
|
|
185
|
-
* Flow:
|
|
186
|
-
* 1. Spawn new session key (unique per share)
|
|
187
|
-
* 2. Create delegation from current session to spawned key
|
|
188
|
-
* 3. Package: { key (with private!), delegation, path, host }
|
|
189
|
-
* 4. Encode based on schema (base64 for now)
|
|
190
|
-
* 5. Return link string
|
|
191
|
-
*/
|
|
192
|
-
async generate(params) {
|
|
193
|
-
// Require session for generating (not for receiving)
|
|
194
|
-
if (!this.session) {
|
|
195
|
-
return {
|
|
196
|
-
ok: false,
|
|
197
|
-
error: createError(DelegationErrorCodes.NOT_INITIALIZED, "Session required for generating sharing links. Call signIn() first."),
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
// Require delegation capability
|
|
201
|
-
if (!this.createDelegationWasmFn && !this.createDelegationFn && !this.delegationManager) {
|
|
202
|
-
return {
|
|
203
|
-
ok: false,
|
|
204
|
-
error: createError(DelegationErrorCodes.NOT_INITIALIZED, "DelegationManager, createDelegation, or createDelegationWasm function required for generating sharing links."),
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
// Validate path
|
|
208
|
-
if (!params.path) {
|
|
209
|
-
return {
|
|
210
|
-
ok: false,
|
|
211
|
-
error: createError(DelegationErrorCodes.INVALID_INPUT, "path is required"),
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
const actions = params.actions ?? DEFAULT_READ_ACTIONS;
|
|
215
|
-
const requestedExpiry = params.expiry ?? new Date(Date.now() + DEFAULT_EXPIRY_MS);
|
|
216
|
-
let expiry = requestedExpiry;
|
|
217
|
-
const schema = params.schema ?? "base64";
|
|
218
|
-
// Build full path with prefix (matches how KVService stores data)
|
|
219
|
-
// If pathPrefix is "demo-app" and path is "hello", fullPath is "demo-app/hello"
|
|
220
|
-
const fullPath = this.pathPrefix
|
|
221
|
-
? `${this.pathPrefix}/${params.path}`.replace(/\/+/g, "/") // Normalize slashes
|
|
222
|
-
: params.path;
|
|
223
|
-
// Only base64 schema is implemented in v1
|
|
224
|
-
if (schema !== "base64") {
|
|
225
|
-
return {
|
|
226
|
-
ok: false,
|
|
227
|
-
error: createError(DelegationErrorCodes.INVALID_INPUT, `Schema '${schema}' not implemented. Only 'base64' is supported.`),
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
// Step 1: Spawn a new session key unique to this share
|
|
231
|
-
// We create this FIRST so we can pass its DID to onRootDelegationNeeded if needed
|
|
232
|
-
let keyId;
|
|
233
|
-
let keyDid;
|
|
234
|
-
let keyJwk;
|
|
235
|
-
try {
|
|
236
|
-
const shareKeyName = `share:${Date.now()}:${Math.random().toString(36).substring(2, 10)}`;
|
|
237
|
-
keyId = await this.keyProvider.createSessionKey(shareKeyName);
|
|
238
|
-
keyDid = await this.keyProvider.getDID(keyId);
|
|
239
|
-
keyJwk = this.keyProvider.getJWK(keyId);
|
|
240
|
-
// Ensure the private key is included
|
|
241
|
-
if (!keyJwk.d) {
|
|
242
|
-
return {
|
|
243
|
-
ok: false,
|
|
244
|
-
error: createError(DelegationErrorCodes.CREATION_FAILED, "KeyProvider did not return private key (d parameter) in JWK"),
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
catch (err) {
|
|
249
|
-
return {
|
|
250
|
-
ok: false,
|
|
251
|
-
error: createError(DelegationErrorCodes.CREATION_FAILED, `Failed to generate session key for share: ${err instanceof Error ? err.message : String(err)}`, err instanceof Error ? err : undefined),
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
// Step 2: Check if any existing key can satisfy this delegation
|
|
255
|
-
// Only prompt for root delegation if NO existing key in the registry can handle it
|
|
256
|
-
let delegation;
|
|
257
|
-
// Strip fragment from DID URL to get plain DID for UCAN audience
|
|
258
|
-
// getDID() returns "did:key:z6Mk...#z6Mk..." but audience needs "did:key:z6Mk..."
|
|
259
|
-
const plainDID = keyDid.split('#')[0];
|
|
260
|
-
// Helper to handle delegation result (returns early on error)
|
|
261
|
-
const handleDelegationResult = (result) => {
|
|
262
|
-
if (result && typeof result === 'object' && 'ok' in result) {
|
|
263
|
-
return result;
|
|
264
|
-
}
|
|
265
|
-
return result;
|
|
266
|
-
};
|
|
267
|
-
// Check if any key in the registry can satisfy this delegation request
|
|
268
|
-
// A key can satisfy the request if it has a delegation that:
|
|
269
|
-
// 1. Covers the required path and actions
|
|
270
|
-
// 2. Has sufficient expiry (delegation.expiry >= requestedExpiry)
|
|
271
|
-
// 3. Allows sub-delegation
|
|
272
|
-
const canSatisfyFromRegistry = this.findSuitableKeyForDelegation(fullPath, actions, requestedExpiry);
|
|
273
|
-
if (canSatisfyFromRegistry) {
|
|
274
|
-
// An existing key can satisfy this request - use session delegation (no prompt)
|
|
275
|
-
const delegationResult = await this.createSessionDelegation(plainDID, fullPath, actions, expiry);
|
|
276
|
-
const parsed = handleDelegationResult(delegationResult);
|
|
277
|
-
if ('ok' in parsed && parsed.ok === false) {
|
|
278
|
-
return parsed;
|
|
279
|
-
}
|
|
280
|
-
delegation = parsed;
|
|
281
|
-
}
|
|
282
|
-
else if (this.onRootDelegationNeeded) {
|
|
283
|
-
// No existing key can satisfy the request - try root delegation
|
|
284
|
-
try {
|
|
285
|
-
const rootDelegation = await this.onRootDelegationNeeded({
|
|
286
|
-
shareKeyDID: plainDID,
|
|
287
|
-
spaceId: this.session.spaceId,
|
|
288
|
-
path: fullPath,
|
|
289
|
-
actions,
|
|
290
|
-
requestedExpiry,
|
|
291
|
-
});
|
|
292
|
-
if (rootDelegation) {
|
|
293
|
-
delegation = rootDelegation;
|
|
294
|
-
expiry = requestedExpiry;
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
// Root delegation declined, clamp to session expiry
|
|
298
|
-
const fallbackResult = await this.handleSessionExtensionFallback(requestedExpiry);
|
|
299
|
-
expiry = fallbackResult.expiry;
|
|
300
|
-
const delegationResult = await this.createSessionDelegation(plainDID, fullPath, actions, expiry);
|
|
301
|
-
const parsed = handleDelegationResult(delegationResult);
|
|
302
|
-
if ('ok' in parsed && parsed.ok === false) {
|
|
303
|
-
return parsed;
|
|
304
|
-
}
|
|
305
|
-
delegation = parsed;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
catch (err) {
|
|
309
|
-
// Root delegation failed, clamp to session expiry
|
|
310
|
-
const fallbackResult = await this.handleSessionExtensionFallback(requestedExpiry);
|
|
311
|
-
expiry = fallbackResult.expiry;
|
|
312
|
-
const delegationResult = await this.createSessionDelegation(plainDID, fullPath, actions, expiry);
|
|
313
|
-
const parsed = handleDelegationResult(delegationResult);
|
|
314
|
-
if ('ok' in parsed && parsed.ok === false) {
|
|
315
|
-
return parsed;
|
|
316
|
-
}
|
|
317
|
-
delegation = parsed;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
// No root delegation callback, clamp to what session can provide
|
|
322
|
-
const fallbackResult = await this.handleSessionExtensionFallback(requestedExpiry);
|
|
323
|
-
expiry = fallbackResult.expiry;
|
|
324
|
-
const delegationResult = await this.createSessionDelegation(plainDID, fullPath, actions, expiry);
|
|
325
|
-
const parsed = handleDelegationResult(delegationResult);
|
|
326
|
-
if ('ok' in parsed && parsed.ok === false) {
|
|
327
|
-
return parsed;
|
|
328
|
-
}
|
|
329
|
-
delegation = parsed;
|
|
330
|
-
}
|
|
331
|
-
// Step 3: Package the share data
|
|
332
|
-
const shareData = {
|
|
333
|
-
key: keyJwk,
|
|
334
|
-
keyDid,
|
|
335
|
-
delegation,
|
|
336
|
-
path: fullPath,
|
|
337
|
-
host: this.host,
|
|
338
|
-
spaceId: this.session.spaceId,
|
|
339
|
-
version: 1,
|
|
340
|
-
};
|
|
341
|
-
// Step 4: Encode the link
|
|
342
|
-
const encodedData = this.encodeLink(shareData, schema);
|
|
343
|
-
// Step 5: Build the full URL
|
|
344
|
-
const baseUrl = params.baseUrl ?? this.baseUrl;
|
|
345
|
-
const url = baseUrl ? `${baseUrl}/share/${encodedData}` : encodedData;
|
|
346
|
-
const shareLink = {
|
|
347
|
-
token: encodedData,
|
|
348
|
-
url,
|
|
349
|
-
delegation,
|
|
350
|
-
schema,
|
|
351
|
-
expiresAt: expiry,
|
|
352
|
-
description: params.description,
|
|
353
|
-
};
|
|
354
|
-
return { ok: true, data: shareLink };
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Check if any key in the registry can satisfy the delegation request.
|
|
358
|
-
* A key can satisfy if it has a delegation that:
|
|
359
|
-
* 1. Covers the required path (exact match or parent path)
|
|
360
|
-
* 2. Has all required actions
|
|
361
|
-
* 3. Has sufficient expiry (delegation.expiry >= requestedExpiry)
|
|
362
|
-
* 4. Allows sub-delegation
|
|
363
|
-
* @internal
|
|
364
|
-
*/
|
|
365
|
-
findSuitableKeyForDelegation(path, actions, requestedExpiry) {
|
|
366
|
-
// Check session expiry first (most common case)
|
|
367
|
-
if (this.sessionExpiry && requestedExpiry <= this.sessionExpiry) {
|
|
368
|
-
return true;
|
|
369
|
-
}
|
|
370
|
-
// Check registry for keys with sufficient capabilities
|
|
371
|
-
const allKeys = this.registry.getAllKeys();
|
|
372
|
-
for (const key of allKeys) {
|
|
373
|
-
const delegations = this.registry.getDelegationsForKey(key.id);
|
|
374
|
-
for (const delegation of delegations) {
|
|
375
|
-
// Check if delegation is valid and not expired
|
|
376
|
-
if (!this.registry.isDelegationValid(delegation)) {
|
|
377
|
-
continue;
|
|
378
|
-
}
|
|
379
|
-
// Check if delegation has sufficient expiry
|
|
380
|
-
if (delegation.expiry < requestedExpiry) {
|
|
381
|
-
continue;
|
|
382
|
-
}
|
|
383
|
-
// Check if delegation allows sub-delegation
|
|
384
|
-
if (delegation.allowSubDelegation === false) {
|
|
385
|
-
continue;
|
|
386
|
-
}
|
|
387
|
-
// Check if delegation covers the path (exact match or parent path)
|
|
388
|
-
const delegationPath = delegation.path || '';
|
|
389
|
-
if (!this.pathMatches(delegationPath, path)) {
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
// Check if delegation has all required actions
|
|
393
|
-
const delegationActions = delegation.actions || [];
|
|
394
|
-
const hasAllActions = actions.every(action => delegationActions.includes(action) || delegationActions.includes('*'));
|
|
395
|
-
if (!hasAllActions) {
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
// Found a suitable key
|
|
399
|
-
return true;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return false;
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Check if a delegation path matches/covers the requested path.
|
|
406
|
-
* A delegation path covers the request if:
|
|
407
|
-
* - It's an exact match
|
|
408
|
-
* - It's a parent path (e.g., delegation for "" covers "foo/bar")
|
|
409
|
-
* - It uses wildcards that match
|
|
410
|
-
* @internal
|
|
411
|
-
*/
|
|
412
|
-
pathMatches(delegationPath, requestedPath) {
|
|
413
|
-
// Empty delegation path covers everything
|
|
414
|
-
if (delegationPath === '' || delegationPath === '*') {
|
|
415
|
-
return true;
|
|
416
|
-
}
|
|
417
|
-
// Exact match
|
|
418
|
-
if (delegationPath === requestedPath) {
|
|
419
|
-
return true;
|
|
420
|
-
}
|
|
421
|
-
// Check if delegation path is a parent of requested path
|
|
422
|
-
const normalizedDelegation = delegationPath.replace(/\/$/, '');
|
|
423
|
-
const normalizedRequest = requestedPath.replace(/\/$/, '');
|
|
424
|
-
if (normalizedRequest.startsWith(normalizedDelegation + '/')) {
|
|
425
|
-
return true;
|
|
426
|
-
}
|
|
427
|
-
return false;
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* Handle fallback to session extension when root delegation is not available.
|
|
431
|
-
* @internal
|
|
432
|
-
*/
|
|
433
|
-
async handleSessionExtensionFallback(requestedExpiry) {
|
|
434
|
-
// Clamp to current session expiry
|
|
435
|
-
return { expiry: this.sessionExpiry ?? requestedExpiry };
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Create a delegation from the current session to a share key.
|
|
439
|
-
* This is the fallback path when root delegation is not available.
|
|
440
|
-
* @internal
|
|
441
|
-
*/
|
|
442
|
-
async createSessionDelegation(delegateDID, path, actions, expiry) {
|
|
443
|
-
if (!this.session) {
|
|
444
|
-
return {
|
|
445
|
-
ok: false,
|
|
446
|
-
error: createError(DelegationErrorCodes.NOT_INITIALIZED, "Session required for creating delegation"),
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
if (this.createDelegationWasmFn) {
|
|
450
|
-
// Client-side delegation creation via WASM
|
|
451
|
-
try {
|
|
452
|
-
const wasmResult = this.createDelegationWasmFn({
|
|
453
|
-
session: this.session,
|
|
454
|
-
delegateDID,
|
|
455
|
-
spaceId: this.session.spaceId,
|
|
456
|
-
path,
|
|
457
|
-
actions,
|
|
458
|
-
expirationSecs: Math.floor(expiry.getTime() / 1000),
|
|
459
|
-
});
|
|
460
|
-
// Register the delegation with the server
|
|
461
|
-
const registerRes = await this.fetchFn(`${this.host}/delegate`, {
|
|
462
|
-
method: "POST",
|
|
463
|
-
headers: {
|
|
464
|
-
Authorization: wasmResult.delegation,
|
|
465
|
-
},
|
|
466
|
-
});
|
|
467
|
-
if (!registerRes.ok) {
|
|
468
|
-
const errorText = await registerRes.text();
|
|
469
|
-
return {
|
|
470
|
-
ok: false,
|
|
471
|
-
error: createError(DelegationErrorCodes.CREATION_FAILED, `Failed to register delegation with server: ${registerRes.status} ${errorText}`),
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
return {
|
|
475
|
-
cid: wasmResult.cid,
|
|
476
|
-
delegateDID: wasmResult.delegateDID,
|
|
477
|
-
spaceId: this.session.spaceId,
|
|
478
|
-
path: wasmResult.path,
|
|
479
|
-
actions: wasmResult.actions,
|
|
480
|
-
expiry: wasmResult.expiry,
|
|
481
|
-
isRevoked: false,
|
|
482
|
-
authHeader: wasmResult.delegation,
|
|
483
|
-
allowSubDelegation: true,
|
|
484
|
-
createdAt: new Date(),
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
catch (err) {
|
|
488
|
-
return {
|
|
489
|
-
ok: false,
|
|
490
|
-
error: createError(DelegationErrorCodes.CREATION_FAILED, `Failed to create delegation via WASM: ${err instanceof Error ? err.message : String(err)}`, err instanceof Error ? err : undefined),
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
// Server-side delegation creation (fallback)
|
|
496
|
-
const delegationParams = {
|
|
497
|
-
delegateDID,
|
|
498
|
-
path,
|
|
499
|
-
actions,
|
|
500
|
-
expiry,
|
|
501
|
-
disableSubDelegation: false,
|
|
502
|
-
};
|
|
503
|
-
const delegationResult = this.createDelegationFn
|
|
504
|
-
? await this.createDelegationFn(delegationParams)
|
|
505
|
-
: await this.delegationManager.create(delegationParams);
|
|
506
|
-
if (!delegationResult.ok) {
|
|
507
|
-
return {
|
|
508
|
-
ok: false,
|
|
509
|
-
error: createError(DelegationErrorCodes.CREATION_FAILED, `Failed to create delegation for share: ${delegationResult.error.message}`, delegationResult.error.cause, delegationResult.error.meta),
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
return delegationResult.data;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Receive and activate a sharing link.
|
|
517
|
-
*
|
|
518
|
-
* Flow:
|
|
519
|
-
* 1. Decode link -> extract { key, delegation, path, host }
|
|
520
|
-
* 2. Ingest key into CapabilityKeyRegistry
|
|
521
|
-
* 3. If autoSubdelegate (default true) + useSessionKey:
|
|
522
|
-
* - Create sub-delegation from ingested key -> current session
|
|
523
|
-
* - Register sub-delegation capabilities
|
|
524
|
-
* 4. Return ShareAccess with pre-configured KV service
|
|
525
|
-
*/
|
|
526
|
-
async receive(link, options = {}) {
|
|
527
|
-
const { autoSubdelegate = true, useSessionKey = true, ingestOptions, } = options;
|
|
528
|
-
// Step 1: Decode and validate the link
|
|
529
|
-
const decodeResult = this.decodeLinkWithValidation(link);
|
|
530
|
-
if (!decodeResult.ok) {
|
|
531
|
-
return decodeResult;
|
|
532
|
-
}
|
|
533
|
-
const shareData = decodeResult.data;
|
|
534
|
-
// Schema validation ensures key.d and delegation exist, but we need
|
|
535
|
-
// to check business rules (expiry, revocation) separately
|
|
536
|
-
// Check delegation expiry
|
|
537
|
-
const delegationExpiry = new Date(shareData.delegation.expiry);
|
|
538
|
-
if (delegationExpiry < new Date()) {
|
|
539
|
-
return {
|
|
540
|
-
ok: false,
|
|
541
|
-
error: createError(DelegationErrorCodes.AUTH_EXPIRED, "Sharing link has expired"),
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
// Check delegation revocation
|
|
545
|
-
if (shareData.delegation.isRevoked) {
|
|
546
|
-
return {
|
|
547
|
-
ok: false,
|
|
548
|
-
error: createError(DelegationErrorCodes.REVOKED, "Sharing link has been revoked"),
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
// Step 2: Create KeyInfo and ingest into registry
|
|
552
|
-
const keyInfo = {
|
|
553
|
-
id: `ingested:${shareData.keyDid}`,
|
|
554
|
-
did: shareData.keyDid,
|
|
555
|
-
type: "ingested",
|
|
556
|
-
jwk: shareData.key,
|
|
557
|
-
priority: 2, // Ingested keys have lowest priority
|
|
558
|
-
};
|
|
559
|
-
this.registry.ingestKey(keyInfo, shareData.delegation, ingestOptions);
|
|
560
|
-
// The delegation and key to use for operations
|
|
561
|
-
let activeDelegation = shareData.delegation;
|
|
562
|
-
let activeKey = keyInfo;
|
|
563
|
-
// Step 3: Auto-subdelegate if requested
|
|
564
|
-
if (autoSubdelegate && useSessionKey && this.session) {
|
|
565
|
-
try {
|
|
566
|
-
// Get current session key DID
|
|
567
|
-
// Note: We need to create a sub-delegation from the ingested key to the session key
|
|
568
|
-
// This requires the session key DID, which should be available from the session
|
|
569
|
-
// For now, we'll register the ingested key's capabilities directly
|
|
570
|
-
// The auto-subdelegation would require additional infrastructure to sign with the ingested key
|
|
571
|
-
// This is a simplification - full implementation would sign a new delegation with the ingested key
|
|
572
|
-
// TODO: Implement full auto-subdelegation when signing infrastructure is available
|
|
573
|
-
// For now, the ingested key can be used directly via the registry
|
|
574
|
-
}
|
|
575
|
-
catch (err) {
|
|
576
|
-
// Log but don't fail - can still use the ingested key directly
|
|
577
|
-
console.warn("Auto-subdelegation failed, using ingested key directly:", err);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
// Step 4: Create pre-configured KV service for the shared path
|
|
581
|
-
// Construct session from share data - no need for existing session
|
|
582
|
-
// Use the authHeader if available, otherwise fall back to constructing from CID
|
|
583
|
-
const authHeader = shareData.delegation.authHeader ?? `Bearer ${shareData.delegation.cid}`;
|
|
584
|
-
const shareSession = {
|
|
585
|
-
delegationHeader: { Authorization: authHeader },
|
|
586
|
-
delegationCid: shareData.delegation.cid,
|
|
587
|
-
spaceId: shareData.spaceId,
|
|
588
|
-
verificationMethod: shareData.keyDid,
|
|
589
|
-
jwk: shareData.key,
|
|
590
|
-
};
|
|
591
|
-
const kvService = this.createKVService({
|
|
592
|
-
hosts: [shareData.host],
|
|
593
|
-
session: shareSession,
|
|
594
|
-
invoke: this.invoke,
|
|
595
|
-
fetch: this.fetchFn,
|
|
596
|
-
pathPrefix: shareData.path,
|
|
597
|
-
});
|
|
598
|
-
const shareAccess = {
|
|
599
|
-
delegation: activeDelegation,
|
|
600
|
-
key: activeKey,
|
|
601
|
-
kv: kvService,
|
|
602
|
-
spaceId: shareData.spaceId,
|
|
603
|
-
path: shareData.path,
|
|
604
|
-
};
|
|
605
|
-
return { ok: true, data: shareAccess };
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* Encode sharing data into a link string.
|
|
609
|
-
*
|
|
610
|
-
* @param data - The share data to encode
|
|
611
|
-
* @param schema - The encoding schema (default: "base64")
|
|
612
|
-
* @returns Encoded link string
|
|
613
|
-
*/
|
|
614
|
-
encodeLink(data, schema = "base64") {
|
|
615
|
-
if (schema !== "base64") {
|
|
616
|
-
throw new Error(`Schema '${schema}' not implemented. Only 'base64' is supported.`);
|
|
617
|
-
}
|
|
618
|
-
const jsonString = JSON.stringify(data);
|
|
619
|
-
const encoded = base64UrlEncode(jsonString);
|
|
620
|
-
return `${BASE64_PREFIX}${encoded}`;
|
|
621
|
-
}
|
|
622
|
-
/**
|
|
623
|
-
* Decode a link string into sharing data.
|
|
624
|
-
*
|
|
625
|
-
* @param link - The encoded link string (may include URL prefix)
|
|
626
|
-
* @returns Decoded share data
|
|
627
|
-
* @throws Error if link format is invalid or data fails validation
|
|
628
|
-
*/
|
|
629
|
-
decodeLink(link) {
|
|
630
|
-
const result = this.decodeLinkWithValidation(link);
|
|
631
|
-
if (!result.ok) {
|
|
632
|
-
throw new Error(result.error.message);
|
|
633
|
-
}
|
|
634
|
-
return result.data;
|
|
635
|
-
}
|
|
636
|
-
/**
|
|
637
|
-
* Decode and validate a link string into sharing data.
|
|
638
|
-
*
|
|
639
|
-
* Internal method that returns a Result instead of throwing.
|
|
640
|
-
* Used by receive() for proper error handling.
|
|
641
|
-
*
|
|
642
|
-
* @param link - The encoded link string (may include URL prefix)
|
|
643
|
-
* @returns Result with decoded share data or validation error
|
|
644
|
-
*/
|
|
645
|
-
decodeLinkWithValidation(link) {
|
|
646
|
-
// Extract the encoded data from the link
|
|
647
|
-
let encoded = link;
|
|
648
|
-
// Handle full URL format: https://share.example.com/share/tc1:...
|
|
649
|
-
if (link.includes("/share/")) {
|
|
650
|
-
const parts = link.split("/share/");
|
|
651
|
-
encoded = parts[parts.length - 1];
|
|
652
|
-
}
|
|
653
|
-
// Handle query parameter format: ?share=tc1:...
|
|
654
|
-
if (link.includes("?share=")) {
|
|
655
|
-
try {
|
|
656
|
-
const url = new URL(link);
|
|
657
|
-
encoded = url.searchParams.get("share") ?? encoded;
|
|
658
|
-
}
|
|
659
|
-
catch {
|
|
660
|
-
return {
|
|
661
|
-
ok: false,
|
|
662
|
-
error: createError(DelegationErrorCodes.INVALID_TOKEN, "Invalid URL format in sharing link"),
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
// Remove the schema prefix
|
|
667
|
-
if (!encoded.startsWith(BASE64_PREFIX)) {
|
|
668
|
-
return {
|
|
669
|
-
ok: false,
|
|
670
|
-
error: createError(DelegationErrorCodes.INVALID_TOKEN, `Invalid sharing link format. Expected prefix '${BASE64_PREFIX}'`),
|
|
671
|
-
};
|
|
672
|
-
}
|
|
673
|
-
const base64Data = encoded.slice(BASE64_PREFIX.length);
|
|
674
|
-
let jsonString;
|
|
675
|
-
try {
|
|
676
|
-
jsonString = base64UrlDecode(base64Data);
|
|
677
|
-
}
|
|
678
|
-
catch (err) {
|
|
679
|
-
return {
|
|
680
|
-
ok: false,
|
|
681
|
-
error: createError(DelegationErrorCodes.INVALID_TOKEN, `Failed to decode base64 data: ${err instanceof Error ? err.message : String(err)}`, err instanceof Error ? err : undefined),
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
let parsed;
|
|
685
|
-
try {
|
|
686
|
-
parsed = JSON.parse(jsonString);
|
|
687
|
-
}
|
|
688
|
-
catch (err) {
|
|
689
|
-
return {
|
|
690
|
-
ok: false,
|
|
691
|
-
error: createError(DelegationErrorCodes.INVALID_TOKEN, `Failed to parse share data JSON: ${err instanceof Error ? err.message : String(err)}`, err instanceof Error ? err : undefined),
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
// Convert delegation expiry to Date before validation if it's a string
|
|
695
|
-
// This is needed because JSON.parse doesn't restore Date objects
|
|
696
|
-
if (parsed &&
|
|
697
|
-
typeof parsed === "object" &&
|
|
698
|
-
"delegation" in parsed &&
|
|
699
|
-
parsed.delegation &&
|
|
700
|
-
typeof parsed.delegation === "object" &&
|
|
701
|
-
"expiry" in parsed.delegation &&
|
|
702
|
-
typeof parsed.delegation.expiry === "string") {
|
|
703
|
-
parsed.delegation.expiry = new Date(parsed.delegation.expiry);
|
|
704
|
-
}
|
|
705
|
-
// Validate against schema
|
|
706
|
-
const validationResult = validateEncodedShareData(parsed);
|
|
707
|
-
if (!validationResult.ok) {
|
|
708
|
-
return {
|
|
709
|
-
ok: false,
|
|
710
|
-
error: createError(DelegationErrorCodes.INVALID_TOKEN, validationResult.error.message, undefined, validationResult.error.meta),
|
|
711
|
-
};
|
|
712
|
-
}
|
|
713
|
-
return { ok: true, data: validationResult.data };
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
/**
|
|
717
|
-
* Create a new SharingService instance.
|
|
718
|
-
*/
|
|
719
|
-
export function createSharingService(config) {
|
|
720
|
-
return new SharingService(config);
|
|
721
|
-
}
|
|
722
|
-
//# sourceMappingURL=SharingService.js.map
|