{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/discovery/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAM7B,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,2BAA2B,QAAkB,CAAC;AAC3D,eAAO,MAAM,qCAAqC,QAAc,CAAC;AAEjE,MAAM,WAAW,6BAA6B;IAC7C,iBAAiB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE,iBAAiB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,iBAAiB;IACjC,cAAc,EAAE,gBAAgB,CAAC;IACjC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,KAAK,EAAE,yBAAyB,CAAC;CACjC;AAeD;;;;GAIG;AACH,qBAAa,sBAAsB;IAClC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgD;IAClF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgD;IAClF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsC;IAErE,YAAY,OAAO,EAAE,6BAA6B,EAWjD;IAED,4EAA4E;IACtE,QAAQ,CAAC,eAAe,EAAE,SAAS,gBAAgB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAkCzF;IAED,4EAA4E;IACtE,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAqBzE;CACD","sourcesContent":["import type { EvoPackManifest } from \"../pack/pack.ts\";\nimport { parseEvoPackManifest } from \"../pack/pack.ts\";\nimport { canonicalJson } from \"../storage.ts\";\nimport {\n\ttype EvoPackRegistryEntry,\n\ttype EvoPackRegistryEntryTrust,\n\ttype EvoRawFileSource,\n\ttype EvoTrustedRegistrySigner,\n\tparseEvoPackRegistryEntry,\n\tparseEvoPackRegistryIndex,\n\tparseEvoRawFileSource,\n\tvalidateTrustedEvoRegistrySigners,\n\tverifyEvoPackRegistryEntryTrust,\n} from \"./registry.ts\";\n\nexport const EVO_PACK_REGISTRY_MAX_BYTES = 2 * 1024 * 1024;\nexport const EVO_DISCOVERY_PACK_MANIFEST_MAX_BYTES = 1024 * 1024;\n\nexport interface EvoPackDiscoveryClientOptions {\n\treadRegistryIndex: (source: EvoRawFileSource) => Promise<string>;\n\tfetchPackManifest: (source: EvoRawFileSource) => Promise<string>;\n\ttrustedSigners?: readonly EvoTrustedRegistrySigner[];\n}\n\nexport interface EvoDiscoveredPack {\n\tregistrySource: EvoRawFileSource;\n\tentry: EvoPackRegistryEntry;\n\ttrust: EvoPackRegistryEntryTrust;\n}\n\nfunction parseJson(text: string, label: string): unknown {\n\ttry {\n\t\treturn JSON.parse(text) as unknown;\n\t} catch {\n\t\tthrow new Error(`${label} is not valid JSON`);\n\t}\n}\n\nfunction assertByteLimit(text: string, maximumBytes: number, label: string): void {\n\tconst bytes = Buffer.byteLength(text, \"utf8\");\n\tif (bytes > maximumBytes) throw new Error(`${label} exceeds ${maximumBytes} bytes`);\n}\n\n/**\n * Read-only discovery over caller-provided transports. The client has no\n * ambient network or filesystem access: registry reads and manifest fetches\n * are explicit injected functions.\n */\nexport class EvoPackDiscoveryClient {\n\tprivate readonly readRegistryIndex: (source: EvoRawFileSource) => Promise<string>;\n\tprivate readonly fetchManifestText: (source: EvoRawFileSource) => Promise<string>;\n\tprivate readonly trustedSigners: readonly EvoTrustedRegistrySigner[];\n\n\tconstructor(options: EvoPackDiscoveryClientOptions) {\n\t\tif (typeof options.readRegistryIndex !== \"function\") {\n\t\t\tthrow new Error(\"discovery readRegistryIndex must be a function\");\n\t\t}\n\t\tif (typeof options.fetchPackManifest !== \"function\") {\n\t\t\tthrow new Error(\"discovery fetchPackManifest must be a function\");\n\t\t}\n\t\tthis.readRegistryIndex = options.readRegistryIndex;\n\t\tthis.fetchManifestText = options.fetchPackManifest;\n\t\tthis.trustedSigners = [...(options.trustedSigners ?? [])];\n\t\tvalidateTrustedEvoRegistrySigners(this.trustedSigners);\n\t}\n\n\t/** Read, validate, and merge registry indexes without downloading packs. */\n\tasync discover(registrySources: readonly EvoRawFileSource[]): Promise<EvoDiscoveredPack[]> {\n\t\tconst discovered: EvoDiscoveredPack[] = [];\n\t\tconst registryKeys = new Set<string>();\n\t\tconst packIdentities = new Set<string>();\n\t\tconst packIntegrities = new Set<string>();\n\t\tfor (const sourceValue of registrySources) {\n\t\t\tconst registrySource = parseEvoRawFileSource(sourceValue);\n\t\t\tconst registryKey = canonicalJson(registrySource);\n\t\t\tif (registryKeys.has(registryKey)) {\n\t\t\t\tthrow new Error(`duplicate pack registry source: ${registrySource.rawUrl}`);\n\t\t\t}\n\t\t\tregistryKeys.add(registryKey);\n\t\t\tconst text = await this.readRegistryIndex(registrySource);\n\t\t\tif (typeof text !== \"string\") throw new Error(\"discovery readRegistryIndex must return a string\");\n\t\t\tassertByteLimit(text, EVO_PACK_REGISTRY_MAX_BYTES, `pack registry ${registrySource.rawUrl}`);\n\t\t\tconst index = parseEvoPackRegistryIndex(parseJson(text, `pack registry ${registrySource.rawUrl}`));\n\t\t\tfor (const entry of index.entries) {\n\t\t\t\tconst identity = `${entry.name}\\0${entry.version}`;\n\t\t\t\tif (packIdentities.has(identity)) {\n\t\t\t\t\tthrow new Error(`discovery found duplicate pack version: ${entry.name}@${entry.version}`);\n\t\t\t\t}\n\t\t\t\tif (packIntegrities.has(entry.integrity)) {\n\t\t\t\t\tthrow new Error(`discovery found duplicate pack integrity: ${entry.integrity}`);\n\t\t\t\t}\n\t\t\t\tpackIdentities.add(identity);\n\t\t\t\tpackIntegrities.add(entry.integrity);\n\t\t\t\tdiscovered.push({\n\t\t\t\t\tregistrySource,\n\t\t\t\t\tentry,\n\t\t\t\t\ttrust: verifyEvoPackRegistryEntryTrust(entry, this.trustedSigners),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn discovered;\n\t}\n\n\t/** Fetch and cross-check a discovered pack's declared manifest metadata. */\n\tasync fetchPackManifest(pack: EvoDiscoveredPack): Promise<EvoPackManifest> {\n\t\tconst entry = parseEvoPackRegistryEntry(pack.entry);\n\t\tverifyEvoPackRegistryEntryTrust(entry, this.trustedSigners);\n\t\tconst text = await this.fetchManifestText(entry.source);\n\t\tif (typeof text !== \"string\") throw new Error(\"discovery fetchPackManifest must return a string\");\n\t\tassertByteLimit(text, EVO_DISCOVERY_PACK_MANIFEST_MAX_BYTES, `pack manifest ${entry.source.rawUrl}`);\n\t\tconst manifest = parseEvoPackManifest(parseJson(text, `pack manifest ${entry.source.rawUrl}`));\n\t\tif (\n\t\t\tmanifest.name !== entry.name ||\n\t\t\tmanifest.version !== entry.version ||\n\t\t\tmanifest.integrity !== entry.integrity\n\t\t) {\n\t\t\tthrow new Error(`pack manifest metadata does not match registry entry ${entry.name}@${entry.version}`);\n\t\t}\n\t\tif (entry.author !== undefined && manifest.author !== entry.author) {\n\t\t\tthrow new Error(`pack manifest author does not match registry entry ${entry.name}@${entry.version}`);\n\t\t}\n\t\tif (entry.description !== undefined && manifest.description !== entry.description) {\n\t\t\tthrow new Error(`pack manifest description does not match registry entry ${entry.name}@${entry.version}`);\n\t\t}\n\t\treturn manifest;\n\t}\n}\n"]}