@things-factory/integration-data-go-kr 10.0.0-beta.62

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 (67) hide show
  1. package/README.md +73 -0
  2. package/ROADMAP.md +271 -0
  3. package/dist-server/engine/connector/data-go-kr-client.d.ts +27 -0
  4. package/dist-server/engine/connector/data-go-kr-client.js +115 -0
  5. package/dist-server/engine/connector/data-go-kr-client.js.map +1 -0
  6. package/dist-server/engine/connector/data-go-kr-connector.d.ts +35 -0
  7. package/dist-server/engine/connector/data-go-kr-connector.js +59 -0
  8. package/dist-server/engine/connector/data-go-kr-connector.js.map +1 -0
  9. package/dist-server/engine/connector/index.d.ts +1 -0
  10. package/dist-server/engine/connector/index.js +4 -0
  11. package/dist-server/engine/connector/index.js.map +1 -0
  12. package/dist-server/engine/index.d.ts +2 -0
  13. package/dist-server/engine/index.js +5 -0
  14. package/dist-server/engine/index.js.map +1 -0
  15. package/dist-server/engine/spec/building-ledger.d.ts +9 -0
  16. package/dist-server/engine/spec/building-ledger.js +135 -0
  17. package/dist-server/engine/spec/building-ledger.js.map +1 -0
  18. package/dist-server/engine/spec/index.d.ts +16 -0
  19. package/dist-server/engine/spec/index.js +42 -0
  20. package/dist-server/engine/spec/index.js.map +1 -0
  21. package/dist-server/engine/spec/types.d.ts +79 -0
  22. package/dist-server/engine/spec/types.js +30 -0
  23. package/dist-server/engine/spec/types.js.map +1 -0
  24. package/dist-server/engine/task/building-ledger/general.d.ts +41 -0
  25. package/dist-server/engine/task/building-ledger/general.js +92 -0
  26. package/dist-server/engine/task/building-ledger/general.js.map +1 -0
  27. package/dist-server/engine/task/building-ledger/index.d.ts +12 -0
  28. package/dist-server/engine/task/building-ledger/index.js +15 -0
  29. package/dist-server/engine/task/building-ledger/index.js.map +1 -0
  30. package/dist-server/engine/task/call.d.ts +33 -0
  31. package/dist-server/engine/task/call.js +128 -0
  32. package/dist-server/engine/task/call.js.map +1 -0
  33. package/dist-server/engine/task/index.d.ts +19 -0
  34. package/dist-server/engine/task/index.js +22 -0
  35. package/dist-server/engine/task/index.js.map +1 -0
  36. package/dist-server/engine/types.d.ts +63 -0
  37. package/dist-server/engine/types.js +9 -0
  38. package/dist-server/engine/types.js.map +1 -0
  39. package/dist-server/index.d.ts +4 -0
  40. package/dist-server/index.js +10 -0
  41. package/dist-server/index.js.map +1 -0
  42. package/dist-server/tsconfig.tsbuildinfo +1 -0
  43. package/helps/integration/connector/data-go-kr-connector.md +39 -0
  44. package/helps/integration/services/building-ledger.md +109 -0
  45. package/helps/integration/task/building-ledger.md +111 -0
  46. package/helps/integration/task/data-go-kr-call.md +87 -0
  47. package/package.json +28 -0
  48. package/server/engine/connector/data-go-kr-client.ts +133 -0
  49. package/server/engine/connector/data-go-kr-connector.ts +75 -0
  50. package/server/engine/connector/index.ts +1 -0
  51. package/server/engine/index.ts +2 -0
  52. package/server/engine/spec/building-ledger.ts +140 -0
  53. package/server/engine/spec/index.ts +41 -0
  54. package/server/engine/spec/types.ts +84 -0
  55. package/server/engine/task/building-ledger/general.ts +109 -0
  56. package/server/engine/task/building-ledger/index.ts +12 -0
  57. package/server/engine/task/call.ts +157 -0
  58. package/server/engine/task/index.ts +19 -0
  59. package/server/engine/types.ts +64 -0
  60. package/server/index.ts +5 -0
  61. package/things-factory.config.js +1 -0
  62. package/translations/en.json +11 -0
  63. package/translations/ja.json +11 -0
  64. package/translations/ko.json +11 -0
  65. package/translations/ms.json +11 -0
  66. package/translations/zh.json +11 -0
  67. package/tsconfig.json +10 -0
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @things-factory/integration-data-go-kr
2
+
3
+ 한국 공공데이터포털 **[data.go.kr](https://www.data.go.kr)** 의 Open API 를 Things-Factory 통합 엔진에서 호출하기 위한 커넥터 + 태스크 묶음.
4
+
5
+ ## 설계 철학
6
+
7
+ 공공데이터포털에는 수천 개의 API 가 있지만 대부분 **같은 봉투 규약**(`response.header.resultCode` + `response.body.items.item`) 을 따른다. 그래서:
8
+
9
+ - **한 개의 커넥터** (`data-go-kr-connector`) 가 ServiceKey 를 관리
10
+ - **한 개의 범용 태스크** (`data-go-kr-call`) 가 모든 오퍼레이션을 호출
11
+ - **선언적 스펙 레지스트리** 가 파라미터 검증·문서·(장기) UI 도움말의 단일 원천
12
+ - **자주 쓰이는 도메인 전용 태스크** 만 별도 등록 (예: `data-go-kr-building-ledger`)
13
+
14
+ 이렇게 하면 TaskRegistry 가 폭발하지 않고, 새 서비스는 스펙 파일 한 개만 추가해서 즉시 사용 가능하다.
15
+
16
+ ## 제공 기능 (Phase 0)
17
+
18
+ ### Connector
19
+ - `data-go-kr-connector` — ServiceKey 기반 공용 클라이언트
20
+
21
+ ### Tasks
22
+ - `data-go-kr-call` — 범용 오퍼레이션 호출 (스펙 기반 자동 검증)
23
+ - `data-go-kr-building-ledger` — 건축물대장 표제부 조회 (순수 fetch; 집계·KPI 추출은 소비자 몫)
24
+
25
+ ### 서비스 스펙
26
+ - `1613000/BldRgstService_v2` — 국토교통부 건축물대장정보 서비스 v2 (8 오퍼레이션)
27
+
28
+ ## 빠른 시작
29
+
30
+ ```
31
+ 1. data.go.kr 가입 + 서비스 활용신청 + ServiceKey 복사
32
+ 2. Things-Factory 통합 UI → Connection 생성 (type=data-go-kr-connector)
33
+ 3. Scenario → Step 추가 (data-go-kr-call 또는 data-go-kr-building-ledger)
34
+ 4. 실행 후 로그 파일에서 결과 확인
35
+ ```
36
+
37
+ 자세한 가이드는 [helps/integration/connector/data-go-kr-connector.md](./helps/integration/connector/data-go-kr-connector.md) 참조.
38
+
39
+ ## 확장 — 새 공공 API 추가
40
+
41
+ ```
42
+ server/engine/
43
+ ├── spec/ # 서비스 스펙 (한 도메인 = 한 파일)
44
+ │ ├── types.ts # OperationSpec, ServiceSpec 정의
45
+ │ ├── index.ts # SpecRegistry
46
+ │ ├── building-ledger.ts # 건축물대장 서비스 스펙 (현재)
47
+ │ └── (향후) property-trade.ts # 부동산실거래가
48
+ │
49
+ └── task/ # 태스크 (도메인 = 폴더)
50
+ ├── index.ts # 전체 배럴
51
+ ├── call.ts # data-go-kr-call (범용)
52
+ ├── building-ledger/ # 건축물대장 도메인 전용 태스크 (현재)
53
+ │ ├── index.ts
54
+ │ └── general.ts # data-go-kr-building-ledger
55
+ └── (향후) property-trade/
56
+ ├── index.ts
57
+ └── apt-trade.ts # data-go-kr-property-trade-apt
58
+ ```
59
+
60
+ **추가 우선순위**:
61
+ 1. **공통 경로로 가능한지 먼저 검토** — `spec/<domain>.ts` 만 등록하면 `data-go-kr-call` 로 즉시 호출 가능
62
+ 2. **공통 경로로 못 푸는 예외만 전용 태스크** — 입력 폼이 명시되어야 하거나 응답 비표준 처리·도메인 가공 등이 필요할 때 `task/<domain>/<variant>.ts` 추가
63
+
64
+ 자세한 단계별 절차는 [ROADMAP.md 의 "기여 가이드"](./ROADMAP.md#기여-가이드--새-서비스-추가-워크플로우) 참조.
65
+
66
+ ## 로드맵
67
+
68
+ 전체 중장기 계획은 [ROADMAP.md](./ROADMAP.md) 참조.
69
+
70
+ ## 레퍼런스
71
+
72
+ - [공공데이터포털](https://www.data.go.kr)
73
+ - [Things-Factory integration-base](https://github.com/hatiolab/things-factory/tree/main/packages/integration-base)
package/ROADMAP.md ADDED
@@ -0,0 +1,271 @@
1
+ # @things-factory/integration-data-go-kr — ROADMAP
2
+
3
+ 본 문서는 본 모듈의 **단기·중기·장기 계획** 을 추적한다. 각 Phase 는 상호 독립적으로 진행 가능하며, 위로 갈수록 진입 장벽이 낮고 아래로 갈수록 integration-base 업스트림 변경 등 의존이 생긴다.
4
+
5
+ ---
6
+
7
+ ## Phase 0 — 초기 구조 (✅ Done)
8
+
9
+ | 항목 | 상태 | 비고 |
10
+ | --- | --- | --- |
11
+ | 패키지 스켈레톤 (`@things-factory/integration-data-go-kr`) | ✅ | integration-weather/integration-openai 패턴 준수 |
12
+ | `DataGoKrConnector` — ServiceKey 관리 + Encoding/Decoding 자동 정규화 | ✅ | `origin` 오버라이드 지원 |
13
+ | `DataGoKrClient` — 범용 HTTP + User-Agent/Accept + URL 인코딩 이슈 방지 | ✅ | 단건/다건 자동 정규화(`getItems`) |
14
+ | `OperationSpec` / `ServiceSpec` 타입 + `SpecRegistry` | ✅ | 도움말 메타 포함 (description, example, responseNotes, externalDocsUrl) |
15
+ | 건축물대장 v2 (`1613000/BldRgstService_v2`) 8 오퍼레이션 스펙 | ✅ | PNU 5요소 공통 파라미터 |
16
+ | 범용 태스크 `data-go-kr-call` | ✅ | 스펙 기반 validation + zero-pad + default + enum |
17
+ | 도메인 전용 태스크 `data-go-kr-building-ledger` | ✅ | 표제부 조회 (순수 fetch; 집계·KPI 추출은 소비자 스텝에서 처리) |
18
+ | 5개 언어 번역 (ko/en/ja/ms/zh) | ✅ | label 기반 |
19
+ | 도움말 마크다운 (커넥터/태스크/서비스 카탈로그) | ✅ | |
20
+ | dssp/dkpi 연동 | ⏳ Phase 1 | 기존 `@dssp/integration-seumter` 제거 후 본 모듈로 교체 |
21
+
22
+ ---
23
+
24
+ ## Phase 1 — 운영 안정성 (단기, ~2주)
25
+
26
+ > 실사용 중 빈번한 장애 패턴을 클라이언트 레벨에서 흡수.
27
+
28
+ ### 1.1 자동 재시도 with exponential backoff
29
+
30
+ data.go.kr 은 500 "Unexpected errors" 가 간헐적으로 발생 (피크 타임대). 현재 1회 실패 = 시나리오 실패인데 운영에서는 **일시 장애 자동 복구** 가 필수.
31
+
32
+ - `DataGoKrClient` 에 `retry` 옵션 추가 (기본 3회, 2초→4초→8초 backoff)
33
+ - 5xx 또는 네트워크 오류에만 재시도, 4xx (키/파라미터 문제) 는 즉시 실패
34
+ - Connection 레벨에서 `maxRetries`, `retryBackoffBaseMs` 파라미터 노출
35
+
36
+ ### 1.2 레이트리밋/쿼터 백프레셔
37
+
38
+ - 일일 10,000건 제약을 클라이언트가 의식하도록 메트릭 수집 (선택적 Prometheus counter)
39
+ - 제한 근접 시 로그 경고
40
+ - Connection 파라미터로 `requestsPerMinute` 소프트 제한 (선택)
41
+
42
+ ### 1.3 결과 캐싱 layer (optional)
43
+
44
+ - 건축물대장처럼 **자주 변경되지 않는 데이터** 는 PNU 단위로 TTL 캐시 (기본 24시간)
45
+ - `@things-factory/cache-service` 활용
46
+ - Connection 파라미터로 `cacheTtlSec` 노출, `0` 이면 캐싱 OFF
47
+
48
+ ### 1.4 dssp/dkpi 이관 완료
49
+
50
+ - `@dssp/integration-seumter` 삭제
51
+ - `dkpi/package.json` 에 `@things-factory/integration-data-go-kr` 추가
52
+ - `dkpi/server/index.ts` import 교체
53
+ - 기존 Connection row 의 `type` 값 업데이트 SQL:
54
+ ```sql
55
+ UPDATE connection SET type = 'data-go-kr-connector' WHERE type = 'seumter-connector';
56
+ ```
57
+ - 기존 Scenario step 의 `task` 값 업데이트:
58
+ ```sql
59
+ UPDATE step SET task = 'data-go-kr-building-ledger' WHERE task = 'seumter-general-building';
60
+ ```
61
+ - 파라미터 키(`sigunguCd`, `bjdongCd` 등) 는 그대로 호환.
62
+
63
+ ---
64
+
65
+ ## Phase 2 — 스펙 기반 자동화 (중기, ~4주)
66
+
67
+ > 스펙이 진실의 원천이므로, 문서·UI·검증 모든 산출물이 스펙에서 자동 파생되도록.
68
+
69
+ ### 2.1 서비스 카탈로그 markdown 자동 생성
70
+
71
+ - `scripts/generate-service-help.ts` 작성
72
+ - `ServiceSpec` → `helps/integration/services/<serviceId>.md` 로 변환
73
+ - CI 에서 `npm run docs:services` → 수동으로 쓴 markdown 과 diff 검증
74
+ - 장기적으로는 모든 서비스 카탈로그가 spec 에서 자동 생성 (현재는 building-ledger 만 수작업)
75
+
76
+ ### 2.2 스펙 기반 타입 생성 (선택)
77
+
78
+ - 각 오퍼레이션의 응답 레코드 타입(`BrTitleItem` 등) 을 spec 으로부터 TypeScript 인터페이스로 자동 생성
79
+ - 현재는 `types.ts` 에 수작업. 서비스 수가 늘면 필요.
80
+
81
+ ### 2.3 OpenAPI/Swagger 호환 export
82
+
83
+ - `SpecRegistry` 를 OpenAPI 3.0 스펙으로 export
84
+ - Swagger UI 로 로컬 문서 서빙 (개발자 탐색용)
85
+
86
+ ---
87
+
88
+ ## Phase 3 — 동적 parameterSpec (중기, ~6주)
89
+
90
+ > 현재는 범용 태스크의 `params` 가 freeform JSON. operation 선택 시 **자동 생성된 폼** 으로 바뀌게 하려면 integration-base 업스트림 작업 필요.
91
+
92
+ ### 3.1 integration-base 업스트림 제안
93
+
94
+ - `TaskHandler.parameterSpec` 이 **정적 배열 | 동적 함수** 양쪽 수용하도록 타입 확장
95
+ ```ts
96
+ type DynamicParameterSpec = (context: { step: Step; connection: Connection }) => PropertySpec[]
97
+ parameterSpec?: PropertySpec[] | DynamicParameterSpec
98
+ ```
99
+ - UI(`integration-ui`) 가 `operationRef` 변경 시 `parameterSpec` 를 재조회하도록 훅 추가
100
+ - PR → things-factory 모노레포 주변 검토
101
+
102
+ ### 3.2 본 모듈에서 동적 parameterSpec 활용
103
+
104
+ - `data-go-kr-call.ts` 의 `parameterSpec` 을 함수형으로 전환
105
+ - `operationRef` 가 선택되면 해당 스펙의 `params` 로 UI 폼 자동 생성 (label, description 툴팁, enum → select, required 등)
106
+ - 도움말이 **각 필드별 툴팁** 으로 렌더 → markdown 을 안 열어도 됨
107
+
108
+ ---
109
+
110
+ ## Phase 4 — 서비스 라인업 확장 (중기, ~8주)
111
+
112
+ > 실제 프로젝트 수요를 확인하며 스펙을 하나씩 추가. 각각은 스펙 파일 1개 + 선택적으로 도메인 태스크 1개.
113
+
114
+ ### 4.1 집합건축물 정밀 조회
115
+
116
+ - `data-go-kr-building-ledger-apt` 전용 태스크 추가
117
+ - `getBrRecapTitleInfo` + `getBrExposPubuseAreaInfo` 조합으로 아파트 단지 정확한 연면적·세대수 추출
118
+ - 현재 `building-ledger` 는 일반건축물 표제부 기반
119
+
120
+ ### 4.2 부동산 실거래가 (`1613000/RTMSOBJSvc`)
121
+
122
+ - 아파트매매/전월세, 연립다세대, 단독다가구, 토지 거래 데이터
123
+ - 스펙: `server/engine/spec/rtms-trade.ts`
124
+ - 활용: KPI "시장가격 대비 비용성과" 지표 자동화
125
+
126
+ ### 4.3 주소/공간 (`1613000/JusoService` 또는 VWorld)
127
+
128
+ - 도로명주소 ↔ PNU 변환 (체이닝 핵심)
129
+ - `data-go-kr-address-to-pnu` 전용 태스크 → 주소 문자열 입력 → PNU 자동 반환
130
+ - dkpi 프로젝트 등록 시 UX 혁신 (사용자가 PNU 수동 입력 불필요)
131
+
132
+ ### 4.4 국토부 공간정보 / SGIS / 통계청
133
+
134
+ - 필요 시점에 추가
135
+
136
+ ### 4.5 용도별 전용 도메인 태스크
137
+
138
+ 도메인 가공이 필요할 때만 추가. 기준: **"시나리오에서 후처리로 3줄 이상 쓸 값" = 전용 태스크 후보**.
139
+
140
+ ---
141
+
142
+ ## Phase 5 — 엔터프라이즈 운영 (장기)
143
+
144
+ ### 5.1 멀티 ServiceKey 페일오버
145
+
146
+ - Connection 에 백업 ServiceKey 배열 지원
147
+ - 주 키가 실패/쿼터 초과 시 대체 키로 자동 전환
148
+
149
+ ### 5.2 비동기 배치 모드
150
+
151
+ - Phase 1 의 재시도·캐싱과 별개로, 수백~수천 건 일괄 조회 시 워커 풀 + 레이트리밋 제어
152
+ - dkpi 의 "프로젝트 전체 리프레시" 같은 시나리오용
153
+
154
+ ### 5.3 스펙 라이선싱 모델 공유
155
+
156
+ - 본 패키지의 `ServiceSpec` 포맷이 유용하다면, 다른 공공 포털(일본 e-Gov 등) 과 공유 가능한 메타 포맷으로 표준화
157
+ - `@things-factory/integration-public-data-core` 를 만들고 `integration-data-go-kr`, `integration-data-go-jp` 등을 파생
158
+
159
+ ---
160
+
161
+ ## 기여 가이드 — 새 서비스 추가 워크플로우
162
+
163
+ ### 원칙
164
+
165
+ - **1순위: 공통 경로 (`data-go-kr-call` + SpecRegistry) 로 최대한 커버**
166
+ - **2순위: 공통 경로로 못 푸는 예외만 전용 태스크로**
167
+
168
+ 대부분의 공공데이터포털 API 는 동일한 봉투 규약(`response.header.resultCode` + `response.body.items.item`) 을 따르므로 1순위로 처리된다. 그러나 아래 경우에는 2순위(전용 태스크) 가 필요하다:
169
+ - 입력 폼이 명시되어야 운영이 편한 자주 쓰는 오퍼레이션
170
+ - 응답 구조가 비표준 (다른 봉투, 배열 아닌 중첩 구조 등)
171
+ - 오퍼레이션 호출 전후에 도메인 가공 (파생 계산, 추가 호출 조합 등) 이 필요
172
+ - 여러 오퍼레이션을 묶은 매크로 호출
173
+
174
+ ### 디렉토리 컨벤션
175
+
176
+ ```
177
+ server/engine/
178
+ ├── spec/ # 서비스 스펙 (한 도메인 = 한 파일)
179
+ │ ├── types.ts # OperationSpec, ServiceSpec 정의
180
+ │ ├── index.ts # SpecRegistry
181
+ │ ├── building-ledger.ts # 건축물대장 관련 ServiceSpec 모음
182
+ │ └── (향후) property-trade.ts # 부동산실거래가 관련 ServiceSpec 모음
183
+ │
184
+ └── task/ # 태스크 (도메인 = 폴더)
185
+ ├── index.ts # 전체 배럴
186
+ ├── call.ts # data-go-kr-call (범용)
187
+ ├── building-ledger/ # 건축물대장 도메인 전용 태스크 그룹
188
+ │ ├── index.ts
189
+ │ ├── general.ts # data-go-kr-building-ledger
190
+ │ └── (향후) apt.ts # data-go-kr-building-ledger-apt
191
+ └── (향후) property-trade/
192
+ ├── index.ts
193
+ └── apt-trade.ts
194
+ ```
195
+
196
+ ### 단계별 절차
197
+
198
+ **1. 데이터셋 선정**
199
+ - [data.go.kr](https://www.data.go.kr) 에서 상품 확인
200
+ - 앱에 구독 추가, ServiceKey 는 기존 Connection 재사용 가능
201
+
202
+ **2. 스펙 파일 작성** — `server/engine/spec/<domain>.ts`
203
+ ```ts
204
+ import { ServiceSpec } from './types'
205
+
206
+ export const MyService: ServiceSpec = {
207
+ serviceId: '1234567/MyService',
208
+ label: '...',
209
+ description: '...',
210
+ homepage: 'https://www.data.go.kr/data/<dataset-id>/openapi.do',
211
+ operations: {
212
+ getFoo: {
213
+ operationId: 'getFoo',
214
+ label: '...',
215
+ description: '...',
216
+ params: [
217
+ { name: 'param1', required: true, length: 5, description: '...' }
218
+ ]
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ **3. 레지스트리 등록** — `spec/index.ts` 의 `registerService(MyService)` 에 추가
225
+
226
+ **4. 범용 경로로 호출 검증** — `data-go-kr-call` + `operationRef: "<serviceId>.getFoo"` 으로 시나리오 돌려봄. 여기서 끝나면 이상적.
227
+
228
+ **5. 필요 시 전용 태스크 작성** — `task/<domain>/<variant>.ts`
229
+ ```ts
230
+ import { TaskRegistry, ConnectionManager, Context, evaluateTemplate } from '@things-factory/integration-base'
231
+ import { DataGoKrConnectionInstance } from '../../connector/data-go-kr-connector'
232
+
233
+ async function MyTask(step, context: Context) {
234
+ const instance: DataGoKrConnectionInstance = await ConnectionManager.getConnectionInstanceByName(context.domain, step.connection)
235
+ // ... 전용 로직
236
+ return { data: { ... } }
237
+ }
238
+
239
+ MyTask.parameterSpec = [ /* 명시적 입력 폼 */ ]
240
+ MyTask.help = 'integration/task/<my-task-name>'
241
+
242
+ TaskRegistry.registerTaskHandler('data-go-kr-<my-task-name>', MyTask)
243
+ ```
244
+
245
+ **6. 태스크 배럴에 import 추가**
246
+ - `task/<domain>/index.ts` 에 `import './<variant>'`
247
+ - (신규 도메인 폴더인 경우) `task/index.ts` 에 `import './<domain>'`
248
+
249
+ **7. 도움말 작성**
250
+ - 서비스 카탈로그: `helps/integration/services/<domain>.md` (수동 — Phase 2 에서 자동 생성 예정)
251
+ - 전용 태스크 생성 시: `helps/integration/task/<my-task-name>.md`
252
+
253
+ **8. 테스트 시나리오**
254
+ - 범용 태스크로 최소 1회 정상 응답 확인
255
+ - 전용 태스크가 있다면 전용 태스크로도 호출 확인
256
+
257
+ ---
258
+
259
+ ## 현재 우선순위
260
+
261
+ | 우선순위 | 항목 | 담당 |
262
+ | --- | --- | --- |
263
+ | P0 | Phase 1.4 (dssp/dkpi 이관) | 진행 중 |
264
+ | P1 | Phase 1.1 (자동 재시도) | 다음 |
265
+ | P2 | Phase 3.1 (integration-base 동적 parameterSpec 제안 PR) | 중기 |
266
+ | P3 | Phase 4.3 (주소→PNU 자동화) | dkpi UX 개선 시점 |
267
+
268
+ ---
269
+
270
+ **최종 수정**: 2026-04-25
271
+ **담당**: @hatiolab/dssp 팀
@@ -0,0 +1,27 @@
1
+ import { DataGoKrResponse } from '../types';
2
+ export interface DataGoKrClientOptions {
3
+ serviceKey: string;
4
+ /** 오리진 오버라이드 (모의 서버/사설 프록시 용도). 기본 `https://apis.data.go.kr`. */
5
+ origin?: string;
6
+ }
7
+ export declare class DataGoKrClient {
8
+ private readonly serviceKey;
9
+ private readonly origin;
10
+ constructor(options: DataGoKrClientOptions);
11
+ /**
12
+ * 범용 GET 호출.
13
+ *
14
+ * @param servicePath `<agency>/<service>/<operation>` (예: `1613000/BldRgstService_v2/getBrTitleInfo`)
15
+ * @param params 쿼리 파라미터 (serviceKey / _type 은 자동 추가)
16
+ */
17
+ get<T>(servicePath: string, params: Record<string, any>): Promise<DataGoKrResponse<T>>;
18
+ /**
19
+ * 단건 또는 복수 items 를 배열로 정규화해서 반환한다.
20
+ *
21
+ * data.go.kr 공통 특성으로, body.items 가 아래 세 가지 형태로 올 수 있다:
22
+ * - `""` (빈 문자열, 결과 없음)
23
+ * - `{ item: { ... } }` (단건)
24
+ * - `{ item: [ ... ] }` (복수)
25
+ */
26
+ getItems<T>(servicePath: string, params: Record<string, any>): Promise<T[]>;
27
+ }
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataGoKrClient = void 0;
4
+ /**
5
+ * 공공데이터포털(data.go.kr) 공용 HTTP 클라이언트.
6
+ *
7
+ * 모든 data.go.kr Open API 는 아래 공통 규약을 따른다:
8
+ * - URL: `https://apis.data.go.kr/<agency>/<service>/<operation>`
9
+ * - 인증: `serviceKey` 쿼리 파라미터 (Encoding/Decoding 두 형태 모두 수용)
10
+ * - 포맷: `_type=json` 없으면 XML
11
+ * - 에러: `<OpenAPI_ServiceResponse>` XML 또는 `response.header.resultCode !== '00'`
12
+ *
13
+ * 본 클라이언트는 서비스·오퍼레이션에 독립적으로 동작하며, 경로를 파라미터로 받는다.
14
+ * 서비스별 도메인 로직(파라미터 검증, 응답 매핑) 은 task 레이어에서 처리.
15
+ */
16
+ const DEFAULT_ORIGIN = 'https://apis.data.go.kr';
17
+ class DataGoKrClient {
18
+ constructor(options) {
19
+ if (!options.serviceKey) {
20
+ throw new Error('DataGoKrClient requires serviceKey');
21
+ }
22
+ /* Encoding 키(%2B 포함)를 붙여넣어도 Decoding 키처럼 동작하도록 정규화.
23
+ base64 키는 `%` 를 포함하지 않으므로 raw Decoding 키는 영향 없음. */
24
+ this.serviceKey = normalizeServiceKey(options.serviceKey.trim());
25
+ this.origin = (options.origin || DEFAULT_ORIGIN).replace(/\/$/, '');
26
+ }
27
+ /**
28
+ * 범용 GET 호출.
29
+ *
30
+ * @param servicePath `<agency>/<service>/<operation>` (예: `1613000/BldRgstService_v2/getBrTitleInfo`)
31
+ * @param params 쿼리 파라미터 (serviceKey / _type 은 자동 추가)
32
+ */
33
+ async get(servicePath, params) {
34
+ const path = servicePath.startsWith('/') ? servicePath : `/${servicePath}`;
35
+ const url = new URL(`${this.origin}${path}`);
36
+ url.searchParams.set('serviceKey', this.serviceKey);
37
+ url.searchParams.set('_type', 'json');
38
+ for (const [k, v] of Object.entries(params)) {
39
+ if (v === undefined || v === null || v === '')
40
+ continue;
41
+ url.searchParams.set(k, String(v));
42
+ }
43
+ const response = await fetch(url.toString(), {
44
+ method: 'GET',
45
+ headers: {
46
+ 'User-Agent': '@things-factory/integration-data-go-kr',
47
+ Accept: 'application/json'
48
+ }
49
+ });
50
+ const raw = await response.text();
51
+ const nonSensitiveParams = Object.entries(params)
52
+ .filter(([, v]) => v !== undefined && v !== null && v !== '')
53
+ .map(([k, v]) => `${k}=${v}`)
54
+ .join(' ');
55
+ if (!response.ok) {
56
+ throw new Error(`data.go.kr ${servicePath} failed (${response.status}): ${raw.slice(0, 300)} — params: ${nonSensitiveParams}`);
57
+ }
58
+ let parsed;
59
+ try {
60
+ parsed = JSON.parse(raw);
61
+ }
62
+ catch (err) {
63
+ if (raw.includes('<OpenAPI_ServiceResponse') || raw.includes('<returnReasonCode>')) {
64
+ throw new Error(`data.go.kr ${servicePath}: ${parseOpenApiError(raw)} — params: ${nonSensitiveParams}`);
65
+ }
66
+ throw new Error(`data.go.kr ${servicePath}: non-JSON response: ${raw.slice(0, 300)} — params: ${nonSensitiveParams}`);
67
+ }
68
+ const header = parsed?.response?.header;
69
+ if (!header) {
70
+ throw new Error(`data.go.kr ${servicePath}: response missing header — body: ${raw.slice(0, 300)}`);
71
+ }
72
+ if (header.resultCode !== '00') {
73
+ throw new Error(`data.go.kr ${servicePath}: resultCode=${header.resultCode} msg=${header.resultMsg} — params: ${nonSensitiveParams}`);
74
+ }
75
+ return parsed;
76
+ }
77
+ /**
78
+ * 단건 또는 복수 items 를 배열로 정규화해서 반환한다.
79
+ *
80
+ * data.go.kr 공통 특성으로, body.items 가 아래 세 가지 형태로 올 수 있다:
81
+ * - `""` (빈 문자열, 결과 없음)
82
+ * - `{ item: { ... } }` (단건)
83
+ * - `{ item: [ ... ] }` (복수)
84
+ */
85
+ async getItems(servicePath, params) {
86
+ const response = await this.get(servicePath, params);
87
+ const items = response.response?.body?.items;
88
+ if (!items)
89
+ return [];
90
+ const arr = items.item;
91
+ if (!arr)
92
+ return [];
93
+ return Array.isArray(arr) ? arr : [arr];
94
+ }
95
+ }
96
+ exports.DataGoKrClient = DataGoKrClient;
97
+ /** Encoding 키(%2B) 를 붙여넣어도 Decoding 키로 정규화. */
98
+ function normalizeServiceKey(key) {
99
+ if (!key.includes('%'))
100
+ return key;
101
+ try {
102
+ return decodeURIComponent(key);
103
+ }
104
+ catch {
105
+ return key;
106
+ }
107
+ }
108
+ /** data.go.kr 공용 OpenAPI 에러 XML 에서 원인 추출. */
109
+ function parseOpenApiError(xml) {
110
+ const code = /<returnReasonCode>([^<]+)<\/returnReasonCode>/.exec(xml)?.[1];
111
+ const msg = /<errMsg>([^<]+)<\/errMsg>/.exec(xml)?.[1];
112
+ const auth = /<returnAuthMsg>([^<]+)<\/returnAuthMsg>/.exec(xml)?.[1];
113
+ return `code=${code} msg=${msg} auth=${auth}`;
114
+ }
115
+ //# sourceMappingURL=data-go-kr-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-go-kr-client.js","sourceRoot":"","sources":["../../../server/engine/connector/data-go-kr-client.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,cAAc,GAAG,yBAAyB,CAAA;AAQhD,MAAa,cAAc;IAIzB,YAAY,OAA8B;QACxC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACvD,CAAC;QACD;8DACsD;QACtD,IAAI,CAAC,UAAU,GAAG,mBAAmB,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAA;QAChE,IAAI,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACrE,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,CAAI,WAAmB,EAAE,MAA2B;QAC3D,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAA;QAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC,CAAA;QAC5C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QACnD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACrC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE;gBAAE,SAAQ;YACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YAC3C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,YAAY,EAAE,wCAAwC;gBACtD,MAAM,EAAE,kBAAkB;aAC3B;SACF,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAEjC,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;aAC9C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;aAC5D,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;aAC5B,IAAI,CAAC,GAAG,CAAC,CAAA;QAEZ,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,cAAc,WAAW,YAAY,QAAQ,CAAC,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,cAAc,kBAAkB,EAAE,CAC9G,CAAA;QACH,CAAC;QAED,IAAI,MAA2B,CAAA;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAA;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,CAAC,QAAQ,CAAC,0BAA0B,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBACnF,MAAM,IAAI,KAAK,CAAC,cAAc,WAAW,KAAK,iBAAiB,CAAC,GAAG,CAAC,cAAc,kBAAkB,EAAE,CAAC,CAAA;YACzG,CAAC;YACD,MAAM,IAAI,KAAK,CACb,cAAc,WAAW,wBAAwB,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,cAAc,kBAAkB,EAAE,CACrG,CAAA;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAA;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,cAAc,WAAW,qCAAqC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QACpG,CAAC;QACD,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,cAAc,WAAW,gBAAgB,MAAM,CAAC,UAAU,QAAQ,MAAM,CAAC,SAAS,cAAc,kBAAkB,EAAE,CACrH,CAAA;QACH,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAI,WAAmB,EAAE,MAA2B;QAChE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAI,WAAW,EAAE,MAAM,CAAC,CAAA;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAA;QAC5C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAA;QACrB,MAAM,GAAG,GAAI,KAAa,CAAC,IAAI,CAAA;QAC/B,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAA;QACnB,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACzC,CAAC;CACF;AA3FD,wCA2FC;AAED,+CAA+C;AAC/C,SAAS,mBAAmB,CAAC,GAAW;IACtC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAA;IAClC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAA;IACZ,CAAC;AACH,CAAC;AAED,6CAA6C;AAC7C,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,IAAI,GAAG,+CAA+C,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC3E,MAAM,GAAG,GAAG,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACtD,MAAM,IAAI,GAAG,yCAAyC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACrE,OAAO,QAAQ,IAAI,QAAQ,GAAG,SAAS,IAAI,EAAE,CAAA;AAC/C,CAAC","sourcesContent":["import { DataGoKrResponse } from '../types'\n\n/**\n * 공공데이터포털(data.go.kr) 공용 HTTP 클라이언트.\n *\n * 모든 data.go.kr Open API 는 아래 공통 규약을 따른다:\n * - URL: `https://apis.data.go.kr/<agency>/<service>/<operation>`\n * - 인증: `serviceKey` 쿼리 파라미터 (Encoding/Decoding 두 형태 모두 수용)\n * - 포맷: `_type=json` 없으면 XML\n * - 에러: `<OpenAPI_ServiceResponse>` XML 또는 `response.header.resultCode !== '00'`\n *\n * 본 클라이언트는 서비스·오퍼레이션에 독립적으로 동작하며, 경로를 파라미터로 받는다.\n * 서비스별 도메인 로직(파라미터 검증, 응답 매핑) 은 task 레이어에서 처리.\n */\n\nconst DEFAULT_ORIGIN = 'https://apis.data.go.kr'\n\nexport interface DataGoKrClientOptions {\n serviceKey: string\n /** 오리진 오버라이드 (모의 서버/사설 프록시 용도). 기본 `https://apis.data.go.kr`. */\n origin?: string\n}\n\nexport class DataGoKrClient {\n private readonly serviceKey: string\n private readonly origin: string\n\n constructor(options: DataGoKrClientOptions) {\n if (!options.serviceKey) {\n throw new Error('DataGoKrClient requires serviceKey')\n }\n /* Encoding 키(%2B 포함)를 붙여넣어도 Decoding 키처럼 동작하도록 정규화.\n base64 키는 `%` 를 포함하지 않으므로 raw Decoding 키는 영향 없음. */\n this.serviceKey = normalizeServiceKey(options.serviceKey.trim())\n this.origin = (options.origin || DEFAULT_ORIGIN).replace(/\\/$/, '')\n }\n\n /**\n * 범용 GET 호출.\n *\n * @param servicePath `<agency>/<service>/<operation>` (예: `1613000/BldRgstService_v2/getBrTitleInfo`)\n * @param params 쿼리 파라미터 (serviceKey / _type 은 자동 추가)\n */\n async get<T>(servicePath: string, params: Record<string, any>): Promise<DataGoKrResponse<T>> {\n const path = servicePath.startsWith('/') ? servicePath : `/${servicePath}`\n const url = new URL(`${this.origin}${path}`)\n url.searchParams.set('serviceKey', this.serviceKey)\n url.searchParams.set('_type', 'json')\n for (const [k, v] of Object.entries(params)) {\n if (v === undefined || v === null || v === '') continue\n url.searchParams.set(k, String(v))\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers: {\n 'User-Agent': '@things-factory/integration-data-go-kr',\n Accept: 'application/json'\n }\n })\n const raw = await response.text()\n\n const nonSensitiveParams = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== null && v !== '')\n .map(([k, v]) => `${k}=${v}`)\n .join(' ')\n\n if (!response.ok) {\n throw new Error(\n `data.go.kr ${servicePath} failed (${response.status}): ${raw.slice(0, 300)} — params: ${nonSensitiveParams}`\n )\n }\n\n let parsed: DataGoKrResponse<T>\n try {\n parsed = JSON.parse(raw) as DataGoKrResponse<T>\n } catch (err) {\n if (raw.includes('<OpenAPI_ServiceResponse') || raw.includes('<returnReasonCode>')) {\n throw new Error(`data.go.kr ${servicePath}: ${parseOpenApiError(raw)} — params: ${nonSensitiveParams}`)\n }\n throw new Error(\n `data.go.kr ${servicePath}: non-JSON response: ${raw.slice(0, 300)} — params: ${nonSensitiveParams}`\n )\n }\n\n const header = parsed?.response?.header\n if (!header) {\n throw new Error(`data.go.kr ${servicePath}: response missing header — body: ${raw.slice(0, 300)}`)\n }\n if (header.resultCode !== '00') {\n throw new Error(\n `data.go.kr ${servicePath}: resultCode=${header.resultCode} msg=${header.resultMsg} — params: ${nonSensitiveParams}`\n )\n }\n\n return parsed\n }\n\n /**\n * 단건 또는 복수 items 를 배열로 정규화해서 반환한다.\n *\n * data.go.kr 공통 특성으로, body.items 가 아래 세 가지 형태로 올 수 있다:\n * - `\"\"` (빈 문자열, 결과 없음)\n * - `{ item: { ... } }` (단건)\n * - `{ item: [ ... ] }` (복수)\n */\n async getItems<T>(servicePath: string, params: Record<string, any>): Promise<T[]> {\n const response = await this.get<T>(servicePath, params)\n const items = response.response?.body?.items\n if (!items) return []\n const arr = (items as any).item\n if (!arr) return []\n return Array.isArray(arr) ? arr : [arr]\n }\n}\n\n/** Encoding 키(%2B) 를 붙여넣어도 Decoding 키로 정규화. */\nfunction normalizeServiceKey(key: string): string {\n if (!key.includes('%')) return key\n try {\n return decodeURIComponent(key)\n } catch {\n return key\n }\n}\n\n/** data.go.kr 공용 OpenAPI 에러 XML 에서 원인 추출. */\nfunction parseOpenApiError(xml: string): string {\n const code = /<returnReasonCode>([^<]+)<\\/returnReasonCode>/.exec(xml)?.[1]\n const msg = /<errMsg>([^<]+)<\\/errMsg>/.exec(xml)?.[1]\n const auth = /<returnAuthMsg>([^<]+)<\\/returnAuthMsg>/.exec(xml)?.[1]\n return `code=${code} msg=${msg} auth=${auth}`\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import { Connector } from '@things-factory/integration-base';
2
+ import { DataGoKrClient } from './data-go-kr-client';
3
+ /**
4
+ * 공공데이터포털(data.go.kr) Open API 커넥터.
5
+ *
6
+ * 하나의 ServiceKey 로 data.go.kr 산하 **모든 오퍼레이션** 을 호출할 수 있으므로,
7
+ * 사용자는 Connection 을 보통 한 개만 만들고 (앱·법인별로 1개) 여러 태스크에서 재사용한다.
8
+ *
9
+ * Connection 의 `endpoint` 필드는 무시된다. 오리진 오버라이드가 필요하면 `origin`
10
+ * 파라미터 사용 (모의 서버/사설 프록시).
11
+ */
12
+ export interface DataGoKrConnectionInstance {
13
+ client: DataGoKrClient;
14
+ }
15
+ export declare class DataGoKrConnector implements Connector {
16
+ ready(connectionConfigs: any): Promise<void>;
17
+ connect(connection: any): Promise<void>;
18
+ disconnect(connection: any): Promise<void>;
19
+ get parameterSpec(): ({
20
+ type: string;
21
+ name: string;
22
+ label: string;
23
+ useDomainAttribute: boolean;
24
+ placeholder?: undefined;
25
+ } | {
26
+ type: string;
27
+ name: string;
28
+ label: string;
29
+ placeholder: string;
30
+ useDomainAttribute?: undefined;
31
+ })[];
32
+ get taskPrefixes(): string[];
33
+ get help(): string;
34
+ get description(): string;
35
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataGoKrConnector = void 0;
4
+ const integration_base_1 = require("@things-factory/integration-base");
5
+ const data_go_kr_client_1 = require("./data-go-kr-client");
6
+ class DataGoKrConnector {
7
+ async ready(connectionConfigs) {
8
+ await Promise.all(connectionConfigs.map(this.connect.bind(this)));
9
+ integration_base_1.ConnectionManager.logger.info('data-go-kr-connector connections are ready');
10
+ }
11
+ async connect(connection) {
12
+ const { params } = connection;
13
+ try {
14
+ const client = new data_go_kr_client_1.DataGoKrClient({
15
+ serviceKey: params.serviceKey,
16
+ origin: params.origin
17
+ });
18
+ const instance = { client };
19
+ integration_base_1.ConnectionManager.addConnectionInstance(connection, instance);
20
+ integration_base_1.ConnectionManager.logger.info(`data-go-kr-connector connection(${connection.name}) is connected`);
21
+ }
22
+ catch (ex) {
23
+ integration_base_1.ConnectionManager.logger.error(`data-go-kr-connector connection(${connection.name}) failed`, ex);
24
+ throw ex;
25
+ }
26
+ }
27
+ async disconnect(connection) {
28
+ integration_base_1.ConnectionManager.removeConnectionInstance(connection);
29
+ integration_base_1.ConnectionManager.logger.info(`data-go-kr-connector connection(${connection.name}) is disconnected`);
30
+ }
31
+ get parameterSpec() {
32
+ return [
33
+ {
34
+ type: 'secret',
35
+ name: 'serviceKey',
36
+ label: 'label.service-key',
37
+ useDomainAttribute: true
38
+ },
39
+ {
40
+ type: 'string',
41
+ name: 'origin',
42
+ label: 'label.api-origin',
43
+ placeholder: 'https://apis.data.go.kr'
44
+ }
45
+ ];
46
+ }
47
+ get taskPrefixes() {
48
+ return ['data-go-kr'];
49
+ }
50
+ get help() {
51
+ return 'integration/connector/data-go-kr-connector';
52
+ }
53
+ get description() {
54
+ return 'Korean Public Data Portal (data.go.kr) Connector';
55
+ }
56
+ }
57
+ exports.DataGoKrConnector = DataGoKrConnector;
58
+ integration_base_1.ConnectionManager.registerConnector('data-go-kr-connector', new DataGoKrConnector());
59
+ //# sourceMappingURL=data-go-kr-connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-go-kr-connector.js","sourceRoot":"","sources":["../../../server/engine/connector/data-go-kr-connector.ts"],"names":[],"mappings":";;;AAAA,uEAA+E;AAE/E,2DAAoD;AAepD,MAAa,iBAAiB;IAC5B,KAAK,CAAC,KAAK,CAAC,iBAAiB;QAC3B,MAAM,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjE,oCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAA;IAC7E,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAU;QACtB,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAA;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,kCAAc,CAAC;gBAChC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;aACtB,CAAC,CAAA;YACF,MAAM,QAAQ,GAA+B,EAAE,MAAM,EAAE,CAAA;YACvD,oCAAiB,CAAC,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;YAC7D,oCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,UAAU,CAAC,IAAI,gBAAgB,CAAC,CAAA;QACnG,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,oCAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,UAAU,CAAC,IAAI,UAAU,EAAE,EAAE,CAAC,CAAA;YAChG,MAAM,EAAE,CAAA;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAU;QACzB,oCAAiB,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAA;QACtD,oCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,UAAU,CAAC,IAAI,mBAAmB,CAAC,CAAA;IACtG,CAAC;IAED,IAAI,aAAa;QACf,OAAO;YACL;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,mBAAmB;gBAC1B,kBAAkB,EAAE,IAAI;aACzB;YACD;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,kBAAkB;gBACzB,WAAW,EAAE,yBAAyB;aACvC;SACF,CAAA;IACH,CAAC;IAED,IAAI,YAAY;QACd,OAAO,CAAC,YAAY,CAAC,CAAA;IACvB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,4CAA4C,CAAA;IACrD,CAAC;IAED,IAAI,WAAW;QACb,OAAO,kDAAkD,CAAA;IAC3D,CAAC;CACF;AAvDD,8CAuDC;AAED,oCAAiB,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,IAAI,iBAAiB,EAAE,CAAC,CAAA","sourcesContent":["import { ConnectionManager, Connector } from '@things-factory/integration-base'\n\nimport { DataGoKrClient } from './data-go-kr-client'\n\n/**\n * 공공데이터포털(data.go.kr) Open API 커넥터.\n *\n * 하나의 ServiceKey 로 data.go.kr 산하 **모든 오퍼레이션** 을 호출할 수 있으므로,\n * 사용자는 Connection 을 보통 한 개만 만들고 (앱·법인별로 1개) 여러 태스크에서 재사용한다.\n *\n * Connection 의 `endpoint` 필드는 무시된다. 오리진 오버라이드가 필요하면 `origin`\n * 파라미터 사용 (모의 서버/사설 프록시).\n */\nexport interface DataGoKrConnectionInstance {\n client: DataGoKrClient\n}\n\nexport class DataGoKrConnector implements Connector {\n async ready(connectionConfigs) {\n await Promise.all(connectionConfigs.map(this.connect.bind(this)))\n ConnectionManager.logger.info('data-go-kr-connector connections are ready')\n }\n\n async connect(connection) {\n const { params } = connection\n try {\n const client = new DataGoKrClient({\n serviceKey: params.serviceKey,\n origin: params.origin\n })\n const instance: DataGoKrConnectionInstance = { client }\n ConnectionManager.addConnectionInstance(connection, instance)\n ConnectionManager.logger.info(`data-go-kr-connector connection(${connection.name}) is connected`)\n } catch (ex) {\n ConnectionManager.logger.error(`data-go-kr-connector connection(${connection.name}) failed`, ex)\n throw ex\n }\n }\n\n async disconnect(connection) {\n ConnectionManager.removeConnectionInstance(connection)\n ConnectionManager.logger.info(`data-go-kr-connector connection(${connection.name}) is disconnected`)\n }\n\n get parameterSpec() {\n return [\n {\n type: 'secret',\n name: 'serviceKey',\n label: 'label.service-key',\n useDomainAttribute: true\n },\n {\n type: 'string',\n name: 'origin',\n label: 'label.api-origin',\n placeholder: 'https://apis.data.go.kr'\n }\n ]\n }\n\n get taskPrefixes() {\n return ['data-go-kr']\n }\n\n get help() {\n return 'integration/connector/data-go-kr-connector'\n }\n\n get description() {\n return 'Korean Public Data Portal (data.go.kr) Connector'\n }\n}\n\nConnectionManager.registerConnector('data-go-kr-connector', new DataGoKrConnector())\n"]}
@@ -0,0 +1 @@
1
+ import './data-go-kr-connector';
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("./data-go-kr-connector");
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/connector/index.ts"],"names":[],"mappings":";;AAAA,kCAA+B","sourcesContent":["import './data-go-kr-connector'\n"]}
@@ -0,0 +1,2 @@
1
+ import './connector';
2
+ import './task';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("./connector");
4
+ require("./task");
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;AAAA,uBAAoB;AACpB,kBAAe","sourcesContent":["import './connector'\nimport './task'\n"]}
@@ -0,0 +1,9 @@
1
+ import { ServiceSpec } from './types';
2
+ /**
3
+ * 국토교통부_건축물대장정보 서비스 v2 (data.go.kr 데이터셋 15044713).
4
+ *
5
+ * 세움터(EAIS) DB 를 원천으로 하는 공공 건축물대장 Open API.
6
+ * 모든 오퍼레이션은 동일한 PNU(필지고유번호) 구성요소로 조회한다:
7
+ * - sigunguCd (5) + bjdongCd (5) + platGbCd (1) + bun (4) + ji (4)
8
+ */
9
+ export declare const BldRgstServiceV2: ServiceSpec;