applesauce-core
Advanced tools
Comparing version
@@ -0,1 +1,5 @@ | ||
/** A tag with at least two indexes, the first being the name, the second the value */ | ||
export type NameValueTag<Name extends string = string> = [Name, string, ...string[]]; | ||
/** Tests if a tag has at least two indexes, and optionally the value of the first */ | ||
export declare function isNameValueTag<Name extends string>(tag: string[], name?: Name): tag is NameValueTag<Name>; | ||
/** Checks if tag is an "e" tag and has at least one value */ | ||
@@ -2,0 +6,0 @@ export declare function isETag(tag: string[]): tag is ["e", string, ...string[]]; |
@@ -0,24 +1,28 @@ | ||
/** Tests if a tag has at least two indexes, and optionally the value of the first */ | ||
export function isNameValueTag(tag, name) { | ||
return tag[0] !== undefined && tag[1] !== undefined && (name ? tag[0] === name : true); | ||
} | ||
/** Checks if tag is an "e" tag and has at least one value */ | ||
export function isETag(tag) { | ||
return tag[0] === "e" && tag[1] !== undefined; | ||
return isNameValueTag(tag, "e"); | ||
} | ||
/** Checks if tag is an "p" tag and has at least one value */ | ||
export function isPTag(tag) { | ||
return tag[0] === "p" && tag[1] !== undefined; | ||
return isNameValueTag(tag, "p"); | ||
} | ||
/** Checks if tag is an "r" tag and has at least one value */ | ||
export function isRTag(tag) { | ||
return tag[0] === "r" && tag[1] !== undefined; | ||
return isNameValueTag(tag, "r"); | ||
} | ||
/** Checks if tag is an "d" tag and has at least one value */ | ||
export function isDTag(tag) { | ||
return tag[0] === "d" && tag[1] !== undefined; | ||
return isNameValueTag(tag, "d"); | ||
} | ||
/** Checks if tag is an "a" tag and has at least one value */ | ||
export function isATag(tag) { | ||
return tag[0] === "a" && tag[1] !== undefined; | ||
return isNameValueTag(tag, "a"); | ||
} | ||
/** Checks if tag is an "a" tag and has at least one value */ | ||
export function isTTag(tag) { | ||
return tag[0] === "a" && tag[1] !== undefined; | ||
return isNameValueTag(tag, "t"); | ||
} | ||
@@ -25,0 +29,0 @@ /** Filter and transform tags */ |
import { describe, expect, it } from "vitest"; | ||
import { isATag, processTags } from "./tags.js"; | ||
import { isATag, isNameValueTag, processTags } from "./tags.js"; | ||
import { getAddressPointerFromATag } from "./pointers.js"; | ||
describe("tag helpers", () => { | ||
describe("processTags", () => { | ||
it("should filter out errors", () => { | ||
expect(processTags([["a", "bad coordinate"], ["e"], ["a", "30000:pubkey:list"]], getAddressPointerFromATag)).toEqual([{ identifier: "list", kind: 30000, pubkey: "pubkey" }]); | ||
}); | ||
it("should filter out undefined", () => { | ||
expect(processTags([["a", "bad coordinate"], ["e"], ["a", "30000:pubkey:list"]], (tag) => isATag(tag) ? tag : undefined)).toEqual([ | ||
["a", "bad coordinate"], | ||
["a", "30000:pubkey:list"], | ||
]); | ||
}); | ||
describe("isNameValueTag", () => { | ||
it("should return true if tag has at least two indexes", () => { | ||
expect(isNameValueTag(["a", "30000:pubkey:list"])).toBe(true); | ||
expect(isNameValueTag(["title", "article", "other-value"])).toBe(true); | ||
}); | ||
it("should ignore tags without values", () => { | ||
expect(isNameValueTag(["a"])).toBe(false); | ||
expect(isNameValueTag(["title"])).toBe(false); | ||
}); | ||
}); | ||
describe("processTags", () => { | ||
it("should filter out errors", () => { | ||
expect(processTags([["a", "bad coordinate"], ["e"], ["a", "30000:pubkey:list"]], getAddressPointerFromATag)).toEqual([{ identifier: "list", kind: 30000, pubkey: "pubkey" }]); | ||
}); | ||
it("should filter out undefined", () => { | ||
expect(processTags([["a", "bad coordinate"], ["e"], ["a", "30000:pubkey:list"]], (tag) => isATag(tag) ? tag : undefined)).toEqual([ | ||
["a", "bad coordinate"], | ||
["a", "30000:pubkey:list"], | ||
]); | ||
}); | ||
}); |
@@ -15,1 +15,8 @@ export declare const convertToUrl: (url: string | URL) => URL; | ||
export declare function isAudioURL(url: string | URL): boolean; | ||
/** Tests if two URLs are the same */ | ||
export declare function isSameURL(a: string | URL, b: string | URL): boolean; | ||
/** | ||
* Normalizes a string into a relay URL | ||
* Does not remove the trailing slash | ||
*/ | ||
export declare function normalizeURL(url: string | URL): URL; |
@@ -31,1 +31,31 @@ export const convertToUrl = (url) => (url instanceof URL ? url : new URL(url)); | ||
} | ||
/** Tests if two URLs are the same */ | ||
export function isSameURL(a, b) { | ||
try { | ||
a = normalizeURL(a).toString(); | ||
b = normalizeURL(b).toString(); | ||
return a === b; | ||
} | ||
catch (error) { | ||
return false; | ||
} | ||
} | ||
/** | ||
* Normalizes a string into a relay URL | ||
* Does not remove the trailing slash | ||
*/ | ||
export function normalizeURL(url) { | ||
if (typeof url === "string" && url.indexOf("://") === -1) | ||
url = "wss://" + url; | ||
let p = new URL(url); | ||
// remove any double slashes | ||
p.pathname = p.pathname.replace(/\/+/g, "/"); | ||
// drop the port if its not needed | ||
if ((p.port === "80" && p.protocol === "ws:") || (p.port === "443" && p.protocol === "wss:")) | ||
p.port = ""; | ||
// sort the query params | ||
p.searchParams.sort(); | ||
// remove the hash | ||
p.hash = ""; | ||
return p; | ||
} |
{ | ||
"name": "applesauce-core", | ||
"version": "0.0.0-next-20250210210633", | ||
"version": "0.0.0-next-20250211164604", | ||
"description": "", | ||
@@ -78,3 +78,3 @@ "type": "module", | ||
"typescript": "^5.6.3", | ||
"vitest": "^2.1.8" | ||
"vitest": "^3.0.5" | ||
}, | ||
@@ -81,0 +81,0 @@ "funding": { |
181245
1.11%4444
1.21%