UNPKG

@storm-stack/core

Version:

A build toolkit and runtime used by Storm Software in TypeScript applications

942 lines (937 loc) 37.5 kB
'use strict'; var chunkXTI73WJP_cjs = require('./chunk-XTI73WJP.cjs'); var chunkN2HLPYZL_cjs = require('./chunk-N2HLPYZL.cjs'); var chunkSFV4P2MX_cjs = require('./chunk-SFV4P2MX.cjs'); var chunk3ONWID2V_cjs = require('./chunk-3ONWID2V.cjs'); var types = require('@storm-software/config-tools/types'); var bufferToString = require('@stryke/convert/buffer-to-string'); var hash = require('@stryke/hash/hash'); var filePathFns = require('@stryke/path/file-path-fns'); var isFile = require('@stryke/path/is-file'); var isParentPath = require('@stryke/path/is-parent-path'); var joinPaths = require('@stryke/path/join-paths'); var prettyBytes = require('@stryke/string-format/pretty-bytes'); var isBuffer = require('@stryke/type-checks/is-buffer'); var isFunction = require('@stryke/type-checks/is-function'); var isSetString = require('@stryke/type-checks/is-set-string'); var defu = require('defu'); var memfs = require('memfs'); var fs = require('fs'); var prettier = require('prettier'); var unionfs = require('unionfs'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var defu__default = /*#__PURE__*/_interopDefault(defu); var fs__default = /*#__PURE__*/_interopDefault(fs); var RUNTIME_PREFIX = "storm:"; var VirtualFileSystem = class { static { chunk3ONWID2V_cjs.__name(this, "VirtualFileSystem"); } /** * The internal map of virtual files. */ #runtimeIdMap = /* @__PURE__ */ new Map(); /** * A map of virtual file paths to their underlying file content. */ #cachedFS = /* @__PURE__ */ new Map(); /** * A map of virtual file paths to their underlying file content. */ #cachedResolver = /* @__PURE__ */ new Map(); /** * The internal map of virtual files. */ #virtualFS = new memfs.Volume(); /** * The physical file system. */ #fs = chunkXTI73WJP_cjs.cloneFS(fs__default.default); /** * The unified volume that combines the virtual file system with the real file system. * * @remarks * This volume allows for seamless access to both virtual and real files. */ #unifiedFS = new unionfs.Union(); /** * Indicator specifying if the file system module is patched */ #isPatched = false; /** * Function to revert require patch */ #revert; /** * The context of the virtual file system. */ #context; /** * The file system's logging function. */ #log; /** * Exposes the internal VFS map for advanced usage. */ get [chunkN2HLPYZL_cjs.__VFS_CACHE__]() { return this.#cachedFS; } /** * Exposes the internal VFS resolver cache for advanced usage. */ get [chunkN2HLPYZL_cjs.__VFS_RESOLVER__]() { return this.#cachedResolver; } /** * Exposes the internal VFS map for advanced usage. */ get [chunkN2HLPYZL_cjs.__VFS_VIRTUAL__]() { return this.#virtualFS; } /** * Exposes the internal UFS map for advanced usage. */ get [chunkN2HLPYZL_cjs.__VFS_UNIFIED__]() { return this.#unifiedFS; } /** * Creates a new instance of the VirtualFileSystem. * * @param context - The context of the virtual file system, typically containing options and logging functions. * @param serialized - A map of files/file contents to populate in cache */ constructor(context, serialized) { this.#context = context; this.#cachedFS = /* @__PURE__ */ new Map(); this.#runtimeIdMap = new Map(Object.entries(serialized?.runtimeIdMap ?? {})); if (!this.#fs.existsSync(this.#context.dataPath)) { this.#fs.mkdirSync(this.#context.dataPath, { recursive: true }); } if (!this.#fs.existsSync(this.#context.cachePath)) { this.#fs.mkdirSync(this.#context.cachePath, { recursive: true }); } if (!this.#fs.existsSync(joinPaths.joinPaths(this.#context.options.workspaceRoot, this.#context.options.output.outputPath))) { this.#fs.mkdirSync(joinPaths.joinPaths(this.#context.options.workspaceRoot, this.#context.options.output.outputPath), { recursive: true }); } this.#unifiedFS = this.#unifiedFS.use(this.#fs); if (this.#context.options.output.outputMode !== "fs") { if (serialized?.virtualFiles && Object.keys(serialized.virtualFiles).length > 0) { this.#virtualFS = new memfs.Volume(serialized.virtualFiles); } if (!this.#virtualFS.existsSync(this.#context.artifactsPath)) { this.#virtualFS.mkdirSync(this.#context.artifactsPath, { recursive: true }); } if (!this.#virtualFS.existsSync(this.#context.runtimePath)) { this.#virtualFS.mkdirSync(this.#context.runtimePath, { recursive: true }); } if (!this.#virtualFS.existsSync(this.#context.entryPath)) { this.#virtualFS.mkdirSync(this.#context.entryPath, { recursive: true }); } if (!this.#virtualFS.existsSync(this.#context.dtsPath)) { this.#virtualFS.mkdirSync(this.#context.dtsPath, { recursive: true }); } this.#unifiedFS = this.#unifiedFS.use(this.#virtualFS); } else { if (!this.#fs.existsSync(this.#context.artifactsPath)) { this.#fs.mkdirSync(this.#context.artifactsPath, { recursive: true }); } if (!this.#fs.existsSync(this.#context.runtimePath)) { this.#fs.mkdirSync(this.#context.runtimePath, { recursive: true }); } if (!this.#fs.existsSync(this.#context.entryPath)) { this.#fs.mkdirSync(this.#context.entryPath, { recursive: true }); } if (!this.#fs.existsSync(this.#context.dtsPath)) { this.#fs.mkdirSync(this.#context.dtsPath, { recursive: true }); } } this.#log = chunkSFV4P2MX_cjs.extendLog(this.#context.log, "virtual-file-system"); } [chunkN2HLPYZL_cjs.__VFS_INIT__]() { if (!this.#isPatched && this.#context.options.output.outputMode !== "fs") { this.#revert = chunkXTI73WJP_cjs.patchFS(fs__default.default, this); this.#isPatched = true; } } [chunkN2HLPYZL_cjs.__VFS_REVERT__]() { if (this.#isPatched && this.#context.options.output.outputMode !== "fs") { if (!this.#revert) { throw new Error("Attempting to revert File System patch prior to calling `__init__` function"); } this.#revert?.(); this.#isPatched = false; } } /** * Returns a Map of all runtime file IDs and their corresponding paths in the virtual file system. * * @returns A Map where the keys are runtime file IDs (strings) and the values are their corresponding paths (strings). */ get runtimeIdMap() { return this.#runtimeIdMap; } /** * Lists all runtime IDs in the virtual file system. * * @returns An array of formatted runtime IDs. */ get runtimeIds() { return Array.from(this.runtimeIdMap.keys()).map((id) => this.formatRuntimeId(id)); } /** * Checks if a given path or ID corresponds to a runtime file. * * @param pathOrId - The path or ID to check. * @param options - Options for resolving the path, such as paths to check. * @returns `true` if the path or ID corresponds to a runtime file, otherwise `false`. */ isRuntimeFile(pathOrId, options) { return !!this.runtimeIdMap.values().find((path) => path === this.resolvePath(pathOrId, { ...options, type: "file" })); } /** * Checks if a provided string is a valid runtime ID (does not need to already be created in the file system). * * @param id - The ID to check. * @returns Whether the ID is a valid runtime ID. */ isValidRuntimeId(id) { return id.startsWith(RUNTIME_PREFIX); } /** * Check if a path or ID corresponds to a virtual file. * * @param pathOrId - The path or ID to check. * @param options - Options for resolving the path, such as paths to check. * @returns Whether the path or ID corresponds to a virtual file. */ isVirtualFile(pathOrId, options = {}) { if (!pathOrId) { return false; } const resolvedPath = this.resolvePath(pathOrId, { ...options, type: "file" }); if (!resolvedPath) { return false; } if (this.runtimeIdMap.values().find((path) => path === resolvedPath)) { return true; } return this.#virtualFS.existsSync(resolvedPath); } /** * Check if a path exists within one of the directories specified in the tsconfig.json's `path` field. * * @see https://www.typescriptlang.org/tsconfig#paths * * @param pathOrId - The path or ID to check. * @returns Whether the path or ID corresponds to a virtual file. */ isTsconfigPath(pathOrId) { return !!this.#context.tsconfig.options.paths && Object.keys(this.#context.tsconfig.options.paths).some((path) => pathOrId.startsWith(path.replaceAll("*", ""))); } /** * Checks if a given ID corresponds to a runtime file path. * * @param id - The unique identifier for the runtime file. * @param pathOrId - The path or ID to check. * @returns `true` if the ID corresponds to the path or ID of a runtime file, otherwise `false`. */ isMatchingRuntimeId(id, pathOrId) { const resolvedPath = this.resolvePath(pathOrId); const resolvedId = this.resolveId(pathOrId); return !!(this.isRuntimeFile(pathOrId) && (resolvedPath && (resolvedPath === this.runtimeIdMap.get(id) || resolvedPath === this.runtimeIdMap.get(this.formatRuntimeId(id))) || resolvedId && (resolvedId === this.runtimeIdMap.get(id) || resolvedId === this.runtimeIdMap.get(this.formatRuntimeId(id))))); } /** * Lists all runtime files in the virtual file system. * * @returns A promise that resolves to an array of runtime files. */ async listRuntimeFiles() { const runtimeFiles = []; for (const [id, path] of this.runtimeIdMap.entries()) { const contents = await this.readFile(path); if (contents) { runtimeFiles.push({ id: this.formatRuntimeId(id), path, contents }); } } return runtimeFiles; } /** * Lists files in a given path. * * @param path - The path to list files from. * @param options - Options for listing files, such as encoding and recursion. * @returns An array of file names in the specified path. */ readdirSync(path, options = "utf8") { return this.resolveFS(path).readdirSync(chunkXTI73WJP_cjs.toFilePath(path), options); } /** * Removes a file in the virtual file system (VFS). * * @param path - The path to create the directory at. */ unlinkSync(path, options) { const formattedPath = chunkXTI73WJP_cjs.toFilePath(path); if (!this.fileExistsSync(path)) { return; } this.#log(types.LogLevelLabel.TRACE, `Synchronously removing file: ${formattedPath}`); this.resolveFS(path, options).unlinkSync(formattedPath); this.#cachedFS.delete(formattedPath); this.clearResolverCache(formattedPath); } /** * Removes a file in the virtual file system (VFS). * * @param path - The path to create the directory at. */ async unlink(path, options) { const formattedPath = chunkXTI73WJP_cjs.toFilePath(path); if (!this.fileExistsSync(path)) { return; } this.#log(types.LogLevelLabel.TRACE, `Removing file: ${formattedPath}`); if (isFunction.isFunction(this.resolveFS(path, options).promises.unlink)) { await this.resolveFS(path, options).promises.unlink(formattedPath); this.#cachedFS.delete(formattedPath); this.clearResolverCache(formattedPath); } else { this.unlinkSync(formattedPath, options); } } /** * Removes a directory in the virtual file system (VFS). * * @param path - The path to create the directory at. * @param options - Options for creating the directory. */ rmdirSync(path, options = {}) { const formattedPath = chunkXTI73WJP_cjs.toFilePath(path); if (!this.directoryExistsSync(path)) { return; } this.#log(types.LogLevelLabel.TRACE, `Synchronously removing directory: ${formattedPath}`); this.resolveFS(path, options).rmdirSync(formattedPath, defu__default.default(options, { recursive: true })); this.#cachedFS.delete(formattedPath); this.clearResolverCache(formattedPath); } /** * Removes a directory in the virtual file system (VFS). * * @param path - The path to create the directory at. * @param options - Options for creating the directory. * @returns A promise that resolves to the path of the created directory, or undefined if the directory could not be created. */ async rmdir(path, options = {}) { const formattedPath = chunkXTI73WJP_cjs.toFilePath(path); if (!this.directoryExistsSync(path)) { return; } this.#log(types.LogLevelLabel.TRACE, `Removing directory: ${formattedPath}`); if (isFunction.isFunction(this.resolveFS(path, options).promises.rm)) { await this.resolveFS(path, options).promises.rm(formattedPath, defu__default.default(options, { force: true, recursive: true })); this.#cachedFS.delete(formattedPath); this.clearResolverCache(formattedPath); } else { this.rmdirSync(formattedPath, defu__default.default(options ?? {}, { force: true, recursive: true })); } } /** * Removes a file in the virtual file system (VFS). * * @param path - The path to the file to remove. * @param options - Options for removing the file. * @returns A promise that resolves when the file is removed. */ async rm(path, options = {}) { this.#log(types.LogLevelLabel.TRACE, `Removing: ${chunkXTI73WJP_cjs.toFilePath(path)}`); if (this.directoryExistsSync(path)) { return this.rmdir(path, options); } return this.unlink(path, options); } /** * Creates a directory in the virtual file system (VFS). * * @param path - The path to create the directory at. * @param options - Options for creating the directory. * @returns A promise that resolves to the path of the created directory, or undefined if the directory could not be created. */ mkdirSync(path, options = {}) { const filePath = chunkXTI73WJP_cjs.toFilePath(path); this.clearResolverCache(filePath); return this.resolveFS(filePath, options).mkdirSync(filePath, defu__default.default(options ?? {}, { recursive: true })); } /** * Creates a directory in the virtual file system (VFS). * * @param path - The path to create the directory at. * @param options - Options for creating the directory. * @returns A promise that resolves to the path of the created directory, or undefined if the directory could not be created. */ async mkdir(path, options = {}) { let result; const filePath = chunkXTI73WJP_cjs.toFilePath(path); if (isFunction.isFunction(this.resolveFS(filePath, options).promises.mkdir)) { result = await this.resolveFS(filePath, options).promises.mkdir(filePath, defu__default.default(options ?? {}, { recursive: true })); } else { result = this.resolveFS(filePath, options).mkdirSync(filePath, defu__default.default(options ?? {}, { recursive: true })); } this.clearResolverCache(filePath); return result; } /** * Lists files in a given path. * * @param path - The path to list files from. * @param options - Options for listing files, such as encoding and recursion. * @returns An array of file names in the specified path. */ async readdir(path, options = "utf8") { return this.resolveFS(path).promises.readdir(chunkXTI73WJP_cjs.toFilePath(path), options); } /** * Asynchronously reads a file from the virtual file system (VFS). * * @param pathOrId - The path or ID of the file to read. * @returns A promise that resolves to the contents of the file as a string, or undefined if the file does not exist. */ async readFile(pathOrId, options = "utf8") { if (!pathOrId) { return void 0; } const filePath = this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId), { type: "file" }); if (filePath) { if (this.#cachedFS.has(filePath)) { return this.#cachedFS.get(filePath); } let result; if (isFunction.isFunction(this.resolveFS(filePath).promises.readFile)) { result = (await this.resolveFS(filePath).promises.readFile(filePath, options))?.toString("utf8"); } else { result = this.resolveFS(filePath).readFileSync(filePath, options); } const content = isBuffer.isBuffer(result) ? bufferToString.bufferToString(result) : result; this.#cachedFS.set(filePath, content); return content; } return void 0; } /** * Synchronously reads a file from the virtual file system (VFS). * * @param pathOrId - The path or ID of the file to read. * @returns The contents of the file as a string, or undefined if the file does not exist. */ readFileSync(pathOrId, options = "utf8") { if (!pathOrId) { return void 0; } const filePath = this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId), { type: "file" }); if (filePath) { if (this.#cachedFS.has(filePath)) { return this.#cachedFS.get(filePath); } const result = this.resolveFS(filePath).readFileSync(filePath, options); const content = isBuffer.isBuffer(result) ? bufferToString.bufferToString(result) : result; this.#cachedFS.set(filePath, content); return content; } return void 0; } /** * Writes a file to the virtual file system (VFS). * * @param file - The path to the file. * @param data - The contents of the file. * @param options - Optional parameters for writing the file. * @returns A promise that resolves when the file is written. */ async writeFile(file, data = "", options = "utf8") { const filePath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(file)); if (!this.directoryExistsSync(filePathFns.findFilePath(filePath))) { await this.mkdir(filePathFns.findFilePath(filePath), options); } this.#log(types.LogLevelLabel.TRACE, `Writing ${filePath} file to virtual file system (size: ${prettyBytes.prettyBytes(new Blob([ data ]).size)})`); this.#cachedFS.set(filePath, data.toString()); this.clearResolverCache(filePath); const ifs = this.resolveFS(filePath, options); if (isFunction.isFunction(ifs.promises.writeFile)) { return ifs.promises.writeFile(filePath, data, options); } return ifs.writeFileSync(filePath, data, options); } /** * Synchronously writes a file to the virtual file system (VFS). * * @param file - The file to write. * @param data - The contents of the file. * @param options - Optional parameters for writing the file. */ writeFileSync(file, data = "", options = "utf8") { const filePath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(file)); if (!this.directoryExistsSync(filePathFns.findFilePath(filePath))) { this.mkdirSync(filePathFns.findFilePath(filePath)); } this.#log(types.LogLevelLabel.TRACE, `Writing ${filePath} file to virtual file system (size: ${prettyBytes.prettyBytes(new Blob([ data ]).size)})`); this.#cachedFS.set(filePath, data.toString()); this.clearResolverCache(filePath); const writeStream = this.resolveFS(filePath, options).createWriteStream(filePath); try { writeStream.write(data); } finally { writeStream.close(); } } /** * Writes a runtime file to the virtual file system (VFS). * * @param id - The unique identifier for the runtime file. * @param path - The path to the runtime file. * @param contents - The contents of the runtime file. * @param options - Optional parameters for writing the runtime file. * @returns A promise that resolves when the file is written. */ async writeRuntimeFile(id, path, contents, options = {}) { const formattedId = this.formatRuntimeId(id); const absolutePath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(path)); this.runtimeIdMap.set(formattedId, absolutePath); let data = contents; if (!options.skipFormat) { data = await prettier.format(contents, { absolutePath, ...await prettier.resolveConfig(absolutePath) }); } const _options = defu__default.default(isSetString.isSetString(options) ? {} : options ?? {}, { encoding: isSetString.isSetString(options) ? options : "utf8", outputMode: "memory" }); this.#log(types.LogLevelLabel.DEBUG, `Writing runtime file ${absolutePath} (size: ${prettyBytes.prettyBytes(new Blob([ data ]).size)}) to ${this.resolveOutputMode(absolutePath, _options) === "fs" ? "disk" : "memory"}`); return this.writeFile(absolutePath, data, _options); } /** * Adds an entry file to the virtual file system. * * @param name - The file name or absolute path of the entry module. * @param contents - The contents of the entry file. * @param options - Optional parameters for writing the entry file. */ async writeEntryFile(name, contents, options = {}) { const absolutePath = this.formatAbsoluteFilePath(isFile.isAbsolutePath(chunkXTI73WJP_cjs.toFilePath(name)) ? chunkXTI73WJP_cjs.toFilePath(name) : chunkXTI73WJP_cjs.toFilePath(joinPaths.joinPaths(this.#context.entryPath, name))); let data = contents; if (!options.skipFormat) { data = await prettier.format(contents, { absolutePath, ...await prettier.resolveConfig(absolutePath) }); } const _options = defu__default.default(isSetString.isSetString(options) ? {} : options ?? {}, { encoding: isSetString.isSetString(options) ? options : "utf8", outputMode: "memory" }); this.#log(types.LogLevelLabel.DEBUG, `Writing entry file ${absolutePath} (size: ${prettyBytes.prettyBytes(new Blob([ data ]).size)}) to ${this.resolveOutputMode(absolutePath, _options) === "fs" ? "disk" : "memory"}`); return this.writeFile(absolutePath, data, _options); } /** * Writes a file to disk from the physical file system (on disk). * * @param path - The path to the file to write. * @param contents - The contents of the file to write. * @param options - Optional parameters for writing the file. * @returns A promise that resolves when the file is written. */ async writeFileToDisk(path, contents, options = {}) { const absolutePath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(path)); let data = contents; if (!options.skipFormat) { const resolvedConfig = await prettier.resolveConfig(absolutePath); if (resolvedConfig) { data = await prettier.format(contents, { absolutePath, ...resolvedConfig }); } } return this.writeFile(absolutePath, data, defu__default.default({ outputMode: "fs" }, isSetString.isSetString(options) ? {} : options ?? {}, { encoding: isSetString.isSetString(options) ? options : "utf8" })); } /** * Synchronously checks if a file exists in the virtual file system (VFS). * * @param pathOrId - The path or ID of the file to check. * @returns `true` if the file exists, otherwise `false`. */ existsSync(pathOrId) { return this.pathExistsSync(this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)) || chunkXTI73WJP_cjs.toFilePath(pathOrId)); } /** * Checks if a file exists in the virtual file system (VFS). * * @remarks * This is a base method used by {@link existsSync} - it does not try to resolve the path prior to checking if it exists or not. * * @param path - The path of the file to check. * @returns `true` if the file exists, otherwise `false`. */ fileExistsSync(path) { const formattedPath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(path)); return this.isValidRuntimeId(formattedPath) || this.#virtualFS.existsSync(formattedPath) && this.#virtualFS.lstatSync(formattedPath).isFile() || this.#fs.existsSync(formattedPath) && this.#fs.lstatSync(formattedPath).isFile() || this.resolveFS(path).existsSync(formattedPath) && this.resolveFS(path).lstatSync(formattedPath).isFile(); } /** * Checks if a directory exists in the virtual file system (VFS). * * @param path - The path of the directory to check. * @returns `true` if the directory exists, otherwise `false`. */ directoryExistsSync(path) { const formattedPath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(path)); return this.#virtualFS.existsSync(formattedPath) && this.#virtualFS.lstatSync(formattedPath).isDirectory() || this.#fs.existsSync(formattedPath) && this.#fs.lstatSync(formattedPath).isDirectory() || this.resolveFS(path).existsSync(formattedPath) && this.resolveFS(path).lstatSync(formattedPath).isDirectory(); } /** * Checks if a path exists in the virtual file system (VFS). * * @param path - The path to check. * @returns `true` if the path exists, otherwise `false`. */ pathExistsSync(path) { const formattedPath = this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(path)); return this.isValidRuntimeId(formattedPath) || this.#virtualFS.existsSync(formattedPath) || this.#fs.existsSync(formattedPath) || this.resolveFS(path).existsSync(formattedPath); } /** * Retrieves the status of a file in the virtual file system (VFS). * * @param pathOrId - The path or ID of the file to retrieve status for. * @returns A promise that resolves to the file's status information, or false if the file does not exist. */ async stat(pathOrId, options) { return this.resolveFS(pathOrId).promises.stat(this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)) || chunkXTI73WJP_cjs.toFilePath(pathOrId), options); } /** * Synchronously retrieves the status of a file in the virtual file system (VFS). * * @param pathOrId - The path or ID of the file to retrieve status for. * @returns The file's status information, or false if the file does not exist. */ statSync(pathOrId) { return this.resolveFS(pathOrId).statSync(this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)) || chunkXTI73WJP_cjs.toFilePath(pathOrId)); } /** * Retrieves the status of a symbolic link in the virtual file system (VFS). * * @param pathOrId - The path or ID of the symbolic link to retrieve status for. * @returns A promise that resolves to the symbolic link's status information, or false if the link does not exist. */ async lstat(pathOrId, options) { return this.resolveFS(pathOrId).promises.lstat(this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)) || chunkXTI73WJP_cjs.toFilePath(pathOrId), options); } /** * Synchronously retrieves the status of a symbolic link in the virtual file system (VFS). * * @param pathOrId - The path or ID of the symbolic link to retrieve status for. * @returns The symbolic link's status information, or false if the link does not exist. */ lstatSync(pathOrId, options) { return this.resolveFS(pathOrId).lstatSync(this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)) || chunkXTI73WJP_cjs.toFilePath(pathOrId), options); } /** * Resolves a path or ID to a runtime file id in the virtual file system. * * @param pathOrId - The path or id of the file to resolve. * @returns The resolved id of the runtime file if it exists, otherwise false. */ resolveId(pathOrId) { if (this.runtimeIdMap.has(this.formatRuntimeId(chunkXTI73WJP_cjs.toFilePath(pathOrId)))) { return this.formatRuntimeId(chunkXTI73WJP_cjs.toFilePath(pathOrId)); } const filePath = this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)); if (filePath) { return this.runtimeIdMap.keys().find((id) => this.runtimeIdMap.get(id) === filePath) || false; } return false; } /** * Resolves a path based on TypeScript's `tsconfig.json` paths. * * @see https://www.typescriptlang.org/tsconfig#paths * * @param path - The path to check. * @returns The resolved file path if it exists, otherwise undefined. */ resolveTsconfigPath(path) { if (this.#context.tsconfig.options.paths) { for (const tsconfigPathKey of Object.keys(this.#context.tsconfig.options.paths).filter((tsconfigPath) => path.startsWith(tsconfigPath.replaceAll("*", "")))) { const resolvedPath = this.#context.tsconfig.options.paths[tsconfigPathKey]?.find((tsconfigPath) => this.resolvePathName(joinPaths.joinPaths(this.#context.options.workspaceRoot, tsconfigPath.replaceAll("*", ""), path.replace(tsconfigPathKey.replaceAll("*", ""), ""))) || this.formatAbsoluteFilePath(tsconfigPath) === this.formatAbsoluteFilePath(path)); if (resolvedPath) { return this.formatAbsoluteFilePath(resolvedPath) === this.formatAbsoluteFilePath(path) ? this.formatAbsoluteFilePath(resolvedPath) : this.resolvePathName(joinPaths.joinPaths(this.#context.options.workspaceRoot, resolvedPath.replaceAll("*", ""), path.replace(tsconfigPathKey.replaceAll("*", ""), ""))); } } } return false; } /** * Resolves a path based on TypeScript's `tsconfig.json` paths. * * @see https://www.typescriptlang.org/tsconfig#paths * * @param path - The path to check. * @returns The resolved file path if it exists, otherwise undefined. */ resolveTsconfigPathPackage(path) { if (this.#context.tsconfig.options.paths) { const tsconfigPathKeys = Object.keys(this.#context.tsconfig.options.paths).filter((tsconfigPath) => path.startsWith(tsconfigPath.replaceAll("*", ""))); if (tsconfigPathKeys.length > 0 && tsconfigPathKeys[0]) { return tsconfigPathKeys[0].replace(/\/\*$/, ""); } } return false; } /** * Resolves a path or ID to its real path in the virtual file system (VFS). * * @param pathOrId - The path or ID to resolve. * @returns The resolved real path if it exists, otherwise undefined. */ realpathSync(pathOrId) { const filePath = this.resolvePath(chunkXTI73WJP_cjs.toFilePath(pathOrId)); if (!filePath) { throw new Error(`File not found: ${chunkXTI73WJP_cjs.toFilePath(pathOrId)}`); } return filePath; } /** * Resolves a path or ID parameter to a corresponding virtual file path in the virtual file system (VFS). * * @param pathOrId - The path or ID to resolve. * @param options - Optional parameters for resolving the path, such as whether to include the file extension. * @returns The resolved file path if it exists, otherwise undefined. */ resolvePath(pathOrId, options = {}) { const formattedPath = chunkXTI73WJP_cjs.toFilePath(pathOrId); const resolverKey = `${formattedPath}${options.withExtension ? "-ext" : ""}${options.paths ? `-${hash.hash(options.paths)}` : ""}${options.type ? `-${options.type}` : ""}`; if (this.#cachedResolver.has(resolverKey)) { return this.#cachedResolver.get(resolverKey); } else if (this.#cachedFS.has(formattedPath)) { return formattedPath; } let result = false; if (this.isValidRuntimeId(formattedPath)) { result = this.runtimeIdMap.get(this.formatRuntimeId(formattedPath)); } else { result = this.resolvePathName(formattedPath, options); } if (!result) { result = false; } else { result = chunkXTI73WJP_cjs.toFilePath(result); } if (result && options.withExtension === false) { return result.replace(/\.[m|c]?[t|j]sx?$/, ""); } this.#cachedResolver.set(resolverKey, result); return result; } /** * Formats a file path by removing the runtime prefix and leading null character. * * @param path - The file path to format. * @returns The formatted file path. */ formatFilePath(path) { if (!isSetString.isSetString(path)) { throw new Error(`Invalid path provided. Expected a string or a valid file path.`); } return path.replace(new RegExp(`^${RUNTIME_PREFIX}`), "").replace(/^\\0/, ""); } /** * Converts a relative path to an absolute path based on the workspace and project root. * * @param path - The relative path to convert. * @returns The absolute path. */ formatAbsoluteFilePath = /* @__PURE__ */ chunk3ONWID2V_cjs.__name((path) => { const formattedPath = this.formatFilePath(path); if (isFile.isAbsolutePath(formattedPath) || formattedPath.startsWith(this.#context.options.workspaceRoot)) { return formattedPath; } else if (formattedPath.startsWith(this.#context.options.projectRoot)) { return joinPaths.joinPaths(this.#context.options.workspaceRoot, formattedPath); } return formattedPath; }, "formatAbsoluteFilePath"); /** * Formats a runtime ID by removing the file extension and prepending the runtime prefix. * * @param id - The runtime ID to format. * @returns The formatted runtime ID. */ formatRuntimeId(id) { return `${RUNTIME_PREFIX}${this.formatFilePath(id).replace(/\.[m|c]?[t|j]sx?$/, "")}`; } /** * Resolves a path or ID parameter to a corresponding virtual file path in the virtual file system (VFS). * * @param pathOrId - The path or ID to resolve. * @returns The resolved file path if it exists, otherwise undefined. */ resolvePathName(pathOrId, options = {}) { if (pathOrId.startsWith(RUNTIME_PREFIX)) { return false; } if (isFile.isAbsolutePath(pathOrId)) { if (options.type === "file" ? this.fileExistsSync(pathOrId) : this.pathExistsSync(pathOrId)) { return pathOrId; } const result = chunkXTI73WJP_cjs.checkVariants(pathOrId, this); if (result) { return result; } } for (const path of this.resolveParentPaths(pathOrId, options.paths)) { const request = joinPaths.joinPaths(path, pathOrId); if (options.type === "file" ? this.fileExistsSync(pathOrId) : this.pathExistsSync(pathOrId)) { return request; } const result = chunkXTI73WJP_cjs.checkVariants(request, this); if (result) { return result; } } return false; } resolveParentPaths(request, current = []) { let paths = [ this.#context.options.workspaceRoot, joinPaths.joinPaths(this.#context.options.workspaceRoot, this.#context.options.projectRoot) ]; if (this.#context.tsconfig.options.paths) { paths = this.#context.tsconfig.options.paths ? Object.keys(this.#context.tsconfig.options.paths).filter((tsconfigPath) => request.startsWith(tsconfigPath.replaceAll("*", ""))).map((tsconfigPath) => this.#context.tsconfig.options.paths?.[tsconfigPath]).flat().reduce((ret, path) => { if (path && !ret.includes(joinPaths.joinPaths(this.#context.options.workspaceRoot, path))) { ret.push(joinPaths.joinPaths(this.#context.options.workspaceRoot, path)); } return ret; }, paths) : paths; } return paths.reduce((ret, path) => { if (!ret.includes(path)) { ret.push(path); } return ret; }, current.filter(Boolean).map((p) => this.formatAbsoluteFilePath(chunkXTI73WJP_cjs.toFilePath(p)))); } /** * Select the file system module to use for the operation based on the path or URL. * * @param pathOrUrl - The path to perform the file system operation on. * @param options - Options for the operation, such as output mode. * @returns The file system module used for the operation. */ resolveFS(pathOrUrl, options = {}) { const outputMode = this.resolveOutputMode(pathOrUrl, options); if (outputMode === "memory") { return this.#virtualFS; } else if (outputMode === "fs") { return this.#fs; } return this.#unifiedFS; } /** * Select the file system module to use for the operation based on the path or URL. * * @param pathOrUrl - The path to perform the file system operation on. * @param options - Options for the operation, such as output mode. * @returns The file system module used for the operation. */ resolveOutputMode(pathOrUrl, options = {}) { if (options.outputMode === "memory" && this.#context.options.output.outputMode !== "fs" && isParentPath.isParentPath(chunkXTI73WJP_cjs.toFilePath(pathOrUrl), this.#context.artifactsPath)) { return "memory"; } else if (options.outputMode === "fs" || this.#context.options.output.outputMode === "fs" || isParentPath.isParentPath(chunkXTI73WJP_cjs.toFilePath(pathOrUrl), this.#context.dataPath) || isParentPath.isParentPath(chunkXTI73WJP_cjs.toFilePath(pathOrUrl), this.#context.cachePath) || isParentPath.isParentPath(chunkXTI73WJP_cjs.toFilePath(pathOrUrl), joinPaths.joinPaths(this.#context.options.workspaceRoot, this.#context.options.output.outputPath))) { return "fs"; } return null; } /** * Clears the resolver cache for a given path. * * @param path - The path to clear the resolver cache for. */ clearResolverCache(path) { this.#cachedResolver.keys().filter((key) => key.startsWith(chunkXTI73WJP_cjs.toFilePath(path))).forEach((key) => this.#cachedResolver.delete(key)); } }; function createVfs(context) { const vfs = new VirtualFileSystem(context); return vfs; } chunk3ONWID2V_cjs.__name(createVfs, "createVfs"); function restoreVfs(context, serialized) { const vfs = new VirtualFileSystem(context, serialized); return vfs; } chunk3ONWID2V_cjs.__name(restoreVfs, "restoreVfs"); exports.RUNTIME_PREFIX = RUNTIME_PREFIX; exports.VirtualFileSystem = VirtualFileSystem; exports.createVfs = createVfs; exports.restoreVfs = restoreVfs; //# sourceMappingURL=chunk-4LPHTBJM.cjs.map //# sourceMappingURL=chunk-4LPHTBJM.cjs.map