@simplysm/sd-claude 14.0.88 → 14.0.89

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.
Files changed (122) hide show
  1. package/claude/references/sd-simplysm14/README.md +17 -17
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +27 -53
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +37 -105
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +46 -43
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +22 -32
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +40 -55
  7. package/claude/references/sd-simplysm14/apis/angular/infra.md +40 -40
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +25 -53
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +70 -82
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +44 -39
  11. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +21 -36
  12. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +52 -65
  13. package/claude/references/sd-simplysm14/apis/angular/sheet.md +65 -70
  14. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +33 -35
  15. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +7 -7
  16. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +29 -29
  17. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +45 -50
  18. package/claude/references/sd-simplysm14/apis/core-browser/README.md +42 -55
  19. package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +62 -0
  20. package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +13 -12
  21. package/claude/references/sd-simplysm14/apis/core-common/README.md +222 -98
  22. package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +102 -53
  23. package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +128 -0
  24. package/claude/references/sd-simplysm14/apis/core-common/datetime.md +98 -64
  25. package/claude/references/sd-simplysm14/apis/core-common/errors.md +91 -0
  26. package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +34 -28
  27. package/claude/references/sd-simplysm14/apis/core-common/obj.md +104 -40
  28. package/claude/references/sd-simplysm14/apis/core-node/README.md +11 -8
  29. package/claude/references/sd-simplysm14/apis/core-node/consola.md +23 -31
  30. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +33 -22
  31. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +28 -25
  32. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +39 -53
  33. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +26 -29
  34. package/claude/references/sd-simplysm14/apis/core-node/worker.md +27 -29
  35. package/claude/references/sd-simplysm14/apis/excel/README.md +14 -14
  36. package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
  37. package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
  38. package/claude/references/sd-simplysm14/apis/orm-common/README.md +5 -59
  39. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +98 -67
  40. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +107 -92
  41. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +99 -65
  42. package/claude/references/sd-simplysm14/apis/orm-common/schema.md +83 -98
  43. package/claude/references/sd-simplysm14/apis/orm-common/types.md +62 -52
  44. package/claude/references/sd-simplysm14/apis/orm-node/README.md +62 -25
  45. package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +27 -27
  46. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +12 -15
  47. package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
  48. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
  49. package/claude/references/sd-simplysm14/apis/service-client/README.md +84 -86
  50. package/claude/references/sd-simplysm14/apis/service-client/orm.md +14 -11
  51. package/claude/references/sd-simplysm14/apis/service-client/transport.md +33 -10
  52. package/claude/references/sd-simplysm14/apis/service-common/README.md +37 -23
  53. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +9 -9
  54. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +13 -13
  55. package/claude/references/sd-simplysm14/apis/service-server/README.md +81 -65
  56. package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +32 -35
  57. package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +44 -33
  58. package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +34 -45
  59. package/claude/references/sd-simplysm14/apis/storage/README.md +24 -18
  60. package/claude/skills/sd-demo/SKILL.md +6 -0
  61. package/claude/skills/sd-impl/SKILL.md +4 -7
  62. package/claude/skills/sd-spec/SKILL.md +31 -858
  63. package/claude/skills/sd-spec/references/spec-authoring.md +519 -0
  64. package/claude/workflows/sd-docs.js +84 -0
  65. package/package.json +1 -1
  66. package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
  67. package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
  68. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
  69. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
  70. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
  71. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
  72. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
  73. package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
  74. package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
  75. package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
  76. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
  77. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
  78. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
  79. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
  80. package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
  81. package/claude/skills/sd-docs/SKILL.md +0 -46
  82. package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
  83. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
  84. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
  85. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
  86. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
  87. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
  88. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
  89. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
  90. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
  91. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
  92. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
  93. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
  94. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
  95. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
  96. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
  97. package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
  98. package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
  99. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
  100. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
  101. package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
  102. package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
  103. package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
  104. package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
  105. package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
  106. package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
  107. package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
  108. package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
  109. package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
  110. package/claude/skills/sd-review/evals/golden.jsonl +0 -2
  111. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
  112. package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
  113. package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
  114. package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
  115. package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
  116. package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
  117. package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
  118. package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
  119. package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
  120. package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
  121. package/claude/skills/sd-use/evals/golden.jsonl +0 -6
  122. /package/claude/{skills/sd-docs/references/doc-rules.md → workflows/sd-docs.rules.md} +0 -0
@@ -1,86 +1,72 @@
1
1
  # @simplysm/core-node — fsx
2
2
 
3
- `import { fsx } from "@simplysm/core-node"`. Node `fs` 래퍼 네임스페이스. 대부분 함수는 동기(`...Sync`) 비동기(Promise) 쌍으로 제공된다. IO 실패 시 `SdError(err, targetPath)` 로 경로를 포함해 throw 하고, 쓰기 계열은 상위 디렉토리를 자동 생성한다.
3
+ `export * as fsx` 네임스페이스 (`packages/core-node/src/utils/fs.ts`). Node `fs` 감싼 파일시스템 IO. 대부분 동기(`...Sync`)/비동기 쌍을 제공하며, 실패 시 모두 `SdError(err, targetPath)` 로 원인+경로를 붙여 throw 한다. 항상 `fsx.<fn>(...)` 형태로 호출.
4
4
 
5
5
  ## 존재 확인
6
6
 
7
- - `existsSync(targetPath: string): boolean` / `exists(targetPath: string): Promise<boolean>` — 파일/디렉토리 존재 여부. 비동기는 `fs.access` 실패를 throw 하지 않고 false 반환. 파일·디렉토리 구분은 없음.
7
+ - `existsSync(targetPath: string): boolean` / `exists(targetPath: string): Promise<boolean>` — 파일/디렉토리 존재 여부. 비동기 버전은 `fs.access` 실패를 catch false 반환(throw 함).
8
8
 
9
9
  ## 디렉토리 생성
10
10
 
11
- - `mkdirSync(targetPath: string): void` / `mkdir(targetPath: string): Promise<void>` — `recursive: true` 재귀 생성. 이미 존재하면 무시.
12
-
13
- ```ts
14
- await fsx.mkdir("dist/sub");
15
- ```
11
+ - `mkdirSync(targetPath: string): void` / `mkdir(targetPath: string): Promise<void>` — 재귀 생성(`recursive: true`). 중간 경로가 없어도 전부 만든다.
16
12
 
17
13
  ## 삭제
18
14
 
19
- - `rmSync(targetPath: string): void` — 재귀·force 삭제, **재시도 없이 즉시 실패**. 파일 잠금 우려가 있으면 비동기 `rm` 사용.
20
- - `rm(targetPath: string): Promise<void>` — 재귀·force 삭제, 일시 오류 500ms 간격 최대 6회 재시도(Windows 잠금 대응).
15
+ - `rmSync(targetPath: string): void` — 재귀+force 삭제. **재시도 없이 즉시 실패**. 파일 잠금 일시 오류가 예상되면 비동기 `rm` 을 쓸 것.
16
+ - `rm(targetPath: string): Promise<void>` — 재귀+force 삭제. 일시 오류에 대해 **500ms 간격 최대 6회 재시도**(`retryDelay: 500, maxRetries: 6`).
21
17
 
22
18
  ## 복사
23
19
 
