arc-1 0.9.8 → 0.9.9
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 +28 -1
- package/dist/adt/client.d.ts.map +1 -1
- package/dist/adt/client.js +75 -2
- package/dist/adt/client.js.map +1 -1
- package/dist/adt/ddic-xml.d.ts +18 -0
- package/dist/adt/ddic-xml.d.ts.map +1 -1
- package/dist/adt/ddic-xml.js +21 -4
- package/dist/adt/ddic-xml.js.map +1 -1
- package/dist/adt/devtools.d.ts.map +1 -1
- package/dist/adt/devtools.js +29 -13
- package/dist/adt/devtools.js.map +1 -1
- package/dist/adt/http.d.ts +4 -0
- package/dist/adt/http.d.ts.map +1 -1
- package/dist/adt/http.js +8 -0
- package/dist/adt/http.js.map +1 -1
- package/dist/adt/transport.d.ts +75 -2
- package/dist/adt/transport.d.ts.map +1 -1
- package/dist/adt/transport.js +148 -2
- package/dist/adt/transport.js.map +1 -1
- package/dist/adt/types.d.ts +20 -0
- package/dist/adt/types.d.ts.map +1 -1
- package/dist/adt/xml-parser.d.ts +11 -5
- package/dist/adt/xml-parser.d.ts.map +1 -1
- package/dist/adt/xml-parser.js +25 -10
- package/dist/adt/xml-parser.js.map +1 -1
- package/dist/authz/policy.d.ts.map +1 -1
- package/dist/authz/policy.js +2 -0
- package/dist/authz/policy.js.map +1 -1
- package/dist/handlers/intent.d.ts +1 -1
- package/dist/handlers/intent.d.ts.map +1 -1
- package/dist/handlers/intent.js +166 -36
- package/dist/handlers/intent.js.map +1 -1
- package/dist/handlers/schemas.d.ts +4 -0
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +15 -1
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +14 -4
- package/dist/handlers/tools.js.map +1 -1
- package/dist/server/auth-rate-limit.d.ts +2 -0
- package/dist/server/auth-rate-limit.d.ts.map +1 -1
- package/dist/server/auth-rate-limit.js +9 -2
- package/dist/server/auth-rate-limit.js.map +1 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +86 -11
- package/dist/server/http.js.map +1 -1
- package/dist/server/server.d.ts +1 -1
- package/dist/server/server.js +1 -1
- package/dist/server/xsuaa.d.ts +14 -0
- package/dist/server/xsuaa.d.ts.map +1 -1
- package/dist/server/xsuaa.js +21 -6
- package/dist/server/xsuaa.js.map +1 -1
- package/package.json +10 -10
package/dist/handlers/intent.js
CHANGED
|
@@ -14,7 +14,7 @@ import { buildSiblingExtensionFinding, classifyCdsImpact, deriveSiblingStem, isS
|
|
|
14
14
|
import { diffMethodSets, extractMethodNameFromClause, findSectionAnchor, insertMethodPair, moveMethodDefinition, removeMethodPair, spliceClassDefinition, spliceMethodSignature, } from '../adt/class-structure.js';
|
|
15
15
|
import { findDefinition, findInterfaceImplementersViaSeoMetaRel, findReferences, findWhereUsed, getCompletion, getWhereUsedScope, } from '../adt/codeintel.js';
|
|
16
16
|
import { createObject, deleteObject, lockObject, safeUpdateClassInclude, safeUpdateObject, safeUpdateSource, unlockObject, updateObject, updateSource, } from '../adt/crud.js';
|
|
17
|
-
import { buildDataElementXml, buildDomainXml, buildMessageClassXml, buildPackageXml, buildServiceBindingXml, decodeKtdText, rewriteKtdText, } from '../adt/ddic-xml.js';
|
|
17
|
+
import { buildDataElementXml, buildDomainXml, buildMessageClassXml, buildPackageXml, buildServiceBindingXml, decodeKtdText, normalizeAdtLanguage, rewriteKtdText, } from '../adt/ddic-xml.js';
|
|
18
18
|
import { activate, activateBatch, applyFixProposal, getFixProposals, getPrettyPrinterSettings, prettyPrint, publishServiceBinding, runAtcCheck, runUnitTests, setPrettyPrinterSettings, syntaxCheck, unpublishServiceBinding, } from '../adt/devtools.js';
|
|
19
19
|
import { getDump, getGatewayErrorDetail, getObjectState, getTraceDbAccesses, getTraceHitlist, getTraceStatements, listDumps, listGatewayErrors, listSystemMessages, listTraces, } from '../adt/diagnostics.js';
|
|
20
20
|
import { AdtApiError, AdtNetworkError, AdtSafetyError, classifySapDomainError, isNotFoundError, } from '../adt/errors.js';
|
|
@@ -27,7 +27,7 @@ import { applyRapHandlerScaffold, extractRapHandlerRequirements, findMissingRapH
|
|
|
27
27
|
import { formatRapPreflightFindings, validateRapSource } from '../adt/rap-preflight.js';
|
|
28
28
|
import { changePackage } from '../adt/refactoring.js';
|
|
29
29
|
import { checkOperation, checkPackage, isOperationAllowed, OperationType } from '../adt/safety.js';
|
|
30
|
-
import { createTransport, deleteTransport, getObjectTransports, getTransport, getTransportInfo, listTransports, reassignTransport, releaseTransport, releaseTransportRecursive, } from '../adt/transport.js';
|
|
30
|
+
import { createTransport, createTransportWithTarget, deleteTransport, getObjectTransports, getTransport, getTransportInfo, listTransportLayers, listTransports, listTransportTargets, reassignTransport, releaseTransport, releaseTransportRecursive, supportsExplicitTransportTarget, } from '../adt/transport.js';
|
|
31
31
|
import { getAppInfo } from '../adt/ui5-repository.js';
|
|
32
32
|
import { validateAffHeader } from '../aff/validator.js';
|
|
33
33
|
import { extractCdsDependencies, extractCdsElements } from '../context/cds-deps.js';
|
|
@@ -1248,22 +1248,18 @@ async function handleSAPRead(client, args, cachingLayer) {
|
|
|
1248
1248
|
case 'FUGR': {
|
|
1249
1249
|
const expand = Boolean(args.expand_includes);
|
|
1250
1250
|
if (expand) {
|
|
1251
|
-
|
|
1252
|
-
//
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
}
|
|
1262
|
-
catch {
|
|
1263
|
-
parts.push(`\n=== ${inclName} ===\n[Could not read include "${inclName}"]`);
|
|
1264
|
-
}
|
|
1251
|
+
// Recursive expansion: the function module bodies (FUNCTION…ENDFUNCTION) and
|
|
1252
|
+
// PBO/PAI modules live in nested includes (LZ<grp>U01, …O…, …I…) pulled in from
|
|
1253
|
+
// the UXX include — a one-level walk misses them. getFunctionGroupExpanded BFS-es
|
|
1254
|
+
// the include graph (depth/count-capped, cycle-guarded). Dynpros + GUI status are
|
|
1255
|
+
// not included: ADT doesn't expose them over REST (SAPGUI-only).
|
|
1256
|
+
const { blocks, truncated } = await client.getFunctionGroupExpanded(name, { version: effectiveVersion });
|
|
1257
|
+
const parts = blocks.map((b) => `=== ${b.name} ===\n${b.source}`);
|
|
1258
|
+
if (truncated) {
|
|
1259
|
+
parts.push('=== [truncated] ===\nInclude cap reached; some nested includes were not expanded. ' +
|
|
1260
|
+
'Read remaining includes individually with SAPRead(type="INCL", name="...").');
|
|
1265
1261
|
}
|
|
1266
|
-
return textResult(parts.join('\n'));
|
|
1262
|
+
return textResult(parts.join('\n\n'));
|
|
1267
1263
|
}
|
|
1268
1264
|
const fg = await client.getFunctionGroup(name);
|
|
1269
1265
|
return textResult(JSON.stringify(fg, null, 2));
|
|
@@ -2326,7 +2322,12 @@ export function warnCdsReservedKeywords(source) {
|
|
|
2326
2322
|
return (`Warning: field name(s) ${fieldNames.map((f) => `'${f}'`).join(', ')} may be CDS reserved keywords. ` +
|
|
2327
2323
|
`If the DDL save fails with a generic syntax error, rename them (e.g., 'position' → 'playing_position', 'type' → 'obj_type').`);
|
|
2328
2324
|
}
|
|
2329
|
-
export function buildCreateXml(type, name, pkg, description, properties) {
|
|
2325
|
+
export function buildCreateXml(type, name, pkg, description, properties, language) {
|
|
2326
|
+
// Master/original language for the created object. Derived from the configured
|
|
2327
|
+
// SAP_LANGUAGE (passed by callers as config.language) so the create-XML body
|
|
2328
|
+
// matches the sap-language URL param ARC-1 already sends. Defaults to "EN" when
|
|
2329
|
+
// unset, preserving legacy output. See issue #343.
|
|
2330
|
+
const masterLanguage = normalizeAdtLanguage(language);
|
|
2330
2331
|
switch (type) {
|
|
2331
2332
|
case 'PROG':
|
|
2332
2333
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -2335,7 +2336,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2335
2336
|
adtcore:description="${escapeXml(description)}"
|
|
2336
2337
|
adtcore:name="${escapeXml(name)}"
|
|
2337
2338
|
adtcore:type="PROG/P"
|
|
2338
|
-
adtcore:masterLanguage="
|
|
2339
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2339
2340
|
adtcore:masterSystem="H00"
|
|
2340
2341
|
adtcore:responsible="DEVELOPER">
|
|
2341
2342
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2347,7 +2348,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2347
2348
|
adtcore:description="${escapeXml(description)}"
|
|
2348
2349
|
adtcore:name="${escapeXml(name)}"
|
|
2349
2350
|
adtcore:type="CLAS/OC"
|
|
2350
|
-
adtcore:masterLanguage="
|
|
2351
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2351
2352
|
adtcore:masterSystem="H00"
|
|
2352
2353
|
adtcore:responsible="DEVELOPER">
|
|
2353
2354
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2359,7 +2360,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2359
2360
|
adtcore:description="${escapeXml(description)}"
|
|
2360
2361
|
adtcore:name="${escapeXml(name)}"
|
|
2361
2362
|
adtcore:type="INTF/OI"
|
|
2362
|
-
adtcore:masterLanguage="
|
|
2363
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2363
2364
|
adtcore:masterSystem="H00"
|
|
2364
2365
|
adtcore:responsible="DEVELOPER">
|
|
2365
2366
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2371,7 +2372,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2371
2372
|
adtcore:description="${escapeXml(description)}"
|
|
2372
2373
|
adtcore:name="${escapeXml(name)}"
|
|
2373
2374
|
adtcore:type="PROG/I"
|
|
2374
|
-
adtcore:masterLanguage="
|
|
2375
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2375
2376
|
adtcore:masterSystem="H00"
|
|
2376
2377
|
adtcore:responsible="DEVELOPER">
|
|
2377
2378
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2383,7 +2384,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2383
2384
|
adtcore:description="${escapeXml(description)}"
|
|
2384
2385
|
adtcore:name="${escapeXml(name)}"
|
|
2385
2386
|
adtcore:type="DDLS/DF"
|
|
2386
|
-
adtcore:masterLanguage="
|
|
2387
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2387
2388
|
adtcore:masterSystem="H00"
|
|
2388
2389
|
adtcore:responsible="DEVELOPER">
|
|
2389
2390
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2395,7 +2396,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2395
2396
|
adtcore:description="${escapeXml(description)}"
|
|
2396
2397
|
adtcore:name="${escapeXml(name)}"
|
|
2397
2398
|
adtcore:type="DCLS/DL"
|
|
2398
|
-
adtcore:masterLanguage="
|
|
2399
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2399
2400
|
adtcore:masterSystem="H00"
|
|
2400
2401
|
adtcore:responsible="DEVELOPER">
|
|
2401
2402
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2413,7 +2414,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2413
2414
|
adtcore:description="${escapeXml(description)}"
|
|
2414
2415
|
adtcore:name="${escapeXml(name)}"
|
|
2415
2416
|
adtcore:type="${adtType}"
|
|
2416
|
-
adtcore:masterLanguage="
|
|
2417
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2417
2418
|
adtcore:masterSystem="H00"
|
|
2418
2419
|
adtcore:responsible="DEVELOPER">
|
|
2419
2420
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2428,7 +2429,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2428
2429
|
adtcore:description="${escapeXml(description)}"
|
|
2429
2430
|
adtcore:name="${escapeXml(name)}"
|
|
2430
2431
|
adtcore:type="BDEF/BDO"
|
|
2431
|
-
adtcore:masterLanguage="
|
|
2432
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2432
2433
|
adtcore:masterSystem="H00"
|
|
2433
2434
|
adtcore:responsible="DEVELOPER">
|
|
2434
2435
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2440,7 +2441,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2440
2441
|
adtcore:description="${escapeXml(description)}"
|
|
2441
2442
|
adtcore:name="${escapeXml(name)}"
|
|
2442
2443
|
adtcore:type="SRVD/SRV"
|
|
2443
|
-
adtcore:masterLanguage="
|
|
2444
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2444
2445
|
adtcore:masterSystem="H00"
|
|
2445
2446
|
adtcore:responsible="DEVELOPER"
|
|
2446
2447
|
srvd:srvdSourceType="S">
|
|
@@ -2462,6 +2463,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2462
2463
|
category,
|
|
2463
2464
|
version: properties?.version ? String(properties.version) : undefined,
|
|
2464
2465
|
odataVersion: properties?.odataVersion ? String(properties.odataVersion) : undefined,
|
|
2466
|
+
language: masterLanguage,
|
|
2465
2467
|
};
|
|
2466
2468
|
return buildServiceBindingXml(params);
|
|
2467
2469
|
}
|
|
@@ -2472,7 +2474,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2472
2474
|
adtcore:description="${escapeXml(description)}"
|
|
2473
2475
|
adtcore:name="${escapeXml(name)}"
|
|
2474
2476
|
adtcore:type="DDLX/EX"
|
|
2475
|
-
adtcore:masterLanguage="
|
|
2477
|
+
adtcore:masterLanguage="${masterLanguage}"
|
|
2476
2478
|
adtcore:masterSystem="H00"
|
|
2477
2479
|
adtcore:responsible="DEVELOPER">
|
|
2478
2480
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
@@ -2499,6 +2501,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2499
2501
|
lowercase: toBoolean(properties?.lowercase),
|
|
2500
2502
|
fixedValues,
|
|
2501
2503
|
valueTable: properties?.valueTable ? String(properties.valueTable) : undefined,
|
|
2504
|
+
language: masterLanguage,
|
|
2502
2505
|
};
|
|
2503
2506
|
return buildDomainXml(params);
|
|
2504
2507
|
}
|
|
@@ -2524,6 +2527,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2524
2527
|
setGetParameter: properties?.setGetParameter ? String(properties.setGetParameter) : undefined,
|
|
2525
2528
|
defaultComponentName: properties?.defaultComponentName ? String(properties.defaultComponentName) : undefined,
|
|
2526
2529
|
changeDocument: toBoolean(properties?.changeDocument),
|
|
2530
|
+
language: masterLanguage,
|
|
2527
2531
|
};
|
|
2528
2532
|
return buildDataElementXml(params);
|
|
2529
2533
|
}
|
|
@@ -2548,7 +2552,7 @@ export function buildCreateXml(type, name, pkg, description, properties) {
|
|
|
2548
2552
|
// with Content-Type: application/vnd.sap.adt.functions.groups.v3+xml.
|
|
2549
2553
|
// Verified live on a4h S/4HANA 2023 (issue #250).
|
|
2550
2554
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
2551
|
-
<group:abapFunctionGroup xmlns:group="http://www.sap.com/adt/functions/groups" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:description="${escapeXml(description)}" adtcore:language="
|
|
2555
|
+
<group:abapFunctionGroup xmlns:group="http://www.sap.com/adt/functions/groups" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:description="${escapeXml(description)}" adtcore:language="${masterLanguage}" adtcore:name="${escapeXml(name)}" adtcore:type="FUGR/F" adtcore:masterLanguage="${masterLanguage}">
|
|
2552
2556
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
2553
2557
|
</group:abapFunctionGroup>`;
|
|
2554
2558
|
case 'FUNC': {
|
|
@@ -3196,7 +3200,7 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
3196
3200
|
const mergedProps = await mergeMetadataWriteProperties(client, type, name, metadataProps);
|
|
3197
3201
|
const description = String(args.description ?? mergedProps._description ?? name);
|
|
3198
3202
|
const pkg = String(args.package ?? existingPackage ?? mergedProps._package ?? '$TMP');
|
|
3199
|
-
const body = buildCreateXml(type, name, pkg, description, mergedProps);
|
|
3203
|
+
const body = buildCreateXml(type, name, pkg, description, mergedProps, config.language);
|
|
3200
3204
|
await safeUpdateObject(client.http, client.safety, objectUrl, body, vendorContentTypeForType(type), transport, cachedFeatures?.abapRelease);
|
|
3201
3205
|
invalidateWrittenObject(type, name);
|
|
3202
3206
|
return textResult(`Successfully updated ${type} ${name}.`);
|
|
@@ -3355,8 +3359,9 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
3355
3359
|
// Build the parent URI. ADT URIs use lowercase names by convention (matches the Eclipse trace).
|
|
3356
3360
|
const refParentType = refType.split('/')[0] ?? '';
|
|
3357
3361
|
const refUri = `${objectBasePath(refParentType)}${encodeURIComponent(refName.toLowerCase())}`;
|
|
3362
|
+
const ktdLang = normalizeAdtLanguage(config.language);
|
|
3358
3363
|
const ktdBody = `<?xml version="1.0" encoding="UTF-8"?>
|
|
3359
|
-
<sktd:docu xmlns:sktd="http://www.sap.com/wbobj/texts/sktd" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:language="
|
|
3364
|
+
<sktd:docu xmlns:sktd="http://www.sap.com/wbobj/texts/sktd" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:language="${ktdLang}" adtcore:name="${escapeXml(name)}" adtcore:type="SKTD/TYP" adtcore:masterLanguage="${ktdLang}">
|
|
3360
3365
|
<adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
|
|
3361
3366
|
<sktd:refObject adtcore:description="${escapeXml(refDescription)}" adtcore:name="${escapeXml(refName)}" adtcore:type="${escapeXml(refType)}" adtcore:uri="${escapeXml(refUri)}"/>
|
|
3362
3367
|
</sktd:docu>`;
|
|
@@ -3380,7 +3385,7 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
3380
3385
|
// SAP ADT requires the root element to match the object type —
|
|
3381
3386
|
// a generic objectReferences body returns 400 "System expected the element ...".
|
|
3382
3387
|
const metadataProperties = getMetadataWriteProperties(args);
|
|
3383
|
-
const body = buildCreateXml(type, name, pkg, description, metadataProperties);
|
|
3388
|
+
const body = buildCreateXml(type, name, pkg, description, metadataProperties, config.language);
|
|
3384
3389
|
// Step 1: Create the object (metadata only)
|
|
3385
3390
|
const createUrl = objectUrl.replace(/\/[^/]+$/, ''); // parent collection URL
|
|
3386
3391
|
// DOMA/DTEL/BDEF require vendor-specific content types; all other types use
|
|
@@ -4278,7 +4283,7 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
|
|
|
4278
4283
|
const objUrl = objectUrlForType(objType, objName);
|
|
4279
4284
|
const createUrl = objUrl.replace(/\/[^/]+$/, '');
|
|
4280
4285
|
const objMetadataProps = getMetadataWriteProperties(obj);
|
|
4281
|
-
const body = buildCreateXml(objType, objName, objPackage, objDescription, objMetadataProps);
|
|
4286
|
+
const body = buildCreateXml(objType, objName, objPackage, objDescription, objMetadataProps, config.language);
|
|
4282
4287
|
const contentType = createContentTypeForType(objType);
|
|
4283
4288
|
const needsPackageParam = objType === 'BDEF' || objType === 'TABL' || objType === 'TABL/DT' || objType === 'TABL/DS';
|
|
4284
4289
|
try {
|
|
@@ -5565,11 +5570,136 @@ async function handleSAPTransport(client, args) {
|
|
|
5565
5570
|
const description = String(args.description ?? '');
|
|
5566
5571
|
if (!description)
|
|
5567
5572
|
return errorResult('Description is required for "create" action.');
|
|
5568
|
-
|
|
5569
|
-
|
|
5573
|
+
// Distinguish "target omitted" from "target present but empty": an explicit but
|
|
5574
|
+
// blank target is a caller mistake, not a request to use the package/layer path.
|
|
5575
|
+
const targetProvided = args.target !== undefined && args.target !== null;
|
|
5576
|
+
const explicitTarget = targetProvided ? String(args.target).trim() : undefined;
|
|
5577
|
+
if (targetProvided && !explicitTarget) {
|
|
5578
|
+
return errorResult('"target" was provided but is empty. Pass a transport target — a system (C11), ' +
|
|
5579
|
+
'system.client (C11.021), or target group (/GROUP/) — or omit target to let SAP resolve it from the package.');
|
|
5580
|
+
}
|
|
5581
|
+
// Shared guidance when this release's ADT stack can't set an explicit target.
|
|
5582
|
+
const targetUnsupportedMsg = "This system's ADT stack does not support setting an explicit transport target — the tm:root/newrequest " +
|
|
5583
|
+
'action is not implemented (an ADT-framework limitation on SAP_BASIS 7.50, verified on SP02 and SP32, ' +
|
|
5584
|
+
'independent of STMS/CTC config). It works on newer ABAP Platform / S/4HANA releases. Workaround here: ' +
|
|
5585
|
+
'create the request without "target", then set the Transportziel manually in SE09/SE10 (SAP GUI), which ' +
|
|
5586
|
+
'works when CTC and the target group are configured.';
|
|
5587
|
+
let id;
|
|
5588
|
+
if (explicitTarget) {
|
|
5589
|
+
// Discovery-gate first — the same capability SAP's own Eclipse client checks: the TM
|
|
5590
|
+
// resource that sets an explicit target is advertised in ADT discovery only on releases
|
|
5591
|
+
// that implement it (the transportorganizer Accept type on cts/transportrequests). When
|
|
5592
|
+
// discovery is loaded and the capability is absent (NW 7.50/7.51), fail fast with guidance
|
|
5593
|
+
// rather than POST a request the backend rejects with "user action is not supported".
|
|
5594
|
+
if (supportsExplicitTransportTarget(client.http) === false) {
|
|
5595
|
+
return errorResult(targetUnsupportedMsg);
|
|
5596
|
+
}
|
|
5597
|
+
// Explicit transport target (Transportziel / TR_TARGET): a system (C11),
|
|
5598
|
+
// system.client (C11.021), or target group (/TRG/). Routed via the tm:root/
|
|
5599
|
+
// newrequest endpoint — the only ADT path that sets the target directly. The
|
|
5600
|
+
// group and system.client forms require extended transport control (CTC).
|
|
5601
|
+
try {
|
|
5602
|
+
id = await createTransportWithTarget(client.http, client.safety, description, explicitTarget, client.username);
|
|
5603
|
+
}
|
|
5604
|
+
catch (err) {
|
|
5605
|
+
if (err instanceof AdtApiError && (err.statusCode === 400 || err.statusCode === 404)) {
|
|
5606
|
+
// SAP validates the target server-side: a4h (7.58) returns 400 "Target 'X'
|
|
5607
|
+
// does not exist"; other releases may use 404.
|
|
5608
|
+
if (/does not exist/i.test(err.message)) {
|
|
5609
|
+
return errorResult(`Transport target "${explicitTarget}" does not exist on this system. Valid targets are a ` +
|
|
5610
|
+
'system (e.g. C11), system.client (C11.021), or a target group (/GROUP/) — the group and ' +
|
|
5611
|
+
'system.client forms require extended transport control (CTC) to be active. Use ' +
|
|
5612
|
+
'SAPTransport(action="targets") to list the targets this system actually offers.');
|
|
5613
|
+
}
|
|
5614
|
+
// Fallback for when discovery was not loaded: NW 7.50/7.51 reject tm:root/newrequest
|
|
5615
|
+
// with "user action is not supported" (the gate above pre-empts this when discovery is known).
|
|
5616
|
+
if (/user action/i.test(err.message) && /not supported/i.test(err.message)) {
|
|
5617
|
+
return errorResult(targetUnsupportedMsg);
|
|
5618
|
+
}
|
|
5619
|
+
}
|
|
5620
|
+
throw err;
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
else {
|
|
5624
|
+
const targetPackage = args.package ? String(args.package) : undefined;
|
|
5625
|
+
const transportLayer = args.transportLayer ? String(args.transportLayer) : undefined;
|
|
5626
|
+
id = await createTransport(client.http, client.safety, description, targetPackage, undefined, transportLayer);
|
|
5627
|
+
}
|
|
5570
5628
|
if (!id)
|
|
5571
5629
|
return errorResult('Transport creation succeeded but no transport ID was returned. Check the SAP system manually.');
|
|
5572
|
-
|
|
5630
|
+
// Read the new request back (best-effort) to report its actual transport target.
|
|
5631
|
+
// An empty target means the request is local ("Local Change Requests") — the #1
|
|
5632
|
+
// source of "why does it always create a local transport?" confusion — so we
|
|
5633
|
+
// surface it explicitly instead of just echoing the ID.
|
|
5634
|
+
const created = await getTransport(client.http, client.safety, id).catch(() => null);
|
|
5635
|
+
const target = created?.target?.trim() ?? '';
|
|
5636
|
+
const targetDesc = created?.targetDesc?.trim() ?? '';
|
|
5637
|
+
if (!created)
|
|
5638
|
+
return textResult(`Created transport request: ${id}`);
|
|
5639
|
+
if (target) {
|
|
5640
|
+
return textResult(`Created transport request: ${id}\nTransport target: ${target}${targetDesc ? ` (${targetDesc})` : ''}`);
|
|
5641
|
+
}
|
|
5642
|
+
return textResult(`Created transport request: ${id}\n` +
|
|
5643
|
+
`Transport target: <none>${targetDesc ? ` — "${targetDesc}"` : ''}. This is a LOCAL request — it cannot be transported onward.\n\n` +
|
|
5644
|
+
'To create a request that targets another system, either:\n' +
|
|
5645
|
+
' • set an explicit target — pass target=<system | system.client | /group/> (e.g. target="/TRG/" or "C11"); ' +
|
|
5646
|
+
'the group and system.client forms require extended transport control (CTC) to be active; or\n' +
|
|
5647
|
+
' • let SAP resolve it from the package transport layer + STMS consolidation route (pass transportLayer=<layer> to override the layer).\n' +
|
|
5648
|
+
'Both require the SAP system to actually have transport routes/targets configured (a Basis task). ' +
|
|
5649
|
+
'On a standalone system with no routes, every request is local — expected, and no ADT/Eclipse/SE10 client can change it.');
|
|
5650
|
+
}
|
|
5651
|
+
case 'layers': {
|
|
5652
|
+
// Discovery: list valid values for create's `transportLayer`. Lets a client pick a
|
|
5653
|
+
// real layer instead of guessing. Read-only (no allowTransportWrites required).
|
|
5654
|
+
let layers;
|
|
5655
|
+
try {
|
|
5656
|
+
layers = await listTransportLayers(client.http, client.safety);
|
|
5657
|
+
}
|
|
5658
|
+
catch (err) {
|
|
5659
|
+
// The package transport-layer value help is 7.52+; NW 7.50/7.51 return 404
|
|
5660
|
+
// "No suitable resource found" (verified live on npl 7.50). Surface that clearly
|
|
5661
|
+
// instead of a raw 404, so the caller knows discovery is unavailable on this release.
|
|
5662
|
+
if (err instanceof AdtApiError && err.isNotFound) {
|
|
5663
|
+
return errorResult('Transport-layer discovery is not available on this SAP release — the value help ' +
|
|
5664
|
+
'(/sap/bc/adt/packages/valuehelps/transportlayers) returned 404 (typically NW < 7.52). ' +
|
|
5665
|
+
'Create requests without transportLayer; the route/target is governed by the package + STMS on these releases.');
|
|
5666
|
+
}
|
|
5667
|
+
throw err;
|
|
5668
|
+
}
|
|
5669
|
+
const routed = layers.filter((l) => l.target);
|
|
5670
|
+
const summary = layers.length
|
|
5671
|
+
? routed.length
|
|
5672
|
+
? `${layers.length} transport layer(s); ${routed.length} carry a target. Pass one as transportLayer= on create.`
|
|
5673
|
+
: `${layers.length} transport layer(s), but none expose a consolidation target — created requests will be local on this system.`
|
|
5674
|
+
: 'No transport layers are defined on this system — every request will be local.';
|
|
5675
|
+
return textResult(JSON.stringify({ transportLayers: layers, summary }, null, 2));
|
|
5676
|
+
}
|
|
5677
|
+
case 'targets': {
|
|
5678
|
+
// Discovery: list valid values for create's `target` (Transportziel / TR_TARGET) via the
|
|
5679
|
+
// official ADT target value help. Read-only (no allowTransportWrites required).
|
|
5680
|
+
// Gate on the same capability as create's target path: NW 7.50 returns an empty list
|
|
5681
|
+
// (HTTP 200) from the value help rather than 404, so the discovery accept type — not the
|
|
5682
|
+
// HTTP status — is the reliable "is target discovery meaningful here?" signal.
|
|
5683
|
+
if (supportsExplicitTransportTarget(client.http) === false) {
|
|
5684
|
+
return errorResult("Transport-target discovery is not available on this SAP release — its ADT stack doesn't support " +
|
|
5685
|
+
'explicit transport targets (verified on NW 7.50). Set the target in SE09/SE10 instead.');
|
|
5686
|
+
}
|
|
5687
|
+
let targets;
|
|
5688
|
+
try {
|
|
5689
|
+
targets = await listTransportTargets(client.http, client.safety);
|
|
5690
|
+
}
|
|
5691
|
+
catch (err) {
|
|
5692
|
+
// Fallback when discovery wasn't loaded: some releases 404 the value help.
|
|
5693
|
+
if (err instanceof AdtApiError && err.isNotFound) {
|
|
5694
|
+
return errorResult('Transport-target discovery is not available on this SAP release — the value help ' +
|
|
5695
|
+
'(/sap/bc/adt/cts/transportrequests/valuehelp/target) returned 404. Set the target in SE09/SE10 instead.');
|
|
5696
|
+
}
|
|
5697
|
+
throw err;
|
|
5698
|
+
}
|
|
5699
|
+
const summary = targets.length
|
|
5700
|
+
? `${targets.length} valid transport target(s). Pass one as target= on create.`
|
|
5701
|
+
: 'No transport targets are configured on this system (so created requests are local).';
|
|
5702
|
+
return textResult(JSON.stringify({ transportTargets: targets, summary }, null, 2));
|
|
5573
5703
|
}
|
|
5574
5704
|
case 'release': {
|
|
5575
5705
|
const id = String(args.id ?? '');
|