All files / packages/sds-customization-compliance/src/cli paths.ts

29.72% Statements 11/37
17.85% Branches 5/28
55.55% Functions 5/9
35.48% Lines 11/31

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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122                              4x 4x                                                                                                                 4x 4x               4x 4x 4x                                           4x 4x   6x 6x                      
/**
 * Filesystem conventions for the `sds-compliance` CLI.
 *
 * The CLI defaults all paths off the design-system-2 package root, which
 * is normally the sibling workspace (`packages/design-system-2/`) when
 * this package lives under `packages/sds-customization-compliance/`.
 * Every convention below is overridable via an explicit flag.
 */
 
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
 
/** Package root = two levels up from `dist/cli/paths.js` or `src/cli/paths.ts`. */
export function getPackageRoot(): string {
  const here = fileURLToPath(import.meta.url);
  return path.resolve(path.dirname(here), '..', '..');
}
 
/** Walk up from `start` until we find a sibling `packages/design-system-2` dir. */
export function findDs2Root(start: string = getPackageRoot()): string | null {
  let dir = start;
  for (let i = 0; i < 8; i++) {
    const candidate = path.join(dir, 'packages', 'design-system-2');
    if (fs.existsSync(path.join(candidate, 'src', 'slds2'))) return candidate;
    const parent = path.dirname(dir);
    if (parent === dir) break;
    dir = parent;
  }
  // Fallback: the sibling case (`../../design-system-2`).
  const sibling = path.resolve(start, '..', 'design-system-2');
  if (fs.existsSync(path.join(sibling, 'src', 'slds2'))) return sibling;
  return null;
}
 
export interface ResolvedPaths {
  ds2Root: string;
  slds2Dir: string;
  outDir: string;
  packageRoot: string;
}
 
export interface PathOverrides {
  ds2Root?: string;
  slds2Dir?: string;
  outDir?: string;
}
 
/**
 * Resolved paths for a structural-only build (e.g. the LBC scratch trio).
 * Skips the slds2 layout entirely and treats `sourceDir` as a flat
 * "<sourceDir>/<component>/" parent.
 */
export interface ResolvedStructuralPaths {
  /** Root the report's `inputs` paths are made relative to. */
  baseRoot: string;
  /** Parent dir whose immediate subdirectories are treated as components. */
  sourceDir: string;
  outDir: string;
  packageRoot: string;
}
 
export interface StructuralPathOverrides {
  sourceDir: string;
  outDir?: string;
  baseRoot?: string;
}
 
/**
 * Resolve absolute paths from CLI overrides. Throws a friendly error when
 * no design-system-2 package can be located and no overrides were given.
 */
export function resolvePaths(overrides: PathOverrides = {}): ResolvedPaths {
  const packageRoot = getPackageRoot();
  const ds2Root = overrides.ds2Root
    ? path.resolve(overrides.ds2Root)
    : (findDs2Root() ??
      (() => {
        throw new Error(
          'Could not locate packages/design-system-2. Pass --ds2-root <path> or --src <slds2-dir>.',
        );
      })());
  const slds2Dir = overrides.slds2Dir ?? path.join(ds2Root, 'src', 'slds2');
  const outDir = overrides.outDir ?? path.join(packageRoot, 'build');
  return { ds2Root, slds2Dir, outDir, packageRoot };
}
 
/**
 * Resolve paths for a structural-only build. The `sourceDir` is required;
 * `outDir` defaults to `<sourceDir>/../build/compliance`, `baseRoot` to
 * the package root that contains `sourceDir`.
 */
export function resolveStructuralPaths(overrides: StructuralPathOverrides): ResolvedStructuralPaths {
  const packageRoot = getPackageRoot();
  const sourceDir = path.resolve(overrides.sourceDir);
  const baseRoot = overrides.baseRoot
    ? path.resolve(overrides.baseRoot)
    : path.resolve(sourceDir, '..', '..');
  const outDir = overrides.outDir
    ? path.resolve(overrides.outDir)
    : path.join(baseRoot, 'build', 'compliance');
  return { baseRoot, sourceDir, outDir, packageRoot };
}
 
/** List every `<slds2-dir>/*` directory that looks like an SLDS2 component. */
export function listComponents(slds2Dir: string): string[] {
  Iif (!fs.existsSync(slds2Dir)) return [];
  return fs
    .readdirSync(slds2Dir, { withFileTypes: true })
    .filter((d) => d.isDirectory())
    .map((d) => d.name)
    .sort();
}
 
/** Derive the component name for a file path under slds2Dir, or `null`. */
export function componentForCssPath(slds2Dir: string, cssPath: string): string | null {
  const rel = path.relative(slds2Dir, cssPath);
  if (rel.startsWith('..') || path.isAbsolute(rel)) return null;
  const [name] = rel.split(path.sep);
  return name || null;
}