{"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/helpers.ts","../src/brands.ts","../src/predicates.ts","../src/converters.ts","../src/create.ts"],"sourcesContent":["export const VALID_ID = /^[a-z-A-Z0-9._-]+$/\n\nexport const DRAFTS_DIR = 'drafts'\nexport const VERSION_DIR = 'versions'\n\nexport const PATH_SEPARATOR = '.'\nexport const DRAFTS_PREFIX = `${DRAFTS_DIR}${PATH_SEPARATOR}`\nexport const VERSION_PREFIX = `${VERSION_DIR}${PATH_SEPARATOR}`\n","// internal helpers\n\nimport {partition as lodashPartition} from 'lodash'\n\nexport type SafeError = {success: false; error: Error}\nexport type SafeSuccess<T> = {success: true; value: T}\n\nexport type SafeResult<T> = SafeSuccess<T> | SafeError\n\n// eslint-disable-next-line @typescript-eslint/no-shadow\nexport function error(error: Error): SafeError {\n  return {success: false, error}\n}\nexport function success<T>(value: T): SafeSuccess<T> {\n  return {success: true, value}\n}\n\nexport function safe<T>(fn: () => T): SafeResult<T> {\n  try {\n    return success(fn())\n  } catch (err) {\n    return error(err instanceof Error ? err : new Error(String(err)))\n  }\n}\n\n/**\n * lodash types are wildly inaccurate\n * todo: replace with es-toolkit, which has better typings\n * @param array\n * @param predicate\n */\n\nexport function partition<T, S extends T>(\n  array: T[],\n  predicate: (element: T) => element is S,\n): [trueValues: S[], falseValues: Exclude<T, S>[]] {\n  return lodashPartition(array, predicate)\n}\n","import {type Brand, make} from 'ts-brand'\n\nimport {DRAFTS_PREFIX, VALID_ID, VERSION_PREFIX} from './constants'\nimport {partition, safe} from './helpers'\n\n/**\n * @public\n */\nexport type DraftId = Brand<string, 'draftId'>\n/**\n * @public\n */\nexport type PublishedId = Brand<string, 'publishedId'>\n/**\n * @public\n */\nexport type VersionId = Brand<string, 'versionId'>\n/**\n * @public\n */\nexport type DocumentId = DraftId | PublishedId | VersionId\n\n/**\n * @public\n */\nexport const DocumentId = make<DocumentId>((id: string) => {\n  validateAnyId(id)\n  const results = [validatePublishedId, validateDraftId, validateVersionId].map(\n    validator => safe(() => validator(id)),\n  )\n  const [successes, errors] = partition(results, res => res.success)\n\n  if (successes.length > 0) {\n    return id\n  }\n\n  if (errors.length > 0) {\n    throw new AggregateError(\n      errors.map(res => res.error),\n      `Invalid Document ID\\n - ${errors.map(res => res.error.message).join('\\n - ')}`,\n    )\n  }\n  /* istanbul ignore */\n  /* v8 ignore next 3 */\n  return id\n})\n\n/**\n * @public\n */\n\nexport const DraftId = make<DraftId>(id => {\n  validateAnyId(id)\n  validateDraftId(id)\n})\n/**\n * @public\n */\nexport const PublishedId = make<PublishedId>(id => {\n  validateAnyId(id)\n  validatePublishedId(id)\n})\n\n/**\n * @public\n */\nexport const VersionId = make<VersionId>(id => {\n  validateAnyId(id)\n  validateVersionId(id)\n})\n\nfunction validateAnyId(id: string) {\n  if (id.length === 0) {\n    throw new Error(`Must be a non-empty string`)\n  }\n  if (!VALID_ID.test(id)) {\n    throw new Error(\n      `Not a valid document ID: \"${id}\" – Must match the ${VALID_ID} RegExp`,\n    )\n  }\n\n  return id\n}\n\nfunction validateDraftId(id: string) {\n  if (!id.startsWith(DRAFTS_PREFIX)) {\n    throw new Error(\n      `Not a valid draft ID: \"${id}\" – must start with \"${DRAFTS_PREFIX}\"`,\n    )\n  }\n  if (id.length === DRAFTS_PREFIX.length) {\n    throw new Error(\n      `Not a valid draft ID: \"${id}\" – must have at least one character followed by \"${DRAFTS_PREFIX}\"`,\n    )\n  }\n  return id\n}\n\nfunction validateVersionId(id: string) {\n  if (!id.startsWith(VERSION_PREFIX)) {\n    throw new Error(\n      `Not a valid version ID: \"${id}\" – must start with \"${VERSION_PREFIX}\"`,\n    )\n  }\n  if (id.length === VERSION_PREFIX.length) {\n    throw new Error(\n      `Not a valid version ID: \"${id}\" – must have at least one character followed by \"${VERSION_PREFIX}\"`,\n    )\n  }\n  const [, versionName, ...documentId] = id.split('.')\n  if (!versionName || !VALID_ID.test(versionName)) {\n    throw new Error(\n      `Not a valid version ID: \"${id}\" – VERSION must match the ${VALID_ID} RegExp in versions.[VERSION].id`,\n    )\n  }\n  if (documentId.length === 0) {\n    throw new Error(\n      `Not a valid version ID: \"${id}\" – missing document ID in versions.bundle.[ID]`,\n    )\n  }\n  if (versionName === 'drafts' || versionName === 'versions') {\n    throw new Error(\n      `Not a valid version ID: \"${id}\" – invalid VERSION \"${versionName}\" in versions.[VERSION].id`,\n    )\n  }\n  return id\n}\n\nfunction validatePublishedId(id: string) {\n  if (id.startsWith(DRAFTS_PREFIX) || id.startsWith(VERSION_PREFIX)) {\n    throw new Error(\n      `Not a valid published ID: \"${id}\" – cannot start with \"${DRAFTS_PREFIX}\" or \"${VERSION_PREFIX}\"`,\n    )\n  }\n  return id\n}\n","import {\n  type DocumentId,\n  type DraftId,\n  type PublishedId,\n  type VersionId,\n} from './brands'\nimport {DRAFTS_PREFIX, VERSION_PREFIX} from './constants'\nimport {getPublishedId} from './converters'\n\n/**\n *\n * Checks if two document ids resolves to the same published ID, ignoring any draft or version prefix.\n *\n * @public\n *\n * @param id - The document ID to check\n * @param otherId - The other document ID to check\n *\n * @example\n * Draft vs published document ID, but representing the same document:\n * ```\n * // Prints \"true\":\n * console.log(isPublishedIdEqual('drafts.foo', 'foo'));\n * ```\n * @example\n * Version vs published document ID, but representing the same document:\n * ```\n * // Prints \"true\":\n * console.log(isPublishedIdEqual('versions.xyz.foo', 'foo'));\n * ```\n * @example\n * Different documents:\n * ```\n * // Prints \"false\":\n * console.log(isPublishedIdEqual('foo', 'bar'));\n * ```\n *\n * @returns `true` if the document IDs represents the same document, `false` otherwise\n */\nexport function isPublishedIdEqual(\n  id: DocumentId,\n  otherId: DocumentId,\n): boolean {\n  return getPublishedId(id) === getPublishedId(otherId)\n}\n\n/**\n * Check whether a given document ID is a draft ID\n * @public\n * @param id - The document ID to check\n */\nexport function isDraftId(id: DocumentId): id is DraftId {\n  return id.startsWith(DRAFTS_PREFIX)\n}\n\n/**\n * Check whether a given document ID is a published ID\n * @public\n * @param id - The document ID to check\n */\nexport function isPublishedId(id: DocumentId): id is PublishedId {\n  return !isDraftId(id) && !isVersionId(id)\n}\n\n/**\n * Check whether a given document ID is a version ID\n * @public\n * @param id - The document ID to check\n */\nexport function isVersionId(id: DocumentId): id is VersionId {\n  return id.startsWith(VERSION_PREFIX)\n}\n\n/**\n * Check whether a particular document ID is the draft ID of another document ID\n * @public\n * @param id - The document ID to check if the candidate is a draft of\n * @param candidate - The candidate document ID to check\n * Note: returns true for identical draft ids, i.e. isDraftOf(DraftId('drafts.foo'), DraftId('drafts.foo')) will be true.\n */\nexport function isDraftOf(\n  id: DocumentId,\n  candidate: DocumentId,\n): candidate is DraftId {\n  return isDraftId(candidate) && isPublishedIdEqual(id, candidate)\n}\n\n/**\n * Check whether a particular document ID is the published ID of another document ID\n * @public\n * @param id - The document ID to check if the candidate is a draft of\n * @param candidate - The candidate document ID to check\n *\n * Note: returns true for identical ids, i.e. isPublishedOf(PublishedId('foo'), PublishedId('foo')) will be true.\n */\nexport function isPublishedOf(\n  id: DocumentId,\n  candidate: DocumentId,\n): candidate is VersionId {\n  return isPublishedId(candidate) && isPublishedIdEqual(id, candidate)\n}\n\n/**\n * Check whether a particular document ID is a version ID of another document ID\n * @public\n * @param id - The document ID to check if the candidate is a draft of\n * @param candidate - The candidate document ID to check\n *\n * Note: returns true for identical versions, i.e. isVersionOf(VersionId('versions.xyz.foo'), VersionId('versions.xyz.foo')) will be true.\n */\nexport function isVersionOf(\n  id: DocumentId,\n  candidate: DocumentId,\n): candidate is VersionId {\n  return isVersionId(candidate) && isPublishedIdEqual(id, candidate)\n}\n","import {type DocumentId, DraftId, PublishedId, VersionId} from './brands'\nimport {DRAFTS_PREFIX, PATH_SEPARATOR, VERSION_PREFIX} from './constants'\nimport {isDraftId, isPublishedId, isVersionId} from './predicates'\n\n/**\n * Returns the published ID of the provided document ID\n * @public\n * @param id - the DocumentId to return the published ID for\n */\nexport function getPublishedId(id: DocumentId): PublishedId {\n  if (isDraftId(id)) {\n    return PublishedId(id.slice(DRAFTS_PREFIX.length))\n  }\n  if (isVersionId(id)) {\n    // [\"versions.\", versionId, ...publishedIdParts]\n    const [, , ...publishedId] = id.split(PATH_SEPARATOR)\n    return PublishedId(publishedId.join(PATH_SEPARATOR))\n  }\n  return id\n}\n\n/**\n * Returns the draft ID of the provided document ID\n * @public\n * @param id - the DocumentId to return the draft ID for\n */\nexport function getDraftId(id: DocumentId): DraftId {\n  if (isVersionId(id)) {\n    // [\"versions.\", versionId, ...publishedIdParts]\n    const [, , ...publishedId] = id.split(PATH_SEPARATOR)\n    return DraftId(DRAFTS_PREFIX + publishedId.join(PATH_SEPARATOR))\n  }\n  if (isPublishedId(id)) {\n    return DraftId(DRAFTS_PREFIX + id)\n  }\n  return id\n}\n\n/**\n * Returns a version ID of the provided document ID\n * @public\n * @param id - the DocumentId to return the version ID for\n * @param versionName - the name of the version to return a version ID for\n */\nexport function getVersionId(id: DocumentId, versionName: string): VersionId {\n  if (isVersionId(id) || isDraftId(id)) {\n    return getVersionId(getPublishedId(id), versionName)\n  }\n  return VersionId(VERSION_PREFIX + versionName + PATH_SEPARATOR + id)\n}\n\n/**\n *  @public\n *  Extracts and returns the version name of a version id\n *  e.g. getVersionNameFromId(VersionId(`versions.xyz.foo`)) = `xyz`\n *  @param id - the version id to extract version name from\n */\nexport function getVersionNameFromId(id: VersionId): string {\n  // [\"versions.\", versionId, ...publishedIdParts]\n  const [, versionId] = id.split(PATH_SEPARATOR)\n\n  return versionId!\n}\n","import {uuid} from '@sanity/uuid'\nimport {deburr} from 'lodash'\n\nimport {DraftId, PublishedId, VersionId} from './brands'\nimport {DRAFTS_PREFIX, PATH_SEPARATOR, VERSION_PREFIX} from './constants'\n\nconst UNSAFE_CHARS = /[^a-zA-Z0-9_-]+/g\nconst LEADING = /^[_-]+/\nconst TRAILING = /[_-]+$/\n\n// Note: Document IDs have a max limit of 128 characters, but we need to leave some breathing room\n// for the prefix and separator characters.\n//  - the version prefix is (9 chars)\n//  - version name is typically 9 chars\n//  - the path separator is one char\nconst GENERATED_IDS_MAX_LENGTH = 96\n\n/**\n * Create a new document id\n *\n * @param input Optional input string to create the id from.\n * The input string will be converted to a string safe to use as a sanity document id, i.e.\n * - stripped for any special characters\n * - capped at max 100 chars\n * If no input is provided, a random uuid will be used instead\n */\nexport function createPublishedId(input?: string): PublishedId {\n  return PublishedId(generateId(input))\n}\n\n/**\n * Create a new draft id\n *\n * @param input Optional input string to create the id from.\n * The input string will be converted to a string safe to use as a sanity document id, i.e.\n * - stripped for any special characters\n * - capped at max 100 chars\n * If no input is provided, a random uuid will be used instead\n */\nexport function createDraftId(input?: string): DraftId {\n  return DraftId(DRAFTS_PREFIX + generateId(input))\n}\n\n/**\n * Create a new version id\n *\n * @param versionName - The name of the version to create\n * @param input Optional input string to create the id from.\n * The input string will be converted to a string safe to use as a sanity document id, i.e.\n * - stripped for any special characters\n * - capped at max 100 chars\n * If no input is provided, a random uuid will be used instead\n */\nexport function createVersionId(\n  versionName: string,\n  input?: string,\n): VersionId {\n  return VersionId(\n    VERSION_PREFIX + versionName + PATH_SEPARATOR + generateId(input),\n  )\n}\n\nfunction generateId(input?: string) {\n  return input ? makeSafe(input) : uuid()\n}\n\nfunction makeSafe(input: string) {\n  return deburr(input)\n    .replace(UNSAFE_CHARS, '')\n    .replace(TRAILING, '')\n    .replace(LEADING, '')\n    .slice(0, GENERATED_IDS_MAX_LENGTH)\n}\n"],"names":["error","lodashPartition","make","uuid","deburr"],"mappings":"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"}