@simplysm/sd-claude 14.0.46 → 14.0.48
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/{claude/references/sd-simplysm14/sd-claude/usage.md → README.md} +2 -2
- package/claude/rules/sd-claude-rules.md +27 -9
- package/claude/rules/sd-options.md +11 -6
- package/claude/sd-subagent-start.sh +6 -0
- package/claude/settings.json +1 -12
- package/claude/skills/sd-check/SKILL.md +18 -9
- package/claude/skills/sd-claude-docs/SKILL.md +29 -58
- package/claude/skills/sd-claude-docs/references/package-claudemd.md +12 -0
- package/claude/skills/sd-claude-docs/references/package-doc-gen.md +22 -12
- package/claude/skills/sd-debug/SKILL.md +5 -3
- package/claude/skills/sd-deliverable/SKILL.md +0 -1
- package/claude/skills/sd-dev/SKILL.md +14 -9
- package/claude/skills/sd-doc-extract/SKILL.md +7 -9
- package/claude/skills/sd-doc-extract/_common.py +8 -1
- package/claude/skills/sd-doc-extract/_extract_docx.py +74 -34
- package/claude/skills/sd-doc-extract/_extract_pdf.py +12 -1
- package/claude/skills/sd-doc-extract/_extract_pptx.py +103 -23
- package/claude/skills/sd-doc-extract/_extract_xlsb.py +93 -4
- package/claude/skills/sd-doc-extract/_extract_xlsx.py +98 -36
- package/claude/skills/sd-doc-extract/extract.py +22 -3
- package/claude/skills/sd-inner-clarify/SKILL.md +78 -0
- package/claude/skills/sd-inner-debug/SKILL.md +1 -1
- package/claude/skills/sd-inner-review/SKILL.md +13 -0
- package/claude/skills/sd-plan/SKILL.md +50 -17
- package/claude/skills/sd-prompt/SKILL.md +180 -178
- package/claude/skills/sd-prompt/references/eval-runner.md +5 -31
- package/claude/skills/sd-prompt/references/sd-eval-env-template.md +23 -0
- package/claude/skills/sd-refactor/SKILL.md +2 -2
- package/claude/skills/sd-tdd/SKILL.md +46 -10
- package/claude/skills/sd-use/SKILL.md +84 -80
- package/claude/skills/sd-wbs/SKILL.md +85 -27
- package/{claude/references/sd-simplysm14/sd-claude/docs → docs}/assets.md +2 -3
- package/{claude/references/sd-simplysm14/sd-claude/docs → docs}/hooks.md +7 -6
- package/{claude/references/sd-simplysm14/sd-claude/docs → docs}/scripts.md +1 -9
- package/package.json +3 -2
- package/scripts/sync.mjs +4 -2
- package/claude/references/sd-simplysm14/angular/docs/bootstrap.md +0 -48
- package/claude/references/sd-simplysm14/angular/docs/directives.md +0 -236
- package/claude/references/sd-simplysm14/angular/docs/features.md +0 -379
- package/claude/references/sd-simplysm14/angular/docs/pipes.md +0 -32
- package/claude/references/sd-simplysm14/angular/docs/plugins.md +0 -37
- package/claude/references/sd-simplysm14/angular/docs/provider-types.md +0 -283
- package/claude/references/sd-simplysm14/angular/docs/providers.md +0 -370
- package/claude/references/sd-simplysm14/angular/docs/styling.md +0 -222
- package/claude/references/sd-simplysm14/angular/docs/type-utilities.md +0 -250
- package/claude/references/sd-simplysm14/angular/docs/ui-data.md +0 -275
- package/claude/references/sd-simplysm14/angular/docs/ui-form.md +0 -490
- package/claude/references/sd-simplysm14/angular/docs/ui-layout.md +0 -140
- package/claude/references/sd-simplysm14/angular/docs/ui-navigation.md +0 -241
- package/claude/references/sd-simplysm14/angular/docs/ui-overlay.md +0 -157
- package/claude/references/sd-simplysm14/angular/docs/ui-visual.md +0 -127
- package/claude/references/sd-simplysm14/angular/docs/utils.md +0 -295
- package/claude/references/sd-simplysm14/angular/usage.md +0 -489
- package/claude/references/sd-simplysm14/capacitor-plugin-auto-update/usage.md +0 -182
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/file-operations.md +0 -154
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/permissions.md +0 -84
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/storage-paths.md +0 -107
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/types.md +0 -83
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/usage.md +0 -133
- package/claude/references/sd-simplysm14/capacitor-plugin-intent/usage.md +0 -203
- package/claude/references/sd-simplysm14/capacitor-plugin-usb-storage/usage.md +0 -258
- package/claude/references/sd-simplysm14/core-browser/usage.md +0 -306
- package/claude/references/sd-simplysm14/core-common/docs/errors.md +0 -82
- package/claude/references/sd-simplysm14/core-common/docs/extensions.md +0 -167
- package/claude/references/sd-simplysm14/core-common/docs/features.md +0 -136
- package/claude/references/sd-simplysm14/core-common/docs/types.md +0 -245
- package/claude/references/sd-simplysm14/core-common/docs/utils.md +0 -591
- package/claude/references/sd-simplysm14/core-common/usage.md +0 -255
- package/claude/references/sd-simplysm14/core-node/docs/child-process.md +0 -182
- package/claude/references/sd-simplysm14/core-node/docs/features.md +0 -214
- package/claude/references/sd-simplysm14/core-node/docs/file-system.md +0 -509
- package/claude/references/sd-simplysm14/core-node/docs/file-watching.md +0 -139
- package/claude/references/sd-simplysm14/core-node/docs/logging.md +0 -180
- package/claude/references/sd-simplysm14/core-node/docs/path.md +0 -176
- package/claude/references/sd-simplysm14/core-node/docs/utilities-cpx.md +0 -194
- package/claude/references/sd-simplysm14/core-node/docs/utilities-fsx.md +0 -469
- package/claude/references/sd-simplysm14/core-node/docs/utilities-pathx.md +0 -151
- package/claude/references/sd-simplysm14/core-node/docs/worker-threads.md +0 -334
- package/claude/references/sd-simplysm14/core-node/docs/worker.md +0 -205
- package/claude/references/sd-simplysm14/core-node/usage.md +0 -259
- package/claude/references/sd-simplysm14/excel/docs/core-classes.md +0 -443
- package/claude/references/sd-simplysm14/excel/docs/types.md +0 -455
- package/claude/references/sd-simplysm14/excel/docs/utilities.md +0 -194
- package/claude/references/sd-simplysm14/excel/docs/wrapper.md +0 -73
- package/claude/references/sd-simplysm14/excel/usage.md +0 -134
- package/claude/references/sd-simplysm14/lint/usage.md +0 -130
- package/claude/references/sd-simplysm14/orm-common/docs/core.md +0 -188
- package/claude/references/sd-simplysm14/orm-common/docs/expression.md +0 -190
- package/claude/references/sd-simplysm14/orm-common/docs/models.md +0 -17
- package/claude/references/sd-simplysm14/orm-common/docs/query-builder.md +0 -97
- package/claude/references/sd-simplysm14/orm-common/docs/queryable-executable.md +0 -250
- package/claude/references/sd-simplysm14/orm-common/docs/schema-builders.md +0 -364
- package/claude/references/sd-simplysm14/orm-common/docs/types.md +0 -522
- package/claude/references/sd-simplysm14/orm-common/usage.md +0 -229
- package/claude/references/sd-simplysm14/orm-node/docs/connections.md +0 -137
- package/claude/references/sd-simplysm14/orm-node/docs/core.md +0 -131
- package/claude/references/sd-simplysm14/orm-node/docs/types.md +0 -173
- package/claude/references/sd-simplysm14/orm-node/usage.md +0 -143
- package/claude/references/sd-simplysm14/sd-cli/usage.md +0 -782
- package/claude/references/sd-simplysm14/service-client/docs/features.md +0 -217
- package/claude/references/sd-simplysm14/service-client/docs/main.md +0 -148
- package/claude/references/sd-simplysm14/service-client/docs/protocol.md +0 -53
- package/claude/references/sd-simplysm14/service-client/docs/transport.md +0 -131
- package/claude/references/sd-simplysm14/service-client/docs/types.md +0 -129
- package/claude/references/sd-simplysm14/service-client/usage.md +0 -202
- package/claude/references/sd-simplysm14/service-common/docs/app-structure.md +0 -175
- package/claude/references/sd-simplysm14/service-common/docs/events.md +0 -64
- package/claude/references/sd-simplysm14/service-common/docs/protocol.md +0 -331
- package/claude/references/sd-simplysm14/service-common/docs/service-types.md +0 -90
- package/claude/references/sd-simplysm14/service-common/docs/types.md +0 -19
- package/claude/references/sd-simplysm14/service-common/usage.md +0 -154
- package/claude/references/sd-simplysm14/service-server/docs/auth.md +0 -64
- package/claude/references/sd-simplysm14/service-server/docs/core.md +0 -174
- package/claude/references/sd-simplysm14/service-server/docs/legacy.md +0 -25
- package/claude/references/sd-simplysm14/service-server/docs/main.md +0 -88
- package/claude/references/sd-simplysm14/service-server/docs/protocol.md +0 -33
- package/claude/references/sd-simplysm14/service-server/docs/services.md +0 -94
- package/claude/references/sd-simplysm14/service-server/docs/transport-http.md +0 -93
- package/claude/references/sd-simplysm14/service-server/docs/transport-socket.md +0 -119
- package/claude/references/sd-simplysm14/service-server/docs/types.md +0 -36
- package/claude/references/sd-simplysm14/service-server/docs/utils.md +0 -22
- package/claude/references/sd-simplysm14/service-server/usage.md +0 -171
- package/claude/references/sd-simplysm14/storage/usage.md +0 -301
- package/claude/references/sd-simplysm14.md +0 -35
- package/claude/rules/sd-clarify.md +0 -23
- package/claude/sd-session-start.sh +0 -10
- /package/{claude/references/sd-simplysm14/sd-claude/docs → docs}/cli.md +0 -0
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Utils
|
|
2
|
-
|
|
3
|
-
## `getConfig`
|
|
4
|
-
|
|
5
|
-
`.config.json` 파일을 읽고 캐싱한다. 파일 변경 시 자동 리로드되며, 캐시는 1시간 후 만료된다.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
async function getConfig<TConfig>(filePath: string): Promise<TConfig | undefined>;
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
| Parameter | Type | Description |
|
|
12
|
-
|-----------|------|-------------|
|
|
13
|
-
| `filePath` | `string` | `.config.json` 파일의 절대 경로 |
|
|
14
|
-
|
|
15
|
-
반환값: 파싱된 설정 객체. 파일이 존재하지 않으면 `undefined`.
|
|
16
|
-
|
|
17
|
-
캐싱 동작:
|
|
18
|
-
- `LazyGcMap`을 사용하여 캐시를 관리한다 (10분 간격 GC, 1시간 후 만료)
|
|
19
|
-
- 캐시 히트 시 파일을 다시 읽지 않는다 (접근 시간이 자동 갱신됨)
|
|
20
|
-
- `FsWatcher`로 파일 변경을 감시하고, 변경 시 100ms 지연 후 리로드한다
|
|
21
|
-
- 파일이 삭제되면 캐시와 워처를 모두 해제한다
|
|
22
|
-
- 캐시 만료 시 워처도 함께 해제한다
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
# @simplysm/service-server
|
|
2
|
-
|
|
3
|
-
Fastify 기반 서비스 서버. WebSocket/HTTP 이중 전송, JWT 인증, ORM 브리지, 자동 업데이트를 제공한다.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @simplysm/service-server
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## API Overview
|
|
12
|
-
|
|
13
|
-
### Main
|
|
14
|
-
|
|
15
|
-
| API | Type | Description |
|
|
16
|
-
|-----|------|-------------|
|
|
17
|
-
| `ServiceServer` | class | Fastify 래핑 서버. WebSocket/HTTP 라우팅, JWT 인증, 이벤트 브로드캐스트, graceful shutdown을 처리한다 |
|
|
18
|
-
| `ServerEventProxy` | interface | `getEvent()`가 반환하는 서버 이벤트 프록시 (`emit` 메서드만 포함) |
|
|
19
|
-
| `createServiceServer` | function | `ServiceServer` 인스턴스를 생성하는 팩토리 함수 |
|
|
20
|
-
|
|
21
|
-
→ See [docs/main.md](./docs/main.md) for details.
|
|
22
|
-
|
|
23
|
-
### Types
|
|
24
|
-
|
|
25
|
-
| API | Type | Description |
|
|
26
|
-
|-----|------|-------------|
|
|
27
|
-
| `ServiceServerOptions` | interface | 서버 생성 옵션 (rootPath, port, ssl, auth, services) |
|
|
28
|
-
|
|
29
|
-
→ See [docs/types.md](./docs/types.md) for details.
|
|
30
|
-
|
|
31
|
-
### Auth
|
|
32
|
-
|
|
33
|
-
| API | Type | Description |
|
|
34
|
-
|-----|------|-------------|
|
|
35
|
-
| `AuthTokenPayload` | interface | JWT 페이로드. `roles`와 `data`를 포함하며 `JWTPayload`를 확장한다 |
|
|
36
|
-
| `signJwt` | function | HS256/12시간 유효기간으로 JWT 토큰을 서명한다 |
|
|
37
|
-
| `verifyJwt` | function | JWT 토큰을 검증하고 페이로드를 반환한다 |
|
|
38
|
-
| `decodeJwt` | function | JWT 토큰을 검증 없이 디코딩한다 |
|
|
39
|
-
|
|
40
|
-
→ See [docs/auth.md](./docs/auth.md) for details.
|
|
41
|
-
|
|
42
|
-
### Core
|
|
43
|
-
|
|
44
|
-
| API | Type | Description |
|
|
45
|
-
|-----|------|-------------|
|
|
46
|
-
| `ServiceContext` | interface | 서비스 팩토리에 전달되는 컨텍스트. 인증 정보, 클라이언트 경로, 설정 접근을 제공한다 |
|
|
47
|
-
| `createServiceContext` | function | `ServiceContext` 인스턴스를 생성한다 |
|
|
48
|
-
| `auth` | function | 서비스/메서드에 인증을 요구하는 래퍼 함수 |
|
|
49
|
-
| `getServiceAuthPermissions` | function | `auth()`로 래핑된 함수에서 인증 권한 배열을 읽는다 |
|
|
50
|
-
| `ServiceDefinition` | interface | 서비스 정의 구조체 (name, factory, authPermissions) |
|
|
51
|
-
| `defineService` | function | 이름과 팩토리로 서비스를 정의한다 |
|
|
52
|
-
| `ServiceMethods` | type | `ServiceDefinition`에서 메서드 시그니처를 추출하는 유틸리티 타입 |
|
|
53
|
-
| `executeServiceMethod` | function | 서비스 조회 → 컨텍스트 생성 → 인증 확인 → 메서드 실행 파이프라인 |
|
|
54
|
-
|
|
55
|
-
→ See [docs/core.md](./docs/core.md) for details.
|
|
56
|
-
|
|
57
|
-
### Transport - Socket
|
|
58
|
-
|
|
59
|
-
| API | Type | Description |
|
|
60
|
-
|-----|------|-------------|
|
|
61
|
-
| `WebSocketHandler` | interface | 다중 WebSocket 연결 관리, 메시지 라우팅, 이벤트 브로드캐스트 인터페이스 |
|
|
62
|
-
| `createWebSocketHandler` | function | `WebSocketHandler` 인스턴스를 생성한다 |
|
|
63
|
-
| `ServiceSocket` | interface | 프로토콜 인코딩/디코딩, ping/pong, 이벤트 리스너 추적이 포함된 단일 WebSocket 연결 |
|
|
64
|
-
| `createServiceSocket` | function | `ServiceSocket` 인스턴스를 생성한다 |
|
|
65
|
-
|
|
66
|
-
→ See [docs/transport-socket.md](./docs/transport-socket.md) for details.
|
|
67
|
-
|
|
68
|
-
### Transport - HTTP
|
|
69
|
-
|
|
70
|
-
| API | Type | Description |
|
|
71
|
-
|-----|------|-------------|
|
|
72
|
-
| `handleHttpRequest` | function | GET/POST `/api/:service/:method` 요청을 처리한다 |
|
|
73
|
-
| `handleUpload` | function | `/upload` 경로의 multipart 파일 업로드를 처리한다 |
|
|
74
|
-
| `handleStaticFile` | function | 정적 파일 서빙 (경로 탐색 공격 방지 포함) |
|
|
75
|
-
|
|
76
|
-
→ See [docs/transport-http.md](./docs/transport-http.md) for details.
|
|
77
|
-
|
|
78
|
-
### Protocol
|
|
79
|
-
|
|
80
|
-
| API | Type | Description |
|
|
81
|
-
|-----|------|-------------|
|
|
82
|
-
| `ServerProtocolWrapper` | interface | 메시지 인코딩/디코딩 래퍼. 무거운 작업은 worker 스레드에 위임한다 |
|
|
83
|
-
| `createServerProtocolWrapper` | function | `ServerProtocolWrapper` 인스턴스를 생성한다 |
|
|
84
|
-
|
|
85
|
-
→ See [docs/protocol.md](./docs/protocol.md) for details.
|
|
86
|
-
|
|
87
|
-
### Services
|
|
88
|
-
|
|
89
|
-
| API | Type | Description |
|
|
90
|
-
|-----|------|-------------|
|
|
91
|
-
| `OrmService` | const | ORM 브리지 서비스 정의. WebSocket 전용, 인증 필수 |
|
|
92
|
-
| `OrmServiceType` | type | `OrmService`의 메서드 시그니처 타입 |
|
|
93
|
-
| `AutoUpdateService` | const | 자동 업데이트 서비스 정의. 플랫폼별 최신 버전 파일을 탐색한다 |
|
|
94
|
-
| `AutoUpdateServiceType` | type | `AutoUpdateService`의 메서드 시그니처 타입 |
|
|
95
|
-
| `AppStructureService` | function | 앱 구조 정보 서비스를 생성하는 팩토리 함수. `Record<string, AppStructureItem[]>`을 받아 서비스 정의를 반환한다 |
|
|
96
|
-
| `AppStructureServiceType` | type | `AppStructureService`가 반환하는 서비스의 메서드 시그니처 타입 |
|
|
97
|
-
|
|
98
|
-
→ See [docs/services.md](./docs/services.md) for details.
|
|
99
|
-
|
|
100
|
-
### Utils
|
|
101
|
-
|
|
102
|
-
| API | Type | Description |
|
|
103
|
-
|-----|------|-------------|
|
|
104
|
-
| `getConfig` | function | `.config.json` 파일을 읽고 캐싱한다. 파일 변경 시 자동 리로드된다 |
|
|
105
|
-
|
|
106
|
-
→ See [docs/utils.md](./docs/utils.md) for details.
|
|
107
|
-
|
|
108
|
-
### Legacy
|
|
109
|
-
|
|
110
|
-
| API | Type | Description |
|
|
111
|
-
|-----|------|-------------|
|
|
112
|
-
| `handleV1Connection` | function | V1 레거시 WebSocket 프로토콜 호환 레이어. 자동 업데이트만 지원한다 |
|
|
113
|
-
|
|
114
|
-
→ See [docs/legacy.md](./docs/legacy.md) for details.
|
|
115
|
-
|
|
116
|
-
## Usage Examples
|
|
117
|
-
|
|
118
|
-
### 서버 생성 및 시작
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { createServiceServer, defineService, auth } from "@simplysm/service-server";
|
|
122
|
-
|
|
123
|
-
const HealthService = defineService("Health", (ctx) => ({
|
|
124
|
-
check: () => ({ status: "ok" }),
|
|
125
|
-
}));
|
|
126
|
-
|
|
127
|
-
const UserService = defineService("User", auth((ctx) => ({
|
|
128
|
-
getProfile: () => ctx.authInfo,
|
|
129
|
-
})));
|
|
130
|
-
|
|
131
|
-
const server = createServiceServer<{ userId: string }>({
|
|
132
|
-
rootPath: "/app",
|
|
133
|
-
port: 3000,
|
|
134
|
-
auth: { jwtSecret: "my-secret" },
|
|
135
|
-
services: [HealthService, UserService],
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
await server.listen();
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### JWT 토큰 발급 및 검증
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
const token = await server.signAuthToken({
|
|
145
|
-
roles: ["admin"],
|
|
146
|
-
data: { userId: "123" },
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const payload = await server.verifyAuthToken(token);
|
|
150
|
-
// payload.data.userId === "123"
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### 이벤트 브로드캐스트
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
import { defineEvent } from "@simplysm/service-common";
|
|
157
|
-
|
|
158
|
-
// 서버에서 이벤트 정의 + 타입 export
|
|
159
|
-
export const UserUpdatedEvent = defineEvent<{ userId: string }, { name: string }>("UserUpdated");
|
|
160
|
-
|
|
161
|
-
// 이벤트 프록시 방식 (권장 — getService()와 동일한 패턴)
|
|
162
|
-
const userUpdatedEvt = server.getEvent<typeof UserUpdatedEvent>("UserUpdated");
|
|
163
|
-
await userUpdatedEvt.emit((info) => info.userId === "123", { name: "새 이름" });
|
|
164
|
-
|
|
165
|
-
// 직접 호출 방식 (하위 호환)
|
|
166
|
-
await server.emitEvent<typeof UserUpdatedEvent>(
|
|
167
|
-
"UserUpdated",
|
|
168
|
-
(info) => info.userId === "123",
|
|
169
|
-
{ name: "새 이름" },
|
|
170
|
-
);
|
|
171
|
-
```
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
# @simplysm/storage
|
|
2
|
-
|
|
3
|
-
FTP/FTPS/SFTP 파일 저장소 클라이언트 라이브러리 (Node.js 전용). `StorageClient` 인터페이스로 프로토콜을 통일하고, `StorageFactory`로 연결 생명주기를 관리한다.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @simplysm/storage
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## API Overview
|
|
12
|
-
|
|
13
|
-
### Types
|
|
14
|
-
|
|
15
|
-
| API | Type | Description |
|
|
16
|
-
|-----|------|-------------|
|
|
17
|
-
| `StorageProtocol` | type | 지원 프로토콜 유니온 타입 (`"ftp"` \| `"ftps"` \| `"sftp"`) |
|
|
18
|
-
| `StorageConnConfig` | interface | 스토리지 연결 설정 |
|
|
19
|
-
| `FileInfo` | interface | 파일/디렉토리 정보 |
|
|
20
|
-
| `StorageClient` | interface | 스토리지 클라이언트 공통 인터페이스 |
|
|
21
|
-
|
|
22
|
-
#### `StorageProtocol`
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
type StorageProtocol = "ftp" | "ftps" | "sftp";
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
지원하는 프로토콜을 나타내는 유니온 타입:
|
|
29
|
-
- `"ftp"`: 일반 FTP 프로토콜
|
|
30
|
-
- `"ftps"`: TLS/SSL 암호화 FTP 프로토콜
|
|
31
|
-
- `"sftp"`: SSH 기반 SFTP 프로토콜
|
|
32
|
-
|
|
33
|
-
#### `StorageConnConfig`
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
interface StorageConnConfig {
|
|
37
|
-
host: string;
|
|
38
|
-
port?: number;
|
|
39
|
-
user?: string;
|
|
40
|
-
password?: string;
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
| Field | Type | Description |
|
|
45
|
-
|-------|------|-------------|
|
|
46
|
-
| `host` | `string` | 서버 호스트 주소 |
|
|
47
|
-
| `port` | `number \| undefined` | 포트 번호. 생략 시 프로토콜 기본값 사용 (FTP: 21, FTPS: 21, SFTP: 22) |
|
|
48
|
-
| `user` | `string \| undefined` | 사용자 이름 |
|
|
49
|
-
| `password` | `string \| undefined` | 비밀번호. SFTP에서 생략하면 SSH agent (`SSH_AUTH_SOCK` 환경변수) + `~/.ssh/id_ed25519` 키 파일 인증을 순서대로 시도 |
|
|
50
|
-
|
|
51
|
-
#### `FileInfo`
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
interface FileInfo {
|
|
55
|
-
name: string;
|
|
56
|
-
isFile: boolean;
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
| Field | Type | Description |
|
|
61
|
-
|-------|------|-------------|
|
|
62
|
-
| `name` | `string` | 파일 또는 디렉토리의 이름 |
|
|
63
|
-
| `isFile` | `boolean` | `true`이면 파일, `false`이면 디렉토리 |
|
|
64
|
-
|
|
65
|
-
#### `StorageClient`
|
|
66
|
-
|
|
67
|
-
스토리지 클라이언트 공통 인터페이스. `FtpStorageClient`와 `SftpStorageClient`가 구현한다.
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
interface StorageClient {
|
|
71
|
-
connect(config: StorageConnConfig): Promise<void>;
|
|
72
|
-
mkdir(dirPath: string): Promise<void>;
|
|
73
|
-
rename(fromPath: string, toPath: string): Promise<void>;
|
|
74
|
-
list(dirPath: string): Promise<FileInfo[]>;
|
|
75
|
-
readFile(filePath: string): Promise<Bytes>;
|
|
76
|
-
exists(filePath: string): Promise<boolean>;
|
|
77
|
-
put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void>;
|
|
78
|
-
uploadDir(fromPath: string, toPath: string): Promise<void>;
|
|
79
|
-
remove(filePath: string): Promise<void>;
|
|
80
|
-
close(): Promise<void>;
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
| Method | Parameters | Return | Description |
|
|
85
|
-
|--------|-----------|--------|-------------|
|
|
86
|
-
| `connect` | `config: StorageConnConfig` | `Promise<void>` | 스토리지 서버에 연결. 연결 해제 전 한 번만 호출 가능 |
|
|
87
|
-
| `mkdir` | `dirPath: string` | `Promise<void>` | 디렉토리 생성. 부모 디렉토리가 없으면 함께 생성 |
|
|
88
|
-
| `rename` | `fromPath: string, toPath: string` | `Promise<void>` | 파일/디렉토리 이름 변경 또는 이동 |
|
|
89
|
-
| `list` | `dirPath: string` | `Promise<FileInfo[]>` | 디렉토리 내 파일/디렉토리 목록 조회 |
|
|
90
|
-
| `readFile` | `filePath: string` | `Promise<Bytes>` | 파일 내용을 `Bytes`(`Uint8Array`)로 읽기 |
|
|
91
|
-
| `exists` | `filePath: string` | `Promise<boolean>` | 파일/디렉토리 존재 여부 확인. 모든 예외는 `false` 반환 |
|
|
92
|
-
| `put` | `localPathOrBuffer: string \| Bytes, storageFilePath: string` | `Promise<void>` | 로컬 파일 경로 또는 바이트 데이터를 원격 경로에 업로드 |
|
|
93
|
-
| `uploadDir` | `fromPath: string, toPath: string` | `Promise<void>` | 로컬 디렉토리 전체를 원격 경로에 업로드 |
|
|
94
|
-
| `remove` | `filePath: string` | `Promise<void>` | 파일 삭제 |
|
|
95
|
-
| `close` | 없음 | `Promise<void>` | 연결 종료. 이미 종료된 상태에서 호출해도 안전 |
|
|
96
|
-
|
|
97
|
-
### Clients
|
|
98
|
-
|
|
99
|
-
| API | Type | Description |
|
|
100
|
-
|-----|------|-------------|
|
|
101
|
-
| `FtpStorageClient` | class | FTP/FTPS 프로토콜 스토리지 클라이언트 (`basic-ftp` 라이브러리 기반) |
|
|
102
|
-
| `SftpStorageClient` | class | SFTP 프로토콜 스토리지 클라이언트 (`ssh2-sftp-client` 라이브러리 기반) |
|
|
103
|
-
|
|
104
|
-
#### `FtpStorageClient`
|
|
105
|
-
|
|
106
|
-
FTP/FTPS 프로토콜을 사용하는 스토리지 클라이언트. `StorageClient` 인터페이스를 구현한다.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
class FtpStorageClient implements StorageClient {
|
|
110
|
-
constructor(private readonly _secure: boolean = false);
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**생성자**:
|
|
115
|
-
- `_secure`: `true`이면 FTPS (TLS/SSL 암호화), `false`이면 FTP (기본값)
|
|
116
|
-
|
|
117
|
-
**특징**:
|
|
118
|
-
- `connect()`로 연결 후 메서드 호출. 미연결 상태에서 호출하면 `SdError` 발생
|
|
119
|
-
- `exists()`는 먼저 `size()` 명령으로 파일을 O(1) 성능으로 확인하고, 실패 시 부모 디렉토리 목록을 조회하여 디렉토리 존재 여부 확인. 모든 예외는 `false` 반환
|
|
120
|
-
- 슬래시가 없는 경로(예: `file.txt`)는 루트 디렉토리(`/`)에서 검색
|
|
121
|
-
- `close()`는 이미 종료된 상태에서 호출해도 안전 (오류 미발생)
|
|
122
|
-
|
|
123
|
-
#### `SftpStorageClient`
|
|
124
|
-
|
|
125
|
-
SFTP 프로토콜을 사용하는 스토리지 클라이언트. `StorageClient` 인터페이스를 구현한다.
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
class SftpStorageClient implements StorageClient {
|
|
129
|
-
constructor();
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
**인증 메커니즘**:
|
|
134
|
-
- `password`가 있으면 패스워드 인증 사용
|
|
135
|
-
- `password`가 없으면 다음 순서대로 시도:
|
|
136
|
-
1. SSH agent (`SSH_AUTH_SOCK` 환경변수 설정 시)
|
|
137
|
-
2. `~/.ssh/id_ed25519` 개인키 파일 인증
|
|
138
|
-
3. privateKey 파싱 실패 시 (암호화된 키 등) agent만으로 재시도
|
|
139
|
-
|
|
140
|
-
**특징**:
|
|
141
|
-
- `connect()`로 연결 후 메서드 호출. 미연결 상태에서 호출하면 `SdError` 발생
|
|
142
|
-
- `exists()`는 `ssh2-sftp-client`의 `exists()` 반환값 (`false | 'd' | '-' | 'l'`)을 검사하여 존재 여부 판단. 모든 예외는 `false` 반환
|
|
143
|
-
- `close()`는 이미 종료된 상태에서 호출해도 안전 (오류 미발생)
|
|
144
|
-
|
|
145
|
-
### Factory
|
|
146
|
-
|
|
147
|
-
| API | Type | Description |
|
|
148
|
-
|-----|------|-------------|
|
|
149
|
-
| `StorageFactory` | class | 프로토콜별 클라이언트 생성 및 연결 생명주기 자동 관리 |
|
|
150
|
-
|
|
151
|
-
#### `StorageFactory`
|
|
152
|
-
|
|
153
|
-
스토리지 클라이언트 팩토리. 콜백 패턴으로 연결/종료를 자동 관리한다.
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
class StorageFactory {
|
|
157
|
-
static async connect<R>(
|
|
158
|
-
type: StorageProtocol,
|
|
159
|
-
config: StorageConnConfig,
|
|
160
|
-
fn: (storage: StorageClient) => R | Promise<R>,
|
|
161
|
-
): Promise<R>;
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
**메서드**:
|
|
166
|
-
- `StorageFactory.connect<R>()` (정적 메서드)
|
|
167
|
-
|
|
168
|
-
**파라미터**:
|
|
169
|
-
|
|
170
|
-
| Parameter | Type | Description |
|
|
171
|
-
|-----------|------|-------------|
|
|
172
|
-
| `type` | `StorageProtocol` | 프로토콜 타입 (`"ftp"`, `"ftps"`, `"sftp"`) |
|
|
173
|
-
| `config` | `StorageConnConfig` | 연결 설정 |
|
|
174
|
-
| `fn` | `(storage: StorageClient) => R \| Promise<R>` | 연결된 클라이언트를 받아 작업을 수행하는 콜백. 반환값은 `Promise<R>` 형태로 래핑되어 반환됨 |
|
|
175
|
-
|
|
176
|
-
**동작**:
|
|
177
|
-
- `fn` 콜백이 완료되거나 예외를 발생시키면 연결이 자동으로 종료됨
|
|
178
|
-
- `fn`에서 발생한 예외는 그대로 전파됨
|
|
179
|
-
- 반환값: 콜백의 반환값
|
|
180
|
-
|
|
181
|
-
## Usage Examples
|
|
182
|
-
|
|
183
|
-
### SFTP로 파일 업로드 (StorageFactory 사용 권장)
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
187
|
-
|
|
188
|
-
await StorageFactory.connect(
|
|
189
|
-
"sftp",
|
|
190
|
-
{ host: "sftp.example.com", user: "user", password: "pass" },
|
|
191
|
-
async (storage) => {
|
|
192
|
-
await storage.mkdir("/remote/dir");
|
|
193
|
-
await storage.put("/local/file.txt", "/remote/dir/file.txt");
|
|
194
|
-
},
|
|
195
|
-
);
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
콜백이 완료되거나 예외가 발생하면 자동으로 연결이 종료된다.
|
|
199
|
-
|
|
200
|
-
### FTP로 파일 목록 조회 및 다운로드
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
204
|
-
|
|
205
|
-
const files = await StorageFactory.connect(
|
|
206
|
-
"ftp",
|
|
207
|
-
{ host: "ftp.example.com", port: 21, user: "user", password: "pass" },
|
|
208
|
-
async (storage) => {
|
|
209
|
-
const list = await storage.list("/data");
|
|
210
|
-
for (const file of list.filter((f) => f.isFile)) {
|
|
211
|
-
const content = await storage.readFile(`/data/${file.name}`);
|
|
212
|
-
// content는 Bytes (Uint8Array)
|
|
213
|
-
console.log(`Read ${file.name}: ${content.length} bytes`);
|
|
214
|
-
}
|
|
215
|
-
return list;
|
|
216
|
-
},
|
|
217
|
-
);
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### FTPS로 파일 이름 변경
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
224
|
-
|
|
225
|
-
await StorageFactory.connect(
|
|
226
|
-
"ftps",
|
|
227
|
-
{ host: "ftps.example.com", user: "user", password: "pass" },
|
|
228
|
-
async (storage) => {
|
|
229
|
-
const exists = await storage.exists("/remote/file.txt");
|
|
230
|
-
if (exists) {
|
|
231
|
-
await storage.rename("/remote/file.txt", "/remote/backup.txt");
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
);
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
### 클라이언트 직접 사용 (수동 생명주기 관리)
|
|
238
|
-
|
|
239
|
-
클라이언트를 직접 인스턴스화하여 수동으로 연결 생명주기를 관리할 수 있다. 하지만 연결 누수 위험이 있으므로 `StorageFactory.connect` 사용을 권장한다.
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
import { FtpStorageClient } from "@simplysm/storage";
|
|
243
|
-
|
|
244
|
-
const client = new FtpStorageClient(true); // FTPS 사용
|
|
245
|
-
try {
|
|
246
|
-
await client.connect({ host: "ftps.example.com", user: "user", password: "pass" });
|
|
247
|
-
const exists = await client.exists("/remote/file.txt");
|
|
248
|
-
if (exists) {
|
|
249
|
-
await client.rename("/remote/file.txt", "/remote/backup.txt");
|
|
250
|
-
}
|
|
251
|
-
} finally {
|
|
252
|
-
await client.close();
|
|
253
|
-
}
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### SSH 키 인증으로 SFTP 연결 (비밀번호 생략)
|
|
257
|
-
|
|
258
|
-
`password`를 생략하면 SSH agent와 `~/.ssh/id_ed25519` 키 파일을 사용하여 인증한다.
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
262
|
-
|
|
263
|
-
await StorageFactory.connect(
|
|
264
|
-
"sftp",
|
|
265
|
-
{ host: "sftp.example.com", user: "user" }, // password 생략
|
|
266
|
-
async (storage) => {
|
|
267
|
-
const list = await storage.list("/home/user");
|
|
268
|
-
console.log(`Files: ${list.map((f) => f.name).join(", ")}`);
|
|
269
|
-
},
|
|
270
|
-
);
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### 바이트 데이터로 파일 업로드
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
277
|
-
|
|
278
|
-
const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // "Hello"
|
|
279
|
-
|
|
280
|
-
await StorageFactory.connect(
|
|
281
|
-
"sftp",
|
|
282
|
-
{ host: "sftp.example.com", user: "user", password: "pass" },
|
|
283
|
-
async (storage) => {
|
|
284
|
-
await storage.put(data, "/remote/file.bin");
|
|
285
|
-
},
|
|
286
|
-
);
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### 로컬 디렉토리 전체 업로드
|
|
290
|
-
|
|
291
|
-
```typescript
|
|
292
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
293
|
-
|
|
294
|
-
await StorageFactory.connect(
|
|
295
|
-
"ftp",
|
|
296
|
-
{ host: "ftp.example.com", user: "user", password: "pass" },
|
|
297
|
-
async (storage) => {
|
|
298
|
-
await storage.uploadDir("/local/folder", "/remote/backup");
|
|
299
|
-
},
|
|
300
|
-
);
|
|
301
|
-
```
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# sd-simplysm14: @simplysm v14 소비앱 가이드
|
|
2
|
-
|
|
3
|
-
소비앱이 `@simplysm/*` v14를 사용할 때 적용되는 지침 및 사용법.
|
|
4
|
-
|
|
5
|
-
## 중간 패키지(common) 불필요
|
|
6
|
-
|
|
7
|
-
v14에서는 `import type`으로 타입을 직접 가져올 수 있으므로, 이전 버전에서 클라이언트-서버 간 타입 공유를 위해 필요하던 중간 패키지(예: `service-common`, `orm-common`)가 소비앱의 의존성으로 불필요하다.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
// v14: 서버 패키지에서 타입을 직접 import — common 패키지 의존성 불필요
|
|
11
|
-
import type { ServiceMethods } from "@simplysm/service-server";
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## 패키지별 상세 문서
|
|
15
|
-
|
|
16
|
-
| 패키지 | 문서 |
|
|
17
|
-
| -------------------------------------- | ----------------------------------------------------------------------------- |
|
|
18
|
-
| @simplysm/angular | [usage.md](../references/sd-simplysm14/angular/usage.md) |
|
|
19
|
-
| @simplysm/capacitor-plugin-auto-update | [usage.md](../references/sd-simplysm14/capacitor-plugin-auto-update/usage.md) |
|
|
20
|
-
| @simplysm/capacitor-plugin-file-system | [usage.md](../references/sd-simplysm14/capacitor-plugin-file-system/usage.md) |
|
|
21
|
-
| @simplysm/capacitor-plugin-intent | [usage.md](../references/sd-simplysm14/capacitor-plugin-intent/usage.md) |
|
|
22
|
-
| @simplysm/capacitor-plugin-usb-storage | [usage.md](../references/sd-simplysm14/capacitor-plugin-usb-storage/usage.md) |
|
|
23
|
-
| @simplysm/core-browser | [usage.md](../references/sd-simplysm14/core-browser/usage.md) |
|
|
24
|
-
| @simplysm/core-common | [usage.md](../references/sd-simplysm14/core-common/usage.md) |
|
|
25
|
-
| @simplysm/core-node | [usage.md](../references/sd-simplysm14/core-node/usage.md) |
|
|
26
|
-
| @simplysm/excel | [usage.md](../references/sd-simplysm14/excel/usage.md) |
|
|
27
|
-
| @simplysm/lint | [usage.md](../references/sd-simplysm14/lint/usage.md) |
|
|
28
|
-
| @simplysm/orm-common | [usage.md](../references/sd-simplysm14/orm-common/usage.md) |
|
|
29
|
-
| @simplysm/orm-node | [usage.md](../references/sd-simplysm14/orm-node/usage.md) |
|
|
30
|
-
| @simplysm/sd-claude | [usage.md](../references/sd-simplysm14/sd-claude/usage.md) |
|
|
31
|
-
| @simplysm/sd-cli | [usage.md](../references/sd-simplysm14/sd-cli/usage.md) |
|
|
32
|
-
| @simplysm/service-client | [usage.md](../references/sd-simplysm14/service-client/usage.md) |
|
|
33
|
-
| @simplysm/service-common | [usage.md](../references/sd-simplysm14/service-common/usage.md) |
|
|
34
|
-
| @simplysm/service-server | [usage.md](../references/sd-simplysm14/service-server/usage.md) |
|
|
35
|
-
| @simplysm/storage | [usage.md](../references/sd-simplysm14/storage/usage.md) |
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# sd-clarify: 명확화 규칙
|
|
2
|
-
|
|
3
|
-
정보의 명확성 판단 및 불명확한 정보를 명확화 하고자 할 때 적용한다.
|
|
4
|
-
파악한 정보를 확실성 수준별로 분류하고, 불명확한 항목은 사용자에게 질문하여 해소한다.
|
|
5
|
-
|
|
6
|
-
## 명확성 분류
|
|
7
|
-
|
|
8
|
-
정보의 명확성을 다음 기준으로 분류한다.
|
|
9
|
-
|
|
10
|
-
- **VERIFIED**: 사용자가 직접 말했거나 문서/코드에 명시된 것
|
|
11
|
-
- **INFERRED**
|
|
12
|
-
- **High**: 타겟 코드베이스에서 동일 패턴을 확인했거나 공식 문서에 근거가 있는 추론
|
|
13
|
-
- **Medium**: 일반적 도메인 관행이나 유사 사례에 기반한 추론. 마이그레이션 원본, 이전 버전, 외부 프로젝트의 패턴은 "유사 사례"에 해당
|
|
14
|
-
- **Low**: 약한 유추나 제한적 근거에 기반한 추론
|
|
15
|
-
- **ASSUMED**: 추측에 해당 — 반드시 질문으로 전환
|
|
16
|
-
|
|
17
|
-
분류 결과를 사용자에게 출력한다.
|
|
18
|
-
|
|
19
|
-
## 명확화 질문
|
|
20
|
-
|
|
21
|
-
INFERRED Medium/Low와 ASSUMED는 **MUST** `.claude/rules/sd-options.md` 의 지침에 따라, 사용자에게 질문하여 명확화한다.
|
|
22
|
-
|
|
23
|
-
- VERIFIED와 INFERRED High는 명확한 것으로 본다.
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
echo "Read the following rule files before proceeding:"
|
|
3
|
-
files=$(ls -1 .claude/rules/*.md 2>/dev/null)
|
|
4
|
-
if [ -n "$files" ]; then
|
|
5
|
-
echo "$files" | while read f; do echo "- $f"; done
|
|
6
|
-
fi
|
|
7
|
-
echo
|
|
8
|
-
if [ -f "CLAUDE.md" ]; then
|
|
9
|
-
echo "- CLAUDE.md"
|
|
10
|
-
fi
|
|
File without changes
|