basic object-based js API

feat/vaults
Tomáš Mládek 2021-12-18 15:12:22 +01:00
parent fed5c72f55
commit cce0c2cdd5
6 changed files with 91 additions and 43 deletions

View File

@ -1,30 +1,76 @@
import type { Address, IEntry, ListingResult, OrderedListing } from "./types";
import type {
Address,
IEntry,
ListingResult,
OrderedListing,
VALUE_TYPE,
} from "./types";
export function listingAsOrdered(listing: ListingResult): OrderedListing {
const entries = Object.entries(listing) as [Address, IEntry][];
return entries
.sort(([_, a], [__, b]) => String(a.value.c).localeCompare(b.value.c))
.sort(([_, a], [__, b]) => String(a.value.t).localeCompare(b.value.t))
.sort(([_, a], [__, b]) =>
String(a.value.c).localeCompare(String(b.value.c))
)
.sort(([_, a], [__, b]) =>
String(a.value.t).localeCompare(String(b.value.t))
)
.sort(([_, a], [__, b]) => a.attribute.localeCompare(b.attribute));
}
export function asDict(attributes: IEntry[]) {
const result = {} as { [key: string]: { [key: string]: unknown } };
attributes.forEach((entry) => {
if (!result[entry.entity]) {
result[entry.entity] = {};
}
if (result[entry.entity][entry.attribute]) {
if (!Array.isArray(result[entry.entity][entry.attribute])) {
result[entry.entity][entry.attribute] = [
result[entry.entity][entry.attribute],
];
}
(result[entry.entity][entry.attribute] as unknown[]).push(entry.value.c);
} else {
result[entry.entity][entry.attribute] = entry.value.c;
}
});
export class UpListing {
private entries: UpEntry[];
return result;
constructor(listing: ListingResult) {
this.entries = Object.entries(listing).map((lr) => new UpEntry(...lr));
}
public get objects(): UpObject[] {
const allEntities = new Set(this.entries.map((e) => e.entity));
return Array.from(allEntities).map((entity) => new UpObject(entity));
}
}
export class UpObject {
public readonly address;
constructor(address: string) {
this.address = address;
}
public attr(entries: UpEntry[]) {
const result = {} as { [key: string]: UpEntry[] };
entries
.filter((e) => e.entity == this.address)
.forEach((entry) => {
if (!result[entry.attribute]) {
result[entry.attribute] = [];
}
result[entry.attribute].push(entry);
});
return result;
}
public asDict(entries: UpEntry[]) {
return {
address: this.address,
attributes: this.attr(entries),
};
}
}
export class UpEntry extends UpObject implements IEntry {
entity: string;
attribute: string;
value: { t: VALUE_TYPE; c: string | number };
constructor(address: string, entry: IEntry) {
super(address);
this.entity = entry.entity;
this.attribute = entry.attribute;
this.value = entry.value;
}
}

View File

@ -1,7 +1,7 @@
import test from "ava";
import http from "http";
import { asDict, listingAsOrdered } from ".";
import { ListingResult, OrderedListing } from "./types";
import { UpObject, UpEntry, UpListing } from ".";
import type { Address, IEntry, ListingResult } from "./types";
function fetchJSON(url: string): Promise<unknown> {
return new Promise((resolve, reject) => {
@ -23,12 +23,17 @@ function fetchJSON(url: string): Promise<unknown> {
});
}
test("my passing test", async (t) => {
const data = (await fetchJSON(
"http://localhost:8093/api/hier/NATIVE"
)) as ListingResult;
test("basic hier listing", async (t) => {
const data = (await fetchJSON("http://localhost:8093/api/hier/NATIVE")) as {
target: Address;
entries: IEntry[];
};
console.log(asDict(Object.values(data)));
const native = new UpObject(data.target);
// console.log(native.asDict(data.entries));
// console.log(asDict(Object.values(data)));
t.pass();
});

View File

@ -4,7 +4,7 @@ export type VALUE_TYPE = "Value" | "Address" | "Invalid";
export interface IEntry {
entity: Address;
attribute: string;
value: { t: VALUE_TYPE; c: string };
value: { t: VALUE_TYPE; c: string | number };
}
export interface ListingResult {

View File

@ -2885,7 +2885,7 @@ __metadata:
"typescript@patch:typescript@^4.4.4#~builtin<compat/typescript>":
version: 4.4.4
resolution: "typescript@patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=493e53"
resolution: "typescript@patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=ddd1e8"
bin:
tsc: bin/tsc
tsserver: bin/tsserver

View File

@ -2,9 +2,8 @@
import { useSWR } from "../util/fetch";
import { derived, Readable, readable, writable } from "svelte/store";
import type { IEntry, ListingResult, OrderedListing } from "upend/types";
import { listingAsOrdered } from "upend";
import { listingAsOrdered, UpEntry } from "upend";
import LRU from "lru-cache";
import { attr } from "svelte/internal";
export function useEntity(
address: string | (() => string),
@ -82,13 +81,13 @@ export async function queryOnce(query: string): Promise<OrderedListing> {
}
export async function identify(
attributes: OrderedListing,
backlinks: OrderedListing
attributes: UpEntry[],
backlinks: UpEntry[]
): Promise<string[]> {
// Get all entries where the object is linked
const hasEntries = backlinks
.filter(([_, entry]) => entry.attribute === "HAS")
.map(([addr, _]) => addr);
.filter((entry) => entry.attribute === "HAS")
.map((entry) => entry.address);
// Out of those relations, retrieve their ALIAS attrs
const hasAliases = hasEntries.length
@ -97,13 +96,11 @@ export async function identify(
)
: [];
const aliasValues = hasAliases.map(([_, entry]) => {
return entry.value.c;
});
const aliasValues = hasAliases.map(([_, entry]) => String(entry.value.c));
// Return all LBLs concatenated with named aliases
return attributes
.filter(([_, attr]) => attr.attribute === "LBL")
.map(([_, attr]) => attr.value.c)
.filter((attr) => attr.attribute === "LBL")
.map((attr) => String(attr.value.c))
.concat(aliasValues);
}

View File

@ -3301,8 +3301,8 @@ __metadata:
"upend@file:../tools/upend_js::locator=svelte-app%40workspace%3A.":
version: 0.0.1
resolution: "upend@file:../tools/upend_js#../tools/upend_js::hash=cc5701&locator=svelte-app%40workspace%3A."
checksum: e0acfc00449acb9243dccbf595de95746469d9ec74dcf064bd5fa17103048396578d4a8530ce68943fb095790e980c04961f0f0fe79f7edc1ed1cbfafddd5766
resolution: "upend@file:../tools/upend_js#../tools/upend_js::hash=33980e&locator=svelte-app%40workspace%3A."
checksum: 6370b50d9a8c407e5807f62020fa045f0df1ad727b12d6273fe00cf08b47cc75da6d89493538b084ab5fddd66d3e735fcda33e750fe729910e6ee5be6d66d14e
languageName: node
linkType: hard