applesauce-core 6.0.2 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,6 @@
1
- import { Observable } from "rxjs";
2
1
  import { EventModels, IEventStoreStreams, IEventSubscriptions } from "../event-store/index.js";
3
2
  import { NostrEvent } from "../helpers/event.js";
4
- import { ChainableObservable } from "../observable/chainable.js";
5
- import { User } from "./user.js";
3
+ import { EventCast } from "./event.js";
6
4
  /** The type of event store that is passed to cast references */
7
5
  export type CastRefEventStore = IEventSubscriptions & EventModels & IEventStoreStreams;
8
6
  /** A symbol used to store all the cast instances for a given event */
@@ -13,19 +11,3 @@ export declare const CASTS_SYMBOL: unique symbol;
13
11
  export type CastConstructor<C extends EventCast<NostrEvent>> = new (event: NostrEvent, store: CastRefEventStore) => C;
14
12
  /** Cast a Nostr event to a specific class */
15
13
  export declare function castEvent<C extends EventCast<NostrEvent>>(event: NostrEvent, cls: CastConstructor<C>, store?: CastRefEventStore): C;
16
- /** The base class for all casts */
17
- export declare class EventCast<T extends NostrEvent = NostrEvent> {
18
- #private;
19
- readonly event: T;
20
- readonly store: CastRefEventStore;
21
- get id(): string;
22
- get uid(): string;
23
- get createdAt(): Date;
24
- /** Get the {@link User} that authored this event */
25
- get author(): User;
26
- /** Return the set of relays this event was seen on */
27
- get seen(): Set<string> | undefined;
28
- constructor(event: T, store: CastRefEventStore);
29
- /** Internal method for creating a reference */
30
- protected $$ref<Return extends unknown>(key: string, builder: (store: CastRefEventStore) => Observable<Return>): ChainableObservable<Return>;
31
- }
@@ -1,7 +1,4 @@
1
- import { getEventUID, getParentEventStore } from "../helpers/event.js";
2
- import { getSeenRelays } from "../helpers/relays.js";
3
- import { chainable } from "../observable/chainable.js";
4
- import { castUser } from "./user.js";
1
+ import { getParentEventStore } from "../helpers/event.js";
5
2
  /** A symbol used to store all the cast instances for a given event */
6
3
  export const CAST_REF_SYMBOL = Symbol.for("cast-ref");
7
4
  /** A symbol used to store all the casts for an event */
@@ -26,42 +23,3 @@ export function castEvent(event, cls, store) {
26
23
  casts.set(cls, cast);
27
24
  return cast;
28
25
  }
