@things-factory/integration-data-go-kr 10.0.0-beta.62 → 10.0.0-beta.67
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/README.md +37 -16
- package/ROADMAP.md +25 -14
- package/dist-server/engine/connector/data-go-kr-client.d.ts +1 -1
- package/dist-server/engine/connector/data-go-kr-client.js +25 -2
- package/dist-server/engine/connector/data-go-kr-client.js.map +1 -1
- package/dist-server/engine/connector/data-go-kr-connector.d.ts +5 -11
- package/dist-server/engine/connector/data-go-kr-connector.js +3 -9
- package/dist-server/engine/connector/data-go-kr-connector.js.map +1 -1
- package/dist-server/engine/spec/building-ledger/hub.d.ts +12 -0
- package/dist-server/engine/spec/{building-ledger.js → building-ledger/hub.js} +13 -10
- package/dist-server/engine/spec/building-ledger/hub.js.map +1 -0
- package/dist-server/engine/spec/building-ledger/index.d.ts +7 -0
- package/dist-server/engine/spec/building-ledger/index.js +12 -0
- package/dist-server/engine/spec/building-ledger/index.js.map +1 -0
- package/dist-server/engine/spec/index.d.ts +2 -1
- package/dist-server/engine/spec/index.js +22 -5
- package/dist-server/engine/spec/index.js.map +1 -1
- package/dist-server/engine/spec/types.d.ts +3 -3
- package/dist-server/engine/spec/types.js +1 -1
- package/dist-server/engine/spec/types.js.map +1 -1
- package/dist-server/engine/spec/weather/asos.d.ts +2 -0
- package/dist-server/engine/spec/weather/asos.js +33 -0
- package/dist-server/engine/spec/weather/asos.js.map +1 -0
- package/dist-server/engine/spec/weather/aws.d.ts +2 -0
- package/dist-server/engine/spec/weather/aws.js +28 -0
- package/dist-server/engine/spec/weather/aws.js.map +1 -0
- package/dist-server/engine/spec/weather/index.d.ts +14 -0
- package/dist-server/engine/spec/weather/index.js +23 -0
- package/dist-server/engine/spec/weather/index.js.map +1 -0
- package/dist-server/engine/spec/weather/mid-term-forecast.d.ts +2 -0
- package/dist-server/engine/spec/weather/mid-term-forecast.js +56 -0
- package/dist-server/engine/spec/weather/mid-term-forecast.js.map +1 -0
- package/dist-server/engine/spec/weather/short-term-forecast.d.ts +2 -0
- package/dist-server/engine/spec/weather/short-term-forecast.js +71 -0
- package/dist-server/engine/spec/weather/short-term-forecast.js.map +1 -0
- package/dist-server/engine/spec/weather/warning.d.ts +2 -0
- package/dist-server/engine/spec/weather/warning.js +34 -0
- package/dist-server/engine/spec/weather/warning.js.map +1 -0
- package/dist-server/engine/task/building-ledger/general.js +1 -1
- package/dist-server/engine/task/building-ledger/general.js.map +1 -1
- package/dist-server/engine/task/call.d.ts +10 -3
- package/dist-server/engine/task/call.js +20 -4
- package/dist-server/engine/task/call.js.map +1 -1
- package/dist-server/engine/task/index.d.ts +1 -0
- package/dist-server/engine/task/index.js +1 -0
- package/dist-server/engine/task/index.js.map +1 -1
- package/dist-server/engine/task/weather/grid-converter.d.ts +24 -0
- package/dist-server/engine/task/weather/grid-converter.js +69 -0
- package/dist-server/engine/task/weather/grid-converter.js.map +1 -0
- package/dist-server/engine/task/weather/index.d.ts +13 -0
- package/dist-server/engine/task/weather/index.js +18 -0
- package/dist-server/engine/task/weather/index.js.map +1 -0
- package/dist-server/engine/task/weather/short-term-forecast.d.ts +38 -0
- package/dist-server/engine/task/weather/short-term-forecast.js +99 -0
- package/dist-server/engine/task/weather/short-term-forecast.js.map +1 -0
- package/dist-server/index.d.ts +2 -0
- package/dist-server/index.js +4 -1
- package/dist-server/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/integration/connector/data-go-kr-connector.md +6 -7
- package/helps/integration/services/building-ledger.md +6 -5
- package/helps/integration/services/weather.md +82 -0
- package/helps/integration/task/building-ledger.md +25 -1
- package/helps/integration/task/data-go-kr-call.md +31 -4
- package/helps/integration/task/weather-short-term-forecast.md +96 -0
- package/package.json +3 -3
- package/server/engine/connector/data-go-kr-client.ts +26 -2
- package/server/engine/connector/data-go-kr-connector.ts +8 -11
- package/server/engine/spec/{building-ledger.ts → building-ledger/hub.ts} +12 -9
- package/server/engine/spec/building-ledger/index.ts +7 -0
- package/server/engine/spec/index.ts +24 -3
- package/server/engine/spec/types.ts +3 -3
- package/server/engine/spec/weather/asos.ts +32 -0
- package/server/engine/spec/weather/aws.ts +27 -0
- package/server/engine/spec/weather/index.ts +14 -0
- package/server/engine/spec/weather/mid-term-forecast.ts +56 -0
- package/server/engine/spec/weather/short-term-forecast.ts +73 -0
- package/server/engine/spec/weather/warning.ts +33 -0
- package/server/engine/task/building-ledger/general.ts +2 -2
- package/server/engine/task/call.ts +24 -4
- package/server/engine/task/index.ts +1 -0
- package/server/engine/task/weather/grid-converter.ts +79 -0
- package/server/engine/task/weather/index.ts +14 -0
- package/server/engine/task/weather/short-term-forecast.ts +110 -0
- package/server/index.ts +2 -0
- package/translations/en.json +9 -2
- package/translations/ja.json +9 -2
- package/translations/ko.json +9 -2
- package/translations/ms.json +9 -2
- package/translations/zh.json +9 -2
- package/dist-server/engine/spec/building-ledger.d.ts +0 -9
- package/dist-server/engine/spec/building-ledger.js.map +0 -1
package/README.md
CHANGED
|
@@ -20,10 +20,18 @@
|
|
|
20
20
|
|
|
21
21
|
### Tasks
|
|
22
22
|
- `data-go-kr-call` — 범용 오퍼레이션 호출 (스펙 기반 자동 검증)
|
|
23
|
-
- `data-go-kr-building-ledger` — 건축물대장 표제부 조회 (순수 fetch
|
|
23
|
+
- `data-go-kr-building-ledger` — 건축물대장 표제부 조회 (순수 fetch)
|
|
24
|
+
- `data-go-kr-weather-short-term-forecast` — 기상청 단기예보 조회 (위경도→격자 자동 변환)
|
|
24
25
|
|
|
25
26
|
### 서비스 스펙
|
|
26
|
-
-
|
|
27
|
+
- 건축물대장 도메인
|
|
28
|
+
- `1613000/BldRgstHubService` — 국토교통부 건축물대장 허브 서비스 (8 오퍼레이션)
|
|
29
|
+
- 기상청 도메인
|
|
30
|
+
- `1360000/VilageFcstInfoService_2.0` — 단기예보 (3 오퍼레이션)
|
|
31
|
+
- `1360000/MidFcstInfoService` — 중기예보 (4 오퍼레이션)
|
|
32
|
+
- `1360000/WthrWrnInfoService` — 기상특보 (2 오퍼레이션)
|
|
33
|
+
- `1360000/AsosHourlyInfoService` — 종관기상관측 시간자료 (1 오퍼레이션)
|
|
34
|
+
- `1360000/AwsHrInfoService` — 방재기상관측 시간자료 (1 오퍼레이션)
|
|
27
35
|
|
|
28
36
|
## 빠른 시작
|
|
29
37
|
|
|
@@ -38,28 +46,41 @@
|
|
|
38
46
|
|
|
39
47
|
## 확장 — 새 공공 API 추가
|
|
40
48
|
|
|
49
|
+
**확장성 우선 원칙: 도메인별 폴더 + 한 파일 = 한 서비스/태스크.**
|
|
50
|
+
|
|
41
51
|
```
|
|
42
52
|
server/engine/
|
|
43
|
-
├── spec/
|
|
44
|
-
│ ├── types.ts
|
|
45
|
-
│ ├── index.ts
|
|
46
|
-
│ ├── building-ledger
|
|
47
|
-
│
|
|
53
|
+
├── spec/ # 서비스 스펙 (도메인 = 폴더)
|
|
54
|
+
│ ├── types.ts # OperationSpec, ServiceSpec 정의
|
|
55
|
+
│ ├── index.ts # SpecRegistry (자동 수집·등록)
|
|
56
|
+
│ ├── building-ledger/
|
|
57
|
+
│ │ ├── index.ts
|
|
58
|
+
│ │ └── hub.ts # BldRgstHubService
|
|
59
|
+
│ └── weather/
|
|
60
|
+
│ ├── index.ts
|
|
61
|
+
│ ├── short-term-forecast.ts # 단기예보
|
|
62
|
+
│ ├── mid-term-forecast.ts # 중기예보
|
|
63
|
+
│ ├── warning.ts # 기상특보
|
|
64
|
+
│ ├── asos.ts # 종관기상관측
|
|
65
|
+
│ └── aws.ts # 방재기상관측
|
|
48
66
|
│
|
|
49
|
-
└── task/
|
|
50
|
-
├── index.ts
|
|
51
|
-
├── call.ts
|
|
52
|
-
├── building-ledger/
|
|
67
|
+
└── task/ # 태스크 (도메인 = 폴더)
|
|
68
|
+
├── index.ts # 전체 배럴
|
|
69
|
+
├── call.ts # data-go-kr-call (범용)
|
|
70
|
+
├── building-ledger/
|
|
53
71
|
│ ├── index.ts
|
|
54
|
-
│ └── general.ts
|
|
55
|
-
└──
|
|
72
|
+
│ └── general.ts # data-go-kr-building-ledger
|
|
73
|
+
└── weather/
|
|
56
74
|
├── index.ts
|
|
57
|
-
|
|
75
|
+
├── short-term-forecast.ts # data-go-kr-weather-short-term-forecast
|
|
76
|
+
└── grid-converter.ts # 위경도 ↔ KMA 격자 헬퍼 (export only)
|
|
58
77
|
```
|
|
59
78
|
|
|
60
79
|
**추가 우선순위**:
|
|
61
|
-
1. **공통 경로로 가능한지 먼저 검토** — `spec/<domain>.ts` 만 등록하면 `data-go-kr-call` 로 즉시 호출 가능
|
|
62
|
-
2. **공통 경로로 못 푸는 예외만 전용 태스크** — 입력
|
|
80
|
+
1. **공통 경로로 가능한지 먼저 검토** — `spec/<domain>/<service>.ts` 만 등록하면 `data-go-kr-call` 로 즉시 호출 가능
|
|
81
|
+
2. **공통 경로로 못 푸는 예외만 전용 태스크** — 입력 폼·헬퍼·도메인 가공이 필요한 경우 `task/<domain>/<variant>.ts` 추가
|
|
82
|
+
|
|
83
|
+
**새 도메인 추가**: `spec/<domain>/` 폴더 + `task/<domain>/` 폴더를 짝으로 만들고, 각 폴더의 `index.ts` 가 내부 파일을 import 하도록 작성. 최상위 `spec/index.ts` 는 도메인 폴더 import 한 줄만 추가하면 자동 등록.
|
|
63
84
|
|
|
64
85
|
자세한 단계별 절차는 [ROADMAP.md 의 "기여 가이드"](./ROADMAP.md#기여-가이드--새-서비스-추가-워크플로우) 참조.
|
|
65
86
|
|
package/ROADMAP.md
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
| 항목 | 상태 | 비고 |
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| 패키지 스켈레톤 (`@things-factory/integration-data-go-kr`) | ✅ | integration-weather/integration-openai 패턴 준수 |
|
|
12
|
-
| `DataGoKrConnector` — ServiceKey 관리 + Encoding/Decoding 자동 정규화 | ✅ | `
|
|
12
|
+
| `DataGoKrConnector` — ServiceKey 관리 + Encoding/Decoding 자동 정규화 | ✅ | Connection 의 `endpoint` 필드를 API 오리진으로 사용 (모의 서버 라우팅 가능) |
|
|
13
13
|
| `DataGoKrClient` — 범용 HTTP + User-Agent/Accept + URL 인코딩 이슈 방지 | ✅ | 단건/다건 자동 정규화(`getItems`) |
|
|
14
14
|
| `OperationSpec` / `ServiceSpec` 타입 + `SpecRegistry` | ✅ | 도움말 메타 포함 (description, example, responseNotes, externalDocsUrl) |
|
|
15
|
-
| 건축물대장
|
|
15
|
+
| 건축물대장 허브 서비스 (`1613000/BldRgstHubService`) 8 오퍼레이션 스펙 | ✅ | PNU 5요소 공통 파라미터 |
|
|
16
|
+
| 기상청 5개 서비스 스펙 + 단기예보 전용 태스크 + KMA 격자 변환 헬퍼 | ✅ | spec/weather/, task/weather/ 분할 (확장성 우선) |
|
|
16
17
|
| 범용 태스크 `data-go-kr-call` | ✅ | 스펙 기반 validation + zero-pad + default + enum |
|
|
17
18
|
| 도메인 전용 태스크 `data-go-kr-building-ledger` | ✅ | 표제부 조회 (순수 fetch; 집계·KPI 추출은 소비자 스텝에서 처리) |
|
|
18
19
|
| 5개 언어 번역 (ko/en/ja/ms/zh) | ✅ | label 기반 |
|
|
@@ -171,35 +172,45 @@ data.go.kr 은 500 "Unexpected errors" 가 간헐적으로 발생 (피크 타임
|
|
|
171
172
|
- 오퍼레이션 호출 전후에 도메인 가공 (파생 계산, 추가 호출 조합 등) 이 필요
|
|
172
173
|
- 여러 오퍼레이션을 묶은 매크로 호출
|
|
173
174
|
|
|
174
|
-
### 디렉토리 컨벤션
|
|
175
|
+
### 디렉토리 컨벤션 — 확장성 우선 (도메인=폴더, 한 파일=한 서비스/태스크)
|
|
175
176
|
|
|
176
177
|
```
|
|
177
178
|
server/engine/
|
|
178
|
-
├── spec/ # 서비스 스펙
|
|
179
|
+
├── spec/ # 서비스 스펙
|
|
179
180
|
│ ├── types.ts # OperationSpec, ServiceSpec 정의
|
|
180
|
-
│ ├── index.ts # SpecRegistry
|
|
181
|
-
│ ├── building-ledger
|
|
182
|
-
│
|
|
181
|
+
│ ├── index.ts # SpecRegistry (도메인 자동 수집·등록)
|
|
182
|
+
│ ├── building-ledger/
|
|
183
|
+
│ │ ├── index.ts
|
|
184
|
+
│ │ └── hub.ts # BldRgstHubService
|
|
185
|
+
│ └── weather/
|
|
186
|
+
│ ├── index.ts
|
|
187
|
+
│ ├── short-term-forecast.ts # 단기예보
|
|
188
|
+
│ ├── mid-term-forecast.ts
|
|
189
|
+
│ ├── warning.ts
|
|
190
|
+
│ ├── asos.ts
|
|
191
|
+
│ └── aws.ts
|
|
183
192
|
│
|
|
184
|
-
└── task/
|
|
193
|
+
└── task/
|
|
185
194
|
├── index.ts # 전체 배럴
|
|
186
195
|
├── call.ts # data-go-kr-call (범용)
|
|
187
|
-
├── building-ledger/
|
|
196
|
+
├── building-ledger/
|
|
188
197
|
│ ├── index.ts
|
|
189
|
-
│
|
|
190
|
-
|
|
191
|
-
└── (향후) property-trade/
|
|
198
|
+
│ └── general.ts # data-go-kr-building-ledger
|
|
199
|
+
└── weather/
|
|
192
200
|
├── index.ts
|
|
193
|
-
|
|
201
|
+
├── short-term-forecast.ts # data-go-kr-weather-short-term-forecast
|
|
202
|
+
└── grid-converter.ts # 위경도 ↔ 격자 헬퍼 (export)
|
|
194
203
|
```
|
|
195
204
|
|
|
205
|
+
새 서비스/태스크 추가 = **해당 도메인 폴더 안에 파일 한 개 + 폴더 index 한 줄.** 다른 도메인을 건드리지 않는다.
|
|
206
|
+
|
|
196
207
|
### 단계별 절차
|
|
197
208
|
|
|
198
209
|
**1. 데이터셋 선정**
|
|
199
210
|
- [data.go.kr](https://www.data.go.kr) 에서 상품 확인
|
|
200
211
|
- 앱에 구독 추가, ServiceKey 는 기존 Connection 재사용 가능
|
|
201
212
|
|
|
202
|
-
**2. 스펙 파일 작성** — `server/engine/spec/<domain>.ts`
|
|
213
|
+
**2. 스펙 파일 작성** — `server/engine/spec/<domain>/<service-slug>.ts`. 새 도메인이면 폴더 + `index.ts` 도 만들고 `spec/index.ts` 에 도메인 import 한 줄 추가
|
|
203
214
|
```ts
|
|
204
215
|
import { ServiceSpec } from './types'
|
|
205
216
|
|
|
@@ -11,7 +11,7 @@ export declare class DataGoKrClient {
|
|
|
11
11
|
/**
|
|
12
12
|
* 범용 GET 호출.
|
|
13
13
|
*
|
|
14
|
-
* @param servicePath `<agency>/<service>/<operation>` (예: `1613000/
|
|
14
|
+
* @param servicePath `<agency>/<service>/<operation>` (예: `1613000/BldRgstHubService/getBrTitleInfo`)
|
|
15
15
|
* @param params 쿼리 파라미터 (serviceKey / _type 은 자동 추가)
|
|
16
16
|
*/
|
|
17
17
|
get<T>(servicePath: string, params: Record<string, any>): Promise<DataGoKrResponse<T>>;
|
|
@@ -22,12 +22,12 @@ class DataGoKrClient {
|
|
|
22
22
|
/* Encoding 키(%2B 포함)를 붙여넣어도 Decoding 키처럼 동작하도록 정규화.
|
|
23
23
|
base64 키는 `%` 를 포함하지 않으므로 raw Decoding 키는 영향 없음. */
|
|
24
24
|
this.serviceKey = normalizeServiceKey(options.serviceKey.trim());
|
|
25
|
-
this.origin = (options.origin
|
|
25
|
+
this.origin = resolveOrigin(options.origin);
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* 범용 GET 호출.
|
|
29
29
|
*
|
|
30
|
-
* @param servicePath `<agency>/<service>/<operation>` (예: `1613000/
|
|
30
|
+
* @param servicePath `<agency>/<service>/<operation>` (예: `1613000/BldRgstHubService/getBrTitleInfo`)
|
|
31
31
|
* @param params 쿼리 파라미터 (serviceKey / _type 은 자동 추가)
|
|
32
32
|
*/
|
|
33
33
|
async get(servicePath, params) {
|
|
@@ -94,6 +94,29 @@ class DataGoKrClient {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
exports.DataGoKrClient = DataGoKrClient;
|
|
97
|
+
/**
|
|
98
|
+
* Connection.endpoint 값을 검증하여 유효한 origin URL 로 정규화한다.
|
|
99
|
+
*
|
|
100
|
+
* - 비어있거나 공백만: 기본 오리진 사용
|
|
101
|
+
* - 유효한 절대 URL: trailing slash 제거 후 사용
|
|
102
|
+
* - 유효하지 않은 값: 친절한 에러 throw (단순 오타·누락 방지)
|
|
103
|
+
*/
|
|
104
|
+
function resolveOrigin(value) {
|
|
105
|
+
if (!value || !value.trim())
|
|
106
|
+
return DEFAULT_ORIGIN;
|
|
107
|
+
const trimmed = value.trim();
|
|
108
|
+
try {
|
|
109
|
+
const parsed = new URL(trimmed);
|
|
110
|
+
if (!parsed.protocol.startsWith('http')) {
|
|
111
|
+
throw new Error('protocol must be http or https');
|
|
112
|
+
}
|
|
113
|
+
return trimmed.replace(/\/$/, '');
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
throw new Error(`Invalid Connection.endpoint value '${value}': must be a full URL (예: https://apis.data.go.kr) ` +
|
|
117
|
+
`or empty (기본값 ${DEFAULT_ORIGIN} 사용). Reason: ${err.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
97
120
|
/** Encoding 키(%2B) 를 붙여넣어도 Decoding 키로 정규화. */
|
|
98
121
|
function normalizeServiceKey(key) {
|
|
99
122
|
if (!key.includes('%'))
|
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"data-go-kr-client.js","sourceRoot":"","sources":["../../../server/engine/connector/data-go-kr-client.ts"],"names":[],"mappings":"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","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 = resolveOrigin(options.origin)\n }\n\n /**\n * 범용 GET 호출.\n *\n * @param servicePath `<agency>/<service>/<operation>` (예: `1613000/BldRgstHubService/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/**\n * Connection.endpoint 값을 검증하여 유효한 origin URL 로 정규화한다.\n *\n * - 비어있거나 공백만: 기본 오리진 사용\n * - 유효한 절대 URL: trailing slash 제거 후 사용\n * - 유효하지 않은 값: 친절한 에러 throw (단순 오타·누락 방지)\n */\nfunction resolveOrigin(value: string | undefined): string {\n if (!value || !value.trim()) return DEFAULT_ORIGIN\n const trimmed = value.trim()\n try {\n const parsed = new URL(trimmed)\n if (!parsed.protocol.startsWith('http')) {\n throw new Error('protocol must be http or https')\n }\n return trimmed.replace(/\\/$/, '')\n } catch (err) {\n throw new Error(\n `Invalid Connection.endpoint value '${value}': must be a full URL (예: https://apis.data.go.kr) ` +\n `or empty (기본값 ${DEFAULT_ORIGIN} 사용). Reason: ${(err as Error).message}`\n )\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"]}
|
|
@@ -6,8 +6,9 @@ import { DataGoKrClient } from './data-go-kr-client';
|
|
|
6
6
|
* 하나의 ServiceKey 로 data.go.kr 산하 **모든 오퍼레이션** 을 호출할 수 있으므로,
|
|
7
7
|
* 사용자는 Connection 을 보통 한 개만 만들고 (앱·법인별로 1개) 여러 태스크에서 재사용한다.
|
|
8
8
|
*
|
|
9
|
-
* Connection 의 `endpoint`
|
|
10
|
-
*
|
|
9
|
+
* Connection 의 `endpoint` 필드를 API 오리진(host) 으로 사용한다. 비워두면 기본값
|
|
10
|
+
* `https://apis.data.go.kr` 가 사용되며, 모의 서버/사설 프록시로 라우팅하려면
|
|
11
|
+
* 해당 오리진을 endpoint 에 입력한다.
|
|
11
12
|
*/
|
|
12
13
|
export interface DataGoKrConnectionInstance {
|
|
13
14
|
client: DataGoKrClient;
|
|
@@ -16,19 +17,12 @@ export declare class DataGoKrConnector implements Connector {
|
|
|
16
17
|
ready(connectionConfigs: any): Promise<void>;
|
|
17
18
|
connect(connection: any): Promise<void>;
|
|
18
19
|
disconnect(connection: any): Promise<void>;
|
|
19
|
-
get parameterSpec():
|
|
20
|
+
get parameterSpec(): {
|
|
20
21
|
type: string;
|
|
21
22
|
name: string;
|
|
22
23
|
label: string;
|
|
23
24
|
useDomainAttribute: boolean;
|
|
24
|
-
|
|
25
|
-
} | {
|
|
26
|
-
type: string;
|
|
27
|
-
name: string;
|
|
28
|
-
label: string;
|
|
29
|
-
placeholder: string;
|
|
30
|
-
useDomainAttribute?: undefined;
|
|
31
|
-
})[];
|
|
25
|
+
}[];
|
|
32
26
|
get taskPrefixes(): string[];
|
|
33
27
|
get help(): string;
|
|
34
28
|
get description(): string;
|
|
@@ -9,15 +9,15 @@ class DataGoKrConnector {
|
|
|
9
9
|
integration_base_1.ConnectionManager.logger.info('data-go-kr-connector connections are ready');
|
|
10
10
|
}
|
|
11
11
|
async connect(connection) {
|
|
12
|
-
const { params } = connection;
|
|
12
|
+
const { endpoint, params } = connection;
|
|
13
13
|
try {
|
|
14
14
|
const client = new data_go_kr_client_1.DataGoKrClient({
|
|
15
15
|
serviceKey: params.serviceKey,
|
|
16
|
-
origin:
|
|
16
|
+
origin: endpoint
|
|
17
17
|
});
|
|
18
18
|
const instance = { client };
|
|
19
19
|
integration_base_1.ConnectionManager.addConnectionInstance(connection, instance);
|
|
20
|
-
integration_base_1.ConnectionManager.logger.info(`data-go-kr-connector connection(${connection.name}) is connected`);
|
|
20
|
+
integration_base_1.ConnectionManager.logger.info(`data-go-kr-connector connection(${connection.name}) is connected (endpoint: ${endpoint || '(default)'})`);
|
|
21
21
|
}
|
|
22
22
|
catch (ex) {
|
|
23
23
|
integration_base_1.ConnectionManager.logger.error(`data-go-kr-connector connection(${connection.name}) failed`, ex);
|
|
@@ -35,12 +35,6 @@ class DataGoKrConnector {
|
|
|
35
35
|
name: 'serviceKey',
|
|
36
36
|
label: 'label.service-key',
|
|
37
37
|
useDomainAttribute: true
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: 'string',
|
|
41
|
-
name: 'origin',
|
|
42
|
-
label: 'label.api-origin',
|
|
43
|
-
placeholder: 'https://apis.data.go.kr'
|
|
44
38
|
}
|
|
45
39
|
];
|
|
46
40
|
}
|
|
@@ -1 +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;
|
|
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;AAgBpD,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,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,CAAA;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,kCAAc,CAAC;gBAChC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,MAAM,EAAE,QAAQ;aACjB,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,CAC3B,mCAAmC,UAAU,CAAC,IAAI,6BAA6B,QAAQ,IAAI,WAAW,GAAG,CAC1G,CAAA;QACH,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;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;AAnDD,8CAmDC;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` 필드를 API 오리진(host) 으로 사용한다. 비워두면 기본값\n * `https://apis.data.go.kr` 가 사용되며, 모의 서버/사설 프록시로 라우팅하려면\n * 해당 오리진을 endpoint 에 입력한다.\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 { endpoint, params } = connection\n try {\n const client = new DataGoKrClient({\n serviceKey: params.serviceKey,\n origin: endpoint\n })\n const instance: DataGoKrConnectionInstance = { client }\n ConnectionManager.addConnectionInstance(connection, instance)\n ConnectionManager.logger.info(\n `data-go-kr-connector connection(${connection.name}) is connected (endpoint: ${endpoint || '(default)'})`\n )\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 }\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,12 @@
|
|
|
1
|
+
import { ServiceSpec } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* 국토교통부_건축물대장 허브 서비스 (data.go.kr 데이터셋 15134735).
|
|
4
|
+
*
|
|
5
|
+
* 세움터(EAIS) DB 를 원천으로 하는 공공 건축물대장 통합 Hub Open API.
|
|
6
|
+
* 모든 오퍼레이션은 동일한 PNU(필지고유번호) 구성요소로 조회한다:
|
|
7
|
+
* - sigunguCd (5) + bjdongCd (5) + platGbCd (1) + bun (4) + ji (4)
|
|
8
|
+
*
|
|
9
|
+
* 구버전 `BldRgstService_v2` (`1613000/BldRgstService_v2/`) 는 본 허브 서비스로
|
|
10
|
+
* 사실상 통합·승격되었다. 신규 사용자는 허브 서비스 활용신청을 권장.
|
|
11
|
+
*/
|
|
12
|
+
export declare const BldRgstHubService: ServiceSpec;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.BldRgstHubService = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* PNU 5요소 파라미터 스펙 —
|
|
5
|
+
* PNU 5요소 파라미터 스펙 — BldRgstHubService 의 모든 오퍼레이션이 공유.
|
|
6
6
|
* 별도 배열 분리로 작성해두면 타 서비스(예: 건축물대장 허브) 도 재사용 가능.
|
|
7
7
|
*/
|
|
8
8
|
const pnuParams = [
|
|
@@ -53,17 +53,20 @@ const pnuParams = [
|
|
|
53
53
|
}
|
|
54
54
|
];
|
|
55
55
|
/**
|
|
56
|
-
* 국토교통부_
|
|
56
|
+
* 국토교통부_건축물대장 허브 서비스 (data.go.kr 데이터셋 15134735).
|
|
57
57
|
*
|
|
58
|
-
* 세움터(EAIS) DB 를 원천으로 하는 공공 건축물대장 Open API.
|
|
58
|
+
* 세움터(EAIS) DB 를 원천으로 하는 공공 건축물대장 통합 Hub Open API.
|
|
59
59
|
* 모든 오퍼레이션은 동일한 PNU(필지고유번호) 구성요소로 조회한다:
|
|
60
60
|
* - sigunguCd (5) + bjdongCd (5) + platGbCd (1) + bun (4) + ji (4)
|
|
61
|
+
*
|
|
62
|
+
* 구버전 `BldRgstService_v2` (`1613000/BldRgstService_v2/`) 는 본 허브 서비스로
|
|
63
|
+
* 사실상 통합·승격되었다. 신규 사용자는 허브 서비스 활용신청을 권장.
|
|
61
64
|
*/
|
|
62
|
-
exports.
|
|
63
|
-
serviceId: '1613000/
|
|
64
|
-
label: '국토교통부_
|
|
65
|
+
exports.BldRgstHubService = {
|
|
66
|
+
serviceId: '1613000/BldRgstHubService',
|
|
67
|
+
label: '국토교통부_건축물대장 허브 서비스',
|
|
65
68
|
description: '세움터(EAIS) 원천의 건축물대장 정보를 조회한다. 표제부·총괄표제부·층별개요·부속지번·전유공용면적·주택가격·소유자현황·기본개요 등 8개 오퍼레이션 제공.',
|
|
66
|
-
homepage: 'https://www.data.go.kr/data/
|
|
69
|
+
homepage: 'https://www.data.go.kr/data/15134735/openapi.do',
|
|
67
70
|
operations: {
|
|
68
71
|
getBrTitleInfo: {
|
|
69
72
|
operationId: 'getBrTitleInfo',
|
|
@@ -71,7 +74,7 @@ exports.BldRgstServiceV2 = {
|
|
|
71
74
|
description: '건축물대장 표제부 (건물 본문) 를 조회한다. 연면적·용적률·지상층수·지하층수·주구조·주용도 등 건물 개요를 반환. 한 필지에 동이 여러 개이면 복수 레코드로 내려온다.',
|
|
72
75
|
params: [...pnuParams],
|
|
73
76
|
responseNotes: '응답 `response.body.items.item` 이 배열 또는 단일 객체로 올 수 있음. 모든 숫자 필드가 문자열(`"114000.00"`)로 내려옴. 집합건축물은 `regstrKindCd=3`, 일반건축물은 `regstrKindCd=2`.',
|
|
74
|
-
externalDocsUrl: 'https://www.data.go.kr/data/
|
|
77
|
+
externalDocsUrl: 'https://www.data.go.kr/data/15134735/openapi.do',
|
|
75
78
|
examples: [
|
|
76
79
|
{
|
|
77
80
|
label: '서울 강남구 역삼동 823',
|
|
@@ -132,4 +135,4 @@ exports.BldRgstServiceV2 = {
|
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
};
|
|
135
|
-
//# sourceMappingURL=
|
|
138
|
+
//# sourceMappingURL=hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub.js","sourceRoot":"","sources":["../../../../server/engine/spec/building-ledger/hub.ts"],"names":[],"mappings":"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","sourcesContent":["import { OperationParamSpec, ServiceSpec } from '../types'\n\n/**\n * PNU 5요소 파라미터 스펙 — BldRgstHubService 의 모든 오퍼레이션이 공유.\n * 별도 배열 분리로 작성해두면 타 서비스(예: 건축물대장 허브) 도 재사용 가능.\n */\nconst pnuParams: OperationParamSpec[] = [\n {\n name: 'sigunguCd',\n label: 'label.sigungu-cd',\n required: true,\n length: 5,\n description: '시군구코드 5자리 (법정동코드 10자리의 앞 5자리).',\n example: '11680'\n },\n {\n name: 'bjdongCd',\n label: 'label.bjdong-cd',\n required: true,\n length: 5,\n description: '법정동코드 5자리 (법정동코드 10자리의 뒤 5자리).',\n example: '10300'\n },\n {\n name: 'platGbCd',\n label: 'label.plat-gb-cd',\n default: '0',\n length: 1,\n description: '대지구분 1자리. `0` 대지 / `1` 산 / `2` 블록.',\n example: '0',\n enum: [\n { value: '0', label: '대지' },\n { value: '1', label: '산' },\n { value: '2', label: '블록' }\n ]\n },\n {\n name: 'bun',\n label: 'label.bun',\n required: true,\n pad: 4,\n description: '본번. 자동으로 4자리 zero-pad 됨 (예: `6` → `0006`). 하이픈 포함 지번은 본번/부번을 각각 입력.',\n example: '223'\n },\n {\n name: 'ji',\n label: 'label.ji',\n default: '0',\n pad: 4,\n description: '부번. 없으면 `0`. 자동 4자리 zero-pad.',\n example: '0'\n }\n]\n\n/**\n * 국토교통부_건축물대장 허브 서비스 (data.go.kr 데이터셋 15134735).\n *\n * 세움터(EAIS) DB 를 원천으로 하는 공공 건축물대장 통합 Hub Open API.\n * 모든 오퍼레이션은 동일한 PNU(필지고유번호) 구성요소로 조회한다:\n * - sigunguCd (5) + bjdongCd (5) + platGbCd (1) + bun (4) + ji (4)\n *\n * 구버전 `BldRgstService_v2` (`1613000/BldRgstService_v2/`) 는 본 허브 서비스로\n * 사실상 통합·승격되었다. 신규 사용자는 허브 서비스 활용신청을 권장.\n */\nexport const BldRgstHubService: ServiceSpec = {\n serviceId: '1613000/BldRgstHubService',\n label: '국토교통부_건축물대장 허브 서비스',\n description:\n '세움터(EAIS) 원천의 건축물대장 정보를 조회한다. 표제부·총괄표제부·층별개요·부속지번·전유공용면적·주택가격·소유자현황·기본개요 등 8개 오퍼레이션 제공.',\n homepage: 'https://www.data.go.kr/data/15134735/openapi.do',\n operations: {\n getBrTitleInfo: {\n operationId: 'getBrTitleInfo',\n label: '표제부 조회',\n description:\n '건축물대장 표제부 (건물 본문) 를 조회한다. 연면적·용적률·지상층수·지하층수·주구조·주용도 등 건물 개요를 반환. 한 필지에 동이 여러 개이면 복수 레코드로 내려온다.',\n params: [...pnuParams],\n responseNotes:\n '응답 `response.body.items.item` 이 배열 또는 단일 객체로 올 수 있음. 모든 숫자 필드가 문자열(`\"114000.00\"`)로 내려옴. 집합건축물은 `regstrKindCd=3`, 일반건축물은 `regstrKindCd=2`.',\n externalDocsUrl: 'https://www.data.go.kr/data/15134735/openapi.do',\n examples: [\n {\n label: '서울 강남구 역삼동 823',\n params: { sigunguCd: '11680', bjdongCd: '10300', bun: '823', ji: '0' }\n }\n ]\n },\n getBrRecapTitleInfo: {\n operationId: 'getBrRecapTitleInfo',\n label: '총괄표제부 조회',\n description:\n '집합건축물(아파트 단지 등) 의 총괄표제부를 조회한다. 단지 전체 연면적·대지면적·동 수·세대수 등을 반환. 일반건축물에는 없음.',\n params: [...pnuParams],\n responseNotes: '일반건축물대장(단동) 의 경우 레코드가 없음. 집합건축물일 때만 유효.',\n examples: [\n {\n label: '아파트 단지 (예시)',\n params: { sigunguCd: '11680', bjdongCd: '10300', bun: '823', ji: '0' }\n }\n ]\n },\n getBrFlrOulnInfo: {\n operationId: 'getBrFlrOulnInfo',\n label: '층별개요 조회',\n description:\n '층별로 주용도·구조·면적을 조회. 지하 N층부터 지상 M층까지 각 층의 상세 구성을 반환. `regstrKindCd`, `regstrGbCd` 로 어느 대장의 층인지 구분.',\n params: [...pnuParams],\n responseNotes: '한 필지에 동이 여러 개이면 각 동의 각 층이 모두 나옴 → 결과 건수가 많을 수 있음.'\n },\n getBrExposPubuseAreaInfo: {\n operationId: 'getBrExposPubuseAreaInfo',\n label: '전유공용면적 조회',\n description:\n '집합건축물의 호(세대) 별 전유면적·공용면적을 조회. 아파트 세대별 실제 면적 산출에 사용.',\n params: [...pnuParams],\n responseNotes: '집합건축물일 때만 레코드 존재. 일반건축물에는 해당 없음.'\n },\n getBrAtchJibunInfo: {\n operationId: 'getBrAtchJibunInfo',\n label: '부속지번 조회',\n description: '대장에 연결된 부속지번(인접 필지 등) 목록을 조회.',\n params: [...pnuParams]\n },\n getBrHsprcInfo: {\n operationId: 'getBrHsprcInfo',\n label: '주택가격 조회',\n description: '공동주택/단독주택 공시가격 이력을 조회. 연도별 개별주택가격·공동주택가격 제공.',\n params: [...pnuParams]\n },\n getBrBasisOulnInfo: {\n operationId: 'getBrBasisOulnInfo',\n label: '기본개요 조회',\n description: '대장의 기본개요(대장 구분, 대장 종류, 변동일, 변동원인) 를 조회. 변동 이력 추적 용도.',\n params: [...pnuParams]\n },\n getBrExposInfo: {\n operationId: 'getBrExposInfo',\n label: '전유부 조회',\n description: '집합건축물의 호(세대) 목록과 호별 개요를 조회. 전유공용면적보다 상위 요약 수준.',\n params: [...pnuParams]\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BldRgstHubService = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 건축물대장 도메인 서비스 스펙 묶음.
|
|
6
|
+
*
|
|
7
|
+
* 새 변종(예: BldRgstService_v2 호환 유지, 멸실대장 서비스 등) 추가 시
|
|
8
|
+
* 이 폴더 안에 새 파일을 만들고 본 index 에 export + 아래로 SpecRegistry 에 등록.
|
|
9
|
+
*/
|
|
10
|
+
var hub_1 = require("./hub");
|
|
11
|
+
Object.defineProperty(exports, "BldRgstHubService", { enumerable: true, get: function () { return hub_1.BldRgstHubService; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/engine/spec/building-ledger/index.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,6BAAyC;AAAhC,wGAAA,iBAAiB,OAAA","sourcesContent":["/**\n * 건축물대장 도메인 서비스 스펙 묶음.\n *\n * 새 변종(예: BldRgstService_v2 호환 유지, 멸실대장 서비스 등) 추가 시\n * 이 폴더 안에 새 파일을 만들고 본 index 에 export + 아래로 SpecRegistry 에 등록.\n */\nexport { BldRgstHubService } from './hub'\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OperationSpec, ServiceSpec } from './types';
|
|
2
|
-
export { BldRgstServiceV2 } from './building-ledger';
|
|
3
2
|
export * from './types';
|
|
3
|
+
export * from './building-ledger';
|
|
4
|
+
export * from './weather';
|
|
4
5
|
export declare const SpecRegistry: {
|
|
5
6
|
/** 등록된 모든 서비스 스펙을 반환. */
|
|
6
7
|
listServices(): ServiceSpec[];
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SpecRegistry =
|
|
3
|
+
exports.SpecRegistry = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/* 도메인별 서비스 스펙 — 새 도메인 추가 시 폴더 추가 + 본 import 한 줄 */
|
|
7
|
+
const buildingLedger = tslib_1.__importStar(require("./building-ledger"));
|
|
8
|
+
const weather = tslib_1.__importStar(require("./weather"));
|
|
9
9
|
tslib_1.__exportStar(require("./types"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./building-ledger"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./weather"), exports);
|
|
10
12
|
const services = new Map();
|
|
11
13
|
function registerService(spec) {
|
|
12
14
|
services.set(spec.serviceId, spec);
|
|
13
15
|
}
|
|
14
|
-
|
|
16
|
+
/* 도메인 모듈에서 export 된 모든 ServiceSpec 인스턴스를 자동 등록.
|
|
17
|
+
추가 도메인 import 만 늘리면 이하 코드는 그대로. */
|
|
18
|
+
function registerDomain(domain) {
|
|
19
|
+
for (const value of Object.values(domain)) {
|
|
20
|
+
if (isServiceSpec(value))
|
|
21
|
+
registerService(value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isServiceSpec(value) {
|
|
25
|
+
return (typeof value === 'object' &&
|
|
26
|
+
value !== null &&
|
|
27
|
+
typeof value.serviceId === 'string' &&
|
|
28
|
+
typeof value.operations === 'object');
|
|
29
|
+
}
|
|
30
|
+
registerDomain(buildingLedger);
|
|
31
|
+
registerDomain(weather);
|
|
15
32
|
exports.SpecRegistry = {
|
|
16
33
|
/** 등록된 모든 서비스 스펙을 반환. */
|
|
17
34
|
listServices() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/spec/index.ts"],"names":[],"mappings":";;;;AAAA,mCAAuE;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/spec/index.ts"],"names":[],"mappings":";;;;AAAA,mCAAuE;AAEvE,mDAAmD;AACnD,0EAAmD;AACnD,2DAAoC;AAEpC,kDAAuB;AACvB,4DAAiC;AACjC,oDAAyB;AAEzB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAA;AAE/C,SAAS,eAAe,CAAC,IAAiB;IACxC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AACpC,CAAC;AAED;qCACqC;AACrC,SAAS,cAAc,CAAC,MAA+B;IACrD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IAClD,CAAC;AACH,CAAC;AACD,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAQ,KAAa,CAAC,SAAS,KAAK,QAAQ;QAC5C,OAAQ,KAAa,CAAC,UAAU,KAAK,QAAQ,CAC9C,CAAA;AACH,CAAC;AAED,cAAc,CAAC,cAAc,CAAC,CAAA;AAC9B,cAAc,CAAC,OAAO,CAAC,CAAA;AAEV,QAAA,YAAY,GAAG;IAC1B,yBAAyB;IACzB,YAAY;QACV,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACtC,CAAC;IAED,0BAA0B;IAC1B,UAAU,CAAC,SAAiB;QAC1B,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IAChC,CAAC;IAED,uDAAuD;IACvD,OAAO,CAAC,YAAoB;QAC1B,MAAM,KAAK,GAAG,IAAA,yBAAiB,EAAC,YAAY,CAAC,CAAA;QAC7C,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAA;QAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;QACvD,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAA;QAChC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAA;IAC/B,CAAC;IAED,gCAAgC;IAChC,QAAQ,CAAC,IAAiB;QACxB,eAAe,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC;CACF,CAAA","sourcesContent":["import { OperationSpec, ServiceSpec, parseOperationRef } from './types'\n\n/* 도메인별 서비스 스펙 — 새 도메인 추가 시 폴더 추가 + 본 import 한 줄 */\nimport * as buildingLedger from './building-ledger'\nimport * as weather from './weather'\n\nexport * from './types'\nexport * from './building-ledger'\nexport * from './weather'\n\nconst services = new Map<string, ServiceSpec>()\n\nfunction registerService(spec: ServiceSpec) {\n services.set(spec.serviceId, spec)\n}\n\n/* 도메인 모듈에서 export 된 모든 ServiceSpec 인스턴스를 자동 등록.\n 추가 도메인 import 만 늘리면 이하 코드는 그대로. */\nfunction registerDomain(domain: Record<string, unknown>) {\n for (const value of Object.values(domain)) {\n if (isServiceSpec(value)) registerService(value)\n }\n}\nfunction isServiceSpec(value: unknown): value is ServiceSpec {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as any).serviceId === 'string' &&\n typeof (value as any).operations === 'object'\n )\n}\n\nregisterDomain(buildingLedger)\nregisterDomain(weather)\n\nexport const SpecRegistry = {\n /** 등록된 모든 서비스 스펙을 반환. */\n listServices(): ServiceSpec[] {\n return Array.from(services.values())\n },\n\n /** 서비스 ID 로 서비스 스펙 조회. */\n getService(serviceId: string): ServiceSpec | undefined {\n return services.get(serviceId)\n },\n\n /** `<serviceId>.<operationId>` 참조 문자열로 오퍼레이션 스펙 조회. */\n resolve(operationRef: string): { service: ServiceSpec; operation: OperationSpec } | undefined {\n const parts = parseOperationRef(operationRef)\n if (!parts) return undefined\n const service = services.get(parts.serviceId)\n if (!service) return undefined\n const operation = service.operations[parts.operationId]\n if (!operation) return undefined\n return { service, operation }\n },\n\n /** (확장용) 외부에서 서비스 스펙을 추가 등록. */\n register(spec: ServiceSpec) {\n registerService(spec)\n }\n}\n"]}
|
|
@@ -56,9 +56,9 @@ export interface OperationSpec {
|
|
|
56
56
|
}
|
|
57
57
|
/** 서비스 스펙 (오퍼레이션 묶음). */
|
|
58
58
|
export interface ServiceSpec {
|
|
59
|
-
/** 서비스 경로 (예: `1613000/
|
|
59
|
+
/** 서비스 경로 (예: `1613000/BldRgstHubService`). */
|
|
60
60
|
serviceId: string;
|
|
61
|
-
/** 화면 라벨 (예: '국토교통부_
|
|
61
|
+
/** 화면 라벨 (예: '국토교통부_건축물대장 허브 서비스'). */
|
|
62
62
|
label: string;
|
|
63
63
|
/** 사람이 읽는 설명. */
|
|
64
64
|
description: string;
|
|
@@ -71,7 +71,7 @@ export interface ServiceSpec {
|
|
|
71
71
|
* 오퍼레이션 참조 문자열 파서.
|
|
72
72
|
*
|
|
73
73
|
* 레지스트리 조회 키: `"<serviceId>.<operationId>"` — 점으로 구분.
|
|
74
|
-
* 예: `"1613000/
|
|
74
|
+
* 예: `"1613000/BldRgstHubService.getBrTitleInfo"`
|
|
75
75
|
*/
|
|
76
76
|
export declare function parseOperationRef(ref: string): {
|
|
77
77
|
serviceId: string;
|
|
@@ -16,7 +16,7 @@ exports.parseOperationRef = parseOperationRef;
|
|
|
16
16
|
* 오퍼레이션 참조 문자열 파서.
|
|
17
17
|
*
|
|
18
18
|
* 레지스트리 조회 키: `"<serviceId>.<operationId>"` — 점으로 구분.
|
|
19
|
-
* 예: `"1613000/
|
|
19
|
+
* 예: `"1613000/BldRgstHubService.getBrTitleInfo"`
|
|
20
20
|
*/
|
|
21
21
|
function parseOperationRef(ref) {
|
|
22
22
|
const idx = ref.lastIndexOf('.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../server/engine/spec/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAkEH,8CAOC;AAbD;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,GAAW;IAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;QAChC,WAAW,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;KACpC,CAAA;AACH,CAAC","sourcesContent":["/**\n * 공공데이터포털(data.go.kr) Open API 오퍼레이션 스펙 타입.\n *\n * \"선언적 레지스트리 + 단일 범용 태스크\" 패턴의 핵심.\n *\n * - 런타임에는 `data-go-kr-call` 태스크가 이 스펙으로 파라미터 검증·정규화\n * - 빌드/CI 에서는 이 스펙으로부터 서비스 카탈로그 markdown 을 자동 생성 가능\n * - (장기) 통합 UI 가 이 스펙을 읽어 오퍼레이션 선택 시 **동적 폼 + 인라인 도움말** 을 렌더\n *\n * 즉 스펙 하나가 검증·문서·UI 3가지의 진실의 원천(single source of truth) 이다.\n */\n\n/** 단일 파라미터 스펙 (도움말용 메타 포함). */\nexport interface OperationParamSpec {\n /** 쿼리 파라미터 이름 (예: `sigunguCd`). */\n name: string\n /** 화면 라벨 키 (i18n). 생략 시 `name` 사용. */\n label?: string\n /** 필수 여부. */\n required?: boolean\n /** 기본값 (입력 생략 시 적용). */\n default?: string\n /** zero-pad 길이. 예: `bun=6` + pad=4 → `\"0006\"`. */\n pad?: number\n /** 정확히 이 길이여야 함. 위반 시 태스크가 ValidationError 던짐. */\n length?: number\n /** 사람이 읽는 파라미터 설명 (도움말·UI 툴팁). */\n description: string\n /** 예시 값. */\n example?: string | number\n /** enum 선택지. 제공 시 태스크가 해당 값만 허용. */\n enum?: Array<{ value: string; label: string }>\n}\n\n/** 오퍼레이션(엔드포인트) 스펙. */\nexport interface OperationSpec {\n /** 오퍼레이션 경로명 (예: `getBrTitleInfo`). */\n operationId: string\n /** 화면 라벨 (예: '표제부 조회'). */\n label: string\n /** 사람이 읽는 설명 — 이 오퍼레이션이 무엇을 돌려주는지. */\n description: string\n /** 파라미터 목록 (검증 + 문서). */\n params: OperationParamSpec[]\n /** 응답 구조 주의사항 (예: 다동 필지는 items 복수, 숫자는 문자열 등). */\n responseNotes?: string\n /** data.go.kr 원문 상세 페이지 URL. */\n externalDocsUrl?: string\n /** 자주 쓰는 예시 호출. */\n examples?: Array<{\n label: string\n params: Record<string, any>\n comment?: string\n }>\n}\n\n/** 서비스 스펙 (오퍼레이션 묶음). */\nexport interface ServiceSpec {\n /** 서비스 경로 (예: `1613000/
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../server/engine/spec/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAkEH,8CAOC;AAbD;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,GAAW;IAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;QAChC,WAAW,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;KACpC,CAAA;AACH,CAAC","sourcesContent":["/**\n * 공공데이터포털(data.go.kr) Open API 오퍼레이션 스펙 타입.\n *\n * \"선언적 레지스트리 + 단일 범용 태스크\" 패턴의 핵심.\n *\n * - 런타임에는 `data-go-kr-call` 태스크가 이 스펙으로 파라미터 검증·정규화\n * - 빌드/CI 에서는 이 스펙으로부터 서비스 카탈로그 markdown 을 자동 생성 가능\n * - (장기) 통합 UI 가 이 스펙을 읽어 오퍼레이션 선택 시 **동적 폼 + 인라인 도움말** 을 렌더\n *\n * 즉 스펙 하나가 검증·문서·UI 3가지의 진실의 원천(single source of truth) 이다.\n */\n\n/** 단일 파라미터 스펙 (도움말용 메타 포함). */\nexport interface OperationParamSpec {\n /** 쿼리 파라미터 이름 (예: `sigunguCd`). */\n name: string\n /** 화면 라벨 키 (i18n). 생략 시 `name` 사용. */\n label?: string\n /** 필수 여부. */\n required?: boolean\n /** 기본값 (입력 생략 시 적용). */\n default?: string\n /** zero-pad 길이. 예: `bun=6` + pad=4 → `\"0006\"`. */\n pad?: number\n /** 정확히 이 길이여야 함. 위반 시 태스크가 ValidationError 던짐. */\n length?: number\n /** 사람이 읽는 파라미터 설명 (도움말·UI 툴팁). */\n description: string\n /** 예시 값. */\n example?: string | number\n /** enum 선택지. 제공 시 태스크가 해당 값만 허용. */\n enum?: Array<{ value: string; label: string }>\n}\n\n/** 오퍼레이션(엔드포인트) 스펙. */\nexport interface OperationSpec {\n /** 오퍼레이션 경로명 (예: `getBrTitleInfo`). */\n operationId: string\n /** 화면 라벨 (예: '표제부 조회'). */\n label: string\n /** 사람이 읽는 설명 — 이 오퍼레이션이 무엇을 돌려주는지. */\n description: string\n /** 파라미터 목록 (검증 + 문서). */\n params: OperationParamSpec[]\n /** 응답 구조 주의사항 (예: 다동 필지는 items 복수, 숫자는 문자열 등). */\n responseNotes?: string\n /** data.go.kr 원문 상세 페이지 URL. */\n externalDocsUrl?: string\n /** 자주 쓰는 예시 호출. */\n examples?: Array<{\n label: string\n params: Record<string, any>\n comment?: string\n }>\n}\n\n/** 서비스 스펙 (오퍼레이션 묶음). */\nexport interface ServiceSpec {\n /** 서비스 경로 (예: `1613000/BldRgstHubService`). */\n serviceId: string\n /** 화면 라벨 (예: '국토교통부_건축물대장 허브 서비스'). */\n label: string\n /** 사람이 읽는 설명. */\n description: string\n /** data.go.kr 활용신청 페이지 URL. */\n homepage?: string\n /** 오퍼레이션 맵 (operationId → spec). */\n operations: Record<string, OperationSpec>\n}\n\n/**\n * 오퍼레이션 참조 문자열 파서.\n *\n * 레지스트리 조회 키: `\"<serviceId>.<operationId>\"` — 점으로 구분.\n * 예: `\"1613000/BldRgstHubService.getBrTitleInfo\"`\n */\nexport function parseOperationRef(ref: string): { serviceId: string; operationId: string } | null {\n const idx = ref.lastIndexOf('.')\n if (idx < 0) return null\n return {\n serviceId: ref.substring(0, idx),\n operationId: ref.substring(idx + 1)\n }\n}\n"]}
|