tangled
alpha
login
or
join now
pds.ls
/
pdsls
399
fork
atom
atmosphere explorer
pds.ls
tool
typescript
atproto
399
fork
atom
overview
issues
1
pulls
pipelines
reactive plcDirectory setting
handle.invalid
2 months ago
4698a710
e13f3356
verified
This commit was signed with the committer's
known signature
.
handle.invalid
SSH Key Fingerprint:
SHA256:mBrT4x0JdzLpbVR95g1hjI1aaErfC02kmLRkPXwsYCk=
+51
-33
7 changed files
expand all
collapse all
unified
split
src
auth
oauth-config.ts
layout.tsx
utils
api.ts
views
logs.tsx
record.tsx
repo.tsx
settings.tsx
+8
-3
src/auth/oauth-config.ts
···
1
1
-
import { configureOAuth, defaultIdentityResolver } from "@atcute/oauth-browser-client";
1
1
+
import { LocalActorResolver } from "@atcute/identity-resolver";
2
2
+
import { configureOAuth } from "@atcute/oauth-browser-client";
2
3
import { didDocumentResolver, handleResolver } from "../utils/api";
3
4
5
5
+
const reactiveDidDocumentResolver = {
6
6
+
resolve: async (did: string) => didDocumentResolver().resolve(did as any),
7
7
+
};
8
8
+
4
9
configureOAuth({
5
10
metadata: {
6
11
client_id: import.meta.env.VITE_OAUTH_CLIENT_ID,
7
12
redirect_uri: import.meta.env.VITE_OAUTH_REDIRECT_URL,
8
13
},
9
9
-
identityResolver: defaultIdentityResolver({
14
14
+
identityResolver: new LocalActorResolver({
10
15
handleResolver: handleResolver,
11
11
-
didDocumentResolver: didDocumentResolver,
16
16
+
didDocumentResolver: reactiveDidDocumentResolver,
12
17
}),
13
18
});
+3
-4
src/layout.tsx
···
12
12
import { Search, SearchButton, showSearch } from "./components/search.jsx";
13
13
import { themeEvent } from "./components/theme.jsx";
14
14
import { resolveHandle } from "./utils/api.js";
15
15
+
import { plcDirectory } from "./views/settings.jsx";
15
16
16
17
export const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 1;
17
18
···
187
188
</Show>
188
189
</div>
189
190
<NotificationContainer />
190
190
-
<Show
191
191
-
when={localStorage.plcDirectory && localStorage.plcDirectory !== "https://plc.directory"}
192
192
-
>
191
191
+
<Show when={plcDirectory() !== "https://plc.directory"}>
193
192
<div class="dark:bg-dark-500 fixed right-0 bottom-0 left-0 z-10 flex items-center justify-center bg-neutral-100 px-3 py-1 text-xs">
194
193
<span>
195
195
-
PLC directory: <span class="font-medium">{localStorage.plcDirectory}</span>
194
194
+
PLC directory: <span class="font-medium">{plcDirectory()}</span>
196
195
</span>
197
196
</div>
198
197
</Show>
+21
-13
src/utils/api.ts
···
16
16
import { DohJsonLexiconAuthorityResolver, LexiconSchemaResolver } from "@atcute/lexicon-resolver";
17
17
import { Did, Handle } from "@atcute/lexicons";
18
18
import { AtprotoDid, isHandle, Nsid } from "@atcute/lexicons/syntax";
19
19
+
import { createMemo } from "solid-js";
19
20
import { createStore } from "solid-js/store";
20
21
import { setPDS } from "../components/navbar";
22
22
+
import { plcDirectory } from "../views/settings";
21
23
22
22
-
export const didDocumentResolver = new CompositeDidDocumentResolver({
23
23
-
methods: {
24
24
-
plc: new PlcDidDocumentResolver({
25
25
-
apiUrl: localStorage.getItem("plcDirectory") ?? "https://plc.directory",
24
24
+
export const didDocumentResolver = createMemo(
25
25
+
() =>
26
26
+
new CompositeDidDocumentResolver({
27
27
+
methods: {
28
28
+
plc: new PlcDidDocumentResolver({
29
29
+
apiUrl: plcDirectory(),
30
30
+
}),
31
31
+
web: new AtprotoWebDidDocumentResolver(),
32
32
+
},
26
33
}),
27
27
-
web: new AtprotoWebDidDocumentResolver(),
28
28
-
},
29
29
-
});
34
34
+
);
30
35
31
36
export const handleResolver = new CompositeHandleResolver({
32
37
strategy: "dns-first",
···
40
45
dohUrl: "https://dns.google/resolve?",
41
46
});
42
47
43
43
-
const schemaResolver = new LexiconSchemaResolver({
44
44
-
didDocumentResolver: didDocumentResolver,
45
45
-
});
48
48
+
const schemaResolver = createMemo(
49
49
+
() =>
50
50
+
new LexiconSchemaResolver({
51
51
+
didDocumentResolver: didDocumentResolver(),
52
52
+
}),
53
53
+
);
46
54
47
55
const didPDSCache: Record<string, string> = {};
48
56
const [labelerCache, setLabelerCache] = createStore<Record<string, string>>({});
···
54
62
throw new Error("Not a valid DID identifier");
55
63
}
56
64
57
57
-
const doc = await didDocumentResolver.resolve(did);
65
65
+
const doc = await didDocumentResolver().resolve(did);
58
66
didDocCache[did] = doc;
59
67
60
68
const pds = getPdsEndpoint(doc);
···
83
91
if (!isAtprotoDid(did)) {
84
92
throw new Error("Not a valid DID identifier");
85
93
}
86
86
-
return await didDocumentResolver.resolve(did);
94
94
+
return await didDocumentResolver().resolve(did);
87
95
};
88
96
89
97
const validateHandle = async (handle: Handle, did: Did) => {
···
145
153
};
146
154
147
155
const resolveLexiconSchema = async (authority: AtprotoDid, nsid: Nsid) => {
148
148
-
return await schemaResolver.resolve(authority, nsid);
156
156
+
return await schemaResolver().resolve(authority, nsid);
149
157
};
150
158
151
159
interface LinkData {
+2
-3
src/views/logs.tsx
···
8
8
import { createEffect, createResource, createSignal, For, Show } from "solid-js";
9
9
import { localDateFromTimestamp } from "../utils/date.js";
10
10
import { createOperationHistory, DiffEntry, groupBy } from "../utils/plc-logs.js";
11
11
+
import { plcDirectory } from "./settings.jsx";
11
12
12
13
type PlcEvent = "handle" | "rotation_key" | "service" | "verification_method";
13
14
···
23
24
!activePlcEvent() || diffs.some((d) => d.type.startsWith(activePlcEvent()!));
24
25
25
26
const fetchPlcLogs = async () => {
26
26
-
const res = await fetch(
27
27
-
`${localStorage.plcDirectory ?? "https://plc.directory"}/${props.did}/log/audit`,
28
28
-
);
27
27
+
const res = await fetch(`${plcDirectory()}/${props.did}/log/audit`);
29
28
const json = await res.json();
30
29
const logs = defs.indexedEntryLog.parse(json);
31
30
setRawLogs(logs);
+1
-1
src/views/record.tsx
···
57
57
const schemaPromise = (async () => {
58
58
let didDocPromise = documentCache.get(authority);
59
59
if (!didDocPromise) {
60
60
-
didDocPromise = didDocumentResolver.resolve(authority);
60
60
+
didDocPromise = didDocumentResolver().resolve(authority);
61
61
documentCache.set(authority, didDocPromise);
62
62
}
63
63
+4
-5
src/views/repo.tsx
···
42
42
import { detectDidKeyType, detectKeyType } from "../utils/key.js";
43
43
import { BlobView } from "./blob.jsx";
44
44
import { PlcLogView } from "./logs.jsx";
45
45
+
import { plcDirectory } from "./settings.jsx";
45
46
46
47
export const RepoView = () => {
47
48
const params = useParams();
···
101
102
};
102
103
103
104
const getRotationKeys = async () => {
104
104
-
const res = await fetch(
105
105
-
`${localStorage.plcDirectory ?? "https://plc.directory"}/${did}/log/last`,
106
106
-
);
105
105
+
const res = await fetch(`${plcDirectory()}/${did}/log/last`);
107
106
const json = await res.json();
108
107
setRotationKeys(json.rotationKeys ?? []);
109
108
};
···
364
363
<NavMenu
365
364
href={
366
365
did.startsWith("did:plc") ?
367
367
-
`${localStorage.plcDirectory ?? "https://plc.directory"}/${did}`
366
366
+
`${plcDirectory()}/${did}`
368
367
: `https://${did.split("did:web:")[1]}/.well-known/did.json`
369
368
}
370
369
newTab
···
373
372
/>
374
373
<Show when={did.startsWith("did:plc")}>
375
374
<NavMenu
376
376
-
href={`${localStorage.plcDirectory ?? "https://plc.directory"}/${did}/log/audit`}
375
375
+
href={`${plcDirectory()}/${did}/log/audit`}
377
376
newTab
378
377
label="Audit log"
379
378
icon="lucide--external-link"
+12
-4
src/views/settings.tsx
···
4
4
import { ThemeSelection } from "../components/theme.jsx";
5
5
6
6
export const [hideMedia, setHideMedia] = createSignal(localStorage.hideMedia === "true");
7
7
+
export const [plcDirectory, setPlcDirectory] = createSignal(
8
8
+
localStorage.plcDirectory || "https://plc.directory",
9
9
+
);
7
10
8
11
const Settings = () => {
9
12
return (
···
17
20
</label>
18
21
<TextInput
19
22
id="plcDirectory"
20
20
-
value={localStorage.plcDirectory || "https://plc.directory"}
23
23
+
value={plcDirectory()}
21
24
onInput={(e) => {
22
22
-
e.currentTarget.value.length ?
23
23
-
(localStorage.plcDirectory = e.currentTarget.value)
24
24
-
: localStorage.removeItem("plcDirectory");
25
25
+
const value = e.currentTarget.value;
26
26
+
if (value.length) {
27
27
+
localStorage.plcDirectory = value;
28
28
+
setPlcDirectory(value);
29
29
+
} else {
30
30
+
localStorage.removeItem("plcDirectory");
31
31
+
setPlcDirectory("https://plc.directory");
32
32
+
}
25
33
}}
26
34
/>
27
35
</div>