@fedify/nuxt 2.2.0-dev.898 → 2.2.0-dev.924
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.
- package/dist/logic-66Hndkgv.js +37 -0
- package/dist/logic-CVtLv4lJ.cjs +60 -0
- package/dist/mod.cjs +7 -2
- package/dist/mod.d.cts +2 -59068
- package/dist/mod.d.ts +2 -59068
- package/dist/mod.js +7 -2
- package/dist/runtime/server/middleware.cjs +24 -0
- package/dist/runtime/server/middleware.d.cts +7 -0
- package/dist/runtime/server/middleware.d.ts +7 -0
- package/dist/runtime/server/middleware.js +23 -0
- package/dist/runtime/server/plugin.cjs +18 -0
- package/dist/runtime/server/plugin.d.cts +14 -0
- package/dist/runtime/server/plugin.d.ts +15 -0
- package/dist/runtime/server/plugin.js +18 -0
- package/package.json +5 -5
- package/src/runtime/server/lib.ts +0 -4
- package/src/runtime/server/logic.test.ts +0 -50
- package/src/runtime/server/logic.ts +0 -60
- package/src/runtime/server/middleware.ts +0 -44
- package/src/runtime/server/plugin.test.ts +0 -118
- package/src/runtime/server/plugin.ts +0 -49
package/dist/mod.js
CHANGED
|
@@ -7,6 +7,9 @@ function resolveModulePath(modulePath, aliases, rootDir) {
|
|
|
7
7
|
if (resolved.startsWith("./") || resolved.startsWith("../")) return resolve(rootDir, resolved);
|
|
8
8
|
return resolved;
|
|
9
9
|
}
|
|
10
|
+
function resolveRuntimeServerPath(resolver, fileName) {
|
|
11
|
+
return resolver.resolve(`../dist/runtime/server/${fileName}`);
|
|
12
|
+
}
|
|
10
13
|
function buildContextFactoryResolver(contextDataFactoryModule) {
|
|
11
14
|
if (contextDataFactoryModule == null) return "const contextDataFactory = undefined;";
|
|
12
15
|
return `
|
|
@@ -42,10 +45,12 @@ const fedifyNuxtModule = defineNuxtModule({
|
|
|
42
45
|
const federationModule = resolveModulePath(options.federationModule, nuxt.options.alias, rootDir);
|
|
43
46
|
const contextDataFactoryModule = options.contextDataFactoryModule == null ? void 0 : resolveModulePath(options.contextDataFactoryModule, nuxt.options.alias, rootDir);
|
|
44
47
|
const middlewareFilename = "fedify-nuxt-options.mjs";
|
|
48
|
+
const middlewareModule = resolveRuntimeServerPath(resolver, "middleware.js");
|
|
49
|
+
const pluginModule = resolveRuntimeServerPath(resolver, "plugin.js");
|
|
45
50
|
addServerTemplate({
|
|
46
51
|
filename: middlewareFilename,
|
|
47
52
|
getContents: () => {
|
|
48
|
-
const imports = [`import * as federationModule from ${JSON.stringify(federationModule)};`, `import { createFedifyMiddleware } from ${JSON.stringify(
|
|
53
|
+
const imports = [`import * as federationModule from ${JSON.stringify(federationModule)};`, `import { createFedifyMiddleware } from ${JSON.stringify(middlewareModule)};`];
|
|
49
54
|
if (contextDataFactoryModule != null) imports.push(`import * as contextFactoryModule from ${JSON.stringify(contextDataFactoryModule)};`);
|
|
50
55
|
return [
|
|
51
56
|
...imports,
|
|
@@ -61,7 +66,7 @@ const fedifyNuxtModule = defineNuxtModule({
|
|
|
61
66
|
middleware: true,
|
|
62
67
|
handler: middlewareFilename
|
|
63
68
|
});
|
|
64
|
-
addServerPlugin(
|
|
69
|
+
addServerPlugin(pluginModule);
|
|
65
70
|
}
|
|
66
71
|
});
|
|
67
72
|
//#endregion
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_logic = require("../../logic-CVtLv4lJ.cjs");
|
|
3
|
+
let h3 = require("h3");
|
|
4
|
+
//#region src/runtime/server/middleware.ts
|
|
5
|
+
function assertFederation(federation) {
|
|
6
|
+
const candidate = federation;
|
|
7
|
+
if (candidate == null || typeof candidate.fetch !== "function") throw new TypeError("@fedify/nuxt: Federation instance is missing. Export default Federation (or named 'federation') from the configured module.");
|
|
8
|
+
}
|
|
9
|
+
function createFedifyMiddleware(federation, contextDataFactory) {
|
|
10
|
+
assertFederation(federation);
|
|
11
|
+
return (0, h3.defineEventHandler)(async (event) => {
|
|
12
|
+
const request = (0, h3.toWebRequest)(event);
|
|
13
|
+
const contextData = typeof contextDataFactory === "function" ? await contextDataFactory(event, request) : void 0;
|
|
14
|
+
const result = await require_logic.fetchWithFedify(federation.fetch.bind(federation), request, contextData);
|
|
15
|
+
if (result.kind === "not-found") return;
|
|
16
|
+
if (result.kind === "not-acceptable") {
|
|
17
|
+
event.context[require_logic.DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY] = true;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
return result.response;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
exports.createFedifyMiddleware = createFedifyMiddleware;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as _$h3 from "h3";
|
|
2
|
+
import { H3Event } from "h3";
|
|
3
|
+
|
|
4
|
+
//#region src/runtime/server/middleware.d.ts
|
|
5
|
+
declare function createFedifyMiddleware(federation: unknown, contextDataFactory?: (event: H3Event, request: Request) => unknown): _$h3.EventHandler<_$h3.EventHandlerRequest, Promise<Response>>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { createFedifyMiddleware };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as _$h3 from "h3";
|
|
2
|
+
import { H3Event } from "h3";
|
|
3
|
+
|
|
4
|
+
//#region src/runtime/server/middleware.d.ts
|
|
5
|
+
declare function createFedifyMiddleware(federation: unknown, contextDataFactory?: (event: H3Event, request: Request) => unknown): _$h3.EventHandler<_$h3.EventHandlerRequest, Promise<Response>>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { createFedifyMiddleware };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { r as DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY, t as fetchWithFedify } from "../../logic-66Hndkgv.js";
|
|
2
|
+
import { defineEventHandler, toWebRequest } from "h3";
|
|
3
|
+
//#region src/runtime/server/middleware.ts
|
|
4
|
+
function assertFederation(federation) {
|
|
5
|
+
const candidate = federation;
|
|
6
|
+
if (candidate == null || typeof candidate.fetch !== "function") throw new TypeError("@fedify/nuxt: Federation instance is missing. Export default Federation (or named 'federation') from the configured module.");
|
|
7
|
+
}
|
|
8
|
+
function createFedifyMiddleware(federation, contextDataFactory) {
|
|
9
|
+
assertFederation(federation);
|
|
10
|
+
return defineEventHandler(async (event) => {
|
|
11
|
+
const request = toWebRequest(event);
|
|
12
|
+
const contextData = typeof contextDataFactory === "function" ? await contextDataFactory(event, request) : void 0;
|
|
13
|
+
const result = await fetchWithFedify(federation.fetch.bind(federation), request, contextData);
|
|
14
|
+
if (result.kind === "not-found") return;
|
|
15
|
+
if (result.kind === "not-acceptable") {
|
|
16
|
+
event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY] = true;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return result.response;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { createFedifyMiddleware };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const require_logic = require("../../logic-CVtLv4lJ.cjs");
|
|
2
|
+
let h3 = require("h3");
|
|
3
|
+
//#region src/runtime/server/plugin.ts
|
|
4
|
+
const fedifyPlugin = (nitroApp) => {
|
|
5
|
+
nitroApp.hooks.hook("beforeResponse", (event, payload) => {
|
|
6
|
+
const deferred = event.context[require_logic.DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY] === true;
|
|
7
|
+
delete event.context[require_logic.DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY];
|
|
8
|
+
const negotiatedResponse = require_logic.resolveDeferredNotAcceptable(deferred, (0, h3.getResponseStatus)(event), event.context.matchedRoute != null);
|
|
9
|
+
if (negotiatedResponse == null) return;
|
|
10
|
+
(0, h3.setResponseStatus)(event, negotiatedResponse.status);
|
|
11
|
+
negotiatedResponse.headers.forEach((value, key) => {
|
|
12
|
+
(0, h3.setResponseHeader)(event, key, value);
|
|
13
|
+
});
|
|
14
|
+
payload.body = require_logic.NOT_ACCEPTABLE_BODY;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
module.exports = fedifyPlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { H3Event } from "h3";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/server/plugin.d.ts
|
|
4
|
+
interface ResponsePayload {
|
|
5
|
+
body?: unknown;
|
|
6
|
+
}
|
|
7
|
+
interface MinimalNitroApp {
|
|
8
|
+
hooks: {
|
|
9
|
+
hook(name: "beforeResponse", callback: (event: H3Event, payload: ResponsePayload) => void): void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
type NitroAppPlugin = (nitroApp: MinimalNitroApp) => void;
|
|
13
|
+
declare const fedifyPlugin: NitroAppPlugin;
|
|
14
|
+
export = fedifyPlugin;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { H3Event } from "h3";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/server/plugin.d.ts
|
|
4
|
+
interface ResponsePayload {
|
|
5
|
+
body?: unknown;
|
|
6
|
+
}
|
|
7
|
+
interface MinimalNitroApp {
|
|
8
|
+
hooks: {
|
|
9
|
+
hook(name: "beforeResponse", callback: (event: H3Event, payload: ResponsePayload) => void): void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
type NitroAppPlugin = (nitroApp: MinimalNitroApp) => void;
|
|
13
|
+
declare const fedifyPlugin: NitroAppPlugin;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { fedifyPlugin as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { i as NOT_ACCEPTABLE_BODY, n as resolveDeferredNotAcceptable, r as DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY } from "../../logic-66Hndkgv.js";
|
|
2
|
+
import { getResponseStatus, setResponseHeader, setResponseStatus } from "h3";
|
|
3
|
+
//#region src/runtime/server/plugin.ts
|
|
4
|
+
const fedifyPlugin = (nitroApp) => {
|
|
5
|
+
nitroApp.hooks.hook("beforeResponse", (event, payload) => {
|
|
6
|
+
const deferred = event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY] === true;
|
|
7
|
+
delete event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY];
|
|
8
|
+
const negotiatedResponse = resolveDeferredNotAcceptable(deferred, getResponseStatus(event), event.context.matchedRoute != null);
|
|
9
|
+
if (negotiatedResponse == null) return;
|
|
10
|
+
setResponseStatus(event, negotiatedResponse.status);
|
|
11
|
+
negotiatedResponse.headers.forEach((value, key) => {
|
|
12
|
+
setResponseHeader(event, key, value);
|
|
13
|
+
});
|
|
14
|
+
payload.body = NOT_ACCEPTABLE_BODY;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { fedifyPlugin as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/nuxt",
|
|
3
|
-
"version": "2.2.0-dev.
|
|
3
|
+
"version": "2.2.0-dev.924+c82ee90a",
|
|
4
4
|
"description": "Integrate Fedify with Nuxt",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Fedify",
|
|
@@ -46,18 +46,17 @@
|
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
48
48
|
"dist/",
|
|
49
|
-
"src/runtime/",
|
|
50
49
|
"package.json"
|
|
51
50
|
],
|
|
52
51
|
"peerDependencies": {
|
|
53
|
-
"@nuxt/kit": "^4.4.
|
|
52
|
+
"@nuxt/kit": "^4.4.2",
|
|
53
|
+
"@nuxt/schema": "^4.4.2",
|
|
54
54
|
"h3": "^1.15.0",
|
|
55
55
|
"nuxt": "^4.4.2",
|
|
56
|
-
"@fedify/fedify": "^2.2.0-dev.
|
|
56
|
+
"@fedify/fedify": "^2.2.0-dev.924+c82ee90a"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "^22.17.0",
|
|
60
|
-
"@nuxt/schema": "^4.4.0",
|
|
61
60
|
"tsdown": "^0.21.6",
|
|
62
61
|
"typescript": "^5.9.2",
|
|
63
62
|
"@fedify/fixture": "^2.0.0"
|
|
@@ -66,6 +65,7 @@
|
|
|
66
65
|
"build:self": "tsdown",
|
|
67
66
|
"build": "pnpm --filter @fedify/nuxt... run build:self",
|
|
68
67
|
"prepublish": "pnpm build",
|
|
68
|
+
"pretest": "pnpm build:self",
|
|
69
69
|
"test": "node --experimental-transform-types --test"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { test } from "@fedify/fixture";
|
|
2
|
-
import { equal, ok, strictEqual } from "node:assert/strict";
|
|
3
|
-
import { fetchWithFedify, resolveDeferredNotAcceptable } from "./logic.ts";
|
|
4
|
-
|
|
5
|
-
test(
|
|
6
|
-
"genuine handler 406 must be classified as handled",
|
|
7
|
-
async () => {
|
|
8
|
-
const handlerBody = JSON.stringify({ error: "custom reason" });
|
|
9
|
-
const handlerResponse = new Response(handlerBody, {
|
|
10
|
-
status: 406,
|
|
11
|
-
headers: { "Content-Type": "application/json" },
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
const result = await fetchWithFedify(
|
|
15
|
-
() => Promise.resolve(handlerResponse),
|
|
16
|
-
new Request("https://example.com/inbox"),
|
|
17
|
-
undefined,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
equal(result.kind, "handled");
|
|
21
|
-
if (result.kind === "handled") {
|
|
22
|
-
strictEqual(result.response, handlerResponse);
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
test(
|
|
28
|
-
"framework intentional 404 on shared route must not become 406",
|
|
29
|
-
() => {
|
|
30
|
-
// When a route handler ran (routeHandled=true), preserve the
|
|
31
|
-
// framework's 404 instead of rewriting it to 406.
|
|
32
|
-
const result = resolveDeferredNotAcceptable(true, 404, true);
|
|
33
|
-
equal(
|
|
34
|
-
result,
|
|
35
|
-
undefined,
|
|
36
|
-
"should preserve framework 404 when route was handled",
|
|
37
|
-
);
|
|
38
|
-
},
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
test(
|
|
42
|
-
"deferred 406 fires when no route handler matched",
|
|
43
|
-
() => {
|
|
44
|
-
// When no route handler matched (routeHandled=false), the 404
|
|
45
|
-
// is a genuine route miss and should be converted to 406.
|
|
46
|
-
const result = resolveDeferredNotAcceptable(true, 404, false);
|
|
47
|
-
ok(result, "should return 406 when no route handled the request");
|
|
48
|
-
equal(result!.status, 406);
|
|
49
|
-
},
|
|
50
|
-
);
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { FederationFetchOptions } from "@fedify/fedify/federation";
|
|
2
|
-
import { NOT_ACCEPTABLE_BODY } from "./lib.ts";
|
|
3
|
-
|
|
4
|
-
export { DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY } from "./lib.ts";
|
|
5
|
-
|
|
6
|
-
const DUMMY_NOT_FOUND_RESPONSE = new Response("", { status: 404 });
|
|
7
|
-
|
|
8
|
-
const createNotAcceptableResponse = () =>
|
|
9
|
-
new Response(NOT_ACCEPTABLE_BODY, {
|
|
10
|
-
status: 406,
|
|
11
|
-
headers: {
|
|
12
|
-
"Content-Type": "text/plain",
|
|
13
|
-
Vary: "Accept",
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export type FetchResult =
|
|
18
|
-
| { kind: "handled"; response: Response }
|
|
19
|
-
| { kind: "not-found" }
|
|
20
|
-
| { kind: "not-acceptable" };
|
|
21
|
-
|
|
22
|
-
export async function fetchWithFedify<TContextData = unknown>(
|
|
23
|
-
fetcher: (
|
|
24
|
-
request: Request,
|
|
25
|
-
options: FederationFetchOptions<TContextData>,
|
|
26
|
-
) => Promise<Response>,
|
|
27
|
-
request: Request,
|
|
28
|
-
contextData: TContextData,
|
|
29
|
-
): Promise<FetchResult> {
|
|
30
|
-
let notAcceptableResponse: Response | null = null;
|
|
31
|
-
|
|
32
|
-
const response = await fetcher(request, {
|
|
33
|
-
contextData,
|
|
34
|
-
onNotFound: () => DUMMY_NOT_FOUND_RESPONSE,
|
|
35
|
-
onNotAcceptable: () => {
|
|
36
|
-
notAcceptableResponse = createNotAcceptableResponse();
|
|
37
|
-
return notAcceptableResponse;
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
if (response === DUMMY_NOT_FOUND_RESPONSE) {
|
|
42
|
-
return { kind: "not-found" };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (notAcceptableResponse != null && response === notAcceptableResponse) {
|
|
46
|
-
return { kind: "not-acceptable" };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return { kind: "handled", response };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function resolveDeferredNotAcceptable(
|
|
53
|
-
isDeferred: boolean,
|
|
54
|
-
frameworkStatus: number,
|
|
55
|
-
routeHandled?: boolean,
|
|
56
|
-
): Response | undefined {
|
|
57
|
-
if (!isDeferred || frameworkStatus !== 404) return undefined;
|
|
58
|
-
if (routeHandled) return undefined;
|
|
59
|
-
return createNotAcceptableResponse();
|
|
60
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Federation } from "@fedify/fedify/federation";
|
|
2
|
-
import { defineEventHandler, type H3Event, toWebRequest } from "h3";
|
|
3
|
-
import { DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY } from "./lib.ts";
|
|
4
|
-
import { fetchWithFedify } from "./logic.ts";
|
|
5
|
-
|
|
6
|
-
function assertFederation(
|
|
7
|
-
federation: unknown,
|
|
8
|
-
): asserts federation is Federation<unknown> {
|
|
9
|
-
const candidate = federation as { fetch?: unknown } | null | undefined;
|
|
10
|
-
if (candidate == null || typeof candidate.fetch !== "function") {
|
|
11
|
-
throw new TypeError(
|
|
12
|
-
"@fedify/nuxt: Federation instance is missing. " +
|
|
13
|
-
"Export default Federation (or named 'federation') from the configured module.",
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function createFedifyMiddleware(
|
|
19
|
-
federation: unknown,
|
|
20
|
-
contextDataFactory?: (event: H3Event, request: Request) => unknown,
|
|
21
|
-
) {
|
|
22
|
-
assertFederation(federation);
|
|
23
|
-
|
|
24
|
-
return defineEventHandler(async (event) => {
|
|
25
|
-
const request = toWebRequest(event);
|
|
26
|
-
const contextData = typeof contextDataFactory === "function"
|
|
27
|
-
? await contextDataFactory(event, request)
|
|
28
|
-
: undefined;
|
|
29
|
-
|
|
30
|
-
const result = await fetchWithFedify(
|
|
31
|
-
federation.fetch.bind(federation),
|
|
32
|
-
request,
|
|
33
|
-
contextData,
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
if (result.kind === "not-found") return;
|
|
37
|
-
if (result.kind === "not-acceptable") {
|
|
38
|
-
event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY] = true;
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return result.response;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { test } from "@fedify/fixture";
|
|
2
|
-
import type { H3Event } from "h3";
|
|
3
|
-
import { equal, ok } from "node:assert/strict";
|
|
4
|
-
import {
|
|
5
|
-
DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY,
|
|
6
|
-
NOT_ACCEPTABLE_BODY,
|
|
7
|
-
} from "./lib.ts";
|
|
8
|
-
import fedifyPlugin from "./plugin.ts";
|
|
9
|
-
|
|
10
|
-
interface MockResponse {
|
|
11
|
-
statusCode: number;
|
|
12
|
-
statusMessage?: string;
|
|
13
|
-
setHeader(name: string, value: string): void;
|
|
14
|
-
getHeader(name: string): string | undefined;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function createMockResponse(statusCode: number): MockResponse {
|
|
18
|
-
const headers = new Map<string, string>();
|
|
19
|
-
return {
|
|
20
|
-
statusCode,
|
|
21
|
-
setHeader(name: string, value: string) {
|
|
22
|
-
headers.set(name.toLowerCase(), value);
|
|
23
|
-
},
|
|
24
|
-
getHeader(name: string) {
|
|
25
|
-
return headers.get(name.toLowerCase());
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function registerBeforeResponseHook() {
|
|
31
|
-
let callback:
|
|
32
|
-
| ((event: H3Event, payload: { body?: unknown }) => void)
|
|
33
|
-
| undefined;
|
|
34
|
-
|
|
35
|
-
fedifyPlugin({
|
|
36
|
-
hooks: {
|
|
37
|
-
hook(name, registeredCallback) {
|
|
38
|
-
equal(name, "beforeResponse");
|
|
39
|
-
callback = registeredCallback;
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
ok(callback, "beforeResponse hook should be registered");
|
|
45
|
-
return callback;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
test(
|
|
49
|
-
"plugin rewrites deferred 404 without matched route to 406",
|
|
50
|
-
() => {
|
|
51
|
-
const beforeResponse = registerBeforeResponseHook();
|
|
52
|
-
const response = createMockResponse(404);
|
|
53
|
-
const payload = { body: "original body" };
|
|
54
|
-
const event = {
|
|
55
|
-
context: {
|
|
56
|
-
[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY]: true,
|
|
57
|
-
},
|
|
58
|
-
node: { res: response },
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
beforeResponse(event as unknown as H3Event, payload);
|
|
62
|
-
|
|
63
|
-
equal(response.statusCode, 406);
|
|
64
|
-
equal(response.getHeader("content-type"), "text/plain");
|
|
65
|
-
equal(response.getHeader("vary"), "Accept");
|
|
66
|
-
equal(payload.body, NOT_ACCEPTABLE_BODY);
|
|
67
|
-
equal(
|
|
68
|
-
event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY],
|
|
69
|
-
undefined,
|
|
70
|
-
);
|
|
71
|
-
},
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
test(
|
|
75
|
-
"plugin ignores 404 when deferred flag is absent",
|
|
76
|
-
() => {
|
|
77
|
-
const beforeResponse = registerBeforeResponseHook();
|
|
78
|
-
const response = createMockResponse(404);
|
|
79
|
-
const payload = { body: "regular 404" };
|
|
80
|
-
const event: H3Event = {
|
|
81
|
-
context: {},
|
|
82
|
-
node: { res: response },
|
|
83
|
-
} as unknown as H3Event;
|
|
84
|
-
|
|
85
|
-
beforeResponse(event, payload);
|
|
86
|
-
|
|
87
|
-
equal(response.statusCode, 404);
|
|
88
|
-
equal(response.getHeader("content-type"), undefined);
|
|
89
|
-
equal(payload.body, "regular 404");
|
|
90
|
-
},
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
test(
|
|
94
|
-
"plugin preserves shared-route 404 when Nuxt matched the route",
|
|
95
|
-
() => {
|
|
96
|
-
const beforeResponse = registerBeforeResponseHook();
|
|
97
|
-
const response = createMockResponse(404);
|
|
98
|
-
const payload = { body: "missing actor page" };
|
|
99
|
-
const event = {
|
|
100
|
-
context: {
|
|
101
|
-
[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY]: true,
|
|
102
|
-
matchedRoute: {},
|
|
103
|
-
},
|
|
104
|
-
node: { res: response },
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
beforeResponse(event as unknown as H3Event, payload);
|
|
108
|
-
|
|
109
|
-
equal(response.statusCode, 404);
|
|
110
|
-
equal(response.getHeader("content-type"), undefined);
|
|
111
|
-
equal(response.getHeader("vary"), undefined);
|
|
112
|
-
equal(payload.body, "missing actor page");
|
|
113
|
-
equal(
|
|
114
|
-
event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY],
|
|
115
|
-
undefined,
|
|
116
|
-
);
|
|
117
|
-
},
|
|
118
|
-
);
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { H3Event } from "h3";
|
|
2
|
-
import { getResponseStatus, setResponseHeader, setResponseStatus } from "h3";
|
|
3
|
-
import {
|
|
4
|
-
DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY,
|
|
5
|
-
NOT_ACCEPTABLE_BODY,
|
|
6
|
-
} from "./lib.ts";
|
|
7
|
-
import { resolveDeferredNotAcceptable } from "./logic.ts";
|
|
8
|
-
|
|
9
|
-
interface ResponsePayload {
|
|
10
|
-
body?: unknown;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface MinimalNitroApp {
|
|
14
|
-
hooks: {
|
|
15
|
-
hook(
|
|
16
|
-
name: "beforeResponse",
|
|
17
|
-
callback: (event: H3Event, payload: ResponsePayload) => void,
|
|
18
|
-
): void;
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type NitroAppPlugin = (nitroApp: MinimalNitroApp) => void;
|
|
23
|
-
|
|
24
|
-
const fedifyPlugin: NitroAppPlugin = (nitroApp: MinimalNitroApp) => {
|
|
25
|
-
nitroApp.hooks.hook(
|
|
26
|
-
"beforeResponse",
|
|
27
|
-
(event: H3Event, payload: ResponsePayload) => {
|
|
28
|
-
const deferred =
|
|
29
|
-
event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY] === true;
|
|
30
|
-
delete event.context[DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY];
|
|
31
|
-
|
|
32
|
-
const negotiatedResponse = resolveDeferredNotAcceptable(
|
|
33
|
-
deferred,
|
|
34
|
-
getResponseStatus(event),
|
|
35
|
-
event.context.matchedRoute != null,
|
|
36
|
-
);
|
|
37
|
-
if (negotiatedResponse == null) return;
|
|
38
|
-
|
|
39
|
-
setResponseStatus(event, negotiatedResponse.status);
|
|
40
|
-
negotiatedResponse.headers.forEach((value: string, key: string) => {
|
|
41
|
-
setResponseHeader(event, key, value);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
payload.body = NOT_ACCEPTABLE_BODY;
|
|
45
|
-
},
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export default fedifyPlugin;
|