{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/components/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAkC,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAqBxF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAiB,GAAG,IAAI,CAIhF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAkB,GAAG,IAAI,CAI3E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAyB,GAAG,IAAI,CAIvF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAuE9E","sourcesContent":["import { basename } from \"node:path\";\nimport { isDigest } from \"../bundle/schema.ts\";\nimport type { EvoComponentActivationBoundary, EvoComponentManifest } from \"../types.ts\";\n\nconst COMPONENT_ID_PATTERN = /^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/;\nconst ABI_ID_PATTERN = /^[a-z][a-z0-9-]*\\/v[1-9][0-9]*$/;\nconst CAPABILITY_PATTERN = /^[a-z][a-z0-9]*(?:[._:-][a-z0-9]+)*$/;\nconst ACTIVATION_BOUNDARIES = new Set<EvoComponentActivationBoundary>([\"turn\", \"session\", \"process\", \"invocation\"]);\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be an object`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction exactKeys(record: Record<string, unknown>, allowed: readonly string[], label: string): void {\n\tconst allowedKeys = new Set(allowed);\n\tfor (const key of Object.keys(record)) {\n\t\tif (!allowedKeys.has(key)) throw new Error(`${label} has unknown key: ${key}`);\n\t}\n}\n\nexport function assertEvoComponentId(value: string, label = \"component id\"): void {\n\tif (!COMPONENT_ID_PATTERN.test(value) || value.length > 128) {\n\t\tthrow new Error(`${label} must be a lowercase component identifier`);\n\t}\n}\n\nexport function assertEvoAbiId(value: string, label = \"component ABI\"): void {\n\tif (!ABI_ID_PATTERN.test(value) || value.length > 128) {\n\t\tthrow new Error(`${label} must have the form surface/vN`);\n\t}\n}\n\nexport function assertEvoCapability(value: string, label = \"component capability\"): void {\n\tif (!CAPABILITY_PATTERN.test(value) || value.length > 128) {\n\t\tthrow new Error(`${label} is invalid`);\n\t}\n}\n\nexport function parseEvoComponentManifest(value: unknown): EvoComponentManifest {\n\tconst record = asRecord(value, \"component manifest\");\n\texactKeys(\n\t\trecord,\n\t\t[\n\t\t\t\"schemaVersion\",\n\t\t\t\"id\",\n\t\t\t\"version\",\n\t\t\t\"artifactDigest\",\n\t\t\t\"entrypointSha256\",\n\t\t\t\"abi\",\n\t\t\t\"activationBoundary\",\n\t\t\t\"capabilities\",\n\t\t\t\"entrypoint\",\n\t\t],\n\t\t\"component manifest\",\n\t);\n\tif (record.schemaVersion !== 1) throw new Error(\"component manifest schemaVersion must be 1\");\n\tif (typeof record.id !== \"string\") throw new Error(\"component manifest id must be a string\");\n\tassertEvoComponentId(record.id, \"component manifest id\");\n\tif (\n\t\ttypeof record.version !== \"string\" ||\n\t\t!record.version ||\n\t\trecord.version.length > 128 ||\n\t\t!/^[A-Za-z0-9][A-Za-z0-9._+-]*$/.test(record.version)\n\t) {\n\t\tthrow new Error(\"component manifest version is invalid\");\n\t}\n\tif (typeof record.artifactDigest !== \"string\" || !isDigest(record.artifactDigest)) {\n\t\tthrow new Error(\"component manifest artifactDigest must be a digest\");\n\t}\n\tif (typeof record.entrypointSha256 !== \"string\" || !isDigest(record.entrypointSha256)) {\n\t\tthrow new Error(\"component manifest entrypointSha256 must be a digest\");\n\t}\n\tif (typeof record.abi !== \"string\") throw new Error(\"component manifest abi must be a string\");\n\tassertEvoAbiId(record.abi, \"component manifest abi\");\n\tif (\n\t\ttypeof record.activationBoundary !== \"string\" ||\n\t\t!ACTIVATION_BOUNDARIES.has(record.activationBoundary as EvoComponentActivationBoundary)\n\t) {\n\t\tthrow new Error(\"component manifest activationBoundary is invalid\");\n\t}\n\tif (!Array.isArray(record.capabilities) || record.capabilities.some((entry) => typeof entry !== \"string\")) {\n\t\tthrow new Error(\"component manifest capabilities must be a string array\");\n\t}\n\tconst capabilities = record.capabilities as string[];\n\tfor (const [index, capability] of capabilities.entries()) {\n\t\tassertEvoCapability(capability, `component manifest capabilities[${index}]`);\n\t}\n\tif (new Set(capabilities).size !== capabilities.length) {\n\t\tthrow new Error(\"component manifest capabilities must not contain duplicates\");\n\t}\n\tif (\n\t\ttypeof record.entrypoint !== \"string\" ||\n\t\t!record.entrypoint.endsWith(\".mjs\") ||\n\t\tbasename(record.entrypoint) !== record.entrypoint ||\n\t\trecord.entrypoint.length > 128\n\t) {\n\t\tthrow new Error(\"component manifest entrypoint must be a direct .mjs file\");\n\t}\n\treturn {\n\t\tschemaVersion: 1,\n\t\tid: record.id,\n\t\tversion: record.version,\n\t\tartifactDigest: record.artifactDigest,\n\t\tentrypointSha256: record.entrypointSha256,\n\t\tabi: record.abi,\n\t\tactivationBoundary: record.activationBoundary as EvoComponentActivationBoundary,\n\t\tcapabilities: [...capabilities].sort(),\n\t\tentrypoint: record.entrypoint,\n\t};\n}\n"]}