claudeos-core 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeos-core",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
5
5
  "main": "health-checker/index.js",
6
6
  "bin": {
@@ -350,6 +350,50 @@ async function scanStructure(stack) {
350
350
  domainMap[d].xmlMappers = xml.length;
351
351
  backendDomains.push({ name: d, type: "backend", ...domainMap[d], totalFiles: svc.length + mpr.length + dto.length + xml.length + domainMap[d].controllers });
352
352
  }
353
+
354
+ // ── Java 폴백: 위 글로브가 0개일 때 전체 .java 파일에서 직접 도메인 추출 ──
355
+ if (backendDomains.length === 0) {
356
+ const allJava = await glob("**/*.java", { cwd: ROOT, ignore: ["**/node_modules/**", "**/build/**", "**/target/**", "**/test/**", "**/generated/**"] });
357
+ const javaDomains = {};
358
+ const skipNames = ["common", "config", "util", "utils", "base", "shared", "global", "framework", "infra", "api", "main"];
359
+ const layerNames = ["controller", "service", "mapper", "repository", "dao", "dto", "vo", "entity", "aggregator", "adapter"];
360
+
361
+ for (const f of allJava) {
362
+ const parts = f.replace(/\\/g, "/").split("/");
363
+ for (let i = 0; i < parts.length - 1; i++) {
364
+ if (layerNames.includes(parts[i]) && i > 0) {
365
+ // Pattern A 감지: .../{domain}/controller/... 또는 .../controller/{domain}/...
366
+ const prevDir = parts[i - 1];
367
+ const nextDir = parts[i + 1];
368
+
369
+ // {domain}/layer/ 패턴 (도메인이 레이어 앞에)
370
+ if (!skipNames.includes(prevDir) && !layerNames.includes(prevDir) && !prevDir.includes(".")) {
371
+ if (!javaDomains[prevDir]) javaDomains[prevDir] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "B" };
372
+ if (parts[i] === "controller") javaDomains[prevDir].controllers++;
373
+ else if (parts[i] === "service") javaDomains[prevDir].services++;
374
+ else if (["mapper", "repository", "dao"].includes(parts[i])) javaDomains[prevDir].mappers++;
375
+ else if (["dto", "vo"].includes(parts[i])) javaDomains[prevDir].dtos++;
376
+ }
377
+ // layer/{domain}/ 패턴 (레이어가 도메인 앞에)
378
+ if (nextDir && !nextDir.endsWith(".java") && !skipNames.includes(nextDir) && !layerNames.includes(nextDir)) {
379
+ if (!javaDomains[nextDir]) javaDomains[nextDir] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "A" };
380
+ if (parts[i] === "controller") javaDomains[nextDir].controllers++;
381
+ else if (parts[i] === "service") javaDomains[nextDir].services++;
382
+ else if (["mapper", "repository", "dao"].includes(parts[i])) javaDomains[nextDir].mappers++;
383
+ else if (["dto", "vo"].includes(parts[i])) javaDomains[nextDir].dtos++;
384
+ }
385
+ break;
386
+ }
387
+ }
388
+ }
389
+
390
+ for (const [d, data] of Object.entries(javaDomains)) {
391
+ const total = data.controllers + data.services + data.mappers + data.dtos;
392
+ if (total > 0) {
393
+ backendDomains.push({ name: d, type: "backend", ...data, totalFiles: total });
394
+ }
395
+ }
396
+ }
353
397
  }
354
398
 
355
399
  // ── Node.js 백엔드 (Express/NestJS) — 프론트엔드 존재 여부와 무관하게 스캔 ──
@@ -421,6 +465,67 @@ async function scanStructure(stack) {
421
465
  frontendDomains.push({ name: `comp-${name}`, type: "frontend", components: files.length, totalFiles: files.length });
422
466
  }
423
467
  }
468
+
469
+ // ── 폴백: 위 스캐너로 0개일 때 page.tsx/index.tsx 위치에서 직접 도메인 추출 ──
470
+ if (frontendDomains.length === 0) {
471
+ const pageFiles = await glob("**/page.{tsx,jsx}", { cwd: ROOT, ignore: ["**/node_modules/**", "**/.next/**"] });
472
+ const domainSet = {};
473
+ const skipNames = ["app", "src", "pages", "api", "_app", "_document"];
474
+ for (const f of pageFiles) {
475
+ const parts = f.replace(/\\/g, "/").split("/");
476
+ const appIdx = parts.indexOf("app");
477
+ const pagesIdx = parts.indexOf("pages");
478
+ const baseIdx = appIdx >= 0 ? appIdx : pagesIdx;
479
+ if (baseIdx >= 0 && baseIdx + 1 < parts.length - 1) {
480
+ const domain = parts[baseIdx + 1];
481
+ if (!skipNames.includes(domain) && !domain.startsWith("_") && !domain.startsWith("(") && !domain.startsWith(".")) {
482
+ if (!domainSet[domain]) domainSet[domain] = { pages: 0, clientFiles: 0, totalFiles: 0 };
483
+ domainSet[domain].pages++;
484
+ domainSet[domain].totalFiles++;
485
+ }
486
+ }
487
+ }
488
+ // client.tsx도 카운트
489
+ const clientFiles = await glob("**/client.{tsx,jsx}", { cwd: ROOT, ignore: ["**/node_modules/**", "**/.next/**"] });
490
+ for (const f of clientFiles) {
491
+ const parts = f.replace(/\\/g, "/").split("/");
492
+ const appIdx = parts.indexOf("app");
493
+ const baseIdx = appIdx >= 0 ? appIdx : -1;
494
+ if (baseIdx >= 0 && baseIdx + 1 < parts.length - 1) {
495
+ const domain = parts[baseIdx + 1];
496
+ if (domainSet[domain]) {
497
+ domainSet[domain].clientFiles++;
498
+ domainSet[domain].totalFiles++;
499
+ }
500
+ }
501
+ }
502
+ for (const [name, data] of Object.entries(domainSet)) {
503
+ frontendDomains.push({
504
+ name, type: "frontend", pages: data.pages, clientFiles: data.clientFiles, totalFiles: data.totalFiles,
505
+ rscPattern: data.clientFiles > 0 ? "RSC+Client split" : "default",
506
+ });
507
+ }
508
+
509
+ // widgets/features/entities도 직접 스캔 (글로브 폴백)
510
+ for (const layer of ["widgets", "features", "entities"]) {
511
+ const layerFiles = await glob(`**/${layer}/*/**/*.{tsx,jsx,ts,js}`, { cwd: ROOT, ignore: ["**/node_modules/**", "**/.next/**", "**/*.spec.*", "**/*.test.*"] });
512
+ const layerDomains = {};
513
+ for (const f of layerFiles) {
514
+ const parts = f.replace(/\\/g, "/").split("/");
515
+ const layerIdx = parts.indexOf(layer);
516
+ if (layerIdx >= 0 && layerIdx + 1 < parts.length) {
517
+ const domain = parts[layerIdx + 1];
518
+ if (!["ui", "common", "shared", "lib", "config"].includes(domain)) {
519
+ if (!layerDomains[domain]) layerDomains[domain] = 0;
520
+ layerDomains[domain]++;
521
+ }
522
+ }
523
+ }
524
+ for (const [name, count] of Object.entries(layerDomains)) {
525
+ frontendDomains.push({ name: `${layer}/${name}`, type: "frontend", totalFiles: count });
526
+ }
527
+ }
528
+ }
424
529
  }
425
530
 
426
531
  // ── Python/Django ──