basic object-based js API

This commit is contained in:
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 { 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;
}
} }

View file

@ -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();
}); });

View file

@ -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 {

View file

@ -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

View file

@ -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);
} }

View file

@ -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