@gaballahtech/seba 0.0.0-stage → 0.2.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.
Files changed (86) hide show
  1. package/ARCHITECTURE.md +242 -0
  2. package/BUILD_REPORT.md +195 -0
  3. package/CHANGELOG.md +59 -0
  4. package/LICENSE +21 -0
  5. package/README.md +282 -2
  6. package/RESEARCH.md +180 -0
  7. package/SECURITY.md +224 -0
  8. package/VALIDATION_REPORT.md +187 -0
  9. package/dist/browser/index.d.ts +9 -0
  10. package/dist/browser/index.d.ts.map +1 -0
  11. package/dist/browser/index.js +9 -0
  12. package/dist/browser/index.js.map +1 -0
  13. package/dist/browser/platform.d.ts +14 -0
  14. package/dist/browser/platform.d.ts.map +1 -0
  15. package/dist/browser/platform.js +60 -0
  16. package/dist/browser/platform.js.map +1 -0
  17. package/dist/browser/provider-modal.d.ts +15 -0
  18. package/dist/browser/provider-modal.d.ts.map +1 -0
  19. package/dist/browser/provider-modal.js +126 -0
  20. package/dist/browser/provider-modal.js.map +1 -0
  21. package/dist/browser/storage.d.ts +32 -0
  22. package/dist/browser/storage.d.ts.map +1 -0
  23. package/dist/browser/storage.js +121 -0
  24. package/dist/browser/storage.js.map +1 -0
  25. package/dist/core/client.d.ts +49 -0
  26. package/dist/core/client.d.ts.map +1 -0
  27. package/dist/core/client.js +371 -0
  28. package/dist/core/client.js.map +1 -0
  29. package/dist/core/discovery.d.ts +82 -0
  30. package/dist/core/discovery.d.ts.map +1 -0
  31. package/dist/core/discovery.js +243 -0
  32. package/dist/core/discovery.js.map +1 -0
  33. package/dist/core/dpop.d.ts +67 -0
  34. package/dist/core/dpop.d.ts.map +1 -0
  35. package/dist/core/dpop.js +176 -0
  36. package/dist/core/dpop.js.map +1 -0
  37. package/dist/core/errors.d.ts +86 -0
  38. package/dist/core/errors.d.ts.map +1 -0
  39. package/dist/core/errors.js +104 -0
  40. package/dist/core/errors.js.map +1 -0
  41. package/dist/core/http.d.ts +68 -0
  42. package/dist/core/http.d.ts.map +1 -0
  43. package/dist/core/http.js +128 -0
  44. package/dist/core/http.js.map +1 -0
  45. package/dist/core/identity.d.ts +145 -0
  46. package/dist/core/identity.d.ts.map +1 -0
  47. package/dist/core/identity.js +735 -0
  48. package/dist/core/identity.js.map +1 -0
  49. package/dist/core/oidc.d.ts +175 -0
  50. package/dist/core/oidc.d.ts.map +1 -0
  51. package/dist/core/oidc.js +413 -0
  52. package/dist/core/oidc.js.map +1 -0
  53. package/dist/core/session.d.ts +116 -0
  54. package/dist/core/session.d.ts.map +1 -0
  55. package/dist/core/session.js +350 -0
  56. package/dist/core/session.js.map +1 -0
  57. package/dist/core/storage.d.ts +22 -0
  58. package/dist/core/storage.d.ts.map +1 -0
  59. package/dist/core/storage.js +48 -0
  60. package/dist/core/storage.js.map +1 -0
  61. package/dist/index.d.ts +18 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +3 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/node/index.d.ts +9 -0
  66. package/dist/node/index.d.ts.map +1 -0
  67. package/dist/node/index.js +9 -0
  68. package/dist/node/index.js.map +1 -0
  69. package/dist/node/platform.d.ts +25 -0
  70. package/dist/node/platform.d.ts.map +1 -0
  71. package/dist/node/platform.js +161 -0
  72. package/dist/node/platform.js.map +1 -0
  73. package/dist/seba.d.ts +39 -0
  74. package/dist/seba.d.ts.map +1 -0
  75. package/dist/seba.js +58 -0
  76. package/dist/seba.js.map +1 -0
  77. package/dist/types.d.ts +279 -0
  78. package/dist/types.d.ts.map +1 -0
  79. package/dist/types.js +8 -0
  80. package/dist/types.js.map +1 -0
  81. package/examples/node/index.ts +61 -0
  82. package/examples/react/App.tsx +127 -0
  83. package/examples/react/index.html +12 -0
  84. package/examples/react/main.tsx +14 -0
  85. package/examples/react/vite.config.ts +27 -0
  86. package/package.json +83 -4
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Runtime-independent implementation of the four public operations.
3
+ *
4
+ * The platform object supplies storage, navigation, callback capture and `fetch`; this
5
+ * class owns the protocol flow and the security decisions that must be identical in
6
+ * every runtime.
7
+ */
8
+ import { createDPoPKey } from "./dpop.js";
9
+ import { SebaAuthError, SebaConfigError, SebaNoUIError } from "./errors.js";
10
+ import { discoverProvider, isLoopbackHost } from "./discovery.js";
11
+ import { httpFetch, inputToString } from "./http.js";
12
+ import { assertRedirectUriPublished, discoverIssuerForWebId, loadClientIdDocument, validateClientIdUrl, validateWebId, } from "./identity.js";
13
+ import { buildAuthorizationUrl, createPendingAuthorization, exchangeAuthorizationCode, parseAuthorizationResponse, pkceChallenge, } from "./oidc.js";
14
+ import { SessionManager } from "./session.js";
15
+ import { assertStorageKind } from "./session.js";
16
+ /** HTTP statuses that carry a `Location` header. */
17
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
18
+ /** Maximum same-origin redirects followed by {@link SebaClient.fetch}. */
19
+ const MAX_REDIRECTS = 5;
20
+ /** Hard cap on attempts per logical request (redirects, nonce and token refresh included). */
21
+ const MAX_ATTEMPTS = 8;
22
+ /**
23
+ * The protocol engine behind {@link Seba}.
24
+ *
25
+ * Obtained through `Seba`, which resolves the platform first. Not exported from the
26
+ * package entry point.
27
+ */
28
+ export class SebaClient {
29
+ #platform;
30
+ #config;
31
+ #sessions;
32
+ #nonce = null;
33
+ constructor(config, platform) {
34
+ this.#platform = platform;
35
+ this.#config = resolveConfig(config, platform);
36
+ this.#sessions = new SessionManager({
37
+ clientId: this.#config.clientId,
38
+ storage: platform.createStorage(this.#config.storage),
39
+ fetchImpl: platform.fetch,
40
+ discover: (issuer) => discoverProvider(issuer, platform.fetch),
41
+ debug: (message) => {
42
+ this.#debug(message);
43
+ },
44
+ });
45
+ }
46
+ /** Current session, if any (token-free). */
47
+ get session() {
48
+ return this.#sessions.toPublicSession();
49
+ }
50
+ /**
51
+ * Sign in, or finish a sign-in that the provider redirected back to this application.
52
+ *
53
+ * When the current URL carries an authorization response, the stored transaction is
54
+ * validated and the code is exchanged. Otherwise a new authorization request is
55
+ * started: the returned promise resolves after the redirect in Node.js and never
56
+ * settles in the browser (the page navigates away).
57
+ */
58
+ async login(options = {}) {
59
+ const callbackUrl = this.#callbackUrl();
60
+ if (callbackUrl !== null) {
61
+ return this.#completeLogin(callbackUrl);
62
+ }
63
+ const existing = this.#sessions.toPublicSession();
64
+ if (existing !== null) {
65
+ return existing;
66
+ }
67
+ return this.#startLogin(options);
68
+ }
69
+ /**
70
+ * Restore a previous session from storage.
71
+ *
72
+ * @returns The session, or `null` when nothing is stored.
73
+ * @throws SebaSessionExpiredError when the stored grant was revoked (state cleared).
74
+ */
75
+ async restoreSession() {
76
+ return this.#sessions.restore();
77
+ }
78
+ /**
79
+ * Perform a DPoP-authenticated request.
80
+ *
81
+ * A fresh proof is created for every attempt. Same-origin redirects are followed with a
82
+ * new proof per hop; cross-origin redirects are returned to the caller unchanged, so
83
+ * credentials are never forwarded to another origin. One retry is allowed for a DPoP
84
+ * nonce challenge and one for an expired access token; non-replayable bodies are never
85
+ * resent.
86
+ */
87
+ async fetch(input, init) {
88
+ this.#sessions.require();
89
+ if (this.#sessions.isExpired()) {
90
+ await this.#sessions.refreshIfNeeded();
91
+ }
92
+ const template = buildTemplate(input, init);
93
+ const replayable = isReplayable(input, init);
94
+ const body = template.body === null ? null : replayable ? await readBody(template) : template.body;
95
+ const origin = new URL(template.url).origin;
96
+ let current = {
97
+ url: template.url,
98
+ method: template.method,
99
+ headers: new Headers(template.headers),
100
+ };
101
+ let redirects = 0;
102
+ let nonceRetried = false;
103
+ let tokenRetried = false;
104
+ for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {
105
+ const state = this.#sessions.require();
106
+ const accessToken = state.tokens.accessToken;
107
+ const headers = new Headers(current.headers);
108
+ headers.set("authorization", `DPoP ${accessToken}`);
109
+ headers.set("DPoP", await state.signer.createProof({
110
+ method: current.method,
111
+ url: current.url,
112
+ accessToken,
113
+ ...(this.#nonce === null ? {} : { nonce: this.#nonce }),
114
+ }));
115
+ const response = await this.#send(current, headers, body, init?.signal ?? null);
116
+ const nonce = response.headers.get("dpop-nonce");
117
+ if (nonce !== null) {
118
+ this.#nonce = nonce;
119
+ }
120
+ if (REDIRECT_STATUSES.has(response.status)) {
121
+ const location = response.headers.get("location");
122
+ const next = location === null ? null : safeResolve(location, current.url);
123
+ if (next === null || next.origin !== origin || redirects >= MAX_REDIRECTS || !replayable) {
124
+ return response;
125
+ }
126
+ redirects += 1;
127
+ const method = downgradeToGet(response.status, current.method) ? "GET" : current.method;
128
+ current = {
129
+ url: next.href,
130
+ method,
131
+ headers: current.headers,
132
+ };
133
+ continue;
134
+ }
135
+ if (response.status === 400 || response.status === 401) {
136
+ if (nonce !== null && !nonceRetried && replayable) {
137
+ nonceRetried = true;
138
+ continue;
139
+ }
140
+ if (response.status === 401 && !tokenRetried && replayable) {
141
+ tokenRetried = true;
142
+ await this.#sessions.refreshIfNeeded(true);
143
+ continue;
144
+ }
145
+ }
146
+ return response;
147
+ }
148
+ throw new SebaAuthError("The request could not be completed after following redirects and retrying the DPoP nonce and access token. " +
149
+ "Reduce the redirect chain or check that the resource server accepts the session's DPoP key.");
150
+ }
151
+ /** Sign out, revoking the refresh token when the provider supports revocation. */
152
+ async logout() {
153
+ await this.#sessions.logout();
154
+ }
155
+ async #send(request, headers, body, signal) {
156
+ const init = {
157
+ method: request.method,
158
+ headers,
159
+ redirect: "manual",
160
+ };
161
+ if (body !== null && request.method !== "GET" && request.method !== "HEAD") {
162
+ init.body = body;
163
+ if (body instanceof ReadableStream) {
164
+ init.duplex = "half";
165
+ }
166
+ }
167
+ return httpFetch(request.url, init, {
168
+ fetchImpl: this.#platform.fetch,
169
+ signal,
170
+ });
171
+ }
172
+ async #startLogin(options) {
173
+ let webId = options.webId === undefined ? undefined : validateWebId(options.webId).webId;
174
+ let issuer = options.issuer;
175
+ if (webId === undefined && issuer === undefined) {
176
+ if (this.#platform.selectIdentity === undefined) {
177
+ throw new SebaNoUIError("No WebID or identity provider was provided and this runtime cannot ask the user. " +
178
+ "Call login({ issuer }) or login({ webId }) in Node.js.");
179
+ }
180
+ const chosen = await this.#platform.selectIdentity();
181
+ webId = chosen.webId === undefined ? undefined : validateWebId(chosen.webId).webId;
182
+ issuer = chosen.issuer;
183
+ }
184
+ if (issuer === undefined && webId !== undefined) {
185
+ issuer = await discoverIssuerForWebId(webId, this.#platform.fetch);
186
+ }
187
+ if (issuer === undefined) {
188
+ throw new SebaConfigError("Login requires either a WebID or an identity provider issuer. Neither was provided.");
189
+ }
190
+ const configuration = await discoverProvider(issuer, this.#platform.fetch);
191
+ const document = await loadClientIdDocument(this.#config.clientId, this.#platform.fetch);
192
+ assertRedirectUriPublished(document, this.#config.redirectUri);
193
+ const pending = await createPendingAuthorization({
194
+ issuer: configuration.issuer,
195
+ clientId: this.#config.clientId,
196
+ redirectUri: this.#config.redirectUri,
197
+ ...(webId === undefined ? {} : { webId }),
198
+ });
199
+ const codeChallenge = await pkceChallenge(pending.codeVerifier);
200
+ const authorizationUrl = buildAuthorizationUrl({
201
+ configuration,
202
+ clientId: this.#config.clientId,
203
+ redirectUri: this.#config.redirectUri,
204
+ state: pending.state,
205
+ nonce: pending.nonce,
206
+ codeChallenge,
207
+ });
208
+ await this.#platform.pendingAuth.save(pending);
209
+ this.#debug(`starting authorization at ${describeEndpoint(configuration.authorizationEndpoint)}`);
210
+ const responseUrl = await this.#platform.beginInteractiveLogin({
211
+ authorizationUrl,
212
+ redirectUri: this.#config.redirectUri,
213
+ state: pending.state,
214
+ ...(this.#config.openAuthorizationUrl === undefined
215
+ ? {}
216
+ : { openAuthorizationUrl: this.#config.openAuthorizationUrl }),
217
+ });
218
+ return this.#completeLogin(responseUrl.href);
219
+ }
220
+ async #completeLogin(callbackUrl) {
221
+ const pending = await this.#platform.pendingAuth.load();
222
+ if (pending === null) {
223
+ throw new SebaAuthError("An authorization response was found in the URL, but no login is pending. " +
224
+ "Start the login from this application; responses from other tabs or sessions are ignored.");
225
+ }
226
+ if (pending.clientId !== this.#config.clientId || pending.redirectUri !== this.#config.redirectUri) {
227
+ await this.#platform.pendingAuth.clear();
228
+ throw new SebaAuthError("The pending login was started for a different client or redirect URI. The response was ignored.");
229
+ }
230
+ const code = parseAuthorizationResponse(callbackUrl, pending);
231
+ const configuration = await discoverProvider(pending.issuer, this.#platform.fetch);
232
+ const material = await createDPoPKey();
233
+ const result = await exchangeAuthorizationCode({
234
+ configuration,
235
+ clientId: this.#config.clientId,
236
+ redirectUri: this.#config.redirectUri,
237
+ code,
238
+ codeVerifier: pending.codeVerifier,
239
+ nonce: pending.nonce,
240
+ signer: material.signer,
241
+ fetchImpl: this.#platform.fetch,
242
+ ...(pending.webId === undefined ? {} : { expectedWebId: pending.webId }),
243
+ });
244
+ await this.#sessions.adopt({
245
+ tokens: result.tokens,
246
+ identity: result.identity,
247
+ signer: material.signer,
248
+ key: material.persisted,
249
+ configuration,
250
+ });
251
+ await this.#platform.pendingAuth.clear();
252
+ this.#platform.clearCallback?.();
253
+ this.#debug(`authenticated as ${result.identity.webId}`);
254
+ const session = this.#sessions.toPublicSession();
255
+ if (session === null) {
256
+ throw new SebaAuthError("The session was created but could not be read back.");
257
+ }
258
+ return session;
259
+ }
260
+ #callbackUrl() {
261
+ const url = this.#platform.currentUrl();
262
+ if (url === null) {
263
+ return null;
264
+ }
265
+ const params = url.searchParams;
266
+ if (!params.has("code") && !params.has("error")) {
267
+ return null;
268
+ }
269
+ if (!params.has("state")) {
270
+ return null;
271
+ }
272
+ let configured;
273
+ try {
274
+ configured = new URL(this.#config.redirectUri);
275
+ }
276
+ catch {
277
+ return null;
278
+ }
279
+ if (url.origin !== configured.origin || url.pathname !== configured.pathname) {
280
+ return null;
281
+ }
282
+ return url.href;
283
+ }
284
+ #debug(message) {
285
+ if (!this.#config.debug) {
286
+ return;
287
+ }
288
+ console.debug(`[seba] ${message}`);
289
+ }
290
+ }
291
+ function resolveConfig(config, platform) {
292
+ const clientId = validateClientIdUrl(config.clientId);
293
+ let redirect;
294
+ try {
295
+ redirect = new URL(config.redirectUri);
296
+ }
297
+ catch {
298
+ throw new SebaConfigError(`The redirectUri "${config.redirectUri}" is not an absolute URL. ` +
299
+ 'Use the callback URL published in your Client ID Document, for example "https://app.example/auth/callback".');
300
+ }
301
+ if (redirect.protocol !== "https:" && !(redirect.protocol === "http:" && isLoopbackHost(redirect.hostname))) {
302
+ throw new SebaConfigError(`The redirectUri "${config.redirectUri}" must use https. ` +
303
+ "Plain http is only accepted for loopback development hosts.");
304
+ }
305
+ if (platform.kind === "node" && !isLoopbackHost(redirect.hostname)) {
306
+ throw new SebaConfigError(`In Node.js the redirectUri must point at a loopback interface (127.0.0.1, ::1 or localhost), ` +
307
+ `but "${config.redirectUri}" does not. The temporary callback server only listens on loopback.`);
308
+ }
309
+ const storage = config.storage ?? platform.defaultStorage;
310
+ assertStorageKind(storage);
311
+ return {
312
+ clientId,
313
+ redirectUri: config.redirectUri,
314
+ storage,
315
+ debug: config.debug === true,
316
+ ...(config.openAuthorizationUrl === undefined ? {} : { openAuthorizationUrl: config.openAuthorizationUrl }),
317
+ };
318
+ }
319
+ function buildTemplate(input, init) {
320
+ try {
321
+ return new Request(input, init);
322
+ }
323
+ catch (error) {
324
+ throw new SebaConfigError(`The request for "${safeDescribe(inputToString(input))}" could not be constructed. ` +
325
+ "Use an absolute URL and a body type accepted by fetch.", { cause: error });
326
+ }
327
+ }
328
+ function isReplayable(input, init) {
329
+ if (init?.body instanceof ReadableStream) {
330
+ return false;
331
+ }
332
+ if (input instanceof Request && input.body !== null) {
333
+ return false;
334
+ }
335
+ return true;
336
+ }
337
+ async function readBody(request) {
338
+ try {
339
+ return await request.arrayBuffer();
340
+ }
341
+ catch (error) {
342
+ throw new SebaConfigError("The request body could not be read.", { cause: error });
343
+ }
344
+ }
345
+ function downgradeToGet(status, method) {
346
+ if (status === 303) {
347
+ return true;
348
+ }
349
+ return (status === 301 || status === 302) && method === "POST";
350
+ }
351
+ function safeResolve(location, base) {
352
+ try {
353
+ return new URL(location, base);
354
+ }
355
+ catch {
356
+ return null;
357
+ }
358
+ }
359
+ function safeDescribe(value) {
360
+ try {
361
+ const url = new URL(value);
362
+ return `${url.origin}${url.pathname}`;
363
+ }
364
+ catch {
365
+ return "the request URL";
366
+ }
367
+ }
368
+ function describeEndpoint(value) {
369
+ return safeDescribe(value);
370
+ }
371
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * OpenID Provider discovery (OpenID Connect Discovery 1.0 §3–§4).
3
+ *
4
+ * SEBA only trusts a discovery document whose `issuer` is byte-identical to the issuer it
5
+ * asked for, and only uses `https` endpoints (loopback `http` for local development).
6
+ */
7
+ import type { OIDCConfiguration } from "../types.js";
8
+ /**
9
+ * Whether a hostname is a loopback interface.
10
+ *
11
+ * @param hostname - Hostname from a parsed URL.
12
+ */
13
+ export declare function isLoopbackHost(hostname: string): boolean;
14
+ /**
15
+ * Validate an issuer identifier.
16
+ *
17
+ * Rules applied (Solid-OIDC §6.1, OIDC Discovery §3): absolute URL, `https` scheme (plain
18
+ * `http` is accepted for loopback development hosts only), a host, and no query or
19
+ * fragment. The issuer string is returned unchanged because issuer identity is exact.
20
+ *
21
+ * @param issuer - Candidate issuer URL.
22
+ * @param label - Field name used in error messages.
23
+ * @throws {@link SebaDiscoveryError} when the value is not a usable issuer.
24
+ */
25
+ export declare function validateIssuerUrl(issuer: string, label?: string): string;
26
+ /**
27
+ * Candidate well-known configuration URLs for an issuer.
28
+ *
29
+ * RFC 8414 inserts the well-known segment between host and path; several providers only
30
+ * serve the appended form. Both are tried, in that order, and only on 404.
31
+ *
32
+ * @param issuer - Validated issuer URL.
33
+ */
34
+ export declare function wellKnownCandidates(issuer: string): string[];
35
+ /**
36
+ * Compare a provider-declared issuer with the requested one.
37
+ *
38
+ * Exact equality is required, with one narrowly scoped exception: a provider whose issuer
39
+ * has an empty path may publish it as `https://host/` while the caller typed
40
+ * `https://host` (no path). Both denote the same identifier and real providers
41
+ * (solidcommunity.net, solidweb.me, Community Solid Server) publish the trailing-slash
42
+ * form. Nothing else is normalized: paths, ports, schemes and query strings must match.
43
+ *
44
+ * @param declared - Issuer string from the discovery document.
45
+ * @param requested - Issuer string the caller asked for.
46
+ */
47
+ export declare function issuerEquivalent(declared: string, requested: string): boolean;
48
+ /**
49
+ * Validate an endpoint URL from provider metadata.
50
+ *
51
+ * @param value - Candidate value from the discovery document.
52
+ * @param field - Metadata member name, used in error messages.
53
+ * @param issuer - Issuer the document was fetched for, used in error messages.
54
+ */
55
+ export declare function validateEndpointUrl(value: unknown, field: string, issuer: string): string;
56
+ /**
57
+ * Parse and validate an OpenID Provider configuration document.
58
+ *
59
+ * @param raw - Parsed JSON document.
60
+ * @param requestedIssuer - Issuer that was requested; must match the document exactly.
61
+ */
62
+ export declare function parseProviderConfiguration(raw: unknown, requestedIssuer: string): OIDCConfiguration;
63
+ /**
64
+ * Fetch and validate the OpenID Provider configuration for an issuer.
65
+ *
66
+ * @param issuer - Issuer identifier supplied by configuration, WebID discovery or the user.
67
+ * @param fetchImpl - Runtime `fetch` implementation.
68
+ * @throws {@link SebaDiscoveryError} for an unusable issuer or an invalid/missing document.
69
+ * @throws {@link SebaNetworkError} when the provider cannot be reached.
70
+ */
71
+ export declare function discoverProvider(issuer: string, fetchImpl: typeof fetch): Promise<OIDCConfiguration>;
72
+ /**
73
+ * Whether a provider advertises Solid `webid` scope support.
74
+ *
75
+ * Used to decide whether Solid-specific ID token requirements (`aud` containing `solid`,
76
+ * `cnf.jkt` binding) are enforced. A provider that does not publish `scopes_supported` is
77
+ * treated as not advertising `webid`, so standard OIDC validation applies.
78
+ *
79
+ * @param configuration - Validated provider configuration.
80
+ */
81
+ export declare function advertisesWebIdScope(configuration: OIDCConfiguration): boolean;
82
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,MAAM,CA6B1E;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAoB7E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAsBzF;AAYD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,iBAAiB,CAiEnG;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiC1G;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,iBAAiB,GAAG,OAAO,CAE9E"}