All files idempotency.js

100% Statements 40/40
100% Branches 17/17
100% Functions 4/4
100% Lines 40/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 418x 8x 8x 8x 8x 8x 8x 8x 8x 8x 677x 677x 675x 675x 2x 2x 2x 2x 677x 8x 8x 8x 33x 33x 8x 8x 8x 21x 4x 4x 17x 21x 8x 8x 8x 8x 8x 198x 198x 198x  
// Copyright 2026 优谷雅言 open.shengzhiai.com. Licensed under the Apache License, Version 2.0.
// Idempotency keys (DESIGN 2.2).
 
import { localError } from './errors.js';
import { getCrypto, randomBytes, toHex } from './util.js';
 
const KEY_PATTERN = /^[\x21-\x7E]{1,200}$/;
 
/** 32 lowercase hex characters: a UUID v4 without dashes. */
export function generateIdempotencyKey(cryptoImpl) {
  const c = getCrypto(cryptoImpl);
  if (c && typeof c.randomUUID === 'function') {
    return c.randomUUID().replace(/-/g, '').toLowerCase();
  }
  const b = randomBytes(16, cryptoImpl);
  b[6] = (b[6] & 0x0f) | 0x40; // version 4
  b[8] = (b[8] & 0x3f) | 0x80; // variant 10
  return toHex(b);
}
 
/** True when the key is 1 to 200 visible ASCII characters. */
export function isValidIdempotencyKey(key) {
  return typeof key === 'string' && KEY_PATTERN.test(key);
}
 
/** Throws InvalidParameterException 90010 for a bad caller key. */
export function validateIdempotencyKey(key) {
  if (!isValidIdempotencyKey(key)) {
    throw localError(90010, 'idempotencyKey 必须是 1 到 200 个可见 ASCII 字符');
  }
  return key;
}
 
/**
 * Key for one logical call: the caller key (validated), a generated key when auto is on, or null.
 */
export function resolveIdempotencyKey(callerKey, auto, cryptoImpl) {
  if (callerKey !== undefined && callerKey !== null) return validateIdempotencyKey(callerKey);
  return auto ? generateIdempotencyKey(cryptoImpl) : null;
}