24
- - `copySync(sourcePath: string, targetPath: string, filter?): void` / `copy(...): Promise<void>` — 파일·디렉토리 재귀 복사. **source 미존재 아무 작업 없이 반환**. 파일 복사는 실패 시 500ms 간격 최대 7회(0~6) 재시도. 비동기는 디렉토리 하위를 `parallelAsync` 병렬 복사.
25
- - `filter?: (absolutePath: string) => boolean` — 하위 항목마다 **절대 경로**로 호출, true 복사. 최상위 source 자신은 필터 대상 아님. 디렉토리에 false 면 그 디렉토리와 모든 하위를 건너뜀. 특정 확장자·폴더만 복사할 때 사용.
20
+ - `copySync(sourcePath, targetPath, filter?): void` / `copy(sourcePath, targetPath, filter?): Promise<void>` — 파일/디렉토리 복사. async 하위 항목을 `parallelAsync` 병렬 복사.
21
+ - `sourcePath: string` — 원본. **존재하지 않으면 아무 것도 하고 반환**(throw 함).
22
+ - `targetPath: string` — 대상. 디렉토리면 대상 디렉토리를 만들고 하위를 재귀 복사, 파일이면 상위 디렉토리 생성 후 복사.
23
+ - `filter?: (absolutePath: string) => boolean` — 복사 여부 결정. 각 하위 항목의 **절대 경로**가 전달되며 true=복사, false=제외. **최상위 sourcePath 자신은 필터 대상 아님**. 디렉토리에 false 면 그 디렉토리와 모든 내용을 건너뜀. 빌드 산출물 중 특정 파일만 복사할 때 사용.
24
+ - 파일 복사 실패 시 500ms busy-wait(sync)/setTimeout(async) 으로 최대 7회 시도 후 실패하면 `SdError` throw.
26
25
 
27
- ```ts
28
- await fsx.copy("src", "dist", (p) => !p.endsWith(".map"));
29
- ```
30
-
31
- ## 파일 읽기
32
-
33
- - `readSync(targetPath: string): string` / `read(...): Promise<string>` — UTF-8 문자열로 읽기.
34
- - `readBytesSync(targetPath: string): Uint8Array` / `readBytes(...): Promise<Uint8Array>` — 바이너리로 읽기.
35
- - `readJsonSync<TData = unknown>(targetPath: string): TData` / `readJson<TData = unknown>(...): Promise<TData>` — `@simplysm/core-common` 의 `json.parse` 로 파싱(표준 `JSON` 아님 — Date 등 확장 타입 복원). 파싱 실패 시 경로 + 내용 500자 프리뷰를 포함해 throw.
36
-
37
- ```ts
38
- const cfg = await fsx.readJson<{ version: string }>("package.json");
39
- ```
26
+ ## 읽기
40
27
 
41
- ## 파일 쓰기
28
+ - `readSync(targetPath: string): string` / `read(...): Promise<string>` — UTF-8 문자열로 읽음.
29
+ - `readBytesSync(targetPath: string): Uint8Array` / `readBytes(...): Promise<Uint8Array>` — 바이너리로 읽음.
30
+ - `readJsonSync<TData = unknown>(targetPath): TData` / `readJson<TData = unknown>(...): Promise<TData>` — 읽어 `json.parse`(`@simplysm/core-common`, Date 등 특수타입 복원) 로 파싱. 파싱 실패 시 SdError 메시지에 내용 앞 500자 프리뷰를 첨부.
42
31
 
43
- - `writeSync(targetPath: string, data: string | Uint8Array): void` / `write(...): Promise<void>` — 상위 디렉토리 자동 생성 후 `flush: true` 로 기록(데이터 손실 방지 강제 플러시).
44
- - `writeJsonSync(targetPath: string, data: unknown, options?): void` / `writeJson(...): Promise<void>` — `json.stringify` 로 직렬화 후 기록.
45
- - `options.replacer?: (this, key: string | undefined, value: unknown) => unknown` — 직렬화 시 값 변환 replacer.
46
- - `options.space?: string | number` — 들여쓰기(가독 출력용).
32
+ ## 쓰기
47
33
 
48
- ```ts
49
- await fsx.writeJson("out.json", data, { space: 2 });
50
- ```
34
+ - `writeSync(targetPath, data): void` / `write(targetPath, data): Promise<void>` — **상위 디렉토리 자동 생성** 후 기록(`flush: true`).
35
+ - `data: string | Uint8Array` — 텍스트 또는 바이너리.
36
+ - `writeJsonSync(targetPath, data, options?): void` / `writeJson(targetPath, data, options?): Promise<void>` — `json.stringify` 로 직렬화 후 write.
37
+ - `data: unknown` — 직렬화 대상.
38
+ - `options?.replacer?: (this, key, value) => unknown` — JSON.stringify 의 replacer 와 동일 역할. 특정 키 값을 변환·제외할 때.
39
+ - `options?.space?: string | number` — 들여쓰기. 사람이 읽을 파일이면 `2` 같은 값 지정.
51
40
 
52
41
  ## 디렉토리 읽기
53
42
 
54
- - `readdirSync(targetPath: string): string[]` / `readdir(...): Promise<string[]>` — 직속 항목 이름(상대 이름) 배열. 절대 경로 아님.
43
+ - `readdirSync(targetPath: string): string[]` / `readdir(...): Promise<string[]>` — 디렉토리 직계 항목명(경로 아님) 배열.
55
44
 
56
45
  ## 파일 정보
57
46
 
58
- - `statSync(targetPath: string): fs.Stats` / `stat(...): Promise<fs.Stats>` — 심볼릭 링크를 따라간 stat.
59
- - `lstatSync(targetPath: string): fs.Stats` / `lstat(...): Promise<fs.Stats>` — 링크 자체의 stat(링크 비추적). 링크 여부 판별·복사 분기에 사용.
47
+ - `statSync(targetPath): fs.Stats` / `stat(...): Promise<fs.Stats>` — 정보 조회. **심볼릭 링크를 따라감**(링크 대상의 정보).
48
+ - `lstatSync(targetPath): fs.Stats` / `lstat(...): Promise<fs.Stats>` — 정보 조회. **심볼릭 링크를 따라가지 않음**(링크 자체 정보). 링크/실파일을 구분해야 하면 lstat.
60
49
 
61
50
  ## Glob
62
51
 
