{"version":3,"file":"utils-C7xfzvt1.mjs","names":[],"sources":["../../src/utils.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nconst hasOwn: (o: object, v: PropertyKey) => boolean = Object.hasOwn ||\n  ((obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop));\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n  return Array.isArray(value) ? value : [value];\n}\n\nconst FORBIDDEN_PROPERTIES = new Set(['__proto__', 'constructor', 'prototype']);\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n  let ref = object;\n  let lastKey = path;\n\n  if (path.indexOf('.') !== -1) {\n    const keys = path.split('.');\n\n    lastKey = keys.pop()!;\n    ref = keys.reduce((res, prop) => {\n      if (FORBIDDEN_PROPERTIES.has(prop)) return res;\n      res[prop] = res[prop] || {};\n      return res[prop] as AnyObject;\n    }, object);\n  }\n\n  if (!FORBIDDEN_PROPERTIES.has(lastKey)) {\n    ref[lastKey] = value;\n  }\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n  T extends string,\n  U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n  if (object) {\n    if (!hasOwn(object, TYPE_FIELD)) {\n      Object.defineProperty(object, TYPE_FIELD, { value: type });\n    } else if (type !== object[TYPE_FIELD]) {\n      throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n    }\n  }\n\n  return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n  const type = typeof value;\n  return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport function getSubjectTypeName(value: SubjectType) {\n  return typeof value === 'string' ? value : getSubjectClassName(value);\n}\n\nexport function detectSubjectType(object: Exclude<Subject, SubjectType>): string {\n  if (hasOwn(object, TYPE_FIELD)) {\n    return object[TYPE_FIELD];\n  }\n\n  return getSubjectClassName(object.constructor as SubjectClass);\n}\n\nexport const DETECT_SUBJECT_TYPE_STRATEGY = {\n  function: (object: Exclude<Subject, SubjectType>) => object.constructor as SubjectClass,\n  string: detectSubjectType\n};\n\ntype AliasMerge = (actions: string[], action: string | string[]) => string[];\nfunction expandActions(aliasMap: AliasesMap, rawActions: string | string[], merge: AliasMerge) {\n  let actions = wrapArray(rawActions);\n  let i = 0;\n\n  while (i < actions.length) {\n    const action = actions[i++];\n\n    if (hasOwn(aliasMap, action)) {\n      actions = merge(actions, aliasMap[action]);\n    }\n  }\n\n  return actions;\n}\n\nfunction findDuplicate(actions: string[], actionToFind: string | string[]) {\n  if (typeof actionToFind === 'string' && actions.indexOf(actionToFind) !== -1) {\n    return actionToFind;\n  }\n\n  for (let i = 0; i < actionToFind.length; i++) {\n    if (actions.indexOf(actionToFind[i]) !== -1) return actionToFind[i];\n  }\n\n  return null;\n}\n\nconst defaultAliasMerge: AliasMerge = (actions, action) => actions.concat(action);\nfunction validateForCycles(aliasMap: AliasesMap, reservedAction: string) {\n  if (reservedAction in aliasMap) {\n    throw new Error(`Cannot use \"${reservedAction}\" as an alias because it's reserved action.`);\n  }\n\n  const keys = Object.keys(aliasMap);\n  const mergeAliasesAndDetectCycles: AliasMerge = (actions, action) => {\n    const duplicate = findDuplicate(actions, action);\n    if (duplicate) throw new Error(`Detected cycle ${duplicate} -> ${actions.join(', ')}`);\n\n    const isUsingReservedAction = typeof action === 'string' && action === reservedAction\n      || actions.indexOf(reservedAction) !== -1\n      || Array.isArray(action) && action.indexOf(reservedAction) !== -1;\n    if (isUsingReservedAction) throw new Error(`Cannot make an alias to \"${reservedAction}\" because this is reserved action`);\n\n    return actions.concat(action);\n  };\n\n  for (let i = 0; i < keys.length; i++) {\n    expandActions(aliasMap, keys[i], mergeAliasesAndDetectCycles);\n  }\n}\n\nexport type AliasResolverOptions = { skipValidate?: boolean; anyAction?: string };\nexport function createAliasResolver(aliasMap: AliasesMap, options?: AliasResolverOptions) {\n  if (!options || options.skipValidate !== false) {\n    validateForCycles(aliasMap, options && options.anyAction || 'manage');\n  }\n\n  return (action: string | string[]) => expandActions(aliasMap, action, defaultAliasMerge);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: readonly T[], start: number) {\n  for (let i = start; i < target.length; i++) {\n    dest.push(target[i]);\n  }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n  array?: readonly T[],\n  anotherArray?: readonly T[]\n): readonly T[] {\n  if (!array || !array.length) {\n    return anotherArray || [];\n  }\n\n  if (!anotherArray || !anotherArray.length) {\n    return array || [];\n  }\n\n  let i = 0;\n  let j = 0;\n  const merged: T[] = [];\n\n  while (i < array.length && j < anotherArray.length) {\n    if (array[i].priority < anotherArray[j].priority) {\n      merged.push(array[i]);\n      i++;\n    } else if (array[i].priority > anotherArray[j].priority) {\n      merged.push(anotherArray[j]);\n      j++;\n    } else {\n      // rule priority is unique, if it's equal then it's the exact same rule, so we skip the duplicate\n      merged.push(array[i]);\n      i++;\n      j++;\n    }\n  }\n\n  copyArrayTo(merged, array, i);\n  copyArrayTo(merged, anotherArray, j);\n\n  return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n  let value = map.get(key);\n\n  if (!value) {\n    value = defaultValue();\n    map.set(key, value);\n  }\n\n  return value;\n}\n\nexport const identity = <T>(x: T) => x;\n\nexport function filterWithLazyAllocation<T>(array: T[], predicate: (item: T) => boolean): T[] {\n  let result: T[] | undefined;\n  for (let i = 0; i < array.length; i++) {\n    const matches = predicate(array[i]);\n    if (result && matches) {\n      result.push(array[i]);\n    }\n    if (!matches) {\n      result ??= array.slice(0, i);\n    }\n  }\n\n  return result || array;\n}\n"],"mappings":"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"}