Add some type utils, findFeed, and fix feed listener to use limit: 0 instead of since
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
--ignore-dir=docs/assets
|
||||||
--ignore-dir=docs/reference
|
--ignore-dir=docs/reference
|
||||||
--ignore-dir=docs/.vitepress/cache
|
--ignore-dir=docs/.vitepress/cache
|
||||||
--ignore-dir=dist
|
--ignore-dir=dist
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ export class FeedController {
|
|||||||
|
|
||||||
// Load events with specified limit
|
// Load events with specified limit
|
||||||
load(limit: number): Promise<void>
|
load(limit: number): Promise<void>
|
||||||
|
|
||||||
|
// Get listener function (memoized)
|
||||||
|
getListener(): Promise<() => Promise<void>>
|
||||||
|
|
||||||
|
// Listen for new events in the feed
|
||||||
|
listen(): Promise<void>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -90,4 +96,10 @@ await controller.load(50)
|
|||||||
|
|
||||||
// Load more events
|
// Load more events
|
||||||
await controller.load(50)
|
await controller.load(50)
|
||||||
|
|
||||||
|
// Listen for new events
|
||||||
|
const unlisten = controller.listen()
|
||||||
|
|
||||||
|
// Unsubscribe from listener
|
||||||
|
unlisten()
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -123,6 +123,23 @@ walkFeed(feed, (node) => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Find a specific feed in a feed tree:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const feed = makeIntersectionFeed(
|
||||||
|
makeAuthorFeed("pubkey1"),
|
||||||
|
makeUnionFeed(
|
||||||
|
makeKindFeed(1),
|
||||||
|
makeTagFeed("#t", "bitcoin")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Find a feed matching a specific condition
|
||||||
|
const bitcoinTagFeed = findFeed(feed, (f) =>
|
||||||
|
isTagFeed(f) && getFeedArgs(f)[1] === "bitcoin"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
## Feed Simplification
|
## Feed Simplification
|
||||||
|
|
||||||
Flatten nested feeds of the same type:
|
Flatten nested feeds of the same type:
|
||||||
|
|||||||
@@ -2,6 +2,36 @@
|
|||||||
|
|
||||||
The `Tools` module provides a comprehensive collection of utility functions for common programming tasks. It includes functions for array manipulation, object handling, type checking, math operations, and more.
|
The `Tools` module provides a comprehensive collection of utility functions for common programming tasks. It includes functions for array manipulation, object handling, type checking, math operations, and more.
|
||||||
|
|
||||||
|
## Working with types
|
||||||
|
|
||||||
|
Utility types for TypeScript development:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Override properties of type T with properties from type R
|
||||||
|
export type Override<T, R> = Omit<T, keyof R> & R;
|
||||||
|
|
||||||
|
// Make specific properties of type T optional
|
||||||
|
export type MakeOptional<T, K extends keyof T> = Override<T, Partial<Pick<T, K>>>;
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```typescript
|
||||||
|
interface User {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
age: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the id to be a number instead
|
||||||
|
type UserWithNumericId = Override<User, { id: number }>;
|
||||||
|
// Result: { id: number; name: string; email: string; age: number; }
|
||||||
|
|
||||||
|
// Make email and age optional
|
||||||
|
type PartialUser = MakeOptional<User, 'email' | 'age'>;
|
||||||
|
// Result: { id: string; name: string; email?: string; age?: number; }
|
||||||
|
```
|
||||||
|
|
||||||
## Basic functional programming utilities
|
## Basic functional programming utilities
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman",
|
"name": "@welshman",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/app",
|
"name": "@welshman/app",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A collection of svelte stores for use in building nostr client applications.",
|
"description": "A collection of svelte stores for use in building nostr client applications.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/content",
|
"name": "@welshman/content",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A collection of utilities for parsing nostr note content.",
|
"description": "A collection of utilities for parsing nostr note content.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/editor",
|
"name": "@welshman/editor",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A batteries-included nostr editor.",
|
"description": "A batteries-included nostr editor.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/feeds",
|
"name": "@welshman/feeds",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Utilities for building dynamic nostr feeds.",
|
"description": "Utilities for building dynamic nostr feeds.",
|
||||||
|
|||||||
@@ -350,12 +350,9 @@ export class FeedController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const since = now()
|
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
const signal = AbortSignal.any(removeNil([controller.signal, this.options.signal]))
|
const signal = AbortSignal.any(removeNil([controller.signal, this.options.signal]))
|
||||||
const requestFilters = filters!
|
const requestFilters = filters!.map((filter: Filter) => ({...filter, limit: 0}))
|
||||||
.filter((filter: Filter) => !filter.until || filter.until <= since)
|
|
||||||
.map((filter: Filter) => ({...filter, since}))
|
|
||||||
|
|
||||||
requestPage(
|
requestPage(
|
||||||
omitVals([undefined], {
|
omitVals([undefined], {
|
||||||
|
|||||||
@@ -214,6 +214,20 @@ export const walkFeed = (feed: Feed, visit: (feed: Feed) => void) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const findFeed = (feed: Feed, match: (feed: Feed) => boolean): Feed | undefined => {
|
||||||
|
if (match(feed)) return feed
|
||||||
|
|
||||||
|
if (hasSubFeeds(feed)) {
|
||||||
|
for (const subFeed of getFeedArgs(feed)) {
|
||||||
|
const found = findFeed(subFeed, match)
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const simplifyFeed = (feed: Feed): Feed => {
|
export const simplifyFeed = (feed: Feed): Feed => {
|
||||||
if (isUnionFeed(feed)) {
|
if (isUnionFeed(feed)) {
|
||||||
const args = getFeedArgs(feed)
|
const args = getFeedArgs(feed)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/lib",
|
"name": "@welshman/lib",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A collection of utilities.",
|
"description": "A collection of utilities.",
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ export const isNotNil = <T>(x: T, ...args: unknown[]) => x !== undefined && x !=
|
|||||||
|
|
||||||
export const assertNotNil = <T>(x: T, ...args: unknown[]) => x!
|
export const assertNotNil = <T>(x: T, ...args: unknown[]) => x!
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Working with types
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export type Override<T, R> = Omit<T, keyof R> & R
|
||||||
|
|
||||||
|
export type MakeOptional<T, K extends keyof T> = Override<T, Partial<Pick<T, K>>>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Basic functional programming utilities
|
// Basic functional programming utilities
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/net",
|
"name": "@welshman/net",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Utilities for connecting with nostr relays.",
|
"description": "Utilities for connecting with nostr relays.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/relay",
|
"name": "@welshman/relay",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "An in-memory nostr relay implementation.",
|
"description": "An in-memory nostr relay implementation.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/router",
|
"name": "@welshman/router",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A collection of utilities for nostr relay selection.",
|
"description": "A collection of utilities for nostr relay selection.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/signer",
|
"name": "@welshman/signer",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A nostr signer implemenation supporting several login methods.",
|
"description": "A nostr signer implemenation supporting several login methods.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/store",
|
"name": "@welshman/store",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A collection of utilities based on svelte/store for use with welshman",
|
"description": "A collection of utilities based on svelte/store for use with welshman",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/util",
|
"name": "@welshman/util",
|
||||||
"version": "0.4.5",
|
"version": "0.4.6",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A collection of nostr-related utilities.",
|
"description": "A collection of nostr-related utilities.",
|
||||||
|
|||||||
Reference in New Issue
Block a user