basic object-based js API
This commit is contained in:
parent
fed5c72f55
commit
cce0c2cdd5
6 changed files with 91 additions and 43 deletions
|
@ -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 {
|
export function listingAsOrdered(listing: ListingResult): OrderedListing {
|
||||||
const entries = Object.entries(listing) as [Address, IEntry][];
|
const entries = Object.entries(listing) as [Address, IEntry][];
|
||||||
return entries
|
return entries
|
||||||
.sort(([_, a], [__, b]) => String(a.value.c).localeCompare(b.value.c))
|
.sort(([_, a], [__, b]) =>
|
||||||
.sort(([_, a], [__, b]) => String(a.value.t).localeCompare(b.value.t))
|
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));
|
.sort(([_, a], [__, b]) => a.attribute.localeCompare(b.attribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asDict(attributes: IEntry[]) {
|
export class UpListing {
|
||||||
const result = {} as { [key: string]: { [key: string]: unknown } };
|
private entries: UpEntry[];
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
import http from "http";
|
import http from "http";
|
||||||
import { asDict, listingAsOrdered } from ".";
|
import { UpObject, UpEntry, UpListing } from ".";
|
||||||
import { ListingResult, OrderedListing } from "./types";
|
import type { Address, IEntry, ListingResult } from "./types";
|
||||||
|
|
||||||
function fetchJSON(url: string): Promise<unknown> {
|
function fetchJSON(url: string): Promise<unknown> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -23,12 +23,17 @@ function fetchJSON(url: string): Promise<unknown> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
test("my passing test", async (t) => {
|
test("basic hier listing", async (t) => {
|
||||||
const data = (await fetchJSON(
|
const data = (await fetchJSON("http://localhost:8093/api/hier/NATIVE")) as {
|
||||||
"http://localhost:8093/api/hier/NATIVE"
|
target: Address;
|
||||||
)) as ListingResult;
|
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();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ export type VALUE_TYPE = "Value" | "Address" | "Invalid";
|
||||||
export interface IEntry {
|
export interface IEntry {
|
||||||
entity: Address;
|
entity: Address;
|
||||||
attribute: string;
|
attribute: string;
|
||||||
value: { t: VALUE_TYPE; c: string };
|
value: { t: VALUE_TYPE; c: string | number };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListingResult {
|
export interface ListingResult {
|
||||||
|
|
|
@ -2885,7 +2885,7 @@ __metadata:
|
||||||
|
|
||||||
"typescript@patch:typescript@^4.4.4#~builtin<compat/typescript>":
|
"typescript@patch:typescript@^4.4.4#~builtin<compat/typescript>":
|
||||||
version: 4.4.4
|
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:
|
bin:
|
||||||
tsc: bin/tsc
|
tsc: bin/tsc
|
||||||
tsserver: bin/tsserver
|
tsserver: bin/tsserver
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
import { useSWR } from "../util/fetch";
|
import { useSWR } from "../util/fetch";
|
||||||
import { derived, Readable, readable, writable } from "svelte/store";
|
import { derived, Readable, readable, writable } from "svelte/store";
|
||||||
import type { IEntry, ListingResult, OrderedListing } from "upend/types";
|
import type { IEntry, ListingResult, OrderedListing } from "upend/types";
|
||||||
import { listingAsOrdered } from "upend";
|
import { listingAsOrdered, UpEntry } from "upend";
|
||||||
import LRU from "lru-cache";
|
import LRU from "lru-cache";
|
||||||
import { attr } from "svelte/internal";
|
|
||||||
|
|
||||||
export function useEntity(
|
export function useEntity(
|
||||||
address: string | (() => string),
|
address: string | (() => string),
|
||||||
|
@ -82,13 +81,13 @@ export async function queryOnce(query: string): Promise<OrderedListing> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function identify(
|
export async function identify(
|
||||||
attributes: OrderedListing,
|
attributes: UpEntry[],
|
||||||
backlinks: OrderedListing
|
backlinks: UpEntry[]
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
// Get all entries where the object is linked
|
// Get all entries where the object is linked
|
||||||
const hasEntries = backlinks
|
const hasEntries = backlinks
|
||||||
.filter(([_, entry]) => entry.attribute === "HAS")
|
.filter((entry) => entry.attribute === "HAS")
|
||||||
.map(([addr, _]) => addr);
|
.map((entry) => entry.address);
|
||||||
|
|
||||||
// Out of those relations, retrieve their ALIAS attrs
|
// Out of those relations, retrieve their ALIAS attrs
|
||||||
const hasAliases = hasEntries.length
|
const hasAliases = hasEntries.length
|
||||||
|
@ -97,13 +96,11 @@ export async function identify(
|
||||||
)
|
)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const aliasValues = hasAliases.map(([_, entry]) => {
|
const aliasValues = hasAliases.map(([_, entry]) => String(entry.value.c));
|
||||||
return entry.value.c;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return all LBLs concatenated with named aliases
|
// Return all LBLs concatenated with named aliases
|
||||||
return attributes
|
return attributes
|
||||||
.filter(([_, attr]) => attr.attribute === "LBL")
|
.filter((attr) => attr.attribute === "LBL")
|
||||||
.map(([_, attr]) => attr.value.c)
|
.map((attr) => String(attr.value.c))
|
||||||
.concat(aliasValues);
|
.concat(aliasValues);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3301,8 +3301,8 @@ __metadata:
|
||||||
|
|
||||||
"upend@file:../tools/upend_js::locator=svelte-app%40workspace%3A.":
|
"upend@file:../tools/upend_js::locator=svelte-app%40workspace%3A.":
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
resolution: "upend@file:../tools/upend_js#../tools/upend_js::hash=cc5701&locator=svelte-app%40workspace%3A."
|
resolution: "upend@file:../tools/upend_js#../tools/upend_js::hash=33980e&locator=svelte-app%40workspace%3A."
|
||||||
checksum: e0acfc00449acb9243dccbf595de95746469d9ec74dcf064bd5fa17103048396578d4a8530ce68943fb095790e980c04961f0f0fe79f7edc1ed1cbfafddd5766
|
checksum: 6370b50d9a8c407e5807f62020fa045f0df1ad727b12d6273fe00cf08b47cc75da6d89493538b084ab5fddd66d3e735fcda33e750fe729910e6ee5be6d66d14e
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue