@bimatrix-aud-platform/aud_mcp_server 1.0.0

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.
@@ -0,0 +1,152 @@
1
+ import { parseHexColor } from "../utils/color.js";
2
+ import { parseDocking } from "../utils/docking.js";
3
+ import { generateId } from "../utils/uuid.js";
4
+ import { defaultPosition, defaultStyle, defaultFont, ELEMENT_DEFAULTS_MAP, } from "./defaults.js";
5
+ // 단축 표기 처리 완료된 키 목록
6
+ const SHORTHAND_KEYS = new Set([
7
+ "type",
8
+ "id",
9
+ "name",
10
+ "text",
11
+ "position",
12
+ "docking",
13
+ "font",
14
+ "background",
15
+ "border",
16
+ "color",
17
+ "visible",
18
+ ]);
19
+ export function generateElement(input) {
20
+ const warnings = [];
21
+ const type = input.type;
22
+ // 1. ID 생성
23
+ const id = input.id || generateId(type);
24
+ const name = input.name || id;
25
+ // 2. Position 구성
26
+ const position = defaultPosition();
27
+ if (input.position) {
28
+ if (input.position.left !== undefined)
29
+ position.Left = input.position.left;
30
+ if (input.position.top !== undefined)
31
+ position.Top = input.position.top;
32
+ if (input.position.width !== undefined)
33
+ position.Width = input.position.width;
34
+ if (input.position.height !== undefined)
35
+ position.Height = input.position.height;
36
+ }
37
+ if (input.docking) {
38
+ position.Docking = parseDocking(input.docking);
39
+ }
40
+ // 3. Style 구성
41
+ const style = defaultStyle();
42
+ // 3a. Font 단축 표기
43
+ if (input.font || input.color) {
44
+ const font = defaultFont();
45
+ if (input.font) {
46
+ if (input.font.size !== undefined)
47
+ font.Size = input.font.size;
48
+ if (input.font.bold !== undefined)
49
+ font.Bold = input.font.bold;
50
+ if (input.font.italic !== undefined)
51
+ font.Italic = input.font.italic;
52
+ if (input.font.family)
53
+ font.Family = input.font.family;
54
+ if (input.font.color)
55
+ font.Color = parseHexColor(input.font.color);
56
+ if (input.font.align)
57
+ font.HorizontalAlignment = input.font.align;
58
+ if (input.font.valign)
59
+ font.VerticalAlignment = input.font.valign;
60
+ }
61
+ if (input.color && !input.font?.color) {
62
+ font.Color = parseHexColor(input.color);
63
+ }
64
+ style.Font = font;
65
+ }
66
+ // 3b. Background 단축 표기
67
+ if (input.background) {
68
+ style.Background = { Color: parseHexColor(input.background) };
69
+ }
70
+ // 3c. Border 단축 표기
71
+ if (input.border) {
72
+ style.Border = parseBorderShorthand(input.border);
73
+ }
74
+ // 4. 기본 Element 구성
75
+ const element = {
76
+ Type: type,
77
+ Id: id,
78
+ Name: name,
79
+ Position: position,
80
+ Style: style,
81
+ };
82
+ // 5. 타입별 기본값 적용
83
+ const defaultsFactory = ELEMENT_DEFAULTS_MAP[type];
84
+ if (defaultsFactory) {
85
+ const typeDefaults = defaultsFactory();
86
+ for (const [key, value] of Object.entries(typeDefaults)) {
87
+ if (!(key in element)) {
88
+ element[key] = value;
89
+ }
90
+ }
91
+ }
92
+ else {
93
+ warnings.push(`타입 '${type}'에 대한 기본값이 정의되어 있지 않습니다. 기본 Element 속성만 생성됩니다.`);
94
+ }
95
+ // 6. text 단축 표기 적용
96
+ if (input.text !== undefined) {
97
+ if (type === "Label" || type === "CheckBox") {
98
+ element.Text = input.text;
99
+ }
100
+ else if (type === "Button") {
101
+ element.Value = input.text;
102
+ }
103
+ }
104
+ // 7. visible 적용
105
+ if (input.visible === false) {
106
+ element.Visible = false;
107
+ }
108
+ // 8. 나머지 입력을 PascalCase로 pass-through
109
+ for (const [key, value] of Object.entries(input)) {
110
+ if (!SHORTHAND_KEYS.has(key)) {
111
+ const schemaKey = key.charAt(0).toUpperCase() + key.slice(1);
112
+ if (!(schemaKey in element)) {
113
+ element[schemaKey] = value;
114
+ }
115
+ }
116
+ }
117
+ return { element, warnings };
118
+ }
119
+ function parseBorderShorthand(shorthand) {
120
+ if (shorthand === "none") {
121
+ return {
122
+ CornerRadius: "0,0,0,0",
123
+ LineType: "none",
124
+ Thickness: "0,0,0,0",
125
+ };
126
+ }
127
+ // "solid 1px #DDD" 패턴 파싱
128
+ const parts = shorthand.trim().split(/\s+/);
129
+ let lineType = "solid";
130
+ let thickness = "1,1,1,1";
131
+ let color = { R: 204, G: 204, B: 204, A: 255 };
132
+ for (const part of parts) {
133
+ if (["solid", "dashed", "dotted", "none"].includes(part)) {
134
+ lineType = part;
135
+ }
136
+ else if (part.endsWith("px")) {
137
+ const px = parseInt(part);
138
+ if (!isNaN(px)) {
139
+ thickness = `${px},${px},${px},${px}`;
140
+ }
141
+ }
142
+ else if (part.startsWith("#")) {
143
+ color = parseHexColor(part);
144
+ }
145
+ }
146
+ return {
147
+ Color: color,
148
+ CornerRadius: "0,0,0,0",
149
+ LineType: lineType,
150
+ Thickness: thickness,
151
+ };
152
+ }
@@ -0,0 +1,22 @@
1
+ export interface ColumnInput {
2
+ name: string;
3
+ header?: string;
4
+ width?: number;
5
+ type?: string;
6
+ align?: string;
7
+ headerAlign?: string;
8
+ format?: string;
9
+ editable?: boolean;
10
+ visible?: boolean;
11
+ sortable?: boolean;
12
+ filterable?: boolean;
13
+ keyType?: number;
14
+ definedItems?: string;
15
+ [key: string]: any;
16
+ }
17
+ export declare function generateGridColumns(input: {
18
+ columns: ColumnInput[];
19
+ }): {
20
+ columns: Record<string, any>[];
21
+ warnings: string[];
22
+ };
@@ -0,0 +1,87 @@
1
+ import { defaultValidator } from "./defaults.js";
2
+ // ColumnType 매핑 (스키마 기준: 0:Text, 1:CheckBox, 2:ComboBox)
3
+ const COLUMN_TYPE_MAP = {
4
+ text: 0,
5
+ checkbox: 1,
6
+ combo: 2,
7
+ };
8
+ const PROCESSED_KEYS = new Set([
9
+ "name",
10
+ "header",
11
+ "width",
12
+ "type",
13
+ "align",
14
+ "headerAlign",
15
+ "format",
16
+ "editable",
17
+ "visible",
18
+ "sortable",
19
+ "filterable",
20
+ "keyType",
21
+ "definedItems",
22
+ ]);
23
+ export function generateGridColumns(input) {
24
+ const warnings = [];
25
+ const columns = [];
26
+ for (const col of input.columns) {
27
+ const column = {
28
+ Name: col.name,
29
+ Caption: col.header || col.name,
30
+ Width: col.width ?? 100,
31
+ Validator: defaultValidator(),
32
+ KeyType: col.keyType ?? 0,
33
+ HeaderPosition: col.headerAlign || "center",
34
+ };
35
+ // 컬럼 타입
36
+ if (col.type) {
37
+ const ct = COLUMN_TYPE_MAP[col.type.toLowerCase()];
38
+ if (ct !== undefined) {
39
+ column.ColumnType = ct;
40
+ }
41
+ else {
42
+ warnings.push(`알 수 없는 컬럼 타입: '${col.type}'. 기본값(0:text) 사용.`);
43
+ column.ColumnType = 0;
44
+ }
45
+ }
46
+ // 텍스트 정렬
47
+ if (col.align) {
48
+ column.TextPosition = col.align;
49
+ }
50
+ // 숫자 포맷 → 우측 정렬 자동
51
+ if (col.format) {
52
+ column.DataType = 1; // Number
53
+ if (!col.align) {
54
+ column.TextPosition = "right";
55
+ }
56
+ }
57
+ // Checkbox 타입 편의
58
+ if (col.type === "checkbox") {
59
+ if (col.editable === undefined)
60
+ column.Editable = true;
61
+ }
62
+ // Combo 타입 편의
63
+ if (col.type === "combo" && col.definedItems) {
64
+ column.DefinedItems = col.definedItems;
65
+ }
66
+ // 선택적 boolean 속성
67
+ if (col.editable !== undefined)
68
+ column.Editable = col.editable;
69
+ if (col.visible !== undefined)
70
+ column.Visible = col.visible;
71
+ if (col.sortable !== undefined)
72
+ column.Sortable = col.sortable;
73
+ if (col.filterable !== undefined)
74
+ column.Filterable = col.filterable;
75
+ // 나머지 pass-through
76
+ for (const [key, value] of Object.entries(col)) {
77
+ if (!PROCESSED_KEYS.has(key)) {
78
+ const schemaKey = key.charAt(0).toUpperCase() + key.slice(1);
79
+ if (!(schemaKey in column)) {
80
+ column[schemaKey] = value;
81
+ }
82
+ }
83
+ }
84
+ columns.push(column);
85
+ }
86
+ return { columns, warnings };
87
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};