UNPKG

@jsenv/core

Version:

Tool to develop, test and build js projects

148 lines (144 loc) 4.5 kB
import { readEntryStatSync } from "@jsenv/filesystem"; import { ensurePathnameTrailingSlash } from "@jsenv/urls"; import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js"; import { readFileSync, readdirSync } from "node:fs"; import { FILE_AND_SERVER_URLS_CONVERTER } from "./file_and_server_urls_converter.js"; import { jsenvPluginDirectoryListing } from "./jsenv_plugin_directory_listing.js"; import { jsenvPluginFsRedirection } from "./jsenv_plugin_fs_redirection.js"; const directoryContentMagicName = "..."; export const jsenvPluginProtocolFile = ({ spa = true, magicExtensions, magicDirectoryIndex, preserveSymlinks, directoryListing, rootDirectoryUrl, mainFilePath, packageDirectory, sourceFilesConfig, }) => { return [ jsenvPluginFsRedirection({ spa, directoryContentMagicName, magicExtensions, magicDirectoryIndex, preserveSymlinks, }), { name: "jsenv:fs_resolution", appliesDuring: "*", resolveReference: { filesystem: (reference) => { const ownerUrlInfo = reference.ownerUrlInfo; const baseUrl = ownerUrlInfo.type === "directory" ? ensurePathnameTrailingSlash(ownerUrlInfo.url) : ownerUrlInfo.url; return new URL(reference.specifier, baseUrl).href; }, }, }, { name: "jsenv:@fs", // during build it's fine to use "file://"" urls // but during dev it's a browser running the code // so absolute file urls needs to be relativized appliesDuring: "dev", resolveReference: (reference) => { if (reference.specifier.startsWith("/@fs/")) { return FILE_AND_SERVER_URLS_CONVERTER.asFileUrl(reference.specifier); } return null; }, formatReference: (reference) => { const { generatedUrl } = reference; if (!generatedUrl.startsWith("file:")) { return null; } if (reference.original) { const originalSpecifierPathname = reference.original.specifierPathname; if ( originalSpecifierPathname.endsWith(`/${directoryContentMagicName}`) ) { return originalSpecifierPathname; } } const { rootDirectoryUrl } = reference.ownerUrlInfo.context; return FILE_AND_SERVER_URLS_CONVERTER.asServerUrl( generatedUrl, rootDirectoryUrl, ); }, }, ...(directoryListing ? [ jsenvPluginDirectoryListing({ spa, ...directoryListing, directoryContentMagicName, rootDirectoryUrl, mainFilePath, packageDirectory, sourceFilesConfig, }), ] : []), { name: "jsenv:directory_as_json", appliesDuring: "*", fetchUrlContent: (urlInfo) => { if (!urlInfo.url.startsWith("file:")) { return null; } const { firstReference } = urlInfo; let { fsStat } = firstReference; if (!fsStat) { fsStat = readEntryStatSync(urlInfo.url, { nullIfNotFound: true }); } if (!fsStat) { return null; } const isDirectory = fsStat.isDirectory(); if (!isDirectory) { return null; } const directoryContentArray = readdirSync(new URL(urlInfo.url)); const content = JSON.stringify(directoryContentArray, null, " "); return { type: "directory", contentType: "application/json", content, }; }, }, { name: "jsenv:file_url_fetching", appliesDuring: "*", fetchUrlContent: (urlInfo) => { if (!urlInfo.url.startsWith("file:")) { return null; } const { firstReference } = urlInfo; let { fsStat } = firstReference; if (!fsStat) { fsStat = readEntryStatSync(urlInfo.url, { nullIfNotFound: true }); } const serveFile = (url) => { const contentType = CONTENT_TYPE.fromUrlExtension(url); const fileBuffer = readFileSync(new URL(url)); const content = CONTENT_TYPE.isTextual(contentType) ? String(fileBuffer) : fileBuffer; return { content, contentType, contentLength: fileBuffer.length, }; }; return serveFile(urlInfo.url); }, }, ]; };