claudeos-core 1.0.1 → 1.0.2

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,75 +1,75 @@
1
- {
2
- "name": "claudeos-core",
3
- "version": "1.0.1",
4
- "description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
5
- "main": "health-checker/index.js",
6
- "bin": {
7
- "claudeos-core": "bin/cli.js"
8
- },
9
- "files": [
10
- "bin/",
11
- "content-validator/",
12
- "health-checker/",
13
- "import-linter/",
14
- "manifest-generator/",
15
- "pass-json-validator/",
16
- "pass-prompts/",
17
- "plan-installer/",
18
- "plan-validator/",
19
- "sync-checker/",
20
- "bootstrap.sh",
21
- "README.md",
22
- "README.ko.md",
23
- "LICENSE",
24
- "CHANGELOG.md",
25
- "CONTRIBUTING.md",
26
- "README.zh-CN.md",
27
- "README.ja.md",
28
- "README.es.md",
29
- "README.vi.md",
30
- "README.hi.md",
31
- "README.ru.md",
32
- "README.fr.md",
33
- "README.de.md"
34
- ],
35
- "scripts": {
36
- "init": "node bin/cli.js init",
37
- "health": "node bin/cli.js health",
38
- "validate": "node bin/cli.js validate",
39
- "refresh": "node bin/cli.js refresh",
40
- "restore": "node bin/cli.js restore",
41
- "test": "node health-checker/index.js"
42
- },
43
- "keywords": [
44
- "claude-code",
45
- "automation",
46
- "code-analysis",
47
- "CLAUDE.md",
48
- "standards",
49
- "rules",
50
- "skills",
51
- "scaffolding",
52
- "spring-boot",
53
- "nextjs",
54
- "express",
55
- "django",
56
- "fastapi"
57
- ],
58
- "author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
59
- "license": "ISC",
60
- "repository": {
61
- "type": "git",
62
- "url": "git+https://github.com/claudeos-core/claudeos-core.git"
63
- },
64
- "homepage": "https://github.com/claudeos-core/claudeos-core#readme",
65
- "bugs": {
66
- "url": "https://github.com/claudeos-core/claudeos-core/issues"
67
- },
68
- "engines": {
69
- "node": ">=18.0.0"
70
- },
71
- "dependencies": {
72
- "glob": "^13.0.6",
73
- "gray-matter": "^4.0.3"
74
- }
75
- }
1
+ {
2
+ "name": "claudeos-core",
3
+ "version": "1.0.2",
4
+ "description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
5
+ "main": "health-checker/index.js",
6
+ "bin": {
7
+ "claudeos-core": "bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "content-validator/",
12
+ "health-checker/",
13
+ "import-linter/",
14
+ "manifest-generator/",
15
+ "pass-json-validator/",
16
+ "pass-prompts/",
17
+ "plan-installer/",
18
+ "plan-validator/",
19
+ "sync-checker/",
20
+ "bootstrap.sh",
21
+ "README.md",
22
+ "README.ko.md",
23
+ "LICENSE",
24
+ "CHANGELOG.md",
25
+ "CONTRIBUTING.md",
26
+ "README.zh-CN.md",
27
+ "README.ja.md",
28
+ "README.es.md",
29
+ "README.vi.md",
30
+ "README.hi.md",
31
+ "README.ru.md",
32
+ "README.fr.md",
33
+ "README.de.md"
34
+ ],
35
+ "scripts": {
36
+ "init": "node bin/cli.js init",
37
+ "health": "node bin/cli.js health",
38
+ "validate": "node bin/cli.js validate",
39
+ "refresh": "node bin/cli.js refresh",
40
+ "restore": "node bin/cli.js restore",
41
+ "test": "node health-checker/index.js"
42
+ },
43
+ "keywords": [
44
+ "claude-code",
45
+ "automation",
46
+ "code-analysis",
47
+ "CLAUDE.md",
48
+ "standards",
49
+ "rules",
50
+ "skills",
51
+ "scaffolding",
52
+ "spring-boot",
53
+ "nextjs",
54
+ "express",
55
+ "django",
56
+ "fastapi"
57
+ ],
58
+ "author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
59
+ "license": "ISC",
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "git+https://github.com/claudeos-core/claudeos-core.git"
63
+ },
64
+ "homepage": "https://github.com/claudeos-core/claudeos-core#readme",
65
+ "bugs": {
66
+ "url": "https://github.com/claudeos-core/claudeos-core/issues"
67
+ },
68
+ "engines": {
69
+ "node": ">=18.0.0"
70
+ },
71
+ "dependencies": {
72
+ "glob": "^13.0.6",
73
+ "gray-matter": "^4.0.3"
74
+ }
75
+ }
@@ -194,24 +194,117 @@ async function scanStructure(stack) {
194
194
  if (stack.language === "java") {
195
195
  const javaFiles = await glob("src/main/java/**/*.java", { cwd: ROOT });
196
196
  for (const f of javaFiles) {
197
- const m = f.match(/src\/main\/java\/(.+?)\/(controller|service|mapper|dto|entity|repository)/);
197
+ const m = f.match(/src\/main\/java\/(.+?)\/(controller|service|mapper|dto|entity|repository|adapter)/);
198
198
  if (m) { rootPackage = m[1].replace(/\//g, "."); break; }
199
199
  }
200
- const controllers = await glob("src/main/java/**/controller/*/*.java", { cwd: ROOT });
201
200
  const domainMap = {};
202
- for (const f of controllers) {
201
+ let detectedPattern = null;
202
+
203
+ // Pattern A: controller/{domain}/*.java (레이어 우선 — controller 아래에 도메인)
204
+ const controllersA = await glob("src/main/java/**/controller/*/*.java", { cwd: ROOT });
205
+ for (const f of controllersA) {
203
206
  const m = f.match(/controller\/([^/]+)\//);
204
207
  if (m) {
205
208
  const d = m[1];
206
- if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0 };
209
+ if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "A" };
207
210
  domainMap[d].controllers++;
208
211
  }
209
212
  }
213
+ if (Object.keys(domainMap).length > 0) detectedPattern = "A";
214
+
215
+ // Pattern B/D: {domain}/controller/*.java (도메인 우선 — 도메인 아래에 controller)
216
+ // D는 B의 확장: {module}/{domain}/controller/ — 동일 도메인명 충돌 시 module/domain 형태로 전환
217
+ if (!detectedPattern) {
218
+ const controllersB = await glob("src/main/java/**/*/controller/*.java", { cwd: ROOT });
219
+ const domainPaths = {};
220
+ for (const f of controllersB) {
221
+ const m = f.match(/\/([^/]+)\/controller\/[^/]+\.java$/);
222
+ if (m) {
223
+ const d = m[1];
224
+ const parentMatch = f.match(/\/([^/]+)\/([^/]+)\/controller\//);
225
+ const parentModule = parentMatch ? parentMatch[1] : null;
226
+ if (!domainPaths[d]) domainPaths[d] = [];
227
+ domainPaths[d].push({ file: f, module: parentModule });
228
+ }
229
+ }
230
+
231
+ // 동일 도메인명이 여러 모듈에서 발견되면 module/domain 형태로 (Pattern D)
232
+ for (const [d, entries] of Object.entries(domainPaths)) {
233
+ const modules = [...new Set(entries.map(e => e.module).filter(Boolean))];
234
+ if (modules.length > 1) {
235
+ // Pattern D: 충돌 — module/domain 형태로 등록
236
+ for (const entry of entries) {
237
+ const fullName = entry.module ? `${entry.module}/${d}` : d;
238
+ if (!domainMap[fullName]) domainMap[fullName] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "D", modulePath: entry.module, domainName: d };
239
+ domainMap[fullName].controllers++;
240
+ }
241
+ } else {
242
+ if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "B" };
243
+ domainMap[d].controllers += entries.length;
244
+ }
245
+ }
246
+ if (Object.keys(domainMap).length > 0) detectedPattern = domainMap[Object.keys(domainMap)[0]].pattern;
247
+ }
248
+
249
+ // Pattern E: DDD/헥사고날 — {domain}/adapter/in/web/*.java 또는 {domain}/adapter/in/rest/*.java
250
+ if (!detectedPattern) {
251
+ const controllersE = await glob("src/main/java/**/adapter/in/{web,rest}/*.java", { cwd: ROOT });
252
+ for (const f of controllersE) {
253
+ const m = f.match(/\/([^/]+)\/adapter\/in\/(web|rest)\/[^/]+\.java$/);
254
+ if (m) {
255
+ const d = m[1];
256
+ if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "E" };
257
+ domainMap[d].controllers++;
258
+ }
259
+ }
260
+ if (Object.keys(domainMap).length > 0) detectedPattern = "E";
261
+ }
262
+
263
+ // Pattern C: 플랫 구조 — controller/*.java (도메인 디렉토리 없음, 클래스명에서 도메인 추출)
264
+ if (!detectedPattern) {
265
+ const controllersC = await glob("src/main/java/**/controller/*.java", { cwd: ROOT });
266
+ for (const f of controllersC) {
267
+ const m = f.match(/\/([A-Z][a-zA-Z]*)Controller\.java$/);
268
+ if (m) {
269
+ const d = m[1].toLowerCase();
270
+ if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "C" };
271
+ domainMap[d].controllers++;
272
+ }
273
+ }
274
+ if (Object.keys(domainMap).length > 0) detectedPattern = "C";
275
+ }
276
+
277
+ // 각 도메인의 service/mapper/dto/xml 파일 스캔
210
278
  for (const d of Object.keys(domainMap)) {
211
- const svc = await glob(`src/main/java/**/service/${d}/*.java`, { cwd: ROOT });
212
- const mpr = await glob(`src/main/java/**/{mapper,repository}/${d}/*.java`, { cwd: ROOT });
213
- const dto = await glob(`src/main/java/**/dto/${d}/**/*.java`, { cwd: ROOT });
214
- const xml = await glob(`src/main/resources/mapper/**/${d}/*.xml`, { cwd: ROOT });
279
+ const p = domainMap[d].pattern;
280
+ const dn = domainMap[d].domainName || d;
281
+ let svcGlob, mprGlob, dtoGlob;
282
+
283
+ if (p === "A") {
284
+ svcGlob = `src/main/java/**/service/${d}/*.java`;
285
+ mprGlob = `src/main/java/**/{mapper,repository}/${d}/*.java`;
286
+ dtoGlob = `src/main/java/**/dto/${d}/**/*.java`;
287
+ } else if (p === "B" || p === "D") {
288
+ svcGlob = `src/main/java/**/${dn}/service/*.java`;
289
+ mprGlob = `src/main/java/**/${dn}/{mapper,repository}/*.java`;
290
+ dtoGlob = `src/main/java/**/${dn}/dto/**/*.java`;
291
+ } else if (p === "E") {
292
+ svcGlob = `src/main/java/**/${d}/{application,domain}/**/*.java`;
293
+ mprGlob = `src/main/java/**/${d}/adapter/out/{persistence,repository}/*.java`;
294
+ dtoGlob = `src/main/java/**/${d}/**/{dto,command,query}/**/*.java`;
295
+ } else {
296
+ // Pattern C: 플랫 — 도메인명으로 파일명 매칭
297
+ const cap = d.charAt(0).toUpperCase() + d.slice(1);
298
+ svcGlob = `src/main/java/**/service/${cap}*.java`;
299
+ mprGlob = `src/main/java/**/{mapper,repository}/${cap}*.java`;
300
+ dtoGlob = `src/main/java/**/dto/${cap}*.java`;
301
+ }
302
+ const xmlGlob = `src/main/resources/mapper/**/${dn}/*.xml`;
303
+
304
+ const svc = await glob(svcGlob, { cwd: ROOT });
305
+ const mpr = await glob(mprGlob, { cwd: ROOT });
306
+ const dto = await glob(dtoGlob, { cwd: ROOT });
307
+ const xml = await glob(xmlGlob, { cwd: ROOT });
215
308
  domainMap[d].services = svc.length;
216
309
  domainMap[d].mappers = mpr.length;
217
310
  domainMap[d].dtos = dto.length;