63
- - `globSync(pattern: string, options?: GlobOptions): string[]` / `glob(...): Promise<string[]>` — glob 매칭. 입력 패턴의 `\` 를 `/` 로 치환하고, 결과는 `path.resolve` **절대 경로** 배열.
64
- - `options?: GlobOptions` — `glob` 라이브러리 옵션(`dot`, `ignore`, `nodir` 등).
65
-
66
- ```ts
67
- const files = await fsx.glob("src/**/*.ts", { ignore: ["**/*.d.ts"] });
68
- ```
52
+ - `globSync(pattern: string, options?: GlobOptions): string[]` / `glob(...): Promise<string[]>` — glob 검색. 입력 패턴의 `\` 를 `/` 로 치환해 매칭하고, 결과는 모두 `path.resolve` **절대 경로**화해 반환.
53
+ - `pattern: string` — glob 패턴(예: `"src/**/*.ts"`).
54
+ - `options?: GlobOptions` — `glob` 패키지 옵션 그대로(`dot`, `cwd`, `ignore` 등). 숨김 파일 포함하려면 `{ dot: true }`.
69
55
 
70
56
  ## 유틸리티
71
57
 
72
- - `clearEmptyDirectory(dirPath: string): Promise<void>` — 하위를 재귀 순회해 파일이 하나도 없는 디렉토리를 삭제(하위 삭제로 비게 상위도 삭제). 미존재 무시.
73
- - `findAllParentChildPathsSync(childGlob: string, fromPath: string, rootPath?: string): string[]` / `findAllParentChildPaths(...): Promise<string[]>` — fromPath 에서 루트 방향으로 부모 디렉토리를 순회하며 각 디렉토리에서 `childGlob` 매칭 파일을 수집(절대 경로). `tsconfig.json` 설정 파일 상향 탐색에 사용.
74
- - `childGlob` — 각 디렉토리에서 검색할 glob 패턴.
75
- - `fromPath` — 탐색 시작 경로.
76
- - `rootPath?` — 탐색 중단 경로. 미지정이거나 fromPath rootPath 하위가 아니면 파일시스템 루트까지 올라감.
58
+ - `clearEmptyDirectory(dirPath: string): Promise<void>` — `dirPath` 하위를 재귀 순회하며 **빈 디렉토리만** 삭제. 하위가 모두 비어 상위도 비게 되면 상위도 삭제. 파일이 하나라도 있으면 그 디렉토리는 보존. 존재하지 않으면 즉시 반환.
59
+ - `findAllParentChildPathsSync(childGlob, fromPath, rootPath?): string[]` / `findAllParentChildPaths(...): Promise<string[]>` — `fromPath` 에서 루트 방향으로 부모 디렉토리를 거슬러 올라가며 각 디렉토리에서 `childGlob` 매칭 파일을 모아 평탄화 반환. 상위 디렉토리의 설정 파일(예: 단계 `package.json`) 수집에 사용.
60
+ - `childGlob: string` — 각 디렉토리에서 검색할 glob.
61
+ - `fromPath: string` — 탐색 시작 경로.
62
+ - `rootPath?: string` — 탐색 중단 경로. 생략 시 파일시스템 루트까지. **주의: fromPath rootPath 하위여야 함**, 아니면 루트까지 올라간다.
63
+
64
+ ## 사용 예
77
65
 
78
66
  ```ts
