@bimatrix-aud-platform/aud_mcp_server 1.1.14 → 1.1.16

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/dist/index.js CHANGED
@@ -35,6 +35,26 @@ catch (error) {
35
35
  console.error("Failed to load module schema:", error);
36
36
  process.exit(1);
37
37
  }
38
+ // Load json2 schema
39
+ const json2SchemaPath = join(__dirname, "..", "schemas", "json2.schema.json");
40
+ let json2Schema;
41
+ try {
42
+ json2Schema = JSON.parse(readFileSync(json2SchemaPath, "utf-8"));
43
+ }
44
+ catch (error) {
45
+ console.error("Failed to load json2 schema:", error);
46
+ process.exit(1);
47
+ }
48
+ // Load ds schema
49
+ const dsSchemaPath = join(__dirname, "..", "schemas", "ds.schema.json");
50
+ let dsSchema;
51
+ try {
52
+ dsSchema = JSON.parse(readFileSync(dsSchemaPath, "utf-8"));
53
+ }
54
+ catch (error) {
55
+ console.error("Failed to load ds schema:", error);
56
+ process.exit(1);
57
+ }
38
58
  // Initialize AJV validator
39
59
  const ajv = new Ajv.default({
40
60
  allErrors: true,
@@ -44,6 +64,8 @@ const ajv = new Ajv.default({
44
64
  addFormats.default(ajv);
45
65
  const validate = ajv.compile(mtsdSchema);
46
66
  const validateModule = ajv.compile(moduleSchema);
67
+ const validateJson2 = ajv.compile(json2Schema);
68
+ const validateDs = ajv.compile(dsSchema);
47
69
  // Error message translation (Korean)
48
70
  function translateError(error) {
49
71
  const path = error.instancePath || "(root)";
@@ -142,14 +164,39 @@ const tools = [
142
164
  "DataSources",
143
165
  "Form",
144
166
  "Element",
167
+ // Display
145
168
  "LabelElement",
146
169
  "ButtonElement",
147
- "DataGridElement",
148
- "GroupElement",
149
- "ComboBoxElement",
150
- "CheckBoxElement",
170
+ "ImageElement",
171
+ // Input
151
172
  "TextBoxElement",
173
+ "MaskTextBoxElement",
152
174
  "NumberBoxElement",
175
+ "RichTextBoxElement",
176
+ "ComboBoxElement",
177
+ "MultiComboBoxElement",
178
+ "PickListElement",
179
+ "CheckBoxElement",
180
+ "RadioButtonElement",
181
+ "ColorSelectorElement",
182
+ "SliderElement",
183
+ "CalendarElement",
184
+ "FileUploadButtonElement",
185
+ // Grid
186
+ "DataGridElement",
187
+ "TreeGridElement",
188
+ "OlapGridElement",
189
+ "iGridElement",
190
+ // Chart
191
+ "ChartElement",
192
+ // Container / Layout
193
+ "GroupElement",
194
+ "TabElement",
195
+ "TableLayoutElement",
196
+ "UserComponentElement",
197
+ // Etc
198
+ "WebContainerElement",
199
+ // Non-Element
153
200
  "Variable",
154
201
  "Module",
155
202
  "ExecutionPlan",
@@ -185,15 +232,40 @@ const tools = [
185
232
  "Font",
186
233
  "Border",
187
234
  "Background",
235
+ // Display
188
236
  "LabelElement",
189
237
  "ButtonElement",
190
- "DataGridElement",
191
- "GroupElement",
192
- "ComboBoxElement",
193
- "CheckBoxElement",
238
+ "ImageElement",
239
+ // Input
194
240
  "TextBoxElement",
241
+ "MaskTextBoxElement",
195
242
  "NumberBoxElement",
243
+ "RichTextBoxElement",
244
+ "ComboBoxElement",
245
+ "MultiComboBoxElement",
246
+ "PickListElement",
247
+ "CheckBoxElement",
248
+ "RadioButtonElement",
249
+ "ColorSelectorElement",
250
+ "SliderElement",
251
+ "CalendarElement",
252
+ "FileUploadButtonElement",
253
+ // Grid
254
+ "DataGridElement",
255
+ "TreeGridElement",
256
+ "OlapGridElement",
257
+ "iGridElement",
196
258
  "GridColumn",
259
+ // Chart
260
+ "ChartElement",
261
+ // Container / Layout
262
+ "GroupElement",
263
+ "TabElement",
264
+ "TableLayoutElement",
265
+ "UserComponentElement",
266
+ // Etc
267
+ "WebContainerElement",
268
+ // Non-Element
197
269
  "Variable",
198
270
  "Module",
199
271
  "ExecutionPlan",
@@ -233,11 +305,25 @@ const tools = [
233
305
  type: "string",
234
306
  description: "Element 타입",
235
307
  enum: [
236
- "Label", "Button", "DataGrid", "Group", "Image",
237
- "RichTextBox", "CheckBox", "ComboBox", "TextBox", "NumberBox",
238
- "RadioButton", "Chart", "PieChart", "ScatterChart", "TreeGrid",
239
- "OlapGrid", "Slider", "FileUpload", "Browser", "ColorPicker",
240
- "MultiComboBox", "PickList", "UserComponent", "ListGrid",
308
+ // Display
309
+ "Label", "Button", "Image",
310
+ // Input
311
+ "TextBox", "MaskTextBox", "NumberBox", "RichTextBox",
312
+ "ComboBox", "MultiComboBox", "PickList",
313
+ "CheckBox", "RadioButton", "Tree",
314
+ "ColorSelector", "Slider",
315
+ "Calendar", "CalendarYear", "CalendarYM",
316
+ "FileUploadButton",
317
+ // Grid
318
+ "DataGrid", "TreeGrid", "OlapGrid", "iGrid", "CompactDataGrid",
319
+ // TreeView
320
+ "TreeView",
321
+ // Chart
322
+ "Chart", "PieChart", "ScatterChart", "PolygonChart",
323
+ // Container / Layout
324
+ "Group", "Tab", "AddIn", "UserComponent",
325
+ // Etc
326
+ "WebContainer", "DiagramControl", "Slicer",
241
327
  ],
242
328
  },
243
329
  id: {
@@ -439,6 +525,28 @@ const tools = [
439
525
  },
440
526
  },
441
527
  },
528
+ {
529
+ name: "validate_mxgrid",
530
+ description: "MX-GRID 템플릿(.json2) 및 데이터셋(.ds) 파일을 검증합니다. 파일 경로 또는 JSON 문자열/객체를 받아 스키마 준수 여부를 확인하고, 비즈니스 로직 경고(스타일 참조 불일치, 시트명 참조 불일치 등)도 포함합니다.",
531
+ inputSchema: {
532
+ type: "object",
533
+ properties: {
534
+ path: {
535
+ type: "string",
536
+ description: "파일의 전체 경로 (.json2 또는 .ds 확장자). 확장자로 타입을 자동 감지합니다.",
537
+ },
538
+ document: {
539
+ type: ["string", "object"],
540
+ description: "검증할 JSON 문서 (JSON 문자열 또는 객체). path와 document 중 하나를 지정합니다.",
541
+ },
542
+ type: {
543
+ type: "string",
544
+ enum: ["json2", "ds"],
545
+ description: "문서 타입. document 파라미터 사용 시 필수. path 사용 시 확장자에서 자동 감지.",
546
+ },
547
+ },
548
+ },
549
+ },
442
550
  {
443
551
  name: "get_control_info",
444
552
  description: "MTSD 파일에서 컨트롤의 Name과 Type 매핑 정보를 추출합니다. TypeScript 스크립트 작성 시 컨트롤 변수의 타입을 확인하거나, import 문을 생성할 때 사용합니다.",
@@ -703,30 +811,49 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
703
811
  }
704
812
  case "get_element_types": {
705
813
  const elementTypes = [
814
+ // ── Display ──
706
815
  { type: "Label", description: "텍스트 표시용 레이블" },
707
816
  { type: "Button", description: "클릭 가능한 버튼" },
708
- { type: "DataGrid", description: "데이터 표시/편집용 그리드" },
709
- { type: "Group", description: "컨트롤을 그룹화하는 컨테이너" },
710
- { type: "Image", description: "이미지 표시" },
711
- { type: "RichTextBox", description: "서식있는 텍스트 편집기" },
712
- { type: "CheckBox", description: "체크박스 선택 컨트롤" },
713
- { type: "ComboBox", description: "드롭다운 선택 컨트롤" },
817
+ { type: "Image", description: "이미지 표시 (내부적으로 WebImage)" },
818
+ // ── Input ──
714
819
  { type: "TextBox", description: "텍스트 입력 필드" },
820
+ { type: "MaskTextBox", description: "마스크 텍스트 입력 (입력 패턴 지정)" },
715
821
  { type: "NumberBox", description: "숫자 입력 필드" },
822
+ { type: "RichTextBox", description: "서식있는 텍스트 편집기" },
823
+ { type: "ComboBox", description: "드롭다운 선택 컨트롤" },
824
+ { type: "MultiComboBox", description: "다중 선택 콤보박스" },
825
+ { type: "PickList", description: "픽리스트 컨트롤" },
826
+ { type: "CheckBox", description: "체크박스 선택 컨트롤" },
716
827
  { type: "RadioButton", description: "라디오 버튼 선택" },
828
+ { type: "Tree", description: "트리 체크박스 컨트롤" },
829
+ { type: "ColorSelector", description: "색상 선택기" },
830
+ { type: "Slider", description: "슬라이더 컨트롤" },
831
+ { type: "Calendar", description: "달력 (날짜 선택)" },
832
+ { type: "CalendarYear", description: "달력 (연도 선택)" },
833
+ { type: "CalendarYM", description: "달력 (연월 선택)" },
834
+ { type: "FileUploadButton", description: "파일 업로드 버튼" },
835
+ // ── Grid ──
836
+ { type: "DataGrid", description: "데이터 표시/편집용 그리드" },
837
+ { type: "TreeGrid", description: "트리 구조 그리드" },
838
+ { type: "OlapGrid", description: "OLAP 분석용 그리드" },
839
+ { type: "iGrid", description: "인터랙티브 그리드 (MXGrid)" },
840
+ { type: "CompactDataGrid", description: "컴팩트 데이터 그리드" },
841
+ // ── TreeView ──
842
+ { type: "TreeView", description: "트리뷰 (계층 구조 표시)" },
843
+ // ── Chart ──
717
844
  { type: "Chart", description: "차트 (막대, 선, 영역)" },
718
845
  { type: "PieChart", description: "파이 차트" },
719
846
  { type: "ScatterChart", description: "산점도 차트" },
720
- { type: "TreeGrid", description: "트리 구조 그리드" },
721
- { type: "OlapGrid", description: "OLAP 분석용 그리드" },
722
- { type: "Slider", description: "슬라이더 컨트롤" },
723
- { type: "FileUpload", description: "파일 업로드 컨트롤" },
724
- { type: "Browser", description: " 브라우저 컨트롤" },
725
- { type: "ColorPicker", description: "색상 선택기" },
726
- { type: "MultiComboBox", description: "다중 선택 콤보박스" },
727
- { type: "PickList", description: "픽리스트 컨트롤" },
847
+ { type: "PolygonChart", description: "다각형/레이더 차트" },
848
+ // ── Container / Layout ──
849
+ { type: "Group", description: "컨트롤을 그룹화하는 컨테이너" },
850
+ { type: "Tab", description: " 컨테이너 (탭 페이지별 자식 컨트롤)" },
851
+ { type: "AddIn", description: "애드인 컨테이너" },
728
852
  { type: "UserComponent", description: "보고서 컨테이너 (서브 보고서)" },
729
- { type: "ListGrid", description: "목록 그리드" },
853
+ // ── Etc ──
854
+ { type: "WebContainer", description: "웹 브라우저 컨테이너 (기본 이름: Browser)" },
855
+ { type: "DiagramControl", description: "다이어그램 컨트롤" },
856
+ { type: "Slicer", description: "슬라이서 컨트롤" },
730
857
  ];
731
858
  return {
732
859
  content: [
@@ -962,6 +1089,184 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
962
1089
  };
963
1090
  }
964
1091
  }
1092
+ case "validate_mxgrid": {
1093
+ let doc = args?.document;
1094
+ const filePath = args?.path;
1095
+ let docType = args?.type;
1096
+ // 확장자로 타입 자동 감지
1097
+ if (filePath && !docType) {
1098
+ if (filePath.endsWith(".json2"))
1099
+ docType = "json2";
1100
+ else if (filePath.endsWith(".ds"))
1101
+ docType = "ds";
1102
+ else {
1103
+ return {
1104
+ content: [
1105
+ {
1106
+ type: "text",
1107
+ text: JSON.stringify({
1108
+ valid: false,
1109
+ error: "파일 확장자가 .json2 또는 .ds가 아닙니다. type 파라미터를 지정해 주세요.",
1110
+ }),
1111
+ },
1112
+ ],
1113
+ };
1114
+ }
1115
+ }
1116
+ // 파일 읽기
1117
+ if (!doc && filePath) {
1118
+ try {
1119
+ const raw = readFileSync(filePath, "utf-8");
1120
+ doc = JSON.parse(raw);
1121
+ }
1122
+ catch (e) {
1123
+ return {
1124
+ content: [
1125
+ {
1126
+ type: "text",
1127
+ text: JSON.stringify({
1128
+ valid: false,
1129
+ error: `파일 읽기/파싱 오류: ${e instanceof Error ? e.message : String(e)}`,
1130
+ }),
1131
+ },
1132
+ ],
1133
+ };
1134
+ }
1135
+ }
1136
+ if (!doc) {
1137
+ return {
1138
+ content: [
1139
+ {
1140
+ type: "text",
1141
+ text: JSON.stringify({ error: "path 또는 document 파라미터가 필요합니다." }),
1142
+ },
1143
+ ],
1144
+ };
1145
+ }
1146
+ if (!docType) {
1147
+ return {
1148
+ content: [
1149
+ {
1150
+ type: "text",
1151
+ text: JSON.stringify({
1152
+ error: "document 사용 시 type 파라미터('json2' 또는 'ds')가 필요합니다.",
1153
+ }),
1154
+ },
1155
+ ],
1156
+ };
1157
+ }
1158
+ // 문자열이면 파싱
1159
+ if (typeof doc === "string") {
1160
+ try {
1161
+ doc = JSON.parse(doc);
1162
+ }
1163
+ catch (e) {
1164
+ return {
1165
+ content: [
1166
+ {
1167
+ type: "text",
1168
+ text: JSON.stringify({
1169
+ valid: false,
1170
+ error: "JSON 파싱 오류: 유효한 JSON 형식이 아닙니다.",
1171
+ }),
1172
+ },
1173
+ ],
1174
+ };
1175
+ }
1176
+ }
1177
+ // 검증기 선택
1178
+ const validatorFn = docType === "json2" ? validateJson2 : validateDs;
1179
+ const docTypeName = docType === "json2" ? "MX-GRID 템플릿(.json2)" : "MX-GRID 데이터셋(.ds)";
1180
+ const isValid = validatorFn(doc);
1181
+ if (isValid) {
1182
+ // 비즈니스 로직 경고
1183
+ const warnings = [];
1184
+ if (docType === "json2") {
1185
+ const json2Doc = doc;
1186
+ // 1. Style 참조 검증: Ranges에서 참조하는 스타일이 정의되어 있는지
1187
+ const definedStyles = new Set((json2Doc.Styles || []).map((s) => s.Name));
1188
+ for (const ws of json2Doc.WorkSheets || []) {
1189
+ for (const range of ws.Ranges || []) {
1190
+ if (typeof range.Style === "string" && !definedStyles.has(range.Style)) {
1191
+ warnings.push(`WorkSheet "${ws.Name}" Range "${range.Range}": 스타일 "${range.Style}"이(가) Styles에 정의되어 있지 않습니다.`);
1192
+ }
1193
+ }
1194
+ }
1195
+ // 2. Names 시트 참조 검증
1196
+ const sheetNames = new Set((json2Doc.WorkSheets || []).map((ws) => ws.Name));
1197
+ for (const nameDef of json2Doc.Names || []) {
1198
+ if (nameDef.SheetName && !sheetNames.has(nameDef.SheetName)) {
1199
+ warnings.push(`Names "${nameDef.Name}": SheetName "${nameDef.SheetName}"이(가) WorkSheets에 존재하지 않습니다.`);
1200
+ }
1201
+ }
1202
+ // 3. DataBinding 시트 참조 검증
1203
+ for (const binding of json2Doc.DataBinding || []) {
1204
+ if (binding.Sheet && !sheetNames.has(binding.Sheet)) {
1205
+ warnings.push(`DataBinding "${binding.Name}": Sheet "${binding.Sheet}"이(가) WorkSheets에 존재하지 않습니다.`);
1206
+ }
1207
+ }
1208
+ // 4. 중복 Style 이름 검증
1209
+ const styleNames = (json2Doc.Styles || []).map((s) => s.Name);
1210
+ const seen = new Set();
1211
+ for (const name of styleNames) {
1212
+ if (seen.has(name)) {
1213
+ warnings.push(`Styles: 스타일 이름 "${name}"이(가) 중복 정의되어 있습니다.`);
1214
+ }
1215
+ seen.add(name);
1216
+ }
1217
+ }
1218
+ if (docType === "ds") {
1219
+ const dsDoc = doc;
1220
+ const datas = dsDoc.DataSources?.Datas || [];
1221
+ // 1. 중복 Id 검증
1222
+ const idSeen = new Set();
1223
+ for (const d of datas) {
1224
+ if (idSeen.has(d.Id)) {
1225
+ warnings.push(`DataSources.Datas: Id "${d.Id}"이(가) 중복되어 있습니다.`);
1226
+ }
1227
+ idSeen.add(d.Id);
1228
+ }
1229
+ // 2. 빈 SQL 경고
1230
+ for (let i = 0; i < datas.length; i++) {
1231
+ const d = datas[i];
1232
+ if (d.SQL !== undefined && d.SQL.trim() === "") {
1233
+ warnings.push(`DataSources.Datas[${i}] "${d.Name}": SQL이 비어 있습니다.`);
1234
+ }
1235
+ }
1236
+ }
1237
+ return {
1238
+ content: [
1239
+ {
1240
+ type: "text",
1241
+ text: JSON.stringify({
1242
+ valid: true,
1243
+ message: `${docTypeName} 문서가 스키마를 준수합니다.`,
1244
+ warnings: warnings.length > 0 ? warnings : undefined,
1245
+ }),
1246
+ },
1247
+ ],
1248
+ };
1249
+ }
1250
+ else {
1251
+ const errors = validatorFn.errors || [];
1252
+ const groupedErrors = groupErrors(errors);
1253
+ const errorCount = errors.length;
1254
+ return {
1255
+ content: [
1256
+ {
1257
+ type: "text",
1258
+ text: JSON.stringify({
1259
+ valid: false,
1260
+ errorCount,
1261
+ summary: `${errorCount}개의 오류가 발견되었습니다.`,
1262
+ errors: groupedErrors,
1263
+ rawErrors: errors.slice(0, 20).map(translateError),
1264
+ }),
1265
+ },
1266
+ ],
1267
+ };
1268
+ }
1269
+ }
965
1270
  case "get_control_info": {
966
1271
  const filePath = args?.path;
967
1272
  if (!filePath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bimatrix-aud-platform/aud_mcp_server",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "description": "MCP Server for i-AUD MTSD document validation and generation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,68 @@
1
+ /**
2
+ * MX-GRID 데이터셋(.ds) 파일 구조 인터페이스
3
+ * .ds 파일은 MX-GRID 스프레드시트의 데이터 바인딩 소스를 정의합니다.
4
+ */
5
+
6
+ // ============================================
7
+ // 루트 인터페이스
8
+ // ============================================
9
+
10
+ /**
11
+ * .ds 파일 최상위 구조
12
+ */
13
+ export interface IDsDocument {
14
+ /** 데이터 소스 정의 */
15
+ DataSources: IDataSources;
16
+ }
17
+
18
+ /**
19
+ * 데이터 소스 컨테이너
20
+ */
21
+ export interface IDataSources {
22
+ /** 데이터 소스 항목 배열 */
23
+ Datas: IDataItem[];
24
+ }
25
+
26
+ // ============================================
27
+ // 데이터 소스 항목
28
+ // ============================================
29
+
30
+ /**
31
+ * 개별 데이터 소스 항목
32
+ */
33
+ export interface IDataItem {
34
+ /** 데이터 소스 고유 ID */
35
+ Id: string;
36
+ /** 데이터 소스 이름 */
37
+ Name: string;
38
+ /** 데이터 출력 주소 (예: "'V1'!$A$2:$B$3") */
39
+ OutputAddress: string;
40
+ /** 설명 */
41
+ Description?: string;
42
+ /** 컬럼 헤더 출력 여부 */
43
+ WriterColumnHeader?: boolean;
44
+ /** 데이터베이스 연결 코드 */
45
+ ConnectionCode?: string;
46
+ /** 데이터베이스 연결 이름 */
47
+ ConnectionName?: string;
48
+ /** 데이터베이스 유형 코드 */
49
+ DBType?: number;
50
+ /** 소유자 코드 */
51
+ OwnerCode?: string;
52
+ /** 선택된 스키마 이름 */
53
+ SelectedSchemaName?: string;
54
+ /** 소스 유형 코드 */
55
+ SourceType?: number;
56
+ /** SQL 쿼리 */
57
+ SQL?: string;
58
+ /** i-META 배치 정보 (값이 있는 경우 수정 불가) */
59
+ MetaLayout?: string | null;
60
+ /** 바인딩용 SQL */
61
+ BindSQL?: string;
62
+ /** 마지막 수정일시 */
63
+ LastModifyDate?: string;
64
+ /** 서비스 ID */
65
+ ServiceID?: string;
66
+ /** 레코드 수 */
67
+ RecordCount?: number;
68
+ }
@@ -0,0 +1,102 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "ds-file-schema",
4
+ "title": "MX-GRID DataSource Schema",
5
+ "description": "MX-GRID 데이터셋(.ds) 파일 스키마. 스프레드시트 데이터 바인딩 소스를 정의합니다.",
6
+ "type": "object",
7
+ "required": ["DataSources"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "DataSources": {
11
+ "type": "object",
12
+ "description": "데이터 소스 정의",
13
+ "required": ["Datas"],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "Datas": {
17
+ "type": "array",
18
+ "description": "데이터 소스 항목 배열",
19
+ "items": { "$ref": "#/$defs/DataItem" }
20
+ }
21
+ }
22
+ }
23
+ },
24
+ "$defs": {
25
+ "DataItem": {
26
+ "type": "object",
27
+ "description": "개별 데이터 소스 항목",
28
+ "required": ["Id", "Name", "OutputAddress"],
29
+ "additionalProperties": true,
30
+ "properties": {
31
+ "Id": {
32
+ "type": "string",
33
+ "description": "데이터 소스 고유 ID"
34
+ },
35
+ "Name": {
36
+ "type": "string",
37
+ "description": "데이터 소스 이름"
38
+ },
39
+ "OutputAddress": {
40
+ "type": "string",
41
+ "description": "데이터 출력 주소 (예: \"'V1'!$A$2:$B$3\")"
42
+ },
43
+ "Description": {
44
+ "type": ["string", "null"],
45
+ "description": "설명"
46
+ },
47
+ "WriterColumnHeader": {
48
+ "type": "boolean",
49
+ "description": "컬럼 헤더 출력 여부"
50
+ },
51
+ "ConnectionCode": {
52
+ "type": "string",
53
+ "description": "데이터베이스 연결 코드"
54
+ },
55
+ "ConnectionName": {
56
+ "type": "string",
57
+ "description": "데이터베이스 연결 이름"
58
+ },
59
+ "DBType": {
60
+ "type": "integer",
61
+ "description": "데이터베이스 유형 코드"
62
+ },
63
+ "OwnerCode": {
64
+ "type": "string",
65
+ "description": "소유자 코드"
66
+ },
67
+ "SelectedSchemaName": {
68
+ "type": ["string", "null"],
69
+ "description": "선택된 스키마 이름"
70
+ },
71
+ "SourceType": {
72
+ "type": "integer",
73
+ "description": "소스 유형 코드"
74
+ },
75
+ "SQL": {
76
+ "type": "string",
77
+ "description": "SQL 쿼리"
78
+ },
79
+ "MetaLayout": {
80
+ "type": ["string", "null"],
81
+ "description": "i-META 배치 정보 (값이 있는 경우 수정 불가)"
82
+ },
83
+ "BindSQL": {
84
+ "type": "string",
85
+ "description": "바인딩용 SQL"
86
+ },
87
+ "LastModifyDate": {
88
+ "type": "string",
89
+ "description": "마지막 수정일시"
90
+ },
91
+ "ServiceID": {
92
+ "type": "string",
93
+ "description": "서비스 ID"
94
+ },
95
+ "RecordCount": {
96
+ "type": "integer",
97
+ "description": "레코드 수"
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }