#!/usr/bin/env -S deno run --allow-net --allow-read
// Copyright 2018-2026 the Deno authors. MIT license.
import {
  serveDir as stableServeDir,
  type ServeDirOptions as StableServeDirOptions,
  serveFile as stableServeFile,
  type ServeFileOptions as StableServeFileOptions,
} from "./file_server.ts";

/**
 * Serves the files under the given directory root (opts.fsRoot).
 *
 * @experimental **UNSTABLE**: New API, yet to be vetted.
 *
 * @example Usage
 * ```ts ignore
 * import { serveDir } from "@std/http/file-server";
 *
 * Deno.serve((req) => {
 *   const pathname = new URL(req.url).pathname;
 *   if (pathname.startsWith("/static")) {
 *     return serveDir(req, {
 *       fsRoot: "path/to/static/files/dir",
 *     });
 *   }
 *   // Do dynamic responses
 *   return new Response();
 * });
 * ```
 *
 * @example Changing the URL root
 *
 * Requests to `/static/path/to/file` will be served from `./public/path/to/file`.
 *
 * ```ts ignore
 * import { serveDir } from "@std/http/file-server";
 *
 * Deno.serve((req) => serveDir(req, {
 *   fsRoot: "public",
 *   urlRoot: "static",
 * }));
 * ```
 *
 * @param req The request to handle
 * @param opts Additional options.
 * @returns A response for the request.
 */
export function serveDir(
  req: Request,
  opts: ServeDirOptions = {},
): Promise<Response> {
  return stableServeDir(req, opts);
}

/** Interface for serveDir options. */
export interface ServeDirOptions extends StableServeDirOptions {
  /**
   * Also serves `.html` files without the need for specifying the extension.
   * For example `foo.html` could be accessed through both `/foo` and `/foo.html`.
   *
   * @default {false}
   */
  cleanUrls?: boolean;
}

/** Interface for serveFile options. */
export interface ServeFileOptions extends StableServeFileOptions {
  /** Headers to add to each response
   *
   * @default {[]}
   */
  headers?: string[];
}

/**
 * Resolves a {@linkcode Response} with the requested file as the body.
 *
 * @experimental **UNSTABLE**: New API, yet to be vetted.
 *
 * @example Usage
 * ```ts ignore
 * import { serveFile } from "@std/http/file-server";
 *
 * Deno.serve((req) => {
 *   return serveFile(req, "README.md");
 * });
 * ```
 *
 * @param req The server request context used to cleanup the file handle.
 * @param filePath Path of the file to serve.
 * @param options Additional options.
 * @returns A response for the request.
 */
export async function serveFile(
  req: Request,
  filePath: string,
  options?: ServeFileOptions,
): Promise<Response> {
  const response = await stableServeFile(req, filePath, options);

  if (options?.headers) {
    for (const header of options.headers) {
      const headerSplit = header.split(":");
      const name = headerSplit[0]!;
      const value = headerSplit.slice(1).join(":");
      response.headers.append(name, value);
    }
  }

  return response;
}
