arc-1 0.6.7 → 0.6.8
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/adt/client.d.ts +2 -0
- package/dist/adt/client.d.ts.map +1 -1
- package/dist/adt/client.js +7 -0
- package/dist/adt/client.js.map +1 -1
- package/dist/adt/ddic-xml.d.ts +16 -0
- package/dist/adt/ddic-xml.d.ts.map +1 -1
- package/dist/adt/ddic-xml.js +79 -0
- package/dist/adt/ddic-xml.js.map +1 -1
- package/dist/adt/http.d.ts.map +1 -1
- package/dist/adt/http.js +21 -4
- package/dist/adt/http.js.map +1 -1
- package/dist/adt/refactoring.d.ts +60 -0
- package/dist/adt/refactoring.d.ts.map +1 -0
- package/dist/adt/refactoring.js +117 -0
- package/dist/adt/refactoring.js.map +1 -0
- package/dist/handlers/intent.d.ts.map +1 -1
- package/dist/handlers/intent.js +149 -6
- package/dist/handlers/intent.js.map +1 -1
- package/dist/handlers/schemas.d.ts +18 -0
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +16 -0
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +44 -6
- package/dist/handlers/tools.js.map +1 -1
- package/dist/server/server.d.ts +1 -1
- package/dist/server/server.js +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADT Refactoring API — Change Package Assignment.
|
|
3
|
+
*
|
|
4
|
+
* Moves ABAP objects between packages via the ADT refactoring endpoint.
|
|
5
|
+
* Two-step flow: preview (validate + discover transport) then execute.
|
|
6
|
+
*
|
|
7
|
+
* Endpoint: POST /sap/bc/adt/refactorings
|
|
8
|
+
* - Preview: ?step=preview&rel=http://www.sap.com/adt/relations/refactoring/changepackage
|
|
9
|
+
* - Execute: ?step=execute
|
|
10
|
+
*
|
|
11
|
+
* Preview uses "wrapped" XML (outer changePackageRefactoring element).
|
|
12
|
+
* Execute uses "unwrapped" XML (just genericRefactoring element).
|
|
13
|
+
*/
|
|
14
|
+
import { checkOperation, OperationType } from './safety.js';
|
|
15
|
+
const NS_CHANGEPACKAGE = 'http://www.sap.com/adt/refactoring/changepackagerefactoring';
|
|
16
|
+
const NS_GENERIC = 'http://www.sap.com/adt/refactoring/genericrefactoring';
|
|
17
|
+
const NS_ADTCORE = 'http://www.sap.com/adt/core';
|
|
18
|
+
/** Escape XML special characters */
|
|
19
|
+
function escapeXml(s) {
|
|
20
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
21
|
+
}
|
|
22
|
+
/** Build the inner genericRefactoring XML fragment (shared by preview and execute) */
|
|
23
|
+
function buildGenericRefactoringInner(params) {
|
|
24
|
+
const desc = escapeXml(params.description ?? 'ABAP Object');
|
|
25
|
+
const transport = params.transport ?? '';
|
|
26
|
+
return [
|
|
27
|
+
`<generic:title>Change Package</generic:title>`,
|
|
28
|
+
`<generic:adtObjectUri>${escapeXml(params.objectUri)}</generic:adtObjectUri>`,
|
|
29
|
+
`<generic:affectedObjects>`,
|
|
30
|
+
`<generic:affectedObject`,
|
|
31
|
+
` adtcore:description="${desc}"`,
|
|
32
|
+
` adtcore:name="${escapeXml(params.objectName)}"`,
|
|
33
|
+
` adtcore:packageName="${escapeXml(params.oldPackage)}"`,
|
|
34
|
+
` adtcore:type="${escapeXml(params.objectType)}"`,
|
|
35
|
+
` adtcore:uri="${escapeXml(params.objectUri)}">`,
|
|
36
|
+
`<generic:userContent/>`,
|
|
37
|
+
`<generic:changePackageDelta>`,
|
|
38
|
+
`<generic:newPackage>${escapeXml(params.newPackage)}</generic:newPackage>`,
|
|
39
|
+
`</generic:changePackageDelta>`,
|
|
40
|
+
`</generic:affectedObject>`,
|
|
41
|
+
`</generic:affectedObjects>`,
|
|
42
|
+
`<generic:transport>${escapeXml(transport)}</generic:transport>`,
|
|
43
|
+
`<generic:ignoreSyntaxErrorsAllowed>false</generic:ignoreSyntaxErrorsAllowed>`,
|
|
44
|
+
`<generic:ignoreSyntaxErrors>false</generic:ignoreSyntaxErrors>`,
|
|
45
|
+
`<generic:userContent/>`,
|
|
46
|
+
].join('');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Build "wrapped" preview XML.
|
|
50
|
+
* Root: <changepackage:changePackageRefactoring> with inner <generic:genericRefactoring>.
|
|
51
|
+
*/
|
|
52
|
+
export function buildPreviewXml(params) {
|
|
53
|
+
return [
|
|
54
|
+
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
55
|
+
`<changepackage:changePackageRefactoring`,
|
|
56
|
+
` xmlns:adtcore="${NS_ADTCORE}"`,
|
|
57
|
+
` xmlns:generic="${NS_GENERIC}"`,
|
|
58
|
+
` xmlns:changepackage="${NS_CHANGEPACKAGE}">`,
|
|
59
|
+
`<changepackage:oldPackage>${escapeXml(params.oldPackage)}</changepackage:oldPackage>`,
|
|
60
|
+
`<changepackage:newPackage>${escapeXml(params.newPackage)}</changepackage:newPackage>`,
|
|
61
|
+
`<generic:genericRefactoring>`,
|
|
62
|
+
buildGenericRefactoringInner(params),
|
|
63
|
+
`</generic:genericRefactoring>`,
|
|
64
|
+
`<changepackage:userContent/>`,
|
|
65
|
+
`</changepackage:changePackageRefactoring>`,
|
|
66
|
+
].join('');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build "unwrapped" execute XML.
|
|
70
|
+
* Root: <generic:genericRefactoring> (no changePackageRefactoring wrapper).
|
|
71
|
+
*/
|
|
72
|
+
export function buildExecuteXml(params) {
|
|
73
|
+
return [
|
|
74
|
+
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
75
|
+
`<generic:genericRefactoring`,
|
|
76
|
+
` xmlns:generic="${NS_GENERIC}"`,
|
|
77
|
+
` xmlns:adtcore="${NS_ADTCORE}">`,
|
|
78
|
+
buildGenericRefactoringInner(params),
|
|
79
|
+
`</generic:genericRefactoring>`,
|
|
80
|
+
].join('');
|
|
81
|
+
}
|
|
82
|
+
/** Extract transport value from preview response XML */
|
|
83
|
+
export function parsePreviewResponse(xml) {
|
|
84
|
+
const match = xml.match(/<generic:transport>([^<]*)<\/generic:transport>/);
|
|
85
|
+
if (!match) {
|
|
86
|
+
// Try without namespace prefix (SAP may strip them)
|
|
87
|
+
const fallback = xml.match(/<transport>([^<]*)<\/transport>/);
|
|
88
|
+
const value = fallback?.[1]?.trim();
|
|
89
|
+
return { transport: value || undefined };
|
|
90
|
+
}
|
|
91
|
+
const value = match[1]?.trim();
|
|
92
|
+
return { transport: value || undefined };
|
|
93
|
+
}
|
|
94
|
+
const PREVIEW_URL = '/sap/bc/adt/refactorings?step=preview&rel=http://www.sap.com/adt/relations/refactoring/changepackage';
|
|
95
|
+
const EXECUTE_URL = '/sap/bc/adt/refactorings?step=execute';
|
|
96
|
+
/**
|
|
97
|
+
* Move an ABAP object to a different package via the ADT refactoring API.
|
|
98
|
+
*
|
|
99
|
+
* Two-step flow:
|
|
100
|
+
* 1. Preview: validates the operation, returns server-assigned transport (if any)
|
|
101
|
+
* 2. Execute: performs the actual TADIR change
|
|
102
|
+
*/
|
|
103
|
+
export async function changePackage(http, safety, params) {
|
|
104
|
+
checkOperation(safety, OperationType.Update, 'ChangePackage');
|
|
105
|
+
// Step 1: Preview
|
|
106
|
+
const previewXml = buildPreviewXml(params);
|
|
107
|
+
const previewResp = await http.post(PREVIEW_URL, previewXml, 'application/*', { Accept: 'application/*' });
|
|
108
|
+
const preview = parsePreviewResponse(previewResp.body);
|
|
109
|
+
// Merge transport: explicit param > preview response > empty
|
|
110
|
+
const effectiveTransport = params.transport || preview.transport || '';
|
|
111
|
+
const executeParams = { ...params, transport: effectiveTransport };
|
|
112
|
+
// Step 2: Execute
|
|
113
|
+
const executeXml = buildExecuteXml(executeParams);
|
|
114
|
+
await http.post(EXECUTE_URL, executeXml, 'application/*', { Accept: 'application/*' });
|
|
115
|
+
return { transport: effectiveTransport || undefined };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=refactoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refactoring.js","sourceRoot":"","sources":["../../src/adt/refactoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/handlers/intent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/handlers/intent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAkFlD,OAAO,KAAK,EAAkB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAc9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,2BAA2B;AAC3B,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAY9C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CASnF;AAeD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAe1F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASzD;AA2KD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,CAAC,EAAE,QAAQ,EACnB,OAAO,CAAC,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,YAAY,EAC3B,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,UAAU,CAAC,CAsLrB;AAo0BD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAyB1E;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CA6NR;AAwCD,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIxD;AA+wDD,0CAA0C;AAC1C,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,CAE9E;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,IAAI,gBAAgB,GAAG,SAAS,CAEhE;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAEnE;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D"}
|
package/dist/handlers/intent.js
CHANGED
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { findDefinition, findReferences, findWhereUsed, getCompletion, } from '../adt/codeintel.js';
|
|
13
13
|
import { createObject, deleteObject, lockObject, safeUpdateObject, safeUpdateSource, unlockObject, updateObject, } from '../adt/crud.js';
|
|
14
|
-
import { buildDataElementXml, buildDomainXml, buildMessageClassXml, buildPackageXml, buildServiceBindingXml, } from '../adt/ddic-xml.js';
|
|
14
|
+
import { buildDataElementXml, buildDomainXml, buildMessageClassXml, buildPackageXml, buildServiceBindingXml, decodeKtdText, rewriteKtdText, } from '../adt/ddic-xml.js';
|
|
15
15
|
import { activate, activateBatch, applyFixProposal, getFixProposals, publishServiceBinding, runAtcCheck, runUnitTests, syntaxCheck, unpublishServiceBinding, } from '../adt/devtools.js';
|
|
16
16
|
import { getDump, getTraceDbAccesses, getTraceHitlist, getTraceStatements, listDumps, listTraces, } from '../adt/diagnostics.js';
|
|
17
17
|
import { AdtApiError, AdtNetworkError, AdtSafetyError, classifySapDomainError, isNotFoundError, } from '../adt/errors.js';
|
|
18
18
|
import { classifyTextSearchError, mapSapReleaseToAbaplintVersion, probeFeatures } from '../adt/features.js';
|
|
19
19
|
import { addTileToGroup, createCatalog, createGroup, createTile, deleteCatalog, listCatalogs, listGroups, listTiles, } from '../adt/flp.js';
|
|
20
|
+
import { changePackage } from '../adt/refactoring.js';
|
|
20
21
|
import { checkOperation, checkPackage, isOperationAllowed, OperationType } from '../adt/safety.js';
|
|
21
22
|
import { createTransport, deleteTransport, getTransport, getTransportInfo, listTransports, reassignTransport, releaseTransport, releaseTransportRecursive, } from '../adt/transport.js';
|
|
22
23
|
import { getAppInfo } from '../adt/ui5-repository.js';
|
|
@@ -591,6 +592,21 @@ async function handleSAPRead(client, args, cachingLayer) {
|
|
|
591
592
|
const { source, cacheHit } = await cachedGet('SRVB', name, () => client.getSrvb(name));
|
|
592
593
|
return cachedTextResult(source, cacheHit);
|
|
593
594
|
}
|
|
595
|
+
case 'SKTD': {
|
|
596
|
+
try {
|
|
597
|
+
// ADT returns a <sktd:docu> XML envelope with the Markdown body base64-encoded
|
|
598
|
+
// inside <sktd:text>. Cache the raw envelope (update flow re-uses it) and
|
|
599
|
+
// return the decoded Markdown to the LLM.
|
|
600
|
+
const { source, cacheHit } = await cachedGet('SKTD', name, () => client.getKtd(name));
|
|
601
|
+
return cachedTextResult(decodeKtdText(source), cacheHit);
|
|
602
|
+
}
|
|
603
|
+
catch (err) {
|
|
604
|
+
if (isNotFoundError(err)) {
|
|
605
|
+
return textResult(`No Knowledge Transfer Document (SKTD) found for "${name}". KTD docs are optional Markdown documentation attached to ABAP objects — either one was never created for "${name}", or the name is wrong.`);
|
|
606
|
+
}
|
|
607
|
+
throw err;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
594
610
|
case 'TABL': {
|
|
595
611
|
const { source, cacheHit } = await cachedGet('TABL', name, () => client.getTable(name));
|
|
596
612
|
return cachedTextResult(source, cacheHit);
|
|
@@ -747,7 +763,7 @@ async function handleSAPRead(client, args, cachingLayer) {
|
|
|
747
763
|
}
|
|
748
764
|
}
|
|
749
765
|
default:
|
|
750
|
-
return errorResult(`Unknown SAPRead type: "${type}". Supported types: PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DCLS, DDLX, BDEF, SRVD, SRVB, TABL, VIEW, STRU, DOMA, DTEL, TRAN, TABLE_CONTENTS, DEVC, SOBJ, SYSTEM, COMPONENTS, MESSAGES, TEXT_ELEMENTS, VARIANTS, BSP, BSP_DEPLOY, API_STATE, INACTIVE_OBJECTS. ` +
|
|
766
|
+
return errorResult(`Unknown SAPRead type: "${type}". Supported types: PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DCLS, DDLX, BDEF, SRVD, SRVB, SKTD, TABL, VIEW, STRU, DOMA, DTEL, TRAN, TABLE_CONTENTS, DEVC, SOBJ, SYSTEM, COMPONENTS, MESSAGES, TEXT_ELEMENTS, VARIANTS, BSP, BSP_DEPLOY, API_STATE, INACTIVE_OBJECTS. ` +
|
|
751
767
|
'Tip: Type aliases are auto-normalized (e.g., DDLS/DF → DDLS, DCLS/DL → DCLS, CLAS/OC → CLAS, PROG/P → PROG). ' +
|
|
752
768
|
'Do not pass a URI — use the "type" and "name" parameters instead.');
|
|
753
769
|
}
|
|
@@ -904,12 +920,13 @@ const DATAELEMENT_V2_CONTENT_TYPE = 'application/vnd.sap.adt.dataelements.v2+xml
|
|
|
904
920
|
const SERVICEBINDING_V2_CONTENT_TYPE = 'application/vnd.sap.adt.businessservices.servicebinding.v2+xml; charset=utf-8';
|
|
905
921
|
const BDEF_CONTENT_TYPE = 'application/vnd.sap.adt.blues.v1+xml';
|
|
906
922
|
const MESSAGECLASS_CONTENT_TYPE = 'application/vnd.sap.adt.mc.messageclass+xml';
|
|
923
|
+
const SKTD_V2_CONTENT_TYPE = 'application/vnd.sap.adt.sktdv2+xml';
|
|
907
924
|
function isMetadataWriteType(type) {
|
|
908
925
|
return type === 'DOMA' || type === 'DTEL' || type === 'MSAG' || type === 'SRVB';
|
|
909
926
|
}
|
|
910
927
|
/** Types that require a specific vendor content type for creation (not application/*) */
|
|
911
928
|
function needsVendorContentType(type) {
|
|
912
|
-
return type === 'DOMA' || type === 'DTEL' || type === 'BDEF' || type === 'MSAG';
|
|
929
|
+
return type === 'DOMA' || type === 'DTEL' || type === 'BDEF' || type === 'MSAG' || type === 'SKTD';
|
|
913
930
|
}
|
|
914
931
|
/** Content type used for create POST */
|
|
915
932
|
function createContentTypeForType(type) {
|
|
@@ -946,6 +963,8 @@ function vendorContentTypeForType(type) {
|
|
|
946
963
|
return BDEF_CONTENT_TYPE;
|
|
947
964
|
case 'MSAG':
|
|
948
965
|
return MESSAGECLASS_CONTENT_TYPE;
|
|
966
|
+
case 'SKTD':
|
|
967
|
+
return SKTD_V2_CONTENT_TYPE;
|
|
949
968
|
default:
|
|
950
969
|
// Wildcard lets the SAP server resolve the correct handler.
|
|
951
970
|
// Sending 'application/xml' causes 415 on DDL-based endpoints
|
|
@@ -1435,6 +1454,7 @@ const SLASH_TYPE_MAP = {
|
|
|
1435
1454
|
'DEVC/K': 'DEVC',
|
|
1436
1455
|
'TRAN/O': 'TRAN',
|
|
1437
1456
|
'VIEW/V': 'VIEW',
|
|
1457
|
+
'SKTD/TYP': 'SKTD',
|
|
1438
1458
|
};
|
|
1439
1459
|
/** Normalize ADT type codes and aliases to ARC-1 canonical short types. */
|
|
1440
1460
|
export function normalizeObjectType(type) {
|
|
@@ -1545,13 +1565,17 @@ function objectBasePath(type) {
|
|
|
1545
1565
|
return '/sap/bc/adt/packages/';
|
|
1546
1566
|
case 'TRAN':
|
|
1547
1567
|
return '/sap/bc/adt/vit/wb/object_type/trant/object_name/';
|
|
1568
|
+
case 'SKTD':
|
|
1569
|
+
return '/sap/bc/adt/documentation/ktd/documents/';
|
|
1548
1570
|
default:
|
|
1549
1571
|
return '/sap/bc/adt/programs/programs/';
|
|
1550
1572
|
}
|
|
1551
1573
|
}
|
|
1552
1574
|
/** Map object type + name to the ADT object URL used by CRUD/DevTools/etc. Name is URI-encoded. */
|
|
1553
1575
|
function objectUrlForType(type, name) {
|
|
1554
|
-
|
|
1576
|
+
// KTD endpoints require lowercase object names in the URL path (confirmed via Eclipse ADT trace).
|
|
1577
|
+
const effectiveName = type === 'SKTD' ? name.toLowerCase() : name;
|
|
1578
|
+
return `${objectBasePath(type)}${encodeURIComponent(effectiveName)}`;
|
|
1555
1579
|
}
|
|
1556
1580
|
/** Infer SAP object type from naming conventions. Returns empty string if type cannot be determined. */
|
|
1557
1581
|
function inferObjectType(name) {
|
|
@@ -1569,7 +1593,8 @@ function inferObjectType(name) {
|
|
|
1569
1593
|
* Used for API release state where the full URI is encoded as a single path segment by the caller.
|
|
1570
1594
|
*/
|
|
1571
1595
|
function objectUrlForTypeRaw(type, name) {
|
|
1572
|
-
|
|
1596
|
+
const effectiveName = type === 'SKTD' ? name.toLowerCase() : name;
|
|
1597
|
+
return `${objectBasePath(type)}${effectiveName}`;
|
|
1573
1598
|
}
|
|
1574
1599
|
/** Get the source URL for an object (appends /source/main) */
|
|
1575
1600
|
function sourceUrlForType(type, name) {
|
|
@@ -1602,6 +1627,19 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
1602
1627
|
switch (action) {
|
|
1603
1628
|
case 'update': {
|
|
1604
1629
|
const existingPackage = await enforcePackageForExistingObject();
|
|
1630
|
+
if (type === 'SKTD') {
|
|
1631
|
+
// KTD update requires the full <sktd:docu> XML envelope with the Markdown
|
|
1632
|
+
// body base64-encoded inside <sktd:text>, PUT with
|
|
1633
|
+
// `application/vnd.sap.adt.sktdv2+xml`. PUTting raw text/plain silently
|
|
1634
|
+
// no-ops (or 415s on strict systems). Fetch the current envelope,
|
|
1635
|
+
// replace only the <sktd:text> body, and PUT it back — preserves
|
|
1636
|
+
// responsible/masterLanguage/packageRef/refObject metadata.
|
|
1637
|
+
const currentEnvelope = await client.getKtd(name);
|
|
1638
|
+
const body = rewriteKtdText(currentEnvelope, source);
|
|
1639
|
+
await safeUpdateObject(client.http, client.safety, objectUrl, body, SKTD_V2_CONTENT_TYPE, transport);
|
|
1640
|
+
cachingLayer?.invalidate(type, name);
|
|
1641
|
+
return textResult(`Successfully updated ${type} ${name}.`);
|
|
1642
|
+
}
|
|
1605
1643
|
if (isMetadataWriteType(type)) {
|
|
1606
1644
|
// Metadata updates are full-XML-replace — we must fetch existing metadata
|
|
1607
1645
|
// and merge with provided fields so omitted fields keep their current values.
|
|
@@ -1675,6 +1713,45 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
1675
1713
|
if (!affResult.valid) {
|
|
1676
1714
|
return errorResult(`AFF metadata validation failed for ${type} ${name}:\n- ${(affResult.errors ?? []).join('\n- ')}\n\nFix the metadata and retry.`);
|
|
1677
1715
|
}
|
|
1716
|
+
if (type === 'SKTD') {
|
|
1717
|
+
// A KTD is not a standalone object — it documents a parent object (e.g., a DDLS view or a CLAS).
|
|
1718
|
+
// The create POST goes to the collection URL with a sktd:docu XML body that references the parent.
|
|
1719
|
+
const refType = String(args.refObjectType ?? '');
|
|
1720
|
+
if (!refType) {
|
|
1721
|
+
return errorResult('"refObjectType" is required for SKTD create — the ADT type+subtype of the parent object being documented (e.g., "DDLS/DF", "CLAS/OC", "PROG/P", "INTF/OI", "BDEF/BDO", "SRVD/SRV").');
|
|
1722
|
+
}
|
|
1723
|
+
const refName = String(args.refObjectName ?? name);
|
|
1724
|
+
// SAP rule: a KTD's own name must equal the parent object's name (one KTD per object).
|
|
1725
|
+
// Creating a KTD named differently from its parent fails server-side with a cryptic
|
|
1726
|
+
// "Check of condition failed" — fail fast with a clear message instead.
|
|
1727
|
+
if (refName.toUpperCase() !== name.toUpperCase()) {
|
|
1728
|
+
return errorResult(`SKTD name "${name}" must match refObjectName "${refName}" — a Knowledge Transfer Document inherits the name of the ABAP object it documents (one KTD per object). To document "${refName}", call SAPWrite(action="create", type="SKTD", name="${refName}", refObjectType="${refType}", ...).`);
|
|
1729
|
+
}
|
|
1730
|
+
const refDescription = String(args.refObjectDescription ?? '');
|
|
1731
|
+
// Build the parent URI. ADT URIs use lowercase names by convention (matches the Eclipse trace).
|
|
1732
|
+
const refParentType = refType.split('/')[0] ?? '';
|
|
1733
|
+
const refUri = `${objectBasePath(refParentType)}${encodeURIComponent(refName.toLowerCase())}`;
|
|
1734
|
+
const ktdBody = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1735
|
+
<sktd:docu xmlns:sktd="http://www.sap.com/wbobj/texts/sktd" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:language="EN" adtcore:name="${escapeXml(name)}" adtcore:type="SKTD/TYP" adtcore:masterLanguage="EN">
|
|
1736
|
+
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
1737
|
+
<sktd:refObject adtcore:description="${escapeXml(refDescription)}" adtcore:name="${escapeXml(refName)}" adtcore:type="${escapeXml(refType)}" adtcore:uri="${escapeXml(refUri)}"/>
|
|
1738
|
+
</sktd:docu>`;
|
|
1739
|
+
const ktdCreateUrl = '/sap/bc/adt/documentation/ktd/documents';
|
|
1740
|
+
const ktdResult = await createObject(client.http, client.safety, ktdCreateUrl, ktdBody, SKTD_V2_CONTENT_TYPE, effectiveTransport);
|
|
1741
|
+
// If initial Markdown was provided, follow up with an update PUT to write it.
|
|
1742
|
+
// Same envelope contract as the update path: fetch-then-rewrite ensures we
|
|
1743
|
+
// PUT back exactly the shape SAP gave us (with all the server-assigned
|
|
1744
|
+
// metadata), only swapping <sktd:text>.
|
|
1745
|
+
if (source) {
|
|
1746
|
+
const currentEnvelope = await client.getKtd(name);
|
|
1747
|
+
const body = rewriteKtdText(currentEnvelope, source);
|
|
1748
|
+
await safeUpdateObject(client.http, client.safety, objectUrl, body, SKTD_V2_CONTENT_TYPE, effectiveTransport);
|
|
1749
|
+
cachingLayer?.invalidate(type, name);
|
|
1750
|
+
return textResult(`Created SKTD ${name} in package ${pkg} and wrote Markdown content.\nNext step: SAPActivate(type="SKTD", name="${name}").\n${ktdResult}`);
|
|
1751
|
+
}
|
|
1752
|
+
cachingLayer?.invalidate(type, name);
|
|
1753
|
+
return textResult(`Created SKTD ${name} in package ${pkg} (no Markdown content written — pass "source" to write the body).\nNext step: SAPActivate(type="SKTD", name="${name}").\n${ktdResult}`);
|
|
1754
|
+
}
|
|
1678
1755
|
// Build type-specific creation XML body.
|
|
1679
1756
|
// SAP ADT requires the root element to match the object type —
|
|
1680
1757
|
// a generic objectReferences body returns 400 "System expected the element ...".
|
|
@@ -1785,7 +1862,7 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
1785
1862
|
}
|
|
1786
1863
|
case 'delete': {
|
|
1787
1864
|
await enforcePackageForExistingObject();
|
|
1788
|
-
// Lock, delete, unlock pattern — auto-propagate lock corrNr if no explicit transport
|
|
1865
|
+
// Lock, delete, unlock pattern (works for all types including SKTD) — auto-propagate lock corrNr if no explicit transport
|
|
1789
1866
|
await client.http.withStatefulSession(async (session) => {
|
|
1790
1867
|
const lock = await lockObject(session, client.safety, objectUrl);
|
|
1791
1868
|
const effectiveTransport = transport ?? (lock.corrNr || undefined);
|
|
@@ -2713,6 +2790,72 @@ async function handleSAPManage(client, config, args, cachingLayer, isPerUserClie
|
|
|
2713
2790
|
});
|
|
2714
2791
|
return textResult(`Deleted package ${name}.`);
|
|
2715
2792
|
}
|
|
2793
|
+
case 'change_package': {
|
|
2794
|
+
const objectName = String(args.objectName ?? '').trim();
|
|
2795
|
+
const objectType = String(args.objectType ?? '').trim();
|
|
2796
|
+
const oldPackage = String(args.oldPackage ?? '').trim();
|
|
2797
|
+
const newPackage = String(args.newPackage ?? '').trim();
|
|
2798
|
+
const transport = String(args.transport ?? '').trim();
|
|
2799
|
+
let objectUri = String(args.objectUri ?? '').trim();
|
|
2800
|
+
if (!objectName)
|
|
2801
|
+
return errorResult('"objectName" is required for change_package action.');
|
|
2802
|
+
if (!objectType)
|
|
2803
|
+
return errorResult('"objectType" is required for change_package action.');
|
|
2804
|
+
if (!oldPackage)
|
|
2805
|
+
return errorResult('"oldPackage" is required for change_package action.');
|
|
2806
|
+
if (!newPackage)
|
|
2807
|
+
return errorResult('"newPackage" is required for change_package action.');
|
|
2808
|
+
checkOperation(client.safety, OperationType.Update, 'ChangePackage');
|
|
2809
|
+
checkPackage(client.safety, oldPackage);
|
|
2810
|
+
checkPackage(client.safety, newPackage);
|
|
2811
|
+
// Resolve object URI via search if not provided
|
|
2812
|
+
if (!objectUri) {
|
|
2813
|
+
const searchResp = await client.http.get(`/sap/bc/adt/repository/informationsystem/search?operation=quickSearch&query=${encodeURIComponent(objectName)}&maxResults=10`);
|
|
2814
|
+
const uriMatch = searchResp.body.match(new RegExp(`adtcore:uri="([^"]*)"[^>]*adtcore:type="${objectType.replace('/', '\\/')}"`, 'i'));
|
|
2815
|
+
if (!uriMatch?.[1]) {
|
|
2816
|
+
return errorResult(`Could not find object "${objectName}" with type "${objectType}" via ADT search. ` +
|
|
2817
|
+
`Verify the object exists and the type is correct (e.g., CLAS/OC, DDLS/DF, PROG/P).`);
|
|
2818
|
+
}
|
|
2819
|
+
objectUri = uriMatch[1];
|
|
2820
|
+
}
|
|
2821
|
+
// Transport pre-flight for non-local target packages
|
|
2822
|
+
let effectiveTransport = transport || undefined;
|
|
2823
|
+
if (!effectiveTransport && newPackage.toUpperCase() !== '$TMP') {
|
|
2824
|
+
try {
|
|
2825
|
+
const transportInfo = await getTransportInfo(client.http, client.safety, objectUri, newPackage, 'I');
|
|
2826
|
+
if (transportInfo.lockedTransport) {
|
|
2827
|
+
effectiveTransport = transportInfo.lockedTransport;
|
|
2828
|
+
}
|
|
2829
|
+
else if (!transportInfo.isLocal && transportInfo.recording) {
|
|
2830
|
+
const existingList = transportInfo.existingTransports.length > 0
|
|
2831
|
+
? `\n\nExisting transports for this package:\n${transportInfo.existingTransports
|
|
2832
|
+
.slice(0, 10)
|
|
2833
|
+
.map((t) => ` - ${t.id}: ${t.description} (${t.owner})`)
|
|
2834
|
+
.join('\n')}`
|
|
2835
|
+
: '';
|
|
2836
|
+
return errorResult(`Package "${newPackage}" requires a transport number for change_package, but none was provided.\n\n` +
|
|
2837
|
+
`To fix this, either:\n` +
|
|
2838
|
+
`1. Use SAPTransport(action="list") to find an existing modifiable transport\n` +
|
|
2839
|
+
`2. Use SAPTransport(action="create", description="...") to create a new one\n` +
|
|
2840
|
+
`3. Then retry SAPManage(action="change_package", ..., transport="<transport_id>")` +
|
|
2841
|
+
existingList);
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
catch {
|
|
2845
|
+
// Graceful fallback: let SAP enforce transport requirements if the pre-check fails.
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
const result = await changePackage(client.http, client.safety, {
|
|
2849
|
+
objectUri,
|
|
2850
|
+
objectType,
|
|
2851
|
+
objectName,
|
|
2852
|
+
oldPackage,
|
|
2853
|
+
newPackage,
|
|
2854
|
+
transport: effectiveTransport,
|
|
2855
|
+
});
|
|
2856
|
+
const transportNote = result.transport ? ` (transport: ${result.transport})` : '';
|
|
2857
|
+
return textResult(`Moved ${objectName} from package ${oldPackage} to ${newPackage}${transportNote}.`);
|
|
2858
|
+
}
|
|
2716
2859
|
case 'flp_list_catalogs': {
|
|
2717
2860
|
const catalogs = await listCatalogs(client.http, client.safety);
|
|
2718
2861
|
const customCount = catalogs.filter((c) => /^(Z|Y)/i.test(c.domainId)).length;
|