79
- const tsconfigs = await fsx.findAllParentChildPaths("tsconfig.json", srcDir, projectRoot);
67
+ import { fsx } from "@simplysm/core-node";
68
+ await fsx.writeJson("dist/meta.json", { builtAt: new Date() }, { space: 2 });
69
+ await fsx.copy("src", "dist", (p) => !p.endsWith(".ts")); // .ts 제외 복사
70
+ const pkgs = await fsx.findAllParentChildPaths("package.json", process.cwd());
80
71
  ```
81
-
82
- ## 주의사항
83
-
84
- - 동기 `rmSync`/`copySync` 는 재시도 동작이 비동기와 다름(rmSync 는 무재시도). Windows EPERM/잠금이 우려되면 비동기 버전 사용.
85
- - glob 결과는 항상 절대 경로 — 상대 경로가 필요하면 호출 측에서 `path.relative` 처리.
86
- - JSON IO 는 표준 `JSON` 이 아닌 `@simplysm/core-common` 의 `json` 사용 — Date 등 확장 타입 복원이 다름.
72
+ </content>
@@ -1,42 +1,39 @@
1
1
  # @simplysm/core-node — pathx
2
2
 
3
- `import { pathx } from "@simplysm/core-node"`. 경로 정규화·판정·치환 유틸 네임스페이스. 내부 비교는 항상 POSIX 슬래시 기준이다.
3
+ `export * as pathx` 네임스페이스 (`packages/core-node/src/utils/path.ts`). 경로 문자열 가공·판정 유틸. OS 무관 비교를 위해 POSIX 슬래시(`/`)로 정규화하는 것이 핵심. `pathx.<fn>(...)` 형태로 호출.
4
4
 
5
- ## PosixPath 생성
5
+ ## PosixPath (브랜드 타입)
6
6
 
7
- - `posix(p: string): PosixPath` — `\` `/` 치환만 수행(resolve·결합 ). 반환은 브랜드 타입 `PosixPath`.
8
- - `posixResolve(...args: string[]): PosixPath` — `path.resolve` 로 절대 경로화한 뒤 슬래시 치환. 상대 입력은 cwd 기준으로 절대화.
9
- - `PosixPath` — `string & { [POSIX]: never }` 브랜드 타입. `posix`/`posixResolve` 로만 생성 가능. POSIX 슬래시 경로임을 타입으로 보장할 때 쓰임(예: `FsWatcherChangeInfo.path`).
7
+ - `type PosixPath = string & { [POSIX]: never }` — POSIX 슬래시 경로임을 나타내는 브랜드 타입. `posix()`/`posixResolve()` 로만 생성 가능. 일반 `string` 을 PosixPath 자리에 직접 넣을 수 없어, 정규화를 강제하는 타입 가드 역할.
10
8
 
11
- ```ts
12
- pathx.posix("C:\\a\\b"); // "C:/a/b"
13
- pathx.posixResolve("a", "b"); // "<cwd>/a/b"
14
- ```
9
+ ## 정규화
15
10
 
16
- ## 판정·치환
11
+ - `posix(p: string): PosixPath` — 백슬래시 → 슬래시 치환만 수행. **결합·resolve 안 함**. 예: `posix("C:\\Users\\test")` → `"C:/Users/test"`. 이미 절대 경로인 문자열을 POSIX 표기로만 바꿀 때.
12
+ - `posixResolve(...args: string[]): PosixPath` — 인자들을 `path.resolve` 로 절대 경로 결합 후 슬래시로 변환. 예: `posixResolve("/base", "sub", "f.txt")` → `"/base/sub/f.txt"`, 상대경로 단독이면 cwd 기준 절대화. 경로 결합+정규화를 동시에 할 때.
17
13
 
18
- - `isChildPath(childPath: string, parentPath: string): boolean` — child 가 parent 의 하위인지. **동일 경로는 false**. 내부적으로 양쪽을 `posixResolve` 정규화 후 `parent + "/"` 접두 비교.
19
- - `changeFileDirectory(filePath: string, fromDirectory: string, toDirectory: string): string` — filePath 의 소속 디렉토리를 from→to 로 교체. `filePath === fromDirectory` 면 toDirectory 반환. from 하위가 아니면 `ArgumentError` throw. 빌드 출력 경로 산출에 사용.
20
- - `basenameWithoutExt(filePath: string): string` — 마지막 확장자만 제거한 basename. `file.spec.ts` → `file.spec`.
14
+ ## 경로 가공
21
15
 
22
- ```ts
23
- pathx.isChildPath("/a/b/c", "/a/b"); // true
24
- pathx.changeFileDirectory("/src/x.ts", "/src", "/dist"); // "/dist/x.ts"
25
- ```
16
+ - `changeFileDirectory(filePath, fromDirectory, toDirectory): string` — `filePath` 의 디렉토리 prefix 를 `fromDirectory` → `toDirectory` 로 치환(상대 위치 유지). 예: `("/a/b/c.txt", "/a", "/x")` → `"/x/b/c.txt"`. `filePath === fromDirectory` 면 `toDirectory` 반환. **filePath 가 fromDirectory 내부가 아니면 `ArgumentError` throw**. src→dist 같은 출력 경로 산출에 사용.
26
17
 
27
- ## 타겟 필터링
18
+ ## 판정·필터링
28
19
 
29
- - `filterByTargets(files: string[], targets: string[], cwd: string): string[]` files targets 경로와 일치하거나 하위인 것만 반환.
30
- - `files` — 필터링할 파일 경로. cwd 하위 절대 경로 권장(cwd 외부 경로는 `../` 상대로 변환되어 매칭이 어려움).
31
- - `targets` — cwd 기준 상대 경로(POSIX 슬래시 권장). **빈 배열이면 files 그대로 반환**("필터 없음" 의미).
32
- - `cwd` — 절대 기준 디렉토리. files cwd 상대 경로를 만들어 target 비교.
20
+ - `isChildPath(childPath, parentPath): boolean` `childPath` `parentPath` 하위인지. 양쪽을 `posixResolve` 정규화 비교. **동일 경로면 false**(자기 자신은 하위 아님). 경계 오탐 방지를 위해 parent 끝에 `/` 를 붙여 비교.
21
+ - `filterByTargets(files, targets, cwd): string[]` — 파일 목록을 타겟 경로 하위만 남김.
22
+ - `files: string[]` — 필터링할 파일. **cwd 하위 절대 경로여야 함**(외부 경로는 `../` 상대경로로 변환되어 매칭 실패 가능).
23
+ - `targets: string[]` — 대상 경로(cwd 기준 상대, POSIX 권장). 각 파일의 cwd-상대경로가 target 같거나 `target + "/"` 로 시작하면 통과.
24
+ - `cwd: string` — 기준 작업 디렉토리(절대 경로).
25
+ - **`targets` 가 비면 `files` 를 그대로 반환**(필터 미적용). CLI 의 `-t <패키지>` 같은 부분 빌드 대상 한정에 사용.
33
26
 
34
- ```ts
35
- pathx.filterByTargets(["/p/src/a.ts", "/p/tests/c.ts"], ["src"], "/p");
36
- //["/p/src/a.ts"]
37
- ```
27
+ ## 파일명
28
+
29
+ - `basenameWithoutExt(filePath: string): string` — 확장자 1단계만 제거한 basename. 예: `"file.txt"` `"file"`, `"a/file.spec.ts"` → `"file.spec"`(마지막 확장자만 제거).
38
30
 
39
- ## 주의사항
31
+ ## 사용 예
40
32
 
41
- - `filterByTargets` 의 `targets` 가 비면 전체 통과 — 빈 결과를 기대하지 말 것.
42
- - `changeFileDirectory` 범위 입력을 silent 처리하지 않고 throw 하므로, 호출 전 `isChildPath` 로 보장하거나 throw 를 처리.
33
+ ```ts
34
+ import { pathx } from "@simplysm/core-node";
35
+ const out = pathx.changeFileDirectory(srcFile, "/proj/src", "/proj/dist");
36
+ if (pathx.isChildPath(out, "/proj")) { /* ... */ }
37
+ const targeted = pathx.filterByTargets(allFiles, ["src", "tests"], process.cwd());
38
+ ```
39
+ </content>
@@ -1,54 +1,52 @@
1
- # @simplysm/core-node — Worker
1
+ # @simplysm/core-node — worker
2
2
 
3
- worker_threads 를 타입 안전 RPC + 이벤트로 감싼다. 워커 파일은 `createWorker` 로 메서드 묶음을 `export default` 하고, 메인은 `Worker.create<typeof import("...")>()` 로 프록시를 만들어 메서드를 직접 호출한다. 인자/반환은 `@simplysm/core-common` 의 `transfer`(structured clone + transferList) 직렬화된다.
3
+ `worker_threads` 를 타입 안전하게 쓰기 위한 래퍼. 워커 파일에서 `createWorker(methods)` 로 메서드 묶음을 export 하고, 메인에서 `Worker.create<typeof import("./worker")>(path)` 로 프록시를 만들어 `await worker.method(...)` 처럼 호출. 메시지 직렬화는 `@simplysm/core-common` 의 `transfer`(Date/특수타입·transferList 지원)를 사용한다. 개발(.ts)·프로덕션(.js) 양쪽을 자동 분기한다.
4
4
 
5
- ## createWorker (워커 측)
5
+ ## createWorker (워커 스레드 측)
6
6
 
7
- - `createWorker<TMethods, TEvents>(methods: TMethods): { send; __methods; __events }` — 워커 스레드 내에서 메서드 핸들러를 등록. 반환값을 `export default` 한다. `parentPort` 가 없으면(메인에서 직접 실행) `SdError` throw.
8
- - `methods: Record<string, (...args: any[]) => unknown>` — RPC 노출할 메서드. 반환은 동기/Promise 무관(메인에선 항상 Promise). 핸들러 throw 메인 호출에서 reject 전파.
9
- - `TEvents extends Record<string, unknown>` — 워커→메인 이벤트 페이로드 타입 맵(선택, 기본은 이벤트 없음).
10
- - `send<TEventName extends keyof TEvents & string>(event, data?): void` — 워커→메인 이벤트 전송.
11
- - `__methods` / `__events` — 타입 추론 전용 필드(런타임 의미 없음). 메인의 `Worker.create` 가 시그니처를 끌어올 사용.
12
- - 워커의 `process.stdout.write` 는 내부에서 가로채져 메시지 프로토콜로 메인의 stdout 에 전달됨(워커 로그가 메인 콘솔에 보임).
7
+ - `createWorker<TMethods, TEvents>(methods): { send; __methods; __events }` — 워커 스레드 진입 파일에서 호출하고 반환을 `export default`. `parentPort` 가 없으면(워커 컨텍스트 아님) `SdError` throw. 메서드 호출 메시지를 수신해 실행 후 결과/에러를 응답하고, 워커의 `process.stdout.write` 를 가로채 메인으로 로그를 전달한다.
8
+ - `methods: TMethods` (`Record<string, (...args) => unknown>`)워커가 제공할 메서드 맵. 동기/비동기 모두 가능(await ). 없는 메서드 호출 `SdError("알 수 없는 메서드: ...")` 응답.
9
+ - 제네릭 `TEvents extends Record<string, unknown>` — 워커가 보낼 이벤트명→데이터 타입 맵(메인의 `on` 타입 추론에 사용).
10
+ - 반환 `send<K extends keyof TEvents & string>(event, data?)` — 워커→메인 이벤트 전송. 진행률 등 메서드 반환과 별개 통지에 사용.
11
+ - 반환 `__methods`/`__events` — 타입 추론용 마커(런타임에 `Worker.create` 가 직접 쓰진 않음, 타입에서만 참조).
13
12
 
14
13
  ```ts
15
14
  // worker.ts
16
- interface Events { progress: number }
15
+ interface MyEvents { progress: number; }
17
16
  const methods = {
18
17
  calc: (x: number) => { sender.send("progress", 50); return x * 2; },
19
18
  };
20
- const sender = createWorker<typeof methods, Events>(methods);
19
+ const sender = createWorker<typeof methods, MyEvents>(methods);
21
20
  export default sender;
