Spreadsheet-UX op een echte relationele engine

main

Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.

1.4 kB Ruw bestand
import { randomBytes } from 'node:crypto';

const ALPHABET = '0123456789abcdefghijkmnpqrstvwxyz'; // Crockford-ish: no i, l, o, u
const BASE = ALPHABET.length;

/** Milliseconds, base-33, fixed width — nine digits reach the year 3400. */
const STAMP_WIDTH = 9;

/**
 * Bumped instead of reused when two ids land in one millisecond, so ids sort
 * in the order they were made even inside a single import loop.
 */
let lastStamp = 0;

/**
 * Collision-resistant, URL-safe, time-ordered row identifier.
 *
 * Time-ordered is load-bearing: an unsorted grid is `ORDER BY id`, so ids made
 * in sequence have to sort in sequence — an imported spreadsheet keeps its
 * file order, and a new row lands at the bottom instead of wherever twelve
 * random characters happen to fall. The random tail keeps two servers that
 * share a millisecond from sharing an id.
 */
export function newId(prefix = ''): string {
  const now = Date.now();
  lastStamp = now > lastStamp ? now : lastStamp + 1;

  let stamp = '';
  for (let rest = lastStamp, i = 0; i < STAMP_WIDTH; i++) {
    stamp = ALPHABET[rest % BASE] + stamp;
    rest = Math.floor(rest / BASE);
  }

  let out = stamp;
  for (const b of randomBytes(7)) out += ALPHABET[b % BASE];
  return prefix ? `${prefix}_${out}` : out;
}

/** Row ids are user-visible in the address bar; keep them tightly shaped. */
export function isValidId(id: string): boolean {
  return /^[A-Za-z0-9_-]{1,64}$/.test(id);
}