File size: 2,272 Bytes
9bd7455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env node
/**
 * Enforce the VS Code-style service naming convention finalized in
 * Phase 5 of the 2026.06.07 services-alignment plan:
 *
 *   - packages/services/src/<domain>/<domain>.ts (+ <domain>Service.ts)
 *   - packages/kap-server/src/services/<domain>/<domain>.ts (+ <domain>Service.ts)
 *
 * Domain dirs and service-related .ts files must be camelCase — never
 * kebab-case (no `-` in the name). Anything outside these two roots is
 * ignored (test fixtures, etc.).
 *
 * Exit code 0 if clean, 1 with an actionable report otherwise.
 */

import { readdirSync, statSync, existsSync } from "node:fs";
import { resolve, join, relative } from "node:path";

const ROOT = resolve(import.meta.dirname, "..");
const SERVICES_SRC = join(ROOT, "packages/services/src");
const SERVER_SERVICES_SRC = join(ROOT, "packages/kap-server/src/services");

/** @type {Array<{ kind: string, path: string }>} */
const violations = [];

function isKebab(name) {
  return name.includes("-");
}

function report(kind, absPath) {
  violations.push({ kind, path: relative(ROOT, absPath) });
}

/**
 * Both roots are organised as <domain>/<files>.ts plus a few top-level files
 * (index.ts, module.ts, pinoLoggerService.ts). Flag kebab in dir names and in
 * any .ts file directly under a domain dir.
 */
function scanServicesSrc(srcRoot = SERVICES_SRC) {
  if (!existsSync(srcRoot)) return;
  for (const entry of readdirSync(srcRoot)) {
    const abs = join(srcRoot, entry);
    const st = statSync(abs);
    if (st.isDirectory()) {
      if (isKebab(entry)) report("kebab-dir", abs);
      for (const f of readdirSync(abs)) {
        if (!f.endsWith(".ts")) continue;
        if (isKebab(f)) report("kebab-file", join(abs, f));
      }
    } else if (entry.endsWith(".ts") && isKebab(entry)) {
      report("kebab-file", abs);
    }
  }
}

scanServicesSrc();
scanServicesSrc(SERVER_SERVICES_SRC);

if (violations.length > 0) {
  console.error(
    "Service naming violations (no kebab-case allowed for service files/dirs):"
  );
  for (const v of violations) console.error(`  [${v.kind}] ${v.path}`);
  console.error(
    "\nRename to camelCase per VS Code convention: <domain>.ts + <domain>Service.ts."
  );
  process.exit(1);
}

console.log("Service naming check passed.");