Skip to content

Commit 1a0c873

Browse files
committed
Add @fedify/nuxt to @fedify/init with GPT-5.4
1 parent 90757cb commit 1a0c873

9 files changed

Lines changed: 179 additions & 0 deletions

File tree

packages/init/src/const.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const WEB_FRAMEWORK = [
1313
"elysia",
1414
"astro",
1515
"express",
16+
"nuxt",
1617
"solidstart",
1718
] as const;
1819
/** All supported message queue backend identifiers. */

packages/init/src/json/deps.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"npm:@dotenvx/dotenvx": "^1.59.1",
1010
"npm:@elysiajs/node": "^1.4.5",
1111
"npm:@hono/node-server": "^1.19.12",
12+
"npm:@nuxt/kit": "^4.4.2",
1213
"npm:@sinclair/typebox": "^0.34.49",
1314
"npm:@solidjs/router": "^0.16.1",
1415
"npm:@solidjs/start": "^1.3.2",
@@ -21,7 +22,10 @@
2122
"npm:elysia": "^1.4.28",
2223
"npm:eslint": "^9.0.0",
2324
"npm:express": "^5.2.1",
25+
"npm:h3": "^1.15.0",
2426
"npm:hono": "^4.12.9",
27+
"npm:nuxi": "^3.34.0",
28+
"npm:nuxt": "^4.4.2",
2529
"npm:openapi-types": "^12.1.3",
2630
"npm:solid-js": "^1.9.12",
2731
"npm:tsx": "^4.21.0",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// https://nuxt.com/docs/api/configuration/nuxt-config
2+
export default defineNuxtConfig({
3+
ssr: false,
4+
devtools: { enabled: true },
5+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createFederation } from "@fedify/fedify";
2+
import { MemoryKvStore } from "@fedify/fedify";
3+
import { Person } from "@fedify/vocab";
4+
import { getLogger } from "@logtape/logtape";
5+
6+
const logger = getLogger("nuxt");
7+
8+
const federation = createFederation({
9+
kv: new MemoryKvStore(),
10+
});
11+
12+
federation.setActorDispatcher(
13+
"/users/{identifier}",
14+
async (ctx, identifier) => {
15+
return new Person({
16+
id: ctx.getActorUri(identifier),
17+
preferredUsername: identifier,
18+
name: identifier,
19+
});
20+
},
21+
);
22+
23+
export default federation;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { configure, getConsoleSink } from "@logtape/logtape";
2+
import { AsyncLocalStorage } from "node:async_hooks";
3+
4+
await configure({
5+
contextLocalStorage: new AsyncLocalStorage(),
6+
sinks: {
7+
console: getConsoleSink(),
8+
},
9+
filters: {},
10+
loggers: [
11+
{
12+
category: "nuxt",
13+
lowestLevel: "debug",
14+
sinks: ["console"],
15+
},
16+
{ category: "fedify", lowestLevel: "info", sinks: ["console"] },
17+
{
18+
category: ["logtape", "meta"],
19+
lowestLevel: "warning",
20+
sinks: ["console"],
21+
},
22+
],
23+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { defineEventHandler } from "h3";
2+
import federation from "../federation";
3+
4+
export default defineEventHandler(async (event) => {
5+
// Construct the full URL from headers
6+
const proto = event.headers.get("x-forwarded-proto") || "http";
7+
const host = event.headers.get("host") || "localhost";
8+
const url = new URL(event.node.req.url || "", `${proto}://${host}`);
9+
10+
const request = new Request(url, {
11+
method: event.node.req.method,
12+
headers: event.node.req.headers as Record<string, string>,
13+
body: ["GET", "HEAD", "DELETE"].includes(event.node.req.method)
14+
? undefined
15+
: undefined,
16+
});
17+
18+
const response = await federation.fetch(request, {
19+
contextData: undefined,
20+
});
21+
22+
if (response.status === 404) return; // Let Nuxt handle 404
23+
return response;
24+
});

packages/init/src/test/port.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,20 @@ export async function replacePortInApp(
145145
return;
146146
}
147147

148+
if (wf === "nuxt") {
149+
// Insert server.port into the Nuxt config (via nitro config in nuxt.config.ts)
150+
const configPath = join(dir, "nuxt.config.ts");
151+
const content = await readFile(configPath, "utf8");
152+
await writeFile(
153+
configPath,
154+
content.replace(
155+
"defineNuxtConfig({",
156+
`defineNuxtConfig({\n nitro: { port: ${newPort} },`,
157+
),
158+
);
159+
return;
160+
}
161+
148162
printErrorMessage`Unknown framework ${wf} — cannot replace port.`;
149163
}
150164

packages/init/src/webframeworks/mod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import express from "./express.ts";
66
import hono from "./hono.ts";
77
import next from "./next.ts";
88
import nitro from "./nitro.ts";
9+
import nuxt from "./nuxt.ts";
910
import solidstart from "./solidstart.ts";
1011

1112
/**
@@ -23,6 +24,7 @@ const webFrameworks: WebFrameworks = {
2324
hono,
2425
next,
2526
nitro,
27+
nuxt,
2628
solidstart,
2729
} as const;
2830

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { PACKAGE_MANAGER } from "../const.ts";
2+
import deps from "../json/deps.json" with { type: "json" };
3+
import { PACKAGE_VERSION, readTemplate } from "../lib.ts";
4+
import type { PackageManager, WebFrameworkDescription } from "../types.ts";
5+
import { defaultDenoDependencies, defaultDevDependencies } from "./const.ts";
6+
import { getInstruction } from "./utils.ts";
7+
8+
const nuxtDescription: WebFrameworkDescription = {
9+
label: "Nuxt",
10+
packageManagers: PACKAGE_MANAGER,
11+
defaultPort: 3000,
12+
init: async ({ packageManager: pm, testMode }) => ({
13+
command: Array.from(getInitCommand(pm)),
14+
dependencies: getDeps(pm),
15+
devDependencies: {
16+
...defaultDevDependencies,
17+
"typescript": deps["npm:typescript"],
18+
"@types/node": deps["npm:@types/node@25"],
19+
},
20+
federationFile: "server/federation.ts",
21+
loggingFile: "server/logging.ts",
22+
env: testMode ? { HOST: "127.0.0.1" } : {} as Record<string, string>,
23+
files: {
24+
"nuxt.config.ts": await readTemplate("nuxt/nuxt.config.ts"),
25+
"server/federation.ts": await readTemplate("nuxt/server/federation.ts"),
26+
"server/logging.ts": await readTemplate("nuxt/server/logging.ts"),
27+
"server/middleware/federation.ts": await readTemplate(
28+
"nuxt/server/middleware/federation.ts",
29+
),
30+
...(pm !== "deno" && {
31+
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
32+
}),
33+
},
34+
tasks: pm !== "deno"
35+
? { "lint": "eslint ." }
36+
: {} as Record<string, string>,
37+
instruction: getInstruction(pm, 3000),
38+
}),
39+
};
40+
41+
export default nuxtDescription;
42+
43+
function* getInitCommand(pm: PackageManager) {
44+
yield* getNuxtInitCommand(pm);
45+
yield "init";
46+
yield ".";
47+
yield "--template";
48+
yield "minimal";
49+
yield "--no-install";
50+
yield "--force";
51+
yield "--packageManager";
52+
yield pm;
53+
yield "--no-gitInit";
54+
yield "--no-modules";
55+
}
56+
57+
/**
58+
* Returns the shell command array to scaffold a new Nuxt project
59+
* in the current directory using the given package manager.
60+
*/
61+
const getNuxtInitCommand = (pm: PackageManager): string[] =>
62+
pm === "bun"
63+
? ["bunx", "nuxi"]
64+
: pm === "deno"
65+
? ["deno", "-A", "npm:nuxi@latest"]
66+
: pm === "npm"
67+
? ["npx", "nuxi"]
68+
: [pm, "dlx", "nuxi"];
69+
70+
const getDeps = (pm: PackageManager): Record<string, string> =>
71+
pm !== "deno"
72+
? {
73+
"@fedify/nuxt": PACKAGE_VERSION,
74+
"h3": deps["npm:h3"],
75+
"nuxt": deps["npm:nuxt"],
76+
}
77+
: {
78+
...defaultDenoDependencies,
79+
"@fedify/nuxt": PACKAGE_VERSION,
80+
"npm:@nuxt/kit": deps["npm:@nuxt/kit"],
81+
"npm:h3": deps["npm:h3"],
82+
"npm:nuxt": deps["npm:nuxt"],
83+
};

0 commit comments

Comments
 (0)