22
21
  ```
23
22
 
24
23
  ## Worker.create (메인 측)
25
24
 
26
- - `Worker.create<TModule extends WorkerModule>(filePath: string, opt?): WorkerProxy<TModule>` — 워커를 띄우고 프록시 반환. `.ts` 경로면 `lib/worker-dev-proxy.js`(tsx) 경유 로드, `.js` 직접 로드. `file://` URL / 절대 경로 모두 허용.
27
- - `filePath` — 워커 파일 경로.
28
- - `opt?: Omit<WorkerRawOptions, "stdout" | "stderr">` — `worker_threads` `WorkerOptions`(단 `stdout`/`stderr` 제외 내부에서 항상 캡처해 파이프). `opt.env` 는 `process.env` 위에 머지, `opt.argv` 는 워커 인자.
29
- - `WorkerProxy<TModule>` — 프록시 형태:
30
- - 각 메서드 — `(...args) => Promise<Awaited<R>>`. 호출하면 RPC. 워커 핸들러 에러는 reject.
31
- - `on(event, listener)` / `off(event, listener)` — 워커 `send` 이벤트 구독/해제.
32
- - `terminate(): Promise<void>` — 워커 종료. 대기 중 요청은 reject.
25
+ - `Worker.create<TModule extends WorkerModule>(filePath, opt?): WorkerProxy<TModule>` — 워커 스레드를 띄우고 메서드 프록시를 반환. 메서드 호출은 메시지로 전달되어 결과가 Promise 로 resolve/reject 된다. 워커 stdout/stderr 메인 프로세스로 파이프되며, 워커 비정상 종료(exit code≠0)·error 대기 중인 모든 호출이 reject 된다. 로거 태그 `sd-worker`.
26
+ - `filePath: string` — 워커 파일 경로. `file://` URL 또는 절대 경로. 확장자가 `.ts` 면 dev 모드로 `lib/worker-dev-proxy.js`(tsx 로 TS 동적 로드)를 통해 실행, `.js` 면 직접 실행.
27
+ - `opt?: Omit<WorkerRawOptions, "stdout" | "stderr">` — worker_threads 옵션(stdout/stderr 내부 고정이라 제외). `env` 는 `process.env` 병합 전달, `argv` 는 dev 모드에서 워커 경로 뒤에 이어 붙음.
28
+ - 반환 `WorkerProxy<TModule>` — 아래.
33
29
 
34
30
  ```ts
35
31
  // main.ts
36
32
  const worker = Worker.create<typeof import("./worker")>("./worker.ts");
37
33
  worker.on("progress", (p) => console.log(p));
38
- const r = await worker.calc(21); // 42
34
+ const result = await worker.calc(10); // 20
39
35
  await worker.terminate();
40
36
  ```
41
37
 
42
- ## 타입
38
+ ## WorkerProxy
39
+
40
+ `Worker.create` 반환 프록시. 워커 메서드 + 예약 메서드 3종을 제공.
43
41
 
44
- - `WorkerModule` `{ default: { __methods; __events } }`. `Worker.create` `TModule` 제약. `typeof import("./worker")` 로 충족.
45
- - `PromisifyMethods<TMethods>` 메서드 반환을 `Promise<Awaited<R>>` 매핑(워커 호출은 항상 비동기).
46
- - `WorkerProxy<TModule>` 프록시 타입(promise화 메서드 + on/off + terminate).
47
- - `WorkerRequest``{ id; method; params }` 내부 요청 메시지.
48
- - `WorkerResponse` — 내부 응답 유니온: `return`(반환값) / `error`(Error) / `event`(send 이벤트) / `log`(stdout 전달).
42
+ - 메서드 프록시: `TModule["default"]["__methods"]` 메서드가 `(...args) => Promise<Awaited<R>>` 로 노출(`PromisifyMethods`). 동기 메서드도 항상 Promise(postMessage 기반).
43
+ - `on<TEventName>(event, listener): void` 워커 `send` 이벤트 구독. `event`/`listener` 타입은 `TEvents` 에서 추론.
44
+ - `off<TEventName>(event, listener): void` 이벤트 구독 해제.
45
+ - `terminate(): Promise<void>` 워커 종료. 대기 호출은 "워커가 종료되었습니다" 로 reject 후 스레드 종료.
49
46
 
50
- ## 주의사항
47
+ ## 타입
51
48
 
52
- - 비정상 종료(exit code≠0)·워커 error 대기 모든 요청이 reject 되고 error 로깅됨silent 무시 아님.
53
- - 워커 메서드는 항상 Promise 반환 동기 시그니처여도 메인에선 `await` 필요.
54
- - 인자/반환은 transfer 직렬화 가능한 값이어야 함(함수·일부 클래스 인스턴스 제약).
49
+ - `interface WorkerModule { default: { __methods: Record<string, (...args) => unknown>; __events: Record<string, unknown> } }` `Worker.create` 제네릭 제약. `typeof import("./worker")` 가 이 구조를 만족(=`createWorker` 반환을 default export).
50
+ - `type PromisifyMethods<TMethods>` 메서드 반환을 `Promise<Awaited<R>>` 바꾸는 매핑 타입.
51
+ - `type WorkerProxy<TModule>` 프록시 타입.
52
+ - `interface WorkerRequest { id; method; params }` / `type WorkerResponse` — 내부 메시지 프로토콜 타입(`return`/`error`/`event`/`log`). 직접 다룰 일은 거의 없음.
@@ -1,35 +1,35 @@
1
1
  # @simplysm/excel
2
2
 
3
- OOXML(.xlsx) 워크북을 ZIP 단위 lazy-load 로 읽고 쓰는 라이브러리. 대용량 파일에서도 접근한 셀에 필요한 XML 파트만 로드한다(모든 셀 메서드가 `async` 인 이유). 워크북 생성·시트 추가·셀 값/스타일·조건부 서식·이미지 삽입·Zod 스키마 기반 레코드 매핑을 제공한다.
3
+ OOXML(.xlsx) 워크북을 ZIP 단위 lazy-load 로 읽고 쓰는 라이브러리. 대용량 파일에서도 접근한 셀에 필요한 XML 파트(SharedStrings/Styles 등)만 그때그때 로드한다(모든 셀 메서드가 `async` 인 이유). `ExcelWorkbook` 진입점에서 시트 추가·셀 값/수식·스타일·조건부 서식·이미지·행 복사를 다루며, Zod 스키마 기반 `ExcelWrapper` 로 레코드 배열 ↔ 엑셀 변환도 지원한다.
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
7
- - **ExcelWorkbook / ExcelWorksheet** — .xlsx 파일을 열거나 새로 만들고 시트를 다루며 바이트로 내보낼 때. 시트 단위 데이터 테이블·매트릭스·이미지·뷰(zoom/freeze) 처리 포함. 자세히: [workbook-worksheet.md](./workbook-worksheet.md)
8
- - **ExcelCell / ExcelRow / ExcelCol** — 개별 셀의 값·수식·병합·스타일을 읽고 쓰거나 행/열 단위로 셀을 순회할 때. 자세히: [cell.md](./cell.md)
9
- - **셀 스타일 (ExcelStyleOptions / ExcelFont)** — 셀 또는 워크북 default 의 배경·테두리·정렬·숫자형식·폰트를 지정할 때. 자세히: [style.md](./style.md)
7
+ - **ExcelWorkbook / ExcelWorksheet** — .xlsx 파일을 열거나 새로 만들고 시트를 다루며 바이트/Blob 내보낼 때. 시트 단위 데이터 테이블·매트릭스·행 복사·이미지·뷰(zoom/freeze/탭색) 처리 포함. 자세히: [workbook-worksheet.md](./workbook-worksheet.md)
8
+ - **ExcelCell / ExcelRow / ExcelCol** — 개별 셀의 값·수식·병합·스타일을 읽고 쓰거나 행/열 단위로 셀을 순회하고 열 너비를 줄 때. 자세히: [cell.md](./cell.md)
9
+ - **셀 스타일 (ExcelStyleOptions / ExcelFont)** — 셀(`cell.setStyle`) 또는 워크북 default(`wb.setDefaultStyle`)의 배경·테두리·정렬·숫자형식·폰트를 지정할 때. 자세히: [style.md](./style.md)
10
10
  - **조건부 서식 (ExcelConditionalRule / ExcelConditionalRuleStyle)** — 셀/범위에 값 비교·텍스트 매칭·수식 기반 native CF 규칙을 추가할 때. 자세히: [conditional-format.md](./conditional-format.md)
