@things-factory/integration-data-go-kr 10.1.165 → 10.1.170
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
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
- **선언적 스펙 레지스트리** 가 파라미터 검증·문서·(장기) UI 도움말의 단일 원천
|
|
12
12
|
- **자주 쓰이는 도메인 전용 태스크** 만 별도 등록 (예: `data-go-kr-building-ledger`)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
이 구조는 TaskRegistry에 개별 태스크를 반복 등록하는 부담을 줄인다. 새 서비스는 스펙 파일을 추가하여 연결할 수 있다.
|
|
15
15
|
|
|
16
16
|
## 제공 기능 (Phase 0)
|
|
17
17
|
|
|
@@ -4,7 +4,7 @@ import { DataGoKrResponse } from '../types';
|
|
|
4
4
|
* 범용 공공데이터포털 호출 태스크.
|
|
5
5
|
*
|
|
6
6
|
* 하나의 태스크가 등록된 레지스트리의 **모든 오퍼레이션** 을 커버한다. TaskRegistry 가
|
|
7
|
-
*
|
|
7
|
+
* 개별 태스크 등록 수가 과도하게 증가하는 것을 방지하는 설계.
|
|
8
8
|
*
|
|
9
9
|
* 입력:
|
|
10
10
|
* - `operationRef` : `"<serviceId>.<operationId>"` 형식 (예: `"1613000/BldRgstHubService.getBrTitleInfo"`)
|
|
@@ -6,7 +6,7 @@ const spec_1 = require("../spec");
|
|
|
6
6
|
* 범용 공공데이터포털 호출 태스크.
|
|
7
7
|
*
|
|
8
8
|
* 하나의 태스크가 등록된 레지스트리의 **모든 오퍼레이션** 을 커버한다. TaskRegistry 가
|
|
9
|
-
*
|
|
9
|
+
* 개별 태스크 등록 수가 과도하게 증가하는 것을 방지하는 설계.
|
|
10
10
|
*
|
|
11
11
|
* 입력:
|
|
12
12
|
* - `operationRef` : `"<serviceId>.<operationId>"` 형식 (예: `"1613000/BldRgstHubService.getBrTitleInfo"`)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call.js","sourceRoot":"","sources":["../../../server/engine/task/call.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConnectionManager, Context, TaskRegistry, evaluateTemplate } from '@things-factory/integration-base'\n\nimport { DataGoKrConnectionInstance } from '../connector/data-go-kr-connector'\nimport { DataGoKrResponse } from '../types'\nimport { OperationSpec, SpecRegistry } from '../spec'\n\n/**\n * 범용 공공데이터포털 호출 태스크.\n *\n * 하나의 태스크가 등록된 레지스트리의 **모든 오퍼레이션** 을 커버한다. TaskRegistry 가\n * 수백 개 태스크로 폭발하는 것을 방지하는 핵심 설계.\n *\n * 입력:\n * - `operationRef` : `\"<serviceId>.<operationId>\"` 형식 (예: `\"1613000/BldRgstHubService.getBrTitleInfo\"`)\n * - `params` : 오퍼레이션 파라미터 객체. 스펙 등록된 오퍼레이션이면 자동 검증·기본값·zero-pad 적용\n *\n * 레지스트리에 없는 오퍼레이션도 호출 가능 (스펙 없음 → 검증 스킵). 새 data.go.kr 서비스가\n * 등장해도 스펙 추가 전까지 범용 호출로 즉시 사용 가능하다는 장점.\n */\nasync function DataGoKrCall(step, context: Context): Promise<{ data: DataGoKrResponse<any> }> {\n const { connection: connectionName, params: stepParams } = step\n const { domain, user, data, variables, lng, logger } = context\n\n const instance: DataGoKrConnectionInstance = await ConnectionManager.getConnectionInstanceByName(\n domain,\n connectionName\n )\n if (!instance?.client) {\n throw new Error(`data-go-kr connection '${connectionName}' is not established.`)\n }\n\n const operationRef = stepParams?.operationRef\n if (!operationRef || typeof operationRef !== 'string') {\n throw new Error('data-go-kr-call: operationRef is required (format: \"<serviceId>.<operationId>\")')\n }\n\n const resolved = SpecRegistry.resolve(operationRef)\n const rawParams = stepParams?.params || {}\n\n const scope = { domain, user, lng, data, variables, console }\n const evalValue = (value: any) => {\n if (value === undefined || value === null) return value\n if (typeof value !== 'string') return value\n try {\n return evaluateTemplate(value, scope)\n } catch (err) {\n throw new Error(`data-go-kr-call: failed to evaluate parameter: ${(err as Error).message}`)\n }\n }\n\n const evaluatedParams: Record<string, any> = {}\n for (const [k, v] of Object.entries(rawParams)) {\n evaluatedParams[k] = evalValue(v)\n }\n\n const { service, operation } = resolved || { service: null, operation: null }\n const finalParams = operation\n ? normalizeAndValidateParams(operation, evaluatedParams)\n : evaluatedParams\n\n const servicePath = resolved\n ? `${service!.serviceId}/${operation!.operationId}`\n : operationRef.replace('.', '/')\n\n logger?.info?.(`[data-go-kr] call ${servicePath} params=${JSON.stringify(finalParams)}`)\n\n const response = await instance.client.get(servicePath, finalParams)\n return { data: response }\n}\n\n/**\n * 스펙 기반 파라미터 정규화·검증.\n *\n * 1. required 필수값 체크\n * 2. default 기본값 주입\n * 3. pad zero-padding (예: bun=6 → \"0006\")\n * 4. length 정확 길이 검증\n * 5. enum 허용 값 검증\n */\nfunction normalizeAndValidateParams(operation: OperationSpec, input: Record<string, any>): Record<string, any> {\n const output: Record<string, any> = {}\n const errors: string[] = []\n\n for (const p of operation.params) {\n let value = input[p.name]\n\n if (value === undefined || value === null || value === '') {\n if (p.default !== undefined) {\n value = p.default\n } else if (p.required) {\n errors.push(`'${p.name}' is required (${p.description})`)\n continue\n } else {\n continue\n }\n }\n\n value = String(value)\n\n if (p.pad && value.length < p.pad) {\n value = '0'.repeat(p.pad - value.length) + value\n }\n\n if (p.length !== undefined && value.length !== p.length) {\n errors.push(\n `'${p.name}' must be exactly ${p.length} characters (got \"${value}\", length ${value.length})`\n )\n continue\n }\n\n if (p.enum && !p.enum.some(e => e.value === value)) {\n errors.push(\n `'${p.name}' must be one of [${p.enum.map(e => e.value).join(', ')}] (got \"${value}\")`\n )\n continue\n }\n\n output[p.name] = value\n }\n\n /* 스펙에 없는 파라미터도 pass-through (미등록 필드 허용) */\n for (const [k, v] of Object.entries(input)) {\n if (!(k in output) && !operation.params.find(p => p.name === k)) {\n if (v !== undefined && v !== null && v !== '') {\n output[k] = v\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(\n `data-go-kr-call parameter validation failed for ${operation.operationId}:\\n - ${errors.join('\\n - ')}`\n )\n }\n\n return output\n}\n\n/**\n * SpecRegistry 에 등록된 모든 오퍼레이션을 (operationRef → display) 옵션으로 펼친다.\n * 모듈 로딩 시 한 번 평가되며, 이후 register() 로 추가된 spec 은 반영되지 않음\n * (드문 케이스라 수용 — 향후 동적 parameterSpec 도입 시 해결).\n */\nfunction buildOperationRefOptions(): Array<{ value: string; display: string }> {\n return SpecRegistry.listServices()\n .flatMap(svc =>\n Object.values(svc.operations).map(op => ({\n value: `${svc.serviceId}.${op.operationId}`,\n display: `[${svc.label}] ${op.label}`\n }))\n )\n .sort((a, b) => a.display.localeCompare(b.display, 'ko'))\n}\n\nDataGoKrCall.parameterSpec = [\n {\n type: 'select',\n name: 'operationRef',\n label: 'label.operation-ref',\n property: {\n options: buildOperationRefOptions()\n }\n },\n {\n type: 'scenario-step-input',\n name: 'params',\n label: 'label.operation-params',\n placeholder:\n '오퍼레이션 파라미터를 JSON 객체로. 예) 건축물대장: {\"sigunguCd\":\"11680\",\"bjdongCd\":\"10300\",\"bun\":\"223\"} · 단기예보: {\"base_date\":\"20260425\",\"base_time\":\"1100\",\"nx\":\"60\",\"ny\":\"127\"}. 정확한 키는 helps/integration/services/<domain>.md 참고.'\n }\n]\n\nDataGoKrCall.help = 'integration/task/data-go-kr-call'\n\nTaskRegistry.registerTaskHandler('data-go-kr-call', DataGoKrCall)\n\nexport default DataGoKrCall\n"]}
|
|
1
|
+
{"version":3,"file":"call.js","sourceRoot":"","sources":["../../../server/engine/task/call.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConnectionManager, Context, TaskRegistry, evaluateTemplate } from '@things-factory/integration-base'\n\nimport { DataGoKrConnectionInstance } from '../connector/data-go-kr-connector'\nimport { DataGoKrResponse } from '../types'\nimport { OperationSpec, SpecRegistry } from '../spec'\n\n/**\n * 범용 공공데이터포털 호출 태스크.\n *\n * 하나의 태스크가 등록된 레지스트리의 **모든 오퍼레이션** 을 커버한다. TaskRegistry 가\n * 개별 태스크 등록 수가 과도하게 증가하는 것을 방지하는 설계.\n *\n * 입력:\n * - `operationRef` : `\"<serviceId>.<operationId>\"` 형식 (예: `\"1613000/BldRgstHubService.getBrTitleInfo\"`)\n * - `params` : 오퍼레이션 파라미터 객체. 스펙 등록된 오퍼레이션이면 자동 검증·기본값·zero-pad 적용\n *\n * 레지스트리에 없는 오퍼레이션도 호출 가능 (스펙 없음 → 검증 스킵). 새 data.go.kr 서비스가\n * 등장해도 스펙 추가 전까지 범용 호출로 즉시 사용 가능하다는 장점.\n */\nasync function DataGoKrCall(step, context: Context): Promise<{ data: DataGoKrResponse<any> }> {\n const { connection: connectionName, params: stepParams } = step\n const { domain, user, data, variables, lng, logger } = context\n\n const instance: DataGoKrConnectionInstance = await ConnectionManager.getConnectionInstanceByName(\n domain,\n connectionName\n )\n if (!instance?.client) {\n throw new Error(`data-go-kr connection '${connectionName}' is not established.`)\n }\n\n const operationRef = stepParams?.operationRef\n if (!operationRef || typeof operationRef !== 'string') {\n throw new Error('data-go-kr-call: operationRef is required (format: \"<serviceId>.<operationId>\")')\n }\n\n const resolved = SpecRegistry.resolve(operationRef)\n const rawParams = stepParams?.params || {}\n\n const scope = { domain, user, lng, data, variables, console }\n const evalValue = (value: any) => {\n if (value === undefined || value === null) return value\n if (typeof value !== 'string') return value\n try {\n return evaluateTemplate(value, scope)\n } catch (err) {\n throw new Error(`data-go-kr-call: failed to evaluate parameter: ${(err as Error).message}`)\n }\n }\n\n const evaluatedParams: Record<string, any> = {}\n for (const [k, v] of Object.entries(rawParams)) {\n evaluatedParams[k] = evalValue(v)\n }\n\n const { service, operation } = resolved || { service: null, operation: null }\n const finalParams = operation\n ? normalizeAndValidateParams(operation, evaluatedParams)\n : evaluatedParams\n\n const servicePath = resolved\n ? `${service!.serviceId}/${operation!.operationId}`\n : operationRef.replace('.', '/')\n\n logger?.info?.(`[data-go-kr] call ${servicePath} params=${JSON.stringify(finalParams)}`)\n\n const response = await instance.client.get(servicePath, finalParams)\n return { data: response }\n}\n\n/**\n * 스펙 기반 파라미터 정규화·검증.\n *\n * 1. required 필수값 체크\n * 2. default 기본값 주입\n * 3. pad zero-padding (예: bun=6 → \"0006\")\n * 4. length 정확 길이 검증\n * 5. enum 허용 값 검증\n */\nfunction normalizeAndValidateParams(operation: OperationSpec, input: Record<string, any>): Record<string, any> {\n const output: Record<string, any> = {}\n const errors: string[] = []\n\n for (const p of operation.params) {\n let value = input[p.name]\n\n if (value === undefined || value === null || value === '') {\n if (p.default !== undefined) {\n value = p.default\n } else if (p.required) {\n errors.push(`'${p.name}' is required (${p.description})`)\n continue\n } else {\n continue\n }\n }\n\n value = String(value)\n\n if (p.pad && value.length < p.pad) {\n value = '0'.repeat(p.pad - value.length) + value\n }\n\n if (p.length !== undefined && value.length !== p.length) {\n errors.push(\n `'${p.name}' must be exactly ${p.length} characters (got \"${value}\", length ${value.length})`\n )\n continue\n }\n\n if (p.enum && !p.enum.some(e => e.value === value)) {\n errors.push(\n `'${p.name}' must be one of [${p.enum.map(e => e.value).join(', ')}] (got \"${value}\")`\n )\n continue\n }\n\n output[p.name] = value\n }\n\n /* 스펙에 없는 파라미터도 pass-through (미등록 필드 허용) */\n for (const [k, v] of Object.entries(input)) {\n if (!(k in output) && !operation.params.find(p => p.name === k)) {\n if (v !== undefined && v !== null && v !== '') {\n output[k] = v\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(\n `data-go-kr-call parameter validation failed for ${operation.operationId}:\\n - ${errors.join('\\n - ')}`\n )\n }\n\n return output\n}\n\n/**\n * SpecRegistry 에 등록된 모든 오퍼레이션을 (operationRef → display) 옵션으로 펼친다.\n * 모듈 로딩 시 한 번 평가되며, 이후 register() 로 추가된 spec 은 반영되지 않음\n * (드문 케이스라 수용 — 향후 동적 parameterSpec 도입 시 해결).\n */\nfunction buildOperationRefOptions(): Array<{ value: string; display: string }> {\n return SpecRegistry.listServices()\n .flatMap(svc =>\n Object.values(svc.operations).map(op => ({\n value: `${svc.serviceId}.${op.operationId}`,\n display: `[${svc.label}] ${op.label}`\n }))\n )\n .sort((a, b) => a.display.localeCompare(b.display, 'ko'))\n}\n\nDataGoKrCall.parameterSpec = [\n {\n type: 'select',\n name: 'operationRef',\n label: 'label.operation-ref',\n property: {\n options: buildOperationRefOptions()\n }\n },\n {\n type: 'scenario-step-input',\n name: 'params',\n label: 'label.operation-params',\n placeholder:\n '오퍼레이션 파라미터를 JSON 객체로. 예) 건축물대장: {\"sigunguCd\":\"11680\",\"bjdongCd\":\"10300\",\"bun\":\"223\"} · 단기예보: {\"base_date\":\"20260425\",\"base_time\":\"1100\",\"nx\":\"60\",\"ny\":\"127\"}. 정확한 키는 helps/integration/services/<domain>.md 참고.'\n }\n]\n\nDataGoKrCall.help = 'integration/task/data-go-kr-call'\n\nTaskRegistry.registerTaskHandler('data-go-kr-call', DataGoKrCall)\n\nexport default DataGoKrCall\n"]}
|