Repository: gatsbyjs/gatsby
File: packages/gatsby/src/utils/create-node-id.ts (TypeScript)

Code before:
 *
 * High level this step is meant to prevent people from using our `id` to have meaning in their site and it's meant
 * to make sure the id ends up being short, whatever the input size was.
 *
 * Note: UUID is relatively slow because it calls into the native crypto library to generate SHA-1 hashes.
 *       We do need the low collision rate of SHA-1 so we use a local (global) cache to speed up repetitive calls
 *
 * @param {String | Number} id - A string of arbitrary length
 * @param {String} namespace - Namespace to use for UUID
 *
 * @return {String} - UUID
 */
export function createNodeId(id: string | number, namespace: string): string {
  if (typeof id === `number`) {
    id = id.toString()
  } else if (typeof id !== `string`) {
    report.panic(
      `The \`id\` parameter passed to createNodeId must be a String or Number (got ${typeof id})`
    )
  } else if (typeof namespace !== `string`) {
    report.panic(
      `The \`namespace\` parameter passed to createNodeId must be a String (got ${typeof namespace})`
    )
  }

  // Note: we can use the idCache for namespace as well since the key for ids will include the namespace
  let nsHash = unprefixedCache.get(namespace)
  if (!nsHash) {
    nsHash = uuidv5(namespace, seedConstant) as string
    unprefixedCache.set(namespace, nsHash)
  }

  // Calling uuid is relatively expensive because it calls into crypto for sha1.
  // We use a local map to cache calls with the same ns+id pair, which helps a lot.
  let nsCache = namespacedCache.get(namespace)
  if (!nsCache) {
    nsCache = new Map()
    namespacedCache.set(namespace, nsCache)
  }

  let hash = nsCache.get(id)
  if (hash) {
    return hash
  }

  hash = uuidv5(id, nsHash) as string
  nsCache.set(id, hash)
  return hash
}


Review comment (performance):
outdated comment? you did move to separate caches for namespaces and node ids and `idCache` is not there anymore

Code after:
 * - The result should be predictably short as it may be used in urls
 *
 * High level this step is meant to prevent people from using our `id` to have meaning in their site and it's meant
 * to make sure the id ends up being short, whatever the input size was.
 *
 * Note: UUID is relatively slow because it calls into the native crypto library to generate SHA-1 hashes.
 *       We do need the low collision rate of SHA-1 so we use a local (global) cache to speed up repetitive calls
 *
 * @param {String | Number} id - A string of arbitrary length
 * @param {String} namespace - Namespace to use for UUID
 *
 * @return {String} - UUID
 */
export function createNodeId(id: string | number, namespace: string): string {
  if (typeof id === `number`) {
    id = id.toString()
  } else if (typeof id !== `string`) {
    report.panic(
      `The \`id\` parameter passed to createNodeId must be a String or Number (got ${typeof id})`
    )
  } else if (typeof namespace !== `string`) {
    report.panic(
      `The \`namespace\` parameter passed to createNodeId must be a String (got ${typeof namespace})`
    )
  }

  let nsHash = unprefixedCache.get(namespace)
  if (!nsHash) {
    nsHash = uuidv5(namespace, seedConstant) as string
    unprefixedCache.set(namespace, nsHash)
  }

  // Calling uuid is relatively expensive because it calls into crypto for sha1.
  // We use a local map to cache calls with the same ns+id pair, which helps a lot.
  let nsCache = namespacedCache.get(namespace)
  if (!nsCache) {
    nsCache = new Map()
    namespacedCache.set(namespace, nsCache)
  }

  let hash = nsCache.get(id)
  if (hash) {
    return hash
  }

  hash = uuidv5(id, nsHash) as string
  nsCache.set(id, hash)
  return hash
}