@fedify/fedify
Version:
An ActivityPub server framework
274 lines (273 loc) • 9.2 kB
JavaScript
import "@js-temporal/polyfill";
import "urlpattern-polyfill";
globalThis.addEventListener = () => {};
import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
import "../std__assert-BBjXFNOb.mjs";
import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
import { t as assert } from "../assert-OguE97r2.mjs";
import { getLogger } from "@logtape/logtape";
import { Router, RouterError, assertPath, isPath } from "@fedify/uri-template";
import { test } from "@fedify/fixture";
//#region src/federation/router.ts
const logger = getLogger([
"fedify",
"federation",
"router",
"deprecated"
]);
let deprecationWarned = false;
function warnDeprecated() {
if (deprecationWarned) return;
deprecationWarned = true;
logger.warn("The `Router` and `RouterError` classes from `@fedify/fedify` are deprecated. Please use `Router` from `@fedify/uri-template` instead.");
}
/**
* URL router and constructor based on URI Template
* ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
*
* @deprecated Import `Router` from `@fedify/uri-template` instead. This class
* remains only for compatibility with older Fedify code. The
* `@fedify/uri-template` router is the replacement implementation
* and should be used directly in new code.
*/
var Router$1 = class Router$1 {
#router;
/**
* Create a new {@link Router}.
* @param options Options for the router.
* @deprecated Use `new Router(options)` from `@fedify/uri-template`
* instead.
*/
constructor(options) {
this.#router = convertRouterError(() => new Router(options));
}
/**
* Whether to ignore trailing slashes when matching paths.
* @deprecated Use `Router` from `@fedify/uri-template` instead. This
* accessor forwards to the underlying `@fedify/uri-template`
* router so that post-construction mutation keeps working as
* in older Fedify code.
*/
get trailingSlashInsensitive() {
return this.#router.trailingSlashInsensitive;
}
set trailingSlashInsensitive(value) {
this.#router.trailingSlashInsensitive = value;
}
/**
* Clones this router.
* @deprecated Use `Router` from `@fedify/uri-template` instead.
*/
clone() {
return convertRouterError(() => {
const clone = new Router$1();
clone.#router = this.#router.clone();
return clone;
});
}
/**
* Checks if a path name exists in the router.
* @param name The name of the path.
* @returns `true` if the path name exists, otherwise `false`.
* @deprecated Use `Router` from `@fedify/uri-template` instead.
*/
has(name) {
return convertRouterError(() => this.#router.has(name));
}
/**
* Adds a new path rule to the router.
* @param template The path pattern.
* @param name The name of the path.
* @returns The names of the variables in the path pattern.
* @deprecated Use `Router` from `@fedify/uri-template` instead. In this
* compatibility class, `add()` both registers the route and
* returns the variables in the path pattern. In
* `@fedify/uri-template`, these two responsibilities are split:
* `router.add(template, name)` registers the route and returns
* `void`, while the pure static method
* `Router.variables(template)` returns the variable names. To
* migrate, call `Router.variables(template)` when variables are
* needed, then call `router.add(template, name)` to register the
* route.
*/
add(template, name) {
return convertRouterError(() => {
assertPath(template);
this.#router.add(template, name);
return Router.variables(template);
});
}
/**
* Resolves a path name and values from a URL, if any match.
* @param url The URL to resolve.
* @returns The name of the path and its values, if any match. Otherwise,
* `null`.
* @deprecated Use `Router` from `@fedify/uri-template` instead. Unlike the
* stricter `@fedify/uri-template` router, this compatibility
* method keeps the old Fedify 2.x contract of returning `null`
* (rather than throwing) for inputs that are not router paths.
*/
route(url) {
return convertRouterError(() => {
if (!isPath(url)) return null;
return this.#router.route(url);
});
}
/**
* Constructs a URL/path from a path name and values.
* @param name The name of the path.
* @param values The values to expand the path with.
* @returns The URL/path, if the name exists. Otherwise, `null`.
* @deprecated Use `Router` from `@fedify/uri-template` instead.
*/
build(name, values) {
return convertRouterError(() => this.#router.build(name, values));
}
};
/**
* An error thrown by the {@link Router}.
* @deprecated Import `RouterError` from `@fedify/uri-template` instead.
*/
var RouterError$1 = class extends RouterError {
/**
* Treats every `RouterError` from `@fedify/uri-template` as an instance of
* this deprecated class.
*
* @deprecated Import `RouterError` from `@fedify/uri-template` instead.
*/
static [Symbol.hasInstance](instance) {
return instance instanceof RouterError;
}
/**
* Create a new {@link RouterError}.
* @param message The error message.
* @deprecated Import `RouterError` from `@fedify/uri-template` instead.
*/
constructor(message) {
super(message);
warnDeprecated();
}
};
function convertRouterError(func) {
try {
warnDeprecated();
return func();
} catch (error) {
if (error instanceof RouterError) throw new RouterError$1(error.message);
throw error;
}
}
//#endregion
//#region src/federation/router.test.ts
function setUp(options = {}) {
const router = new Router$1(options);
router.add("/users/{name}", "user");
router.add("/users/{name}/posts/{postId}" + (options.trailingSlashInsensitive ? "/" : ""), "post");
return router;
}
test("Router.clone()", () => {
const original = setUp();
const clone = original.clone();
clone.add("/users/{name}/friends", "friends");
assert(clone.has("friends"));
assertEquals(clone.route("/users/alice/friends"), {
name: "friends",
template: "/users/{name}/friends",
values: { name: "alice" }
});
assertFalse(original.has("friends"));
assertEquals(original.route("/users/alice/friends"), null);
});
test("Router.add()", () => {
const router = new Router$1();
assertEquals(router.add("/users", "users"), /* @__PURE__ */ new Set());
assertEquals(router.add("/users/{name}", "user"), new Set(["name"]));
assertEquals(router.add("/users/{name}/posts/{postId}", "post"), new Set(["name", "postId"]));
assertThrows(() => router.add("foo", "name"), RouterError$1);
});
test("Router.route()", () => {
let router = setUp();
assertEquals(router.route("/users/alice"), {
name: "user",
template: "/users/{name}",
values: { name: "alice" }
});
assertEquals(router.route("/users/bob/"), null);
assertEquals(router.route("/users/alice/posts/123"), {
name: "post",
template: "/users/{name}/posts/{postId}",
values: {
name: "alice",
postId: "123"
}
});
assertEquals(router.route("/users/bob/posts/456/"), null);
router = setUp({ trailingSlashInsensitive: true });
assertEquals(router.route("/users/alice"), {
name: "user",
template: "/users/{name}",
values: { name: "alice" }
});
assertEquals(router.route("/users/bob/"), {
name: "user",
template: "/users/{name}",
values: { name: "bob" }
});
assertEquals(router.route("/users/alice/posts/123"), {
name: "post",
template: "/users/{name}/posts/{postId}/",
values: {
name: "alice",
postId: "123"
}
});
assertEquals(router.route("/users/bob/posts/456/"), {
name: "post",
template: "/users/{name}/posts/{postId}/",
values: {
name: "bob",
postId: "456"
}
});
});
test("Router.trailingSlashInsensitive (post-construction mutation)", () => {
const router = setUp();
assertFalse(router.trailingSlashInsensitive);
assertEquals(router.route("/users/bob/"), null);
router.trailingSlashInsensitive = true;
assert(router.trailingSlashInsensitive);
assertEquals(router.route("/users/bob/"), {
name: "user",
template: "/users/{name}",
values: { name: "bob" }
});
router.trailingSlashInsensitive = false;
assertFalse(router.trailingSlashInsensitive);
assertEquals(router.route("/users/bob/"), null);
});
test("Router.build()", () => {
const router = setUp();
assertEquals(router.build("user", { name: "alice" }), "/users/alice");
assertEquals(router.build("post", {
name: "alice",
postId: "123"
}), "/users/alice/posts/123");
});
test("Router.route() returns null for non-path inputs", () => {
const router = setUp();
assertEquals(router.route("https://example.com/users/alice"), null);
assertEquals(router.route("users/alice"), null);
assertEquals(router.route("not a path"), null);
assertEquals(router.route("/unknown"), null);
});
test("Compatibility between RouterErrors", () => {
const newError = new RouterError("boom");
assert(newError instanceof RouterError);
assert(newError instanceof RouterError$1);
const previousError = new RouterError$1("boom");
assert(previousError instanceof RouterError$1);
assert(previousError instanceof RouterError);
});
//#endregion
export {};