@simplysm/sd-claude 14.0.88 → 14.0.90

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 (135) hide show
  1. package/claude/references/sd-simplysm14/README.md +16 -17
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +39 -43
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +174 -80
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -50
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +60 -26
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +109 -37
  7. package/claude/references/sd-simplysm14/apis/angular/infra.md +61 -44
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +39 -31
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +73 -85
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -39
  11. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -30
  12. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +71 -67
  13. package/claude/references/sd-simplysm14/apis/angular/sheet.md +82 -72
  14. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +35 -36
  15. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +71 -43
  16. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +38 -30
  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 +39 -38
  21. package/claude/references/sd-simplysm14/apis/core-common/README.md +95 -103
  22. package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +59 -54
  23. package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +86 -0
  24. package/claude/references/sd-simplysm14/apis/core-common/datetime.md +57 -66
  25. package/claude/references/sd-simplysm14/apis/core-common/errors.md +86 -0
  26. package/claude/references/sd-simplysm14/apis/core-common/obj.md +60 -42
  27. package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
  28. package/claude/references/sd-simplysm14/apis/core-node/README.md +10 -8
  29. package/claude/references/sd-simplysm14/apis/core-node/consola.md +29 -32
  30. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +34 -22
  31. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +29 -25
  32. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +40 -53
  33. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +22 -29
  34. package/claude/references/sd-simplysm14/apis/core-node/worker.md +31 -31
  35. package/claude/references/sd-simplysm14/apis/excel/README.md +26 -26
  36. package/claude/references/sd-simplysm14/apis/excel/cell.md +37 -29
  37. package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +29 -15
  38. package/claude/references/sd-simplysm14/apis/excel/style.md +33 -27
  39. package/claude/references/sd-simplysm14/apis/excel/utils.md +29 -19
  40. package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +78 -55
  41. package/claude/references/sd-simplysm14/apis/excel/wrapper.md +42 -45
  42. package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
  43. package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
  44. package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -62
  45. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +149 -67
  46. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +111 -99
  47. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +115 -72
  48. package/claude/references/sd-simplysm14/apis/orm-common/schema.md +134 -92
  49. package/claude/references/sd-simplysm14/apis/orm-common/types.md +67 -52
  50. package/claude/references/sd-simplysm14/apis/orm-node/README.md +63 -26
  51. package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +51 -40
  52. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +10 -12
  53. package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
  54. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
  55. package/claude/references/sd-simplysm14/apis/service-client/README.md +90 -88
  56. package/claude/references/sd-simplysm14/apis/service-client/orm.md +37 -29
  57. package/claude/references/sd-simplysm14/apis/service-client/transport.md +45 -20
  58. package/claude/references/sd-simplysm14/apis/service-common/README.md +89 -40
  59. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +126 -34
  60. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +109 -54
  61. package/claude/references/sd-simplysm14/apis/service-server/README.md +70 -66
  62. package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +47 -47
  63. package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +71 -34
  64. package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +31 -32
  65. package/claude/references/sd-simplysm14/apis/storage/README.md +34 -28
  66. package/claude/references/sd-simplysm14/manuals/client-app-structure.md +142 -140
  67. package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -1
  68. package/claude/references/sd-simplysm14/manuals/client-service.md +19 -7
  69. package/claude/references/sd-simplysm14/manuals/client-shared-data.md +2 -2
  70. package/claude/references/sd-simplysm14/manuals/client-system-log.md +11 -3
  71. package/claude/references/sd-simplysm14/manuals/data-log.md +0 -1
  72. package/claude/references/sd-simplysm14/manuals/orm.md +16 -0
  73. package/claude/rules/sd-design-rules.md +10 -0
  74. package/claude/skills/sd-docs/SKILL.md +58 -46
  75. package/claude/skills/sd-docs/references/{doc-rules.md → subagent-prompt.md} +103 -103
  76. package/claude/skills/sd-impl/SKILL.md +1 -1
  77. package/claude/skills/sd-spec/SKILL.md +858 -858
  78. package/claude/skills/sd-spec/references/example-spec.md +26 -36
  79. package/package.json +1 -1
  80. package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +0 -47
  81. package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
  82. package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
  83. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
  84. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
  85. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
  86. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
  87. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
  88. package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
  89. package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
  90. package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
  91. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
  92. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
  93. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
  94. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
  95. package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
  96. package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
  97. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
  98. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
  99. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
  100. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
  101. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
  102. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
  103. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
  104. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
  105. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
  106. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
  107. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
  108. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
  109. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
  110. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
  111. package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
  112. package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
  113. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
  114. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
  115. package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
  116. package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
  117. package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
  118. package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
  119. package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
  120. package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
  121. package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
  122. package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
  123. package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
  124. package/claude/skills/sd-review/evals/golden.jsonl +0 -2
  125. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
  126. package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
  127. package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
  128. package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
  129. package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
  130. package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
  131. package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
  132. package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
  133. package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
  134. package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
  135. package/claude/skills/sd-use/evals/golden.jsonl +0 -6
