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
63 changes: 46 additions & 17 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
import * as path from "@std/path";

export interface FreshConfig {
/**
* The root directory of the Fresh project.
*
* Other paths, such as `build.outDir`, `staticDir`, and `fsRoutes()`
* are resolved relative to this directory.
* @default Deno.cwd()
*/
root?: string;
build?: {
/**
* The directory to write generated files to when `dev.ts build` is run.
*
* This can be an absolute path, a file URL or a relative path.
* Relative paths are resolved against the `root` option.
* @default "_fresh"
*/
outDir?: string;
};
/**
* Serve fresh from a base path instead of from the root.
* "/foo/bar" -> http://localhost:8000/foo/bar
* @default {undefined}
* @default undefined
*/
basePath?: string;
/**
* The directory to serve static files from.
*
* This can be an absolute path, a file URL or a relative path.
* Relative paths are resolved against the `root` option.
* @default "static"
*/
staticDir?: string;
}

Expand All @@ -35,35 +52,47 @@ export interface ResolvedFreshConfig {
}

export function parseRootPath(root: string, cwd: string): string {
if (root.startsWith("file://")) {
root = path.fromFileUrl(root);
} else if (!path.isAbsolute(root)) {
root = path.join(cwd, root);
return parseDirPath(root, cwd, true);
}

function parseDirPath(
dirPath: string,
root: string,
fileToDir = false,
): string {
if (dirPath.startsWith("file://")) {
dirPath = path.fromFileUrl(dirPath);
} else if (!path.isAbsolute(dirPath)) {
dirPath = path.join(root, dirPath);
}

if (fileToDir) {
const ext = path.extname(dirPath);
if (
ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx" ||
ext === ".mjs"
) {
dirPath = path.dirname(dirPath);
}
}

const ext = path.extname(root);
if (
ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx" ||
ext === ".mjs"
) {
root = path.dirname(root);
if (Deno.build.os === "windows") {
dirPath = dirPath.replaceAll("\\", "/");
}

return root;
return dirPath;
}

export function normalizeConfig(options: FreshConfig): ResolvedFreshConfig {
const root = options.root
? parseRootPath(options.root, Deno.cwd())
: Deno.cwd();
const root = parseRootPath(options.root ?? ".", Deno.cwd());

return {
root,
build: {
outDir: options.build?.outDir ?? path.join(root, "_fresh"),
outDir: parseDirPath(options.build?.outDir ?? "_fresh", root),
},
basePath: options.basePath ?? "",
staticDir: options.staticDir ?? path.join(root, "static"),
staticDir: parseDirPath(options.staticDir ?? "static", root),
mode: "production",
};
}
Expand Down
101 changes: 97 additions & 4 deletions src/config_test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,108 @@
import { expect } from "@std/expect";
import { parseRootPath } from "./config.ts";
import { normalizeConfig, parseRootPath } from "./config.ts";
import type { FreshConfig } from "./mod.ts";

// FIXME: Windows
Deno.test.ignore("parseRootPath", () => {
const cwd = Deno.cwd();
Deno.test("parseRootPath", () => {
const cwd = Deno.cwd().replaceAll("\\", "/");

// File paths
expect(parseRootPath("file:///foo/bar", cwd)).toEqual("/foo/bar");
expect(parseRootPath("file:///foo/bar.ts", cwd)).toEqual("/foo");
if (Deno.build.os === "windows") {
expect(parseRootPath("file:///C:/foo/bar", cwd)).toEqual("C:/foo/bar");
expect(parseRootPath("file:///C:/foo/bar.ts", cwd)).toEqual("C:/foo");
}

// Relative paths
expect(parseRootPath("./foo/bar", cwd)).toEqual(`${cwd}/foo/bar`);
expect(parseRootPath("./foo/bar.ts", cwd)).toEqual(`${cwd}/foo`);

// Absolute paths
expect(parseRootPath("/foo/bar", cwd)).toEqual("/foo/bar");
expect(parseRootPath("/foo/bar.ts", cwd)).toEqual("/foo");
expect(parseRootPath("/foo/bar.tsx", cwd)).toEqual("/foo");
expect(parseRootPath("/foo/bar.js", cwd)).toEqual("/foo");
expect(parseRootPath("/foo/bar.jsx", cwd)).toEqual("/foo");
expect(parseRootPath("/foo/bar.mjs", cwd)).toEqual("/foo");
if (Deno.build.os === "windows") {
expect(parseRootPath("C:/foo/bar", cwd)).toEqual("C:/foo/bar");
expect(parseRootPath("C:/foo/bar.ts", cwd)).toEqual("C:/foo");
}
});

Deno.test("normalizeConfig - root", () => {
const cwd = Deno.cwd().replaceAll("\\", "/");
const configRoot = (root?: string) => normalizeConfig({ root }).root;

expect(configRoot()).toEqual(cwd);
expect(configRoot("/foo/bar")).toEqual("/foo/bar");
expect(configRoot("/foo/bar.ts")).toEqual("/foo");
expect(configRoot("file:///foo/bar")).toEqual("/foo/bar");
expect(configRoot("./foo/bar")).toEqual(`${cwd}/foo/bar`);
expect(configRoot("./foo/bar.ts")).toEqual(`${cwd}/foo`);

if (Deno.build.os === "windows") {
expect(configRoot("C:/foo/bar.ts")).toEqual("C:/foo");
expect(configRoot("file:///C:/foo/bar")).toEqual("C:/foo/bar");
}
});

Deno.test("normalizeConfig - build.outDir", () => {
const cwd = Deno.cwd().replaceAll("\\", "/");
const outDir = (options: FreshConfig) =>
normalizeConfig(options).build.outDir;

// Default outDir
expect(outDir({ root: "./src" })).toEqual(`${cwd}/src/_fresh`);
expect(outDir({ root: "/src" })).toEqual("/src/_fresh");
expect(outDir({ root: "file:///src" })).toEqual("/src/_fresh");

// Relative outDir
expect(outDir({ root: "/src", build: { outDir: "dist" } })).toEqual(
"/src/dist",
);
expect(outDir({ root: "/src", build: { outDir: "./dist" } })).toEqual(
"/src/dist",
);

// Absolute outDir
expect(outDir({ root: "/src", build: { outDir: "/dist" } })).toEqual(
"/dist",
);
expect(outDir({ root: "/src", build: { outDir: "/dist/fresh" } })).toEqual(
"/dist/fresh",
);
expect(outDir({ root: "/src", build: { outDir: "file:///dist" } })).toEqual(
"/dist",
);
});

Deno.test("normalizeConfig - staticDir", () => {
const cwd = Deno.cwd().replaceAll("\\", "/");
const staticDir = (options: FreshConfig) =>
normalizeConfig(options).staticDir;

// Default staticDir
expect(staticDir({ root: "./src" })).toEqual(`${cwd}/src/static`);
expect(staticDir({ root: "/src" })).toEqual("/src/static");
expect(staticDir({ root: "file:///src" })).toEqual("/src/static");

// Relative staticDir
expect(staticDir({ root: "/src", staticDir: "public" })).toEqual(
"/src/public",
);
expect(staticDir({ root: "/src", staticDir: "./public" })).toEqual(
"/src/public",
);

// Absolute staticDir
expect(staticDir({ root: "/src", staticDir: "/public" })).toEqual(
"/public",
);
expect(staticDir({ root: "/src", staticDir: "/public/assets" })).toEqual(
"/public/assets",
);
expect(staticDir({ root: "/src", staticDir: "file:///public" })).toEqual(
"/public",
);
});
Loading