UNPKG

mlld

Version:

mlld: a modular prompt scripting language

276 lines (273 loc) 8.28 kB
import { logger } from './chunk-XGMRAGIT.mjs'; import { MlldResolutionError, MlldFileNotFoundError } from './chunk-YMCO2JI3.mjs'; import { __name, __publicField } from './chunk-OMKLS24H.mjs'; import * as path from 'path'; import * as os from 'os'; async function findProjectRoot(startPath, fileSystem) { let currentDir = path.resolve(startPath); const homeDir = os.homedir(); logger.debug(`Finding project root from: ${startPath}`); while (currentDir !== homeDir && currentDir !== path.dirname(currentDir)) { const lockFilePath = path.join(currentDir, "mlld.lock.json"); if (await fileSystem.exists(lockFilePath)) { logger.debug(`Found mlld.lock.json at: ${currentDir}`); return currentDir; } const fallbackIndicators = [ "package.json", ".git", "pyproject.toml", "Cargo.toml" ]; for (const indicator of fallbackIndicators) { if (await fileSystem.exists(path.join(currentDir, indicator))) { logger.warn(`Found project root at ${currentDir} but mlld.lock.json is missing`); return currentDir; } } currentDir = path.dirname(currentDir); } logger.debug(`No project root found, using original path: ${startPath}`); return startPath; } __name(findProjectRoot, "findProjectRoot"); // core/resolvers/ProjectPathResolver.ts var _ProjectPathResolver = class _ProjectPathResolver { constructor(fileSystem) { __publicField(this, "fileSystem"); __publicField(this, "name"); __publicField(this, "description"); __publicField(this, "type"); __publicField(this, "capabilities"); this.fileSystem = fileSystem; this.name = "base"; this.description = "Resolves @base references to project root files"; this.type = "io"; this.capabilities = { io: { read: true, write: false, list: false }, contexts: { import: true, path: true, output: false }, supportedContentTypes: [ "text", "module" ], defaultContentType: "text", priority: 1, cache: { strategy: "none" } // Project path is static }; } canResolve(ref, config) { return ref.startsWith("@base") || !!config; } /** * Resolve a @base reference */ async resolve(ref, config) { let basePath = config?.basePath; if (!basePath || !await this.isProjectRoot(basePath)) { logger.debug(`Detecting project root (basePath: ${basePath})`); basePath = await this.findProjectRootFromCwd(); } if (!basePath) { throw new MlldResolutionError("ProjectPathResolver: Unable to determine project root. This usually means the resolver registry was not properly configured. Check that @base prefix is mapped to base resolver with basePath.", { reference: ref, availableConfig: Object.keys(config || {}) }); } if (!config || !config.context || config.context === "variable") { if (ref === "@base" || ref === "base") { return { content: basePath, contentType: "text", metadata: { source: "base", timestamp: /* @__PURE__ */ new Date() } }; } } if (config.context === "path") { let relativePath; if (ref.startsWith("@base/")) { relativePath = ref.substring("@base/".length); } else if (ref.startsWith("@base")) { relativePath = ref.substring("@base".length); } else { relativePath = ref; } if (relativePath.startsWith("/")) { relativePath = relativePath.substring(1); } if (!relativePath) { return { content: basePath, contentType: "text", metadata: { source: "base", timestamp: /* @__PURE__ */ new Date() } }; } const fullPath = path.resolve(basePath, relativePath); const normalizedBasePath = path.resolve(basePath); const normalizedFullPath = path.resolve(fullPath); if (!normalizedFullPath.startsWith(normalizedBasePath)) { throw new MlldResolutionError(`Path outside project directory: ${relativePath}`, {}); } if (!await this.fileSystem.exists(fullPath)) { if (!path.extname(fullPath)) { const withMld = fullPath + ".mld"; if (await this.fileSystem.exists(withMld)) { const content = await this.fileSystem.readFile(withMld); const contentType = await this.detectContentType(withMld, content); return { content, contentType, metadata: { source: withMld, timestamp: /* @__PURE__ */ new Date(), originalRef: ref } }; } } throw new MlldFileNotFoundError(`File not found: ${fullPath}`, { path: fullPath }); } try { const content = await this.fileSystem.readFile(fullPath); const contentType = await this.detectContentType(fullPath, content); return { content, contentType, metadata: { source: fullPath, timestamp: /* @__PURE__ */ new Date(), originalRef: ref } }; } catch (error) { throw new MlldFileNotFoundError(`Failed to read file: ${fullPath}`, { path: fullPath }); } } if (config.context === "import") { const result = await this.resolve(ref, { ...config, context: "path" }); if (result.contentType !== "module") { throw new MlldResolutionError(`Import target is not a module: ${ref}`, {}); } return result; } throw new MlldResolutionError(`base resolver does not support context: ${config.context}`, {}); } /** * Validate resolver configuration */ validateConfig(config) { const errors = []; if (!config) { errors.push("Configuration is required"); return errors; } if (!config.basePath) { errors.push("basePath is required"); } else if (typeof config.basePath !== "string") { errors.push("basePath must be a string"); } return errors; } /** * Check if an operation is allowed */ async checkAccess(ref, operation, config) { if (operation === "write" && config?.readonly) { return false; } return operation === "read"; } /** * Detect content type based on file extension and content */ async detectContentType(filePath, content) { if (filePath.endsWith(".mld") || filePath.endsWith(".mlld")) { return "module"; } if (filePath.endsWith(".json")) { return "data"; } try { const { parse } = await import('./parser-X2XXTU6D.mjs'); const result = await parse(content); if (result.success && this.hasModuleExports(result.ast)) { return "module"; } } catch { } try { JSON.parse(content); return "data"; } catch { } return "text"; } /** * Check if AST has module exports */ hasModuleExports(ast) { if (!ast || !Array.isArray(ast)) return false; return ast.some((node) => node && node.type === "Directive" && [ "var", "exe", "path" ].includes(node.kind)); } /** * Check if a path is likely a project root */ async isProjectRoot(path3) { const indicators = [ "package.json", ".git", "mlld.config.json", "mlld.lock.json" ]; for (const indicator of indicators) { if (await this.fileSystem.exists(path3 + "/" + indicator)) { return true; } } return false; } /** * Find project root from current working directory */ async findProjectRootFromCwd() { try { const projectRoot = await findProjectRoot(process.cwd(), this.fileSystem); return projectRoot; } catch (error) { logger.warn("Failed to find project root:", error); return null; } } }; __name(_ProjectPathResolver, "ProjectPathResolver"); var ProjectPathResolver = _ProjectPathResolver; export { ProjectPathResolver, findProjectRoot }; //# sourceMappingURL=chunk-P46TIXQR.mjs.map //# sourceMappingURL=chunk-P46TIXQR.mjs.map