diff --git a/src/App.vue b/src/App.vue index 25c9074e7f3ccc933f663ec50db4158d82a0559d..da537dc8d7bbc6dea124eccb09244d81e09fe07f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -7,7 +7,6 @@ import { RouterLink } from "vue-router"; <nav> <RouterLink to="/">Home</RouterLink> <RouterLink to="/kubo">Kubo</RouterLink> - <RouterLink to="/ipns">IPNS</RouterLink> <RouterLink to="/index">Index</RouterLink> <RouterLink to="/diff">Diff</RouterLink> <RouterLink to="/io">IO</RouterLink> diff --git a/src/assets/base.css b/src/assets/base.css index 8816868a41b651f318dee87c6784ebcd6e29eca1..7c27c2e10c1ba1dc4c6f33b1b1ad80c9edcc6ab9 100644 --- a/src/assets/base.css +++ b/src/assets/base.css @@ -55,7 +55,6 @@ *::after { box-sizing: border-box; margin: 0; - font-weight: normal; } body { diff --git a/src/components/IpnsLink.vue b/src/components/IpnsLink.vue index 5a5644a0196cf82ed3e88a1a93aead04fea4b312..d9b7777bc36cdd6b6b4f98d18a25f0fa4d88396e 100644 --- a/src/components/IpnsLink.vue +++ b/src/components/IpnsLink.vue @@ -10,5 +10,5 @@ const short = computed(() => props.ipns.slice(0, 5) + '...' + props.ipns.slice(- </script> <template> - <a target="_blank" :href="gatewayUrlIPNS(ipns)" class="mono">{{ short }}</a> + <a target="_blank" :href="gatewayUrlIPNS(ipns)" class="mono"><slot>{{ short }}</slot></a> </template> diff --git a/src/indexer/ipns.ts b/src/indexer/ipns.ts index d07d485102cdcd225e9fe2c3aef66b4470216a08..d09d749232348e90cbc291c5bb9ff7725a593143 100644 --- a/src/indexer/ipns.ts +++ b/src/indexer/ipns.ts @@ -11,9 +11,6 @@ export async function getSelfDdKeys(): Promise<DdKeys> { tamt: ks.get('dd_tamt')!, tamt_hist: ks.get('dd_tamt_hist')!, profiles: ks.get('dd_profiles')!, - ui_client_demo: ks.get('dd_ui_client_demo') || null, - ui_client_demo_hist: ks.get('dd_ui_client_demo_hist') || null, - ui_admin: ks.get('dd_ui_admin') || null } return keys } diff --git a/src/indexer/types.ts b/src/indexer/types.ts index f87867eed587fc1db38f433ffe84a76276e18eb6..b37cd4f75ca5d1946d365f1b5f93021a226feb0d 100644 --- a/src/indexer/types.ts +++ b/src/indexer/types.ts @@ -8,11 +8,8 @@ export interface DiffData { newItems: Array<[CID, IndexRequest]> } - // this object allows to share a single ipns key with other datapods // so that they use components as bootstrap -// each key can be replaced by their own version if they publish something in their name -// or keep pointing to a name maintained by someone else export interface DdKeys { // root entry mapping to all the other ones below root: string @@ -22,10 +19,6 @@ export interface DdKeys { tamt_hist: string // C+ profiles kinds grouped in a single tree for efficient indexing profiles: string - // demo client UI - ui_client_demo: string | null - // history of demo client UI - ui_client_demo_hist: string | null - // node admin UI - ui_admin: string | null -} \ No newline at end of file +} +// names of keys for iter since we can not easily get them programatically +export const ddKeysNames = ['root', 'tamt', 'tamt_hist', 'profiles'] diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 6e1d218263e4c864abcb984b19ae14c33403f782..3137835ce2167683840d1437b8ad6b56cb37d07d 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -10,9 +10,8 @@ </p> <h2>Main menu</h2> <ul> - <li><RouterLink to="/">Home</RouterLink> -- here</li> + <li><RouterLink to="/">Home</RouterLink> – here</li> <li><RouterLink to="/kubo">Kubo</RouterLink></li> - <li><RouterLink to="/ipns">IPNS</RouterLink></li> <li><RouterLink to="/index">Index</RouterLink></li> <li><RouterLink to="/diff">Diff</RouterLink></li> <li><RouterLink to="/io">IO</RouterLink></li> @@ -21,6 +20,7 @@ <h2>Not in main menu</h2> <ul> <li><RouterLink to="/feed">Feed</RouterLink></li> + <li><RouterLink to="/ipns">IPNS</RouterLink></li> </ul> </main> </template> diff --git a/src/views/IpnsView.vue b/src/views/IpnsView.vue index f1ff2dab71d7b85eb0e0a06ffea8d274589ec5cc..dcc9e35e8be4cca9602f13c72a4acf88290f618e 100644 --- a/src/views/IpnsView.vue +++ b/src/views/IpnsView.vue @@ -1,56 +1,86 @@ <script setup lang="ts"> +import { ref, type Ref, computed, onMounted, reactive, type ShallowReactive } from 'vue' import { kubo } from '@/kubo' import { emptyInode, type IndexHist } from '../types' import { EMPTY_NODE_CID } from '../consts' import { CID } from 'multiformats' -import { ref, type Ref, computed, onMounted } from 'vue' -import { ddKeys } from '../indexer/ipns' +import { ddKeys as _ddKeys } from '../indexer/ipns' +import { ddKeysNames, type DdKeys } from '../indexer/types' +import IpnsLink from '@/components/IpnsLink.vue' +import CidLink from '@/components/CidLink.vue' -const targetMsg = ref('') -const targetCID: Ref<CID | null> = ref(null) -const histCID: Ref<CID | null> = ref(null) +const ddKeys = _ddKeys as any // for easy manipulation -const isValid = computed(() => { +const targetCids: ShallowReactive<any> = reactive({}) +const targetCidsMsg: ShallowReactive<any> = reactive({}) + +function set(k: string) { try { - CID.parse(targetMsg.value) - return true - } catch { - return false + const cid = CID.parse(targetCidsMsg[k]) + targetCidsMsg[k] = '' + kubo.name + .publish(cid, { key: 'dd_' + k, ttl: '1s' }) + .then(() => { + targetCids[k] = cid.toString() + if (k == 'tamt') { + // track it on the history + updateHist(cid) + } + }) + .catch((e) => { + console.log(e) + targetCidsMsg[k] = 'error publishing' + }) + } catch (e) { + console.log(e) + targetCidsMsg[k] = 'can not parse CID' } -}) +} -// inits indexing and publishes ipns entry for it -async function initIndex() { - targetCID.value = EMPTY_NODE_CID - // publish result to ipns - kubo.name.publish(EMPTY_NODE_CID, { ttl: '1s', key: 'self' }).then(console.log) - // track it on the history - updateHist(EMPTY_NODE_CID) +function reinitialize(k: string) { + switch (k) { + case 'tamt': { + console.log('reinitialize tamt') + targetCidsMsg.tamt = EMPTY_NODE_CID.toString() + set(k) + break + } + case 'tamt_hist': { + console.log('reinitialize tamt history') + initTamtHistOn(ddKeys.tamt) + break + } + case 'profiles': { + console.log('reinitialize profiles') + break + } + default: + console.log('unimplemented') + } } // inits indexing and publishes ipns entry for it -async function initIndexHist() { +async function initTamtHistOn(cid: CID) { const firstHist: IndexHist = { last_history: null, - current_index: targetCID.value!, + current_index: cid, number: 0, timestamp: Date.now() } const firstHistCID = await kubo.dag.put(firstHist) - kubo.name.publish(firstHistCID, { ttl: '1s', key: 'index_history' }).then(console.log) + kubo.name.publish(firstHistCID, { key: 'dd_tamt_hist', ttl: '1s' }).then(console.log) } // resolve given ipns async function resolveIPNS(ipns: string): Promise<CID> { - let cid = null - for await (const name of kubo.name.resolve(ipns, { nocache: true })) { - cid = CID.parse(name.slice(6)) + for await (const name of kubo.name.resolve(ipns, { nocache: true, timeout: 100 })) { + return CID.parse(name.slice(6)) } - return cid! + throw Error('could not resolve') } // update history chain with new cid -async function updateHist(cid: CID) { +async function updateHist(cid: CID): Promise<CID> { const lastHistCID = await resolveIPNS(ddKeys.tamt_hist) const lastHist = (await kubo.dag.get(lastHistCID)).value const newHist: IndexHist = { @@ -61,48 +91,75 @@ async function updateHist(cid: CID) { } const newHistCID = await kubo.dag.put(newHist) kubo.name.publish(newHistCID, { ttl: '1s', key: 'index_history' }) -} - -// publish cid to IPNS -function setTargetCid() { - if (isValid.value) { - const cid = CID.parse(targetMsg.value) - targetCID.value = cid - kubo.name.publish(cid, { ttl: '1s' }) - } else { - targetCID.value = null - } + return newHistCID } onMounted(() => { - resolveIPNS(ddKeys.tamt).then((c) => (targetCID.value = c)) - resolveIPNS(ddKeys.tamt_hist).then((c) => (histCID.value = c)) + for (let k of ddKeysNames) { + resolveIPNS(ddKeys[k]) + .then((c) => (targetCids[k] = c?.toString())) + .catch(console.log) + } }) </script> <template> <div> <h1>IPNS</h1> - <p>Info about IPNS entries</p> - <h2>Index root</h2> - <p>Root node IPNS</p> - <p class="mono">{{ ddKeys.tamt }}</p> - <p>is pointing to</p> - <p class="mono">{{ targetCID }}</p> - <p>initialize empty index: <button @click="initIndex">reinitialize ⚠️</button></p> + <p>Info about Datapod IPNS entries. These keys are named with a "dd_" prefix.</p> <p> - or set to custom CID <br /> - <input v-model="targetMsg" @keyup.enter="setTargetCid" size="50" /> - <button v-on:click="setTargetCid">Set ⚠️</button> + To see all keys available in the node, not restricted to these ones, go to + <RouterLink to="/kubo">Kubo view</RouterLink>. </p> - <h2>Index history</h2> - <p>History IPNS</p> - <p class="mono">{{ ddKeys.tamt_hist }}</p> - <p>is pointing to</p> - <p class="mono">{{ histCID }}</p> - <p>reinitialize history to current target cid <button @click="initIndexHist">reinitialize ⚠️</button></p> - <p>and got to <RouterLink to="/index">index</RouterLink> to see more about index history</p> + <ul> + <li><b>dd_root</b> points to the object listing all the keys</li> + <li> + <b>dd_tamt</b> points to the root node of the TAMT, see more on <RouterLink to="/index">index view</RouterLink>. + </li> + <li> + <b>dd_tamt_hist</b> points to the head of the history of TAMT root, see more on + <RouterLink to="/index">index view</RouterLink>. + </li> + <li><b>dd_profiles</b> points to the root node of profiles index</li> + </ul> + <p> + In the table below you can edit your IPNS entires. Think of it as DNS and keep in mind that the datapod is using + it. + </p> + <br /> + <table> + <thead> + <tr> + <th>name</th> + <th>target</th> + <th>set target</th> + <th>⚠️ reset</th> + </tr> + </thead> + <tbody> + <tr v-for="k in ddKeysNames"> + <td> + <IpnsLink :ipns="ddKeys[k]">dd_{{ k }}</IpnsLink> + </td> + <td><CidLink v-if="targetCids[k]" :cid="targetCids[k]" /><template v-else>undefined</template></td> + <template v-if="k == 'root'"> + <td class="center">-</td> + <td class="center">-</td> + </template> + <template v-else> + <td> + <input size="40" @keyup.enter="set(k)" v-model="targetCidsMsg[k]" /><button @click="set(k)">set</button> + </td> + <td class="center"><button @click="reinitialize(k)">reset</button></td> + </template> + </tr> + </tbody> + </table> </div> </template> -<style scoped></style> +<style scoped> +.center { + text-align: center; +} +</style> diff --git a/src/views/KuboView.vue b/src/views/KuboView.vue index f8026e3449bd4194f613cd1297a0cfe3a789ec93..dfcd98acec94e8a436ce702a5ff75d314d0542a2 100644 --- a/src/views/KuboView.vue +++ b/src/views/KuboView.vue @@ -49,6 +49,7 @@ refresh() <p v-else>loading stats...<br /><br /><br /><br /><br /></p> <h2>Keys</h2> <p>Key prefixed by "dd" are used by the datapod. They should be listed in object published on dd_root.</p> + <p>To inspect and edit IPNS entries, go to <RouterLink to="/ipns">IPNS view</RouterLink>.</p> <table> <thead> <tr>