29
- /** The base class for all casts */
30
- export class EventCast {
31
- event;
32
- store;
33
- get id() {
34
- return this.event.id;
35
- }
36
- get uid() {
37
- return getEventUID(this.event);
38
- }
39
- get createdAt() {
40
- return new Date(this.event.created_at * 1000);
41
- }
42
- /** Get the {@link User} that authored this event */
43
- get author() {
44
- return castUser(this.event, this.store);
45
- }
46
- /** Return the set of relays this event was seen on */
47
- get seen() {
48
- return getSeenRelays(this.event);
49
- }
50
- // Enfore kind check in constructor. this will force child classes to verify the event before calling super()
51
- constructor(event, store) {
52
- this.event = event;
53
- this.store = store;
54
- }
55
- /** A cache of observable references */
56
- #refs = {};
57
- /** Internal method for creating a reference */
58
- $$ref(key, builder) {
59
- // Return cached observable
60
- if (this.#refs[key])
61
- return this.#refs[key];
62
- // Build a new observable and cache it
63
- const observable = chainable(builder(this.store));
64
- this.#refs[key] = observable;
65
- return observable;
66
- }
67
- }
@@ -0,0 +1,33 @@
1
+ import { Observable } from "rxjs";
2
+ import { NostrEvent } from "../helpers/event.js";
3
+ import { AddressPointer, EventPointer } from "../helpers/pointers.js";
4
+ import { ChainableObservable } from "../observable/chainable.js";
5
+ import { CastRefEventStore } from "./cast.js";
6
+ import { User } from "./user.js";
7
+ /** The base class for all casts */
8
+ export declare class EventCast<T extends NostrEvent = NostrEvent> {
9
+ #private;
10
+ readonly event: T;
11
+ readonly store: CastRefEventStore;
12
+ /** Alias for event.id */
13
+ get id(): string;
14
+ /** Alias for event.kind */
15
+ get kind(): number;
16
+ /** Returns the unique identifier for this event */
17
+ get uid(): string;
18
+ /** Returns the created_at timestamp as a Date object */
19
+ get createdAt(): Date;
20
+ /** Get the {@link User} that authored this event */
21
+ get author(): User;
22
+ /** Return the set of relays this event was seen on */
23
+ get seen(): Set<string> | undefined;
24
+ /** Returns the NIP-01 address string for this event if its replaceable or addressable, otherwise returns null */
25
+ get coordinate(): string | null;
26
+ /** Alias for {@link coordinate} */
27
+ get replaceableAddress(): string | null;
28
+ /** Returns a single {@link EventPointer} or {@link AddressPointer} for this event */
29
+ get pointer(): EventPointer | AddressPointer;
30
+ constructor(event: T, store: CastRefEventStore);
31
+ /** Internal method for creating a reference */
32
+ protected $$ref<Return extends unknown>(key: string, builder: (store: CastRefEventStore) => Observable<Return>): ChainableObservable<Return>;
33
+ }
@@ -0,0 +1,65 @@
1
+ import { getEventUID, isAddressableKind, isReplaceableKind } from "../helpers/event.js";
2
+ import { getAddressPointerForEvent, getEventPointerForEvent, getReplaceableAddressForEvent, } from "../helpers/pointers.js";
3
+ import { getSeenRelays } from "../helpers/relays.js";
4
+ import { chainable } from "../observable/chainable.js";
5
+ import { castUser } from "./user.js";
6
+ /** The base class for all casts */
7
+ export class EventCast {
8
+ event;
9
+ store;
10
+ /** Alias for event.id */
11
+ get id() {
12
+ return this.event.id;
13
+ }
14
+ /** Alias for event.kind */
15
+ get kind() {
16
+ return this.event.kind;
17
+ }
18
+ /** Returns the unique identifier for this event */
19
+ get uid() {
20
+ return getEventUID(this.event);
21
+ }
22
+ /** Returns the created_at timestamp as a Date object */
23
+ get createdAt() {
24
+ return new Date(this.event.created_at * 1000);
25
+ }
26
+ /** Get the {@link User} that authored this event */
27
+ get author() {
28
+ return castUser(this.event, this.store);
29
+ }
30
+ /** Return the set of relays this event was seen on */
31
+ get seen() {
32
+ return getSeenRelays(this.event);
33
+ }
34
+ /** Returns the NIP-01 address string for this event if its replaceable or addressable, otherwise returns null */
35
+ get coordinate() {
36
+ return getReplaceableAddressForEvent(this.event);
37
+ }
38
+ /** Alias for {@link coordinate} */
39
+ get replaceableAddress() {
40
+ return this.coordinate;
41
+ }
42
+ /** Returns a single {@link EventPointer} or {@link AddressPointer} for this event */
43
+ get pointer() {
44
+ if (isReplaceableKind(this.kind) || isAddressableKind(this.kind))
45
+ return getAddressPointerForEvent(this.event) || getEventPointerForEvent(this.event);
46
+ return getEventPointerForEvent(this.event);
47
+ }
48
+ // Enfore kind check in constructor. this will force child classes to verify the event before calling super()
49
+ constructor(event, store) {
50
+ this.event = event;
51
+ this.store = store;
52
+ }
53
+ /** A cache of observable references */
54
+ #refs = {};
55
+ /** Internal method for creating a reference */
56
+ $$ref(key, builder) {
57
+ // Return cached observable
58
+ if (this.#refs[key])
59
+ return this.#refs[key];
60
+ // Build a new observable and cache it
61
+ const observable = chainable(builder(this.store));
62
+ this.#refs[key] = observable;
63
+ return observable;
64
+ }
65
+ }
@@ -1,3 +1,4 @@
1
1
  export * from "./cast.js";
2
+ export * from "./event.js";
2
3
  export * from "./pubkey.js";
3
4
  export * from "./user.js";
@@ -1,3 +1,4 @@
1
1
  export * from "./cast.js";
2
+ export * from "./event.js";
2
3
  export * from "./pubkey.js";
3
4
  export * from "./user.js";
@@ -1,4 +1,3 @@
1
- /** A constructor type for {@link PubkeyCast} subclasses */
2
1
  import { Observable } from "rxjs";
3
2
  import { NostrEvent } from "../helpers/event.js";
4
3
  import type { ProfilePointer } from "../helpers/pointers.js";
@@ -1,4 +1,3 @@
1
- /** A constructor type for {@link PubkeyCast} subclasses */
2
1
  import { isEvent } from "../helpers/event.js";
3
2
  import { isHexKey } from "../helpers/string.js";
4
3
  import { chainable } from "../observable/chainable.js";
@@ -1,8 +1,11 @@
1
+ import { Observable } from "rxjs";
1
2
  import { NostrEvent } from "../helpers/event.js";
3
+ import { Filter } from "../helpers/filter.js";
2
4
  import { ProfilePointer } from "../helpers/pointers.js";
3
5
  import { ChainableObservable } from "../observable/chainable.js";
4
- import type { CastRefEventStore } from "./cast.js";
6
+ import type { CastConstructor, CastRefEventStore } from "./cast.js";
5
7
  import { PubkeyCast } from "./pubkey.js";
8
+ import { EventCast } from "./event.js";
6
9
  /** Cast a Nostr event or pointer into a {@link User} */
7
10
  export declare function castUser(event: NostrEvent, store: CastRefEventStore): User;
8
11
  export declare function castUser(user: string | ProfilePointer, store: CastRefEventStore): User;
@@ -10,10 +13,19 @@ export declare function castUser(user: string | ProfilePointer, store: CastRefEv
10
13
  export declare class User extends PubkeyCast {
11
14
  /** A global cache of pubkey -> {@link User} */
12
15
  static cache: Map<string, User>;
16
+ /** Returns the NIP-19 npub for this user */
13
17
  get npub(): `npub1${string}`;
18
+ /** Returns the NIP-19 nprofile for this user */
14
19
  get nprofile(): `nprofile1${string}`;
15
20
  /** Subscribe to a replaceable event for this user */
16
21
  replaceable(kind: number, identifier?: string, relays?: string[]): ChainableObservable<NostrEvent | undefined>;
17
22
  /** Subscribe to an addressable event for this user */
18
23
  addressable(kind: number, identifier: string, relays?: string[]): ChainableObservable<NostrEvent | undefined>;
24
+ /**
25
+ * Creates an observable of a timeline of events created by this user
26
+ * @param input - The filter(s) for the timeline or kind(s)
27
+ * @returns A timeline observable of events by the user rom the event store
28
+ */
29
+ timeline$(input: Omit<Filter, "authors"> | Omit<Filter, "authors">[] | number | number[]): Observable<NostrEvent[]>;
30
+ timeline$<T extends EventCast>(input: Omit<Filter, "authors"> | Omit<Filter, "authors">[] | number | number[], cast?: CastConstructor<T>): Observable<T[]>;
19
31
  }
@@ -1,6 +1,8 @@
1
+ import hash_sum from "hash-sum";
1
2
  import { nprofileEncode, npubEncode } from "../helpers/pointers.js";
2
3
  import { chainable } from "../observable/chainable.js";
3
4
  import { castPubkey, PubkeyCast } from "./pubkey.js";
5
+ import { castTimelineStream } from "../observable/cast-stream.js";
4
6
  export function castUser(user, store) {
5
7
  return castPubkey(user, User, store);
6
8
  }
@@ -8,9 +10,11 @@ export function castUser(user, store) {
8
10
  export class User extends PubkeyCast {
9
11
  /** A global cache of pubkey -> {@link User} */
10
12
  static cache = new Map();
13
+ /** Returns the NIP-19 npub for this user */
11
14
  get npub() {
12
15
  return npubEncode(this.pubkey);
13
16
  }
17
+ /** Returns the NIP-19 nprofile for this user */
14
18
  get nprofile() {
15
19
  return nprofileEncode(this.pointer);
16
20
  }
@@ -22,4 +26,24 @@ export class User extends PubkeyCast {
22
26
  addressable(kind, identifier, relays) {
23
27
  return chainable(this.store.addressable({ kind, pubkey: this.pointer.pubkey, identifier, relays }));
24
28
  }
29
+ timeline$(input, cast) {
30
+ let filters = [];
31
+ if (typeof input === "number") {
32
+ filters.push({ kinds: [input] });
33
+ }
34
+ else if (Array.isArray(input)) {
35
+ filters.push(...input.map((f) => (typeof f === "number" ? { kinds: [f] } : f)));
36
+ }
37
+ else if (input instanceof Object) {
38
+ filters.push(input);
39
+ }
40
+ // Use hash_sum to create a unique key for the timeline observable
41
+ const key = "timeline$|" + hash_sum(filters);
42
+ const base$ = this.$$ref(key, (store) => store.timeline(filters.map((f) => ({ ...f, authors: [this.pubkey] }))));
43
+ // Cast the timeline stream into a cast if provided
44
+ if (cast)
45
+ return base$.pipe(castTimelineStream(cast));
46
+ else
47
+ return base$;
48
+ }
25
49
  }
@@ -137,14 +137,24 @@ export class AsyncEventStore extends EventModels {
137
137
  addSeenRelay(event, fromRelay);
138
138
  // Get the replaceable identifier
139
139
  const identifier = isReplaceable(event.kind) ? getReplaceableIdentifier(event) : undefined;
140
- // Don't insert the event if there is already a newer version
140
+ // Don't insert the event if there is already a winning version
141
+ // (NIP-01: newer created_at wins; on tie, lexicographically lower id wins).
141
142
  if (this.keepOldVersions === false && isReplaceable(event.kind)) {
142
143
  const existing = await this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
143
- // If there is already a newer version, copy cached symbols and return existing event
144
- if (existing && existing.length > 0 && existing[0].created_at >= event.created_at) {
145
- if (EventStore.copySymbolsToDuplicateEvent(event, existing[0]))
146
- await this.update(existing[0]);
147
- return existing[0];
144
+ // If the existing set has any event that beats the incoming one per
145
+ // NIP-01, the incoming event is rejected.
146
+ if (existing && existing.length > 0) {
147
+ let winner = existing[0];
148
+ for (const e of existing) {
149
+ if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
150
+ winner = e;
151
+ }
152
+ const incomingBeatsWinner = event.created_at > winner.created_at || (event.created_at === winner.created_at && event.id < winner.id);
153
+ if (!incomingBeatsWinner) {
154
+ if (EventStore.copySymbolsToDuplicateEvent(event, winner))
155
+ await this.update(winner);
156
+ return winner;
157
+ }
148
158
  }
149
159
  }
150
160
  // Verify event before inserting into the database
@@ -173,17 +183,24 @@ export class AsyncEventStore extends EventModels {
173
183
  if (EventStore.copySymbolsToDuplicateEvent(event, inserted))
174
184
  await this.update(inserted);
175
185
  }
176
- // remove all old version of the replaceable event
186
+ // remove all losing versions of the replaceable event
187
+ // (NIP-01: keep newest created_at; on tie, keep lowest id).
177
188
  if (this.keepOldVersions === false && isReplaceable(event.kind)) {
178
189
  const existing = await this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
179
190
  if (existing && existing.length > 0) {
180
- const older = Array.from(existing).filter((e) => e.created_at < event.created_at);
181
- for (const old of older)
191
+ // Find the NIP-01 winner across all stored versions.
192
+ let winner = existing[0];
193
+ for (const e of existing) {
194
+ if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
195
+ winner = e;
196
+ }
197
+ const losers = existing.filter((e) => e !== winner);
198
+ for (const old of losers)
182
199
  await this.remove(old);
183
- // return the newest version of the replaceable event
200
+ // return the winning version of the replaceable event
184
201
  // most of the time this will be === event, but not always
185
- if (existing.length !== older.length)
186
- return existing[0];
202
+ if (losers.length > 0)
203
+ return winner;
187
204
  }
188
205
  }
189
206
  // Add event to expiration manager if it has an expiration tag
@@ -161,14 +161,24 @@ export class EventStore extends EventModels {
161
161
  addSeenRelay(event, fromRelay);
162
162
  // Get the replaceable identifier
163
163
  const identifier = isReplaceable(event.kind) ? getReplaceableIdentifier(event) : undefined;
164
- // Don't insert the event if there is already a newer version
164
+ // Don't insert the event if there is already a winning version
165
+ // (NIP-01: newer created_at wins; on tie, lexicographically lower id wins).
165
166
  if (this.keepOldVersions === false && isReplaceable(event.kind)) {
166
167
  const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
167
- // If there is already a newer version, copy cached symbols and return existing event
168
- if (existing && existing.length > 0 && existing[0].created_at >= event.created_at) {
169
- if (EventStore.copySymbolsToDuplicateEvent(event, existing[0]))
170
- this.update(existing[0]);
171
- return existing[0];
168
+ // If the existing set has any event that beats the incoming one per
169
+ // NIP-01, the incoming event is rejected.
170
+ if (existing && existing.length > 0) {
171
+ let winner = existing[0];
172
+ for (const e of existing) {
173
+ if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
174
+ winner = e;
175
+ }
176
+ const incomingBeatsWinner = event.created_at > winner.created_at || (event.created_at === winner.created_at && event.id < winner.id);
177
+ if (!incomingBeatsWinner) {
178
+ if (EventStore.copySymbolsToDuplicateEvent(event, winner))
179
+ this.update(winner);
180
+ return winner;
181
+ }
172
182
  }
173
183
  }
174
184
  // Verify event before inserting into the database
@@ -197,17 +207,24 @@ export class EventStore extends EventModels {
197
207
  if (EventStore.copySymbolsToDuplicateEvent(event, inserted))
198
208
  this.update(inserted);
199
209
  }
200
- // remove all old version of the replaceable event
210
+ // remove all losing versions of the replaceable event
211
+ // (NIP-01: keep newest created_at; on tie, keep lowest id).
201
212
  if (this.keepOldVersions === false && isReplaceable(event.kind)) {
202
213
  const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
203
214
  if (existing && existing.length > 0) {
204
- const older = Array.from(existing).filter((e) => e.created_at < event.created_at);
205
- for (const old of older)
215
+ // Find the NIP-01 winner across all stored versions.
216
+ let winner = existing[0];
217
+ for (const e of existing) {
218
+ if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
219
+ winner = e;
220
+ }
221
+ const losers = existing.filter((e) => e !== winner);
222
+ for (const old of losers)
206
223
  this.remove(old);
207
- // return the newest version of the replaceable event
224
+ // return the winning version of the replaceable event
208
225
  // most of the time this will be === event, but not always
209
- if (existing.length !== older.length)
210
- return existing[0];
226
+ if (losers.length > 0)
227
+ return winner;
211
228
  }
212
229
  }
213
230
  // Add event to expiration manager if it has an expiration tag
@@ -39,6 +39,8 @@ export declare function isProfilePointer(pointer: any): pointer is ProfilePointe
39
39
  export declare function isEventPointer(pointer: any): pointer is EventPointer;
40
40
  /** Returns the stringified NIP-19 encoded naddr address pointer for an AddressPointer. */
41
41
  export declare function getReplaceableAddressFromPointer(pointer: AddressPointer): string;
42
+ /** Returns the replaceable coordinate for a replaceable event ( used for "a" tags to reference replaceable events ). */
43
+ export declare function getReplaceableAddressForEvent(event: NostrEvent): string | null;
42
44
  /** Returns an AddressPointer for a replaceable event. Returns null if the event is not addressable or replaceable. */
43
45
  export declare function getAddressPointerForEvent(event: NostrEvent, relays?: string[]): AddressPointer | null;
44
46
  /** Returns an EventPointer for an event */
@@ -204,6 +204,13 @@ export function isEventPointer(pointer) {
204
204
  export function getReplaceableAddressFromPointer(pointer) {
205
205
  return pointer.kind + ":" + pointer.pubkey + ":" + pointer.identifier;
206
206
  }
207
+ /** Returns the replaceable coordinate for a replaceable event ( used for "a" tags to reference replaceable events ). */
208
+ export function getReplaceableAddressForEvent(event) {
209
+ if (!isReplaceableKind(event.kind) && !isAddressableKind(event.kind))
210
+ return null;
211
+ const d = getReplaceableIdentifier(event);
212
+ return event.kind + ":" + event.pubkey + ":" + d;
213
+ }
207
214
  /** Returns an AddressPointer for a replaceable event. Returns null if the event is not addressable or replaceable. */
208
215
  export function getAddressPointerForEvent(event, relays) {
209
216
  if (!isAddressableKind(event.kind) && !isReplaceableKind(event.kind))
@@ -34,10 +34,10 @@ export const Tokens = {
34
34
  return Expressions.link;
35
35
  },
36
36
  get cashu() {
37
- return new RegExp(`(?<=^|\\s)${Expressions.cashu.source}`, "gi");
37
+ return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.cashu.source}`, "gi");
38
38
  },
39
39
  get nostrLink() {
40
- return new RegExp(`(?<=^|\\s)${Expressions.nostrLink.source}`, "gi");
40
+ return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.nostrLink.source}`, "gi");
41
41
  },
42
42
  get emoji() {
43
43
  return Expressions.emoji;
@@ -46,9 +46,9 @@ export const Tokens = {
46
46
  return Expressions.hashtag;
47
47
  },
48
48
  get lightning() {
49
- return new RegExp(`(?<=^|\\s)${Expressions.lightning.source}`, "gim");
49
+ return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.lightning.source}`, "gim");
50
50
  },
51
51
  get blossom() {
52
- return new RegExp(`(?<=^|\\s)${Expressions.blossom.source}`, "g");
52
+ return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.blossom.source}`, "g");
53
53
  },
54
54
  };
@@ -0,0 +1,8 @@
1
+ import { OperatorFunction } from "rxjs";
2
+ import type { CastConstructor, CastRefEventStore } from "../casts/cast.js";
3
+ import { EventCast } from "../casts/index.js";
4
+ import { NostrEvent } from "../helpers/event.js";
5
+ /** Casts an event to a specific type */
6
+ export declare function castEventStream<C extends EventCast>(cls: CastConstructor<C>, store?: CastRefEventStore): OperatorFunction<NostrEvent | undefined, C | undefined>;
7
+ /** Casts and array of events to an array of casted events and filters out undefined values */
8
+ export declare function castTimelineStream<C extends EventCast>(cls: CastConstructor<C>, store?: CastRefEventStore): OperatorFunction<NostrEvent[], C[]>;
@@ -0,0 +1,29 @@
1
+ import { map } from "rxjs";
2
+ import { castEvent } from "../casts/index.js";
3
+ import { defined } from "./defined.js";
4
+ /** Casts an event to a specific type */
5
+ export function castEventStream(cls, store) {
6
+ return (source) => source.pipe(map((event) => {
7
+ if (!event)
8
+ return undefined;
9
+ try {
10
+ return castEvent(event, cls, store);
11
+ }
12
+ catch { }
13
+ return undefined;
14
+ }));
15
+ }
16
+ /** Casts and array of events to an array of casted events and filters out undefined values */
17
+ export function castTimelineStream(cls, store) {
18
+ return (source) => source.pipe(map((events) => {
19
+ const castedEvents = [];
20
+ for (const event of events) {
21
+ try {
22
+ const casted = castEvent(event, cls, store);
23
+ castedEvents.push(casted);
24
+ }
25
+ catch { }
26
+ }
27
+ return castedEvents;
28
+ }), defined());
29
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "6.0.2",
3
+ "version": "6.1.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",