UNPKG

typia

Version:

Superfast runtime validators with only one line

133 lines (132 loc) 5.14 kB
import fs from "fs"; import path from "path"; //#region src/executable/FileSystemIdentity.ts let FileSystemIdentity; (function(_FileSystemIdentity) { function create(caseSensitive, pathApi = path) { const fold = (value) => caseSensitive ? value : value.toLowerCase(); const filesystemKey = (file) => fold(pathApi.normalize(file)); return { caseSensitive, contains: (file, directory) => { const fileKey = filesystemKey(pathApi.resolve(file)); const directoryKey = filesystemKey(pathApi.resolve(directory)); const prefix = directoryKey.endsWith(pathApi.sep) ? directoryKey : `${directoryKey}${pathApi.sep}`; return fileKey === directoryKey || fileKey.startsWith(prefix); }, filesystemKey, isDeclarationFile: (file) => DTS_PATTERN.test(fold(pathApi.basename(file))), isSamePath: (x, y) => filesystemKey(x) === filesystemKey(y), isSupportedExtension: (file) => { const filename = fold(pathApi.basename(file)); return TS_PATTERN.test(filename) && DTS_PATTERN.test(filename) === false; }, projectFileKey: fold }; } _FileSystemIdentity.create = create; class Policy { observe(caseSensitive, location) { if (caseSensitive === void 0) return; if (this.caseSensitive_ === void 0) { this.caseSensitive_ = caseSensitive; this.location_ = location; } else if (this.caseSensitive_ !== caseSensitive) throw new URIError(`Error on TypiaGenerateWizard.generate(): inconsistent filesystem case behavior between ${this.location_} and ${location}.`); } get() { if (this.caseSensitive_ === void 0) throw new URIError("Error on TypiaGenerateWizard.generate(): unable to determine filesystem case behavior for this run."); return create(this.caseSensitive_); } } _FileSystemIdentity.Policy = Policy; async function inspectDirectory(directory) { const names = await fs.promises.readdir(directory); const entries = new Set(names); for (const name of names) { const alternate = alternateCase(name); if (alternate === void 0) continue; if (entries.has(alternate)) return true; try { await fs.promises.lstat(path.join(directory, alternate)); return false; } catch (error) { if (isMissingFileError(error)) return true; throw error; } } } _FileSystemIdentity.inspectDirectory = inspectDirectory; async function probeDirectory(directory) { const inspected = await inspectDirectory(directory); if (inspected !== void 0) return inspected; for (let attempt = 0; attempt < 10; ++attempt) { const name = `.typia-case-probe-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`.toLowerCase(); const original = path.join(directory, name); const alternate = path.join(directory, name.toUpperCase()); let handle; try { handle = await fs.promises.open(original, "wx"); } catch (error) { if (isAlreadyExistsError(error)) continue; throw new URIError(`Error on TypiaGenerateWizard.generate(): unable to probe filesystem case behavior at ${directory}: ${formatUnknownError(error)}`); } let closed = false; try { await handle.close(); closed = true; try { await fs.promises.lstat(alternate); return false; } catch (error) { if (isMissingFileError(error)) return true; throw error; } } finally { let cleanupError; if (closed === false) try { await handle.close(); } catch (error) { cleanupError = error; } try { await fs.promises.unlink(original); } catch (error) { if (isMissingFileError(error) === false) cleanupError ??= error; } if (cleanupError !== void 0) throw new URIError(`Error on TypiaGenerateWizard.generate(): unable to clean filesystem case probe ${original}: ${formatUnknownError(cleanupError)}`); } } throw new URIError(`Error on TypiaGenerateWizard.generate(): unable to reserve a filesystem case probe at ${directory}.`); } _FileSystemIdentity.probeDirectory = probeDirectory; function identityKey(stat, realpath) { return stat.ino === BigInt(0) ? `path:${path.normalize(realpath)}` : `inode:${stat.dev}:${stat.ino}`; } _FileSystemIdentity.identityKey = identityKey; function alternateCase(name) { let changed = false; let output = ""; for (const character of name) if (character >= "a" && character <= "z") { output += character.toUpperCase(); changed = true; } else if (character >= "A" && character <= "Z") { output += character.toLowerCase(); changed = true; } else output += character; return changed ? output : void 0; } function isAlreadyExistsError(error) { return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST"; } function isMissingFileError(error) { return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT"; } function formatUnknownError(error) { return error instanceof Error ? error.message : String(error); } })(FileSystemIdentity || (FileSystemIdentity = {})); const TS_PATTERN = /\.[cm]?tsx?$/; const DTS_PATTERN = /\.d\.[cm]?tsx?$/; //#endregion export { FileSystemIdentity }; //# sourceMappingURL=FileSystemIdentity.mjs.map