@aturi.to/waypoints 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +6 -6
- package/dist/index.cjs +321 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +320 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ type WaypointType = 'post' | 'profile' | 'list' | 'record' | 'unknown';
|
|
|
6
6
|
* atproto collections). Display groupings live in `WAYPOINT_CATEGORIES_DATA`
|
|
7
7
|
* and are independent of this.
|
|
8
8
|
*/
|
|
9
|
-
type RedirectCompatFamily = 'bluesky-social' | 'standard-site' | 'tangled' | 'margin' | 'grain' | 'pinksky' | 'semble' | 'streamplace' | 'popfeed' | 'sifa' | 'blento';
|
|
9
|
+
type RedirectCompatFamily = 'bluesky-social' | 'standard-site' | 'tangled' | 'margin' | 'grain' | 'pinksky' | 'semble' | 'streamplace' | 'popfeed' | 'sifa' | 'blento' | 'atproto-explorer';
|
|
10
10
|
type WaypointData = {
|
|
11
11
|
id: string;
|
|
12
12
|
name: string;
|
|
@@ -110,13 +110,32 @@ declare function parseURI(handle: string, collection?: string, rkey?: string): P
|
|
|
110
110
|
/**
|
|
111
111
|
* Resolve a handle to a DID using the Bluesky API
|
|
112
112
|
*/
|
|
113
|
+
/**
|
|
114
|
+
* Handle resolution that distinguishes a definitive "no such handle" from a
|
|
115
|
+
* transient "resolver unavailable". Callers that need to decide between a real
|
|
116
|
+
* 404 and a retry state use this; `resolveHandle` remains for the common
|
|
117
|
+
* did-or-null case.
|
|
118
|
+
*
|
|
119
|
+
* - `not-found`: the appview returned a 4xx (invalid/unknown handle). Safe to
|
|
120
|
+
* surface as a 404.
|
|
121
|
+
* - `unavailable`: network failure or 5xx. Must NOT be shown as a 404 — it's a
|
|
122
|
+
* real account we couldn't look up right now.
|
|
123
|
+
*/
|
|
124
|
+
type HandleResolution = {
|
|
125
|
+
did: string;
|
|
126
|
+
reason?: undefined;
|
|
127
|
+
} | {
|
|
128
|
+
did: null;
|
|
129
|
+
reason: 'not-found' | 'unavailable';
|
|
130
|
+
};
|
|
131
|
+
declare function resolveHandleStatus(handle: string): Promise<HandleResolution>;
|
|
113
132
|
declare function resolveHandle(handle: string): Promise<string | null>;
|
|
114
133
|
/**
|
|
115
134
|
* Get display name from handle or DID
|
|
116
135
|
*/
|
|
117
136
|
declare function getDisplayName(handle: string, did?: string): string;
|
|
118
137
|
|
|
119
|
-
type SourceApp = 'bluesky' | 'bluepy' | 'blacksky' | 'reddwarf' | '
|
|
138
|
+
type SourceApp = 'aturi' | 'aturiExplore' | 'bluesky' | 'bluepy' | 'blacksky' | 'reddwarf' | 'impro' | 'witchsky' | 'deer' | 'mu' | 'anisota' | 'pinksky' | 'leaflet' | 'tangled' | 'margin' | 'pdsls' | 'atptools' | 'semble' | 'streamplace' | 'grain' | 'popfeed' | 'sifa' | 'blento' | 'standardReader' | 'taproot' | 'offprint' | 'pckt' | 'headDetected';
|
|
120
139
|
type ReverseMatch = {
|
|
121
140
|
source: SourceApp;
|
|
122
141
|
parsed: ParsedURI;
|
|
@@ -138,6 +157,13 @@ declare function parseAtUri(uri: string): ReverseMatch | null;
|
|
|
138
157
|
* worker to decide if a tab is "relevant" before doing more expensive work.
|
|
139
158
|
*/
|
|
140
159
|
declare const SUPPORTED_HOSTS: string[];
|
|
160
|
+
/**
|
|
161
|
+
* Whether a hostname belongs to a supported waypoint. Prefer this over a raw
|
|
162
|
+
* `SUPPORTED_HOSTS.includes(...)` check: it strips a leading `www.` and also
|
|
163
|
+
* recognizes subdomains of hosts that opt in (e.g. `eclose.anisota.net`), so
|
|
164
|
+
* the extension popup and resolve API treat those tabs as known.
|
|
165
|
+
*/
|
|
166
|
+
declare function isSupportedHost(host: string): boolean;
|
|
141
167
|
|
|
142
168
|
type ResolvedWaypoint = {
|
|
143
169
|
id: string;
|
|
@@ -259,4 +285,4 @@ type ResolveViaApiOptions = {
|
|
|
259
285
|
*/
|
|
260
286
|
declare function resolveViaApi(input: ResolveApiInput, options?: ResolveViaApiOptions): Promise<ResolveApiResponse>;
|
|
261
287
|
|
|
262
|
-
export { type BuildWaypointsOptions, CATEGORY_ORDER, COMPAT_FAMILIES, COMPAT_FAMILY_ORDER, type CategorizedWaypointsData, type CompatFamilyMeta, DID_REQUIRED_WAYPOINTS, type ParsedURI, type RedirectCompatFamily, type ResolveApiFailure, type ResolveApiInput, type ResolveApiParsed, type ResolveApiResponse, type ResolveApiSuccess, type ResolveResult, type ResolveUrlOptions, type ResolveViaApiOptions, type ResolvedRecommendation, type ResolvedWaypoint, type ReverseMatch, SUPPORTED_HOSTS, type SourceApp, WAYPOINT_CATEGORIES_DATA, WAYPOINT_DESTINATIONS_DATA, WAYPOINT_ORDER, type WaypointActivity, type WaypointCategoryData, type WaypointData, type WaypointType, buildWaypointsForParsed, getCategorizedWaypointsData, getDisplayName, getFeaturedWaypointData, getRecommendedWaypointsData, getWaypointCountData, getWaypointDataForType, matchSupportedUrl, parseAtUri, parseURI, resolveAtUri, resolveHandle, resolveUrl, resolveViaApi, waypointActivity };
|
|
288
|
+
export { type BuildWaypointsOptions, CATEGORY_ORDER, COMPAT_FAMILIES, COMPAT_FAMILY_ORDER, type CategorizedWaypointsData, type CompatFamilyMeta, DID_REQUIRED_WAYPOINTS, type HandleResolution, type ParsedURI, type RedirectCompatFamily, type ResolveApiFailure, type ResolveApiInput, type ResolveApiParsed, type ResolveApiResponse, type ResolveApiSuccess, type ResolveResult, type ResolveUrlOptions, type ResolveViaApiOptions, type ResolvedRecommendation, type ResolvedWaypoint, type ReverseMatch, SUPPORTED_HOSTS, type SourceApp, WAYPOINT_CATEGORIES_DATA, WAYPOINT_DESTINATIONS_DATA, WAYPOINT_ORDER, type WaypointActivity, type WaypointCategoryData, type WaypointData, type WaypointType, buildWaypointsForParsed, getCategorizedWaypointsData, getDisplayName, getFeaturedWaypointData, getRecommendedWaypointsData, getWaypointCountData, getWaypointDataForType, isSupportedHost, matchSupportedUrl, parseAtUri, parseURI, resolveAtUri, resolveHandle, resolveHandleStatus, resolveUrl, resolveViaApi, waypointActivity };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type WaypointType = 'post' | 'profile' | 'list' | 'record' | 'unknown';
|
|
|
6
6
|
* atproto collections). Display groupings live in `WAYPOINT_CATEGORIES_DATA`
|
|
7
7
|
* and are independent of this.
|
|
8
8
|
*/
|
|
9
|
-
type RedirectCompatFamily = 'bluesky-social' | 'standard-site' | 'tangled' | 'margin' | 'grain' | 'pinksky' | 'semble' | 'streamplace' | 'popfeed' | 'sifa' | 'blento';
|
|
9
|
+
type RedirectCompatFamily = 'bluesky-social' | 'standard-site' | 'tangled' | 'margin' | 'grain' | 'pinksky' | 'semble' | 'streamplace' | 'popfeed' | 'sifa' | 'blento' | 'atproto-explorer';
|
|
10
10
|
type WaypointData = {
|
|
11
11
|
id: string;
|
|
12
12
|
name: string;
|
|
@@ -110,13 +110,32 @@ declare function parseURI(handle: string, collection?: string, rkey?: string): P
|
|
|
110
110
|
/**
|
|
111
111
|
* Resolve a handle to a DID using the Bluesky API
|
|
112
112
|
*/
|
|
113
|
+
/**
|
|
114
|
+
* Handle resolution that distinguishes a definitive "no such handle" from a
|
|
115
|
+
* transient "resolver unavailable". Callers that need to decide between a real
|
|
116
|
+
* 404 and a retry state use this; `resolveHandle` remains for the common
|
|
117
|
+
* did-or-null case.
|
|
118
|
+
*
|
|
119
|
+
* - `not-found`: the appview returned a 4xx (invalid/unknown handle). Safe to
|
|
120
|
+
* surface as a 404.
|
|
121
|
+
* - `unavailable`: network failure or 5xx. Must NOT be shown as a 404 — it's a
|
|
122
|
+
* real account we couldn't look up right now.
|
|
123
|
+
*/
|
|
124
|
+
type HandleResolution = {
|
|
125
|
+
did: string;
|
|
126
|
+
reason?: undefined;
|
|
127
|
+
} | {
|
|
128
|
+
did: null;
|
|
129
|
+
reason: 'not-found' | 'unavailable';
|
|
130
|
+
};
|
|
131
|
+
declare function resolveHandleStatus(handle: string): Promise<HandleResolution>;
|
|
113
132
|
declare function resolveHandle(handle: string): Promise<string | null>;
|
|
114
133
|
/**
|
|
115
134
|
* Get display name from handle or DID
|
|
116
135
|
*/
|
|
117
136
|
declare function getDisplayName(handle: string, did?: string): string;
|
|
118
137
|
|
|
119
|
-
type SourceApp = 'bluesky' | 'bluepy' | 'blacksky' | 'reddwarf' | '
|
|
138
|
+
type SourceApp = 'aturi' | 'aturiExplore' | 'bluesky' | 'bluepy' | 'blacksky' | 'reddwarf' | 'impro' | 'witchsky' | 'deer' | 'mu' | 'anisota' | 'pinksky' | 'leaflet' | 'tangled' | 'margin' | 'pdsls' | 'atptools' | 'semble' | 'streamplace' | 'grain' | 'popfeed' | 'sifa' | 'blento' | 'standardReader' | 'taproot' | 'offprint' | 'pckt' | 'headDetected';
|
|
120
139
|
type ReverseMatch = {
|
|
121
140
|
source: SourceApp;
|
|
122
141
|
parsed: ParsedURI;
|
|
@@ -138,6 +157,13 @@ declare function parseAtUri(uri: string): ReverseMatch | null;
|
|
|
138
157
|
* worker to decide if a tab is "relevant" before doing more expensive work.
|
|
139
158
|
*/
|
|
140
159
|
declare const SUPPORTED_HOSTS: string[];
|
|
160
|
+
/**
|
|
161
|
+
* Whether a hostname belongs to a supported waypoint. Prefer this over a raw
|
|
162
|
+
* `SUPPORTED_HOSTS.includes(...)` check: it strips a leading `www.` and also
|
|
163
|
+
* recognizes subdomains of hosts that opt in (e.g. `eclose.anisota.net`), so
|
|
164
|
+
* the extension popup and resolve API treat those tabs as known.
|
|
165
|
+
*/
|
|
166
|
+
declare function isSupportedHost(host: string): boolean;
|
|
141
167
|
|
|
142
168
|
type ResolvedWaypoint = {
|
|
143
169
|
id: string;
|
|
@@ -259,4 +285,4 @@ type ResolveViaApiOptions = {
|
|
|
259
285
|
*/
|
|
260
286
|
declare function resolveViaApi(input: ResolveApiInput, options?: ResolveViaApiOptions): Promise<ResolveApiResponse>;
|
|
261
287
|
|
|
262
|
-
export { type BuildWaypointsOptions, CATEGORY_ORDER, COMPAT_FAMILIES, COMPAT_FAMILY_ORDER, type CategorizedWaypointsData, type CompatFamilyMeta, DID_REQUIRED_WAYPOINTS, type ParsedURI, type RedirectCompatFamily, type ResolveApiFailure, type ResolveApiInput, type ResolveApiParsed, type ResolveApiResponse, type ResolveApiSuccess, type ResolveResult, type ResolveUrlOptions, type ResolveViaApiOptions, type ResolvedRecommendation, type ResolvedWaypoint, type ReverseMatch, SUPPORTED_HOSTS, type SourceApp, WAYPOINT_CATEGORIES_DATA, WAYPOINT_DESTINATIONS_DATA, WAYPOINT_ORDER, type WaypointActivity, type WaypointCategoryData, type WaypointData, type WaypointType, buildWaypointsForParsed, getCategorizedWaypointsData, getDisplayName, getFeaturedWaypointData, getRecommendedWaypointsData, getWaypointCountData, getWaypointDataForType, matchSupportedUrl, parseAtUri, parseURI, resolveAtUri, resolveHandle, resolveUrl, resolveViaApi, waypointActivity };
|
|
288
|
+
export { type BuildWaypointsOptions, CATEGORY_ORDER, COMPAT_FAMILIES, COMPAT_FAMILY_ORDER, type CategorizedWaypointsData, type CompatFamilyMeta, DID_REQUIRED_WAYPOINTS, type HandleResolution, type ParsedURI, type RedirectCompatFamily, type ResolveApiFailure, type ResolveApiInput, type ResolveApiParsed, type ResolveApiResponse, type ResolveApiSuccess, type ResolveResult, type ResolveUrlOptions, type ResolveViaApiOptions, type ResolvedRecommendation, type ResolvedWaypoint, type ReverseMatch, SUPPORTED_HOSTS, type SourceApp, WAYPOINT_CATEGORIES_DATA, WAYPOINT_DESTINATIONS_DATA, WAYPOINT_ORDER, type WaypointActivity, type WaypointCategoryData, type WaypointData, type WaypointType, buildWaypointsForParsed, getCategorizedWaypointsData, getDisplayName, getFeaturedWaypointData, getRecommendedWaypointsData, getWaypointCountData, getWaypointDataForType, isSupportedHost, matchSupportedUrl, parseAtUri, parseURI, resolveAtUri, resolveHandle, resolveHandleStatus, resolveUrl, resolveViaApi, waypointActivity };
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,11 @@ var COMPAT_FAMILIES = {
|
|
|
54
54
|
id: "blento",
|
|
55
55
|
name: "Blento",
|
|
56
56
|
description: "Blento profiles."
|
|
57
|
+
},
|
|
58
|
+
"atproto-explorer": {
|
|
59
|
+
id: "atproto-explorer",
|
|
60
|
+
name: "Record explorers",
|
|
61
|
+
description: "Raw AT Protocol record explorers (pdsls, atp.tools, Aturi Explore) that render any record by its AT URI."
|
|
57
62
|
}
|
|
58
63
|
};
|
|
59
64
|
var COMPAT_FAMILY_ORDER = [
|
|
@@ -67,7 +72,8 @@ var COMPAT_FAMILY_ORDER = [
|
|
|
67
72
|
"streamplace",
|
|
68
73
|
"popfeed",
|
|
69
74
|
"sifa",
|
|
70
|
-
"blento"
|
|
75
|
+
"blento",
|
|
76
|
+
"atproto-explorer"
|
|
71
77
|
];
|
|
72
78
|
var WAYPOINT_DESTINATIONS_DATA = {
|
|
73
79
|
aturi: {
|
|
@@ -193,7 +199,32 @@ var WAYPOINT_DESTINATIONS_DATA = {
|
|
|
193
199
|
return `https://reddwarf.app/profile/${handle}`;
|
|
194
200
|
},
|
|
195
201
|
supportedTypes: ["post", "profile", "list", "record"],
|
|
196
|
-
category: "
|
|
202
|
+
category: "blueskyClients",
|
|
203
|
+
redirectCompat: ["bluesky-social"],
|
|
204
|
+
expectedCollections: ["app.bsky."]
|
|
205
|
+
},
|
|
206
|
+
impro: {
|
|
207
|
+
id: "impro",
|
|
208
|
+
name: "Impro",
|
|
209
|
+
description: (collection) => {
|
|
210
|
+
if (collection === "app.bsky.feed.post") return "View post on impro.social";
|
|
211
|
+
if (collection === "app.bsky.graph.list") return "View list on impro.social";
|
|
212
|
+
return "View profile on impro.social";
|
|
213
|
+
},
|
|
214
|
+
getUrl: (handle, collection, rkey) => {
|
|
215
|
+
if (collection && rkey) {
|
|
216
|
+
if (collection === "app.bsky.feed.post") {
|
|
217
|
+
return `https://impro.social/profile/${handle}/post/${rkey}`;
|
|
218
|
+
}
|
|
219
|
+
if (collection === "app.bsky.graph.list") {
|
|
220
|
+
return `https://impro.social/profile/${handle}/lists/${rkey}`;
|
|
221
|
+
}
|
|
222
|
+
return `https://impro.social/profile/${handle}`;
|
|
223
|
+
}
|
|
224
|
+
return `https://impro.social/profile/${handle}`;
|
|
225
|
+
},
|
|
226
|
+
supportedTypes: ["post", "profile", "list", "record"],
|
|
227
|
+
category: "blueskyClients",
|
|
197
228
|
redirectCompat: ["bluesky-social"],
|
|
198
229
|
expectedCollections: ["app.bsky."]
|
|
199
230
|
},
|
|
@@ -222,7 +253,7 @@ var WAYPOINT_DESTINATIONS_DATA = {
|
|
|
222
253
|
},
|
|
223
254
|
supportedTypes: ["post", "profile", "list", "record"],
|
|
224
255
|
category: "devTools",
|
|
225
|
-
redirectCompat: []
|
|
256
|
+
redirectCompat: ["atproto-explorer"]
|
|
226
257
|
},
|
|
227
258
|
aturiExplore: {
|
|
228
259
|
id: "aturiExplore",
|
|
@@ -243,7 +274,7 @@ var WAYPOINT_DESTINATIONS_DATA = {
|
|
|
243
274
|
},
|
|
244
275
|
supportedTypes: ["post", "profile", "list", "record"],
|
|
245
276
|
category: "devTools",
|
|
246
|
-
redirectCompat: []
|
|
277
|
+
redirectCompat: ["atproto-explorer"]
|
|
247
278
|
},
|
|
248
279
|
atptools: {
|
|
249
280
|
id: "atptools",
|
|
@@ -258,7 +289,7 @@ var WAYPOINT_DESTINATIONS_DATA = {
|
|
|
258
289
|
},
|
|
259
290
|
supportedTypes: ["post", "profile", "list", "record"],
|
|
260
291
|
category: "devTools",
|
|
261
|
-
redirectCompat: []
|
|
292
|
+
redirectCompat: ["atproto-explorer"]
|
|
262
293
|
},
|
|
263
294
|
bluepy: {
|
|
264
295
|
id: "bluepy",
|
|
@@ -303,44 +334,44 @@ var WAYPOINT_DESTINATIONS_DATA = {
|
|
|
303
334
|
redirectCompat: ["bluesky-social"],
|
|
304
335
|
expectedCollections: ["app.bsky."]
|
|
305
336
|
},
|
|
306
|
-
|
|
307
|
-
id: "
|
|
308
|
-
name: "
|
|
337
|
+
deer: {
|
|
338
|
+
id: "deer",
|
|
339
|
+
name: "Deer",
|
|
309
340
|
description: (collection) => {
|
|
310
|
-
if (collection === "app.bsky.feed.post") return "View post on
|
|
311
|
-
if (collection === "app.bsky.graph.list") return "View list on
|
|
312
|
-
return "View profile on
|
|
341
|
+
if (collection === "app.bsky.feed.post") return "View post on deer.social";
|
|
342
|
+
if (collection === "app.bsky.graph.list") return "View list on deer.social";
|
|
343
|
+
return "View profile on deer.social";
|
|
313
344
|
},
|
|
314
345
|
getUrl: (handle, collection, rkey) => {
|
|
315
346
|
if (collection && rkey) {
|
|
316
347
|
if (collection === "app.bsky.feed.post") {
|
|
317
|
-
return `https://
|
|
348
|
+
return `https://deer.social/profile/${handle}/post/${rkey}`;
|
|
318
349
|
}
|
|
319
|
-
return `https://
|
|
350
|
+
return `https://deer.social/profile/${handle}`;
|
|
320
351
|
}
|
|
321
|
-
return `https://
|
|
352
|
+
return `https://deer.social/profile/${handle}`;
|
|
322
353
|
},
|
|
323
354
|
supportedTypes: ["post", "profile", "list", "record"],
|
|
324
355
|
category: "blueskyForks",
|
|
325
356
|
redirectCompat: ["bluesky-social"],
|
|
326
357
|
expectedCollections: ["app.bsky."]
|
|
327
358
|
},
|
|
328
|
-
|
|
329
|
-
id: "
|
|
330
|
-
name: "
|
|
359
|
+
mu: {
|
|
360
|
+
id: "mu",
|
|
361
|
+
name: "Mu",
|
|
331
362
|
description: (collection) => {
|
|
332
|
-
if (collection === "app.bsky.feed.post") return "View post on
|
|
333
|
-
if (collection === "app.bsky.graph.list") return "View list on
|
|
334
|
-
return "View profile on
|
|
363
|
+
if (collection === "app.bsky.feed.post") return "View post on mu.social";
|
|
364
|
+
if (collection === "app.bsky.graph.list") return "View list on mu.social";
|
|
365
|
+
return "View profile on mu.social";
|
|
335
366
|
},
|
|
336
367
|
getUrl: (handle, collection, rkey) => {
|
|
337
368
|
if (collection && rkey) {
|
|
338
369
|
if (collection === "app.bsky.feed.post") {
|
|
339
|
-
return `https://
|
|
370
|
+
return `https://mu.social/profile/${handle}/post/${rkey}`;
|
|
340
371
|
}
|
|
341
|
-
return `https://
|
|
372
|
+
return `https://mu.social/profile/${handle}`;
|
|
342
373
|
}
|
|
343
|
-
return `https://
|
|
374
|
+
return `https://mu.social/profile/${handle}`;
|
|
344
375
|
},
|
|
345
376
|
supportedTypes: ["post", "profile", "list", "record"],
|
|
346
377
|
category: "blueskyForks",
|
|
@@ -553,14 +584,54 @@ var WAYPOINT_DESTINATIONS_DATA = {
|
|
|
553
584
|
category: "publications",
|
|
554
585
|
redirectCompat: ["standard-site"],
|
|
555
586
|
expectedCollections: ["pub.leaflet.", "site.standard."]
|
|
587
|
+
},
|
|
588
|
+
standardReader: {
|
|
589
|
+
id: "standardReader",
|
|
590
|
+
name: "Standard Reader",
|
|
591
|
+
description: (collection) => {
|
|
592
|
+
if (collection?.startsWith("site.standard.") || collection?.startsWith("pub.leaflet.")) {
|
|
593
|
+
return "Read document on standard-reader.app";
|
|
594
|
+
}
|
|
595
|
+
return "View documents on standard-reader.app";
|
|
596
|
+
},
|
|
597
|
+
getUrl: (handle, collection, rkey, did) => {
|
|
598
|
+
const identifier = did || handle;
|
|
599
|
+
if (collection && rkey && (collection.startsWith("site.standard.") || collection.startsWith("pub.leaflet."))) {
|
|
600
|
+
return `https://standard-reader.app/a/${identifier}/${rkey}`;
|
|
601
|
+
}
|
|
602
|
+
return `https://standard-reader.app/u/${identifier}`;
|
|
603
|
+
},
|
|
604
|
+
supportedTypes: ["post", "profile", "list", "record"],
|
|
605
|
+
category: "publications",
|
|
606
|
+
redirectCompat: ["standard-site"],
|
|
607
|
+
expectedCollections: ["pub.leaflet.", "site.standard."]
|
|
608
|
+
},
|
|
609
|
+
taproot: {
|
|
610
|
+
id: "taproot",
|
|
611
|
+
name: "Taproot",
|
|
612
|
+
description: (collection) => {
|
|
613
|
+
if (collection) return "Inspect record on atproto.at";
|
|
614
|
+
return "Browse repo on atproto.at";
|
|
615
|
+
},
|
|
616
|
+
getUrl: (handle, collection, rkey, did) => {
|
|
617
|
+
const identifier = did || handle;
|
|
618
|
+
if (collection && rkey) {
|
|
619
|
+
return `https://atproto.at/uri/at://${identifier}/${collection}/${rkey}`;
|
|
620
|
+
}
|
|
621
|
+
return `https://atproto.at/uri/at://${identifier}`;
|
|
622
|
+
},
|
|
623
|
+
supportedTypes: ["post", "profile", "list", "record"],
|
|
624
|
+
category: "devTools",
|
|
625
|
+
redirectCompat: []
|
|
556
626
|
}
|
|
557
627
|
};
|
|
558
628
|
var WAYPOINT_ORDER = [
|
|
559
629
|
"anisota",
|
|
560
630
|
"bluesky",
|
|
561
631
|
"bluepy",
|
|
562
|
-
"blacksky",
|
|
563
632
|
"reddwarf",
|
|
633
|
+
"impro",
|
|
634
|
+
"blacksky",
|
|
564
635
|
"leaflet",
|
|
565
636
|
"aturi",
|
|
566
637
|
"pinksky",
|
|
@@ -574,12 +645,14 @@ var WAYPOINT_ORDER = [
|
|
|
574
645
|
"anisotaReader",
|
|
575
646
|
"offprint",
|
|
576
647
|
"pckt",
|
|
648
|
+
"standardReader",
|
|
577
649
|
"aturiExplore",
|
|
578
650
|
"pdsls",
|
|
579
651
|
"tangled",
|
|
580
652
|
"atptools",
|
|
653
|
+
"taproot",
|
|
581
654
|
"witchsky",
|
|
582
|
-
"
|
|
655
|
+
"mu",
|
|
583
656
|
"deer"
|
|
584
657
|
];
|
|
585
658
|
function getWaypointDataForType(type) {
|
|
@@ -674,13 +747,13 @@ var RECOMMENDED_WAYPOINTS = {
|
|
|
674
747
|
label: "Recommended for Repos"
|
|
675
748
|
},
|
|
676
749
|
"record": {
|
|
677
|
-
waypointIds: ["aturiExplore", "pdsls", "atptools"],
|
|
750
|
+
waypointIds: ["aturiExplore", "pdsls", "atptools", "taproot"],
|
|
678
751
|
label: "Recommended for Records"
|
|
679
752
|
}
|
|
680
753
|
};
|
|
681
754
|
var RECOMMENDED_NAMESPACE_PREFIXES = {
|
|
682
755
|
"site.standard": {
|
|
683
|
-
waypointIds: ["leaflet", "anisotaReader", "offprint", "pckt", "pdsls"],
|
|
756
|
+
waypointIds: ["leaflet", "standardReader", "anisotaReader", "offprint", "pckt", "pdsls"],
|
|
684
757
|
label: "Recommended for Publications"
|
|
685
758
|
},
|
|
686
759
|
"pub.leaflet": {
|
|
@@ -748,6 +821,26 @@ function waypointActivity(waypoint, repoCollections) {
|
|
|
748
821
|
return "absent";
|
|
749
822
|
}
|
|
750
823
|
|
|
824
|
+
// src/upstreamFetch.ts
|
|
825
|
+
var RETRY_DELAY_MS = 250;
|
|
826
|
+
async function upstreamFetch(url, { timeoutMs = 8e3, retries = 1, ...init } = {}) {
|
|
827
|
+
let lastError;
|
|
828
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
829
|
+
try {
|
|
830
|
+
return await fetch(url, {
|
|
831
|
+
...init,
|
|
832
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
833
|
+
});
|
|
834
|
+
} catch (error) {
|
|
835
|
+
lastError = error;
|
|
836
|
+
if (attempt < retries) {
|
|
837
|
+
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
throw lastError;
|
|
842
|
+
}
|
|
843
|
+
|
|
751
844
|
// src/uriParser.ts
|
|
752
845
|
function parseURI(handle, collection, rkey) {
|
|
753
846
|
if (!handle) {
|
|
@@ -789,25 +882,29 @@ function parseURI(handle, collection, rkey) {
|
|
|
789
882
|
error: "Invalid URI structure"
|
|
790
883
|
};
|
|
791
884
|
}
|
|
792
|
-
async function
|
|
885
|
+
async function resolveHandleStatus(handle) {
|
|
793
886
|
if (handle.startsWith("did:")) {
|
|
794
|
-
return handle;
|
|
887
|
+
return { did: handle };
|
|
795
888
|
}
|
|
796
889
|
try {
|
|
797
890
|
const apiUrl = process.env.NEXT_PUBLIC_BSKY_API_URL || "https://public.api.bsky.app";
|
|
798
|
-
const response = await
|
|
891
|
+
const response = await upstreamFetch(
|
|
799
892
|
`${apiUrl}/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`
|
|
800
893
|
);
|
|
801
894
|
if (!response.ok) {
|
|
802
|
-
return null;
|
|
895
|
+
return { did: null, reason: response.status >= 500 ? "unavailable" : "not-found" };
|
|
803
896
|
}
|
|
804
897
|
const data = await response.json();
|
|
805
|
-
return data.did
|
|
898
|
+
if (data.did) return { did: data.did };
|
|
899
|
+
return { did: null, reason: "not-found" };
|
|
806
900
|
} catch (error) {
|
|
807
901
|
console.error("Error resolving handle:", error);
|
|
808
|
-
return null;
|
|
902
|
+
return { did: null, reason: "unavailable" };
|
|
809
903
|
}
|
|
810
904
|
}
|
|
905
|
+
async function resolveHandle(handle) {
|
|
906
|
+
return (await resolveHandleStatus(handle)).did;
|
|
907
|
+
}
|
|
811
908
|
function getDisplayName(handle, did) {
|
|
812
909
|
if (handle.startsWith("did:")) {
|
|
813
910
|
return did ? `@${did.slice(0, 16)}...` : "Unknown";
|
|
@@ -820,16 +917,28 @@ var BLUESKY_FAMILY = [
|
|
|
820
917
|
{ source: "bluesky", hosts: ["bsky.app"] },
|
|
821
918
|
{ source: "blacksky", hosts: ["blacksky.community"] },
|
|
822
919
|
{ source: "reddwarf", hosts: ["reddwarf.app"] },
|
|
920
|
+
{ source: "impro", hosts: ["impro.social"] },
|
|
823
921
|
{ source: "witchsky", hosts: ["witchsky.app"] },
|
|
824
|
-
{ source: "catsky", hosts: ["catsky.social"] },
|
|
825
922
|
{ source: "deer", hosts: ["deer.social"] },
|
|
826
|
-
{ source: "
|
|
923
|
+
{ source: "mu", hosts: ["mu.social"] },
|
|
924
|
+
{ source: "anisota", hosts: ["anisota.net"], matchSubdomains: true }
|
|
827
925
|
];
|
|
926
|
+
var SUBDOMAIN_HOSTS = BLUESKY_FAMILY.filter((f) => f.matchSubdomains).flatMap(
|
|
927
|
+
(f) => f.hosts
|
|
928
|
+
);
|
|
828
929
|
function normalizeHost(host) {
|
|
829
930
|
return host.toLowerCase().replace(/^www\./, "");
|
|
830
931
|
}
|
|
932
|
+
function isSubdomainOf(host, base) {
|
|
933
|
+
return host.endsWith(`.${base}`);
|
|
934
|
+
}
|
|
935
|
+
function hostMatchesConfig(host, config) {
|
|
936
|
+
if (config.hosts.includes(host)) return true;
|
|
937
|
+
if (!config.matchSubdomains) return false;
|
|
938
|
+
return config.hosts.some((h) => isSubdomainOf(host, h));
|
|
939
|
+
}
|
|
831
940
|
function matchBlueskyFamily(host, parts) {
|
|
832
|
-
const entry = BLUESKY_FAMILY.find((f) =>
|
|
941
|
+
const entry = BLUESKY_FAMILY.find((f) => hostMatchesConfig(host, f));
|
|
833
942
|
if (!entry) return null;
|
|
834
943
|
if (parts[0] !== "profile" || !parts[1]) return null;
|
|
835
944
|
const handle = parts[1];
|
|
@@ -871,6 +980,19 @@ function matchBlueskyFamily(host, parts) {
|
|
|
871
980
|
}
|
|
872
981
|
};
|
|
873
982
|
}
|
|
983
|
+
if (parts[2] === "document" && parts[3]) {
|
|
984
|
+
return {
|
|
985
|
+
source: entry.source,
|
|
986
|
+
parsed: {
|
|
987
|
+
type: "record",
|
|
988
|
+
uri: `at://${handle}/site.standard.document/${parts[3]}`,
|
|
989
|
+
handle,
|
|
990
|
+
did,
|
|
991
|
+
collection: "site.standard.document",
|
|
992
|
+
rkey: parts[3]
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
}
|
|
874
996
|
return {
|
|
875
997
|
source: entry.source,
|
|
876
998
|
parsed: {
|
|
@@ -1141,11 +1263,160 @@ function matchBlento(host, parts) {
|
|
|
1141
1263
|
parsed: { type: "profile", uri: `at://${handle}`, handle, did }
|
|
1142
1264
|
};
|
|
1143
1265
|
}
|
|
1266
|
+
function matchStandardReader(host, parts) {
|
|
1267
|
+
if (host !== "standard-reader.app") return null;
|
|
1268
|
+
if (parts[0] === "a" && parts[1] && parts[2]) {
|
|
1269
|
+
const handle = parts[1];
|
|
1270
|
+
const did = handle.startsWith("did:") ? handle : void 0;
|
|
1271
|
+
const rkey = parts[2];
|
|
1272
|
+
return {
|
|
1273
|
+
source: "standardReader",
|
|
1274
|
+
parsed: {
|
|
1275
|
+
type: "record",
|
|
1276
|
+
uri: `at://${handle}/site.standard.document/${rkey}`,
|
|
1277
|
+
handle,
|
|
1278
|
+
did,
|
|
1279
|
+
collection: "site.standard.document",
|
|
1280
|
+
rkey
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
if (parts[0] === "u" && parts[1]) {
|
|
1285
|
+
const handle = parts[1];
|
|
1286
|
+
const did = handle.startsWith("did:") ? handle : void 0;
|
|
1287
|
+
return {
|
|
1288
|
+
source: "standardReader",
|
|
1289
|
+
parsed: { type: "profile", uri: `at://${handle}`, handle, did }
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
return null;
|
|
1293
|
+
}
|
|
1294
|
+
function matchFlatRecordHost(host, parts, target) {
|
|
1295
|
+
if (host !== target.host) return null;
|
|
1296
|
+
const [handle, collection, rkey] = parts;
|
|
1297
|
+
if (!handle || !collection || !rkey) return null;
|
|
1298
|
+
if (!collection.includes(".")) return null;
|
|
1299
|
+
const did = handle.startsWith("did:") ? handle : void 0;
|
|
1300
|
+
return {
|
|
1301
|
+
source: target.source,
|
|
1302
|
+
parsed: {
|
|
1303
|
+
type: inferType(collection),
|
|
1304
|
+
uri: `at://${handle}/${collection}/${rkey}`,
|
|
1305
|
+
handle,
|
|
1306
|
+
did,
|
|
1307
|
+
collection,
|
|
1308
|
+
rkey
|
|
1309
|
+
}
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
function matchTaproot(host, pathname) {
|
|
1313
|
+
if (host !== "atproto.at") return null;
|
|
1314
|
+
const m = pathname.replace(/^\/+/, "").match(/^uri\/at:\/{1,2}(.+)$/);
|
|
1315
|
+
if (!m) return null;
|
|
1316
|
+
const segments = m[1].split("/").filter(Boolean);
|
|
1317
|
+
if (segments.length === 0) return null;
|
|
1318
|
+
const handle = segments[0];
|
|
1319
|
+
const collection = segments[1];
|
|
1320
|
+
const rkey = segments[2];
|
|
1321
|
+
const did = handle.startsWith("did:") ? handle : void 0;
|
|
1322
|
+
if (collection && rkey) {
|
|
1323
|
+
return {
|
|
1324
|
+
source: "taproot",
|
|
1325
|
+
parsed: {
|
|
1326
|
+
type: inferType(collection),
|
|
1327
|
+
uri: `at://${handle}/${collection}/${rkey}`,
|
|
1328
|
+
handle,
|
|
1329
|
+
did,
|
|
1330
|
+
collection,
|
|
1331
|
+
rkey
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
return {
|
|
1336
|
+
source: "taproot",
|
|
1337
|
+
parsed: { type: "profile", uri: `at://${handle}`, handle, did }
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
function matchAturi(host, parts) {
|
|
1341
|
+
if (host !== "aturi.to") return null;
|
|
1342
|
+
const isIdentifier = (seg) => !!seg && (seg.startsWith("did:") || seg.includes("."));
|
|
1343
|
+
if (parts[0] === "explore" && isIdentifier(parts[1])) {
|
|
1344
|
+
const handle = parts[1];
|
|
1345
|
+
const did = handle.startsWith("did:") ? handle : void 0;
|
|
1346
|
+
const collection = parts[2];
|
|
1347
|
+
const rkey = parts[3];
|
|
1348
|
+
if (collection && rkey) {
|
|
1349
|
+
return {
|
|
1350
|
+
source: "aturiExplore",
|
|
1351
|
+
parsed: {
|
|
1352
|
+
type: inferType(collection),
|
|
1353
|
+
uri: `at://${handle}/${collection}/${rkey}`,
|
|
1354
|
+
handle,
|
|
1355
|
+
did,
|
|
1356
|
+
collection,
|
|
1357
|
+
rkey
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
return {
|
|
1362
|
+
source: "aturiExplore",
|
|
1363
|
+
parsed: { type: "profile", uri: `at://${handle}`, handle, did }
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
if (parts[0] === "profile" && isIdentifier(parts[1])) {
|
|
1367
|
+
const handle = parts[1];
|
|
1368
|
+
const did = handle.startsWith("did:") ? handle : void 0;
|
|
1369
|
+
if (parts[2] === "post" && parts[3]) {
|
|
1370
|
+
return {
|
|
1371
|
+
source: "aturi",
|
|
1372
|
+
parsed: {
|
|
1373
|
+
type: "post",
|
|
1374
|
+
uri: `at://${handle}/app.bsky.feed.post/${parts[3]}`,
|
|
1375
|
+
handle,
|
|
1376
|
+
did,
|
|
1377
|
+
collection: "app.bsky.feed.post",
|
|
1378
|
+
rkey: parts[3]
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
if (parts[2] === "lists" && parts[3]) {
|
|
1383
|
+
return {
|
|
1384
|
+
source: "aturi",
|
|
1385
|
+
parsed: {
|
|
1386
|
+
type: "list",
|
|
1387
|
+
uri: `at://${handle}/app.bsky.graph.list/${parts[3]}`,
|
|
1388
|
+
handle,
|
|
1389
|
+
did,
|
|
1390
|
+
collection: "app.bsky.graph.list",
|
|
1391
|
+
rkey: parts[3]
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
if (parts[2] && parts[2].includes(".") && parts[3]) {
|
|
1396
|
+
return {
|
|
1397
|
+
source: "aturi",
|
|
1398
|
+
parsed: {
|
|
1399
|
+
type: inferType(parts[2]),
|
|
1400
|
+
uri: `at://${handle}/${parts[2]}/${parts[3]}`,
|
|
1401
|
+
handle,
|
|
1402
|
+
did,
|
|
1403
|
+
collection: parts[2],
|
|
1404
|
+
rkey: parts[3]
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
return {
|
|
1409
|
+
source: "aturi",
|
|
1410
|
+
parsed: { type: "profile", uri: `at://${handle}`, handle, did }
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
return null;
|
|
1414
|
+
}
|
|
1144
1415
|
function matchSupportedUrl(url) {
|
|
1145
1416
|
const host = normalizeHost(url.hostname);
|
|
1146
1417
|
const parts = url.pathname.split("/").filter(Boolean);
|
|
1147
1418
|
const search = url.searchParams;
|
|
1148
|
-
return matchBlueskyFamily(host, parts) || matchPinksky(host, parts, search) || matchLeaflet(host, parts) || matchTangled(host, parts) || matchMargin(host, parts) || matchPdsls(host, url.pathname) || matchAtpTools(host, url.pathname) || matchBluepy(host, url.pathname) || matchSemble(host, parts) || matchStreamplace(host, parts) || matchGrain(host, parts) || matchPopfeed(host, parts) || matchSifa(host, parts) || matchBlento(host, parts);
|
|
1419
|
+
return matchAturi(host, parts) || matchBlueskyFamily(host, parts) || matchPinksky(host, parts, search) || matchLeaflet(host, parts) || matchTangled(host, parts) || matchMargin(host, parts) || matchPdsls(host, url.pathname) || matchAtpTools(host, url.pathname) || matchBluepy(host, url.pathname) || matchSemble(host, parts) || matchStreamplace(host, parts) || matchGrain(host, parts) || matchPopfeed(host, parts) || matchSifa(host, parts) || matchBlento(host, parts) || matchStandardReader(host, parts) || matchFlatRecordHost(host, parts, { host: "offprint.app", source: "offprint" }) || matchFlatRecordHost(host, parts, { host: "pckt.blog", source: "pckt" }) || matchTaproot(host, url.pathname);
|
|
1149
1420
|
}
|
|
1150
1421
|
function parseAtUri(uri) {
|
|
1151
1422
|
if (!uri.startsWith("at://")) return null;
|
|
@@ -1175,6 +1446,7 @@ function parseAtUri(uri) {
|
|
|
1175
1446
|
};
|
|
1176
1447
|
}
|
|
1177
1448
|
var SUPPORTED_HOSTS = [
|
|
1449
|
+
"aturi.to",
|
|
1178
1450
|
...BLUESKY_FAMILY.flatMap((e) => e.hosts),
|
|
1179
1451
|
"pinkleap.app",
|
|
1180
1452
|
"leaflet.pub",
|
|
@@ -1188,8 +1460,17 @@ var SUPPORTED_HOSTS = [
|
|
|
1188
1460
|
"grain.social",
|
|
1189
1461
|
"popfeed.social",
|
|
1190
1462
|
"sifa.id",
|
|
1191
|
-
"blento.app"
|
|
1463
|
+
"blento.app",
|
|
1464
|
+
"standard-reader.app",
|
|
1465
|
+
"offprint.app",
|
|
1466
|
+
"pckt.blog",
|
|
1467
|
+
"atproto.at"
|
|
1192
1468
|
];
|
|
1469
|
+
function isSupportedHost(host) {
|
|
1470
|
+
const h = normalizeHost(host);
|
|
1471
|
+
if (SUPPORTED_HOSTS.includes(h)) return true;
|
|
1472
|
+
return SUBDOMAIN_HOSTS.some((base) => isSubdomainOf(h, base));
|
|
1473
|
+
}
|
|
1193
1474
|
|
|
1194
1475
|
// src/resolve.ts
|
|
1195
1476
|
var DID_REQUIRED_WAYPOINTS = /* @__PURE__ */ new Set([
|
|
@@ -1322,6 +1603,6 @@ async function detectAtUriInHead(url, timeoutMs) {
|
|
|
1322
1603
|
}
|
|
1323
1604
|
}
|
|
1324
1605
|
|
|
1325
|
-
export { CATEGORY_ORDER, COMPAT_FAMILIES, COMPAT_FAMILY_ORDER, DID_REQUIRED_WAYPOINTS, SUPPORTED_HOSTS, WAYPOINT_CATEGORIES_DATA, WAYPOINT_DESTINATIONS_DATA, WAYPOINT_ORDER, buildWaypointsForParsed, getCategorizedWaypointsData, getDisplayName, getFeaturedWaypointData, getRecommendedWaypointsData, getWaypointCountData, getWaypointDataForType, matchSupportedUrl, parseAtUri, parseURI, resolveAtUri, resolveHandle, resolveUrl, resolveViaApi, waypointActivity };
|
|
1606
|
+
export { CATEGORY_ORDER, COMPAT_FAMILIES, COMPAT_FAMILY_ORDER, DID_REQUIRED_WAYPOINTS, SUPPORTED_HOSTS, WAYPOINT_CATEGORIES_DATA, WAYPOINT_DESTINATIONS_DATA, WAYPOINT_ORDER, buildWaypointsForParsed, getCategorizedWaypointsData, getDisplayName, getFeaturedWaypointData, getRecommendedWaypointsData, getWaypointCountData, getWaypointDataForType, isSupportedHost, matchSupportedUrl, parseAtUri, parseURI, resolveAtUri, resolveHandle, resolveHandleStatus, resolveUrl, resolveViaApi, waypointActivity };
|
|
1326
1607
|
//# sourceMappingURL=index.js.map
|
|
1327
1608
|
//# sourceMappingURL=index.js.map
|