@@ -93,14 +93,14 @@ flowchart LR
93
93
 
94
94
  ## 4. 화면
95
95
 
96
- | § | 분류 | 화면 | 유형 | 장치 |
97
- | --- | -------- | ------------------ | -------- | ---- |
98
- | 4.1 | 기준정보 | 품목 관리 | 마스터 | PC |
99
- | 4.2 | 기준정보 | 품목 등록·편집 | 마스터 | PC |
100
- | 4.3 | 기준정보 | Location 관리 | 마스터 | PC |
101
- | 4.4 | 기준정보 | Location 등록·편집 | 마스터 | PC |
102
- | 4.5 | 입고 | 입고 스캔 | 트랜잭션 | PDA |
103
- | 4.6 | 재고 | 재고 확인 | 조회 | PC |
96
+ | § | 분류 | 화면 | 유형 | 장치 |
97
+ | --- | -------- | ------------- | -------- | ---- |
98
+ | 4.1 | 기준정보 | 품목 관리 | 마스터 | PC |
99
+ | 4.2 | 기준정보 | Location 관리 | 마스터 | PC |
100
+ | 4.3 | 입고 | 입고 스캔 | 트랜잭션 | PDA |
101
+ | 4.4 | 재고 | 재고 확인 | 조회 | PC |
102
+
103
+ 전용 모달(품목 등록·편집·Location 등록·편집)은 각각 호출 화면(품목 관리·Location 관리) 한 곳에서만 쓰이므로 별도 §4.x 분리하지 않고 부모 §4.x 안에 포함 (sub-section). 자세한 배치 규칙은 spec-authoring.md "모달 처리" 참조.
104
104
 
105
105
  ### 4.1 품목 관리 (PC) [확정: 2026-04-01, 구현: 2026-04-05]
106
106
 
@@ -145,8 +145,8 @@ Actor: 창고 관리자
145
145
  #### 동작
146
146
 
147
147
  - `[조회]` 클릭: 검색 필터 조건으로 목록을 갱신
148
- - `[등록]` 클릭: [화면.품목 등록·편집] 을 빈 폼 상태로 모달 띄움
149
- - ID 버튼 클릭: [화면.품목 등록·편집] 을 해당 행 데이터로 채워 모달 띄움
148
+ - `[등록]` 클릭: 품목 등록·편집 을 빈 폼 상태로 모달 띄움
149
+ - ID 버튼 클릭: 품목 등록·편집 을 해당 행 데이터로 채워 모달 띄움
150
150
  - `[선택 삭제]` 클릭: 선택된 행들의 활성 여부를 false 로 전환 (이후 해당 품목 입출고 불가)
151
151
  - `[선택 복구]` 클릭: 선택된 행들의 활성 여부를 true 로 전환
152
152
  - `[엑셀 업로드]` 클릭: 엑셀 파일 선택 후, 코드를 키로 일괄 등록·수정
@@ -166,16 +166,11 @@ Actor: 창고 관리자
166
166
  | `화주코드` + `SEQ` | [모델.품목.코드] | `<화주코드>-<SEQ>` 형식으로 합성 |
167
167
  | `품목명` | [모델.품목.명칭] | 1:1 |
168
168
 
169
- ### 4.2 품목 등록·편집 (PC) [확정: 2026-04-01, 구현: 2026-04-05]
169
+ #### 품목 등록·편집 (모달)
170
170
 
171
- Actor: 창고 관리자
172
- 관련 섹션: [프로세스.입고]
173
-
174
- 기능 개요:
171
+ 품목 신규 등록 또는 기존 품목 편집 (호출하는 쪽에서 빈 폼/기존 데이터로 모달 띄움).
175
172
 
176
- - 품목 신규 등록 또는 기존 품목 편집 (호출하는 쪽에서 빈 폼/기존 데이터로 모달 띄움)
177
-
178
- #### 와이어프레임
173
+ ##### 와이어프레임
179
174
 
180
175
  ```
181
176
  ┌──────────────────────────────────────┐
@@ -187,7 +182,7 @@ Actor: 창고 관리자
187
182
  └──────────────────────────────────────┘
188
183
  ```
189
184
 