11
- - **ExcelWrapper** — Zod 스키마로 헤더 매핑·타입 변환·유효성 검사를 자동화해 레코드 배열 ↔ Excel 변환할 때. 자세히: [wrapper.md](./wrapper.md)
12
- - **ExcelUtils** — 셀 주소(A1 ↔ 좌표) 변환, Excel 날짜 시리얼 ↔ 타임스탬프 변환, 숫자형식 코드/ID/이름 상호 변환이 필요할 때. 자세히: [utils.md](./utils.md)
13
- - **값/주소/형식 타입** — 셀 값 유니온·숫자형식 프리셋·셀 타입·주소 좌표 타입을 시그니처에서 참조할 때. 아래 인라인 섹션 참조.
11
+ - **ExcelWrapper** — Zod 스키마로 헤더 매핑·타입 변환·유효성 검사를 자동화해 레코드 배열 ↔ 엑셀을 변환할 때. 자세히: [wrapper.md](./wrapper.md)
12
+ - **ExcelUtils** — 셀 주소(A1 ↔ 좌표) 변환, 엑셀 날짜 시리얼 ↔ 타임스탬프 변환, 숫자형식 코드/ID/이름 상호 변환이 필요할 때. 자세히: [utils.md](./utils.md)
13
+ - **값/주소/형식 타입** — 셀 값 유니온·숫자형식 프리셋·셀 타입·주소 좌표·정렬/테두리 enum 시그니처에서 참조할 때. 아래 인라인 섹션 참조.
14
14
  - **OOXML XML-shape 타입** — `ExcelXml*` / `Excel*Data` 류. 라이브러리 내부 XML 파서/직렬화기가 쓰는 OOXML 노드 구조 타입. 아래 인라인 섹션 참조.
15
15
 
16
16
  ## 값/주소/형식 타입
17
17
 
18
18
  `./types` 가 노출하는 사용자 대면 타입. 셀 값을 다루거나 메서드 시그니처를 해석할 때 참조.
19
19
 
20
- - `ExcelValueType` = `number | string | DateOnly | DateTime | Time | boolean | undefined` — 셀이 가질 수 있는 값 유니온. `getValue()` 반환·`setValue()` 인자 타입. `undefined` = (읽기 시 없음, 쓰기 시 셀 삭제).
21
- - `ExcelNumberFormat` = `"number" | "string" | "DateOnly" | "DateTime" | "Time"` — 숫자형식 프리셋 이름. 셀의 numFmt 를 의미 단위로 분류한 값. `"number"` = 일반 수치, `"string"` = 텍스트 형식, 나머지는 날짜/시간 시리얼 해석에 사용.
22
- - `ExcelCellType` = `"s" | "b" | "str" | "n" | "inlineStr" | "e"` — OOXML 셀 `t` 속성. `"s"` = SharedString 인덱스 참조, `"b"` = boolean, `"str"` = 수식 결과 문자열, `"n"` = 숫자, `"inlineStr"` = 인라인 서식 텍스트, `"e"` = 에러(읽기 시 throw). 보통 직접 다루지 않고 `getValue`/`setValue` 가 자동 처리.
20
+ - `ExcelValueType` = `number | string | DateOnly | DateTime | Time | boolean | undefined` — 셀이 가질 수 있는 값 유니온. `getValue()` 반환·`setValue()` 인자 타입. `undefined` = "값 없음"(읽기 시 셀, 쓰기 시 셀 삭제)이므로 결측을 끝까지 보존. `DateOnly`/`DateTime`/`Time` 은 `@simplysm/core-common` 타입.
21
+ - `ExcelNumberFormat` = `"number" | "string" | "DateOnly" | "DateTime" | "Time"` — 숫자형식 프리셋 이름. `"number"` = 일반 수치, `"string"` = 텍스트 형식, 나머지는 날짜/시간 시리얼 해석/표시에 사용. `ExcelStyleOptions.numberFormat` 와 `ExcelUtils` 변환의 공용 단위.
22
+ - `ExcelCellType` = `"s" | "b" | "str" | "n" | "inlineStr" | "e"` — OOXML 셀 `t` 속성. `"s"` = SharedString 인덱스 참조, `"b"` = boolean(`"1"`/`"0"`), `"str"` = 수식 결과 문자열, `"n"` = 숫자, `"inlineStr"` = 인라인 서식 텍스트, `"e"` = 에러(읽기 시 throw). 보통 직접 다루지 않고 `getValue`/`setValue` 가 자동 매핑.
23
23
  - `ExcelAddressPoint` = `{ r: number; c: number }` — 0 기반 행(`r`)·열(`c`) 좌표. 셀 단일 위치 단위.
24
24
  - `ExcelAddressRangePoint` = `{ s: ExcelAddressPoint; e: ExcelAddressPoint }` — 범위 좌표. `s` = 시작(좌상단), `e` = 끝(우하단). `getRange()` 반환 타입.
25
25
  - `ExcelBorderPosition` = `"left" | "right" | "top" | "bottom"` — 테두리 적용 변. `ExcelStyleOptions.border` 배열 원소.
26
- - `ExcelHorizontalAlign` = `"center" | "left" | "right"` — 가로 정렬.
27
- - `ExcelVerticalAlign` = `"center" | "top" | "bottom"` — 세로 정렬.
26
+ - `ExcelHorizontalAlign` = `"center" | "left" | "right"` — 가로 정렬 값.
27
+ - `ExcelVerticalAlign` = `"center" | "top" | "bottom"` — 세로 정렬 값.
28
28
  - `ExcelFontUnderline` = `"single" | "double" | "singleAccounting" | "doubleAccounting"` — 밑줄 종류. OOXML `<u val="...">` 의 val 에 그대로 매핑.
29
29
 
30
30
  ## OOXML XML-shape 타입
31
31
 
32
- `./types` 가 함께 export 하는 다음 인터페이스·타입은 라이브러리 내부 XML 파서/직렬화기가 OOXML 파트의 파싱 결과(`xml2js` 스타일의 `$`=속성, 배열 래핑) 구조를 표현하는 데이터 모델이다. 일반 사용 흐름(값/스타일/시트 API)에서는 직접 다루지 않으며, OOXML 노드를 직접 조작·검증할 때만 참조한다.
32
+ `./types` 가 함께 export 하는 다음 인터페이스·타입은 라이브러리 내부 XML 파서/직렬화기가 OOXML 파트의 파싱 결과(`xml2js` 스타일의 `$`=속성, 자식 배열 래핑) 표현하는 데이터 모델이다. 일반 사용 흐름(값/스타일/시트 API)에서는 직접 다루지 않으며, OOXML 노드를 직접 조작·검증할 때만 참조한다.
33
33
 
34
34
  - `ExcelXmlContentTypeData` — `[Content_Types].xml` 의 `Types`(Default/Override 파트 등록) 구조.
35
35
  - `ExcelXmlRelationshipData` / `ExcelRelationshipData` — `*.rels` 의 `Relationships` 및 개별 `Relationship`(Id/Target/Type) 구조.
@@ -40,4 +40,4 @@ OOXML(.xlsx) 워크북을 ZIP 단위 lazy-load 로 읽고 쓰는 라이브러리
40
40
  - `ExcelXmlDrawingData` — `xl/drawings/drawingN.xml` 의 `wsDr`(twoCellAnchor/pic/blipFill/spPr 등 이미지 앵커) 구조.
