1 | import * as check from "./fs/types/check.js";
|
2 | import * as debug from "./common/debug.js";
|
3 | import * as did from "./did/index.js";
|
4 | import * as dns from "./dns/index.js";
|
5 | import * as ucan from "./ucan/index.js";
|
6 | import { api } from "./common/index.js";
|
7 | import { setup } from "./setup/internal.js";
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | const EMPTY_CID = 'Qmc5m94Gu7z62RC8waSKkZUrCCBJPyHbkpmGzEePxy2oXJ';
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | export async function lookup(username) {
|
20 | const maybeRoot = await lookupOnFisson(username);
|
21 | if (maybeRoot === EMPTY_CID)
|
22 | return null;
|
23 | if (maybeRoot !== null)
|
24 | return maybeRoot;
|
25 | try {
|
26 | const cid = await dns.lookupDnsLink(username + '.files.' + setup.endpoints.user);
|
27 | return cid === EMPTY_CID ? null : cid;
|
28 | }
|
29 | catch (err) {
|
30 | console.error(err);
|
31 | throw new Error('Could not locate user root in dns');
|
32 | }
|
33 | }
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | export async function lookupOnFisson(username) {
|
40 | try {
|
41 | const resp = await fetch(`${setup.endpoints.api}/user/data/${username}`, { cache: 'reload' }
|
42 | );
|
43 | const cid = await resp.json();
|
44 | if (!check.isCID(cid)) {
|
45 | throw new Error("Did not receive a CID");
|
46 | }
|
47 | return cid;
|
48 | }
|
49 | catch (err) {
|
50 | debug.log('Could not locate user root on Fission server: ', err.toString());
|
51 | return null;
|
52 | }
|
53 | }
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | export async function update(cid, proof) {
|
61 | const apiEndpoint = setup.endpoints.api;
|
62 |
|
63 | debug.log("🌊 Updating your DNSLink:", cid);
|
64 |
|
65 | return await fetchWithRetry(`${apiEndpoint}/user/data/${cid}`, {
|
66 | headers: async () => {
|
67 | const jwt = ucan.encode(await ucan.build({
|
68 | audience: await api.did(),
|
69 | issuer: await did.ucan(),
|
70 | potency: "APPEND",
|
71 | proof,
|
72 |
|
73 |
|
74 | resource: ucan.decode(proof).payload.rsc
|
75 | }));
|
76 | return { 'authorization': `Bearer ${jwt}` };
|
77 | },
|
78 | retries: 100,
|
79 | retryDelay: 5000,
|
80 | retryOn: [502, 503, 504],
|
81 | }, {
|
82 | method: 'PATCH'
|
83 | }).then((response) => {
|
84 | if (response.status < 300)
|
85 | debug.log("🪴 DNSLink updated:", cid);
|
86 | else
|
87 | debug.log("🔥 Failed to update DNSLink for:", cid);
|
88 | return { success: response.status < 300 };
|
89 | }).catch(err => {
|
90 | debug.log("🔥 Failed to update DNSLink for:", cid);
|
91 | console.error(err);
|
92 | return { success: false };
|
93 | });
|
94 | }
|
95 | async function fetchWithRetry(url, retryOptions, fetchOptions, retry = 0) {
|
96 | const headers = await retryOptions.headers();
|
97 | const response = await fetch(url, {
|
98 | ...fetchOptions,
|
99 | headers: { ...fetchOptions.headers, ...headers }
|
100 | });
|
101 | if (retryOptions.retryOn.includes(response.status)) {
|
102 | if (retry < retryOptions.retries) {
|
103 | return await new Promise((resolve, reject) => setTimeout(() => fetchWithRetry(url, retryOptions, fetchOptions, retry + 1).then(resolve, reject), retryOptions.retryDelay));
|
104 | }
|
105 | else {
|
106 | throw new Error("Too many retries for fetch");
|
107 | }
|
108 | }
|
109 | return response;
|
110 | }
|
111 |
|
\ | No newline at end of file |