All files / packages/sds-customization-compliance/src/checks no-orphan-hooks.ts

92.59% Statements 25/27
75% Branches 12/16
100% Functions 3/3
100% Lines 23/23

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 69 70 71 72 73 74 75                                    4x   4x 10x 10x 4x                 6x 6x 6x 7x 7x 7x 4x 4x   7x     6x 6x 4x 5x 4x     6x 5x                   1x           1x            
/**
 * Compliance row: no orphan hooks (every definition assigned by at least
 * one theme).
 *
 * An orphan hook is a component hook whose every theme assignment is the
 * literal `revert` keyword — i.e. dead API that no theme ever meaningfully
 * binds. Per the RFC, the correct fix is to delete the hook or give it a
 * value in at least one theme.
 */
 
import type { ComplianceCheck, ComplianceRow } from '../types.js';
import {
  hookDefsFromThemeData,
  sampleHooks,
  NOT_MIGRATED_DETAIL,
  type HookDefRow,
} from './helpers/themeDataAccess.js';
 
const LABEL = 'No orphan hooks (all definitions assigned by at least one theme)';
 
export const noOrphanHooks: ComplianceCheck = (input): ComplianceRow => {
  const { themeData } = input;
  if (!themeData) {
    return {
      id: 'no-orphan-hooks',
      label: LABEL,
      status: 'info',
      count: 0,
      detail: NOT_MIGRATED_DETAIL,
    };
  }
 
  const defs = hookDefsFromThemeData(themeData);
  const defsByHook = new Map<string, HookDefRow[]>();
  for (const d of defs) {
    Iif (!d.prop?.startsWith('--slds-c-')) continue;
    let bucket = defsByHook.get(d.prop);
    if (!bucket) {
      bucket = [];
      defsByHook.set(d.prop, bucket);
    }
    bucket.push(d);
  }
 
  const orphan: string[] = [];
  for (const [hook, rows] of defsByHook) {
    Iif (rows.length === 0) continue;
    const allRevert = rows.every((d) => String(d.rawValue ?? '').trim() === 'revert');
    if (allRevert) orphan.push(hook);
  }
 
  if (orphan.length === 0) {
    return {
      id: 'no-orphan-hooks',
      label: LABEL,
      status: 'pass',
      count: 0,
      detail:
        'Every defined hook is assigned a real value in at least one theme — none resolve to `revert` everywhere.',
    };
  }
 
  return {
    id: 'no-orphan-hooks',
    label: LABEL,
    status: 'fail',
    count: orphan.length,
    detail: `${orphan.length} hook${orphan.length === 1 ? '' : 's'} resolve to \`revert\` in every tracked theme: ${sampleHooks(orphan)}. Either delete the hook (dead API) or assign it a real value in at least one theme.`,
    offenders: orphan.map((hook) => ({
      hook,
      fix: `Either delete \`${hook}\` (dead API) or assign it a real value in at least one theme instead of \`revert\`.`,
    })),
  };
};