190
- #### 항목
185
+ ##### 항목
191
186
 
192
187
  **입력 폼**
193
188
 
@@ -196,12 +191,12 @@ Actor: 창고 관리자
196
191
  | 코드 | 텍스트 입력 | O | [모델.품목.코드] | |
197
192
  | 명칭 | 텍스트 입력 | O | [모델.품목.명칭] | |
198
193
 
199
- #### 동작
194
+ ##### 동작
200
195
 
201
196
  - `[저장]` 클릭: 활성 품목 내에서 코드·명칭 유일성을 검증한 뒤 저장하고 모달 닫음
202
197
  - `[취소]` 클릭: 변경 사항을 폐기하고 모달 닫음
203
198
 
204
- ### 4.3 Location 관리 (PC) [확정: 2026-04-01]
199
+ ### 4.2 Location 관리 (PC) [확정: 2026-04-01]
205
200
 
206
201
  Actor: 창고 관리자
207
202
  관련 섹션: [프로세스.입고]
@@ -243,8 +238,8 @@ Actor: 창고 관리자
243
238
  #### 동작
244
239
 
245
240
  - `[조회]` 클릭: 검색 필터 조건으로 목록을 갱신
246
- - `[등록]` 클릭: [화면.Location 등록·편집] 을 빈 폼 상태로 모달 띄움
247
- - ID 버튼 클릭: [화면.Location 등록·편집] 을 해당 행 데이터로 채워 모달 띄움
241
+ - `[등록]` 클릭: Location 등록·편집 을 빈 폼 상태로 모달 띄움
242
+ - ID 버튼 클릭: Location 등록·편집 을 해당 행 데이터로 채워 모달 띄움
248
243
  - `[선택 삭제]` 클릭: 선택된 행들의 활성 여부를 false 로 전환
249
244
  - `[선택 복구]` 클릭: 선택된 행들의 활성 여부를 true 로 전환
250
245
  - `[엑셀 업로드]` 클릭: 엑셀 파일 선택 후, 코드를 키로 일괄 등록·수정
@@ -264,16 +259,11 @@ Actor: 창고 관리자
264
259
 
265
260
  - 비활성 행: 전체 텍스트에 취소선 + 회색 처리
266
261
 
267
- ### 4.4 Location 등록·편집 (PC) [확정: 2026-04-01]
262
+ #### Location 등록·편집 (모달)
268
263
 
269
- Actor: 창고 관리자
270
- 관련 섹션: [프로세스.입고]
271
-
272
- 기능 개요:
264
+ Location 신규 등록 또는 기존 Location 편집 (호출하는 쪽에서 빈 폼/기존 데이터로 모달 띄움).
273
265
 
274
- - Location 신규 등록 또는 기존 Location 편집 (호출하는 쪽에서 빈 폼/기존 데이터로 모달 띄움)
275
-
276
- #### 와이어프레임
266
+ ##### 와이어프레임
277
267
 
278
268
  ```
279
269
  ┌──────────────────────────────────────┐
@@ -285,7 +275,7 @@ Actor: 창고 관리자
285
275
  └──────────────────────────────────────┘
286
276
  ```
287
277
 
288
- #### 항목
278
+ ##### 항목
289
279
 
290
280
  **입력 폼**
291
281
 
@@ -293,12 +283,12 @@ Actor: 창고 관리자
293
283
  | ---- | ----------- | ---- | -------------------- | ----------------------- |
294
284
  | 코드 | 텍스트 입력 | O | [모델.Location.코드] | 영문 대문자/숫자/하이픈 |
295
285
 
296
- #### 동작
286
+ ##### 동작
297
287
 
298
288
  - `[저장]` 클릭: 활성 Location 내에서 코드 유일성을 검증한 뒤 저장하고 모달 닫음
299
289
  - `[취소]` 클릭: 변경 사항을 폐기하고 모달 닫음
300
290
 
301
- ### 4.5 입고 스캔 (PDA) [확정: 2026-04-01]
291
+ ### 4.3 입고 스캔 (PDA) [확정: 2026-04-01]
302
292
 
303
293
  Actor: 창고 작업자
304
294
  관련 섹션: [프로세스.입고], [외부 인터페이스.ERP 입고 통보]
@@ -338,7 +328,7 @@ Actor: 창고 작업자
338
328
  3. [모델.재고] 레코드 생성
339
329
  4. [외부 인터페이스.ERP 입고 통보] 호출
340
330
 
341
- ### 4.6 재고 확인 (PC) [확정: 2026-04-01]
331
+ ### 4.4 재고 확인 (PC) [확정: 2026-04-01]
342
332
 
