trm-core 10.3.0 → 10.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.txt CHANGED
@@ -8,6 +8,17 @@ Legend
8
8
  + : added
9
9
  - : removed
10
10
 
11
+ 2026-10-14 v10.3.2
12
+ -------------------
13
+ * post activities xml -> json
14
+ + post activity ui method parameters
15
+ + default values for local export
16
+
17
+ 2026-10-14 v10.3.1
18
+ -------------------
19
+ * dependency tree preserves the direct ABAP package instead of collapsing it to the root package
20
+ * dependency tree lists every object referencing the same TRM package
21
+
11
22
  2026-10-14 v10.3.0
12
23
  -------------------
13
24
  * rollback cleanup excludes LANG entries rejected by SAP deletion transports
@@ -114,12 +114,12 @@ export type CustomizingRow = {
114
114
  */
115
115
  export declare function getPackagesInstalledIn(systemPackages: TrmPackage[], installed: TrmPackage, devclasses: Set<string>): TrmPackage[];
116
116
  /**
117
- * Locks on those of `objects` that removing `installed` certainly deletes: the objects of its
118
- * installed transport still in its SAP packages. These would abort the cleanup at its objects
119
- * lock check, so they can be checked before asking anything. Objects added locally or moved
120
- * outside the installation are left out, as the cleanup may keep them.
117
+ * Locks on what removing `installed` certainly deletes: the objects of its installed transport
118
+ * still in its SAP packages, and the SAP packages themselves when nothing may keep them. These
119
+ * would abort the cleanup at its objects lock check, so they can be checked before asking anything.
120
+ * Objects added locally or moved outside the installation are left out, as the cleanup may keep them.
121
121
  */
122
- export declare function getInstalledObjectsLocks(installed: TrmPackage, previousInstallPackages: InstallPackageReplacements[], systemPackages: TrmPackage[], objects: CleanupObject[]): Promise<ZTRM_OBJ_LOCK[]>;
122
+ export declare function getInstalledObjectsLocks(installed: TrmPackage, previousInstallPackages: InstallPackageReplacements[], systemPackages: TrmPackage[]): Promise<ZTRM_OBJ_LOCK[]>;
123
123
  /** Deletes every temporary package, reporting the first failure after the cleanup pass. */
124
124
  export declare function deleteTemporaryCleanupPackages(temporaryPackages: Array<Pick<E071, 'objName'>>): Promise<void>;
125
125
  /**
@@ -161,26 +161,47 @@ function readRelocatedObjects(objects, tree) {
161
161
  });
162
162
  }
163
163
  /**
164
- * Locks on those of `objects` that removing `installed` certainly deletes: the objects of its
165
- * installed transport still in its SAP packages. These would abort the cleanup at its objects
166
- * lock check, so they can be checked before asking anything. Objects added locally or moved
167
- * outside the installation are left out, as the cleanup may keep them.
164
+ * Locks on what removing `installed` certainly deletes: the objects of its installed transport
165
+ * still in its SAP packages, and the SAP packages themselves when nothing may keep them. These
166
+ * would abort the cleanup at its objects lock check, so they can be checked before asking anything.
167
+ * Objects added locally or moved outside the installation are left out, as the cleanup may keep them.
168
168
  */
169
- function getInstalledObjectsLocks(installed, previousInstallPackages, systemPackages, objects) {
169
+ function getInstalledObjectsLocks(installed, previousInstallPackages, systemPackages) {
170
170
  return __awaiter(this, void 0, void 0, function* () {
171
- if (objects.length === 0) {
172
- return [];
173
- }
174
171
  const { previousTransportObjects } = yield readInstalledTransportObjects(installed);
175
172
  const installedKeys = new Set(previousTransportObjects.map(objectKey));
176
- const candidates = new Map(objects
177
- .filter(object => installedKeys.has(objectKey(object)))
173
+ // TRM comment rows are not objects; SAP packages follow the decision for the whole installation.
174
+ const candidates = new Map(previousTransportObjects
175
+ .filter(object => normalize(object.pgmid) !== '*' && !isDevclass(object))
178
176
  .map(object => [objectKey(object), object]));
179
- if (candidates.size === 0) {
180
- return [];
181
- }
182
177
  const tree = yield readInstallationTree(installed, previousInstallPackages, previousTransportObjects, [], systemPackages);
183
- (yield readRelocatedObjects(Array.from(candidates.values()), tree)).forEach(object => candidates.delete(objectKey(object)));
178
+ // SAP packages are kept when a TRM package is installed underneath, or when the cleanup of
179
+ // locally added packages or objects is declined.
180
+ let packagesDeleted = tree.otherInstallations.size === 0
181
+ && Array.from(tree.previousDevclasses.keys()).every(devclass => tree.installedDevclasses.has(devclass));
182
+ for (const devclass of packagesDeleted ? tree.previousDevclasses.values() : []) {
183
+ if ((yield systemConnector_1.SystemConnector.getDevclassObjects(devclass, false)).some(object => !isDevclass(object) && !isNamespace(object) && !installedKeys.has(objectKey(object)))) {
184
+ packagesDeleted = false;
185
+ break;
186
+ }
187
+ }
188
+ if (packagesDeleted) {
189
+ tree.previousDevclasses.forEach(devclass => candidates.set(objectKey({ pgmid: 'R3TR', object: 'DEVC', objName: devclass }), { pgmid: 'R3TR', object: 'DEVC', objName: devclass }));
190
+ }
191
+ // Only existing objects are deleted, and only those still in the installation's SAP packages.
192
+ const checkedObjects = Array.from(candidates.values()).filter(object => normalize(object.pgmid) === 'R3TR');
193
+ if (checkedObjects.length > 0) {
194
+ const existing = new Map((yield systemConnector_1.SystemConnector.getExistingObjects(checkedObjects.map(object => ({
195
+ pgmid: object.pgmid, object: object.object, objName: object.objName, devclass: ''
196
+ })))).map(object => [objectKey(object), object]));
197
+ checkedObjects.forEach(object => {
198
+ const tadir = existing.get(objectKey(object));
199
+ if (!tadir || (!isDevclass(object) && tadir.devclass
200
+ && (!tree.previousDevclasses.has(normalize(tadir.devclass)) || tree.isOtherInstallation(tadir.devclass)))) {
201
+ candidates.delete(objectKey(object));
202
+ }
203
+ });
204
+ }
184
205
  if (candidates.size === 0) {
185
206
  return [];
186
207
  }
@@ -176,8 +176,24 @@ exports.init = {
176
176
  //if not provided, derive it from the system package (previous publish), then prompt (if allowed)
177
177
  //supplied or derived values are normalized and validated, prompted values are validated by the prompt
178
178
  var packageNeedsValidation = true;
179
+ let installedPublicPackage;
180
+ if (context.rawInput.packageData.registry.getRegistryType() === registry_1.RegistryType.LOCAL) {
181
+ installedPublicPackage = context.rawInput.contextData.systemPackages.find(o => o.compareName(context.rawInput.packageData.name)
182
+ && o.registry.getRegistryType() === registry_1.RegistryType.PUBLIC
183
+ && !!o.manifest);
184
+ if (installedPublicPackage) {
185
+ const manifest = installedPublicPackage.manifest.get();
186
+ context.runtime.latest.data = {
187
+ manifest,
188
+ dist_tags: { latest: manifest.version },
189
+ versions: [manifest.version],
190
+ yanked_versions: [],
191
+ transports: []
192
+ };
193
+ }
194
+ }
179
195
  if (!context.rawInput.packageData.devclass) {
180
- const trmPackage = context.rawInput.contextData.systemPackages.find(o => trmPackage_1.TrmPackage.compare(o, new trmPackage_1.TrmPackage(context.rawInput.packageData.name, context.rawInput.packageData.registry)));
196
+ const trmPackage = installedPublicPackage || context.rawInput.contextData.systemPackages.find(o => trmPackage_1.TrmPackage.compare(o, new trmPackage_1.TrmPackage(context.rawInput.packageData.name, context.rawInput.packageData.registry)));
181
197
  if (trmPackage) {
182
198
  context.rawInput.packageData.devclass = trmPackage.getDevclass();
183
199
  }
@@ -77,17 +77,16 @@ exports.init = {
77
77
  const previousInstallPackages = yield systemConnector_1.SystemConnector.getInstallPackages(installed.packageName, installed.registry);
78
78
  const previousInstallTransports = yield systemConnector_1.SystemConnector.getInstallTransports(installed.packageName, installed.registry);
79
79
  const nestedPackages = yield (0, uninstallNestedPackages_1.getNestedPackages)(context.rawInput.contextData.systemPackages, installed, previousInstallPackages.map(replacement => replacement.installDevclass));
80
- //5- dirty check: changes still being edited would fail the cleanup objects lock check,
81
- //so check them before asking anything
82
- const allDirtyEntries = yield (0, utils_1.withoutOwnTrmTransports)(installed.getDirtyEntries(), installed.packageName);
83
- if (allDirtyEntries.length > 0) {
84
- trm_commons_1.Logger.loading(`Checking changed objects locks...`, true);
85
- const locks = yield (0, utils_1.getInstalledObjectsLocks)(installed, previousInstallPackages, context.rawInput.contextData.systemPackages, allDirtyEntries);
86
- if (locks.length > 0) {
87
- locks.forEach(lock => trm_commons_1.Logger.error(`${lock.pgmid} ${lock.object} ${lock.objName} is currently locked in transport ${lock.trkorr}`, { important: true }));
88
- throw new Error(`Uninstall aborted. To continue, all cleanup objects and SAP packages must be released`);
89
- }
80
+ //5- dirty check: objects still being edited would fail the cleanup objects lock check,
81
+ //so check them before asking anything. Dirty entries may not list every edit: check all
82
+ //the cleanup deletes for sure
83
+ trm_commons_1.Logger.loading(`Checking installed objects locks...`, true);
84
+ const locks = yield (0, utils_1.getInstalledObjectsLocks)(installed, previousInstallPackages, context.rawInput.contextData.systemPackages);
85
+ if (locks.length > 0) {
86
+ locks.forEach(lock => trm_commons_1.Logger.error(`${lock.pgmid} ${lock.object} ${lock.objName} is currently locked in transport ${lock.trkorr}`, { important: true }));
87
+ throw new Error(`Uninstall aborted. To continue, all cleanup objects and SAP packages must be released`);
90
88
  }
89
+ const allDirtyEntries = yield (0, utils_1.withoutOwnTrmTransports)(installed.getDirtyEntries(), installed.packageName);
91
90
  //the TRM packages installed under it confirm their own changes
92
91
  const dirtyEntries = yield (0, uninstallNestedPackages_1.withoutNestedDirtyEntries)(allDirtyEntries, nestedPackages.all);
93
92
  if (dirtyEntries.length > 0 && !context.rawInput.uninstallData.checks.ignoreDirty) {
@@ -80,7 +80,7 @@ class PackageDependencies {
80
80
  foundIn: []
81
81
  }) - 1;
82
82
  }
83
- if (!this.trmPackageDependencies[depIndex].foundIn.find(f => f.object === o.object && f.objName === f.objName)) {
83
+ if (!this.trmPackageDependencies[depIndex].foundIn.find(f => f.object === o.object && f.objName === o.objName)) {
84
84
  this.trmPackageDependencies[depIndex].foundIn.push({
85
85
  object: o.object,
86
86
  objName: o.objName
@@ -98,11 +98,12 @@ class PackageDependencies {
98
98
  for (const dep of sapPackage.dependencies) {
99
99
  // only if the abap package is not a subpackage of the one analyzed
100
100
  if (!(yield this.getDevclasses()).includes(sapPackage.package)) {
101
- // get the root, in trm we assume subpackages are part of the same package (supposing the user will generate on after a mising dependency)
102
- const root = yield systemConnector_1.SystemConnector.getRootDevclass(sapPackage.package);
103
- var packageIndex = this.abapPackageDependencies.findIndex(k => k.abapPackage.devclass === root);
101
+ // Keep the package that owns the dependency. Collapsing it to the topmost
102
+ // superpackage loses the actionable package reported by TADIR and can group
103
+ // unrelated dependencies under a broad customer-package root.
104
+ var packageIndex = this.abapPackageDependencies.findIndex(k => k.abapPackage.devclass === sapPackage.package);
104
105
  if (packageIndex < 0) {
105
- const abapPackage = yield systemConnector_1.SystemConnector.getDevclass(root);
106
+ const abapPackage = yield systemConnector_1.SystemConnector.getDevclass(sapPackage.package);
106
107
  packageIndex = this.abapPackageDependencies.push({
107
108
  abapPackage: abapPackage,
108
109
  isCustomerPackage: !abapPackage.tpclass,
@@ -755,6 +755,30 @@ class Manifest {
755
755
  }];
756
756
  }
757
757
  }
758
+ if (oAbapManifest.postActivities && oAbapManifest.postActivities.item) {
759
+ const postActivities = Array.isArray(oAbapManifest.postActivities.item)
760
+ ? oAbapManifest.postActivities.item
761
+ : [oAbapManifest.postActivities.item];
762
+ manifest.postActivities = postActivities.map(postActivity => {
763
+ var _a, _b;
764
+ const parsedPostActivity = {
765
+ name: (_a = postActivity.name) === null || _a === void 0 ? void 0 : _a.text
766
+ };
767
+ if ((_b = postActivity.parameters) === null || _b === void 0 ? void 0 : _b.item) {
768
+ const parameters = Array.isArray(postActivity.parameters.item)
769
+ ? postActivity.parameters.item
770
+ : [postActivity.parameters.item];
771
+ parsedPostActivity.parameters = parameters.map(parameter => {
772
+ var _a, _b;
773
+ return ({
774
+ name: (_a = parameter.name) === null || _a === void 0 ? void 0 : _a.text,
775
+ value: (_b = parameter.value) === null || _b === void 0 ? void 0 : _b.text
776
+ });
777
+ });
778
+ }
779
+ return parsedPostActivity;
780
+ });
781
+ }
758
782
  if (oAbapManifest.engines && oAbapManifest.engines.text) {
759
783
  try {
760
784
  manifest.engines = JSON.parse(oAbapManifest.engines.text);
@@ -85,10 +85,20 @@ class SystemConnectorBase {
85
85
  const hasMore = classes.length > ctx.limit;
86
86
  const rows = classes.slice(0, ctx.limit).map(o => ({ name: o.clsname }));
87
87
  if (rows.length > 0) {
88
- const texts = yield this.readTable('SEOCLASSTX', [{ fieldName: 'CLSNAME' }, { fieldName: 'DESCRIPT' }], `LANGU EQ '${this.getLangu(true)}' AND ( ${rows.map(o => `CLSNAME EQ '${o.name}'`).join(' OR ')} )`);
88
+ const classOptions = `( ${rows.map(o => `CLSNAME EQ '${o.name}'`).join(' OR ')} )`;
89
+ const [texts, mandatoryParameters] = yield Promise.all([
90
+ this.readTable('SEOCLASSTX', [{ fieldName: 'CLSNAME' }, { fieldName: 'DESCRIPT' }], `LANGU EQ '${this.getLangu(true)}' AND ${classOptions}`),
91
+ this.readTable('SEOSUBCODF', [{ fieldName: 'CLSNAME' }, { fieldName: 'SCONAME' }, { fieldName: 'PARVALUE' }], `CMPNAME EQ '${exports.POST_ACTIVITY_METHOD}' AND PARDECLTYP EQ '0' AND PAROPTIONL EQ '' AND VERSION EQ '1' AND ${classOptions}`)
92
+ ]);
89
93
  rows.forEach(o => {
90
94
  var _a;
91
95
  o.description = (_a = texts.find(t => t.clsname === o.name)) === null || _a === void 0 ? void 0 : _a.descript;
96
+ const parameters = mandatoryParameters
97
+ .filter(parameter => parameter.clsname === o.name)
98
+ .map(parameter => (Object.assign({ name: parameter.sconame }, (parameter.parvalue ? { value: parameter.parvalue } : {}))));
99
+ if (parameters.length > 0) {
100
+ o.parameters = parameters;
101
+ }
92
102
  });
93
103
  }
94
104
  return { rows, hasMore };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trm-core",
3
- "version": "10.3.0",
3
+ "version": "10.3.2",
4
4
  "description": "TRM (Transport Request Manager) Core",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -67,7 +67,7 @@
67
67
  "xml-js": "^1.6.11"
68
68
  },
69
69
  "peerDependencies": {
70
- "trm-commons": "^5.3.0"
70
+ "trm-commons": "^5.4.1"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@types/adm-zip": "^0.5.0",
@@ -84,7 +84,7 @@
84
84
  "@types/stack-trace": "^0.0.33",
85
85
  "jest": "^30.5.2",
86
86
  "rimraf": "^6.0.1",
87
- "trm-commons": "^5.3.0",
87
+ "trm-commons": "^5.4.1",
88
88
  "ts-jest": "^29.4.1",
89
89
  "ts-node": "^10.9.2",
90
90
  "typescript": "^5.8.2"