/** * Package Resolver * Maps model names to package names using descriptor XML files * and filesystem scanning. * * In D365FO, the metadata directory structure is: * {Root}/{PackageName}/{ModelName}/AxClass/... * {Root}/{PackageName}/Descriptor/{ModelName}.xml * * The descriptor XML contains (package name) and (model name). * A single package (e.g., "CustomExtensions") can contain many models * (e.g., "Contoso Utilities", "Contoso Reporting"). * * This resolver builds a map from model name -> package info by: * 1. Reading descriptor XML files (primary strategy) * 2. Falling back to filesystem scanning for directories with AOT-type folders */ export interface ResolvedPackage { packageName: string; modelName: string; rootPath: string; } export declare class PackageResolver { private roots; private modelToPackageMap; /** Lowercase lookup mirror of modelToPackageMap for case-insensitive resolve(). */ private lowercaseLookup; private buildPromise; constructor(roots: string[]); /** * Resolve a model name to its package name. * Returns null if the model cannot be found in any root. * * The direct probe first, because buildMap() is a sweep of the WHOLE metadata * root and every write path calls this. On the reference VM's 214-package * PackagesLocalDirectory the sweep is ~5 s with the directory metadata already * cached, and every write pays it again on a fresh instance — a create in * benchmark run d79f62a3 took 341 s and reported all of it as `(unmeasured)`. * `/` answers the same question in two readdirs. * * When two packages declare the same model name the sweep's answer is * whichever directory readdir happened to return first; the probe's is the * package named after the model, which is the better of the two anyway. */ resolve(modelName: string): Promise; /** * `/` — the layout every D365FO package uses unless someone * deliberately named the package differently from the model. * * Reads the same two things buildMap() would for that one directory: the * descriptor (authoritative for both names) and, failing that, the presence of * an AOT folder one level down. Anything unexpected returns null and lets the * full sweep decide, so this can only make the common case cheaper — never * change what an unusual layout resolves to. */ private probeDirect; /** * Resolve with an explicit package name (bypasses lookup). */ resolveWithPackage(modelName: string, packageName: string): ResolvedPackage; /** * Get all known model-to-package mappings. */ getAllMappings(): Promise>; /** * Invalidate the cache to force a rescan. */ clearCache(): void; private ensureBuilt; private buildMap; private static readonly AOT_FOLDERS; private hasAotTypeFolder; } //# sourceMappingURL=packageResolver.d.ts.map