343
333
  Actor: 창고 관리자
344
334
  관련 섹션: [프로세스.입고], [기타.과거 재고 조회], [자동 처리.재고 스냅샷]
@@ -602,4 +592,4 @@ Actor: 창고 관리자
602
592
  - 영향: 업무 프로세스 출고(2.2번 섹션) OPEN 상태 유지
603
593
 
604
594
  - 2026-04-05: 품목 마스터 sd-impl 완료 (구현 마커 부착)
605
- - 근거: 시연 검증 통과 — 화면 품목 관리(4.1번 섹션), 품목 등록·편집(4.2번 섹션)
595
+ - 근거: 시연 검증 통과 — 화면 품목 관리(4.1번 섹션, 품목 등록·편집 모달 영역 포함)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/sd-claude",
3
- "version": "14.0.88",
3
+ "version": "14.0.90",
4
4
  "description": "심플리즘 패키지 - Claude Code 셋업",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",
@@ -1,47 +0,0 @@
1
- # @simplysm/core-common — 직렬화 (json / xml / transfer)
2
-
3
- 커스텀 타입을 보존하며 직렬화/역직렬화할 때 함께 읽히는 묶음. `json`(문자열 ↔ 객체), `xml`(XML ↔ 객체), `transfer`(Web Worker 전송용). 세 모듈 모두 `DateTime`/`DateOnly`/`Time`/`Uuid`/`Set`/`Map`/`Error`/`Uint8Array` 등을 `__type__` 태그 객체로 변환해 왕복 보존한다.
4
-
5
- ## json 네임스페이스
6
-
7
- `import { json } from "@simplysm/core-common"`. 전역 프로토타입을 건드리지 않아 Worker 환경 안전.
8
-
9
- - `json.stringify(obj, options?): string` — 커스텀 타입(Date/DateTime/DateOnly/Time/Uuid/Set/Map/Error/Uint8Array)을 `{ __type__, data }` 로 변환 후 직렬화. `options`:
10
- - `space?: string | number` — 들여쓰기(숫자=공백 수, 문자열=들여쓰기 문자열).
11
- - `replacer?: (key, value) => unknown` — 기본 타입 변환 **전에** 호출되는 커스텀 변환기.
12
- - `redactBytes?: boolean` — true 면 `Uint8Array` 내용을 `"__hidden__"` 로 대체(로깅용). 이 결과는 `json.parse` 로 복원 불가.
13
- - 순환 참조는 `TypeError`, `toJSON` 메서드가 있으면 호출(위 커스텀 타입은 예외), `undefined` 속성은 제외.
14
- - `json.parse<T>(json): T` — `__type__`/`data` 태그를 보고 커스텀 타입 복원. 모든 JSON `null` 을 `undefined` 로 변환(simplysm null-free 규칙). 사용자 데이터에 우연히 `{ __type__, data }` 형태가 있으면 오변환 위험. `redactBytes` 로 가려진 바이트를 만나면 `SdError`. 파싱 실패 시 `SdError`(환경변수 `DEV` 가 truthy 면 전체 JSON, 아니면 길이만 메시지에 포함).
15
-
16
- ```typescript
17
- const text = json.stringify({ at: new DateTime(), bin: new Uint8Array([1, 2]) }, { space: 2 });
18
- const back = json.parse<{ at: DateTime; bin: Uint8Array }>(text); // 타입 복원됨
19
- ```
20
-
21
- ## xml 네임스페이스
22
-
23
- `import { xml } from "@simplysm/core-common"`. `fast-xml-parser` 기반.
24
-
25
- - `xml.parse(str, options?): unknown` — XML → 객체. 속성은 `$` 객체로, 텍스트 노드는 `_` key 로, 자식 요소는 배열로 변환(루트 제외). `options.stripTagPrefix?: boolean` 면 태그의 네임스페이스 접두사(`ns:tag`)를 제거(속성 접두사는 유지).
26
- - `xml.stringify(obj, options?): string` — 객체 → XML. `options` 는 fast-xml-parser 의 `XmlBuilderOptions`(기본값을 덮어쓸 때만 사용).
27
-
28
- ```typescript
29
- xml.parse('<root id="1"><item>hi</item></root>');
30
- // { root: { $: { id: "1" }, item: [{ _: "hi" }] } }
31
- ```
32
-
33
- ## transfer 네임스페이스
34
-
35
- `import { transfer } from "@simplysm/core-common"`. Web Worker 간 데이터 전송용. `structuredClone` 이 못 다루는 커스텀 타입을 처리하고, `Uint8Array` 의 버퍼를 zero-copy 전송 목록에 담는다.
36
-
37
- - `transfer.encode(obj): { result, transferList }` — 커스텀 타입을 `{ __type__, data }` 로 변환한 `result` 와 transfer 대상 `ArrayBuffer[]`(transferList) 반환. `worker.postMessage(result, transferList)` 형태로 사용. 순환 참조 시 경로 포함 `TypeError`. 같은 객체 다중 참조는 인코딩 결과 캐시 재사용. `SharedArrayBuffer` 는 transferList 에 넣지 않음.
38
- - `transfer.decode(obj): unknown` — 수신한 태그 객체를 커스텀 타입으로 복원(Date/DateTime/DateOnly/Time/Uuid/RegExp/Error, Map/Set/Array/객체 재귀). `Uint8Array` 는 그대로.
39
-
40
- `json` 과 차이: transfer 는 날짜류를 tick(숫자)으로 저장하고 `RegExp` 를 지원하며 `Uint8Array` 를 직렬화하지 않고 버퍼째 넘긴다. JSON 문자열이 아니라 구조화 클론 가능한 객체를 만든다.
41
-
42
- ```typescript
43
- const { result, transferList } = transfer.encode(payload);
44
- worker.postMessage(result, transferList);
45
- // 수신 측
46
- const data = transfer.decode(event.data);
47
- ```
@@ -1,29 +0,0 @@
1
- # @simplysm/orm-common — QueryBuilder (dialect SQL 렌더러)
2
-
3
- `QueryDef` AST 를 각 DBMS SQL 문자열로 변환하는 클래스군. executor 구현체(`@simplysm/orm-node` 등)가 사용하며, 일반 쿼리 작성에선 직접 다루지 않는다.
4
-
5
- ## 팩토리
6
-
7
- - `createQueryBuilder(dialect: Dialect): QueryBuilderBase` — dialect 에 맞는 QueryBuilder 인스턴스 생성. `dialect` 가 `"mysql"|"mssql"|"postgresql"` 중 하나에 따라 아래 구현체 반환.
8
-
9
- ```typescript
10
- const builder = createQueryBuilder("mysql");
11
- const { sql } = builder.build(queryDef);
12
- ```
13
-
14
- ## QueryBuilder 클래스
15
-
16
- - `abstract class QueryBuilderBase` — QueryDef → SQL 추상 기반.
17
- - `build(def: QueryDef): QueryBuildResult` — `def.type` 과 동일 이름 메서드로 동적 dispatch 하여 SQL 렌더. 알 수 없는 타입이면 throw. dialect 공통 로직만 구현하고 차이나는 부분은 abstract(하위 클래스 구현).
18
- - `class MysqlQueryBuilder extends QueryBuilderBase` — MySQL 렌더러.
19
- - `class MssqlQueryBuilder extends QueryBuilderBase` — MSSQL 렌더러(TOP, IDENTITY_INSERT, OUTPUT 등).
20
- - `class PostgresqlQueryBuilder extends QueryBuilderBase` — PostgreSQL 렌더러.
21
-
22
- ## ExprRenderer 클래스
23
-
24
- `QueryBuilder` 내부에서 `Expr`/`WhereExpr` AST 를 SQL 식 문자열로 렌더.
25
-
26
- - `abstract class ExprRendererBase` — 표현식 렌더 추상 기반. `render(expr)`/`renderWhere(wheres)` 를 dispatch, dialect 차이(함수명·NULL 안전 비교·날짜 함수 등)는 abstract.
27
- - `class MysqlExprRenderer extends ExprRendererBase` — MySQL 표현식 렌더러(`<=>` 등).
28
- - `class MssqlExprRenderer extends ExprRendererBase` — MSSQL 표현식 렌더러.
29
- - `class PostgresqlExprRenderer extends ExprRendererBase` — PostgreSQL 표현식 렌더러.
@@ -1,99 +0,0 @@
1
- # 재고 관리 요구 분석서
2
-
3
- ## 1. 개요
4
-
5
- ### 1.1 핵심 목적 [확정: 2026-05-26]
6
-
7
- 창고별 품목 재고 현황 조회 시스템
8
-
9
- ### 1.2 주요 목표 [확정: 2026-05-26]
10
-
11
- - 창고별·품목별 재고 현황 조회
12
-
13
- ### 1.3 최종 사용자/이해관계자 [확정: 2026-05-26]
14
-
15
- - 창고 관리자: PC 로 재고 현황 조회
16
-
17
- ### 1.4 환경/장치 [확정: 2026-05-26]
18
-
19
- ```
20
- ┌─────────┐
21
- │ PC │
22
- └────┬────┘
23
-
24
-
25
- ┌──────────┐
26
- │ WMS 서버 │
27
- └──────────┘
28
- ```
29
-
30
- - PC — 창고 관리자가 재고 화면 조회에 사용
31
- - OS: Windows 11
32
- - Browser: Chrome 최신
33
- - 해상도: 1920 x 1080
34
-
35
- ## 4. 화면
36
-
37
- | § | 분류 | 화면 | 유형 | 장치 |
38
- | --- | ---- | --------- | ---- | ---- |
39
- | 4.1 | 재고 | 재고 조회 | 조회 | PC |
40
-
41
- ### 4.1 재고 조회 (PC) [확정: 2026-05-26]
42
-
43
- Actor: 창고 관리자
44
- 관련 섹션: [모델.재고]
45
-
46
- 기능 개요:
47
-
48
- - 창고별·품목별 재고 현황 조회
49
-
50
- #### 와이어프레임
51
-
52
- ```
53
- ┌────────────────────────────────────────────────────────────────────┐
54
- │ 재고 조회 │
55
- │ [조회] <필터> │
56
- ├────────────────────────────────────────────────────────────────────┤
57
- │ <재고 목록 시트> │
58
- └────────────────────────────────────────────────────────────────────┘
59
- ```
60
-
61
- #### 항목
62
-
63
- **필터**
64
-
65
- | 항목 | 종류 | 필수 | 비고 |
66
- | --------- | --------- | ---- | ------------------------ |
67
- | 창고 | 정적 선택 | X | 전체·창고 목록 |
68
- | 품목 검색 | 텍스트 | X | 코드 또는 명칭 부분 일치 |
69
-
70
- **재고 목록 시트**
71
-
72
- | 컬럼 | 종류 | 필수 | 도메인 매핑 | 비고 |
73
- | ------ | ---- | ---- | -------------------- | --------- |
74
- | 창고 | 문자 | - | [모델.재고.창고] | |
75
- | 품목 | 문자 | - | [모델.재고.품목명] | |
76
- | 재고량 | 숫자 | - | [모델.재고.수량] | 우측 정렬 |
77
- | 갱신일 | 날짜 | - | [모델.재고.갱신일] | |
78
-
79
- #### 동작
80
-
81
- - `[조회]` 클릭: 검색 필터 조건으로 목록 갱신
82
-
83
- #### 빈 상태
84
-
85
- - 검색 결과 없음: "조회된 재고가 없습니다." 표시
86
-
87
- ## 8. 도메인 모델
88
-
89
- ### 8.1 재고 [확정: 2026-05-26]
90
-
91
- 필드:
92
-
93
- | 필드 | 타입 | 필수 | 비고 |
94
- | ------ | ---- | ---- | ---------------- |
95
- | ID | 숫자 | O | 자동 부여 |
96
- | 창고 | 문자 | O | 창고명 |
97
- | 품목명 | 문자 | O | 품목명 |
98
- | 수량 | 숫자 | O | 재고 수량 |
99
- | 갱신일 | 날짜 | O | 마지막 갱신 일자 |
@@ -1,12 +0,0 @@
1
- {
2
- "name": "@demo/client",
3
- "version": "0.0.0",
4
- "private": true,
5
- "type": "module",
6
- "dependencies": {
7
- "@angular/core": "^21.0.0",
8
- "@ng-icons/core": "^32.0.0",
9
- "@ng-icons/tabler-icons": "^32.0.0",
10
- "@simplysm/angular": "^14.0.0"
11
- }
12
- }
@@ -1,3 +0,0 @@
1
- export { InventoryMasterListComponent } from "./screens/inventory/inventory-master.list";
2
- export { OutboundListComponent } from "./screens/outbound/outbound.list";
3
- export { InboundListComponent } from "./screens/inbound/inbound.list";
@@ -1,150 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- ViewEncapsulation,
5
- effect,
6
- inject,
7
- signal,
8
- untracked,
9
- } from "@angular/core";
10
- import {
11
- injectPermsSignal,
12
- mark,
13
- SdCrudListComponent,
14
- SdSheetColumnDirective,
15
- SdTextfieldComponent,
16
- SdToastProvider,
17
- } from "@simplysm/angular";
18
-
19
- interface IInboundItem {
20
- id: number;
21
- receiptNo: string;
22
- supplierName: string;
23
- itemName: string;
24
- quantity: number;
25
- receivedAt: string;
26
- }
27
-
28
- interface IFilter {
29
- searchText: string;
30
- }
31
-
32
- @Component({
33
- selector: "app-inbound-list",
34
- changeDetection: ChangeDetectionStrategy.OnPush,
35
- encapsulation: ViewEncapsulation.None,
36
- standalone: true,
37
- imports: [SdCrudListComponent, SdSheetColumnDirective, SdTextfieldComponent],
38
- template: `
39
- <div class="flex-column fill">
40
- <sd-crud-list
41
- title="입고 내역 조회"
42
- [(ready)]="ready"
43
- [initialized]="initialized()"
44
- [(busyCount)]="busyCount"
45
- [items]="items()"
46
- [(selectedKeys)]="selectedKeys"
47
- [(page)]="page"
48
- [totalPageCount]="pageLength()"
49
- [(sorts)]="sortingDefs"
50
- [trackByFn]="trackByFn"
51
- [restricted]="!perms().includes('use')"
52
- (filterSubmit)="onFilterSubmit()"
53
- >
54
- <ng-template #filterTpl>
55
- <div class="form-box-inline">
56
- <div>
57
- <label>검색</label>
58
- <sd-textfield [(value)]="filter().searchText" (valueChange)="mark(filter)" />
59
- </div>
60
- </div>
61
- </ng-template>
62
-
63
- <sd-sheet-column [key]="'receiptNo'" [header]="'입고 번호'">
64
- <ng-template [cell]="items()" let-item="item">
65
- <div class="p-xs-sm">{{ item.receiptNo }}</div>
66
- </ng-template>
67
- </sd-sheet-column>
68
-
69
- <sd-sheet-column [key]="'supplierName'" [header]="'공급처'">
70
- <ng-template [cell]="items()" let-item="item">
71
- <div class="p-xs-sm">{{ item.supplierName }}</div>
72
- </ng-template>
73
- </sd-sheet-column>
74
-
75
- <sd-sheet-column [key]="'itemName'" [header]="'품목'">
76
- <ng-template [cell]="items()" let-item="item">
77
- <div class="p-xs-sm">{{ item.itemName }}</div>
78
- </ng-template>
79
- </sd-sheet-column>
80
-
81
- <sd-sheet-column [key]="'quantity'" [header]="'수량'">
82
- <ng-template [cell]="items()" let-item="item">
83
- <div class="p-xs-sm tx-right">{{ item.quantity }}</div>
84
- </ng-template>
85
- </sd-sheet-column>
86
- </sd-crud-list>
87
-
88
- @if (initialized() && items().length === 0) {
89
- <div class="p-default tx-center tx-theme-gray-default">조회된 입고 내역이 없습니다.</div>
90
- }
91
- </div>
92
- `,
93
- })
94
- export class InboundListComponent {
95
- private readonly _sdToast = inject(SdToastProvider);
96
-
97
- perms = injectPermsSignal(["inbound"], ["use"]);
98
-
99
- ready = signal(false);
100
- initialized = signal(false);
101
- busyCount = signal(0);
102
-
103
- items = signal<IInboundItem[]>([]);
104
- selectedKeys = signal<number[]>([]);
105
- page = signal(0);
106
- pageLength = signal(0);
107
- sortingDefs = signal<{ key: string; desc: boolean }[]>([]);
108
-
109
- filter = signal<IFilter>({ searchText: "" });
110
- lastFilter = signal<IFilter>({ searchText: "" });
111
-
112
- trackByFn = (item: IInboundItem) => item.id;
113
-
114
- protected readonly mark = mark;
115
-
116
- constructor() {
117
- effect(() => {
118
- if (!this.perms().includes("use") || !this.ready()) {
119
- this.initialized.set(true);
120
- return;
121
- }
122
-
123
- this.lastFilter();
124
- this.page();
125
- this.sortingDefs();
126
-
127
- void untracked(async () => {
128
- this.busyCount.update((v) => v + 1);
129
- await this._sdToast.try(async () => {
130
- await this._refresh();
131
- });
132
- this.busyCount.update((v) => v - 1);
133
- this.initialized.set(true);
134
- });
135
- });
136
- }
137
-
138
- onFilterSubmit(): void {
139
- this.page.set(0);
140
- this.lastFilter.set({ ...this.filter() });
141
- }
142
-
143
- doRefresh(): void {
144
- if (!this.perms().includes("use")) return;
145
- mark(this.lastFilter);
146
- }
147
-
148
- private async _refresh(): Promise<void> {
149
- }
150
- }
@@ -1,143 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- ViewEncapsulation,
5
- effect,
6
- inject,
7
- signal,
8
- untracked,
9
- } from "@angular/core";
10
- import {
11
- injectPermsSignal,
12
- mark,
13
- SdCrudListComponent,
14
- SdSheetColumnDirective,
15
- SdTextfieldComponent,
16
- SdToastProvider,
17
- } from "@simplysm/angular";
18
-
19
- interface IInventoryMasterItem {
20
- id: number;
21
- warehouseCode: string;
22
- itemCode: string;
23
- itemName: string;
24
- active: boolean;
25
- }
26
-
27
- interface IFilter {
28
- searchText: string;
29
- }
30
-
31
- @Component({
32
- selector: "app-inventory-master-list",
33
- changeDetection: ChangeDetectionStrategy.OnPush,
34
- encapsulation: ViewEncapsulation.None,
35
- standalone: true,
36
- imports: [SdCrudListComponent, SdSheetColumnDirective, SdTextfieldComponent],
37
- template: `
38
- <div class="flex-column fill">
39
- <sd-crud-list
40
- title="재고 마스터"
41
- [(ready)]="ready"
42
- [initialized]="initialized()"
43
- [(busyCount)]="busyCount"
44
- [items]="items()"
45
- [(selectedKeys)]="selectedKeys"
46
- [(page)]="page"
47
- [totalPageCount]="pageLength()"
48
- [(sorts)]="sortingDefs"
49
- [trackByFn]="trackByFn"
50
- [restricted]="!perms().includes('use')"
51
- (filterSubmit)="onFilterSubmit()"
52
- >
53
- <ng-template #filterTpl>
54
- <div class="form-box-inline">
55
- <div>
56
- <label>검색</label>
57
- <sd-textfield [(value)]="filter().searchText" (valueChange)="mark(filter)" />
58
- </div>
59
- </div>
60
- </ng-template>
61
-
62
- <sd-sheet-column [key]="'warehouseCode'" [header]="'창고'">
63
- <ng-template [cell]="items()" let-item="item">
64
- <div class="p-xs-sm">{{ item.warehouseCode }}</div>
65
- </ng-template>
66
- </sd-sheet-column>
67
-
68
- <sd-sheet-column [key]="'itemCode'" [header]="'품목 코드'">
69
- <ng-template [cell]="items()" let-item="item">
70
- <div class="p-xs-sm">{{ item.itemCode }}</div>
71
- </ng-template>
72
- </sd-sheet-column>
73
-
74
- <sd-sheet-column [key]="'itemName'" [header]="'품목명'">
75
- <ng-template [cell]="items()" let-item="item">
76
- <div class="p-xs-sm">{{ item.itemName }}</div>
77
- </ng-template>
78
- </sd-sheet-column>
79
- </sd-crud-list>
80
-
81
- @if (initialized() && items().length === 0) {
82
- <div class="p-default tx-center tx-theme-gray-default">조회된 재고 마스터가 없습니다.</div>
83
- }
84
- </div>
85
- `,
86
- })
87
- export class InventoryMasterListComponent {
88
- private readonly _sdToast = inject(SdToastProvider);
89
-
90
- perms = injectPermsSignal(["inventory.master"], ["use", "edit"]);
91
-
92
- ready = signal(false);
93
- initialized = signal(false);
94
- busyCount = signal(0);
95
-
96
- items = signal<IInventoryMasterItem[]>([]);
97
- selectedKeys = signal<number[]>([]);
98
- page = signal(0);
99
- pageLength = signal(0);
100
- sortingDefs = signal<{ key: string; desc: boolean }[]>([]);
101
-
102
- filter = signal<IFilter>({ searchText: "" });
103
- lastFilter = signal<IFilter>({ searchText: "" });
104
-
105
- trackByFn = (item: IInventoryMasterItem) => item.id;
106
-
107
- protected readonly mark = mark;
108
-
109
- constructor() {
110
- effect(() => {
111
- if (!this.perms().includes("use") || !this.ready()) {
112
- this.initialized.set(true);
113
- return;
114
- }
115
-
116
- this.lastFilter();
117
- this.page();
118
- this.sortingDefs();
119
-
120
- void untracked(async () => {
121
- this.busyCount.update((v) => v + 1);
122
- await this._sdToast.try(async () => {
123
- await this._refresh();
124
- });
125
- this.busyCount.update((v) => v - 1);
126
- this.initialized.set(true);
127
- });
128
- });
129
- }
130
-
131
- onFilterSubmit(): void {
132
- this.page.set(0);
133
- this.lastFilter.set({ ...this.filter() });
134
- }
135
-
136
- doRefresh(): void {
137
- if (!this.perms().includes("use")) return;
138
- mark(this.lastFilter);
139
- }
140
-
141
- private async _refresh(): Promise<void> {
142
- }
143
- }