Browse Source

Use ES2025 private member syntax

master
buttercat1791 1 year ago
parent
commit
43dac80578
  1. 7
      src/lib/data_structures/lazy.ts
  2. 82
      src/lib/data_structures/publication_tree.ts

7
src/lib/data_structures/lazy.ts

@ -1,11 +1,14 @@
export class Lazy<T> { export class Lazy<T> {
#value?: T; #value?: T;
#resolver: () => Promise<T>;
constructor(private readonly resolver: () => Promise<T>) {} constructor(resolver: () => Promise<T>) {
this.#resolver = resolver;
}
async value(): Promise<T> { async value(): Promise<T> {
if (!this.#value) { if (!this.#value) {
this.#value = await this.resolver(); this.#value = await this.#resolver();
} }
return this.#value; return this.#value;

82
src/lib/data_structures/publication_tree.ts

@ -19,48 +19,48 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
/** /**
* The root node of the tree. * The root node of the tree.
*/ */
private root: PublicationTreeNode; #root: PublicationTreeNode;
/** /**
* A map of addresses in the tree to their corresponding nodes. * A map of addresses in the tree to their corresponding nodes.
*/ */
private nodes: Map<string, PublicationTreeNode>; #nodes: Map<string, PublicationTreeNode>;
/** /**
* A map of addresses in the tree to their corresponding events. * A map of addresses in the tree to their corresponding events.
*/ */
private events: Map<string, NDKEvent>; #events: Map<string, NDKEvent>;
/** /**
* An ordered list of the addresses of the leaves of the tree. * An ordered list of the addresses of the leaves of the tree.
*/ */
private leaves: string[] = []; #leaves: string[] = [];
/** /**
* The address of the last-visited node. Used for iteration and progressive retrieval. * The address of the last-visited node. Used for iteration and progressive retrieval.
*/ */
private bookmark?: string; #bookmark?: string;
/** /**
* The NDK instance used to fetch events. * The NDK instance used to fetch events.
*/ */
private ndk: NDK; #ndk: NDK;
constructor(rootEvent: NDKEvent, ndk: NDK) { constructor(rootEvent: NDKEvent, ndk: NDK) {
const rootAddress = rootEvent.tagAddress(); const rootAddress = rootEvent.tagAddress();
this.root = { this.#root = {
type: PublicationTreeNodeType.Root, type: PublicationTreeNodeType.Root,
address: rootAddress, address: rootAddress,
children: [], children: [],
}; };
this.nodes = new Map<string, PublicationTreeNode>(); this.#nodes = new Map<string, PublicationTreeNode>();
this.nodes.set(rootAddress, this.root); this.#nodes.set(rootAddress, this.#root);
this.events = new Map<string, NDKEvent>(); this.#events = new Map<string, NDKEvent>();
this.events.set(rootAddress, rootEvent); this.#events.set(rootAddress, rootEvent);
this.ndk = ndk; this.#ndk = ndk;
} }
/** /**
@ -74,7 +74,7 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
addEvent(event: NDKEvent, parentEvent: NDKEvent) { addEvent(event: NDKEvent, parentEvent: NDKEvent) {
const address = event.tagAddress(); const address = event.tagAddress();
const parentAddress = parentEvent.tagAddress(); const parentAddress = parentEvent.tagAddress();
const parentNode = this.nodes.get(parentAddress); const parentNode = this.#nodes.get(parentAddress);
if (!parentNode) { if (!parentNode) {
throw new Error( throw new Error(
@ -83,14 +83,14 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
} }
const node = { const node = {
type: this.getNodeType(event), type: this.#getNodeType(event),
address, address,
parent: parentNode, parent: parentNode,
children: [], children: [],
}; };
parentNode.children!.push(new Lazy<PublicationTreeNode>(() => Promise.resolve(node))); parentNode.children!.push(new Lazy<PublicationTreeNode>(() => Promise.resolve(node)));
this.nodes.set(address, node); this.#nodes.set(address, node);
this.events.set(address, event); this.#events.set(address, event);
} }
/** /**
@ -103,7 +103,7 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
*/ */
addEventByAddress(address: string, parentEvent: NDKEvent) { addEventByAddress(address: string, parentEvent: NDKEvent) {
const parentAddress = parentEvent.tagAddress(); const parentAddress = parentEvent.tagAddress();
const parentNode = this.nodes.get(parentAddress); const parentNode = this.#nodes.get(parentAddress);
if (!parentNode) { if (!parentNode) {
throw new Error( throw new Error(
@ -112,7 +112,7 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
} }
parentNode.children!.push( parentNode.children!.push(
new Lazy<PublicationTreeNode>(() => this.resolveNode(address, parentNode)) new Lazy<PublicationTreeNode>(() => this.#resolveNode(address, parentNode))
); );
} }
@ -122,9 +122,9 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
* @returns The event, or null if the event is not found. * @returns The event, or null if the event is not found.
*/ */
async getEvent(address: string): Promise<NDKEvent | null> { async getEvent(address: string): Promise<NDKEvent | null> {
let event = this.events.get(address) ?? null; let event = this.#events.get(address) ?? null;
if (!event) { if (!event) {
event = await this.depthFirstRetrieve(address); event = await this.#depthFirstRetrieve(address);
} }
return event; return event;
@ -135,12 +135,12 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
* @param address The address of the event to bookmark. * @param address The address of the event to bookmark.
*/ */
setBookmark(address: string) { setBookmark(address: string) {
this.bookmark = address; this.#bookmark = address;
this.#cursor.tryMoveTo(address); this.#cursor.tryMoveTo(address);
} }
[Symbol.asyncIterator](): AsyncIterator<NDKEvent> { [Symbol.asyncIterator](): AsyncIterator<NDKEvent> {
this.#cursor.tryMoveTo(this.bookmark); this.#cursor.tryMoveTo(this.#bookmark);
return this; return this;
} }
@ -176,29 +176,29 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
* will return the first leaf in the tree. * will return the first leaf in the tree.
* @returns The event, or null if the event is not found. * @returns The event, or null if the event is not found.
*/ */
private async depthFirstRetrieve(address?: string): Promise<NDKEvent | null> { async #depthFirstRetrieve(address?: string): Promise<NDKEvent | null> {
if (address && this.nodes.has(address)) { if (address && this.#nodes.has(address)) {
return this.events.get(address)!; return this.#events.get(address)!;
} }
const stack: string[] = [this.root.address]; const stack: string[] = [this.#root.address];
let currentEvent: NDKEvent | null | undefined; let currentEvent: NDKEvent | null | undefined;
while (stack.length > 0) { while (stack.length > 0) {
const currentAddress = stack.pop(); const currentAddress = stack.pop();
// Stop immediately if the target of the search is found. // Stop immediately if the target of the search is found.
if (address != null && currentAddress === address) { if (address != null && currentAddress === address) {
return this.events.get(address)!; return this.#events.get(address)!;
} }
// Augment the tree with the children of the current event. // Augment the tree with the children of the current event.
const currentChildAddresses = this.events const currentChildAddresses = this.#events
.get(currentAddress!)!.tags .get(currentAddress!)!.tags
.filter(tag => tag[0] === 'a') .filter(tag => tag[0] === 'a')
.map(tag => tag[1]); .map(tag => tag[1]);
for (const childAddress of currentChildAddresses) { for (const childAddress of currentChildAddresses) {
if (this.nodes.has(childAddress)) { if (this.#nodes.has(childAddress)) {
continue; continue;
} }
@ -207,7 +207,7 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
// If the current event has no children, it is a leaf. // If the current event has no children, it is a leaf.
if (currentChildAddresses.length === 0) { if (currentChildAddresses.length === 0) {
this.leaves.push(currentAddress!); this.#leaves.push(currentAddress!);
// Return the first leaf if no address was provided. // Return the first leaf if no address was provided.
if (address == null) { if (address == null) {
@ -226,12 +226,12 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
return null; return null;
} }
private async resolveNode( async #resolveNode(
address: string, address: string,
parentNode: PublicationTreeNode parentNode: PublicationTreeNode
): Promise<PublicationTreeNode> { ): Promise<PublicationTreeNode> {
const [kind, pubkey, dTag] = address.split(':'); const [kind, pubkey, dTag] = address.split(':');
const event = await this.ndk.fetchEvent({ const event = await this.#ndk.fetchEvent({
kinds: [parseInt(kind)], kinds: [parseInt(kind)],
authors: [pubkey], authors: [pubkey],
'#d': [dTag], '#d': [dTag],
@ -245,23 +245,23 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
const childAddresses = event.tags.filter(tag => tag[0] === 'a').map(tag => tag[1]); const childAddresses = event.tags.filter(tag => tag[0] === 'a').map(tag => tag[1]);
const node: PublicationTreeNode = { const node: PublicationTreeNode = {
type: this.getNodeType(event), type: this.#getNodeType(event),
address, address,
parent: parentNode, parent: parentNode,
children: childAddresses.map( children: childAddresses.map(
address => new Lazy<PublicationTreeNode>(() => this.resolveNode(address, node)) address => new Lazy<PublicationTreeNode>(() => this.#resolveNode(address, node))
), ),
}; };
this.nodes.set(address, node); this.#nodes.set(address, node);
this.events.set(address, event); this.#events.set(address, event);
return node; return node;
} }
private getNodeType(event: NDKEvent): PublicationTreeNodeType { #getNodeType(event: NDKEvent): PublicationTreeNodeType {
const address = event.tagAddress(); const address = event.tagAddress();
const node = this.nodes.get(address); const node = this.#nodes.get(address);
if (!node) { if (!node) {
throw new Error( throw new Error(
`PublicationTree: Event with address ${address} not found in the tree.` `PublicationTree: Event with address ${address} not found in the tree.`
@ -294,10 +294,10 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
async tryMoveTo(address?: string) { async tryMoveTo(address?: string) {
if (!address) { if (!address) {
const startEvent = await this.#tree.depthFirstRetrieve(); const startEvent = await this.#tree.#depthFirstRetrieve();
this.target = this.#tree.nodes.get(startEvent!.tagAddress()); this.target = this.#tree.#nodes.get(startEvent!.tagAddress());
} else { } else {
this.target = this.#tree.nodes.get(address); this.target = this.#tree.#nodes.get(address);
} }
if (!this.target) { if (!this.target) {

Loading…
Cancel
Save