{
  "version": 3,
  "sources": ["../src/policy.ts"],
  "sourcesContent": ["import type { Statement, Policy } from './types.js'\n\n/**\n * Resolves a selector string against a data object, inspired by jq.\n *\n * @returns The selected value, or null if the selection fails at an optional part.\n * @throws Error if the selection fails at a non-optional part.\n */\nfunction resolveSelector (data:unknown, selector:string):unknown {\n    if (selector === '.') {\n        return data\n    }\n\n    // This regex is a simplified parser for the selector syntax.\n    const partsRegex = /(\\.[\\w_]+|\\[-?\\d*:-?\\d*\\]|\\[-?\\d+\\]|\\[\\]|\\?)/g\n    const parts = selector.match(partsRegex) || []\n\n    let currentData = data\n\n    for (let part of parts) {\n        let isOptional = false\n        if (part.endsWith('?')) {\n            isOptional = true\n            part = part.slice(0, -1)\n        }\n\n        try {\n            if (currentData === undefined || currentData === null) {\n                throw new Error(\n          `Cannot process part \"${part}\" on null or undefined value.`\n                )\n            }\n\n            if (part.startsWith('.')) {\n                const key = part.substring(1)\n                if (typeof currentData !== 'object' || Array.isArray(currentData)) {\n                    throw new Error(`Cannot access key \"${key}\" on non-object.`)\n                }\n                currentData = (currentData as Record<string, unknown>)[key]\n            } else if (part === '[]') {\n                if (Array.isArray(currentData)) {\n                    // No-op for arrays, the quantifier will iterate over it.\n                } else if (typeof currentData === 'object') {\n                    currentData = Object.values(currentData as Record<string, unknown>)\n                } else {\n                    throw new Error('Cannot extract values from non-collection.')\n                }\n            } else if (part.startsWith('[') && part.includes(':')) {\n                // Slice\n                if (!Array.isArray(currentData)) {\n                    throw new Error('Slice can only be applied to arrays.')\n                }\n                const [start, end] = part\n                    .substring(1, part.length - 1)\n                    .split(':')\n                    .map((s) => (s ? Number.parseInt(s, 10) : undefined))\n                currentData = currentData.slice(start, end)\n            } else if (part.startsWith('[')) {\n                // Index\n                if (!Array.isArray(currentData)) {\n                    throw new Error('Index can only be applied to arrays.')\n                }\n                const index = Number.parseInt(part.substring(1, part.length - 1), 10)\n                currentData =\n          currentData[index < 0 ? currentData.length + index : index]\n            }\n\n            if (currentData === undefined) {\n                throw new Error(`Path segment returned undefined: ${part}`)\n            }\n        } catch (e) {\n            if (isOptional) {\n                return null\n            }\n            // Re-throw if not optional, to be caught by evaluateStatement\n            throw e\n        }\n    }\n\n    return currentData\n}\n\n/**\n * Performs a deep equality check between two values.\n */\nfunction deepEqual (a:unknown, b:unknown):boolean {\n    if (a === b) return true\n    if (a && b && typeof a === 'object' && typeof b === 'object') {\n        if (a.constructor !== b.constructor) return false\n        if (Array.isArray(a)) {\n            if (a.length !== (b as unknown[]).length) return false\n            for (let i = 0; i < a.length; i++) {\n                if (!deepEqual(a[i], (b as unknown[])[i])) return false\n            }\n            return true\n        }\n        const keys = Object.keys(a)\n        if (keys.length !== Object.keys(b).length) return false\n\n        for (const key of keys) {\n            const isEq = ((b as Record<string, unknown>)\n                .hasOwnProperty(key) ||  // eslint-disable-line\n                !deepEqual(\n                    (a as Record<string, unknown>)[key],\n                    (b as Record<string, unknown>)[key]\n                ))\n\n            if (!isEq) {\n                return false\n            }\n        }\n        return true\n    }\n    return false\n}\n\n/**\n * Converts a UCAN glob pattern to a regular expression.\n */\nfunction likeRegex (pattern:string):RegExp {\n    // Convert UCAN glob pattern to a regular expression.\n    // The glob pattern has `*` as a wildcard (zero or more chars)\n    // and `\\*` as an escape for a literal asterisk.\n    let regexString = '^'\n    let i = 0\n    while (i < pattern.length) {\n        const char = pattern[i]\n\n        if (char === '\\\\') {\n            // Handle escape sequence\n            if (i + 1 < pattern.length) {\n                const nextChar = pattern[i + 1]\n                if (nextChar === '*') {\n                    // This is an escaped asterisk `\\*`. Match a literal `*`.\n                    regexString += '\\\\*'\n                    i += 2 // Move past both `\\` and `*`\n                } else {\n                    // This is another escape, like `\\\\`. Treat the `\\` as a literal character.\n                    regexString += '\\\\\\\\'\n                    i++\n                }\n            } else {\n                // Trailing backslash. Treat as a literal `\\`.\n                regexString += '\\\\\\\\'\n                i++\n            }\n        } else if (char === '*') {\n            // This is a wildcard `*`. Match zero or more characters.\n            regexString += '.*'\n            i++\n        } else {\n            // This is a regular character. Escape it if it's a special regex metacharacter.\n            regexString += char.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n            i++\n        }\n    }\n    regexString += '$'\n\n    return new RegExp(regexString)\n}\n\n/**\n * Evaluates a single policy statement against the invocation args.\n *\n * @returns The result of the evaluation.\n */\nfunction evaluateStatement<Args> (args:Args, statement:Statement<Args>):boolean {\n    const [op, ...params] = statement\n\n    try {\n        switch (op) {\n            // Comparisons\n            case '==': {\n                const [selector, value] = params as [string, unknown]\n\n                return deepEqual(resolveSelector(args, selector), value)\n            }\n            case '!=': {\n                const [selector, value] = params as [string, unknown]\n                return !deepEqual(resolveSelector(args, selector), value)\n            }\n            case '>':\n            case '>=':\n            case '<':\n            case '<=': {\n                const [selector, value] = params as [string, number]\n                const selected = resolveSelector(args, selector)\n                if (typeof selected !== 'number' || typeof value !== 'number') { return false }\n                if (op === '>') return selected > value\n                if (op === '>=') return selected >= value\n                if (op === '<') return selected < value\n                if (op === '<=') return selected <= value\n                break\n            }\n            // Glob Matching\n            case 'like': {\n                const [selector, pattern] = params as [string, string]\n                const selected = resolveSelector(args, selector)\n                if (typeof selected !== 'string') return false\n                const regex = likeRegex(pattern)\n                return regex.test(selected)\n            }\n            // Connectives\n            case 'and': {\n                const [statements] = params as [Statement<Args>[]]\n                return statements.every((stmt) => evaluateStatement(args, stmt))\n            }\n            case 'or': {\n                const [statements] = params as [Statement<Args>[]]\n                if (statements.length === 0) return true\n                return statements.some((stmt) => evaluateStatement(args, stmt))\n            }\n            case 'not': {\n                const [statement] = params as [Statement<Args>]\n                return !evaluateStatement(args, statement)\n            }\n            // Quantification\n            case 'all':\n            case 'any': {\n                const [selector, innerStmt] =\n                params as [string, Statement<unknown>]\n                let collection = resolveSelector(args, selector)\n\n                if ((innerStmt as Statement<unknown>)[0] === 'any' || (innerStmt as Statement<unknown>)[0] === 'all') {\n                    return evaluateStatement(collection, innerStmt)\n                }\n\n                if (\n                    collection &&\n          typeof collection === 'object' &&\n          !Array.isArray(collection)\n                ) {\n                    collection = Object.values(collection as Record<string, unknown>)\n                }\n                if (!Array.isArray(collection)) return false\n                if (collection.length === 0) return true\n                if (op === 'all') {\n                    return collection.every((item) => {\n                        return evaluateStatement(item, innerStmt)\n                    })\n                }\n                // any\n                return collection.some((item) => evaluateStatement(item, innerStmt))\n            }\n            default:\n                return false // Unknown operator\n        }\n    } catch {\n    // As per the spec, if a selector cannot be resolved, the statement MUST return false.\n        return false\n    }\n    return false\n}\n\n/**\n * Validates invocation arguments against a UCAN policy.\n *\n * @returns True if the args are valid according to the policy, false otherwise.\n */\nexport function validate<Args> (args:Args, policy:Policy<Args>):boolean {\n    // The top-level policy is an implicit 'and'.\n    return policy.every((statement) => evaluateStatement(args, statement))\n}\n"],
  "mappings": "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",
  "names": ["policy_exports", "__export", "validate", "__toCommonJS", "resolveSelector", "data", "selector", "partsRegex", "parts", "currentData", "part", "isOptional", "key", "start", "end", "s", "index", "e", "__name", "deepEqual", "a", "b", "i", "keys", "likeRegex", "pattern", "regexString", "char", "evaluateStatement", "args", "statement", "op", "params", "value", "selected", "statements", "stmt", "innerStmt", "collection", "item", "validate", "policy"]
}
