@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 +333 -28
- package/package.json +1 -1
- package/schemas/ds.interface.ts +68 -0
- package/schemas/ds.schema.json +102 -0
- package/schemas/json2.interface.ts +503 -0
- package/schemas/json2.schema.json +605 -0
- package/schemas/mtsd.interface.ts +599 -17
- package/schemas/mtsd.schema.json +316 -7
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
|
-
"
|
|
148
|
-
|
|
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
|
-
"
|
|
191
|
-
|
|
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
|
-
|
|
237
|
-
"
|
|
238
|
-
|
|
239
|
-
"
|
|
240
|
-
"
|
|
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: "
|
|
709
|
-
|
|
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: "
|
|
721
|
-
|
|
722
|
-
{ type: "
|
|
723
|
-
{ type: "
|
|
724
|
-
{ type: "
|
|
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
|
-
|
|
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
|
@@ -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
|
+
}
|