All files / packages/fds-uif/core/src/validate shared.ts

85.71% Statements 12/14
75% Branches 6/8
100% Functions 3/3
92.3% Lines 12/13

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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68                                  30x                               327x   327x 327x   327x 566x 117x   449x     449x     210x               5x                 5x    
/**
 * @fds-uif/core - Validation Shared Utilities
 *
 * Helpers used by more than one validator in this directory: the
 * `ValidationErrorCode` enum, JSON path utilities, and path-formatting
 * helpers for human-readable diagnostics.
 *
 * Validators that consume helpers used in only one place keep those helpers
 * co-located rather than promoting them here.
 */
 
/**
 * Error codes for {@link ValidationError} entries produced by the
 * orchestrator. Each per-validator file owns one or two of these codes; the
 * enum is centralized so that {@link validateUif} (and downstream consumers
 * pattern-matching on `code`) only need to import a single object.
 */
export const ValidationErrorCode = {
  DUPLICATE_IDENTIFIER: 'UIF_DUPLICATE_IDENTIFIER',
  INVALID_STATE_REFERENCE: 'UIF_INVALID_STATE_REFERENCE',
  CONFLICTING_MARKERS: 'UIF_CONFLICTING_MARKERS',
  VARIANT_CONFLICT: 'UIF_VARIANT_CONFLICT',
  INVALID_EXTENSIONS: 'UIF_INVALID_EXTENSIONS',
  DEPRECATED_DEFAULT: 'UIF_DEPRECATED_DEFAULT',
} as const;
 
/**
 * Resolve a dot-notation path (e.g. `'structure.modifiers'`) against an
 * arbitrary unknown value, returning `undefined` when any segment of the
 * walk hits a non-object or missing key. Used by the identifier and marker
 * validators to navigate UIFs whose shape has not yet been schema-validated.
 */
export function getByPath(obj: unknown, path: string): unknown {
  Iif (!path) return obj;
 
  const parts = path.split('.');
  let current: unknown = obj;
 
  for (const part of parts) {
    if (current === null || current === undefined) {
      return undefined;
    }
    Iif (typeof current !== 'object') {
      return undefined;
    }
    current = (current as Record<string, unknown>)[part];
  }
 
  return current;
}
 
/**
 * Format a path for user-friendly display.
 * Converts `"structure.children[0].name"` to `"structure > children[0] > name"`.
 */
export function formatPathForDisplay(path: string): string {
  return path.replaceAll('.', ' > ').replaceAll(/\[(\d+)\]/g, '[$1]');
}
 
/**
 * Format the path line for error messages. Notes that this is a path in
 * the merged UIF, not a source file location, so consumers of the message
 * don't try to map it back to disk.
 */
export function formatPathLine(path: string): string {
  return `Path (in merged UIF): ${formatPathForDisplay(path)}`;
}