41
41
  - `ExcelXmlSharedStringData` / `ExcelXmlSharedStringDataSi` / `ExcelXmlSharedStringDataText` — `xl/sharedStrings.xml` 의 `sst` 와 `si` 항목(단순 `t` 또는 서식 run `r[]`), 텍스트 노드(`space="preserve"` 보존) 구조.
42
42
  - `ExcelXmlStyleData` 및 하위(`...Font` / `...Fill` / `...Border` / `...Xf` / `...Dxf`) — `xl/styles.xml` 의 `styleSheet`(numFmts/fonts/fills/borders/cellXfs/dxfs) 와 각 자원 노드 구조.
43
- - `ExcelXml` = `{ readonly data: unknown; cleanup(): void }` — 모든 XML 파트 래퍼가 따르는 공통 인터페이스. `data` = 파싱된 노드 트리, `cleanup()` = 직렬화 전 마무리 정리.
43
+ - `ExcelXml` = `{ readonly data: unknown; cleanup(): void }` — 모든 XML 파트 래퍼가 따르는 공통 인터페이스. `data` = 파싱된 노드 트리, `cleanup()` = 직렬화 전 마무리 정리. 외부에서 구현할 일은 거의 없다.
@@ -1,43 +1,49 @@
1
1
  # @simplysm/lint
2
2
 
3
- 심플리즘 워크스페이스 전용 ESLint 플러그인. 커스텀 규칙 9 묶음(`eslint-plugin`)과, 규칙들을 포함해 JS/TS/HTML 파일별로 완성된 flat config 배열(`eslint-recommended`)을 서브패스 export 로 제공. `src/index.ts` 없음 — `package.json` 의 `exports`(`./eslint-plugin`, `./eslint-recommended`)가 진입점.
3
+ simplysm 전용 ESLint 9 flat-config 프리셋과 커스텀 규칙 9종을 제공하는 ESLint 플러그인 패키지. `src/index.ts` 없음 — `package.json` 의 `exports`(`./eslint-plugin`, `./eslint-recommended`) 두 subpath 가 진입점. 패키지 루트 import 는 없음.
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
7
- - **eslint-recommended** — 프로젝트 `eslint.config.{js,mjs,cjs}` 에서 simplysm 표준 lint 규칙 전체(JS/TS/HTML 파일별 + tseslint/angular-eslint 통합)를 번에 적용할 import 하는 default export(완성된 flat config 배열).
8
- - **eslint-plugin** `@simplysm/<rule>` 커스텀 규칙 9종을 직접 켜거나, 개별 규칙의 감지 범위·메시지·autofix·옵션을 파악할 때. 자세히: [rules.md](./rules.md)
7
+ - **eslint-recommended** (`@simplysm/lint/eslint-recommended`) — 프로젝트 `eslint.config.ts` 에서 통째로 spread 쓰는 완성형 flat-config 배열. JS/TS/HTML 파일별 규칙·ignore·플러그인·Angular 통합이 모두 포함됨. 프로젝트 lint 설정을 잡을 때.
8
+ - **eslint-plugin** (`@simplysm/lint/eslint-plugin`) 커스텀 규칙만 담은 ESLint Plugin 객체(`{ rules }`). recommended 를 쓰지 않고 규칙을 직접 골라 등록할 때, 또는 규칙 동작을 개별 검토할 때. 자세히: [rules.md](./rules.md)
9
9
 
10
10
  ## eslint-recommended
11
11
 
12
- `@simplysm/lint/eslint-recommended` 의 default export. `tseslint.config(...)` 결과(`FlatConfig` 배열)이므로 호출형이 아니라 완성된 상수. 그대로 export 하거나 spread 항목을 덧붙여 사용.
12
+ `@simplysm/lint/eslint-recommended` 의 default export. `typescript-eslint` 의 `tseslint.config(...)` 결과 = flat-config 객체 배열. 그대로 spread 해서 사용함.
13
13
 
14
- ```js
15
- // eslint.config.js
14
+ ```typescript
15
+ // eslint.config.ts
16
16
  import recommended from "@simplysm/lint/eslint-recommended";
