Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support ignore to ignore scanned files #1430

Merged
merged 2 commits into from
Jul 14, 2023
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
1 change: 1 addition & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const NitroDefaults: NitroConfig = {
},
virtual: {},
compressPublicAssets: false,
ignore: [],

// Dev
dev: false,
Expand Down
110 changes: 54 additions & 56 deletions src/scan.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,53 @@
import { resolve, join } from "pathe";
import { relative, join } from "pathe";
import { globby } from "globby";

import { withBase, withLeadingSlash, withoutTrailingSlash } from "ufo";
import type { Nitro, NitroEventHandler } from "./types";
import type { Nitro } from "./types";

export const GLOB_SCAN_PATTERN = "**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}";
type FileInfo = { dir: string; path: string; fullPath: string };
type FileInfo = { path: string; fullPath: string };

const httpMethodRegex =
/\.(connect|delete|get|head|options|patch|post|put|trace)/;

export async function scanHandlers(nitro: Nitro) {
const middleware = await scanMiddleware(nitro);

const handlers = await Promise.all([
scanMiddleware(nitro),
scanRoutes(nitro, "api", "/api"),
scanRoutes(nitro, "routes", "/"),
scanServerRoutes(nitro, "api", "/api"),
scanServerRoutes(nitro, "routes", "/"),
]).then((r) => r.flat());

nitro.scannedHandlers = handlers
.flatMap((h) => h.handlers)
.filter((h, index, array) => {
nitro.scannedHandlers = [
...middleware,
...handlers.filter((h, index, array) => {
return (
h.middleware ||
array.findIndex(
(h2) => h.route === h2.route && h.method === h2.method
) === index
);
});
}),
];

return handlers;
}

export function scanMiddleware(nitro: Nitro) {
return scanServerDir(nitro, "middleware", (file) => ({
middleware: true,
handler: file.fullPath,
}));
export async function scanMiddleware(nitro: Nitro) {
const files = await scanFiles(nitro, "middleware");
return files.map((file) => {
return {
middleware: true,
handler: file.fullPath,
};
});
}

export function scanRoutes(nitro: Nitro, dir: string, prefix = "/") {
return scanServerDir(nitro, dir, (file) => {
export async function scanServerRoutes(
nitro: Nitro,
dir: "routes" | "api",
prefix = "/"
) {
const files = await scanFiles(nitro, dir);
return files.map((file) => {
let route = file.path
.replace(/\.[A-Za-z]+$/, "")
.replace(/\[\.{3}]/g, "**")
Expand All @@ -59,52 +67,42 @@ export function scanRoutes(nitro: Nitro, dir: string, prefix = "/") {
return {
handler: file.fullPath,
lazy: true,
middlweware: false,
route,
method,
};
});
}

async function scanServerDir(
nitro: Nitro,
name: string,
mapper: (file: FileInfo) => NitroEventHandler
) {
const dirs = nitro.options.scanDirs.map((dir) => join(dir, name));
const files = await scanDirs(dirs);
const handlers: NitroEventHandler[] = files.map((f) => mapper(f));
return { dirs, files, handlers };
export async function scanPlugins(nitro: Nitro) {
const files = await scanFiles(nitro, "plugins");
return files.map((f) => f.fullPath);
}

export async function scanPlugins(nitro: Nitro) {
const plugins = [];
for (const dir of nitro.options.scanDirs) {
const pluginDir = join(dir, "plugins");
const pluginFiles = await globby(GLOB_SCAN_PATTERN, {
cwd: pluginDir,
absolute: true,
});
plugins.push(...pluginFiles.sort());
}
return plugins;
async function scanFiles(nitro: Nitro, name: string): Promise<FileInfo[]> {
const files = await Promise.all(
nitro.options.scanDirs.map((dir) => scanDir(nitro, dir, name))
).then((r) => r.flat());
return files;
}

function scanDirs(dirs: string[]): Promise<FileInfo[]> {
return Promise.all(
dirs.map(async (dir) => {
const fileNames = await globby(GLOB_SCAN_PATTERN, {
cwd: dir,
dot: true,
});
return fileNames
.map((fileName) => {
return {
dir,
path: fileName,
fullPath: resolve(dir, fileName),
};
})
.sort((a, b) => a.path.localeCompare(b.path));
async function scanDir(
nitro: Nitro,
dir: string,
name: string
): Promise<FileInfo[]> {
const fileNames = await globby(join(name, GLOB_SCAN_PATTERN), {
cwd: dir,
dot: true,
ignore: nitro.options.ignore,
absolute: true,
});
return fileNames
.map((fullPath) => {
return {
fullPath,
path: relative(join(dir, name), fullPath),
};
})
).then((r) => r.flat());
.sort((a, b) => a.path.localeCompare(b.path));
}
1 change: 1 addition & 0 deletions src/types/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export interface NitroOptions extends PresetOptions {
plugins: string[];
virtual: Record<string, string | (() => string | Promise<string>)>;
compressPublicAssets: boolean | CompressOptions;
ignore: string[];

// Dev
dev: boolean;
Expand Down
3 changes: 3 additions & 0 deletions test/fixture/api/_ignored.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default eventHandler((event) => {
throw createError("This file should be ignored!");
});
3 changes: 3 additions & 0 deletions test/fixture/middleware/_ignored.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default eventHandler((event) => {
throw createError("This file should be ignored!");
});
1 change: 1 addition & 0 deletions test/fixture/nitro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default defineNitroConfig({
dir: "files",
},
],
ignore: ["api/**/_*", "middleware/_ignored.ts", "routes/_*.ts"],
appConfig: {
"nitro-config": true,
dynamic: "initial",
Expand Down
3 changes: 3 additions & 0 deletions test/fixture/routes/_ignored.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default eventHandler((event) => {
throw createError("This file should be ignored!");
});
7 changes: 7 additions & 0 deletions test/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,4 +394,11 @@ export function testNitro(
const res = await callHandler({ url: "/wait-until" });
expect(res.data).toBe("done");
});

describe("ignore", () => {
it("server routes should be ignored", async () => {
expect((await callHandler({ url: "/api/_ignored" })).status).toBe(404);
expect((await callHandler({ url: "/_ignored" })).status).toBe(404);
});
});
}