0.1.6Updated a month ago
import { join, relative } from "https://deno.land/std@0.214.0/path/mod.ts";
import type { Manifest } from "$fresh/server.ts";
import { existsSync, walk } from "jsr:@std/fs@^1.0.13";

const infinityImport = (path: string, index: number) => [`import * as $_${index} from "@infinity-beyond/${relative(Deno.cwd(), path)}"`.replace(/\\+/g, '/'), `$_${index}`];
const islandImport = (path: string, index: number) => [`import * as $_${index} from "@islands/${relative(join(Deno.cwd(), '/ui/islands/'), path)}"`.replace(/\\+/g, '/'), `$_${index}`];

const route_file_pattern = /\.tsx?$/;
const buildInfinityManifest = async () => {
  const manifest: Manifest = {routes: {}, islands: {}, baseUrl: ''};

  const www_path = join(Deno.cwd(), 'ui');

  if(!existsSync(www_path)) return { manifest, import_statements: [] };

  const import_statements: string[] = [];

  const routes_path = join(www_path, '/routes');
  if(existsSync(routes_path)) {
    for await (const dirEntry of walk(routes_path, { includeDirs: false })) {
      if(!route_file_pattern.test(dirEntry.name)) continue;
  
      let relative_path = `/${relative(www_path, dirEntry.path)}`.replace(/\\+/g, '/');
      if(relative_path.endsWith('/index')) relative_path = relative_path.replace(/\/index$/, '');
  
      const [import_statement, placeholder] = infinityImport(dirEntry.path, import_statements.length);

      import_statements.push(import_statement);

      manifest.routes['.'+relative_path] = placeholder as any;
    }
  }

  const islands_path = join(www_path, '/islands');
  if(existsSync(islands_path)) {
    for await (const dirEntry of walk(islands_path, { includeDirs: false })) {
      if(!route_file_pattern.test(dirEntry.name)) continue;
  
      let relative_path = `/${relative(www_path, dirEntry.path)}`.replace(/\\+/g, '/');
      if(relative_path.endsWith('/index')) relative_path = relative_path.replace(/\/index$/, '');
  
      const [import_statement, placeholder] = islandImport(dirEntry.path, import_statements.length);

      import_statements.push(import_statement);

      manifest.islands['.'+relative_path] = placeholder as any;
    }
  }

  return { manifest, import_statements };
}

const { manifest: infinity_manifest, import_statements } = await buildInfinityManifest();

const infinity_manifest_output = JSON.stringify(infinity_manifest, null, 2)
  .replace(/"(\$_\d+)"/g, '$1')
  .replace(/\"(routes|islands|baseUrl)\"\: /g, "$1: ");

const full_output = `import type { Manifest } from "$fresh/server.ts";

${import_statements.join('\n')}

export const manifest: Manifest = ${infinity_manifest_output}\n`;

const infinity_manifest_path = join(Deno.cwd(), 'dist/manifest.ts');

Deno.writeTextFileSync(infinity_manifest_path, full_output);