20 lines · 801 B
import { randomId } from "../crypto";

const SCOPE_ID = /^[a-z0-9]{20}$/;
const SUFFIX_LENGTH = 12;
const EMBEDDED = /^[a-z0-9]{32}$/;

/**
 * An id for a new row that carries its scope: the 20-character repo or account id followed by 12 random
 * characters. Lookups by such an id need no directory read, and no locator row is written for it. Scopes that
 * aren't plain ids (`site:<id>`, `scratch:<id>`) fall back to a random id plus a locator.
 */
export function scopedId(scopeId: string): string {
  return SCOPE_ID.test(scopeId) ? scopeId + randomId(SUFFIX_LENGTH) : randomId();
}

/** The scope an id carries, or null for older random ids and credential hashes. */
export function embeddedScope(key: string): string | null {
  return EMBEDDED.test(key) ? key.slice(0, -SUFFIX_LENGTH) : null;
}