Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions packages/init/src/action/configs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { message } from "@optique/core";
import { kvStores, messageQueues } from "../lib.ts";
import type { InitCommandData } from "../types.ts";
import bareBonesDescription from "../webframeworks/bare-bones.ts";
import nuxtDescription from "../webframeworks/nuxt.ts";
import { loadDenoConfig } from "./configs.ts";
import { patchFiles } from "./patch.ts";

Expand Down Expand Up @@ -133,6 +134,28 @@ test("patchFiles creates a Biome config matching the npm package version", async
}
});

test("patchFiles wires Nuxt logging through a Nitro plugin", async () => {
const dir = await mkdtemp(join(tmpdir(), "fedify-init-nuxt-"));

try {
const data = await createNuxtNpmInitData(dir);
await patchFiles(data);

const logging = await readFile(join(dir, "server/logging.ts"), "utf8");
const plugin = await readFile(
join(dir, "server/plugins/logging.ts"),
"utf8",
);

assert.match(logging, /export default configure\(/);
assert.doesNotMatch(logging, /await configure\(/);
assert.match(plugin, /import loggingConfigured from "\.\.\/logging";/);
assert.match(plugin, /await loggingConfigured;/);
} finally {
await rm(dir, { recursive: true, force: true });
}
});

async function createNpmInitData(dir: string): Promise<InitCommandData> {
const initializer = await bareBonesDescription.init({
command: "init",
Expand Down Expand Up @@ -166,6 +189,39 @@ async function createNpmInitData(dir: string): Promise<InitCommandData> {
return data;
}

async function createNuxtNpmInitData(dir: string): Promise<InitCommandData> {
const initializer = await nuxtDescription.init({
command: "init",
projectName: "example",
packageManager: "npm",
webFramework: "nuxt",
kvStore: "in-memory",
messageQueue: "in-process",
dryRun: false,
allowNonEmpty: false,
testMode: false,
dir,
});

const data = {
command: "init",
projectName: "example",
packageManager: "npm",
webFramework: "nuxt",
kvStore: "in-memory",
messageQueue: "in-process",
dryRun: false,
allowNonEmpty: false,
testMode: false,
dir,
initializer,
kv: kvStores["in-memory"],
mq: messageQueues["in-process"],
env: {},
} satisfies InitCommandData;
return data;
}
Comment on lines +192 to +223
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Optional: factor out shared init-data construction.

createNuxtNpmInitData and createNpmInitData differ only in webFramework and the initializer source. Consider parameterizing a single helper to reduce duplication as more framework-specific tests are added.

♻️ Sketch of a parameterized helper
async function createInitDataFor(
  description: WebFrameworkDescription,
  webFramework: WebFramework,
  dir: string,
): Promise<InitCommandData> {
  const base = {
    command: "init" as const,
    projectName: "example",
    packageManager: "npm" as const,
    webFramework,
    kvStore: "in-memory" as const,
    messageQueue: "in-process" as const,
    dryRun: false,
    allowNonEmpty: false,
    testMode: false,
    dir,
  };
  const initializer = await description.init(base);
  return {
    ...base,
    initializer,
    kv: kvStores["in-memory"],
    mq: messageQueues["in-process"],
    env: {},
  } satisfies InitCommandData;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/init/src/action/configs.test.ts` around lines 192 - 223,
createNuxtNpmInitData and createNpmInitData are duplicated; refactor by
introducing a parameterized helper (eg. createInitDataFor) that accepts a
WebFrameworkDescription (description), a WebFramework (webFramework) and dir,
builds the shared base init args, calls description.init(base) to get
initializer, and returns the combined object satisfying InitCommandData
(including kv: kvStores["in-memory"], mq: messageQueues["in-process"], env: {}).
Replace createNuxtNpmInitData and createNpmInitData to call this helper with the
appropriate description and webFramework values.


function getSchemaVersion(schema: string): string {
const match = schema.match(/\/schemas\/(\d+\.\d+\.\d+)\//);
assert.ok(match, `Unexpected Biome schema URL: ${schema}`);
Expand Down
6 changes: 4 additions & 2 deletions packages/init/src/action/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ export const loadFederation = async (
* @param param0 - Destructured object containing the project name
* @returns The complete logging configuration file content as a string
*/
export const loadLogging = async ({ projectName }: InitCommandData) =>
export const loadLogging = async (
{ projectName, initializer }: InitCommandData,
) =>
pipe(
await readTemplate("defaults/logging.ts"),
await readTemplate(initializer.loggingTemplate ?? "defaults/logging.ts"),
replace(/\/\* project name \*\//, JSON.stringify(projectName)),
);

Expand Down
23 changes: 23 additions & 0 deletions packages/init/src/templates/nuxt/server/logging.ts.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { configure, getConsoleSink } from "@logtape/logtape";
import { AsyncLocalStorage } from "node:async_hooks";

export default configure({
contextLocalStorage: new AsyncLocalStorage(),
sinks: {
console: getConsoleSink(),
},
filters: {},
loggers: [
{
category: /* project name */,
lowestLevel: "debug",
sinks: ["console"],
},
{ category: "fedify", lowestLevel: "info", sinks: ["console"] },
{
category: ["logtape", "meta"],
lowestLevel: "warning",
sinks: ["console"],
},
],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import loggingConfigured from "../logging";

export default defineNitroPlugin(async () => {
await loggingConfigured;
});
2 changes: 2 additions & 0 deletions packages/init/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ export interface WebFrameworkInitializer {
federationFile: string;
/** Relative path where the logging configuration file will be created. */
loggingFile: string;
/** Optional template path for the logging configuration file. */
loggingTemplate?: string;
/**
* Additional files to create, keyed by relative path to file content.
* Do not use `".env"` as a key — use the {@link env} property instead so
Expand Down
4 changes: 4 additions & 0 deletions packages/init/src/webframeworks/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ const nuxtDescription: WebFrameworkDescription = {
},
federationFile: "server/federation.ts",
loggingFile: "server/logging.ts",
loggingTemplate: "nuxt/server/logging.ts",
env: testMode ? { HOST: "127.0.0.1" } : {} as Record<string, string>,
files: {
"nuxt.config.ts": await readTemplate("nuxt/nuxt.config.ts"),
"server/plugins/logging.ts": await readTemplate(
"nuxt/server/plugins/logging.ts",
),
...(pm !== "deno" && {
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
}),
Expand Down
Loading