@mcp-abap-adt/adt-clients 3.9.0 → 3.9.2
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/core/dataElement/update.d.ts +11 -9
- package/dist/core/dataElement/update.d.ts.map +1 -1
- package/dist/core/dataElement/update.js +146 -176
- package/dist/core/domain/update.d.ts +4 -1
- package/dist/core/domain/update.d.ts.map +1 -1
- package/dist/core/domain/update.js +61 -51
- package/dist/core/functionGroup/update.d.ts.map +1 -1
- package/dist/core/functionGroup/update.js +5 -18
- package/dist/core/package/update.d.ts +5 -2
- package/dist/core/package/update.d.ts.map +1 -1
- package/dist/core/package/update.js +45 -97
- package/dist/core/tabletype/update.d.ts +4 -5
- package/dist/core/tabletype/update.d.ts.map +1 -1
- package/dist/core/tabletype/update.js +59 -163
- package/dist/utils/xmlPatch.d.ts +35 -0
- package/dist/utils/xmlPatch.d.ts.map +1 -0
- package/dist/utils/xmlPatch.js +81 -0
- package/package.json +1 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DataElement update operations
|
|
3
|
+
*
|
|
4
|
+
* Uses read-modify-write pattern: GET current XML → patch fields → PUT.
|
|
5
|
+
* This preserves all SAP-managed fields that would be lost if XML were built from scratch.
|
|
3
6
|
*/
|
|
4
7
|
import type { IAdtResponse as AxiosResponse, IAbapConnection, ILogger } from '@mcp-abap-adt/interfaces';
|
|
5
8
|
import type { IUpdateDataElementParams } from './types';
|
|
@@ -12,18 +15,17 @@ export declare function getDomainInfo(connection: IAbapConnection, domainName: s
|
|
|
12
15
|
decimals: number;
|
|
13
16
|
}>;
|
|
14
17
|
/**
|
|
15
|
-
* Update data element
|
|
16
|
-
* Requires object to be locked first (
|
|
18
|
+
* Update data element - atomic PUT operation (read-modify-write pattern)
|
|
19
|
+
* NOTE: Requires object to be locked first via lockDataElement()
|
|
20
|
+
* NOTE: Caller should call connection.setSessionType("stateful") before locking
|
|
21
|
+
*/
|
|
22
|
+
export declare function updateDataElement(connection: IAbapConnection, params: IUpdateDataElementParams, lockHandle: string, logger?: ILogger): Promise<AxiosResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated Use updateDataElement directly. Kept for backward compatibility.
|
|
17
25
|
*/
|
|
18
|
-
export declare function updateDataElementInternal(connection: IAbapConnection, args: IUpdateDataElementParams, lockHandle: string,
|
|
26
|
+
export declare function updateDataElementInternal(connection: IAbapConnection, args: IUpdateDataElementParams, lockHandle: string, _username: string, _domainInfo: {
|
|
19
27
|
dataType: string;
|
|
20
28
|
length: number;
|
|
21
29
|
decimals: number;
|
|
22
30
|
}, logger?: ILogger): Promise<AxiosResponse>;
|
|
23
|
-
/**
|
|
24
|
-
* Update data element - atomic PUT operation
|
|
25
|
-
* NOTE: Requires object to be locked first via lockDataElement()
|
|
26
|
-
* NOTE: Caller should call connection.setSessionType("stateful") before locking
|
|
27
|
-
*/
|
|
28
|
-
export declare function updateDataElement(connection: IAbapConnection, params: IUpdateDataElementParams, lockHandle: string, logger?: ILogger): Promise<AxiosResponse>;
|
|
29
31
|
//# sourceMappingURL=update.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/core/dataElement/update.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/core/dataElement/update.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,IAAI,aAAa,EAC7B,eAAe,EACf,OAAO,EACR,MAAM,0BAA0B,CAAC;AAgBlC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAIxD;;GAEG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,eAAe,EAC3B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAmCjE;AAqID;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,wBAAwB,EAChC,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,CAAC,CAkExB;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,eAAe,EAC3B,IAAI,EAAE,wBAAwB,EAC9B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACnE,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,CAAC,CAExB"}
|
|
@@ -1,21 +1,57 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* DataElement update operations
|
|
4
|
+
*
|
|
5
|
+
* Uses read-modify-write pattern: GET current XML → patch fields → PUT.
|
|
6
|
+
* This preserves all SAP-managed fields that would be lost if XML were built from scratch.
|
|
4
7
|
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
5
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
42
|
exports.getDomainInfo = getDomainInfo;
|
|
7
|
-
exports.updateDataElementInternal = updateDataElementInternal;
|
|
8
43
|
exports.updateDataElement = updateDataElement;
|
|
9
|
-
|
|
44
|
+
exports.updateDataElementInternal = updateDataElementInternal;
|
|
10
45
|
const contentTypes_1 = require("../../constants/contentTypes");
|
|
11
46
|
const internalUtils_1 = require("../../utils/internalUtils");
|
|
12
|
-
const systemInfo_1 = require("../../utils/systemInfo");
|
|
13
47
|
const timeouts_1 = require("../../utils/timeouts");
|
|
48
|
+
const xmlPatch_1 = require("../../utils/xmlPatch");
|
|
14
49
|
const debugEnabled = process.env.DEBUG_ADT_LIBS === 'true';
|
|
15
50
|
/**
|
|
16
51
|
* Get domain info to extract dataType, length, decimals
|
|
17
52
|
*/
|
|
18
53
|
async function getDomainInfo(connection, domainName) {
|
|
54
|
+
const { XMLParser } = await Promise.resolve().then(() => __importStar(require('fast-xml-parser')));
|
|
19
55
|
const domainNameEncoded = (0, internalUtils_1.encodeSapObjectName)(domainName.toLowerCase());
|
|
20
56
|
const url = `/sap/bc/adt/ddic/domains/${domainNameEncoded}`;
|
|
21
57
|
const headers = {
|
|
@@ -27,7 +63,7 @@ async function getDomainInfo(connection, domainName) {
|
|
|
27
63
|
timeout: (0, timeouts_1.getTimeout)('default'),
|
|
28
64
|
headers,
|
|
29
65
|
});
|
|
30
|
-
const parser = new
|
|
66
|
+
const parser = new XMLParser({
|
|
31
67
|
ignoreAttributes: false,
|
|
32
68
|
attributeNamePrefix: '',
|
|
33
69
|
});
|
|
@@ -43,160 +79,106 @@ async function getDomainInfo(connection, domainName) {
|
|
|
43
79
|
};
|
|
44
80
|
}
|
|
45
81
|
/**
|
|
46
|
-
*
|
|
82
|
+
* Patch current data element XML with updated values.
|
|
83
|
+
* Only modifies fields that are explicitly provided in args.
|
|
47
84
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const response = await connection.makeAdtRequest({
|
|
55
|
-
url,
|
|
56
|
-
method: 'GET',
|
|
57
|
-
timeout: (0, timeouts_1.getTimeout)('default'),
|
|
58
|
-
headers,
|
|
59
|
-
});
|
|
60
|
-
const parser = new fast_xml_parser_1.XMLParser({
|
|
61
|
-
ignoreAttributes: false,
|
|
62
|
-
attributeNamePrefix: '',
|
|
63
|
-
});
|
|
64
|
-
const result = parser.parse(response.data);
|
|
65
|
-
return result['blue:wbobj'];
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Update data element with new data
|
|
69
|
-
* Requires object to be locked first (lockHandle must be provided)
|
|
70
|
-
*/
|
|
71
|
-
async function updateDataElementInternal(connection, args, lockHandle, username, _domainInfo, logger) {
|
|
72
|
-
const dataElementNameEncoded = (0, internalUtils_1.encodeSapObjectName)(args.data_element_name.toLowerCase());
|
|
73
|
-
const corrNrParam = args.transport_request
|
|
74
|
-
? `&corrNr=${args.transport_request}`
|
|
75
|
-
: '';
|
|
76
|
-
const url = `/sap/bc/adt/ddic/dataelements/${dataElementNameEncoded}?lockHandle=${encodeURIComponent(lockHandle)}${corrNrParam}`;
|
|
77
|
-
if (!args.type_kind) {
|
|
78
|
-
throw new Error('type_kind is required. Must be one of: domain, predefinedAbapType, refToPredefinedAbapType, refToDictionaryType, refToClifType');
|
|
79
|
-
}
|
|
80
|
-
// Validate required parameters based on type_kind
|
|
81
|
-
// predefinedAbapType and refToPredefinedAbapType require data_type
|
|
82
|
-
// Other types (domain, refToDictionaryType, refToClifType) require type_name
|
|
83
|
-
if (args.type_kind === 'predefinedAbapType' ||
|
|
84
|
-
args.type_kind === 'refToPredefinedAbapType') {
|
|
85
|
-
if (!args.data_type) {
|
|
86
|
-
throw new Error(`data_type is required when type_kind is '${args.type_kind}'. Provide data type (e.g., CHAR, NUMC, INT4).`);
|
|
87
|
-
}
|
|
85
|
+
function patchDataElementXml(currentXml, args) {
|
|
86
|
+
let xml = currentXml;
|
|
87
|
+
// Description
|
|
88
|
+
if (args.description) {
|
|
89
|
+
const description = (0, internalUtils_1.limitDescription)(args.description);
|
|
90
|
+
xml = (0, xmlPatch_1.patchXmlAttribute)(xml, 'adtcore:description', description);
|
|
88
91
|
}
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
// Type information
|
|
93
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.type_kind, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'dtel:typeKind', val));
|
|
94
|
+
// typeName — handle domain type: use type_name or data_type as domain name
|
|
95
|
+
if (args.type_kind || args.type_name || args.data_type) {
|
|
96
|
+
let typeName = '';
|
|
91
97
|
if (args.type_kind === 'domain') {
|
|
92
|
-
|
|
93
|
-
if (!args.type_name && !args.data_type) {
|
|
94
|
-
throw new Error(`type_name (domain name) is required when type_kind is 'domain'. Provide domain name (e.g., ZOK_AUTH_ID).`);
|
|
95
|
-
}
|
|
98
|
+
typeName = (args.type_name || args.data_type || '').toUpperCase();
|
|
96
99
|
}
|
|
97
|
-
else {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
else if (args.type_name) {
|
|
101
|
+
typeName = args.type_name.toUpperCase();
|
|
102
|
+
}
|
|
103
|
+
if (typeName) {
|
|
104
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:typeName', typeName);
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<dtel:longFieldLength>${longLength}</dtel:longFieldLength>
|
|
176
|
-
<dtel:longFieldMaxLength>${longMaxLength}</dtel:longFieldMaxLength>
|
|
177
|
-
<dtel:headingFieldLabel>${headingLabel}</dtel:headingFieldLabel>
|
|
178
|
-
<dtel:headingFieldLength>${headingLength}</dtel:headingFieldLength>
|
|
179
|
-
<dtel:headingFieldMaxLength>${headingMaxLength}</dtel:headingFieldMaxLength>
|
|
180
|
-
${searchHelp ? `<dtel:searchHelp>${searchHelp}</dtel:searchHelp>` : '<dtel:searchHelp/>'}
|
|
181
|
-
${searchHelpParameter ? `<dtel:searchHelpParameter>${searchHelpParameter}</dtel:searchHelpParameter>` : '<dtel:searchHelpParameter/>'}
|
|
182
|
-
${setGetParameter ? `<dtel:setGetParameter>${setGetParameter}</dtel:setGetParameter>` : '<dtel:setGetParameter/>'}
|
|
183
|
-
${defaultComponentName ? `<dtel:defaultComponentName>${defaultComponentName}</dtel:defaultComponentName>` : '<dtel:defaultComponentName/>'}
|
|
184
|
-
<dtel:deactivateInputHistory>${deactivateInputHistory}</dtel:deactivateInputHistory>
|
|
185
|
-
<dtel:changeDocument>${changeDocument}</dtel:changeDocument>
|
|
186
|
-
<dtel:leftToRightDirection>${leftToRightDirection}</dtel:leftToRightDirection>
|
|
187
|
-
<dtel:deactivateBIDIFiltering>${deactivateBIDIFiltering}</dtel:deactivateBIDIFiltering>
|
|
188
|
-
</dtel:dataElement>
|
|
189
|
-
</blue:wbobj>`;
|
|
190
|
-
const headers = {
|
|
191
|
-
Accept: contentTypes_1.ACCEPT_DATA_ELEMENT,
|
|
192
|
-
'Content-Type': 'application/vnd.sap.adt.dataelements.v2+xml; charset=utf-8',
|
|
193
|
-
};
|
|
194
|
-
// Debug: log XML when DEBUG_ADT_LIBS is enabled (formatted for readability)
|
|
107
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.data_type, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'dtel:dataType', val));
|
|
108
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.length, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'dtel:dataTypeLength', String(val).padStart(6, '0')));
|
|
109
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.decimals, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'dtel:dataTypeDecimals', String(val).padStart(6, '0')));
|
|
110
|
+
// Labels
|
|
111
|
+
if (args.short_label !== undefined) {
|
|
112
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:shortFieldLabel', args.short_label);
|
|
113
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:shortFieldLength', String(args.short_label.length || 10));
|
|
114
|
+
}
|
|
115
|
+
if (args.medium_label !== undefined) {
|
|
116
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:mediumFieldLabel', args.medium_label);
|
|
117
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:mediumFieldLength', String(args.medium_label.length || 20));
|
|
118
|
+
}
|
|
119
|
+
if (args.long_label !== undefined) {
|
|
120
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:longFieldLabel', args.long_label);
|
|
121
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:longFieldLength', String(args.long_label.length || 40));
|
|
122
|
+
}
|
|
123
|
+
if (args.heading_label !== undefined) {
|
|
124
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:headingFieldLabel', args.heading_label);
|
|
125
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:headingFieldLength', String(args.heading_label.length || 55));
|
|
126
|
+
}
|
|
127
|
+
// Optional fields
|
|
128
|
+
if (args.search_help !== undefined) {
|
|
129
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:searchHelp', args.search_help);
|
|
130
|
+
}
|
|
131
|
+
if (args.search_help_parameter !== undefined) {
|
|
132
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:searchHelpParameter', args.search_help_parameter);
|
|
133
|
+
}
|
|
134
|
+
if (args.set_get_parameter !== undefined) {
|
|
135
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:setGetParameter', args.set_get_parameter);
|
|
136
|
+
}
|
|
137
|
+
if (args.default_component_name !== undefined) {
|
|
138
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:defaultComponentName', args.default_component_name);
|
|
139
|
+
}
|
|
140
|
+
if (args.deactivate_input_history !== undefined) {
|
|
141
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:deactivateInputHistory', String(args.deactivate_input_history));
|
|
142
|
+
}
|
|
143
|
+
if (args.change_document !== undefined) {
|
|
144
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:changeDocument', String(args.change_document));
|
|
145
|
+
}
|
|
146
|
+
if (args.left_to_right_direction !== undefined) {
|
|
147
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:leftToRightDirection', String(args.left_to_right_direction));
|
|
148
|
+
}
|
|
149
|
+
if (args.deactivate_bidi_filtering !== undefined) {
|
|
150
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'dtel:deactivateBIDIFiltering', String(args.deactivate_bidi_filtering));
|
|
151
|
+
}
|
|
152
|
+
return xml;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Update data element - atomic PUT operation (read-modify-write pattern)
|
|
156
|
+
* NOTE: Requires object to be locked first via lockDataElement()
|
|
157
|
+
* NOTE: Caller should call connection.setSessionType("stateful") before locking
|
|
158
|
+
*/
|
|
159
|
+
async function updateDataElement(connection, params, lockHandle, logger) {
|
|
160
|
+
if (!params.data_element_name) {
|
|
161
|
+
throw new Error('Data element name is required');
|
|
162
|
+
}
|
|
163
|
+
if (!params.package_name) {
|
|
164
|
+
throw new Error('Package name is required');
|
|
165
|
+
}
|
|
166
|
+
const dataElementNameEncoded = (0, internalUtils_1.encodeSapObjectName)(params.data_element_name.toLowerCase());
|
|
167
|
+
// 1. GET current XML
|
|
168
|
+
const currentResponse = await connection.makeAdtRequest({
|
|
169
|
+
url: `/sap/bc/adt/ddic/dataelements/${dataElementNameEncoded}`,
|
|
170
|
+
method: 'GET',
|
|
171
|
+
timeout: (0, timeouts_1.getTimeout)('default'),
|
|
172
|
+
headers: { Accept: contentTypes_1.ACCEPT_DATA_ELEMENT },
|
|
173
|
+
});
|
|
174
|
+
const currentXml = (0, xmlPatch_1.extractXmlString)(currentResponse.data);
|
|
175
|
+
// 2. Patch only changed fields
|
|
176
|
+
const updatedXml = patchDataElementXml(currentXml, params);
|
|
177
|
+
// Debug: log XML when DEBUG_ADT_LIBS is enabled
|
|
195
178
|
if (debugEnabled) {
|
|
196
179
|
logger?.debug?.('[UPDATE XML]');
|
|
197
|
-
// Format XML with indentation for readability
|
|
198
180
|
try {
|
|
199
|
-
const { XMLParser, XMLBuilder } = require('fast-xml-parser');
|
|
181
|
+
const { XMLParser, XMLBuilder } = await Promise.resolve().then(() => __importStar(require('fast-xml-parser')));
|
|
200
182
|
const parser = new XMLParser({
|
|
201
183
|
ignoreAttributes: false,
|
|
202
184
|
attributeNamePrefix: '',
|
|
@@ -207,46 +189,34 @@ async function updateDataElementInternal(connection, args, lockHandle, username,
|
|
|
207
189
|
format: true,
|
|
208
190
|
indentBy: ' ',
|
|
209
191
|
});
|
|
210
|
-
const parsed = parser.parse(
|
|
192
|
+
const parsed = parser.parse(updatedXml);
|
|
211
193
|
const formatted = builder.build(parsed);
|
|
212
194
|
logger?.debug?.(formatted);
|
|
213
195
|
}
|
|
214
196
|
catch {
|
|
215
|
-
|
|
216
|
-
logger?.debug?.(xmlBody);
|
|
197
|
+
logger?.debug?.(updatedXml);
|
|
217
198
|
}
|
|
218
199
|
}
|
|
200
|
+
// 3. PUT
|
|
201
|
+
const corrNrParam = params.transport_request
|
|
202
|
+
? `&corrNr=${params.transport_request}`
|
|
203
|
+
: '';
|
|
204
|
+
const url = `/sap/bc/adt/ddic/dataelements/${dataElementNameEncoded}?lockHandle=${encodeURIComponent(lockHandle)}${corrNrParam}`;
|
|
205
|
+
const headers = {
|
|
206
|
+
Accept: contentTypes_1.ACCEPT_DATA_ELEMENT,
|
|
207
|
+
'Content-Type': 'application/vnd.sap.adt.dataelements.v2+xml; charset=utf-8',
|
|
208
|
+
};
|
|
219
209
|
return connection.makeAdtRequest({
|
|
220
210
|
url,
|
|
221
211
|
method: 'PUT',
|
|
222
212
|
timeout: (0, timeouts_1.getTimeout)('default'),
|
|
223
|
-
data:
|
|
213
|
+
data: updatedXml,
|
|
224
214
|
headers,
|
|
225
215
|
});
|
|
226
216
|
}
|
|
227
217
|
/**
|
|
228
|
-
*
|
|
229
|
-
* NOTE: Requires object to be locked first via lockDataElement()
|
|
230
|
-
* NOTE: Caller should call connection.setSessionType("stateful") before locking
|
|
218
|
+
* @deprecated Use updateDataElement directly. Kept for backward compatibility.
|
|
231
219
|
*/
|
|
232
|
-
async function
|
|
233
|
-
|
|
234
|
-
throw new Error('Data element name is required');
|
|
235
|
-
}
|
|
236
|
-
if (!params.package_name) {
|
|
237
|
-
throw new Error('Package name is required');
|
|
238
|
-
}
|
|
239
|
-
if (!params.type_kind) {
|
|
240
|
-
throw new Error('type_kind is required. Must be one of: domain, predefinedAbapType, refToPredefinedAbapType, refToDictionaryType, refToClifType');
|
|
241
|
-
}
|
|
242
|
-
// Get system information for username
|
|
243
|
-
const systemInfo = await (0, systemInfo_1.getSystemInformation)(connection);
|
|
244
|
-
const username = systemInfo?.userName || '';
|
|
245
|
-
// Use provided values directly - no automatic determination
|
|
246
|
-
const domainInfo = {
|
|
247
|
-
dataType: params.data_type || '',
|
|
248
|
-
length: params.length || 0,
|
|
249
|
-
decimals: params.decimals || 0,
|
|
250
|
-
};
|
|
251
|
-
return updateDataElementInternal(connection, params, lockHandle, username, domainInfo, logger);
|
|
220
|
+
async function updateDataElementInternal(connection, args, lockHandle, _username, _domainInfo, logger) {
|
|
221
|
+
return updateDataElement(connection, args, lockHandle, logger);
|
|
252
222
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Domain update operations
|
|
3
|
+
*
|
|
4
|
+
* Uses read-modify-write pattern: GET current XML → patch fields → PUT.
|
|
5
|
+
* This preserves all SAP-managed fields that would be lost if XML were built from scratch.
|
|
3
6
|
*/
|
|
4
7
|
import type { IAdtResponse as AxiosResponse, IAbapConnection } from '@mcp-abap-adt/interfaces';
|
|
5
8
|
import type { IUpdateDomainParams } from './types';
|
|
6
9
|
/**
|
|
7
|
-
* Update domain with new data
|
|
10
|
+
* Update domain with new data (read-modify-write pattern)
|
|
8
11
|
*
|
|
9
12
|
* NOTE: Requires stateful session mode enabled via connection.setSessionType("stateful")
|
|
10
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/core/domain/update.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/core/domain/update.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,IAAI,aAAa,EAC7B,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAelC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAsEnD;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,eAAe,EAC3B,IAAI,EAAE,mBAAmB,EACzB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAiCxB"}
|
|
@@ -1,72 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Domain update operations
|
|
4
|
+
*
|
|
5
|
+
* Uses read-modify-write pattern: GET current XML → patch fields → PUT.
|
|
6
|
+
* This preserves all SAP-managed fields that would be lost if XML were built from scratch.
|
|
4
7
|
*/
|
|
5
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
9
|
exports.updateDomain = updateDomain;
|
|
7
10
|
const contentTypes_1 = require("../../constants/contentTypes");
|
|
8
11
|
const internalUtils_1 = require("../../utils/internalUtils");
|
|
9
12
|
const timeouts_1 = require("../../utils/timeouts");
|
|
13
|
+
const xmlPatch_1 = require("../../utils/xmlPatch");
|
|
14
|
+
/**
|
|
15
|
+
* Patch current domain XML with updated values.
|
|
16
|
+
* Only modifies fields that are explicitly provided in args.
|
|
17
|
+
*/
|
|
18
|
+
function patchDomainXml(currentXml, args) {
|
|
19
|
+
let xml = currentXml;
|
|
20
|
+
// Description
|
|
21
|
+
if (args.description) {
|
|
22
|
+
const description = (0, internalUtils_1.limitDescription)(args.description);
|
|
23
|
+
xml = (0, xmlPatch_1.patchXmlAttribute)(xml, 'adtcore:description', description);
|
|
24
|
+
}
|
|
25
|
+
// Type information
|
|
26
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.datatype, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'doma:datatype', val));
|
|
27
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.length, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'doma:length', String(val)));
|
|
28
|
+
xml = (0, xmlPatch_1.patchIf)(xml, args.decimals, (x, val) => (0, xmlPatch_1.patchXmlElement)(x, 'doma:decimals', String(val)));
|
|
29
|
+
// Output information
|
|
30
|
+
if (args.conversion_exit !== undefined) {
|
|
31
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'doma:conversionExit', args.conversion_exit || '');
|
|
32
|
+
}
|
|
33
|
+
if (args.sign_exists !== undefined) {
|
|
34
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'doma:signExists', String(args.sign_exists));
|
|
35
|
+
}
|
|
36
|
+
if (args.lowercase !== undefined) {
|
|
37
|
+
xml = (0, xmlPatch_1.patchXmlElement)(xml, 'doma:lowercase', String(args.lowercase));
|
|
38
|
+
}
|
|
39
|
+
// Value table
|
|
40
|
+
if (args.value_table !== undefined) {
|
|
41
|
+
xml = (0, xmlPatch_1.patchXmlElementAttribute)(xml, 'doma:valueTableRef', 'adtcore:name', args.value_table || '');
|
|
42
|
+
}
|
|
43
|
+
// Fixed values — replace entire block
|
|
44
|
+
if (args.fixed_values !== undefined) {
|
|
45
|
+
if (args.fixed_values && args.fixed_values.length > 0) {
|
|
46
|
+
const fixValueItems = args.fixed_values
|
|
47
|
+
.map((fv) => ` <doma:fixValue>\n <doma:low>${fv.low}</doma:low>\n <doma:text>${fv.text}</doma:text>\n </doma:fixValue>`)
|
|
48
|
+
.join('\n');
|
|
49
|
+
const fixValuesBlock = `<doma:fixValues>\n${fixValueItems}\n </doma:fixValues>`;
|
|
50
|
+
xml = (0, xmlPatch_1.patchXmlBlock)(xml, 'doma:fixValues', fixValuesBlock);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
xml = (0, xmlPatch_1.patchXmlBlock)(xml, 'doma:fixValues', '<doma:fixValues/>');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return xml;
|
|
57
|
+
}
|
|
10
58
|
/**
|
|
11
|
-
* Update domain with new data
|
|
59
|
+
* Update domain with new data (read-modify-write pattern)
|
|
12
60
|
*
|
|
13
61
|
* NOTE: Requires stateful session mode enabled via connection.setSessionType("stateful")
|
|
14
62
|
*/
|
|
15
63
|
async function updateDomain(connection, args, lockHandle) {
|
|
16
64
|
const domainNameEncoded = (0, internalUtils_1.encodeSapObjectName)(args.domain_name.toLowerCase());
|
|
65
|
+
// 1. GET current XML
|
|
66
|
+
const currentResponse = await connection.makeAdtRequest({
|
|
67
|
+
url: `/sap/bc/adt/ddic/domains/${domainNameEncoded}`,
|
|
68
|
+
method: 'GET',
|
|
69
|
+
timeout: (0, timeouts_1.getTimeout)('default'),
|
|
70
|
+
headers: { Accept: contentTypes_1.ACCEPT_DOMAIN },
|
|
71
|
+
});
|
|
72
|
+
const currentXml = (0, xmlPatch_1.extractXmlString)(currentResponse.data);
|
|
73
|
+
// 2. Patch only changed fields
|
|
74
|
+
const updatedXml = patchDomainXml(currentXml, args);
|
|
75
|
+
// 3. PUT
|
|
17
76
|
const corrNrParam = args.transport_request
|
|
18
77
|
? `&corrNr=${args.transport_request}`
|
|
19
78
|
: '';
|
|
20
79
|
const url = `/sap/bc/adt/ddic/domains/${domainNameEncoded}?lockHandle=${encodeURIComponent(lockHandle)}${corrNrParam}`;
|
|
21
|
-
const datatype = args.datatype || 'CHAR';
|
|
22
|
-
const length = args.length || 100;
|
|
23
|
-
const decimals = args.decimals || 0;
|
|
24
|
-
let fixValuesXml = '';
|
|
25
|
-
if (args.fixed_values && args.fixed_values.length > 0) {
|
|
26
|
-
const fixValueItems = args.fixed_values
|
|
27
|
-
.map((fv) => ` <doma:fixValue>\n <doma:low>${fv.low}</doma:low>\n <doma:text>${fv.text}</doma:text>\n </doma:fixValue>`)
|
|
28
|
-
.join('\n');
|
|
29
|
-
fixValuesXml = ` <doma:fixValues>\n${fixValueItems}\n </doma:fixValues>`;
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
fixValuesXml = ' <doma:fixValues/>';
|
|
33
|
-
}
|
|
34
|
-
// Description is limited to 60 characters in SAP ADT
|
|
35
|
-
const description = (0, internalUtils_1.limitDescription)(args.description || args.domain_name);
|
|
36
|
-
const masterSystemAttr = args.masterSystem
|
|
37
|
-
? ` adtcore:masterSystem="${args.masterSystem}"`
|
|
38
|
-
: '';
|
|
39
|
-
const responsibleAttr = args.responsible
|
|
40
|
-
? ` adtcore:responsible="${args.responsible}"`
|
|
41
|
-
: '';
|
|
42
|
-
const xmlBody = `<?xml version="1.0" encoding="UTF-8"?>
|
|
43
|
-
<doma:domain xmlns:doma="http://www.sap.com/dictionary/domain"
|
|
44
|
-
xmlns:adtcore="http://www.sap.com/adt/core"
|
|
45
|
-
adtcore:description="${description}"
|
|
46
|
-
adtcore:language="EN"
|
|
47
|
-
adtcore:name="${args.domain_name.toUpperCase()}"
|
|
48
|
-
adtcore:type="DOMA/DD"
|
|
49
|
-
adtcore:masterLanguage="EN"${masterSystemAttr}${responsibleAttr}>
|
|
50
|
-
<adtcore:packageRef adtcore:name="${args.package_name.toUpperCase()}"/>
|
|
51
|
-
<doma:content>
|
|
52
|
-
<doma:typeInformation>
|
|
53
|
-
<doma:datatype>${datatype}</doma:datatype>
|
|
54
|
-
<doma:length>${length}</doma:length>
|
|
55
|
-
<doma:decimals>${decimals}</doma:decimals>
|
|
56
|
-
</doma:typeInformation>
|
|
57
|
-
<doma:outputInformation>
|
|
58
|
-
<doma:length>${length}</doma:length>
|
|
59
|
-
<doma:conversionExit>${args.conversion_exit || ''}</doma:conversionExit>
|
|
60
|
-
<doma:signExists>${args.sign_exists || false}</doma:signExists>
|
|
61
|
-
<doma:lowercase>${args.lowercase || false}</doma:lowercase>
|
|
62
|
-
</doma:outputInformation>
|
|
63
|
-
<doma:valueInformation>
|
|
64
|
-
<doma:valueTableRef adtcore:name="${args.value_table || ''}"/>
|
|
65
|
-
<doma:appendExists>false</doma:appendExists>
|
|
66
|
-
${fixValuesXml}
|
|
67
|
-
</doma:valueInformation>
|
|
68
|
-
</doma:content>
|
|
69
|
-
</doma:domain>`;
|
|
70
80
|
const headers = {
|
|
71
81
|
Accept: contentTypes_1.ACCEPT_DOMAIN,
|
|
72
82
|
'Content-Type': 'application/vnd.sap.adt.domains.v2+xml; charset=utf-8',
|
|
@@ -75,7 +85,7 @@ ${fixValuesXml}
|
|
|
75
85
|
url,
|
|
76
86
|
method: 'PUT',
|
|
77
87
|
timeout: (0, timeouts_1.getTimeout)('default'),
|
|
78
|
-
data:
|
|
88
|
+
data: updatedXml,
|
|
79
89
|
headers,
|
|
80
90
|
});
|
|
81
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/core/functionGroup/update.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,IAAI,aAAa,EAE7B,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/core/functionGroup/update.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,IAAI,aAAa,EAE7B,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AA2C1D;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,0BAA0B,EAClC,YAAY,CAAC,EAAE,gBAAgB,GAC9B,OAAO,CAAC,aAAa,CAAC,CAmGxB"}
|