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

WIP: feat: staticRoute #655

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions examples/counter/fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
// This file is automatically updated during development when running `dev.ts`.

import * as $0 from "./routes/index.tsx";
import * as $1 from "./routes/index1.tsx";
import * as $$0 from "./islands/Counter.tsx";

const manifest = {
routes: {
"./routes/index.tsx": $0,
"./routes/index1.tsx": $1,
},
staticRoutes: {
"./staticRoutes/index.html": "./staticRoutes/index.html",
},
islands: {
"./islands/Counter.tsx": $$0,
Expand Down
15 changes: 15 additions & 0 deletions examples/counter/routes/index1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** @jsx h */
import { h } from "preact";
import Counter from "../islands/Counter.tsx";

export default function Home() {
return (
<div>
<p>
Welcome to Fresh. Try to update this message in the ./routes/index.tsx
file, and refresh.
</p>
<Counter start={3} />
</div>
);
}
12 changes: 12 additions & 0 deletions examples/counter/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

</body>
</html>
12 changes: 12 additions & 0 deletions examples/counter/staticRoutes/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello world</title>
</head>
<body>
<span>hello world</span>
</body>
</html>
53 changes: 47 additions & 6 deletions src/dev/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { error } from "./error.ts";

interface Manifest {
routes: string[];
staticRoutes: string[];
islands: string[];
}

export async function collect(directory: string): Promise<Manifest> {
const routesDir = join(directory, "./routes");
const staticRoutesDir = join(directory, "./staticRoutes");
const islandsDir = join(directory, "./islands");

const routes = [];
Expand Down Expand Up @@ -46,6 +48,36 @@ export async function collect(directory: string): Promise<Manifest> {
}
}
routes.sort();
// read static html route
const staticRoutes = [];
try {
const routesUrl = toFileUrl(staticRoutesDir);
// TODO(lucacasonato): remove the extranious Deno.readDir when
// https://github.com/denoland/deno_std/issues/1310 is fixed.
for await (const _ of Deno.readDir(staticRoutesDir)) {
// do nothing
}
const routesFolder = walk(staticRoutesDir, {
includeDirs: false,
includeFiles: true,
exts: [".html"],
});
for await (const entry of routesFolder) {
if (entry.isFile) {
const file = toFileUrl(entry.path).href.substring(
routesUrl.href.length,
);
staticRoutes.push(file);
}
}
} catch (err) {
if (err instanceof Deno.errors.NotFound) {
// Do nothing.
} else {
throw err;
}
}
staticRoutes.sort();

const islands = [];
try {
Expand Down Expand Up @@ -73,11 +105,11 @@ export async function collect(directory: string): Promise<Manifest> {
}
islands.sort();

return { routes, islands };
return { routes, islands, staticRoutes };
}

export async function generate(directory: string, manifest: Manifest) {
const { routes, islands } = manifest;
const { routes, islands, staticRoutes } = manifest;

const output = `// DO NOT EDIT. This file is generated by fresh.
// This file SHOULD be checked into source version control.
Expand All @@ -100,6 +132,12 @@ const manifest = {
.join("\n ")
}
},
staticRoutes: {
${
staticRoutes.map((file) => `${JSON.stringify(`./staticRoutes${file}`)}: "./staticRoutes${file}",`)
.join("\n ")
}
},
islands: {
${
islands.map((file, i) => `${JSON.stringify(`./islands${file}`)}: $$${i},`)
Expand Down Expand Up @@ -149,17 +187,20 @@ export async function dev(base: string, entrypoint: string) {
if (prevManifest) {
currentManifest = JSON.parse(prevManifest);
} else {
currentManifest = { islands: [], routes: [] };
currentManifest = { islands: [], routes: [], staticRoutes: [] };
}
const newManifest = await collect(dir);
Deno.env.set("FRSH_DEV_PREVIOUS_MANIFEST", JSON.stringify(newManifest));

const manifestChanged =
!arraysEqual(newManifest.routes, currentManifest.routes) ||
!arraysEqual(newManifest.islands, currentManifest.islands);

if (manifestChanged) await generate(dir, newManifest);

try {
if (manifestChanged) await generate(dir, newManifest);
} catch (error) {

console.log('entrypoint', error)
}
await import(entrypoint);
}

Expand Down
53 changes: 52 additions & 1 deletion src/server/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ interface StaticFile {
export class ServerContext {
#dev: boolean;
#routes: Route[];
#staticRoutes: StaticFile[];
#islands: Island[];
#staticFiles: StaticFile[];
#bundler: Bundler;
Expand All @@ -66,6 +67,7 @@ export class ServerContext {

constructor(
routes: Route[],
staticRoutes: StaticFile[],
islands: Island[],
staticFiles: StaticFile[],
renderfn: RenderFunction,
Expand All @@ -77,6 +79,7 @@ export class ServerContext {
importMapURL: URL,
) {
this.#routes = routes;
this.#staticRoutes = staticRoutes;
this.#islands = islands;
this.#staticFiles = staticFiles;
this.#renderFn = renderfn;
Expand Down Expand Up @@ -104,9 +107,42 @@ export class ServerContext {
const routes: Route[] = [];
const islands: Island[] = [];
const middlewares: MiddlewareRoute[] = [];
const encoder = new TextEncoder();
let app: AppModule = DEFAULT_APP;
let notFound: UnknownPage = DEFAULT_NOT_FOUND;
let error: ErrorPage = DEFAULT_ERROR;
const staticRoutes: StaticFile[] = [];
for (const [self, staticPath] of Object.entries(manifest.staticRoutes ?? {})) {
const url = new URL(self, baseUrl).href;
// console.log('static route', self, staticPath, url)
if (!url.startsWith(baseUrl + "staticRoutes")) {
throw new TypeError("Page is not a child of the basepath.");
}
const path = url.substring(baseUrl.length - 1);
const fileUrl = new URL(staticPath, baseUrl)
// const localUrl = toFileUrl(url)
const stat = await Deno.stat(fileUrl);
const contentType = typeByExtension(extname(url)) ??
"application/octet-stream";
const etag = await crypto.subtle.digest(
"SHA-1",
encoder.encode(BUILD_ID + self),
).then((hash) =>
Array.from(new Uint8Array(hash))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("")
);
const staticRoute = {
localUrl: fileUrl,
path,
size: stat.size,
contentType,
etag,
};
console.log('static route1', staticRoute)
staticRoutes.push(staticRoute);
}

for (const [self, module] of Object.entries(manifest.routes)) {
const url = new URL(self, baseUrl).href;
if (!url.startsWith(baseUrl + "routes")) {
Expand Down Expand Up @@ -223,7 +259,7 @@ export class ServerContext {
includeDirs: false,
followSymlinks: false,
});
const encoder = new TextEncoder();
// const encoder = new TextEncoder();
for await (const entry of entires) {
const localUrl = toFileUrl(entry.path);
const path = localUrl.href.substring(staticFolder.href.length);
Expand All @@ -245,6 +281,7 @@ export class ServerContext {
contentType,
etag,
};
console.log(staticFile)
staticFiles.push(staticFile);
}
} catch (err) {
Expand All @@ -257,6 +294,7 @@ export class ServerContext {

return new ServerContext(
routes,
staticRoutes,
islands,
staticFiles,
opts.render ?? DEFAULT_RENDER_FN,
Expand Down Expand Up @@ -388,6 +426,19 @@ export class ServerContext {
);
}

for (
const { localUrl, path, size, contentType, etag } of this.#staticRoutes
) {
const route = sanitizePathToRegex(path);
routes[`GET@${route}`] = this.#staticFileHandler(
localUrl,
size,
contentType,
etag,
);
console.log(routes)
}

const genRender = <Data = undefined>(
route: Route<Data> | UnknownPage | ErrorPage,
status: number,
Expand Down
1 change: 1 addition & 0 deletions src/server/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export interface Manifest {
| ErrorPageModule
| UnknownPageModule
>;
staticRoutes: Record<string, string>;
islands: Record<string, IslandModule>;
baseUrl: string;
}
Expand Down