{"version":3,"sources":["../src/artifact-path.ts"],"names":[],"mappings":";;;AASA,IAAM,SAAA,GACJ,sGAAA;AAEK,SAAS,oBAAA,CACd,SACA,OAAA,EACoC;AACpC,EAAA,MAAM,OAAA,GAAU,cAAc,OAAO,CAAA;AACrC,EAAA,IAAI,CAAC,OAAA,CAAQ,EAAA,EAAI,OAAO,WAAA,CAAY,SAAS,OAAO,CAAA;AAEpD,EAAA,MAAM,UAAA,GAAa,qBAAA,CAAsB,OAAA,CAAQ,KAAK,CAAA;AACtD,EAAA,IAAI,CAAC,UAAA,EAAY,OAAO,WAAA,CAAY,SAAS,OAAO,CAAA;AAEpD,EAAA,OAAO,GAAG,UAAU,CAAA;AACtB;AAEA,SAAS,cAAc,OAAA,EAAuC;AAC5D,EAAA,IAAI,OAAA,GAAU,OAAA;AACd,EAAA,IAAI;AACF,IAAA,KAAA,IAAS,IAAA,GAAO,CAAA,EAAG,IAAA,GAAO,CAAA,EAAG,QAAQ,CAAA,EAAG;AACtC,MAAA,MAAM,IAAA,GAAO,mBAAmB,OAAO,CAAA;AACvC,MAAA,IAAI,SAAS,OAAA,EAAS;AACtB,MAAA,OAAA,GAAU,IAAA;AAAA,IACZ;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAI,IAAI,CAAA;AAAA,EACjB;AACA,EAAA,OAAO,GAAG,OAAO,CAAA;AACnB;AAEA,SAAS,sBAAsB,OAAA,EAAgC;AAC7D,EAAA,IAAI,QAAQ,MAAA,KAAW,CAAA,IAAK,QAAQ,QAAA,CAAS,KAAK,GAAG,OAAO,IAAA;AAC5D,EAAA,IAAI,OAAA,CAAQ,WAAW,GAAG,CAAA,IAAK,kBAAkB,IAAA,CAAK,OAAO,GAAG,OAAO,IAAA;AAEvE,EAAA,MAAM,WAAW,OAAA,CAAQ,UAAA,CAAW,MAAM,GAAG,CAAA,CAAE,MAAM,GAAG,CAAA;AACxD,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,OAAA,KAAY,MAAM,OAAO,IAAA;AAC7B,IAAA,IAAI,OAAA,KAAY,EAAA,IAAM,OAAA,KAAY,GAAA,EAAK;AACvC,IAAA,UAAA,CAAW,KAAK,OAAO,CAAA;AAAA,EACzB;AACA,EAAA,OAAO,WAAW,MAAA,GAAS,CAAA,GAAI,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA;AACxD;AAEA,SAAS,WAAA,CACP,SACA,OAAA,EACmC;AACnC,EAAA,OAAO,GAAA,CAAI;AAAA,IACT,IAAA,EAAM,6BAAA;AAAA,IACN,QAAA,EAAU,6CAAA;AAAA,IACV,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ;AAAA,MACN,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,QAAA,EAAU,OAAA;AAAA,MACV,UAAU,OAAA,CAAQ;AAAA;AACpB,GACD,CAAA;AACH","file":"artifact-path.mjs","sourcesContent":["import type { AssetArtifactError } from '@forgeax/engine-types';\nimport { err, ok, type Result } from '@forgeax/engine-types';\n\nexport interface ArtifactPathContext {\n  readonly packageRoot: string;\n  readonly guid: string;\n  readonly artifactKey: string;\n}\n\nconst PATH_HINT =\n  'use a normalized package-relative artifact path without traversal, absolute prefixes, or remote URLs';\n\nexport function validateArtifactPath(\n  locator: string,\n  context: ArtifactPathContext,\n): Result<string, AssetArtifactError> {\n  const decoded = decodeLocator(locator);\n  if (!decoded.ok) return invalidPath(locator, context);\n\n  const normalized = normalizeRelativePath(decoded.value);\n  if (!normalized) return invalidPath(locator, context);\n\n  return ok(normalized);\n}\n\nfunction decodeLocator(locator: string): Result<string, null> {\n  let decoded = locator;\n  try {\n    for (let pass = 0; pass < 3; pass += 1) {\n      const next = decodeURIComponent(decoded);\n      if (next === decoded) break;\n      decoded = next;\n    }\n  } catch {\n    return err(null);\n  }\n  return ok(decoded);\n}\n\nfunction normalizeRelativePath(locator: string): string | null {\n  if (locator.length === 0 || locator.includes('://')) return null;\n  if (locator.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(locator)) return null;\n\n  const segments = locator.replaceAll('\\\\', '/').split('/');\n  const normalized: string[] = [];\n  for (const segment of segments) {\n    if (segment === '..') return null;\n    if (segment === '' || segment === '.') continue;\n    normalized.push(segment);\n  }\n  return normalized.length > 0 ? normalized.join('/') : null;\n}\n\nfunction invalidPath(\n  locator: string,\n  context: ArtifactPathContext,\n): Result<never, AssetArtifactError> {\n  return err({\n    code: 'asset-artifact-path-invalid',\n    expected: 'a normalized package-relative artifact path',\n    hint: PATH_HINT,\n    detail: {\n      guid: context.guid,\n      artifactKey: context.artifactKey,\n      observed: locator,\n      expected: context.packageRoot,\n    },\n  });\n}\n"]}