Merge branch 'acct-parse-url' into lookup-api

This commit is contained in:
tamaina 2025-08-29 16:50:35 +09:00
commit 515e24bf7d
3 changed files with 28 additions and 4 deletions

View File

@ -28,7 +28,8 @@ declare namespace acct {
parseUrl, parseUrl,
parseAcctOrUrl, parseAcctOrUrl,
toString_2 as toString, toString_2 as toString,
Acct Acct,
UrlIsNotAcctLikeError
} }
} }
export { acct } export { acct }
@ -3640,6 +3641,11 @@ type TestResponse = operations['test']['responses']['200']['content']['applicati
// @public (undocumented) // @public (undocumented)
function toString_2(acct: Acct): string; function toString_2(acct: Acct): string;
// @public (undocumented)
class UrlIsNotAcctLikeError extends Error {
constructor();
}
// @public (undocumented) // @public (undocumented)
type User = components['schemas']['User']; type User = components['schemas']['User'];

View File

@ -27,15 +27,25 @@ export function parse(acct: string): Acct {
return { username: split[0], host: split[1] || null }; return { username: split[0], host: split[1] || null };
} }
export class UrlIsNotAcctLikeError extends Error {
constructor() {
super('This url is not acct like.');
}
}
export function parseUrl(str: string): Acct { export function parseUrl(str: string): Acct {
const url = new URL(str); const url = new URL(str);
if (url.hash.length > 0) throw new UrlIsNotAcctLikeError();
if (url.search.length > 0) throw new UrlIsNotAcctLikeError();
const splited = url.pathname.split('/'); const splited = url.pathname.split('/');
let path = splited.pop(); let path = splited.pop();
if (path === '') path = splited.pop(); // If the last segment is empty due to a trailing '/', use the previous segment if (path === '') path = splited.pop(); // If the last segment is empty due to a trailing '/', use the previous segment
if (!path) throw new Error('This url is not acct like.'); if (!path) throw new UrlIsNotAcctLikeError();
if (!path.startsWith('@')) throw new Error('This url is not acct like.'); if (!path.startsWith('@')) throw new UrlIsNotAcctLikeError();
if (path.length <= 1) throw new Error('This url is not acct like.'); if (path.length <= 1) throw new UrlIsNotAcctLikeError();
const split = path.split('@', 3); // ['', 'username', 'other.example.com'] const split = path.split('@', 3); // ['', 'username', 'other.example.com']

View File

@ -59,6 +59,14 @@ function testParseUrl(fn: (acct: string) => acct.Acct) {
it('throws url have @username path but ended with sub directory', () => { it('throws url have @username path but ended with sub directory', () => {
expect(() => fn('https://example.com/@alice/subdir')).toThrowError(); expect(() => fn('https://example.com/@alice/subdir')).toThrowError();
}); });
it('throws url with search params', () => {
expect(() => fn('https://example.com/@alice?foo=bar')).toThrowError();
});
it('throws url with hash', () => {
expect(() => fn('https://example.com/@alice#fragment')).toThrowError();
});
} }
describe('acct.parse', () => { describe('acct.parse', () => {