@abapify/adk 0.4.1 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +672 -220
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1854 -357
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
- package/dist/factory-DtyrTGlN.mjs +0 -394
- package/dist/factory-DtyrTGlN.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createLockService, createLockService as createLockService$1, resolveLockCorrelation } from "@abapify/adt-locks";
|
|
2
|
+
import { assertAdtUri } from "@abapify/adt-client";
|
|
3
3
|
|
|
4
|
+
//#region \0rolldown/runtime.js
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __exportAll = (all, no_symbols) => {
|
|
7
|
+
let target = {};
|
|
8
|
+
for (var name in all) {
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (!no_symbols) {
|
|
15
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
|
+
}
|
|
17
|
+
return target;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
4
21
|
//#region src/base/fetch-utils.ts
|
|
5
22
|
/**
|
|
6
23
|
* Utility for handling v2 client fetch responses.
|
|
@@ -30,6 +47,25 @@ async function toText(result) {
|
|
|
30
47
|
//#endregion
|
|
31
48
|
//#region src/base/model.ts
|
|
32
49
|
/**
|
|
50
|
+
* SAP accepted the skeleton POST, but rejected the immediate follow-up lock.
|
|
51
|
+
*
|
|
52
|
+
* The object therefore exists in SAP, while the source or metadata supplied
|
|
53
|
+
* to the original save call has not yet been persisted. Callers must retry
|
|
54
|
+
* the same object with `mode: 'update'` after the CTS/editor lock is cleared;
|
|
55
|
+
* repeating `mode: 'create'` risks an "already exists" response.
|
|
56
|
+
*/
|
|
57
|
+
var AdkPostCreateLockError = class extends Error {
|
|
58
|
+
objectUri;
|
|
59
|
+
transport;
|
|
60
|
+
code = "ADT_POST_CREATE_LOCKED";
|
|
61
|
+
name = "AdkPostCreateLockError";
|
|
62
|
+
constructor(objectUri, transport, cause) {
|
|
63
|
+
super(`SAP created ${objectUri}, but its post-create CTS lock is still active. Retry the pending change with mode: 'update' after the lock clears; do not create the object again.`, { cause });
|
|
64
|
+
this.objectUri = objectUri;
|
|
65
|
+
this.transport = transport;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
33
69
|
* Base class for all ADK objects
|
|
34
70
|
*
|
|
35
71
|
* All ADK objects (AdkPackage, AdkTransportRequest, etc.) extend this.
|
|
@@ -263,10 +299,23 @@ var AdkObject = class {
|
|
|
263
299
|
const { transport, mode = "update" } = options;
|
|
264
300
|
this._unchanged = false;
|
|
265
301
|
if (mode === "create") {
|
|
266
|
-
if (!await this.checkObjectExists())
|
|
302
|
+
if (!await this.checkObjectExists()) {
|
|
303
|
+
await this.saveViaContract("create", { transport });
|
|
304
|
+
try {
|
|
305
|
+
return await this.save({
|
|
306
|
+
...options,
|
|
307
|
+
mode: "update",
|
|
308
|
+
postCreate: true
|
|
309
|
+
});
|
|
310
|
+
} catch (error) {
|
|
311
|
+
if (this.isPostCreateLockConflict(error)) throw new AdkPostCreateLockError(this.objectUri, transport, error);
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
267
315
|
return this.save({
|
|
268
316
|
...options,
|
|
269
|
-
mode: "update"
|
|
317
|
+
mode: "update",
|
|
318
|
+
postCreate: options.postCreateLockRetry !== void 0
|
|
270
319
|
});
|
|
271
320
|
}
|
|
272
321
|
const hasPendingSources = this.hasPendingSources();
|
|
@@ -285,13 +334,14 @@ var AdkObject = class {
|
|
|
285
334
|
}
|
|
286
335
|
const wasLocked = this.isLocked;
|
|
287
336
|
if (!wasLocked) try {
|
|
288
|
-
await this.
|
|
337
|
+
if (options.postCreate) await this.lockAfterCreate(transport, options.postCreateLockRetry);
|
|
338
|
+
else await this.lock(transport);
|
|
289
339
|
} catch (e) {
|
|
290
340
|
if (mode === "upsert" && !confirmedExists && this.shouldFallbackToCreate(e)) return this.fallbackToCreate(options);
|
|
291
341
|
throw e;
|
|
292
342
|
}
|
|
293
343
|
try {
|
|
294
|
-
const effectiveTransport =
|
|
344
|
+
const effectiveTransport = resolveLockCorrelation(this._lockHandle ?? {}, transport);
|
|
295
345
|
if (!wasLocked) await this.refreshETagsAfterLock();
|
|
296
346
|
if (hasPendingSources) await this.savePendingSources({
|
|
297
347
|
lockHandle: this._lockHandle?.handle,
|
|
@@ -417,6 +467,41 @@ var AdkObject = class {
|
|
|
417
467
|
return false;
|
|
418
468
|
}
|
|
419
469
|
/**
|
|
470
|
+
* Some CTS backends can retain the lock created by a successful object POST
|
|
471
|
+
* long enough for the immediate follow-up LOCK to fail. This is distinct
|
|
472
|
+
* from an arbitrary edit conflict because this save invocation already
|
|
473
|
+
* created the skeleton successfully.
|
|
474
|
+
*/
|
|
475
|
+
isPostCreateLockConflict(e) {
|
|
476
|
+
let message = "";
|
|
477
|
+
if (typeof e === "string") message = e;
|
|
478
|
+
else if (e instanceof Error) message = e.message;
|
|
479
|
+
else if (typeof e === "object" && e !== null && typeof e.message === "string") message = e.message;
|
|
480
|
+
const normalized = message.toLowerCase();
|
|
481
|
+
return normalized.includes("already locked in request") || normalized.includes("currently editing") || normalized.includes("is being edited");
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Some backends retain the lock implicitly created by a successful POST for
|
|
485
|
+
* a short time. Retry only this known follow-up LOCK; no arbitrary update or
|
|
486
|
+
* source write is repeated, and each successful lock still uses the normal
|
|
487
|
+
* handle-backed save/unlock lifecycle.
|
|
488
|
+
*/
|
|
489
|
+
async lockAfterCreate(transport, retry) {
|
|
490
|
+
const attempts = retry?.attempts ?? 1;
|
|
491
|
+
const delayMs = retry?.delayMs ?? 0;
|
|
492
|
+
if (!Number.isInteger(attempts) || attempts < 1) throw new RangeError("postCreateLockRetry.attempts must be a positive integer.");
|
|
493
|
+
if (!Number.isFinite(delayMs) || delayMs < 0) throw new RangeError("postCreateLockRetry.delayMs must be a non-negative number.");
|
|
494
|
+
let lastConflict;
|
|
495
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) try {
|
|
496
|
+
return await this.lock(transport);
|
|
497
|
+
} catch (error) {
|
|
498
|
+
if (!this.isPostCreateLockConflict(error) || attempt === attempts) throw error;
|
|
499
|
+
lastConflict = error;
|
|
500
|
+
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
501
|
+
}
|
|
502
|
+
throw lastConflict;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
420
505
|
* Upsert fallback: try POST (create), treat 422 "already exists" as unchanged.
|
|
421
506
|
* Extracted to avoid duplication in lock-catch and saveViaContract-catch paths.
|
|
422
507
|
*/
|
|
@@ -486,10 +571,11 @@ var AdkObject = class {
|
|
|
486
571
|
const self = this;
|
|
487
572
|
if (!self._pendingSource) return;
|
|
488
573
|
try {
|
|
489
|
-
const
|
|
574
|
+
const response = await this.ctx.client.fetch(`${this.objectUri}/source/main`, {
|
|
490
575
|
method: "GET",
|
|
491
576
|
headers: { Accept: "text/plain" }
|
|
492
|
-
})
|
|
577
|
+
});
|
|
578
|
+
const currentSource = await toText(response);
|
|
493
579
|
if (this.normalizeSource(currentSource) === this.normalizeSource(self._pendingSource)) {
|
|
494
580
|
this._unchanged = true;
|
|
495
581
|
delete self._pendingSource;
|
|
@@ -512,7 +598,7 @@ var AdkObject = class {
|
|
|
512
598
|
const sapData = (await contract.get(this.name))?.[wrapperKey];
|
|
513
599
|
if (!sapData) return;
|
|
514
600
|
const localData = await this.data();
|
|
515
|
-
const isEmpty = (v) => v == null || v === "" || Array.isArray(v) && v.length === 0 || typeof v === "object" &&
|
|
601
|
+
const isEmpty = (v) => v == null || v === "" || Array.isArray(v) && v.length === 0 || typeof v === "object" && Object.keys(v).length === 0;
|
|
516
602
|
const isSubsetMatch = (local, sap) => {
|
|
517
603
|
if (local === sap) return true;
|
|
518
604
|
if (isEmpty(local) && isEmpty(sap)) return true;
|
|
@@ -613,10 +699,11 @@ var AdkObject = class {
|
|
|
613
699
|
async setSource(sourcePath, content, options = {}) {
|
|
614
700
|
const { transport } = options;
|
|
615
701
|
const wasLocked = this.isLocked;
|
|
616
|
-
if (!wasLocked) await this.lock();
|
|
702
|
+
if (!wasLocked) await this.lock(transport);
|
|
617
703
|
try {
|
|
618
704
|
const params = new URLSearchParams();
|
|
619
|
-
|
|
705
|
+
const effectiveTransport = resolveLockCorrelation(this._lockHandle ?? {}, transport);
|
|
706
|
+
if (effectiveTransport) params.set("corrNr", effectiveTransport);
|
|
620
707
|
if (this._lockHandle) params.set("lockHandle", this._lockHandle.handle);
|
|
621
708
|
const fullPath = `${this.objectUri}${sourcePath}`;
|
|
622
709
|
const url = params.toString() ? `${fullPath}?${params.toString()}` : fullPath;
|
|
@@ -689,10 +776,11 @@ var AdkObject = class {
|
|
|
689
776
|
*/
|
|
690
777
|
async fetchText(url, headers) {
|
|
691
778
|
try {
|
|
692
|
-
|
|
779
|
+
const response = await this.ctx.client.fetch(url, {
|
|
693
780
|
method: "GET",
|
|
694
781
|
headers: headers ?? {}
|
|
695
|
-
})
|
|
782
|
+
});
|
|
783
|
+
return toText(response);
|
|
696
784
|
} catch {
|
|
697
785
|
return;
|
|
698
786
|
}
|
|
@@ -971,16 +1059,23 @@ var AdkObjectSet = class AdkObjectSet {
|
|
|
971
1059
|
const obj = r.object;
|
|
972
1060
|
const deferred = obj._deferredSources;
|
|
973
1061
|
if (deferred && deferred.length > 0) try {
|
|
974
|
-
const lock = await r.object.lock();
|
|
1062
|
+
const lock = await r.object.lock(saveOptions.transport);
|
|
1063
|
+
const effectiveTransport = resolveLockCorrelation(lock, saveOptions.transport);
|
|
975
1064
|
for (const [key, source] of deferred) await obj.saveIncludeSource(key, source, {
|
|
976
1065
|
lockHandle: lock.handle,
|
|
977
|
-
transport:
|
|
1066
|
+
transport: effectiveTransport
|
|
978
1067
|
});
|
|
979
|
-
delete obj._deferredSources;
|
|
980
1068
|
const deferredSet = new AdkObjectSet(this.ctx);
|
|
981
1069
|
deferredSet.add(r.object);
|
|
982
|
-
await deferredSet.activateAll();
|
|
983
|
-
|
|
1070
|
+
const deferredActivation = await deferredSet.activateAll();
|
|
1071
|
+
if (deferredActivation.failed > 0) throw new Error(`Deferred activation failed: ${deferredActivation.messages.join("; ") || "unknown error"}`);
|
|
1072
|
+
delete obj._deferredSources;
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
r.success = false;
|
|
1075
|
+
r.error = `Deferred source deployment failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
1076
|
+
saveResult.success--;
|
|
1077
|
+
saveResult.failed++;
|
|
1078
|
+
} finally {
|
|
984
1079
|
try {
|
|
985
1080
|
await r.object.unlock();
|
|
986
1081
|
} catch {}
|
|
@@ -1102,7 +1197,7 @@ let globalContext = null;
|
|
|
1102
1197
|
* initializeAdk(client);
|
|
1103
1198
|
*
|
|
1104
1199
|
* // Now ADK objects work without context
|
|
1105
|
-
* const transport = await AdkTransportRequest.get('
|
|
1200
|
+
* const transport = await AdkTransportRequest.get('TRLK900001');
|
|
1106
1201
|
* ```
|
|
1107
1202
|
*/
|
|
1108
1203
|
function initializeAdk(client, options) {
|
|
@@ -1165,6 +1260,271 @@ function tryGetGlobalContext() {
|
|
|
1165
1260
|
return globalContext ?? void 0;
|
|
1166
1261
|
}
|
|
1167
1262
|
|
|
1263
|
+
//#endregion
|
|
1264
|
+
//#region src/base/kinds.ts
|
|
1265
|
+
/**
|
|
1266
|
+
* ADK Object Kinds
|
|
1267
|
+
*
|
|
1268
|
+
* Central registry of all ADK object types.
|
|
1269
|
+
* Import specific kinds for type-safe usage:
|
|
1270
|
+
*
|
|
1271
|
+
* @example
|
|
1272
|
+
* import { TransportRequest } from '../base/kinds';
|
|
1273
|
+
* class AdkTransportRequest extends AdkObject<typeof TransportRequest> { ... }
|
|
1274
|
+
*/
|
|
1275
|
+
const TransportRequest = "TransportRequest";
|
|
1276
|
+
const TransportTask = "TransportTask";
|
|
1277
|
+
const Package = "Package";
|
|
1278
|
+
const Class = "Class";
|
|
1279
|
+
const Interface = "Interface";
|
|
1280
|
+
const FunctionGroup = "FunctionGroup";
|
|
1281
|
+
const FunctionModule = "FunctionModule";
|
|
1282
|
+
const Program = "Program";
|
|
1283
|
+
const Include = "Include";
|
|
1284
|
+
const Table = "Table";
|
|
1285
|
+
const Structure = "Structure";
|
|
1286
|
+
const DataElement = "DataElement";
|
|
1287
|
+
const Domain = "Domain";
|
|
1288
|
+
const TableType = "TableType";
|
|
1289
|
+
const DdlSource = "DdlSource";
|
|
1290
|
+
const DclSource = "DclSource";
|
|
1291
|
+
const DdlExtension = "DdlExtension";
|
|
1292
|
+
const CdsAspect = "CdsAspect";
|
|
1293
|
+
const CdsType = "CdsType";
|
|
1294
|
+
const ScalarFunctionDefinition = "ScalarFunctionDefinition";
|
|
1295
|
+
const ScalarFunctionImplementation = "ScalarFunctionImplementation";
|
|
1296
|
+
const EntityBuffer = "EntityBuffer";
|
|
1297
|
+
const DynamicCache = "DynamicCache";
|
|
1298
|
+
const TuningIndex = "TuningIndex";
|
|
1299
|
+
const StaticCache = "StaticCache";
|
|
1300
|
+
const ExternalSchema = "ExternalSchema";
|
|
1301
|
+
const BehaviorDefinition = "BehaviorDefinition";
|
|
1302
|
+
const ServiceDefinition = "ServiceDefinition";
|
|
1303
|
+
const ServiceBinding = "ServiceBinding";
|
|
1304
|
+
const MessageClass = "MessageClass";
|
|
1305
|
+
const EnhancementSpot = "EnhancementSpot";
|
|
1306
|
+
|
|
1307
|
+
//#endregion
|
|
1308
|
+
//#region src/base/registry.ts
|
|
1309
|
+
/**
|
|
1310
|
+
* Parse ADT type into components
|
|
1311
|
+
*
|
|
1312
|
+
* @example
|
|
1313
|
+
* parseAdtType("DEVC/K") // { full: "DEVC/K", main: "DEVC", sub: "K" }
|
|
1314
|
+
* parseAdtType("DEVC") // { full: "DEVC", main: "DEVC", sub: undefined }
|
|
1315
|
+
*/
|
|
1316
|
+
function parseAdtType(adtType) {
|
|
1317
|
+
const [main, sub] = adtType.split("/");
|
|
1318
|
+
return {
|
|
1319
|
+
full: adtType,
|
|
1320
|
+
main: main.toUpperCase(),
|
|
1321
|
+
sub: sub?.toUpperCase()
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Get main type from ADT type
|
|
1326
|
+
*
|
|
1327
|
+
* @example
|
|
1328
|
+
* getMainType("DEVC/K") // "DEVC"
|
|
1329
|
+
* getMainType("CLAS") // "CLAS"
|
|
1330
|
+
*/
|
|
1331
|
+
function getMainType(adtType) {
|
|
1332
|
+
return parseAdtType(adtType).main;
|
|
1333
|
+
}
|
|
1334
|
+
/** Internal registry storage */
|
|
1335
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1336
|
+
/** ADT main type to ADK kind mapping */
|
|
1337
|
+
const adtToKind = /* @__PURE__ */ new Map();
|
|
1338
|
+
/** ADK kind to ADT main type mapping (reverse) */
|
|
1339
|
+
const kindToAdt = /* @__PURE__ */ new Map();
|
|
1340
|
+
/**
|
|
1341
|
+
* Register an ADK object type
|
|
1342
|
+
*
|
|
1343
|
+
* @param adtType - ADT type, either main (e.g., "CLAS") or full (e.g., "TABL/DS")
|
|
1344
|
+
* @param kind - ADK kind constant
|
|
1345
|
+
* @param constructor - Object constructor
|
|
1346
|
+
* @param options - Optional endpoint and name transform settings
|
|
1347
|
+
*/
|
|
1348
|
+
function registerObjectType(adtType, kind, constructor, options) {
|
|
1349
|
+
const normalizedType = adtType.toUpperCase();
|
|
1350
|
+
registry.set(normalizedType, {
|
|
1351
|
+
kind,
|
|
1352
|
+
constructor,
|
|
1353
|
+
endpoint: options?.endpoint,
|
|
1354
|
+
nameTransform: options?.nameTransform,
|
|
1355
|
+
normalizeName: options?.normalizeName
|
|
1356
|
+
});
|
|
1357
|
+
adtToKind.set(normalizedType, kind);
|
|
1358
|
+
kindToAdt.set(kind, normalizedType);
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* Resolve ADT type to registry entry
|
|
1362
|
+
*
|
|
1363
|
+
* Tries full type first (e.g., "TABL/DS"), then falls back to main type (e.g., "TABL").
|
|
1364
|
+
* This allows registering subtypes with different constructors/endpoints.
|
|
1365
|
+
*
|
|
1366
|
+
* @param adtType - Full or main ADT type (e.g., "DEVC/K" or "DEVC")
|
|
1367
|
+
* @returns Registry entry or undefined if not found
|
|
1368
|
+
*/
|
|
1369
|
+
function resolveType(adtType) {
|
|
1370
|
+
const normalized = adtType.toUpperCase();
|
|
1371
|
+
const fullMatch = registry.get(normalized);
|
|
1372
|
+
if (fullMatch) return fullMatch;
|
|
1373
|
+
const mainType = getMainType(adtType);
|
|
1374
|
+
return registry.get(mainType);
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Resolve ADK kind to registry entry
|
|
1378
|
+
*
|
|
1379
|
+
* @param kind - ADK kind constant
|
|
1380
|
+
* @returns Registry entry or undefined if not found
|
|
1381
|
+
*/
|
|
1382
|
+
function resolveKind(kind) {
|
|
1383
|
+
const adtType = kindToAdt.get(kind);
|
|
1384
|
+
if (!adtType) return void 0;
|
|
1385
|
+
return registry.get(adtType);
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Get ADK kind for ADT type
|
|
1389
|
+
*/
|
|
1390
|
+
function getKindForType(adtType) {
|
|
1391
|
+
return adtToKind.get(getMainType(adtType));
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Get ADT main type for ADK kind
|
|
1395
|
+
*/
|
|
1396
|
+
function getTypeForKind(kind) {
|
|
1397
|
+
return kindToAdt.get(kind);
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Check if ADT type is registered
|
|
1401
|
+
*/
|
|
1402
|
+
function isTypeRegistered(adtType) {
|
|
1403
|
+
return registry.has(getMainType(adtType));
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Get all registered ADT types
|
|
1407
|
+
*/
|
|
1408
|
+
function getRegisteredTypes() {
|
|
1409
|
+
return Array.from(registry.keys());
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Get all registered ADK kinds
|
|
1413
|
+
*/
|
|
1414
|
+
function getRegisteredKinds() {
|
|
1415
|
+
return Array.from(kindToAdt.keys());
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Get ADT REST endpoint for a type (e.g., 'oo/classes', 'ddic/tabletypes')
|
|
1419
|
+
* Checks exact type first (e.g., 'TABL/DS') before falling back to main type.
|
|
1420
|
+
*/
|
|
1421
|
+
function getEndpointForType(adtType) {
|
|
1422
|
+
return resolveType(adtType)?.endpoint;
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Build the full ADT object URI for a given type and name.
|
|
1426
|
+
*
|
|
1427
|
+
* @example
|
|
1428
|
+
* getObjectUri('CLAS', 'ZCL_MY_CLASS') // '/sap/bc/adt/oo/classes/zcl_my_class'
|
|
1429
|
+
* getObjectUri('DEVC', 'ZPACKAGE') // '/sap/bc/adt/packages/ZPACKAGE'
|
|
1430
|
+
* getObjectUri('TTYP', 'ZAGE_TTYP_STRTAB') // '/sap/bc/adt/ddic/tabletypes/zage_ttyp_strtab'
|
|
1431
|
+
*/
|
|
1432
|
+
function getObjectUri(adtType, name) {
|
|
1433
|
+
const entry = resolveType(adtType);
|
|
1434
|
+
if (!entry?.endpoint) return void 0;
|
|
1435
|
+
const normalized = entry.normalizeName ? entry.normalizeName(name) : name;
|
|
1436
|
+
const transformedName = entry.nameTransform === "preserve" ? encodeURIComponent(normalized) : encodeURIComponent(normalized.toLowerCase());
|
|
1437
|
+
return `/sap/bc/adt/${entry.endpoint}/${transformedName}`;
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Normalize an object name using type-specific rules.
|
|
1441
|
+
*
|
|
1442
|
+
* If `adtType` is provided, applies that type's normalizer only.
|
|
1443
|
+
* Otherwise, collects all possible normalized forms from every registered type.
|
|
1444
|
+
*
|
|
1445
|
+
* @returns Array of candidate names (always includes the original).
|
|
1446
|
+
*
|
|
1447
|
+
* @example
|
|
1448
|
+
* normalizeObjectName('SAPLZAGE_FUGR') // ['SAPLZAGE_FUGR', 'ZAGE_FUGR']
|
|
1449
|
+
* normalizeObjectName('SAPLZAGE_FUGR', 'FUGR') // ['ZAGE_FUGR']
|
|
1450
|
+
* normalizeObjectName('ZCLAS_TEST') // ['ZCLAS_TEST'] (no normalizer matches)
|
|
1451
|
+
*/
|
|
1452
|
+
function normalizeObjectName(name, adtType) {
|
|
1453
|
+
if (adtType) return [resolveType(adtType)?.normalizeName?.(name) ?? name];
|
|
1454
|
+
const candidates = /* @__PURE__ */ new Set([name]);
|
|
1455
|
+
for (const entry of registry.values()) if (entry.normalizeName) candidates.add(entry.normalizeName(name));
|
|
1456
|
+
return Array.from(candidates);
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Extract the root object URI from a full (possibly sub-resource) URI.
|
|
1460
|
+
*
|
|
1461
|
+
* SAP locks must target the object root, not sub-resources like `/source/main`.
|
|
1462
|
+
* This function matches against registered endpoint prefixes and strips
|
|
1463
|
+
* everything after the object name segment.
|
|
1464
|
+
*
|
|
1465
|
+
* @returns The root object URI, or the original URI unchanged if no endpoint matches.
|
|
1466
|
+
*
|
|
1467
|
+
* @example
|
|
1468
|
+
* getObjectRootUri('/sap/bc/adt/functions/groups/zage_fugr/source/main')
|
|
1469
|
+
* // → '/sap/bc/adt/functions/groups/zage_fugr'
|
|
1470
|
+
* getObjectRootUri('/sap/bc/adt/oo/classes/zcl_test/includes/testclasses')
|
|
1471
|
+
* // → '/sap/bc/adt/oo/classes/zcl_test'
|
|
1472
|
+
* getObjectRootUri('/sap/bc/adt/oo/classes/zcl_test')
|
|
1473
|
+
* // → '/sap/bc/adt/oo/classes/zcl_test' (already root)
|
|
1474
|
+
*/
|
|
1475
|
+
function getObjectRootUri(uri) {
|
|
1476
|
+
const ADT_PREFIX = "/sap/bc/adt/";
|
|
1477
|
+
const endpoints = [];
|
|
1478
|
+
for (const entry of registry.values()) if (entry.endpoint) endpoints.push(entry.endpoint);
|
|
1479
|
+
endpoints.sort((a, b) => b.length - a.length);
|
|
1480
|
+
for (const endpoint of endpoints) {
|
|
1481
|
+
const prefix = `${ADT_PREFIX}${endpoint}/`;
|
|
1482
|
+
if (uri.startsWith(prefix)) return `${prefix}${uri.slice(prefix.length).split("/")[0]}`;
|
|
1483
|
+
}
|
|
1484
|
+
return uri;
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* Known ADT type to ADK kind mappings
|
|
1488
|
+
*
|
|
1489
|
+
* Repository Objects:
|
|
1490
|
+
* - DEVC → Package
|
|
1491
|
+
* - CLAS → Class
|
|
1492
|
+
* - INTF → Interface
|
|
1493
|
+
* - FUGR → FunctionGroup
|
|
1494
|
+
* - FUNC → FunctionModule
|
|
1495
|
+
* - PROG → Program
|
|
1496
|
+
* - INCL → Include
|
|
1497
|
+
*
|
|
1498
|
+
* Data Dictionary:
|
|
1499
|
+
* - TABL → Table
|
|
1500
|
+
* - STRU → Structure (actually TABL with different category)
|
|
1501
|
+
* - DTEL → DataElement
|
|
1502
|
+
* - DOMA → Domain
|
|
1503
|
+
* - TTYP → TableType
|
|
1504
|
+
*
|
|
1505
|
+
* Other:
|
|
1506
|
+
* - MSAG → MessageClass
|
|
1507
|
+
* - ENHS → EnhancementSpot
|
|
1508
|
+
*
|
|
1509
|
+
* CTS:
|
|
1510
|
+
* - (Transport requests/tasks use different identification)
|
|
1511
|
+
*/
|
|
1512
|
+
const ADT_TYPE_MAPPINGS = {
|
|
1513
|
+
DEVC: Package,
|
|
1514
|
+
CLAS: Class,
|
|
1515
|
+
INTF: Interface,
|
|
1516
|
+
FUGR: FunctionGroup,
|
|
1517
|
+
FUNC: FunctionModule,
|
|
1518
|
+
PROG: Program,
|
|
1519
|
+
INCL: Include,
|
|
1520
|
+
TABL: Table,
|
|
1521
|
+
DTEL: DataElement,
|
|
1522
|
+
DOMA: Domain,
|
|
1523
|
+
TTYP: TableType,
|
|
1524
|
+
MSAG: MessageClass,
|
|
1525
|
+
ENHS: EnhancementSpot
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1168
1528
|
//#endregion
|
|
1169
1529
|
//#region src/objects/repository/devc/devc.model.ts
|
|
1170
1530
|
/**
|
|
@@ -1330,7 +1690,8 @@ var AdkPackage = class AdkPackage extends AdkMainObject {
|
|
|
1330
1690
|
* @param ctx - Optional ADK context (uses global context if not provided)
|
|
1331
1691
|
*/
|
|
1332
1692
|
static async get(name, ctx) {
|
|
1333
|
-
const
|
|
1693
|
+
const context = ctx ?? getGlobalContext();
|
|
1694
|
+
const pkg = new AdkPackage(context, name);
|
|
1334
1695
|
await pkg.load();
|
|
1335
1696
|
return pkg;
|
|
1336
1697
|
}
|
|
@@ -1343,7 +1704,8 @@ var AdkPackage = class AdkPackage extends AdkMainObject {
|
|
|
1343
1704
|
*/
|
|
1344
1705
|
static async exists(name, ctx) {
|
|
1345
1706
|
try {
|
|
1346
|
-
|
|
1707
|
+
const context = ctx ?? getGlobalContext();
|
|
1708
|
+
await new AdkPackage(context, name).load();
|
|
1347
1709
|
return true;
|
|
1348
1710
|
} catch {
|
|
1349
1711
|
return false;
|
|
@@ -1360,7 +1722,8 @@ var AdkPackage = class AdkPackage extends AdkMainObject {
|
|
|
1360
1722
|
* @param ctx - Optional ADK context (uses global context if not provided)
|
|
1361
1723
|
*/
|
|
1362
1724
|
static async create(name, data, options, ctx) {
|
|
1363
|
-
const
|
|
1725
|
+
const context = ctx ?? getGlobalContext();
|
|
1726
|
+
const pkg = new AdkPackage(context, name);
|
|
1364
1727
|
pkg.setData({
|
|
1365
1728
|
name,
|
|
1366
1729
|
type: "DEVC/K",
|
|
@@ -1395,7 +1758,8 @@ var AdkPackage = class AdkPackage extends AdkMainObject {
|
|
|
1395
1758
|
* @param ctx - Optional ADK context (uses global context if not provided)
|
|
1396
1759
|
*/
|
|
1397
1760
|
static async delete(name, options, ctx) {
|
|
1398
|
-
|
|
1761
|
+
const context = ctx ?? getGlobalContext();
|
|
1762
|
+
await new AdkPackage(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
1399
1763
|
...options?.transport && { corrNr: options.transport },
|
|
1400
1764
|
...options?.lockHandle && { lockHandle: options.lockHandle }
|
|
1401
1765
|
});
|
|
@@ -1655,7 +2019,8 @@ var AdkClass = class AdkClass extends AdkMainObject {
|
|
|
1655
2019
|
return this.ctx.client.adt.oo.classes;
|
|
1656
2020
|
}
|
|
1657
2021
|
static async get(name, ctx) {
|
|
1658
|
-
|
|
2022
|
+
const context = ctx ?? getGlobalContext();
|
|
2023
|
+
return new AdkClass(context, name).load();
|
|
1659
2024
|
}
|
|
1660
2025
|
/**
|
|
1661
2026
|
* Check if a class exists on SAP
|
|
@@ -1678,7 +2043,8 @@ var AdkClass = class AdkClass extends AdkMainObject {
|
|
|
1678
2043
|
* @param ctx - Optional ADK context
|
|
1679
2044
|
*/
|
|
1680
2045
|
static async create(name, description, packageName, options, ctx) {
|
|
1681
|
-
const
|
|
2046
|
+
const context = ctx ?? getGlobalContext();
|
|
2047
|
+
const cls = new AdkClass(context, name.toUpperCase());
|
|
1682
2048
|
cls.setData({
|
|
1683
2049
|
name: name.toUpperCase(),
|
|
1684
2050
|
type: "CLAS/OC",
|
|
@@ -1705,7 +2071,8 @@ var AdkClass = class AdkClass extends AdkMainObject {
|
|
|
1705
2071
|
* @param ctx - Optional ADK context
|
|
1706
2072
|
*/
|
|
1707
2073
|
static async delete(name, options, ctx) {
|
|
1708
|
-
|
|
2074
|
+
const context = ctx ?? getGlobalContext();
|
|
2075
|
+
await new AdkClass(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
1709
2076
|
corrNr: options?.transport,
|
|
1710
2077
|
lockHandle: options?.lockHandle
|
|
1711
2078
|
});
|
|
@@ -1748,7 +2115,8 @@ var AdkInterface = class AdkInterface extends AdkMainObject {
|
|
|
1748
2115
|
return this.ctx.client.adt.oo.interfaces;
|
|
1749
2116
|
}
|
|
1750
2117
|
static async get(name, ctx) {
|
|
1751
|
-
|
|
2118
|
+
const context = ctx ?? getGlobalContext();
|
|
2119
|
+
return new AdkInterface(context, name).load();
|
|
1752
2120
|
}
|
|
1753
2121
|
/**
|
|
1754
2122
|
* Check if an interface exists on SAP
|
|
@@ -1771,7 +2139,8 @@ var AdkInterface = class AdkInterface extends AdkMainObject {
|
|
|
1771
2139
|
* @param ctx - Optional ADK context
|
|
1772
2140
|
*/
|
|
1773
2141
|
static async create(name, description, packageName, options, ctx) {
|
|
1774
|
-
const
|
|
2142
|
+
const context = ctx ?? getGlobalContext();
|
|
2143
|
+
const intf = new AdkInterface(context, name.toUpperCase());
|
|
1775
2144
|
intf.setData({
|
|
1776
2145
|
name: name.toUpperCase(),
|
|
1777
2146
|
type: "INTF/OI",
|
|
@@ -1798,7 +2167,8 @@ var AdkInterface = class AdkInterface extends AdkMainObject {
|
|
|
1798
2167
|
* @param ctx - Optional ADK context
|
|
1799
2168
|
*/
|
|
1800
2169
|
static async delete(name, options, ctx) {
|
|
1801
|
-
|
|
2170
|
+
const context = ctx ?? getGlobalContext();
|
|
2171
|
+
await new AdkInterface(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
1802
2172
|
corrNr: options?.transport,
|
|
1803
2173
|
lockHandle: options?.lockHandle
|
|
1804
2174
|
});
|
|
@@ -1841,7 +2211,8 @@ var AdkProgram = class AdkProgram extends AdkMainObject {
|
|
|
1841
2211
|
return this.ctx.client.adt.programs.programs;
|
|
1842
2212
|
}
|
|
1843
2213
|
static async get(name, ctx) {
|
|
1844
|
-
|
|
2214
|
+
const context = ctx ?? getGlobalContext();
|
|
2215
|
+
return new AdkProgram(context, name).load();
|
|
1845
2216
|
}
|
|
1846
2217
|
/**
|
|
1847
2218
|
* Check if a program exists on SAP
|
|
@@ -1864,7 +2235,8 @@ var AdkProgram = class AdkProgram extends AdkMainObject {
|
|
|
1864
2235
|
* @param ctx - Optional ADK context
|
|
1865
2236
|
*/
|
|
1866
2237
|
static async create(name, description, packageName, options, ctx) {
|
|
1867
|
-
const
|
|
2238
|
+
const context = ctx ?? getGlobalContext();
|
|
2239
|
+
const prog = new AdkProgram(context, name.toUpperCase());
|
|
1868
2240
|
prog.setData({
|
|
1869
2241
|
name: name.toUpperCase(),
|
|
1870
2242
|
type: "PROG/P",
|
|
@@ -1891,7 +2263,8 @@ var AdkProgram = class AdkProgram extends AdkMainObject {
|
|
|
1891
2263
|
* @param ctx - Optional ADK context
|
|
1892
2264
|
*/
|
|
1893
2265
|
static async delete(name, options, ctx) {
|
|
1894
|
-
|
|
2266
|
+
const context = ctx ?? getGlobalContext();
|
|
2267
|
+
await new AdkProgram(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
1895
2268
|
corrNr: options?.transport,
|
|
1896
2269
|
lockHandle: options?.lockHandle
|
|
1897
2270
|
});
|
|
@@ -1952,7 +2325,8 @@ var AdkInclude = class AdkInclude extends AdkMainObject {
|
|
|
1952
2325
|
return base;
|
|
1953
2326
|
}
|
|
1954
2327
|
static async get(name, ctx) {
|
|
1955
|
-
|
|
2328
|
+
const context = ctx ?? getGlobalContext();
|
|
2329
|
+
return new AdkInclude(context, name).load();
|
|
1956
2330
|
}
|
|
1957
2331
|
/**
|
|
1958
2332
|
* Check if an include exists on SAP
|
|
@@ -1975,7 +2349,8 @@ var AdkInclude = class AdkInclude extends AdkMainObject {
|
|
|
1975
2349
|
* @param ctx - Optional ADK context
|
|
1976
2350
|
*/
|
|
1977
2351
|
static async create(name, description, packageName, options, ctx) {
|
|
1978
|
-
const
|
|
2352
|
+
const context = ctx ?? getGlobalContext();
|
|
2353
|
+
const incl = new AdkInclude(context, name.toUpperCase());
|
|
1979
2354
|
const data = {
|
|
1980
2355
|
name: name.toUpperCase(),
|
|
1981
2356
|
type: "PROG/I",
|
|
@@ -2011,7 +2386,8 @@ var AdkInclude = class AdkInclude extends AdkMainObject {
|
|
|
2011
2386
|
* @param ctx - Optional ADK context
|
|
2012
2387
|
*/
|
|
2013
2388
|
static async delete(name, options, ctx) {
|
|
2014
|
-
|
|
2389
|
+
const context = ctx ?? getGlobalContext();
|
|
2390
|
+
await new AdkInclude(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
2015
2391
|
corrNr: options?.transport,
|
|
2016
2392
|
lockHandle: options?.lockHandle
|
|
2017
2393
|
});
|
|
@@ -2054,7 +2430,8 @@ var AdkFunctionGroup = class AdkFunctionGroup extends AdkMainObject {
|
|
|
2054
2430
|
return this.ctx.client.adt.functions.groups;
|
|
2055
2431
|
}
|
|
2056
2432
|
static async get(name, ctx) {
|
|
2057
|
-
|
|
2433
|
+
const context = ctx ?? getGlobalContext();
|
|
2434
|
+
return new AdkFunctionGroup(context, name).load();
|
|
2058
2435
|
}
|
|
2059
2436
|
/**
|
|
2060
2437
|
* Check if a function group exists on SAP
|
|
@@ -2071,7 +2448,8 @@ var AdkFunctionGroup = class AdkFunctionGroup extends AdkMainObject {
|
|
|
2071
2448
|
* Create a new ABAP function group on SAP
|
|
2072
2449
|
*/
|
|
2073
2450
|
static async create(name, description, packageName, options, ctx) {
|
|
2074
|
-
const
|
|
2451
|
+
const context = ctx ?? getGlobalContext();
|
|
2452
|
+
const fugr = new AdkFunctionGroup(context, name.toUpperCase());
|
|
2075
2453
|
fugr.setData({
|
|
2076
2454
|
name: name.toUpperCase(),
|
|
2077
2455
|
type: "FUGR/F",
|
|
@@ -2094,7 +2472,8 @@ var AdkFunctionGroup = class AdkFunctionGroup extends AdkMainObject {
|
|
|
2094
2472
|
* Delete an ABAP function group from SAP
|
|
2095
2473
|
*/
|
|
2096
2474
|
static async delete(name, options, ctx) {
|
|
2097
|
-
|
|
2475
|
+
const context = ctx ?? getGlobalContext();
|
|
2476
|
+
await new AdkFunctionGroup(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
2098
2477
|
corrNr: options?.transport,
|
|
2099
2478
|
lockHandle: options?.lockHandle
|
|
2100
2479
|
});
|
|
@@ -2387,7 +2766,8 @@ var AdkFunctionModule = class AdkFunctionModule extends AdkObject {
|
|
|
2387
2766
|
* @param ctx - Optional ADK context (uses global if not provided)
|
|
2388
2767
|
*/
|
|
2389
2768
|
static async get(groupName, name, ctx) {
|
|
2390
|
-
|
|
2769
|
+
const context = ctx ?? getGlobalContext();
|
|
2770
|
+
return new AdkFunctionModule(context, groupName, name).load();
|
|
2391
2771
|
}
|
|
2392
2772
|
/**
|
|
2393
2773
|
* Check if a function module exists on SAP
|
|
@@ -2404,7 +2784,8 @@ var AdkFunctionModule = class AdkFunctionModule extends AdkObject {
|
|
|
2404
2784
|
* Create a new ABAP function module on SAP
|
|
2405
2785
|
*/
|
|
2406
2786
|
static async create(groupName, name, description, options, ctx) {
|
|
2407
|
-
const
|
|
2787
|
+
const context = ctx ?? getGlobalContext();
|
|
2788
|
+
const fm = new AdkFunctionModule(context, groupName.toUpperCase(), name.toUpperCase());
|
|
2408
2789
|
fm.setData({
|
|
2409
2790
|
name: name.toUpperCase(),
|
|
2410
2791
|
type: "FUGR/FF",
|
|
@@ -2421,7 +2802,8 @@ var AdkFunctionModule = class AdkFunctionModule extends AdkObject {
|
|
|
2421
2802
|
* Delete a function module from SAP
|
|
2422
2803
|
*/
|
|
2423
2804
|
static async delete(groupName, name, options, ctx) {
|
|
2424
|
-
|
|
2805
|
+
const context = ctx ?? getGlobalContext();
|
|
2806
|
+
await new AdkFunctionModule(context, groupName.toUpperCase(), name.toUpperCase()).crudContract.delete(groupName.toUpperCase(), name.toUpperCase(), {
|
|
2425
2807
|
corrNr: options?.transport,
|
|
2426
2808
|
lockHandle: options?.lockHandle
|
|
2427
2809
|
});
|
|
@@ -2462,7 +2844,8 @@ var AdkDomain = class AdkDomain extends AdkMainObject {
|
|
|
2462
2844
|
return this.ctx.client.adt.ddic.domains;
|
|
2463
2845
|
}
|
|
2464
2846
|
static async get(name, ctx) {
|
|
2465
|
-
|
|
2847
|
+
const context = ctx ?? getGlobalContext();
|
|
2848
|
+
return new AdkDomain(context, name).load();
|
|
2466
2849
|
}
|
|
2467
2850
|
static async exists(name, ctx) {
|
|
2468
2851
|
try {
|
|
@@ -2480,7 +2863,8 @@ var AdkDomain = class AdkDomain extends AdkMainObject {
|
|
|
2480
2863
|
* the domain properties (data type, field length, etc.).
|
|
2481
2864
|
*/
|
|
2482
2865
|
static async create(name, description, packageName, options, ctx) {
|
|
2483
|
-
const
|
|
2866
|
+
const context = ctx ?? getGlobalContext();
|
|
2867
|
+
const domain = new AdkDomain(context, name.toUpperCase());
|
|
2484
2868
|
domain.setData({
|
|
2485
2869
|
name: name.toUpperCase(),
|
|
2486
2870
|
type: "DOMA",
|
|
@@ -2500,7 +2884,8 @@ var AdkDomain = class AdkDomain extends AdkMainObject {
|
|
|
2500
2884
|
return domain;
|
|
2501
2885
|
}
|
|
2502
2886
|
static async delete(name, options, ctx) {
|
|
2503
|
-
|
|
2887
|
+
const context = ctx ?? getGlobalContext();
|
|
2888
|
+
await new AdkDomain(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
2504
2889
|
...options?.transport && { corrNr: options.transport },
|
|
2505
2890
|
...options?.lockHandle && { lockHandle: options.lockHandle }
|
|
2506
2891
|
});
|
|
@@ -2541,7 +2926,8 @@ var AdkDataElement = class AdkDataElement extends AdkMainObject {
|
|
|
2541
2926
|
return this.ctx.client.adt.ddic.dataelements;
|
|
2542
2927
|
}
|
|
2543
2928
|
static async get(name, ctx) {
|
|
2544
|
-
|
|
2929
|
+
const context = ctx ?? getGlobalContext();
|
|
2930
|
+
return new AdkDataElement(context, name).load();
|
|
2545
2931
|
}
|
|
2546
2932
|
static async exists(name, ctx) {
|
|
2547
2933
|
try {
|
|
@@ -2555,7 +2941,8 @@ var AdkDataElement = class AdkDataElement extends AdkMainObject {
|
|
|
2555
2941
|
* Create a new ABAP data element on SAP.
|
|
2556
2942
|
*/
|
|
2557
2943
|
static async create(name, description, packageName, options, ctx) {
|
|
2558
|
-
const
|
|
2944
|
+
const context = ctx ?? getGlobalContext();
|
|
2945
|
+
const dtel = new AdkDataElement(context, name.toUpperCase());
|
|
2559
2946
|
dtel.setData({
|
|
2560
2947
|
name: name.toUpperCase(),
|
|
2561
2948
|
type: "DTEL",
|
|
@@ -2575,7 +2962,8 @@ var AdkDataElement = class AdkDataElement extends AdkMainObject {
|
|
|
2575
2962
|
return dtel;
|
|
2576
2963
|
}
|
|
2577
2964
|
static async delete(name, options, ctx) {
|
|
2578
|
-
|
|
2965
|
+
const context = ctx ?? getGlobalContext();
|
|
2966
|
+
await new AdkDataElement(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
2579
2967
|
...options?.transport && { corrNr: options.transport },
|
|
2580
2968
|
...options?.lockHandle && { lockHandle: options.lockHandle }
|
|
2581
2969
|
});
|
|
@@ -2634,7 +3022,8 @@ var AdkTable = class AdkTable extends AdkMainObject {
|
|
|
2634
3022
|
return this.ctx.client.adt.ddic.tables;
|
|
2635
3023
|
}
|
|
2636
3024
|
static async get(name, ctx) {
|
|
2637
|
-
|
|
3025
|
+
const context = ctx ?? getGlobalContext();
|
|
3026
|
+
return new AdkTable(context, name).load();
|
|
2638
3027
|
}
|
|
2639
3028
|
static async exists(name, ctx) {
|
|
2640
3029
|
try {
|
|
@@ -2648,7 +3037,8 @@ var AdkTable = class AdkTable extends AdkMainObject {
|
|
|
2648
3037
|
* Create a new ABAP database table on SAP.
|
|
2649
3038
|
*/
|
|
2650
3039
|
static async create(name, description, packageName, options, ctx) {
|
|
2651
|
-
const
|
|
3040
|
+
const context = ctx ?? getGlobalContext();
|
|
3041
|
+
const table = new AdkTable(context, name.toUpperCase());
|
|
2652
3042
|
table.setData({
|
|
2653
3043
|
name: name.toUpperCase(),
|
|
2654
3044
|
type: "TABL/DT",
|
|
@@ -2668,7 +3058,8 @@ var AdkTable = class AdkTable extends AdkMainObject {
|
|
|
2668
3058
|
return table;
|
|
2669
3059
|
}
|
|
2670
3060
|
static async delete(name, options, ctx) {
|
|
2671
|
-
|
|
3061
|
+
const context = ctx ?? getGlobalContext();
|
|
3062
|
+
await new AdkTable(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
2672
3063
|
...options?.transport && { corrNr: options.transport },
|
|
2673
3064
|
...options?.lockHandle && { lockHandle: options.lockHandle }
|
|
2674
3065
|
});
|
|
@@ -2699,7 +3090,8 @@ var AdkStructure = class AdkStructure extends AdkMainObject {
|
|
|
2699
3090
|
return this.ctx.client.adt.ddic.structures;
|
|
2700
3091
|
}
|
|
2701
3092
|
static async get(name, ctx) {
|
|
2702
|
-
|
|
3093
|
+
const context = ctx ?? getGlobalContext();
|
|
3094
|
+
return new AdkStructure(context, name).load();
|
|
2703
3095
|
}
|
|
2704
3096
|
static async exists(name, ctx) {
|
|
2705
3097
|
try {
|
|
@@ -2713,7 +3105,8 @@ var AdkStructure = class AdkStructure extends AdkMainObject {
|
|
|
2713
3105
|
* Create a new ABAP structure on SAP.
|
|
2714
3106
|
*/
|
|
2715
3107
|
static async create(name, description, packageName, options, ctx) {
|
|
2716
|
-
const
|
|
3108
|
+
const context = ctx ?? getGlobalContext();
|
|
3109
|
+
const struct = new AdkStructure(context, name.toUpperCase());
|
|
2717
3110
|
struct.setData({
|
|
2718
3111
|
name: name.toUpperCase(),
|
|
2719
3112
|
type: "TABL/DS",
|
|
@@ -2733,7 +3126,8 @@ var AdkStructure = class AdkStructure extends AdkMainObject {
|
|
|
2733
3126
|
return struct;
|
|
2734
3127
|
}
|
|
2735
3128
|
static async delete(name, options, ctx) {
|
|
2736
|
-
|
|
3129
|
+
const context = ctx ?? getGlobalContext();
|
|
3130
|
+
await new AdkStructure(context, name.toUpperCase()).crudContract.delete(name.toUpperCase(), {
|
|
2737
3131
|
...options?.transport && { corrNr: options.transport },
|
|
2738
3132
|
...options?.lockHandle && { lockHandle: options.lockHandle }
|
|
2739
3133
|
});
|
|
@@ -2775,45 +3169,58 @@ var AdkTableType = class AdkTableType extends AdkMainObject {
|
|
|
2775
3169
|
return this.ctx.client.adt.ddic.tabletypes;
|
|
2776
3170
|
}
|
|
2777
3171
|
static async get(name, ctx) {
|
|
2778
|
-
|
|
3172
|
+
const context = ctx ?? getGlobalContext();
|
|
3173
|
+
return new AdkTableType(context, name).load();
|
|
2779
3174
|
}
|
|
2780
3175
|
};
|
|
2781
3176
|
registerObjectType("TTYP", TableType, AdkTableType, { endpoint: "ddic/tabletypes" });
|
|
2782
3177
|
|
|
2783
3178
|
//#endregion
|
|
2784
|
-
//#region src/objects/cds/
|
|
3179
|
+
//#region src/objects/cds/crud-source-object.ts
|
|
2785
3180
|
/**
|
|
2786
|
-
*
|
|
3181
|
+
* Shared implementation for standalone CDS/RAP source objects that support
|
|
3182
|
+
* full CRUD (get, source.main.get/put, post, delete) plus lock/unlock/activate.
|
|
2787
3183
|
*
|
|
2788
|
-
*
|
|
2789
|
-
*
|
|
2790
|
-
*
|
|
2791
|
-
*
|
|
2792
|
-
* The metadata document is at:
|
|
2793
|
-
* GET /sap/bc/adt/ddic/ddl/sources/<name>
|
|
2794
|
-
*
|
|
2795
|
-
* Lock/activate/create follow the same patterns as other source objects.
|
|
3184
|
+
* DDL, DCL, BDEF, and SRVD all follow the same lifecycle pattern:
|
|
3185
|
+
* create skeleton → PUT source → activate
|
|
3186
|
+
* This base eliminates the duplicated load/saveMainSource/lock/unlock/activate
|
|
3187
|
+
* boilerplate across those models.
|
|
2796
3188
|
*/
|
|
2797
|
-
var
|
|
3189
|
+
var AdkCrudSourceObject = class AdkCrudSourceObject {
|
|
2798
3190
|
name;
|
|
2799
3191
|
ctx;
|
|
3192
|
+
metadata;
|
|
2800
3193
|
constructor(ctx, name) {
|
|
2801
3194
|
this.ctx = ctx;
|
|
2802
3195
|
this.name = name.toUpperCase();
|
|
2803
3196
|
}
|
|
2804
3197
|
get objectUri() {
|
|
2805
|
-
return `/sap/bc/adt
|
|
3198
|
+
return `/sap/bc/adt/${this.endpoint}/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
2806
3199
|
}
|
|
2807
|
-
/** Placeholder description — full metadata requires additional SAP fetch */
|
|
2808
3200
|
get description() {
|
|
2809
|
-
|
|
3201
|
+
const key = this.getMetadataKey();
|
|
3202
|
+
return (this.metadata?.[key])?.description ?? this.name;
|
|
2810
3203
|
}
|
|
2811
|
-
get
|
|
2812
|
-
|
|
3204
|
+
get originalLanguage() {
|
|
3205
|
+
const key = this.getMetadataKey();
|
|
3206
|
+
return (this.metadata?.[key])?.masterLanguage;
|
|
3207
|
+
}
|
|
3208
|
+
get abapLanguageVersion() {
|
|
3209
|
+
const key = this.getMetadataKey();
|
|
3210
|
+
return (this.metadata?.[key])?.abapLanguageVersion;
|
|
3211
|
+
}
|
|
3212
|
+
get package() {
|
|
3213
|
+
const key = this.getMetadataKey();
|
|
3214
|
+
return (this.metadata?.[key])?.packageRef?.name;
|
|
2813
3215
|
}
|
|
2814
3216
|
async getSource() {
|
|
2815
3217
|
return toText(await this.contract.source.main.get(this.name));
|
|
2816
3218
|
}
|
|
3219
|
+
async load() {
|
|
3220
|
+
const [metadata] = await Promise.all([this.contract.get(this.name), this.getSource()]);
|
|
3221
|
+
this.metadata = metadata;
|
|
3222
|
+
return this;
|
|
3223
|
+
}
|
|
2817
3224
|
async saveMainSource(source, options) {
|
|
2818
3225
|
await this.contract.source.main.put(this.name, {
|
|
2819
3226
|
...options?.lockHandle ? { lockHandle: options.lockHandle } : {},
|
|
@@ -2826,7 +3233,7 @@ var AdkDdlSource = class AdkDdlSource {
|
|
|
2826
3233
|
return lockService.lock(this.objectUri, {
|
|
2827
3234
|
transport,
|
|
2828
3235
|
objectName: this.name,
|
|
2829
|
-
objectType:
|
|
3236
|
+
objectType: this.objectType
|
|
2830
3237
|
});
|
|
2831
3238
|
}
|
|
2832
3239
|
async unlock(lockHandle) {
|
|
@@ -2841,54 +3248,130 @@ var AdkDdlSource = class AdkDdlSource {
|
|
|
2841
3248
|
}] } });
|
|
2842
3249
|
return this;
|
|
2843
3250
|
}
|
|
3251
|
+
static resolveContext(ctx) {
|
|
3252
|
+
return ctx ?? getGlobalContext();
|
|
3253
|
+
}
|
|
2844
3254
|
/**
|
|
2845
|
-
* Get a
|
|
3255
|
+
* Get a source object (validates it exists by fetching source).
|
|
3256
|
+
* Generic helper used by static `get()` on subclasses.
|
|
2846
3257
|
*/
|
|
2847
|
-
static async
|
|
2848
|
-
const
|
|
3258
|
+
static async getSourceObject(name, ctx) {
|
|
3259
|
+
const context = AdkCrudSourceObject.resolveContext(ctx);
|
|
3260
|
+
const obj = new this(context, name);
|
|
2849
3261
|
await obj.getSource();
|
|
2850
3262
|
return obj;
|
|
2851
3263
|
}
|
|
2852
|
-
|
|
3264
|
+
/**
|
|
3265
|
+
* Check if a source object exists.
|
|
3266
|
+
* Generic helper used by static `exists()` on subclasses.
|
|
3267
|
+
*/
|
|
3268
|
+
static async sourceObjectExists(name, ctx) {
|
|
2853
3269
|
try {
|
|
2854
|
-
await
|
|
3270
|
+
await this.getSourceObject(name, ctx);
|
|
2855
3271
|
return true;
|
|
2856
3272
|
} catch {
|
|
2857
3273
|
return false;
|
|
2858
3274
|
}
|
|
2859
3275
|
}
|
|
2860
3276
|
/**
|
|
2861
|
-
*
|
|
2862
|
-
*
|
|
2863
|
-
* POST /sap/bc/adt/ddic/ddl/sources?corrNr=...
|
|
2864
|
-
* Body matches the `ddl:source` schema (extends abapsource:AbapSourceMainObject).
|
|
3277
|
+
* Shared skeleton-creation helper. Subclasses pass their contract's `post`
|
|
3278
|
+
* function and the root element name + type that their AFF schema expects.
|
|
2865
3279
|
*/
|
|
2866
|
-
static async
|
|
2867
|
-
const context = ctx
|
|
2868
|
-
const nameU = name.toUpperCase();
|
|
2869
|
-
const pkgU = packageName.toUpperCase();
|
|
2870
|
-
await
|
|
3280
|
+
static async createSourceSkeleton(params, post) {
|
|
3281
|
+
const context = AdkCrudSourceObject.resolveContext(params.ctx);
|
|
3282
|
+
const nameU = params.name.toUpperCase();
|
|
3283
|
+
const pkgU = params.packageName.toUpperCase();
|
|
3284
|
+
await post(params.transport ? { corrNr: params.transport } : {}, { [params.rootKey]: {
|
|
2871
3285
|
name: nameU,
|
|
2872
|
-
|
|
3286
|
+
...params.objectTypeCode ? { type: params.objectTypeCode } : {},
|
|
3287
|
+
description: params.description,
|
|
2873
3288
|
language: "EN",
|
|
2874
3289
|
masterLanguage: "EN",
|
|
2875
|
-
responsible: "$TMP",
|
|
3290
|
+
responsible: params.responsible ?? "$TMP",
|
|
2876
3291
|
packageRef: {
|
|
2877
3292
|
name: pkgU,
|
|
2878
3293
|
type: "DEVC/K",
|
|
2879
3294
|
uri: `/sap/bc/adt/packages/${pkgU.toLowerCase()}`
|
|
2880
3295
|
}
|
|
2881
3296
|
} });
|
|
2882
|
-
return new
|
|
3297
|
+
return new this(context, nameU);
|
|
2883
3298
|
}
|
|
2884
|
-
|
|
2885
|
-
|
|
3299
|
+
/**
|
|
3300
|
+
* Shared delete helper. Subclasses pass their contract's `delete` function.
|
|
3301
|
+
*/
|
|
3302
|
+
static async deleteSource(name, options, deleteFn) {
|
|
3303
|
+
await deleteFn(name.toUpperCase(), {
|
|
2886
3304
|
...options?.transport ? { corrNr: options.transport } : {},
|
|
2887
3305
|
...options?.lockHandle ? { lockHandle: options.lockHandle } : {}
|
|
2888
3306
|
});
|
|
2889
3307
|
}
|
|
2890
3308
|
};
|
|
2891
3309
|
|
|
3310
|
+
//#endregion
|
|
3311
|
+
//#region src/objects/cds/ddl.model.ts
|
|
3312
|
+
/**
|
|
3313
|
+
* DDL - CDS Data Definition Language Source (DDLS)
|
|
3314
|
+
*
|
|
3315
|
+
* ADK object for ABAP CDS Data Definition sources.
|
|
3316
|
+
* These are source-based objects stored at:
|
|
3317
|
+
* GET/PUT /sap/bc/adt/ddic/ddl/sources/<name>/source/main
|
|
3318
|
+
*
|
|
3319
|
+
* The metadata document is at:
|
|
3320
|
+
* GET /sap/bc/adt/ddic/ddl/sources/<name>
|
|
3321
|
+
*
|
|
3322
|
+
* Lock/activate/create follow the same patterns as other source objects.
|
|
3323
|
+
*/
|
|
3324
|
+
var AdkDdlSource = class AdkDdlSource extends AdkCrudSourceObject {
|
|
3325
|
+
static kind = DdlSource;
|
|
3326
|
+
kind = AdkDdlSource.kind;
|
|
3327
|
+
objectType = "DDLS";
|
|
3328
|
+
endpoint = "ddic/ddl/sources";
|
|
3329
|
+
get contract() {
|
|
3330
|
+
return this.ctx.client.adt.ddic.ddl.sources;
|
|
3331
|
+
}
|
|
3332
|
+
getMetadataKey() {
|
|
3333
|
+
return "ddlSource";
|
|
3334
|
+
}
|
|
3335
|
+
get sourceOrigin() {
|
|
3336
|
+
return this.metadata?.ddlSource?.source_origin;
|
|
3337
|
+
}
|
|
3338
|
+
get sourceType() {
|
|
3339
|
+
return this.metadata?.ddlSource?.source_type;
|
|
3340
|
+
}
|
|
3341
|
+
/**
|
|
3342
|
+
* Get a DDL source (does not fetch metadata, just returns handle)
|
|
3343
|
+
*/
|
|
3344
|
+
static async get(name, ctx) {
|
|
3345
|
+
return AdkCrudSourceObject.getSourceObject.call(this, name, ctx);
|
|
3346
|
+
}
|
|
3347
|
+
static async exists(name, ctx) {
|
|
3348
|
+
return AdkCrudSourceObject.sourceObjectExists.call(this, name, ctx);
|
|
3349
|
+
}
|
|
3350
|
+
/**
|
|
3351
|
+
* Create a new CDS DDL source on SAP
|
|
3352
|
+
*
|
|
3353
|
+
* POST /sap/bc/adt/ddic/ddl/sources?corrNr=...
|
|
3354
|
+
* Body matches the `ddl:source` schema (extends abapsource:AbapSourceMainObject).
|
|
3355
|
+
*/
|
|
3356
|
+
static async create(name, description, packageName, options, ctx) {
|
|
3357
|
+
const context = ctx ?? getGlobalContext();
|
|
3358
|
+
return AdkCrudSourceObject.createSourceSkeleton.call(this, {
|
|
3359
|
+
name,
|
|
3360
|
+
description,
|
|
3361
|
+
packageName,
|
|
3362
|
+
transport: options?.transport,
|
|
3363
|
+
ctx,
|
|
3364
|
+
rootKey: "source",
|
|
3365
|
+
objectTypeCode: ""
|
|
3366
|
+
}, context.client.adt.ddic.ddl.sources.post.bind(context.client.adt.ddic.ddl.sources));
|
|
3367
|
+
}
|
|
3368
|
+
static async delete(name, options, ctx) {
|
|
3369
|
+
const context = ctx ?? getGlobalContext();
|
|
3370
|
+
return AdkCrudSourceObject.deleteSource(name, options, context.client.adt.ddic.ddl.sources.delete.bind(context.client.adt.ddic.ddl.sources));
|
|
3371
|
+
}
|
|
3372
|
+
};
|
|
3373
|
+
registerObjectType("DDLS", DdlSource, AdkDdlSource, { endpoint: "ddic/ddl/sources" });
|
|
3374
|
+
|
|
2892
3375
|
//#endregion
|
|
2893
3376
|
//#region src/objects/cds/dcl.model.ts
|
|
2894
3377
|
/**
|
|
@@ -2903,94 +3386,304 @@ var AdkDdlSource = class AdkDdlSource {
|
|
|
2903
3386
|
*
|
|
2904
3387
|
* Lock/activate/create follow the same patterns as DDL sources.
|
|
2905
3388
|
*/
|
|
2906
|
-
var AdkDclSource = class AdkDclSource {
|
|
3389
|
+
var AdkDclSource = class AdkDclSource extends AdkCrudSourceObject {
|
|
3390
|
+
static kind = DclSource;
|
|
3391
|
+
kind = AdkDclSource.kind;
|
|
3392
|
+
objectType = "DCLS";
|
|
3393
|
+
endpoint = "acm/dcl/sources";
|
|
3394
|
+
get contract() {
|
|
3395
|
+
return this.ctx.client.adt.ddic.dcl.sources;
|
|
3396
|
+
}
|
|
3397
|
+
getMetadataKey() {
|
|
3398
|
+
return "dclSource";
|
|
3399
|
+
}
|
|
3400
|
+
static async get(name, ctx) {
|
|
3401
|
+
return AdkCrudSourceObject.getSourceObject.call(this, name, ctx);
|
|
3402
|
+
}
|
|
3403
|
+
static async exists(name, ctx) {
|
|
3404
|
+
return AdkCrudSourceObject.sourceObjectExists.call(this, name, ctx);
|
|
3405
|
+
}
|
|
3406
|
+
/**
|
|
3407
|
+
* Create a new CDS DCL source on SAP
|
|
3408
|
+
*/
|
|
3409
|
+
static async create(name, description, packageName, options, ctx) {
|
|
3410
|
+
const context = ctx ?? getGlobalContext();
|
|
3411
|
+
return AdkCrudSourceObject.createSourceSkeleton.call(this, {
|
|
3412
|
+
name,
|
|
3413
|
+
description,
|
|
3414
|
+
packageName,
|
|
3415
|
+
transport: options?.transport,
|
|
3416
|
+
ctx,
|
|
3417
|
+
rootKey: "source",
|
|
3418
|
+
objectTypeCode: ""
|
|
3419
|
+
}, context.client.adt.ddic.dcl.sources.post.bind(context.client.adt.ddic.dcl.sources));
|
|
3420
|
+
}
|
|
3421
|
+
static async delete(name, options, ctx) {
|
|
3422
|
+
const context = ctx ?? getGlobalContext();
|
|
3423
|
+
return AdkCrudSourceObject.deleteSource(name, options, context.client.adt.ddic.dcl.sources.delete.bind(context.client.adt.ddic.dcl.sources));
|
|
3424
|
+
}
|
|
3425
|
+
};
|
|
3426
|
+
registerObjectType("DCLS", DclSource, AdkDclSource, { endpoint: "acm/dcl/sources" });
|
|
3427
|
+
|
|
3428
|
+
//#endregion
|
|
3429
|
+
//#region src/objects/cds/ddlx.model.ts
|
|
3430
|
+
var AdkDdlExtension = class AdkDdlExtension {
|
|
3431
|
+
static kind = DdlExtension;
|
|
3432
|
+
kind = AdkDdlExtension.kind;
|
|
2907
3433
|
name;
|
|
2908
3434
|
ctx;
|
|
3435
|
+
metadata;
|
|
2909
3436
|
constructor(ctx, name) {
|
|
2910
3437
|
this.ctx = ctx;
|
|
2911
3438
|
this.name = name.toUpperCase();
|
|
2912
3439
|
}
|
|
2913
3440
|
get objectUri() {
|
|
2914
|
-
return `/sap/bc/adt/
|
|
3441
|
+
return `/sap/bc/adt/ddic/ddlx/sources/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
2915
3442
|
}
|
|
2916
|
-
/** Placeholder description — full metadata requires additional SAP fetch */
|
|
2917
3443
|
get description() {
|
|
2918
|
-
return this.name;
|
|
3444
|
+
return this.metadata?.ddlxSource?.description ?? this.name;
|
|
3445
|
+
}
|
|
3446
|
+
get originalLanguage() {
|
|
3447
|
+
return this.metadata?.ddlxSource?.masterLanguage;
|
|
3448
|
+
}
|
|
3449
|
+
get abapLanguageVersion() {
|
|
3450
|
+
return this.metadata?.ddlxSource?.abapLanguageVersion;
|
|
3451
|
+
}
|
|
3452
|
+
get package() {
|
|
3453
|
+
return this.metadata?.ddlxSource?.packageRef?.name;
|
|
2919
3454
|
}
|
|
2920
3455
|
get contract() {
|
|
2921
|
-
return this.ctx.client.adt.ddic.
|
|
3456
|
+
return this.ctx.client.adt.ddic.ddlx.sources;
|
|
2922
3457
|
}
|
|
2923
3458
|
async getSource() {
|
|
2924
3459
|
return toText(await this.contract.source.main.get(this.name));
|
|
2925
3460
|
}
|
|
2926
|
-
async
|
|
2927
|
-
await this.contract.
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
}, source);
|
|
3461
|
+
async load() {
|
|
3462
|
+
const [metadata] = await Promise.all([this.contract.get(this.name), this.getSource()]);
|
|
3463
|
+
this.metadata = metadata;
|
|
3464
|
+
return this;
|
|
2931
3465
|
}
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
3466
|
+
};
|
|
3467
|
+
registerObjectType("DDLX", DdlExtension, AdkDdlExtension, { endpoint: "ddic/ddlx/sources" });
|
|
3468
|
+
|
|
3469
|
+
//#endregion
|
|
3470
|
+
//#region src/objects/cds/source-object.ts
|
|
3471
|
+
/** Minimal shared implementation for CDS source objects used by import. */
|
|
3472
|
+
var AdkCdsSourceObject = class {
|
|
3473
|
+
name;
|
|
3474
|
+
ctx;
|
|
3475
|
+
metadata;
|
|
3476
|
+
constructor(ctx, name) {
|
|
3477
|
+
this.ctx = ctx;
|
|
3478
|
+
this.name = name.toUpperCase();
|
|
2940
3479
|
}
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
if (!lockService) throw new Error("Unlock not available: no lockService in context. Did you call initializeAdk()?");
|
|
2944
|
-
await lockService.unlock(this.objectUri, { lockHandle });
|
|
3480
|
+
get objectUri() {
|
|
3481
|
+
return `/sap/bc/adt/${this.endpoint}/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
2945
3482
|
}
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
3483
|
+
get description() {
|
|
3484
|
+
return this.metadata?.blueSource?.description ?? this.name;
|
|
3485
|
+
}
|
|
3486
|
+
get originalLanguage() {
|
|
3487
|
+
return this.metadata?.blueSource?.masterLanguage;
|
|
3488
|
+
}
|
|
3489
|
+
get abapLanguageVersion() {
|
|
3490
|
+
return this.metadata?.blueSource?.abapLanguageVersion;
|
|
3491
|
+
}
|
|
3492
|
+
get package() {
|
|
3493
|
+
return this.metadata?.blueSource?.packageRef?.name;
|
|
3494
|
+
}
|
|
3495
|
+
async getSource() {
|
|
3496
|
+
return toText(await this.contract.source.main.get(this.name));
|
|
3497
|
+
}
|
|
3498
|
+
async load() {
|
|
3499
|
+
const [metadata] = await Promise.all([this.contract.get(this.name), this.getSource()]);
|
|
3500
|
+
this.metadata = metadata;
|
|
2951
3501
|
return this;
|
|
2952
3502
|
}
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
3503
|
+
};
|
|
3504
|
+
|
|
3505
|
+
//#endregion
|
|
3506
|
+
//#region src/objects/cds/dsfd.model.ts
|
|
3507
|
+
var AdkScalarFunctionDefinition = class AdkScalarFunctionDefinition extends AdkCdsSourceObject {
|
|
3508
|
+
static kind = ScalarFunctionDefinition;
|
|
3509
|
+
kind = AdkScalarFunctionDefinition.kind;
|
|
3510
|
+
endpoint = "ddic/dsfd/sources";
|
|
3511
|
+
constructor(ctx, name) {
|
|
3512
|
+
super(ctx, name);
|
|
2957
3513
|
}
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
await AdkDclSource.get(name, ctx);
|
|
2961
|
-
return true;
|
|
2962
|
-
} catch {
|
|
2963
|
-
return false;
|
|
2964
|
-
}
|
|
3514
|
+
get contract() {
|
|
3515
|
+
return this.ctx.client.adt.ddic.dsfd.sources;
|
|
2965
3516
|
}
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
name: pkgU,
|
|
2981
|
-
type: "DEVC/K",
|
|
2982
|
-
uri: `/sap/bc/adt/packages/${pkgU.toLowerCase()}`
|
|
2983
|
-
}
|
|
2984
|
-
} });
|
|
2985
|
-
return new AdkDclSource(context, nameU);
|
|
3517
|
+
};
|
|
3518
|
+
registerObjectType("DSFD", ScalarFunctionDefinition, AdkScalarFunctionDefinition, { endpoint: "ddic/dsfd/sources" });
|
|
3519
|
+
|
|
3520
|
+
//#endregion
|
|
3521
|
+
//#region src/objects/cds/dsfi.model.ts
|
|
3522
|
+
var AdkScalarFunctionImplementation = class AdkScalarFunctionImplementation {
|
|
3523
|
+
static kind = ScalarFunctionImplementation;
|
|
3524
|
+
kind = AdkScalarFunctionImplementation.kind;
|
|
3525
|
+
name;
|
|
3526
|
+
ctx;
|
|
3527
|
+
definition;
|
|
3528
|
+
constructor(ctx, name) {
|
|
3529
|
+
this.ctx = ctx;
|
|
3530
|
+
this.name = name.toUpperCase();
|
|
2986
3531
|
}
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3532
|
+
get objectUri() {
|
|
3533
|
+
return `/sap/bc/adt/ddic/dsfi/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3534
|
+
}
|
|
3535
|
+
get contract() {
|
|
3536
|
+
return this.ctx.client.adt.ddic.dsfi;
|
|
3537
|
+
}
|
|
3538
|
+
async getSource() {
|
|
3539
|
+
return this.definition ?? this.contract.source.main.get(this.name);
|
|
3540
|
+
}
|
|
3541
|
+
async load() {
|
|
3542
|
+
const [, definition] = await Promise.all([this.contract.get(this.name), this.contract.source.main.get(this.name)]);
|
|
3543
|
+
this.definition = definition;
|
|
3544
|
+
return this;
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
registerObjectType("DSFI", ScalarFunctionImplementation, AdkScalarFunctionImplementation, { endpoint: "ddic/dsfi" });
|
|
3548
|
+
|
|
3549
|
+
//#endregion
|
|
3550
|
+
//#region src/objects/cds/dteb.model.ts
|
|
3551
|
+
var AdkEntityBuffer = class AdkEntityBuffer extends AdkCdsSourceObject {
|
|
3552
|
+
static kind = EntityBuffer;
|
|
3553
|
+
kind = AdkEntityBuffer.kind;
|
|
3554
|
+
endpoint = "ddic/dteb/sources";
|
|
3555
|
+
constructor(ctx, name) {
|
|
3556
|
+
super(ctx, name);
|
|
3557
|
+
}
|
|
3558
|
+
get contract() {
|
|
3559
|
+
return this.ctx.client.adt.ddic.dteb.sources;
|
|
2992
3560
|
}
|
|
2993
3561
|
};
|
|
3562
|
+
registerObjectType("DTEB", EntityBuffer, AdkEntityBuffer, { endpoint: "ddic/dteb/sources" });
|
|
3563
|
+
|
|
3564
|
+
//#endregion
|
|
3565
|
+
//#region src/objects/cds/source-only-object.ts
|
|
3566
|
+
/**
|
|
3567
|
+
* CDS source object without a metadata schema in the connected ABAP release.
|
|
3568
|
+
*
|
|
3569
|
+
* DRAS and DRTY are absent from the reference system's repository search, so their source
|
|
3570
|
+
* endpoint is represented by the ADT DDIC naming convention and exercised
|
|
3571
|
+
* with official ABAP File Formats fixtures. The object is intentionally
|
|
3572
|
+
* source-first: import only needs the immutable source and a safe header.
|
|
3573
|
+
*/
|
|
3574
|
+
var AdkSourceOnlyCdsObject = class {
|
|
3575
|
+
name;
|
|
3576
|
+
ctx;
|
|
3577
|
+
source;
|
|
3578
|
+
constructor(ctx, name) {
|
|
3579
|
+
this.ctx = ctx;
|
|
3580
|
+
this.name = name.toUpperCase();
|
|
3581
|
+
}
|
|
3582
|
+
get objectUri() {
|
|
3583
|
+
return `/sap/bc/adt/${this.endpoint}/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3584
|
+
}
|
|
3585
|
+
get description() {
|
|
3586
|
+
return this.name;
|
|
3587
|
+
}
|
|
3588
|
+
get originalLanguage() {
|
|
3589
|
+
return "EN";
|
|
3590
|
+
}
|
|
3591
|
+
async getSource() {
|
|
3592
|
+
this.source ??= await this.ctx.client.readTextBounded(`${this.objectUri}/source/main`, 5242880, { headers: { Accept: "text/plain" } });
|
|
3593
|
+
return this.source;
|
|
3594
|
+
}
|
|
3595
|
+
async load() {
|
|
3596
|
+
await this.getSource();
|
|
3597
|
+
return this;
|
|
3598
|
+
}
|
|
3599
|
+
};
|
|
3600
|
+
|
|
3601
|
+
//#endregion
|
|
3602
|
+
//#region src/objects/cds/dras.model.ts
|
|
3603
|
+
var AdkCdsAspect = class AdkCdsAspect extends AdkSourceOnlyCdsObject {
|
|
3604
|
+
static kind = CdsAspect;
|
|
3605
|
+
kind = AdkCdsAspect.kind;
|
|
3606
|
+
endpoint = "ddic/dras/sources";
|
|
3607
|
+
constructor(ctx, name) {
|
|
3608
|
+
super(ctx, name);
|
|
3609
|
+
}
|
|
3610
|
+
};
|
|
3611
|
+
registerObjectType("DRAS", CdsAspect, AdkCdsAspect, { endpoint: "ddic/dras/sources" });
|
|
3612
|
+
|
|
3613
|
+
//#endregion
|
|
3614
|
+
//#region src/objects/cds/drty.model.ts
|
|
3615
|
+
var AdkCdsType = class AdkCdsType extends AdkSourceOnlyCdsObject {
|
|
3616
|
+
static kind = CdsType;
|
|
3617
|
+
kind = AdkCdsType.kind;
|
|
3618
|
+
endpoint = "ddic/drty/sources";
|
|
3619
|
+
constructor(ctx, name) {
|
|
3620
|
+
super(ctx, name);
|
|
3621
|
+
}
|
|
3622
|
+
};
|
|
3623
|
+
registerObjectType("DRTY", CdsType, AdkCdsType, { endpoint: "ddic/drty/sources" });
|
|
3624
|
+
|
|
3625
|
+
//#endregion
|
|
3626
|
+
//#region src/objects/cds/dtdc.model.ts
|
|
3627
|
+
var AdkDynamicCache = class AdkDynamicCache extends AdkSourceOnlyCdsObject {
|
|
3628
|
+
static kind = DynamicCache;
|
|
3629
|
+
kind = AdkDynamicCache.kind;
|
|
3630
|
+
endpoint = "ddic/dtdc/sources";
|
|
3631
|
+
constructor(ctx, name) {
|
|
3632
|
+
super(ctx, name);
|
|
3633
|
+
}
|
|
3634
|
+
};
|
|
3635
|
+
registerObjectType("DTDC", DynamicCache, AdkDynamicCache, { endpoint: "ddic/dtdc/sources" });
|
|
3636
|
+
|
|
3637
|
+
//#endregion
|
|
3638
|
+
//#region src/objects/cds/dtix.model.ts
|
|
3639
|
+
var AdkTuningIndex = class AdkTuningIndex extends AdkSourceOnlyCdsObject {
|
|
3640
|
+
static kind = TuningIndex;
|
|
3641
|
+
kind = AdkTuningIndex.kind;
|
|
3642
|
+
endpoint = "ddic/dtix/sources";
|
|
3643
|
+
constructor(ctx, name) {
|
|
3644
|
+
super(ctx, name);
|
|
3645
|
+
}
|
|
3646
|
+
};
|
|
3647
|
+
registerObjectType("DTIX", TuningIndex, AdkTuningIndex, { endpoint: "ddic/dtix/sources" });
|
|
3648
|
+
|
|
3649
|
+
//#endregion
|
|
3650
|
+
//#region src/objects/cds/dtsc.model.ts
|
|
3651
|
+
var AdkStaticCache = class AdkStaticCache extends AdkSourceOnlyCdsObject {
|
|
3652
|
+
static kind = StaticCache;
|
|
3653
|
+
kind = AdkStaticCache.kind;
|
|
3654
|
+
endpoint = "ddic/dtsc/sources";
|
|
3655
|
+
constructor(ctx, name) {
|
|
3656
|
+
super(ctx, name);
|
|
3657
|
+
}
|
|
3658
|
+
};
|
|
3659
|
+
registerObjectType("DTSC", StaticCache, AdkStaticCache, { endpoint: "ddic/dtsc/sources" });
|
|
3660
|
+
|
|
3661
|
+
//#endregion
|
|
3662
|
+
//#region src/objects/cds/desd.model.ts
|
|
3663
|
+
var AdkExternalSchema = class AdkExternalSchema {
|
|
3664
|
+
static kind = ExternalSchema;
|
|
3665
|
+
kind = AdkExternalSchema.kind;
|
|
3666
|
+
name;
|
|
3667
|
+
ctx;
|
|
3668
|
+
constructor(ctx, name) {
|
|
3669
|
+
this.ctx = ctx;
|
|
3670
|
+
this.name = name.toUpperCase();
|
|
3671
|
+
}
|
|
3672
|
+
get objectUri() {
|
|
3673
|
+
return `/sap/bc/adt/ddic/desd/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3674
|
+
}
|
|
3675
|
+
get description() {
|
|
3676
|
+
return this.name;
|
|
3677
|
+
}
|
|
3678
|
+
get originalLanguage() {
|
|
3679
|
+
return "EN";
|
|
3680
|
+
}
|
|
3681
|
+
async load() {
|
|
3682
|
+
await this.ctx.client.readTextBounded(this.objectUri, 5242880, { headers: { Accept: "application/xml" } });
|
|
3683
|
+
return this;
|
|
3684
|
+
}
|
|
3685
|
+
};
|
|
3686
|
+
registerObjectType("DESD", ExternalSchema, AdkExternalSchema, { endpoint: "ddic/desd" });
|
|
2994
3687
|
|
|
2995
3688
|
//#endregion
|
|
2996
3689
|
//#region src/objects/repository/bdef/bdef.model.ts
|
|
@@ -3010,71 +3703,26 @@ var AdkDclSource = class AdkDclSource {
|
|
|
3010
3703
|
* not a full AdkMainObject subclass) because BDEF metadata is source-driven
|
|
3011
3704
|
* and the typical lifecycle is: create skeleton → PUT source → activate.
|
|
3012
3705
|
*/
|
|
3013
|
-
var AdkBehaviorDefinition = class AdkBehaviorDefinition {
|
|
3706
|
+
var AdkBehaviorDefinition = class AdkBehaviorDefinition extends AdkCrudSourceObject {
|
|
3014
3707
|
/** Static ADK kind marker — used by abapGit handler registry if needed. */
|
|
3015
|
-
static kind =
|
|
3708
|
+
static kind = BehaviorDefinition;
|
|
3016
3709
|
kind = AdkBehaviorDefinition.kind;
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
constructor(ctx, name) {
|
|
3020
|
-
this.ctx = ctx;
|
|
3021
|
-
this.name = name.toUpperCase();
|
|
3022
|
-
}
|
|
3023
|
-
get objectUri() {
|
|
3024
|
-
return `/sap/bc/adt/bo/behaviordefinitions/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3025
|
-
}
|
|
3026
|
-
/** Placeholder description — full metadata requires additional SAP fetch */
|
|
3027
|
-
get description() {
|
|
3028
|
-
return this.name;
|
|
3029
|
-
}
|
|
3710
|
+
objectType = "BDEF";
|
|
3711
|
+
endpoint = "bo/behaviordefinitions";
|
|
3030
3712
|
get contract() {
|
|
3031
3713
|
return this.ctx.client.adt.bo.behaviordefinitions;
|
|
3032
3714
|
}
|
|
3033
|
-
|
|
3034
|
-
return
|
|
3035
|
-
}
|
|
3036
|
-
async saveMainSource(source, options) {
|
|
3037
|
-
await this.contract.source.main.put(this.name, {
|
|
3038
|
-
...options?.lockHandle ? { lockHandle: options.lockHandle } : {},
|
|
3039
|
-
...options?.transport ? { corrNr: options.transport } : {}
|
|
3040
|
-
}, source);
|
|
3041
|
-
}
|
|
3042
|
-
async lock(transport) {
|
|
3043
|
-
const lockService = this.ctx.lockService;
|
|
3044
|
-
if (!lockService) throw new Error("Lock not available: no lockService in context. Did you call initializeAdk()?");
|
|
3045
|
-
return lockService.lock(this.objectUri, {
|
|
3046
|
-
transport,
|
|
3047
|
-
objectName: this.name,
|
|
3048
|
-
objectType: "BDEF"
|
|
3049
|
-
});
|
|
3050
|
-
}
|
|
3051
|
-
async unlock(lockHandle) {
|
|
3052
|
-
const lockService = this.ctx.lockService;
|
|
3053
|
-
if (!lockService) throw new Error("Unlock not available: no lockService in context. Did you call initializeAdk()?");
|
|
3054
|
-
await lockService.unlock(this.objectUri, { lockHandle });
|
|
3055
|
-
}
|
|
3056
|
-
async activate() {
|
|
3057
|
-
await this.ctx.client.adt.activation.activate.post({}, { objectReferences: { objectReference: [{
|
|
3058
|
-
uri: this.objectUri,
|
|
3059
|
-
name: this.name
|
|
3060
|
-
}] } });
|
|
3061
|
-
return this;
|
|
3715
|
+
getMetadataKey() {
|
|
3716
|
+
return "blueSource";
|
|
3062
3717
|
}
|
|
3063
3718
|
/**
|
|
3064
3719
|
* Get a BDEF (validates it exists by fetching source).
|
|
3065
3720
|
*/
|
|
3066
3721
|
static async get(name, ctx) {
|
|
3067
|
-
|
|
3068
|
-
await obj.getSource();
|
|
3069
|
-
return obj;
|
|
3722
|
+
return AdkCrudSourceObject.getSourceObject.call(this, name, ctx);
|
|
3070
3723
|
}
|
|
3071
3724
|
static async exists(name, ctx) {
|
|
3072
|
-
|
|
3073
|
-
await AdkBehaviorDefinition.get(name, ctx);
|
|
3074
|
-
return true;
|
|
3075
|
-
} catch {
|
|
3076
|
-
return false;
|
|
3077
|
-
}
|
|
3725
|
+
return AdkCrudSourceObject.sourceObjectExists.call(this, name, ctx);
|
|
3078
3726
|
}
|
|
3079
3727
|
/**
|
|
3080
3728
|
* Create a new BDEF on SAP.
|
|
@@ -3085,30 +3733,23 @@ var AdkBehaviorDefinition = class AdkBehaviorDefinition {
|
|
|
3085
3733
|
*/
|
|
3086
3734
|
static async create(name, description, packageName, options, ctx) {
|
|
3087
3735
|
const context = ctx ?? getGlobalContext();
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
await context.client.adt.bo.behaviordefinitions.post(options?.transport ? { corrNr: options.transport } : {}, { blueSource: {
|
|
3091
|
-
name: nameU,
|
|
3092
|
-
type: "BDEF/BDO",
|
|
3736
|
+
return AdkCrudSourceObject.createSourceSkeleton.call(this, {
|
|
3737
|
+
name,
|
|
3093
3738
|
description,
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
}
|
|
3102
|
-
} });
|
|
3103
|
-
return new AdkBehaviorDefinition(context, nameU);
|
|
3739
|
+
packageName,
|
|
3740
|
+
transport: options?.transport,
|
|
3741
|
+
ctx,
|
|
3742
|
+
rootKey: "blueSource",
|
|
3743
|
+
objectTypeCode: "BDEF/BDO",
|
|
3744
|
+
responsible: packageName.toUpperCase()
|
|
3745
|
+
}, context.client.adt.bo.behaviordefinitions.post.bind(context.client.adt.bo.behaviordefinitions));
|
|
3104
3746
|
}
|
|
3105
3747
|
static async delete(name, options, ctx) {
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
...options?.lockHandle ? { lockHandle: options.lockHandle } : {}
|
|
3109
|
-
});
|
|
3748
|
+
const context = ctx ?? getGlobalContext();
|
|
3749
|
+
return AdkCrudSourceObject.deleteSource(name, options, context.client.adt.bo.behaviordefinitions.delete.bind(context.client.adt.bo.behaviordefinitions));
|
|
3110
3750
|
}
|
|
3111
3751
|
};
|
|
3752
|
+
registerObjectType("BDEF", BehaviorDefinition, AdkBehaviorDefinition, { endpoint: "bo/behaviordefinitions" });
|
|
3112
3753
|
|
|
3113
3754
|
//#endregion
|
|
3114
3755
|
//#region src/objects/repository/badi/badi.model.ts
|
|
@@ -3134,6 +3775,8 @@ var AdkBadi = class AdkBadi {
|
|
|
3134
3775
|
kind = AdkBadi.kind;
|
|
3135
3776
|
name;
|
|
3136
3777
|
ctx;
|
|
3778
|
+
_description;
|
|
3779
|
+
_package;
|
|
3137
3780
|
constructor(ctx, name) {
|
|
3138
3781
|
this.ctx = ctx;
|
|
3139
3782
|
this.name = name.toUpperCase();
|
|
@@ -3142,18 +3785,27 @@ var AdkBadi = class AdkBadi {
|
|
|
3142
3785
|
get objectUri() {
|
|
3143
3786
|
return `/sap/bc/adt/enhancements/enhoxhh/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3144
3787
|
}
|
|
3145
|
-
/**
|
|
3788
|
+
/** Description from the ENHO metadata, falling back to the object name. */
|
|
3146
3789
|
get description() {
|
|
3147
|
-
return this.name;
|
|
3790
|
+
return this._description || this.name;
|
|
3791
|
+
}
|
|
3792
|
+
/** Package name from the ENHO metadata. */
|
|
3793
|
+
get package() {
|
|
3794
|
+
return this._package || "";
|
|
3148
3795
|
}
|
|
3149
3796
|
get contract() {
|
|
3150
3797
|
return this.ctx.client.adt.enhancements.enhoxhh;
|
|
3151
3798
|
}
|
|
3152
3799
|
async getMetadata() {
|
|
3153
|
-
|
|
3800
|
+
const data = await this.contract.get(this.name);
|
|
3801
|
+
const impl = data?.enhancementImplementation ?? data;
|
|
3802
|
+
this._description = impl?.description ?? "";
|
|
3803
|
+
this._package = impl?.packageRef?.name ?? "";
|
|
3804
|
+
return data;
|
|
3154
3805
|
}
|
|
3155
3806
|
async getSource() {
|
|
3156
|
-
|
|
3807
|
+
const result = await this.contract.source.main.get(this.name);
|
|
3808
|
+
return toText(result);
|
|
3157
3809
|
}
|
|
3158
3810
|
async saveMainSource(source, options) {
|
|
3159
3811
|
await this.contract.source.main.put(this.name, {
|
|
@@ -3184,7 +3836,8 @@ var AdkBadi = class AdkBadi {
|
|
|
3184
3836
|
}
|
|
3185
3837
|
/** Fetch a BAdI / ENHO, validating existence via a metadata GET. */
|
|
3186
3838
|
static async get(name, ctx) {
|
|
3187
|
-
const
|
|
3839
|
+
const context = ctx ?? getGlobalContext();
|
|
3840
|
+
const obj = new AdkBadi(context, name);
|
|
3188
3841
|
await obj.getMetadata();
|
|
3189
3842
|
return obj;
|
|
3190
3843
|
}
|
|
@@ -3229,6 +3882,63 @@ var AdkBadi = class AdkBadi {
|
|
|
3229
3882
|
}
|
|
3230
3883
|
};
|
|
3231
3884
|
|
|
3885
|
+
//#endregion
|
|
3886
|
+
//#region src/objects/repository/classic-badi/classic-badi.model.ts
|
|
3887
|
+
/**
|
|
3888
|
+
* Classic BAdI — read-only ADK models for SXSD/XD and SXCI/XI metadata.
|
|
3889
|
+
*
|
|
3890
|
+
* Served via vit/wb Basic Object Properties:
|
|
3891
|
+
* GET /sap/bc/adt/vit/wb/object_type/sxsdxd/object_name/{name}
|
|
3892
|
+
* GET /sap/bc/adt/vit/wb/object_type/sxcixi/object_name/{name}
|
|
3893
|
+
*/
|
|
3894
|
+
function isNotFound(error) {
|
|
3895
|
+
return typeof error === "object" && error !== null && error.status === 404;
|
|
3896
|
+
}
|
|
3897
|
+
var AdkClassicBadiBase = class {
|
|
3898
|
+
name;
|
|
3899
|
+
ctx;
|
|
3900
|
+
constructor(input) {
|
|
3901
|
+
this.ctx = input.ctx;
|
|
3902
|
+
this.name = input.name.toUpperCase();
|
|
3903
|
+
}
|
|
3904
|
+
static async get(input) {
|
|
3905
|
+
const context = input.ctx ?? getGlobalContext();
|
|
3906
|
+
const obj = new this({
|
|
3907
|
+
ctx: context,
|
|
3908
|
+
name: input.name
|
|
3909
|
+
});
|
|
3910
|
+
await obj.getMetadata();
|
|
3911
|
+
return obj;
|
|
3912
|
+
}
|
|
3913
|
+
static async exists(input) {
|
|
3914
|
+
try {
|
|
3915
|
+
await this.get(input);
|
|
3916
|
+
return true;
|
|
3917
|
+
} catch (error) {
|
|
3918
|
+
if (!isNotFound(error)) throw error;
|
|
3919
|
+
return false;
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
};
|
|
3923
|
+
var AdkClassicBadiDefinition = class extends AdkClassicBadiBase {
|
|
3924
|
+
kind = "ClassicBadiDefinition";
|
|
3925
|
+
get objectUri() {
|
|
3926
|
+
return `/sap/bc/adt/vit/wb/object_type/sxsdxd/object_name/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3927
|
+
}
|
|
3928
|
+
async getMetadata() {
|
|
3929
|
+
return await this.ctx.client.adt.vit.wb.objectProperties.getDefinition(this.name);
|
|
3930
|
+
}
|
|
3931
|
+
};
|
|
3932
|
+
var AdkClassicBadiImplementation = class extends AdkClassicBadiBase {
|
|
3933
|
+
kind = "ClassicBadiImplementation";
|
|
3934
|
+
get objectUri() {
|
|
3935
|
+
return `/sap/bc/adt/vit/wb/object_type/sxcixi/object_name/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3936
|
+
}
|
|
3937
|
+
async getMetadata() {
|
|
3938
|
+
return await this.ctx.client.adt.vit.wb.objectProperties.getImplementation(this.name);
|
|
3939
|
+
}
|
|
3940
|
+
};
|
|
3941
|
+
|
|
3232
3942
|
//#endregion
|
|
3233
3943
|
//#region src/objects/repository/srvd/srvd.model.ts
|
|
3234
3944
|
/**
|
|
@@ -3242,72 +3952,33 @@ var AdkBadi = class AdkBadi {
|
|
|
3242
3952
|
* Lock/activate/create follow the same patterns as other source objects
|
|
3243
3953
|
* (DDL, DCL, BDEF). Metadata envelope is the dedicated `srvd:source`
|
|
3244
3954
|
* wrapper extending abapsource:AbapSourceMainObject (mirrors DDL).
|
|
3245
|
-
*/
|
|
3246
|
-
var AdkServiceDefinition = class AdkServiceDefinition {
|
|
3247
|
-
/** Static ADK kind marker — used by abapGit handler registry if needed. */
|
|
3248
|
-
static kind =
|
|
3249
|
-
kind = AdkServiceDefinition.kind;
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
this.ctx
|
|
3254
|
-
this.name = name.toUpperCase();
|
|
3255
|
-
}
|
|
3256
|
-
get objectUri() {
|
|
3257
|
-
return `/sap/bc/adt/ddic/srvd/sources/${encodeURIComponent(this.name.toLowerCase())}`;
|
|
3258
|
-
}
|
|
3259
|
-
/** Placeholder description — full metadata requires additional SAP fetch */
|
|
3260
|
-
get description() {
|
|
3261
|
-
return this.name;
|
|
3262
|
-
}
|
|
3263
|
-
get contract() {
|
|
3264
|
-
return this.ctx.client.adt.ddic.srvd.sources;
|
|
3265
|
-
}
|
|
3266
|
-
async getSource() {
|
|
3267
|
-
return toText(await this.contract.source.main.get(this.name));
|
|
3268
|
-
}
|
|
3269
|
-
async saveMainSource(source, options) {
|
|
3270
|
-
await this.contract.source.main.put(this.name, {
|
|
3271
|
-
...options?.lockHandle ? { lockHandle: options.lockHandle } : {},
|
|
3272
|
-
...options?.transport ? { corrNr: options.transport } : {}
|
|
3273
|
-
}, source);
|
|
3274
|
-
}
|
|
3275
|
-
async lock(transport) {
|
|
3276
|
-
const lockService = this.ctx.lockService;
|
|
3277
|
-
if (!lockService) throw new Error("Lock not available: no lockService in context. Did you call initializeAdk()?");
|
|
3278
|
-
return lockService.lock(this.objectUri, {
|
|
3279
|
-
transport,
|
|
3280
|
-
objectName: this.name,
|
|
3281
|
-
objectType: "SRVD"
|
|
3282
|
-
});
|
|
3955
|
+
*/
|
|
3956
|
+
var AdkServiceDefinition = class AdkServiceDefinition extends AdkCrudSourceObject {
|
|
3957
|
+
/** Static ADK kind marker — used by abapGit handler registry if needed. */
|
|
3958
|
+
static kind = ServiceDefinition;
|
|
3959
|
+
kind = AdkServiceDefinition.kind;
|
|
3960
|
+
objectType = "SRVD";
|
|
3961
|
+
endpoint = "ddic/srvd/sources";
|
|
3962
|
+
get contract() {
|
|
3963
|
+
return this.ctx.client.adt.ddic.srvd.sources;
|
|
3283
3964
|
}
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
if (!lockService) throw new Error("Unlock not available: no lockService in context. Did you call initializeAdk()?");
|
|
3287
|
-
await lockService.unlock(this.objectUri, { lockHandle });
|
|
3965
|
+
getMetadataKey() {
|
|
3966
|
+
return "srvdSource";
|
|
3288
3967
|
}
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
return this;
|
|
3968
|
+
get sourceOrigin() {
|
|
3969
|
+
return this.metadata?.srvdSource?.sourceOrigin;
|
|
3970
|
+
}
|
|
3971
|
+
get sourceType() {
|
|
3972
|
+
return this.metadata?.srvdSource?.srvdSourceType;
|
|
3295
3973
|
}
|
|
3296
3974
|
/**
|
|
3297
3975
|
* Get a SRVD (validates it exists by fetching source).
|
|
3298
3976
|
*/
|
|
3299
3977
|
static async get(name, ctx) {
|
|
3300
|
-
|
|
3301
|
-
await obj.getSource();
|
|
3302
|
-
return obj;
|
|
3978
|
+
return AdkCrudSourceObject.getSourceObject.call(this, name, ctx);
|
|
3303
3979
|
}
|
|
3304
3980
|
static async exists(name, ctx) {
|
|
3305
|
-
|
|
3306
|
-
await AdkServiceDefinition.get(name, ctx);
|
|
3307
|
-
return true;
|
|
3308
|
-
} catch {
|
|
3309
|
-
return false;
|
|
3310
|
-
}
|
|
3981
|
+
return AdkCrudSourceObject.sourceObjectExists.call(this, name, ctx);
|
|
3311
3982
|
}
|
|
3312
3983
|
/**
|
|
3313
3984
|
* Create a new SRVD on SAP.
|
|
@@ -3318,30 +3989,23 @@ var AdkServiceDefinition = class AdkServiceDefinition {
|
|
|
3318
3989
|
*/
|
|
3319
3990
|
static async create(name, description, packageName, options, ctx) {
|
|
3320
3991
|
const context = ctx ?? getGlobalContext();
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
await context.client.adt.ddic.srvd.sources.post(options?.transport ? { corrNr: options.transport } : {}, { source: {
|
|
3324
|
-
name: nameU,
|
|
3325
|
-
type: "SRVD/SRV",
|
|
3992
|
+
return AdkCrudSourceObject.createSourceSkeleton.call(this, {
|
|
3993
|
+
name,
|
|
3326
3994
|
description,
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
}
|
|
3335
|
-
} });
|
|
3336
|
-
return new AdkServiceDefinition(context, nameU);
|
|
3995
|
+
packageName,
|
|
3996
|
+
transport: options?.transport,
|
|
3997
|
+
ctx,
|
|
3998
|
+
rootKey: "srvdSource",
|
|
3999
|
+
objectTypeCode: "SRVD/SRV",
|
|
4000
|
+
responsible: packageName.toUpperCase()
|
|
4001
|
+
}, context.client.adt.ddic.srvd.sources.post.bind(context.client.adt.ddic.srvd.sources));
|
|
3337
4002
|
}
|
|
3338
4003
|
static async delete(name, options, ctx) {
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
...options?.lockHandle ? { lockHandle: options.lockHandle } : {}
|
|
3342
|
-
});
|
|
4004
|
+
const context = ctx ?? getGlobalContext();
|
|
4005
|
+
return AdkCrudSourceObject.deleteSource(name, options, context.client.adt.ddic.srvd.sources.delete.bind(context.client.adt.ddic.srvd.sources));
|
|
3343
4006
|
}
|
|
3344
4007
|
};
|
|
4008
|
+
registerObjectType("SRVD", ServiceDefinition, AdkServiceDefinition, { endpoint: "ddic/srvd/sources" });
|
|
3345
4009
|
|
|
3346
4010
|
//#endregion
|
|
3347
4011
|
//#region src/objects/repository/srvb/srvb.model.ts
|
|
@@ -3363,7 +4027,7 @@ var AdkServiceDefinition = class AdkServiceDefinition {
|
|
|
3363
4027
|
*/
|
|
3364
4028
|
var AdkServiceBinding = class AdkServiceBinding {
|
|
3365
4029
|
/** Static ADK kind marker — used by abapGit handler registry if needed. */
|
|
3366
|
-
static kind =
|
|
4030
|
+
static kind = ServiceBinding;
|
|
3367
4031
|
kind = AdkServiceBinding.kind;
|
|
3368
4032
|
name;
|
|
3369
4033
|
ctx;
|
|
@@ -3391,6 +4055,10 @@ var AdkServiceBinding = class AdkServiceBinding {
|
|
|
3391
4055
|
async getSource() {
|
|
3392
4056
|
return "";
|
|
3393
4057
|
}
|
|
4058
|
+
async load() {
|
|
4059
|
+
await this.getMetadata();
|
|
4060
|
+
return this;
|
|
4061
|
+
}
|
|
3394
4062
|
async lock(transport) {
|
|
3395
4063
|
const lockService = this.ctx.lockService;
|
|
3396
4064
|
if (!lockService) throw new Error("Lock not available: no lockService in context. Did you call initializeAdk()?");
|
|
@@ -3430,7 +4098,8 @@ var AdkServiceBinding = class AdkServiceBinding {
|
|
|
3430
4098
|
* Get a SRVB (validates it exists by fetching metadata).
|
|
3431
4099
|
*/
|
|
3432
4100
|
static async get(name, ctx) {
|
|
3433
|
-
const
|
|
4101
|
+
const context = ctx ?? getGlobalContext();
|
|
4102
|
+
const obj = new AdkServiceBinding(context, name);
|
|
3434
4103
|
await obj.getMetadata();
|
|
3435
4104
|
return obj;
|
|
3436
4105
|
}
|
|
@@ -3474,12 +4143,15 @@ var AdkServiceBinding = class AdkServiceBinding {
|
|
|
3474
4143
|
});
|
|
3475
4144
|
}
|
|
3476
4145
|
static async publish(name, ctx) {
|
|
3477
|
-
|
|
4146
|
+
const context = ctx ?? getGlobalContext();
|
|
4147
|
+
await new AdkServiceBinding(context, name).publish();
|
|
3478
4148
|
}
|
|
3479
4149
|
static async unpublish(name, ctx) {
|
|
3480
|
-
|
|
4150
|
+
const context = ctx ?? getGlobalContext();
|
|
4151
|
+
await new AdkServiceBinding(context, name).unpublish();
|
|
3481
4152
|
}
|
|
3482
4153
|
};
|
|
4154
|
+
registerObjectType("SRVB", ServiceBinding, AdkServiceBinding, { endpoint: "businessservices/bindings" });
|
|
3483
4155
|
|
|
3484
4156
|
//#endregion
|
|
3485
4157
|
//#region src/objects/cts/transport/transport-object.ts
|
|
@@ -3487,6 +4159,7 @@ var AdkServiceBinding = class AdkServiceBinding {
|
|
|
3487
4159
|
* Transport Object - wrapper for ABAP objects in a transport
|
|
3488
4160
|
*/
|
|
3489
4161
|
var AdkTransportObject = class {
|
|
4162
|
+
data;
|
|
3490
4163
|
constructor(data) {
|
|
3491
4164
|
this.data = data;
|
|
3492
4165
|
}
|
|
@@ -3525,13 +4198,13 @@ var AdkTransportObject = class {
|
|
|
3525
4198
|
};
|
|
3526
4199
|
|
|
3527
4200
|
//#endregion
|
|
3528
|
-
//#region \0@oxc-project+runtime@0.
|
|
4201
|
+
//#region \0@oxc-project+runtime@0.148.0/helpers/esm/decorateMetadata.js
|
|
3529
4202
|
function __decorateMetadata(k, v) {
|
|
3530
4203
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3531
4204
|
}
|
|
3532
4205
|
|
|
3533
4206
|
//#endregion
|
|
3534
|
-
//#region \0@oxc-project+runtime@0.
|
|
4207
|
+
//#region \0@oxc-project+runtime@0.148.0/helpers/esm/decorate.js
|
|
3535
4208
|
function __decorate(decorators, target, key, desc) {
|
|
3536
4209
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3537
4210
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -3546,10 +4219,18 @@ const STATUS_TEXT = {
|
|
|
3546
4219
|
R: "Released",
|
|
3547
4220
|
N: "Not released"
|
|
3548
4221
|
};
|
|
3549
|
-
function asArray$
|
|
4222
|
+
function asArray$2(val) {
|
|
3550
4223
|
if (!val) return [];
|
|
3551
4224
|
return Array.isArray(val) ? val : [val];
|
|
3552
4225
|
}
|
|
4226
|
+
function transportResponseName(response) {
|
|
4227
|
+
if (response.object_type === "T") {
|
|
4228
|
+
const taskNumber = asArray$2(response.task)[0]?.number;
|
|
4229
|
+
if (taskNumber) return taskNumber;
|
|
4230
|
+
}
|
|
4231
|
+
if (response.name) return response.name;
|
|
4232
|
+
return response.request?.number || "";
|
|
4233
|
+
}
|
|
3553
4234
|
let cachedConfigUri;
|
|
3554
4235
|
async function getConfigUri(ctx) {
|
|
3555
4236
|
if (cachedConfigUri) return cachedConfigUri;
|
|
@@ -3621,7 +4302,7 @@ var AdkTransportRequest = class AdkTransportRequest extends AdkObject {
|
|
|
3621
4302
|
constructor(ctx, dataOrNumber) {
|
|
3622
4303
|
if (typeof dataOrNumber === "string") super(ctx, dataOrNumber);
|
|
3623
4304
|
else super(ctx, {
|
|
3624
|
-
name: dataOrNumber
|
|
4305
|
+
name: transportResponseName(dataOrNumber),
|
|
3625
4306
|
type: dataOrNumber.object_type === "T" ? "RQTQ" : "RQRQ",
|
|
3626
4307
|
response: dataOrNumber
|
|
3627
4308
|
});
|
|
@@ -3682,7 +4363,7 @@ var AdkTransportRequest = class AdkTransportRequest extends AdkObject {
|
|
|
3682
4363
|
get tasks() {
|
|
3683
4364
|
if (!this._tasks) {
|
|
3684
4365
|
const taskData = this.itemData.task;
|
|
3685
|
-
this._tasks = asArray$
|
|
4366
|
+
this._tasks = asArray$2(taskData).map((t) => {
|
|
3686
4367
|
const { request, task: _existingTasks, ...rootProps } = this.response;
|
|
3687
4368
|
const { task: _nestedTasks, ...requestWithoutTasks } = request || {};
|
|
3688
4369
|
const taskResponse = {
|
|
@@ -3703,7 +4384,7 @@ var AdkTransportRequest = class AdkTransportRequest extends AdkObject {
|
|
|
3703
4384
|
*/
|
|
3704
4385
|
get objects() {
|
|
3705
4386
|
if (!this._objects) {
|
|
3706
|
-
const directObjects = asArray$
|
|
4387
|
+
const directObjects = asArray$2(this.itemData.abap_object).map((o) => new AdkTransportObject(o));
|
|
3707
4388
|
const taskObjects = this.tasks.flatMap((t) => t.objects);
|
|
3708
4389
|
this._objects = [...directObjects, ...taskObjects];
|
|
3709
4390
|
}
|
|
@@ -3711,9 +4392,26 @@ var AdkTransportRequest = class AdkTransportRequest extends AdkObject {
|
|
|
3711
4392
|
}
|
|
3712
4393
|
async release() {
|
|
3713
4394
|
try {
|
|
3714
|
-
await this.ctx.client.
|
|
3715
|
-
|
|
3716
|
-
|
|
4395
|
+
await this.ctx.client.fetch(`${this.objectUri}/newreleasejobs`, {
|
|
4396
|
+
method: "POST",
|
|
4397
|
+
headers: {
|
|
4398
|
+
"Content-Type": "application/vnd.sap.adt.transportorganizer.v1+xml",
|
|
4399
|
+
Accept: "application/vnd.sap.adt.transportorganizer.v1+xml"
|
|
4400
|
+
},
|
|
4401
|
+
body: ""
|
|
4402
|
+
});
|
|
4403
|
+
try {
|
|
4404
|
+
await this.load();
|
|
4405
|
+
} catch (reloadError) {
|
|
4406
|
+
return {
|
|
4407
|
+
success: false,
|
|
4408
|
+
message: `Released ${this.number} but failed to verify: ${reloadError instanceof Error ? reloadError.message : String(reloadError)}`
|
|
4409
|
+
};
|
|
4410
|
+
}
|
|
4411
|
+
if (this.status !== "R") return {
|
|
4412
|
+
success: false,
|
|
4413
|
+
message: `SAP did not release ${this.number} (status: ${this.statusText})`
|
|
4414
|
+
};
|
|
3717
4415
|
return { success: true };
|
|
3718
4416
|
} catch (error) {
|
|
3719
4417
|
return {
|
|
@@ -3750,18 +4448,33 @@ var AdkTransportRequest = class AdkTransportRequest extends AdkObject {
|
|
|
3750
4448
|
* @param recursive - When true, also reassign all modifiable tasks
|
|
3751
4449
|
*/
|
|
3752
4450
|
async reassign(newOwner, recursive = false) {
|
|
3753
|
-
await this.ctx.client.adt.cts.transportrequests.useraction.reassign(this.number, {
|
|
3754
|
-
|
|
3755
|
-
recursive
|
|
3756
|
-
}, { root: {
|
|
4451
|
+
await this.ctx.client.adt.cts.transportrequests.useraction.reassign(this.number, { targetUser: newOwner }, { root: {
|
|
4452
|
+
number: this.number,
|
|
3757
4453
|
useraction: "changeowner",
|
|
3758
4454
|
targetuser: newOwner
|
|
3759
4455
|
} });
|
|
3760
|
-
this.
|
|
4456
|
+
const verified = await AdkTransportRequest.get(this.number, this.ctx);
|
|
4457
|
+
if (verified.owner.toUpperCase() !== newOwner.toUpperCase()) throw new Error(`Transport ${this.number} owner verification failed: expected ${newOwner}, found ${verified.owner || "<empty>"}`);
|
|
4458
|
+
this.itemData.owner = verified.owner;
|
|
3761
4459
|
if (recursive) {
|
|
3762
|
-
for (const task of this.tasks) if (task.status
|
|
4460
|
+
for (const task of this.tasks) if (task.status === "D") await task.reassign(newOwner);
|
|
3763
4461
|
}
|
|
3764
4462
|
}
|
|
4463
|
+
/** Create and verify a modifiable task under this request. */
|
|
4464
|
+
async addTask(owner) {
|
|
4465
|
+
if (this.itemType !== "request") throw new Error(`Transport ${this.number} is a task, not a request`);
|
|
4466
|
+
if (this.status !== "D") throw new Error(`Transport ${this.number} is not modifiable: expected status D, found ${this.status}`);
|
|
4467
|
+
const existingTasks = new Set(this.tasks.map((task) => task.number));
|
|
4468
|
+
const returnedNumber = (await this.ctx.client.adt.cts.transportrequests.useraction.addTask(this.number, { owner }, { root: { targetuser: owner } })).root.number;
|
|
4469
|
+
if (!returnedNumber) throw new Error(`Task creation verification failed for ${this.number}: SAP response did not contain a task number`);
|
|
4470
|
+
const verified = await AdkTransportRequest.get(this.number, this.ctx);
|
|
4471
|
+
const created = verified.tasks.find((task) => task.number === returnedNumber && !existingTasks.has(task.number) && task.owner.toUpperCase() === owner.toUpperCase());
|
|
4472
|
+
if (!created) throw new Error(`Task creation verification failed for ${this.number}: no new task owned by ${owner}`);
|
|
4473
|
+
if (created.status !== "D") throw new Error(`Task creation verification failed for ${created.number}: expected status D, found ${created.status}`);
|
|
4474
|
+
this._tasks = verified.tasks;
|
|
4475
|
+
this._objects = void 0;
|
|
4476
|
+
return created;
|
|
4477
|
+
}
|
|
3765
4478
|
/**
|
|
3766
4479
|
* Create a new transport request
|
|
3767
4480
|
*
|
|
@@ -3795,7 +4508,7 @@ var AdkTransportRequest = class AdkTransportRequest extends AdkObject {
|
|
|
3795
4508
|
/**
|
|
3796
4509
|
* Get a transport request by number
|
|
3797
4510
|
*
|
|
3798
|
-
* @param number - Transport number (e.g., '
|
|
4511
|
+
* @param number - Transport number (e.g., 'TRLK900001')
|
|
3799
4512
|
* @param ctx - Optional ADK context (uses global context if not provided)
|
|
3800
4513
|
*/
|
|
3801
4514
|
static async get(number, ctx) {
|
|
@@ -3877,7 +4590,7 @@ var AdkTransportTask = class AdkTransportTask extends AdkTransportRequest {
|
|
|
3877
4590
|
get objects() {
|
|
3878
4591
|
if (!this._objects) {
|
|
3879
4592
|
const taskData = this.itemData;
|
|
3880
|
-
this._objects = asArray$
|
|
4593
|
+
this._objects = asArray$2(taskData?.abap_object).map((o) => new AdkTransportObject(o));
|
|
3881
4594
|
}
|
|
3882
4595
|
return this._objects;
|
|
3883
4596
|
}
|
|
@@ -3897,12 +4610,13 @@ var AdkTransportTask = class AdkTransportTask extends AdkTransportRequest {
|
|
|
3897
4610
|
/**
|
|
3898
4611
|
* Get a transport task by number
|
|
3899
4612
|
*
|
|
3900
|
-
* @param number - Task number (e.g., '
|
|
4613
|
+
* @param number - Task number (e.g., 'TRLK900001')
|
|
3901
4614
|
* @param ctx - Optional ADK context (uses global context if not provided)
|
|
3902
4615
|
*/
|
|
3903
4616
|
static async get(number, ctx) {
|
|
3904
4617
|
const context = ctx ?? getGlobalContext();
|
|
3905
|
-
|
|
4618
|
+
const rawResponse = await context.client.adt.cts.transportrequests.get(number);
|
|
4619
|
+
return new AdkTransportTask(context, rawResponse.root);
|
|
3906
4620
|
}
|
|
3907
4621
|
};
|
|
3908
4622
|
|
|
@@ -3911,7 +4625,7 @@ var AdkTransportTask = class AdkTransportTask extends AdkTransportRequest {
|
|
|
3911
4625
|
/**
|
|
3912
4626
|
* Helper to normalize array/single value to array
|
|
3913
4627
|
*/
|
|
3914
|
-
function asArray(val) {
|
|
4628
|
+
function asArray$1(val) {
|
|
3915
4629
|
if (!val) return [];
|
|
3916
4630
|
return Array.isArray(val) ? val : [val];
|
|
3917
4631
|
}
|
|
@@ -3945,6 +4659,8 @@ function matchesSelector(obj, selector) {
|
|
|
3945
4659
|
* Call load() to get the full ADK object.
|
|
3946
4660
|
*/
|
|
3947
4661
|
var AdkTransportObjectRef = class {
|
|
4662
|
+
ctx;
|
|
4663
|
+
data;
|
|
3948
4664
|
constructor(ctx, data) {
|
|
3949
4665
|
this.ctx = ctx;
|
|
3950
4666
|
this.data = data;
|
|
@@ -3997,7 +4713,7 @@ var AdkTransportObjectRef = class {
|
|
|
3997
4713
|
* @returns The loaded ADK object, or undefined if type not supported
|
|
3998
4714
|
*/
|
|
3999
4715
|
async load() {
|
|
4000
|
-
const { createAdk } = await
|
|
4716
|
+
const { createAdk } = await Promise.resolve().then(() => factory_exports);
|
|
4001
4717
|
const adk = createAdk(this.ctx.client);
|
|
4002
4718
|
try {
|
|
4003
4719
|
const obj = adk.get(this.name, this.type);
|
|
@@ -4016,6 +4732,8 @@ var AdkTransportObjectRef = class {
|
|
|
4016
4732
|
* Transport task reference
|
|
4017
4733
|
*/
|
|
4018
4734
|
var AdkTransportTaskRef = class {
|
|
4735
|
+
ctx;
|
|
4736
|
+
data;
|
|
4019
4737
|
constructor(ctx, data) {
|
|
4020
4738
|
this.ctx = ctx;
|
|
4021
4739
|
this.data = data;
|
|
@@ -4037,7 +4755,7 @@ var AdkTransportTaskRef = class {
|
|
|
4037
4755
|
}
|
|
4038
4756
|
/** Objects in this task */
|
|
4039
4757
|
get objects() {
|
|
4040
|
-
return asArray(this.data.abap_object).map((obj) => new AdkTransportObjectRef(this.ctx, obj));
|
|
4758
|
+
return asArray$1(this.data.abap_object).map((obj) => new AdkTransportObjectRef(this.ctx, obj));
|
|
4041
4759
|
}
|
|
4042
4760
|
};
|
|
4043
4761
|
/**
|
|
@@ -4060,35 +4778,47 @@ var AdkTransportTaskRef = class {
|
|
|
4060
4778
|
* ```
|
|
4061
4779
|
*/
|
|
4062
4780
|
var AdkTransport = class AdkTransport {
|
|
4781
|
+
ctx;
|
|
4782
|
+
data;
|
|
4783
|
+
requestedNumber;
|
|
4063
4784
|
_objects;
|
|
4064
4785
|
_tasks;
|
|
4065
|
-
constructor(ctx, data) {
|
|
4786
|
+
constructor(ctx, data, requestedNumber) {
|
|
4066
4787
|
this.ctx = ctx;
|
|
4067
4788
|
this.data = data;
|
|
4789
|
+
this.requestedNumber = requestedNumber;
|
|
4068
4790
|
}
|
|
4069
4791
|
/** Transport number */
|
|
4070
4792
|
get number() {
|
|
4071
|
-
|
|
4793
|
+
if (this.data.object_type === "T") return asArray$1(this.data.task).find((candidate) => candidate.number?.toUpperCase() === this.requestedNumber)?.number ?? this.requestedNumber;
|
|
4794
|
+
return this.data.request?.number ?? this.data.name ?? this.requestedNumber;
|
|
4795
|
+
}
|
|
4796
|
+
get itemData() {
|
|
4797
|
+
if (this.data.object_type === "T") {
|
|
4798
|
+
const directTasks = asArray$1(this.data.task);
|
|
4799
|
+
return directTasks.find((task) => task.number?.toUpperCase() === this.requestedNumber) ?? directTasks[0] ?? this.data.request ?? {};
|
|
4800
|
+
}
|
|
4801
|
+
return this.data.request ?? {};
|
|
4072
4802
|
}
|
|
4073
4803
|
/** Transport description */
|
|
4074
4804
|
get description() {
|
|
4075
|
-
return this.
|
|
4805
|
+
return this.itemData.desc ?? "";
|
|
4076
4806
|
}
|
|
4077
4807
|
/** Transport owner */
|
|
4078
4808
|
get owner() {
|
|
4079
|
-
return this.
|
|
4809
|
+
return this.itemData.owner ?? "";
|
|
4080
4810
|
}
|
|
4081
4811
|
/** Transport status (D=Modifiable, R=Released) */
|
|
4082
4812
|
get status() {
|
|
4083
|
-
return this.
|
|
4813
|
+
return this.itemData.status ?? "";
|
|
4084
4814
|
}
|
|
4085
4815
|
/** Transport status text */
|
|
4086
4816
|
get statusText() {
|
|
4087
|
-
return this.
|
|
4817
|
+
return this.itemData.status_text ?? "";
|
|
4088
4818
|
}
|
|
4089
4819
|
/** Transport target system */
|
|
4090
4820
|
get target() {
|
|
4091
|
-
return this.
|
|
4821
|
+
return this.itemData.target ?? "";
|
|
4092
4822
|
}
|
|
4093
4823
|
/** Object type (K=Request, T=Task) */
|
|
4094
4824
|
get objectType() {
|
|
@@ -4097,9 +4827,10 @@ var AdkTransport = class AdkTransport {
|
|
|
4097
4827
|
/** Tasks belonging to this transport */
|
|
4098
4828
|
get tasks() {
|
|
4099
4829
|
if (!this._tasks) {
|
|
4100
|
-
const requestTasks = asArray(this.data.request?.task);
|
|
4101
|
-
const rootTasks = asArray(this.data.task);
|
|
4102
|
-
|
|
4830
|
+
const requestTasks = asArray$1(this.data.request?.task);
|
|
4831
|
+
const rootTasks = asArray$1(this.data.task);
|
|
4832
|
+
const allTasks = [...requestTasks, ...rootTasks];
|
|
4833
|
+
this._tasks = allTasks.map((t) => new AdkTransportTaskRef(this.ctx, t));
|
|
4103
4834
|
}
|
|
4104
4835
|
return this._tasks;
|
|
4105
4836
|
}
|
|
@@ -4125,8 +4856,8 @@ var AdkTransport = class AdkTransport {
|
|
|
4125
4856
|
objects.push(new AdkTransportObjectRef(this.ctx, obj));
|
|
4126
4857
|
}
|
|
4127
4858
|
};
|
|
4128
|
-
for (const obj of asArray(this.data.request?.abap_object)) addObject(obj);
|
|
4129
|
-
for (const obj of asArray(this.data.request?.all_objects?.abap_object)) addObject(obj);
|
|
4859
|
+
for (const obj of asArray$1(this.data.request?.abap_object)) addObject(obj);
|
|
4860
|
+
for (const obj of asArray$1(this.data.request?.all_objects?.abap_object)) addObject(obj);
|
|
4130
4861
|
for (const task of this.tasks) for (const objRef of task.objects) addObject(objRef.raw);
|
|
4131
4862
|
return objects;
|
|
4132
4863
|
}
|
|
@@ -4194,7 +4925,9 @@ var AdkTransport = class AdkTransport {
|
|
|
4194
4925
|
*/
|
|
4195
4926
|
static async get(number, ctx) {
|
|
4196
4927
|
const context = ctx ?? getGlobalContext();
|
|
4197
|
-
|
|
4928
|
+
const requestedNumber = number.trim().toUpperCase();
|
|
4929
|
+
const response = await context.client.adt.cts.transportrequests.get(requestedNumber);
|
|
4930
|
+
return new AdkTransport(context, response.root, requestedNumber);
|
|
4198
4931
|
}
|
|
4199
4932
|
/**
|
|
4200
4933
|
* Load multiple transports and merge their objects into a single view.
|
|
@@ -4214,7 +4947,8 @@ var AdkTransport = class AdkTransport {
|
|
|
4214
4947
|
* ```
|
|
4215
4948
|
*/
|
|
4216
4949
|
static async merge(numbers, ctx) {
|
|
4217
|
-
|
|
4950
|
+
const transports = await Promise.all(numbers.map((n) => AdkTransport.get(n, ctx)));
|
|
4951
|
+
return new MergedTransportView(transports);
|
|
4218
4952
|
}
|
|
4219
4953
|
};
|
|
4220
4954
|
function getFilteredObjects(transport, selector) {
|
|
@@ -4226,6 +4960,31 @@ function addResolvedObject(object, sourceTransport, objects, sourceTransportMap,
|
|
|
4226
4960
|
objects.push(object);
|
|
4227
4961
|
sourceTransportMap.set(object.key, sourceTransport);
|
|
4228
4962
|
}
|
|
4963
|
+
function getTransportObjectKey(object) {
|
|
4964
|
+
return `${object.pgmid ?? ""}/${object.type ?? ""}/${object.name ?? ""}`;
|
|
4965
|
+
}
|
|
4966
|
+
function getConcreteSourceTransportMap(transport, requestedNumber) {
|
|
4967
|
+
const sourceTransportMap = /* @__PURE__ */ new Map();
|
|
4968
|
+
const data = transport.raw;
|
|
4969
|
+
const requestNumber = data.request?.number || transport.number || requestedNumber;
|
|
4970
|
+
const addSource = (object, sourceTransport) => {
|
|
4971
|
+
const key = getTransportObjectKey(object);
|
|
4972
|
+
if (!sourceTransportMap.has(key)) sourceTransportMap.set(key, sourceTransport);
|
|
4973
|
+
};
|
|
4974
|
+
for (const object of asArray$1(data.request?.abap_object)) addSource(object, requestNumber);
|
|
4975
|
+
const tasks = [...asArray$1(data.request?.task), ...asArray$1(data.task)];
|
|
4976
|
+
for (const task of tasks) {
|
|
4977
|
+
const taskNumber = task.number || transport.number || requestedNumber;
|
|
4978
|
+
for (const object of asArray$1(task.abap_object)) addSource(object, taskNumber);
|
|
4979
|
+
}
|
|
4980
|
+
for (const object of asArray$1(data.request?.all_objects?.abap_object)) addSource(object, requestNumber);
|
|
4981
|
+
return sourceTransportMap;
|
|
4982
|
+
}
|
|
4983
|
+
function addScopeTransportNumber(number, scopeTransportNumbers, seenScopeTransportNumbers) {
|
|
4984
|
+
if (!number || seenScopeTransportNumbers.has(number)) return;
|
|
4985
|
+
seenScopeTransportNumbers.add(number);
|
|
4986
|
+
scopeTransportNumbers.push(number);
|
|
4987
|
+
}
|
|
4229
4988
|
/**
|
|
4230
4989
|
* Load and resolve objects from one or more transport numbers, with optional
|
|
4231
4990
|
* selector-based filtering and deduplication across TRs.
|
|
@@ -4240,18 +4999,23 @@ function addResolvedObject(object, sourceTransport, objects, sourceTransportMap,
|
|
|
4240
4999
|
async function resolveTransportObjects(transportNumbers, selector, ctx) {
|
|
4241
5000
|
const objects = [];
|
|
4242
5001
|
const sourceTransportMap = /* @__PURE__ */ new Map();
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
const
|
|
4249
|
-
const
|
|
4250
|
-
|
|
5002
|
+
const scopeTransportNumbers = [];
|
|
5003
|
+
const seenScopeTransportNumbers = /* @__PURE__ */ new Set();
|
|
5004
|
+
const transports = await Promise.all(transportNumbers.map((number) => AdkTransport.get(number, ctx)));
|
|
5005
|
+
const seenObjectKeys = /* @__PURE__ */ new Set();
|
|
5006
|
+
for (const [index, transport] of transports.entries()) {
|
|
5007
|
+
const requestedNumber = transportNumbers[index] ?? "";
|
|
5008
|
+
const transportNumber = transport.number || requestedNumber;
|
|
5009
|
+
addScopeTransportNumber(transportNumber, scopeTransportNumbers, seenScopeTransportNumbers);
|
|
5010
|
+
addScopeTransportNumber(transport.raw.request?.number ?? "", scopeTransportNumbers, seenScopeTransportNumbers);
|
|
5011
|
+
for (const task of transport.tasks) addScopeTransportNumber(task.number, scopeTransportNumbers, seenScopeTransportNumbers);
|
|
5012
|
+
const concreteSources = getConcreteSourceTransportMap(transport, requestedNumber);
|
|
5013
|
+
for (const object of getFilteredObjects(transport, selector)) addResolvedObject(object, concreteSources.get(object.key) ?? transportNumber, objects, sourceTransportMap, seenObjectKeys);
|
|
4251
5014
|
}
|
|
4252
5015
|
return {
|
|
4253
5016
|
objects,
|
|
4254
|
-
sourceTransportMap
|
|
5017
|
+
sourceTransportMap,
|
|
5018
|
+
scopeTransportNumbers
|
|
4255
5019
|
};
|
|
4256
5020
|
}
|
|
4257
5021
|
/**
|
|
@@ -4291,10 +5055,743 @@ var MergedTransportView = class MergedTransportView {
|
|
|
4291
5055
|
* @param ctx - Optional ADK context
|
|
4292
5056
|
*/
|
|
4293
5057
|
static async create(numbers, ctx) {
|
|
4294
|
-
|
|
5058
|
+
const transports = await Promise.all(numbers.map((n) => AdkTransport.get(n, ctx)));
|
|
5059
|
+
return new MergedTransportView(transports);
|
|
5060
|
+
}
|
|
5061
|
+
};
|
|
5062
|
+
|
|
5063
|
+
//#endregion
|
|
5064
|
+
//#region src/factory.ts
|
|
5065
|
+
var factory_exports = /* @__PURE__ */ __exportAll({
|
|
5066
|
+
AdkGenericObject: () => AdkGenericObject,
|
|
5067
|
+
createAdk: () => createAdk,
|
|
5068
|
+
createAdkFactory: () => createAdkFactory,
|
|
5069
|
+
parseXmlIdentity: () => parseXmlIdentity
|
|
5070
|
+
});
|
|
5071
|
+
/** Pattern to extract adtcore:type from XML */
|
|
5072
|
+
const TYPE_PATTERN = /adtcore:type="([^"]+)"/;
|
|
5073
|
+
/** Pattern to extract adtcore:name from XML */
|
|
5074
|
+
const NAME_PATTERN = /adtcore:name="([^"]+)"/;
|
|
5075
|
+
/**
|
|
5076
|
+
* Extract ADT type and name from XML
|
|
5077
|
+
*
|
|
5078
|
+
* Relies on adtcore:type and adtcore:name attributes which are
|
|
5079
|
+
* the standard identifiers in ADT XML responses.
|
|
5080
|
+
*
|
|
5081
|
+
* @param xml - XML string from ADT response
|
|
5082
|
+
* @returns Extracted type and name, or undefined if not found
|
|
5083
|
+
*/
|
|
5084
|
+
function parseXmlIdentity(xml) {
|
|
5085
|
+
const typeMatch = xml.match(TYPE_PATTERN);
|
|
5086
|
+
const nameMatch = xml.match(NAME_PATTERN);
|
|
5087
|
+
if (typeMatch && nameMatch) return {
|
|
5088
|
+
type: typeMatch[1],
|
|
5089
|
+
name: nameMatch[1]
|
|
5090
|
+
};
|
|
5091
|
+
}
|
|
5092
|
+
/**
|
|
5093
|
+
* Generic ADK object for unregistered types
|
|
5094
|
+
*
|
|
5095
|
+
* Provides core functionality (adtcore attributes, links)
|
|
5096
|
+
* without type-specific features.
|
|
5097
|
+
*/
|
|
5098
|
+
var AdkGenericObject = class {
|
|
5099
|
+
adtType;
|
|
5100
|
+
adtMainType;
|
|
5101
|
+
adtSubType;
|
|
5102
|
+
ctx;
|
|
5103
|
+
_name;
|
|
5104
|
+
_data;
|
|
5105
|
+
constructor(ctx, name, adtType) {
|
|
5106
|
+
this.ctx = ctx;
|
|
5107
|
+
this._name = name;
|
|
5108
|
+
const parsed = parseAdtType(adtType);
|
|
5109
|
+
this.adtType = parsed.full;
|
|
5110
|
+
this.adtMainType = parsed.main;
|
|
5111
|
+
this.adtSubType = parsed.sub;
|
|
5112
|
+
}
|
|
5113
|
+
get name() {
|
|
5114
|
+
return this._name;
|
|
5115
|
+
}
|
|
5116
|
+
get type() {
|
|
5117
|
+
return this.adtType;
|
|
5118
|
+
}
|
|
5119
|
+
/** Check if data is loaded */
|
|
5120
|
+
get isLoaded() {
|
|
5121
|
+
return this._data !== void 0;
|
|
5122
|
+
}
|
|
5123
|
+
/** Get raw data (if loaded) */
|
|
5124
|
+
get data() {
|
|
5125
|
+
return this._data;
|
|
5126
|
+
}
|
|
5127
|
+
/** Set data (for manual population) */
|
|
5128
|
+
setData(data) {
|
|
5129
|
+
this._data = data;
|
|
5130
|
+
}
|
|
5131
|
+
};
|
|
5132
|
+
/**
|
|
5133
|
+
* Create ADK factory
|
|
5134
|
+
*
|
|
5135
|
+
* @param ctx - ADK context with services
|
|
5136
|
+
* @returns Factory instance
|
|
5137
|
+
*/
|
|
5138
|
+
function createAdkFactory(ctx) {
|
|
5139
|
+
return {
|
|
5140
|
+
ctx,
|
|
5141
|
+
get(name, adtType) {
|
|
5142
|
+
const entry = resolveType(adtType);
|
|
5143
|
+
if (entry) return new entry.constructor(ctx, name);
|
|
5144
|
+
return new AdkGenericObject(ctx, name, adtType);
|
|
5145
|
+
},
|
|
5146
|
+
getWithData(data, adtType) {
|
|
5147
|
+
const entry = resolveType(adtType);
|
|
5148
|
+
if (entry) return new entry.constructor(ctx, data);
|
|
5149
|
+
const obj = new AdkGenericObject(ctx, data.name ?? "", adtType);
|
|
5150
|
+
obj.setData(data);
|
|
5151
|
+
return obj;
|
|
5152
|
+
},
|
|
5153
|
+
byKind(kind, name) {
|
|
5154
|
+
const entry = resolveKind(kind);
|
|
5155
|
+
if (!entry) throw new Error(`No constructor registered for kind: ${kind}`);
|
|
5156
|
+
return new entry.constructor(ctx, name);
|
|
5157
|
+
},
|
|
5158
|
+
fromXml(xml) {
|
|
5159
|
+
const identity = parseXmlIdentity(xml);
|
|
5160
|
+
if (!identity) return;
|
|
5161
|
+
return this.get(identity.name, identity.type);
|
|
5162
|
+
},
|
|
5163
|
+
create(adtType) {
|
|
5164
|
+
return this.get("", adtType);
|
|
5165
|
+
}
|
|
5166
|
+
};
|
|
5167
|
+
}
|
|
5168
|
+
/**
|
|
5169
|
+
* Create ADK factory from ADT client
|
|
5170
|
+
*
|
|
5171
|
+
* Builds context from client and returns factory.
|
|
5172
|
+
* This is the main entry point for most users.
|
|
5173
|
+
*
|
|
5174
|
+
* @example
|
|
5175
|
+
* import { createAdtClient } from '@abapify/adt-client';
|
|
5176
|
+
* import { createAdk } from '@abapify/adk';
|
|
5177
|
+
*
|
|
5178
|
+
* const client = createAdtClient({ ... });
|
|
5179
|
+
* const adk = createAdk(client);
|
|
5180
|
+
*
|
|
5181
|
+
* const cls = adk.get('ZCL_TEST', 'CLAS');
|
|
5182
|
+
* await cls.load();
|
|
5183
|
+
*/
|
|
5184
|
+
function createAdk(client) {
|
|
5185
|
+
return createAdkFactory({ client });
|
|
5186
|
+
}
|
|
5187
|
+
|
|
5188
|
+
//#endregion
|
|
5189
|
+
//#region src/transport-source-manifest.ts
|
|
5190
|
+
/** Stable public failure for errors that occur before a component result exists. */
|
|
5191
|
+
var ObjectSourceHistoryError = class extends Error {
|
|
5192
|
+
code;
|
|
5193
|
+
object;
|
|
5194
|
+
name = "ObjectSourceHistoryError";
|
|
5195
|
+
constructor(code, message, object) {
|
|
5196
|
+
super(message);
|
|
5197
|
+
this.code = code;
|
|
5198
|
+
this.object = object;
|
|
4295
5199
|
}
|
|
4296
5200
|
};
|
|
5201
|
+
const VERSIONS_RELATION = "http://www.sap.com/adt/relations/versions";
|
|
5202
|
+
const DEFAULT_CONCURRENCY = 4;
|
|
5203
|
+
const MAX_CONCURRENCY = 32;
|
|
5204
|
+
const RELATIVE_URI_TRAVERSAL = /(?:^|\/)(?:\.{1,2}|%2e(?:%2e)?)(?:\/|$)/i;
|
|
5205
|
+
const NON_SOURCE_CTS_OBJECT_KEYS = /* @__PURE__ */ new Set(["R3TR/SUSK"]);
|
|
5206
|
+
function asRecord(value) {
|
|
5207
|
+
return value !== null && typeof value === "object" ? value : void 0;
|
|
5208
|
+
}
|
|
5209
|
+
function asArray(value) {
|
|
5210
|
+
if (value === void 0 || value === null) return [];
|
|
5211
|
+
return Array.isArray(value) ? value : [value];
|
|
5212
|
+
}
|
|
5213
|
+
function nonEmptyString(value) {
|
|
5214
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
5215
|
+
}
|
|
5216
|
+
function uniqueStable(values) {
|
|
5217
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5218
|
+
const result = [];
|
|
5219
|
+
for (const value of values) {
|
|
5220
|
+
const normalized = value.trim().toUpperCase();
|
|
5221
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
5222
|
+
seen.add(normalized);
|
|
5223
|
+
result.push(normalized);
|
|
5224
|
+
}
|
|
5225
|
+
return result;
|
|
5226
|
+
}
|
|
5227
|
+
function compareText(left, right) {
|
|
5228
|
+
if (left < right) return -1;
|
|
5229
|
+
if (left > right) return 1;
|
|
5230
|
+
return 0;
|
|
5231
|
+
}
|
|
5232
|
+
/**
|
|
5233
|
+
* Some CTS entries represent SAP-maintained configuration rather than
|
|
5234
|
+
* repository source. They have neither an ADK source model nor an abapGit
|
|
5235
|
+
* representation, so they must not participate in a source-boundary manifest.
|
|
5236
|
+
*/
|
|
5237
|
+
function isNonSourceCtsObject(reference) {
|
|
5238
|
+
return NON_SOURCE_CTS_OBJECT_KEYS.has(`${reference.pgmid.trim().toUpperCase()}/${reference.type.trim().toUpperCase()}`);
|
|
5239
|
+
}
|
|
5240
|
+
function isUnsafeRelativeHref(href) {
|
|
5241
|
+
return href.startsWith("//") || href.includes("\\") || href.includes(":") || RELATIVE_URI_TRAVERSAL.test(href);
|
|
5242
|
+
}
|
|
5243
|
+
function resolveAdtRelativeUri(href, objectUri) {
|
|
5244
|
+
try {
|
|
5245
|
+
const safeObjectUri = assertAdtUri(objectUri);
|
|
5246
|
+
if (href.startsWith("/")) return assertAdtUri(href);
|
|
5247
|
+
if (isUnsafeRelativeHref(href)) return void 0;
|
|
5248
|
+
const directoryBase = safeObjectUri.endsWith("/") ? safeObjectUri : `${safeObjectUri}/`;
|
|
5249
|
+
const resolved = new URL(href, `https://adt.invalid${directoryBase}`);
|
|
5250
|
+
return assertAdtUri(`${resolved.pathname}${resolved.search}${resolved.hash}`);
|
|
5251
|
+
} catch {
|
|
5252
|
+
return;
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
function runtimeLinks(value) {
|
|
5256
|
+
return [...asArray(value["link"]), ...asArray(value["links"])].map(asRecord).filter((link) => Boolean(link));
|
|
5257
|
+
}
|
|
5258
|
+
function discoverComponent(value, id, objectUri) {
|
|
5259
|
+
const sourceHref = nonEmptyString(value["sourceUri"]);
|
|
5260
|
+
if (!sourceHref) return void 0;
|
|
5261
|
+
const sourceUri = resolveAdtRelativeUri(sourceHref, objectUri);
|
|
5262
|
+
const versionsHref = runtimeLinks(value).filter((link) => link.rel === VERSIONS_RELATION).map((link) => nonEmptyString(link.href)).find((href) => Boolean(href));
|
|
5263
|
+
const versionsUri = versionsHref ? resolveAdtRelativeUri(versionsHref, objectUri) : void 0;
|
|
5264
|
+
if (!sourceUri) return {
|
|
5265
|
+
id,
|
|
5266
|
+
diagnostic: {
|
|
5267
|
+
code: "SOURCE_COMPONENT_URI_UNSAFE",
|
|
5268
|
+
message: "The source component exposes an unsafe ADT URI."
|
|
5269
|
+
}
|
|
5270
|
+
};
|
|
5271
|
+
if (versionsHref && !versionsUri) return {
|
|
5272
|
+
id,
|
|
5273
|
+
diagnostic: {
|
|
5274
|
+
code: "SOURCE_COMPONENT_URI_UNSAFE",
|
|
5275
|
+
message: "The source component exposes an unsafe ADT URI."
|
|
5276
|
+
}
|
|
5277
|
+
};
|
|
5278
|
+
return {
|
|
5279
|
+
id,
|
|
5280
|
+
sourceUri,
|
|
5281
|
+
...versionsUri ? { versionsUri } : {}
|
|
5282
|
+
};
|
|
5283
|
+
}
|
|
5284
|
+
function discoverSourceComponents(metadata, objectUri) {
|
|
5285
|
+
const candidates = [];
|
|
5286
|
+
const root = discoverComponent(metadata, "main", objectUri);
|
|
5287
|
+
if (root) candidates.push(root);
|
|
5288
|
+
for (const [index, rawInclude] of asArray(metadata["include"]).entries()) {
|
|
5289
|
+
const include = asRecord(rawInclude);
|
|
5290
|
+
if (!include) continue;
|
|
5291
|
+
const component = discoverComponent(include, nonEmptyString(include["includeType"]) ?? nonEmptyString(include["name"]) ?? `include-${index + 1}`, objectUri);
|
|
5292
|
+
if (component) candidates.push(component);
|
|
5293
|
+
}
|
|
5294
|
+
candidates.sort((left, right) => compareText(left.id, right.id) || compareText(left.sourceUri ?? "", right.sourceUri ?? "") || compareText(left.versionsUri ?? "", right.versionsUri ?? ""));
|
|
5295
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5296
|
+
return candidates.filter((candidate) => {
|
|
5297
|
+
const key = `${candidate.sourceUri ?? ""}\u0000${candidate.versionsUri ?? ""}`;
|
|
5298
|
+
if (seen.has(key)) return false;
|
|
5299
|
+
seen.add(key);
|
|
5300
|
+
return true;
|
|
5301
|
+
});
|
|
5302
|
+
}
|
|
5303
|
+
function loadedMetadata(loaded) {
|
|
5304
|
+
const object = asRecord(loaded);
|
|
5305
|
+
if (!object) return void 0;
|
|
5306
|
+
const dataSync = asRecord(object["dataSync"]);
|
|
5307
|
+
if (dataSync) return dataSync;
|
|
5308
|
+
return asRecord(object["data"]);
|
|
5309
|
+
}
|
|
5310
|
+
function packageNameFrom(metadata) {
|
|
5311
|
+
return nonEmptyString(asRecord(metadata["packageRef"])?.["name"]) ?? nonEmptyString(metadata["packageName"]);
|
|
5312
|
+
}
|
|
5313
|
+
function normalizeSourceHistoryIdentity(objectName, objectType) {
|
|
5314
|
+
const type = objectType.trim().toUpperCase();
|
|
5315
|
+
const requestedName = objectName.trim().toUpperCase();
|
|
5316
|
+
return {
|
|
5317
|
+
name: normalizeObjectName(requestedName, type)[0] ?? requestedName,
|
|
5318
|
+
type
|
|
5319
|
+
};
|
|
5320
|
+
}
|
|
5321
|
+
function ensureObjectLoadable(modelRecord, object) {
|
|
5322
|
+
const load = modelRecord?.["load"];
|
|
5323
|
+
if (typeof load !== "function") throw new ObjectSourceHistoryError("OBJECT_TYPE_UNSUPPORTED", "The repository object type has no loadable ADK model.", object);
|
|
5324
|
+
return load;
|
|
5325
|
+
}
|
|
5326
|
+
async function loadObjectModel(model, load, object) {
|
|
5327
|
+
try {
|
|
5328
|
+
await load.call(model);
|
|
5329
|
+
} catch {
|
|
5330
|
+
throw new ObjectSourceHistoryError("OBJECT_METADATA_LOAD_FAILED", "SAP ADT rejected repository object metadata retrieval.", object);
|
|
5331
|
+
}
|
|
5332
|
+
}
|
|
5333
|
+
function ensureObjectMetadata(model, object) {
|
|
5334
|
+
const modelRecord = asRecord(model);
|
|
5335
|
+
const metadata = loadedMetadata(model);
|
|
5336
|
+
if (!metadata) throw new ObjectSourceHistoryError("OBJECT_METADATA_UNAVAILABLE", "The loaded object has no usable ADT metadata identity.", object);
|
|
5337
|
+
const objectUri = nonEmptyString(modelRecord?.["objectUri"]);
|
|
5338
|
+
if (!objectUri) throw new ObjectSourceHistoryError("OBJECT_METADATA_UNAVAILABLE", "The loaded object has no usable ADT metadata identity.", object);
|
|
5339
|
+
if (!resolveAdtRelativeUri("", objectUri)) throw new ObjectSourceHistoryError("OBJECT_METADATA_UNAVAILABLE", "The loaded object has no usable ADT metadata identity.", object);
|
|
5340
|
+
return {
|
|
5341
|
+
metadata,
|
|
5342
|
+
objectUri
|
|
5343
|
+
};
|
|
5344
|
+
}
|
|
5345
|
+
async function discoverObjectSourceHistory(objectName, objectType, ctx, normalizeIdentity = true, functionGroupName) {
|
|
5346
|
+
const object = normalizeIdentity ? normalizeSourceHistoryIdentity(objectName, objectType) : {
|
|
5347
|
+
name: objectName,
|
|
5348
|
+
type: objectType
|
|
5349
|
+
};
|
|
5350
|
+
let model;
|
|
5351
|
+
if (object.type === "FUGR/FF" && functionGroupName) try {
|
|
5352
|
+
model = await AdkFunctionModule.get(functionGroupName, object.name, ctx);
|
|
5353
|
+
} catch {
|
|
5354
|
+
throw new ObjectSourceHistoryError("OBJECT_METADATA_LOAD_FAILED", "SAP ADT rejected repository object metadata retrieval.", object);
|
|
5355
|
+
}
|
|
5356
|
+
else {
|
|
5357
|
+
model = createAdkFactory(ctx).get(object.name, object.type);
|
|
5358
|
+
const load = ensureObjectLoadable(asRecord(model), object);
|
|
5359
|
+
await loadObjectModel(model, load, object);
|
|
5360
|
+
}
|
|
5361
|
+
const { metadata, objectUri } = ensureObjectMetadata(model, object);
|
|
5362
|
+
let packageName = packageNameFrom(metadata);
|
|
5363
|
+
if (!packageName && functionGroupName) {
|
|
5364
|
+
const fugrModel = createAdkFactory(ctx).get(functionGroupName, "FUGR");
|
|
5365
|
+
await loadObjectModel(fugrModel, ensureObjectLoadable(asRecord(fugrModel), {
|
|
5366
|
+
name: functionGroupName,
|
|
5367
|
+
type: "FUGR"
|
|
5368
|
+
}), {
|
|
5369
|
+
name: functionGroupName,
|
|
5370
|
+
type: "FUGR"
|
|
5371
|
+
});
|
|
5372
|
+
const fugrMetadata = loadedMetadata(fugrModel);
|
|
5373
|
+
if (fugrMetadata) packageName = packageNameFrom(fugrMetadata);
|
|
5374
|
+
}
|
|
5375
|
+
const normalizedObject = {
|
|
5376
|
+
...object,
|
|
5377
|
+
...packageName ? { packageName } : {}
|
|
5378
|
+
};
|
|
5379
|
+
const components = discoverSourceComponents(metadata, objectUri);
|
|
5380
|
+
if (components.length === 0) throw new ObjectSourceHistoryError("SOURCE_COMPONENTS_UNAVAILABLE", "The object metadata exposes no source component.", normalizedObject);
|
|
5381
|
+
return {
|
|
5382
|
+
object: normalizedObject,
|
|
5383
|
+
components
|
|
5384
|
+
};
|
|
5385
|
+
}
|
|
5386
|
+
function normalizeConcurrency(value) {
|
|
5387
|
+
if (value === void 0) return DEFAULT_CONCURRENCY;
|
|
5388
|
+
if (!Number.isFinite(value)) return DEFAULT_CONCURRENCY;
|
|
5389
|
+
return Math.max(1, Math.min(MAX_CONCURRENCY, Math.floor(value)));
|
|
5390
|
+
}
|
|
5391
|
+
async function mapOrdered(values, concurrency, worker) {
|
|
5392
|
+
const results = new Array(values.length);
|
|
5393
|
+
let nextIndex = 0;
|
|
5394
|
+
const workers = Array.from({ length: Math.min(concurrency, values.length) }, async () => {
|
|
5395
|
+
while (nextIndex < values.length) {
|
|
5396
|
+
const index = nextIndex;
|
|
5397
|
+
nextIndex += 1;
|
|
5398
|
+
const value = values[index];
|
|
5399
|
+
if (value !== void 0) results[index] = await worker(value);
|
|
5400
|
+
}
|
|
5401
|
+
});
|
|
5402
|
+
await Promise.all(workers);
|
|
5403
|
+
return results;
|
|
5404
|
+
}
|
|
5405
|
+
function unavailableEntry(object, component, sourceTransport, changeKind, diagnostic) {
|
|
5406
|
+
return {
|
|
5407
|
+
object,
|
|
5408
|
+
component,
|
|
5409
|
+
sourceTransport,
|
|
5410
|
+
changeKind,
|
|
5411
|
+
exact: false,
|
|
5412
|
+
diagnostic
|
|
5413
|
+
};
|
|
5414
|
+
}
|
|
5415
|
+
function selectedRangeDiagnostic(ordered, newestIndex, oldestIndex, scope) {
|
|
5416
|
+
for (const candidate of ordered.slice(newestIndex, oldestIndex + 1)) {
|
|
5417
|
+
if (candidate.transports.some((transport) => scope.has(transport.toUpperCase()))) continue;
|
|
5418
|
+
return candidate.transports.length === 0 ? {
|
|
5419
|
+
code: "SOURCE_HISTORY_PROVENANCE_MISSING",
|
|
5420
|
+
message: "A source version in the selected history range has no transport provenance."
|
|
5421
|
+
} : {
|
|
5422
|
+
code: "SOURCE_HISTORY_INTERVENING_VERSION",
|
|
5423
|
+
message: "An unrelated source version occurs between in-scope versions."
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5426
|
+
}
|
|
5427
|
+
/**
|
|
5428
|
+
* Select immutable before/after references using SAP's observed feed ordinal.
|
|
5429
|
+
*/
|
|
5430
|
+
function selectTransportSourceVersions(versions, scopeTransportNumbers, deleted = false) {
|
|
5431
|
+
const scope = new Set(scopeTransportNumbers.map((transport) => transport.toUpperCase()));
|
|
5432
|
+
const ordinals = versions.map((version) => version.ordinal);
|
|
5433
|
+
if (ordinals.some((ordinal) => !Number.isSafeInteger(ordinal) || ordinal < 0) || new Set(ordinals).size !== ordinals.length) return {
|
|
5434
|
+
changeKind: "ambiguous",
|
|
5435
|
+
exact: false,
|
|
5436
|
+
diagnostic: {
|
|
5437
|
+
code: "SOURCE_HISTORY_ORDER_INVALID",
|
|
5438
|
+
message: "Source version ordinals do not define a unique feed order."
|
|
5439
|
+
}
|
|
5440
|
+
};
|
|
5441
|
+
const ordered = [...versions].sort((left, right) => left.ordinal - right.ordinal);
|
|
5442
|
+
const inScope = ordered.map((candidate, index) => ({
|
|
5443
|
+
candidate,
|
|
5444
|
+
index
|
|
5445
|
+
})).filter(({ candidate }) => candidate.transports.some((transport) => scope.has(transport.toUpperCase())));
|
|
5446
|
+
if (deleted) {
|
|
5447
|
+
if (ordered.length === 0) return {
|
|
5448
|
+
changeKind: "unsupported",
|
|
5449
|
+
exact: false,
|
|
5450
|
+
diagnostic: {
|
|
5451
|
+
code: "DELETED_SOURCE_BASE_UNAVAILABLE",
|
|
5452
|
+
message: "The deleted component has no recoverable historical source."
|
|
5453
|
+
}
|
|
5454
|
+
};
|
|
5455
|
+
const oldestInScope = inScope.at(-1);
|
|
5456
|
+
if (!oldestInScope) return {
|
|
5457
|
+
changeKind: "ambiguous",
|
|
5458
|
+
exact: false,
|
|
5459
|
+
diagnostic: {
|
|
5460
|
+
code: "SOURCE_HISTORY_SCOPE_VERSION_MISSING",
|
|
5461
|
+
message: "No source version is attributed to the requested transport scope."
|
|
5462
|
+
}
|
|
5463
|
+
};
|
|
5464
|
+
const base = ordered[oldestInScope.index + 1];
|
|
5465
|
+
const rangeDiagnostic = selectedRangeDiagnostic(ordered, inScope[0].index, oldestInScope.index, scope);
|
|
5466
|
+
if (rangeDiagnostic) return {
|
|
5467
|
+
changeKind: "ambiguous",
|
|
5468
|
+
exact: false,
|
|
5469
|
+
...base ? { base } : {},
|
|
5470
|
+
diagnostic: rangeDiagnostic
|
|
5471
|
+
};
|
|
5472
|
+
return base ? {
|
|
5473
|
+
changeKind: "deleted",
|
|
5474
|
+
exact: true,
|
|
5475
|
+
base
|
|
5476
|
+
} : {
|
|
5477
|
+
changeKind: "unsupported",
|
|
5478
|
+
exact: false,
|
|
5479
|
+
diagnostic: {
|
|
5480
|
+
code: "DELETED_SOURCE_BASE_UNAVAILABLE",
|
|
5481
|
+
message: "The deleted component has no recoverable historical source."
|
|
5482
|
+
}
|
|
5483
|
+
};
|
|
5484
|
+
}
|
|
5485
|
+
if (inScope.length === 0) return {
|
|
5486
|
+
changeKind: "ambiguous",
|
|
5487
|
+
exact: false,
|
|
5488
|
+
diagnostic: {
|
|
5489
|
+
code: "SOURCE_HISTORY_SCOPE_VERSION_MISSING",
|
|
5490
|
+
message: "No source version is attributed to the requested transport scope."
|
|
5491
|
+
}
|
|
5492
|
+
};
|
|
5493
|
+
const newest = inScope[0];
|
|
5494
|
+
const oldest = inScope.at(-1);
|
|
5495
|
+
if (!newest || !oldest) throw new Error("Unreachable source-history selection state.");
|
|
5496
|
+
const head = newest.candidate;
|
|
5497
|
+
const base = ordered[oldest.index + 1];
|
|
5498
|
+
const rangeDiagnostic = selectedRangeDiagnostic(ordered, newest.index, oldest.index, scope);
|
|
5499
|
+
if (rangeDiagnostic) return {
|
|
5500
|
+
changeKind: "ambiguous",
|
|
5501
|
+
exact: false,
|
|
5502
|
+
...base ? { base } : {},
|
|
5503
|
+
head,
|
|
5504
|
+
diagnostic: rangeDiagnostic
|
|
5505
|
+
};
|
|
5506
|
+
return base ? {
|
|
5507
|
+
changeKind: "modified",
|
|
5508
|
+
exact: true,
|
|
5509
|
+
base,
|
|
5510
|
+
head
|
|
5511
|
+
} : {
|
|
5512
|
+
changeKind: "added",
|
|
5513
|
+
exact: true,
|
|
5514
|
+
head
|
|
5515
|
+
};
|
|
5516
|
+
}
|
|
5517
|
+
function repositoryNameFromUri(uri, type) {
|
|
5518
|
+
if (!uri) return void 0;
|
|
5519
|
+
const endpoint = getEndpointForType(type);
|
|
5520
|
+
if (!endpoint) return void 0;
|
|
5521
|
+
const prefix = `/sap/bc/adt/${endpoint}/`;
|
|
5522
|
+
if (!uri.startsWith(prefix)) return void 0;
|
|
5523
|
+
const encodedName = uri.slice(prefix.length).split("/")[0];
|
|
5524
|
+
if (!encodedName) return void 0;
|
|
5525
|
+
try {
|
|
5526
|
+
return decodeURIComponent(encodedName).trim().toUpperCase() || void 0;
|
|
5527
|
+
} catch {
|
|
5528
|
+
return;
|
|
5529
|
+
}
|
|
5530
|
+
}
|
|
5531
|
+
function resolveFuncGroupReference(reference, rawType) {
|
|
5532
|
+
if (rawType !== "FUNC") return void 0;
|
|
5533
|
+
const ownerName = repositoryNameFromUri(reference.uri, "FUGR");
|
|
5534
|
+
if (!ownerName) return void 0;
|
|
5535
|
+
return {
|
|
5536
|
+
pgmid: "R3TR",
|
|
5537
|
+
type: "FUGR",
|
|
5538
|
+
name: ownerName,
|
|
5539
|
+
isDeleted: false
|
|
5540
|
+
};
|
|
5541
|
+
}
|
|
5542
|
+
async function resolveFuncGroupBySearch(reference, context) {
|
|
5543
|
+
if (reference.pgmid.trim().toUpperCase() !== "LIMU" || reference.type.trim().toUpperCase() !== "FUNC" || reference.wbtype?.trim().toUpperCase().split("/")[0] !== "FUGR") return void 0;
|
|
5544
|
+
try {
|
|
5545
|
+
const result = await context.client.adt.repository.informationsystem.search.quickSearch({
|
|
5546
|
+
query: reference.name,
|
|
5547
|
+
maxResults: 10
|
|
5548
|
+
});
|
|
5549
|
+
const raw = (asRecord(result["objectReferences"]) ?? asRecord(result["mainObject"]))?.["objectReference"] ?? result["objectReference"];
|
|
5550
|
+
const ownerName = (Array.isArray(raw) ? raw : [raw]).map(asRecord).filter((item) => Boolean(item)).filter((item) => nonEmptyString(item["name"])?.toUpperCase() === reference.name.trim().toUpperCase()).map((item) => repositoryNameFromUri(nonEmptyString(item["uri"]), "FUGR")).find((name) => Boolean(name));
|
|
5551
|
+
return ownerName ? {
|
|
5552
|
+
pgmid: "R3TR",
|
|
5553
|
+
type: "FUGR/FF",
|
|
5554
|
+
name: reference.name.trim().toUpperCase(),
|
|
5555
|
+
functionGroupName: ownerName,
|
|
5556
|
+
isDeleted: reference.isDeleted
|
|
5557
|
+
} : void 0;
|
|
5558
|
+
} catch {
|
|
5559
|
+
return;
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5562
|
+
function resolveLimuReference(reference, pgmid, rawType) {
|
|
5563
|
+
if (pgmid !== "LIMU") return void 0;
|
|
5564
|
+
const ownerType = reference.wbtype?.trim().toUpperCase();
|
|
5565
|
+
const ownerName = ownerType ? repositoryNameFromUri(reference.uri, ownerType) : void 0;
|
|
5566
|
+
if (ownerType && ownerName) return {
|
|
5567
|
+
pgmid: "R3TR",
|
|
5568
|
+
type: ownerType,
|
|
5569
|
+
name: ownerName,
|
|
5570
|
+
isDeleted: rawType === "REPS" && reference.isDeleted
|
|
5571
|
+
};
|
|
5572
|
+
if (rawType === "REPS") return {
|
|
5573
|
+
pgmid: "R3TR",
|
|
5574
|
+
type: "PROG",
|
|
5575
|
+
name: reference.name.trim().toUpperCase(),
|
|
5576
|
+
isDeleted: reference.isDeleted
|
|
5577
|
+
};
|
|
5578
|
+
}
|
|
5579
|
+
function fallbackReference(reference, pgmid, rawTypeFull) {
|
|
5580
|
+
return {
|
|
5581
|
+
pgmid,
|
|
5582
|
+
type: rawTypeFull,
|
|
5583
|
+
name: reference.name.trim().toUpperCase(),
|
|
5584
|
+
isDeleted: reference.isDeleted
|
|
5585
|
+
};
|
|
5586
|
+
}
|
|
5587
|
+
/** Resolve a CTS object to the repository object that owns its source. */
|
|
5588
|
+
async function repositoryObjectReference(reference, context) {
|
|
5589
|
+
const pgmid = reference.pgmid.trim().toUpperCase();
|
|
5590
|
+
const rawTypeFull = reference.type.trim().toUpperCase();
|
|
5591
|
+
const rawType = rawTypeFull.split("/")[0] ?? "";
|
|
5592
|
+
return resolveFuncGroupReference(reference, rawType) ?? await resolveFuncGroupBySearch(reference, context) ?? resolveLimuReference(reference, pgmid, rawType) ?? fallbackReference(reference, pgmid, rawTypeFull);
|
|
5593
|
+
}
|
|
5594
|
+
function selectorValues(value) {
|
|
5595
|
+
if (value === void 0) return [];
|
|
5596
|
+
return (Array.isArray(value) ? value : [value]).map((item) => item.trim().toUpperCase());
|
|
5597
|
+
}
|
|
5598
|
+
function selectorDimensionMatches(candidates, expected) {
|
|
5599
|
+
const values = selectorValues(expected);
|
|
5600
|
+
if (values.length === 0) return true;
|
|
5601
|
+
return values.some((value) => value === "*" || candidates.includes(value));
|
|
5602
|
+
}
|
|
5603
|
+
function manifestSelectorMatches(original, repository, selector) {
|
|
5604
|
+
if (!selector) return true;
|
|
5605
|
+
const repositoryType = repository.type.trim().toUpperCase();
|
|
5606
|
+
const repositoryMainType = repositoryType.split("/")[0] ?? "";
|
|
5607
|
+
return selectorDimensionMatches([original.objFunc.trim().toUpperCase()], selector.objFunc) && selectorDimensionMatches([original.pgmid.trim().toUpperCase(), repository.pgmid], selector.pgmid) && selectorDimensionMatches([
|
|
5608
|
+
original.type.trim().toUpperCase(),
|
|
5609
|
+
repositoryType,
|
|
5610
|
+
...repositoryMainType && repositoryMainType !== repositoryType ? [repositoryMainType] : []
|
|
5611
|
+
], selector.type);
|
|
5612
|
+
}
|
|
5613
|
+
function inventoryEntry(reference, sourceTransport) {
|
|
5614
|
+
const wbtype = reference.wbtype?.trim().toUpperCase();
|
|
5615
|
+
const uri = reference.uri?.trim();
|
|
5616
|
+
return {
|
|
5617
|
+
pgmid: reference.pgmid.trim().toUpperCase(),
|
|
5618
|
+
type: reference.type.trim().toUpperCase(),
|
|
5619
|
+
name: reference.name.trim().toUpperCase(),
|
|
5620
|
+
...wbtype ? { wbtype } : {},
|
|
5621
|
+
...uri ? { uri } : {},
|
|
5622
|
+
objFunc: reference.objFunc.trim().toUpperCase(),
|
|
5623
|
+
sourceTransport
|
|
5624
|
+
};
|
|
5625
|
+
}
|
|
5626
|
+
/**
|
|
5627
|
+
* CTS exposes a program's main source as the LIMU/REPS sub-object, while ADT
|
|
5628
|
+
* exposes the same source history through the repository PROG resource. Keep
|
|
5629
|
+
* the CTS key in the public manifest, but use the ADT model identity for
|
|
5630
|
+
* metadata and immutable-version discovery.
|
|
5631
|
+
*/
|
|
5632
|
+
function sourceHistoryDiscoveryType(reference) {
|
|
5633
|
+
const pgmid = reference.pgmid.trim().toUpperCase();
|
|
5634
|
+
const type = reference.type.trim().toUpperCase().split("/")[0];
|
|
5635
|
+
return pgmid === "LIMU" && type === "REPS" ? "PROG" : reference.type;
|
|
5636
|
+
}
|
|
5637
|
+
async function buildObjectEntries(original, repository, sourceTransport, scopeTransportNumbers, ctx) {
|
|
5638
|
+
const baseIdentity = {
|
|
5639
|
+
pgmid: original.pgmid,
|
|
5640
|
+
type: original.type,
|
|
5641
|
+
name: original.name
|
|
5642
|
+
};
|
|
5643
|
+
const hasRepositoryOwner = repository.pgmid !== baseIdentity.pgmid || repository.type !== baseIdentity.type || repository.name !== baseIdentity.name;
|
|
5644
|
+
const withRepositoryOwner = (entry, packageName) => hasRepositoryOwner ? {
|
|
5645
|
+
...entry,
|
|
5646
|
+
repositoryObject: {
|
|
5647
|
+
pgmid: repository.pgmid,
|
|
5648
|
+
type: repository.functionGroupName ? "FUGR" : repository.type,
|
|
5649
|
+
name: repository.functionGroupName ?? repository.name,
|
|
5650
|
+
...packageName ? { packageName } : {}
|
|
5651
|
+
}
|
|
5652
|
+
} : entry;
|
|
5653
|
+
let discovery;
|
|
5654
|
+
try {
|
|
5655
|
+
discovery = await discoverObjectSourceHistory(repository.name, sourceHistoryDiscoveryType(repository), ctx, false, repository.functionGroupName);
|
|
5656
|
+
} catch (error) {
|
|
5657
|
+
if (!(error instanceof ObjectSourceHistoryError)) throw error;
|
|
5658
|
+
return [withRepositoryOwner(unavailableEntry({
|
|
5659
|
+
...baseIdentity,
|
|
5660
|
+
...error.object.packageName ? { packageName: error.object.packageName } : {}
|
|
5661
|
+
}, { id: "object" }, sourceTransport, "unsupported", {
|
|
5662
|
+
code: error.code,
|
|
5663
|
+
message: error.message
|
|
5664
|
+
}))];
|
|
5665
|
+
}
|
|
5666
|
+
const identity = {
|
|
5667
|
+
...baseIdentity,
|
|
5668
|
+
...discovery.object.packageName ? { packageName: discovery.object.packageName } : {}
|
|
5669
|
+
};
|
|
5670
|
+
const manifestComponents = repository.type === "FUGR/FF" ? discovery.components.map((component) => component.id === "main" ? {
|
|
5671
|
+
...component,
|
|
5672
|
+
id: repository.name.toLowerCase()
|
|
5673
|
+
} : component) : discovery.components;
|
|
5674
|
+
const entries = [];
|
|
5675
|
+
for (const component of manifestComponents) {
|
|
5676
|
+
const publicComponent = {
|
|
5677
|
+
id: component.id,
|
|
5678
|
+
...component.sourceUri ? { sourceUri: component.sourceUri } : {},
|
|
5679
|
+
...component.versionsUri ? { versionsUri: component.versionsUri } : {}
|
|
5680
|
+
};
|
|
5681
|
+
if (component.diagnostic) {
|
|
5682
|
+
entries.push(withRepositoryOwner(unavailableEntry(identity, publicComponent, sourceTransport, "unsupported", component.diagnostic), discovery.object.packageName));
|
|
5683
|
+
continue;
|
|
5684
|
+
}
|
|
5685
|
+
if (!component.versionsUri) {
|
|
5686
|
+
entries.push(withRepositoryOwner(unavailableEntry(identity, publicComponent, sourceTransport, "unsupported", {
|
|
5687
|
+
code: "SOURCE_COMPONENT_VERSIONS_UNAVAILABLE",
|
|
5688
|
+
message: "The source component has no exact versions relation."
|
|
5689
|
+
}), discovery.object.packageName));
|
|
5690
|
+
continue;
|
|
5691
|
+
}
|
|
5692
|
+
let versions;
|
|
5693
|
+
try {
|
|
5694
|
+
versions = await ctx.client.services.sourceHistory.listVersions(component.versionsUri);
|
|
5695
|
+
} catch {
|
|
5696
|
+
entries.push(withRepositoryOwner(unavailableEntry(identity, publicComponent, sourceTransport, "failed", {
|
|
5697
|
+
code: "SOURCE_HISTORY_RETRIEVAL_FAILED",
|
|
5698
|
+
message: "SAP ADT rejected source-history metadata retrieval."
|
|
5699
|
+
}), discovery.object.packageName));
|
|
5700
|
+
continue;
|
|
5701
|
+
}
|
|
5702
|
+
const selection = selectTransportSourceVersions(versions, scopeTransportNumbers, repository.isDeleted);
|
|
5703
|
+
entries.push(withRepositoryOwner({
|
|
5704
|
+
object: identity,
|
|
5705
|
+
component: publicComponent,
|
|
5706
|
+
sourceTransport,
|
|
5707
|
+
...selection
|
|
5708
|
+
}, discovery.object.packageName));
|
|
5709
|
+
}
|
|
5710
|
+
return entries;
|
|
5711
|
+
}
|
|
5712
|
+
/**
|
|
5713
|
+
* List immutable source-version metadata for every discovered object component.
|
|
5714
|
+
* Source bodies remain lazy and are never read by this operation.
|
|
5715
|
+
*/
|
|
5716
|
+
async function listObjectSourceVersions(objectName, objectType, options = {}, ctx) {
|
|
5717
|
+
const context = ctx ?? getGlobalContext();
|
|
5718
|
+
const discovery = await discoverObjectSourceHistory(objectName, objectType, context);
|
|
5719
|
+
const requestedComponent = options.component?.trim().toUpperCase();
|
|
5720
|
+
const components = options.component !== void 0 ? discovery.components.filter((component) => component.id.toUpperCase() === requestedComponent) : discovery.components;
|
|
5721
|
+
if (components.length === 0) throw new ObjectSourceHistoryError("SOURCE_COMPONENT_NOT_FOUND", "The requested source component was not exposed by object metadata.", discovery.object);
|
|
5722
|
+
const results = [];
|
|
5723
|
+
for (const component of components) {
|
|
5724
|
+
const publicComponent = {
|
|
5725
|
+
id: component.id,
|
|
5726
|
+
...component.sourceUri ? { sourceUri: component.sourceUri } : {},
|
|
5727
|
+
...component.versionsUri ? { versionsUri: component.versionsUri } : {}
|
|
5728
|
+
};
|
|
5729
|
+
if (component.diagnostic) {
|
|
5730
|
+
results.push({
|
|
5731
|
+
...publicComponent,
|
|
5732
|
+
diagnostic: component.diagnostic
|
|
5733
|
+
});
|
|
5734
|
+
continue;
|
|
5735
|
+
}
|
|
5736
|
+
if (!component.versionsUri) {
|
|
5737
|
+
results.push({
|
|
5738
|
+
...publicComponent,
|
|
5739
|
+
diagnostic: {
|
|
5740
|
+
code: "SOURCE_COMPONENT_VERSIONS_UNAVAILABLE",
|
|
5741
|
+
message: "The source component has no exact versions relation."
|
|
5742
|
+
}
|
|
5743
|
+
});
|
|
5744
|
+
continue;
|
|
5745
|
+
}
|
|
5746
|
+
try {
|
|
5747
|
+
const versions = await context.client.services.sourceHistory.listVersions(component.versionsUri);
|
|
5748
|
+
results.push({
|
|
5749
|
+
...publicComponent,
|
|
5750
|
+
versions
|
|
5751
|
+
});
|
|
5752
|
+
} catch {
|
|
5753
|
+
results.push({
|
|
5754
|
+
...publicComponent,
|
|
5755
|
+
diagnostic: {
|
|
5756
|
+
code: "SOURCE_HISTORY_RETRIEVAL_FAILED",
|
|
5757
|
+
message: "SAP ADT rejected source-history metadata retrieval."
|
|
5758
|
+
}
|
|
5759
|
+
});
|
|
5760
|
+
}
|
|
5761
|
+
}
|
|
5762
|
+
return {
|
|
5763
|
+
object: discovery.object,
|
|
5764
|
+
components: results
|
|
5765
|
+
};
|
|
5766
|
+
}
|
|
5767
|
+
/**
|
|
5768
|
+
* Resolve transport objects and produce immutable source-history references.
|
|
5769
|
+
* Source bodies remain lazy and are never read while building the manifest.
|
|
5770
|
+
*/
|
|
5771
|
+
async function buildTransportSourceManifest(requestedTransports, options = {}, ctx) {
|
|
5772
|
+
const context = ctx ?? getGlobalContext();
|
|
5773
|
+
const requested = uniqueStable(requestedTransports);
|
|
5774
|
+
const resolved = await resolveTransportObjects(requested, {}, context);
|
|
5775
|
+
const scopeTransports = uniqueStable([...requested, ...resolved.scopeTransportNumbers]);
|
|
5776
|
+
const inventory = resolved.objects.map((reference) => inventoryEntry(reference, resolved.sourceTransportMap.get(reference.key) ?? requested[0] ?? "")).sort((left, right) => compareText(left.sourceTransport, right.sourceTransport) || compareText(left.pgmid, right.pgmid) || compareText(left.type, right.type) || compareText(left.name, right.name));
|
|
5777
|
+
const seenRepositoryObjects = /* @__PURE__ */ new Set();
|
|
5778
|
+
return {
|
|
5779
|
+
requestedTransports: requested,
|
|
5780
|
+
scopeTransports,
|
|
5781
|
+
inventory,
|
|
5782
|
+
entries: (await mapOrdered((await mapOrdered(resolved.objects.filter((reference) => !isNonSourceCtsObject(reference)), normalizeConcurrency(options.concurrency), async (original) => ({
|
|
5783
|
+
original,
|
|
5784
|
+
repository: await repositoryObjectReference(original, context),
|
|
5785
|
+
sourceTransport: resolved.sourceTransportMap.get(original.key) ?? requested[0] ?? ""
|
|
5786
|
+
}))).filter(({ original, repository }) => manifestSelectorMatches(original, repository, options.selector)).filter(({ repository }) => {
|
|
5787
|
+
const key = `${repository.pgmid}/${repository.type}/${repository.name}`;
|
|
5788
|
+
if (seenRepositoryObjects.has(key)) return false;
|
|
5789
|
+
seenRepositoryObjects.add(key);
|
|
5790
|
+
return true;
|
|
5791
|
+
}).sort((left, right) => compareText(left.repository.pgmid, right.repository.pgmid) || compareText(left.repository.type, right.repository.type) || compareText(left.repository.name, right.repository.name)), normalizeConcurrency(options.concurrency), ({ original, repository, sourceTransport }) => buildObjectEntries(original, repository, sourceTransport, scopeTransports, context))).flat()
|
|
5792
|
+
};
|
|
5793
|
+
}
|
|
4297
5794
|
|
|
4298
5795
|
//#endregion
|
|
4299
|
-
export { ADT_TYPE_MAPPINGS, AdkBadi, AdkBehaviorDefinition, AdkClass, AdkDataElement, AdkDclSource, AdkDdlSource, AdkDomain, AdkFunctionGroup, AdkFunctionModule, AdkGenericObject, AdkInclude, AdkInterface, AdkMainObject, AdkObject, AdkObjectSet, AdkPackage, AdkProgram, AdkServiceBinding, AdkServiceDefinition, AdkStructure, AdkTable, AdkTableType, AdkTransport, AdkTransportRequest as AdkTransportItem, AdkTransportRequest, AdkTransportObject, AdkTransportObjectRef, AdkTransportTask, AdkTransportTaskRef, Class, DataElement, Domain, EnhancementSpot, FunctionGroup, FunctionModule, Include, Interface, MergedTransportView, MessageClass, Package, Program, Structure, Table, TableType, TransportRequest, TransportTask, clearConfigCache, createAdk, createAdkContract, createAdkFactory, createLockService, getEndpointForType, getGlobalContext, getKindForType, getMainType, getObjectRootUri, getObjectUri, getRegisteredKinds, getRegisteredTypes, getTypeForKind, initializeAdk, isAdkInitialized, isTypeRegistered, matchesSelector, normalizeObjectName, parseAdtType, parseXmlIdentity, registerObjectType, resetAdk, resolveKind, resolveTransportObjects, resolveType, tryGetGlobalContext };
|
|
5796
|
+
export { ADT_TYPE_MAPPINGS, AdkBadi, AdkBehaviorDefinition, AdkCdsAspect, AdkCdsType, AdkClass, AdkClassicBadiDefinition, AdkClassicBadiImplementation, AdkDataElement, AdkDclSource, AdkDdlExtension, AdkDdlSource, AdkDomain, AdkDynamicCache, AdkEntityBuffer, AdkExternalSchema, AdkFunctionGroup, AdkFunctionModule, AdkGenericObject, AdkInclude, AdkInterface, AdkMainObject, AdkObject, AdkObjectSet, AdkPackage, AdkPostCreateLockError, AdkProgram, AdkScalarFunctionDefinition, AdkScalarFunctionImplementation, AdkServiceBinding, AdkServiceDefinition, AdkStaticCache, AdkStructure, AdkTable, AdkTableType, AdkTransport, AdkTransportRequest as AdkTransportItem, AdkTransportRequest, AdkTransportObject, AdkTransportObjectRef, AdkTransportTask, AdkTransportTaskRef, AdkTuningIndex, BehaviorDefinition, CdsAspect, CdsType, Class, DataElement, DclSource, DdlExtension, DdlSource, Domain, DynamicCache, EnhancementSpot, EntityBuffer, ExternalSchema, FunctionGroup, FunctionModule, Include, Interface, MergedTransportView, MessageClass, ObjectSourceHistoryError, Package, Program, ScalarFunctionDefinition, ScalarFunctionImplementation, ServiceBinding, ServiceDefinition, StaticCache, Structure, Table, TableType, TransportRequest, TransportTask, TuningIndex, buildTransportSourceManifest, clearConfigCache, createAdk, createAdkContract, createAdkFactory, createLockService, getEndpointForType, getGlobalContext, getKindForType, getMainType, getObjectRootUri, getObjectUri, getRegisteredKinds, getRegisteredTypes, getTypeForKind, initializeAdk, isAdkInitialized, isTypeRegistered, listObjectSourceVersions, matchesSelector, normalizeObjectName, parseAdtType, parseXmlIdentity, registerObjectType, resetAdk, resolveKind, resolveTransportObjects, resolveType, selectTransportSourceVersions, tryGetGlobalContext };
|
|
4300
5797
|
//# sourceMappingURL=index.mjs.map
|