17
- export default recommended;
18
- // 규칙 추가 시: export default [...recommended, { files: ["**/*.ts"], rules: { "no-debugger": "error" } }];
17
+
18
+ export default [...recommended];
19
19
  ```
20
20
 
21
- config 강제하는 핵심 내용(파일 glob 블록별):
21
+ 배열을 구성하는 config 블록(순서대로):
22
22
 
23
- - **ignores** — `**/node_modules/**`, `**/dist/**`, `**/.*/**`(숨김 디렉터리 전체). 순회 자체를 건너뜀.
24
- - **`**/*.{js,mjs,cjs}`**node globals 적용. 켜는 규칙: `require-await`(async 함수에 await 없으면 오류), `no-shadow`(상위 스코프 변수 가림 금지), `no-duplicate-imports`(같은 모듈 중복 import 금지), `no-unused-expressions`(부수효과 없는 표현식 금지), `no-undef`(선언 안 된 식별자 사용 금지), `unused-imports/no-unused-imports`(미사용 import 제거, autofix), `unused-imports/no-unused-vars`(미사용 변수·인자 경고, `^_` 접두는 무시), `import/no-extraneous-dependencies`(미선언 의존성 import 금지, 단 `lib/**`·`eslint.config.*`·`simplysm.*`·`vitest.config.*` 는 devDependencies 허용), `@simplysm/no-subpath-imports-from-simplysm`, `@simplysm/no-hard-private` + 아래 공통 규칙군.
25
- - **`**/*.ts`** `angular.configs.tsRecommended` 펼친 뒤 추가. `processInlineTemplates` 인라인 템플릿 분리, `tseslint.parser`(`parserOptions.project: true`) 사용, `eslint-import-resolver-typescript` resolver 를 `import.meta.resolve` 로 자동 등록. 켜는 규칙: `no-console`(error), 그리고 타입 인식 `@typescript-eslint/*` 규칙 — `require-await`, `await-thenable`(thenable 만 await), `return-await`(`in-try-catch` = try/catch 안에서만 return await 요구), `no-floating-promises`(await/void 안 한 Promise 금지), `no-shadow`, `no-unnecessary-condition`(`allowConstantLoopConditions: true` = 상수 루프 조건 허용), `no-unnecessary-type-assertion`, `prefer-reduce-type-parameter`, `prefer-return-this-type`, `no-unused-expressions`, `strict-boolean-expressions`(`allowNullableBoolean`·`allowNullableObject` = nullable boolean/object 의 조건식 허용), `ban-ts-comment`(`ts-expect-error` 는 3자 이상 설명 필수), `prefer-readonly`, `naming-convention`(private 멤버는 `_` 접두 필수, 그 외 포맷 제약 없음), `no-misused-promises`(`checksVoidReturn.arguments:false`·`inheritedMethods:false` = 콜백 인자·상속 메서드의 void 반환 검사는 끔), `only-throw-error`(Error 외 throw 금지), `no-array-delete`(배열에 `delete` 금지). 커스텀 규칙 6종: `@simplysm/ng-no-async-effect`, `no-hard-private`, `no-subpath-imports-from-simplysm`, `ts-no-throw-not-implemented-error`(warn), `ts-no-unused-injects`, `ts-no-unused-protected-readonly`. + `@angular-eslint/no-output-native`(off).
26
- - **`**/*.html`** — `angular.configs.templateRecommended` + `templateAccessibility` 확장. 커스텀 템플릿 규칙: `@simplysm/ng-template-no-strict-null-check`, `ng-template-no-todo-comments`(warn), `ng-template-sd-require-binding-attrs` + `@angular-eslint/template/eqeqeq`(`allowNullOrUndefined: true` = null/undefined 비교는 느슨한 비교 허용), `label-has-associated-control`(off), `no-any`(error).
27
- - **`**/tests/**/*.ts`(override)**테스트 완화: `no-console`(off), `import/no-extraneous-dependencies`(off), `@simplysm/ts-no-throw-not-implemented-error`(off).
28
- - **`**/vitest.config.ts`(override)** — `no-restricted-properties`(off). 설정 파일에서 `process.env` 직접 접근 허용.
23
+ - **globalIgnores** — `**/node_modules/**`, `**/dist/**`, `**/.*/**` 순회 자체를 건너뜀. 점(.)으로 시작하는 디렉토리 전체가 제외 대상.
24
+ - **공통 languageOptions** — `ecmaVersion: "latest"`, `sourceType: "module"`.
25
+ - **JS 블록** (`**/*.js`, `**/*.mjs`, `**/*.cjs`) node 글로벌, `import`/`@simplysm`/`unused-imports` 플러그인 등록. 활성 규칙: `require-await`, `no-shadow`, `no-duplicate-imports`, `no-unused-expressions`, `no-undef`, unused-imports 2종, `import/no-extraneous-dependencies`(lib·`eslint.config`·`simplysm`·`vitest.config` 파일은 devDeps 허용), `@simplysm/no-subpath-imports-from-simplysm`, `@simplysm/no-hard-private`, node 빌트인 차단 규칙군, env 직접접근 차단 규칙군.
26
+ - **angular tsRecommended** — `angular.configs.tsRecommended` spread.
27
+ - **TS 블록** (`**/*.ts`) — `processor: angular.processInlineTemplates`(인라인 템플릿 추출 후 별도 lint), `parserOptions.project: true`(타입 정보 사용), `import/resolver` 로 typescript resolver(`alwaysTryTypes: true`) 지정. typescript-eslint 타입체크 규칙 다수 + `@simplysm` 커스텀 규칙 6종 활성. 커스텀 규칙 심각도: `ng-no-async-effect`/`no-hard-private`/`no-subpath-imports-from-simplysm`/`ts-no-unused-injects`/`ts-no-unused-protected-readonly` = `error`, `ts-no-throw-not-implemented-error` = `warn`. `@angular-eslint/no-output-native` 은 `off`.
28
+ - **HTML 블록** (`**/*.html`) — `angular.configs.templateRecommended` + `templateAccessibility` extends. `@simplysm` 템플릿 규칙 3종 활성: `ng-template-no-strict-null-check`=`error`, `ng-template-no-todo-comments`=`warn`, `ng-template-sd-require-binding-attrs`=`error`. `@angular-eslint/template/eqeqeq` `allowNullOrUndefined: true`, `label-has-associated-control`=`off`, `no-any`=`error`.
29
+ - **테스트 오버라이드** (`**/tests/**/*.ts`) — 테스트 코드 완화: `no-console`=`off`, `import/no-extraneous-dependencies`=`off`, `@simplysm/ts-no-throw-not-implemented-error`=`off`.
30
+ - **vitest.config 오버라이드** (`**/vitest.config.ts`) — `no-restricted-properties`=`off` (설정 파일에서 `process.env` 접근 허용).
29
31
 
30
- 공통 규칙군(JS/TS 양쪽 적용): `no-warning-comments`(warn, TODO/FIXME 등 경고), `eqeqeq`(`always`, 단 `null` 비교는 `==`/`!=` 허용), `no-self-compare`, `array-callback-return`(map/filter 등 콜백에 return 강제). 추가 공통 금지: `no-restricted-globals`(`Buffer` 전역 금지 → `Uint8Array`/`BytesUtils`), `no-restricted-imports`(`buffer`·`events`·`eventemitter3` 모듈 금지), `no-restricted-properties`(`process.env` 직접 접근 금지 → `env("...")`), `no-restricted-syntax`(`import.meta.env` 직접 접근·`env("NODE_ENV")`·`=== undefined`/`!== undefined` 류 strict 비교 금지 → `== null`/`!= null`).
32
+ 주의:
31
33
 
32
- 주의: 타입 인식 `@typescript-eslint` 규칙이 켜져 있어 TS 파일은 `parserOptions.project: true` 동작하는 환경(tsconfig 포함)이어야 함.
34
+ - TS 블록은 타입 정보(`parserOptions.project: true`)를 요구하므로, 대상 프로젝트에 유효한 `tsconfig` 있어야 함.
35
+ - node 빌트인 차단(`noNodeBuiltinsRules`): `Buffer` 글로벌 및 `buffer`/`events`/`eventemitter3` import 금지 — 각각 `Uint8Array`/`@simplysm/core-common`의 `BytesUtils`·`EventEmitter` 로 대체 유도. JS·TS 블록 모두에 적용.
36
+ - env 직접접근 차단(`noDirectEnvAccessRules`): `process.env`·`import.meta.env` 직접 접근, `env("NODE_ENV")` 호출, `=== undefined`/`!== undefined`(엄격 비교) 를 `no-restricted-properties`/`no-restricted-syntax` 로 막음(엄격 비교는 `== null`/`!= null` 로 유도). JS·TS 블록 모두에 적용.
33
37
 
34
38
  ## eslint-plugin
35
39
 
36
- `@simplysm/lint/eslint-plugin` 의 default export `{ rules: { ... } }` 형태의 ESLint 플러그인 객체. 9개 규칙을 규칙 ID → 규칙 정의로 매핑. 보통 `eslint-recommended` 가 내부에서 `@simplysm` 네임스페이스로 등록하므로, 직접 import 는 recommended 없이 커스텀 config 를 짜거나 특정 규칙만 개별 제어할 때만 필요. 규칙별 상세는 [rules.md](./rules.md).
40
+ `@simplysm/lint/eslint-plugin` 의 default export. ESLint Plugin 형태 객체.
37
41
 
38
- ```js
42
+ ```typescript
39
43
  import plugin from "@simplysm/lint/eslint-plugin";
40
- export default [{ plugins: { "@simplysm": plugin }, rules: { "@simplysm/no-hard-private": "error" } }];
44
+ // plugin === { rules: { "ng-no-async-effect": ..., "no-hard-private": ..., ... } }
41
45
  ```
42
46
 
43
- 규칙 ID 9종: `ng-no-async-effect`, `ng-template-no-strict-null-check`, `ng-template-no-todo-comments`, `ng-template-sd-require-binding-attrs`, `no-hard-private`, `no-subpath-imports-from-simplysm`, `ts-no-throw-not-implemented-error`, `ts-no-unused-injects`, `ts-no-unused-protected-readonly`.
47
+ - `rules` — 규칙 id → 규칙 객체 맵. 등록된 9 id: `ng-no-async-effect`, `ng-template-no-strict-null-check`, `ng-template-no-todo-comments`, `ng-template-sd-require-binding-attrs`, `no-hard-private`, `no-subpath-imports-from-simplysm`, `ts-no-throw-not-implemented-error`, `ts-no-unused-injects`, `ts-no-unused-protected-readonly`.
48
+
49
+ flat-config 에서 직접 등록할 때는 `plugins: { "@simplysm": plugin }` 로 매핑 후 `"@simplysm/<id>"` 로 켬. 각 규칙의 검사 대상·옵션·autofix·메시지는 [rules.md](./rules.md) 참조.