trm-client 11.1.2 → 11.3.0

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,23 @@ Legend
8
8
  + : added
9
9
  - : removed
10
10
 
11
+ 2026-09-23 v11.3.0
12
+ -------------------
13
+ + system alias connection data saved after connecting when changed (e.g. rotated tokens)
14
+ ! alias check saves updated connection data
15
+ ! compare reads systems one at a time, closing each connection before opening the next
16
+
17
+ 2026-09-23 v11.2.0
18
+ -------------------
19
+ ! trm-core ^9.10.6
20
+ ! trm-commons ^5.1.0
21
+ + --connection-type option (env TRM_CONNECTION_TYPE) for non interactive connection
22
+ + --connection-args option (env TRM_CONNECTION_ARGS), JSON or JSON file path passed to connection
23
+ + cli option names mapped to connection argument keys
24
+ + warning for connection arguments not supported by connection type
25
+ + possible values in invalid connection type error
26
+ ! forward rfc destination no longer defaults to NONE (NONE only for non interactive connection)
27
+
11
28
  2026-09-02 v11.1.2
12
29
  -------------------
13
30
  ! trm-core ^9.10.5
@@ -46,6 +46,8 @@ export declare abstract class AbstractCommand {
46
46
  private checkTrmDependencies;
47
47
  parseTextArg(name: string): string;
48
48
  parseJsonArg(name: string): any;
49
+ private getConnectArgs;
50
+ private parseConnectionArgs;
49
51
  parseArrayArg(name: string): string[];
50
52
  parseNumberArg(name: string): number;
51
53
  run(args?: any, options?: AbstractCommandRunOptions): Promise<void>;
@@ -46,6 +46,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
48
  exports.AbstractCommand = void 0;
49
+ const commander_1 = require("commander");
49
50
  const utils_1 = require("../utils");
50
51
  const LoggerType_1 = require("./LoggerType");
51
52
  const InquirerType_1 = require("./InquirerType");
@@ -206,7 +207,9 @@ class AbstractCommand {
206
207
  .option(`-r, --sap-router <sap router>`, `RFC SAP Router.`)
207
208
  .option(`-n, --sys-nr <sysnr>`, `Instance number.`)
208
209
  .option(`-e, --endpoint <endpoint>`, `REST endpoint.`)
209
- .option(`-x, --forward-rfc-dest [destination]`, `REST forward destination.`, `NONE`);
210
+ .option(`-x, --forward-rfc-dest [destination]`, `REST forward RFC destination.`)
211
+ .addOption(new commander_1.Option(`--connection-type <type>`, `Connection type (e.g. RFC, REST or a plugin connection type), skips the connection prompt.`).env(`TRM_CONNECTION_TYPE`))
212
+ .addOption(new commander_1.Option(`--connection-args <arguments>`, `Connection arguments, passed to the connection type (JSON or path to JSON file).`).env(`TRM_CONNECTION_ARGS`));
210
213
  if (!this.registerOpts.noSystemAlias) {
211
214
  this.command
212
215
  .option(`-a, --alias <alias>`, `System Alias.`);
@@ -384,6 +387,52 @@ class AbstractCommand {
384
387
  catch (_a) { }
385
388
  }
386
389
  }
390
+ getConnectArgs() {
391
+ const connectArgs = Object.assign({}, this.args);
392
+ const mapping = [
393
+ ['client', 'mandt'],
394
+ ['passwd', 'password'],
395
+ ['ashost', 'applicationServer'],
396
+ ['sysnr', 'sysNr'],
397
+ ['saprouter', 'sapRouter']
398
+ ];
399
+ mapping.forEach(([key, cliKey]) => {
400
+ if (connectArgs[key] === undefined && connectArgs[cliKey] !== undefined) {
401
+ connectArgs[key] = connectArgs[cliKey];
402
+ }
403
+ });
404
+ if (this.args.connectionType) {
405
+ connectArgs.type = this.args.connectionType;
406
+ if (typeof connectArgs.forwardRfcDest !== 'string') {
407
+ connectArgs.forwardRfcDest = 'NONE';
408
+ }
409
+ }
410
+ connectArgs.connectionArgs = this.parseConnectionArgs();
411
+ return connectArgs;
412
+ }
413
+ parseConnectionArgs() {
414
+ if (!this.args.connectionArgs) {
415
+ return undefined;
416
+ }
417
+ var sValue;
418
+ try {
419
+ sValue = (0, fs_1.readFileSync)(this.args.connectionArgs).toString();
420
+ }
421
+ catch (_a) {
422
+ sValue = this.args.connectionArgs;
423
+ }
424
+ var value;
425
+ try {
426
+ value = JSON.parse(sValue);
427
+ }
428
+ catch (_b) {
429
+ throw new Error(`Invalid connection arguments: expected a JSON object or the path to a JSON file.`);
430
+ }
431
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
432
+ throw new Error(`Invalid connection arguments: expected a JSON object.`);
433
+ }
434
+ return value;
435
+ }
387
436
  parseArrayArg(name) {
388
437
  if (this.args[name]) {
389
438
  try {
@@ -493,13 +542,25 @@ class AbstractCommand {
493
542
  });
494
543
  if (this.registerOpts.requiresConnection) {
495
544
  var system;
545
+ var systemAlias;
496
546
  if (this.args.alias) {
497
- system = systemAlias_1.SystemAlias.get(this.args.alias).getConnection();
547
+ systemAlias = systemAlias_1.SystemAlias.get(this.args.alias);
548
+ system = systemAlias.getConnection();
498
549
  }
499
550
  else {
500
- system = (yield (0, prompts_1.connect)(this.args, true, this.registerOpts.addNoConnection)).connect.getSystemConnector();
551
+ const connectArgs = this.getConnectArgs();
552
+ system = (yield (0, prompts_1.connect)(connectArgs, !this.args.connectionType, this.registerOpts.addNoConnection)).connect.getSystemConnector();
501
553
  }
502
554
  yield system.connect(false);
555
+ if (systemAlias) {
556
+ try {
557
+ systemAlias.saveChanges();
558
+ }
559
+ catch (e) {
560
+ Commons.Logger.warning(`Couldn't update system alias "${this.args.alias}" data.`);
561
+ Commons.Logger.error(e, true);
562
+ }
563
+ }
503
564
  Core.SystemConnector.systemConnector = system;
504
565
  yield Commons.Plugin.call("client", "onInitializeSystemConnector", Core.SystemConnector.systemConnector);
505
566
  if (this.registerOpts.requiresTrmDependencies) {
@@ -33,9 +33,10 @@ class Alias extends AbstractCommand_1.AbstractCommand {
33
33
  check(alias) {
34
34
  return __awaiter(this, void 0, void 0, function* () {
35
35
  trm_commons_1.Logger.loading(`Checking connection with alias "${alias.alias}"...`);
36
- const oSystemAlias = new systemAlias_1.SystemAlias(alias.type, alias.data);
36
+ const oSystemAlias = new systemAlias_1.SystemAlias(alias.type, alias.data, alias.alias);
37
37
  try {
38
38
  yield oSystemAlias.getConnection().connect(false);
39
+ oSystemAlias.saveChanges();
39
40
  trm_commons_1.Logger.success(`Connection to alias "${alias.alias}" OK.`);
40
41
  }
41
42
  catch (e) {
@@ -24,7 +24,7 @@ class Compare extends AbstractCommand_1.AbstractCommand {
24
24
  promptConnections() {
25
25
  return __awaiter(this, void 0, void 0, function* () {
26
26
  if (this.connections.length > 0) {
27
- trm_commons_1.Logger.info(`Compare systems: ${this.connections.map(o => o.getDest()).join(', ')}`);
27
+ trm_commons_1.Logger.info(`Compare systems: ${this.connections.map(o => o.connector.getDest()).join(', ')}`);
28
28
  }
29
29
  var askConnection = true;
30
30
  const inq1 = yield trm_commons_1.Inquirer.prompt([{
@@ -39,7 +39,8 @@ class Compare extends AbstractCommand_1.AbstractCommand {
39
39
  const connectArgs = yield (0, prompts_1.connect)({}, false, false);
40
40
  const systemConnector = connectArgs.connect.getSystemConnector();
41
41
  yield systemConnector.connect(false);
42
- this.connections.push(systemConnector);
42
+ yield systemConnector.closeConnection();
43
+ this.connections.push({ connector: systemConnector });
43
44
  return true;
44
45
  }
45
46
  else {
@@ -56,8 +57,7 @@ class Compare extends AbstractCommand_1.AbstractCommand {
56
57
  for (const sAlias of inputConnections) {
57
58
  if (typeof (sAlias) === 'string') {
58
59
  const oAlias = systemAlias_1.SystemAlias.get(sAlias);
59
- const oConnection = oAlias.getConnection();
60
- this.connections.push(oConnection);
60
+ this.connections.push({ connector: oAlias.getConnection(), alias: oAlias });
61
61
  }
62
62
  }
63
63
  }
@@ -67,7 +67,7 @@ class Compare extends AbstractCommand_1.AbstractCommand {
67
67
  keepPrompt = yield this.promptConnections();
68
68
  }
69
69
  }
70
- trm_commons_1.Logger.info(`Compare systems: ${this.connections.map(o => o.getDest()).join(', ')}`);
70
+ trm_commons_1.Logger.info(`Compare systems: ${this.connections.map(o => o.connector.getDest()).join(', ')}`);
71
71
  const tableHead = [`System`, `Installed`, `Version`, `Devclass`, `Import transport`];
72
72
  var tableData = [];
73
73
  trm_commons_1.Logger.loading(`Reading registry data...`);
@@ -77,14 +77,30 @@ class Compare extends AbstractCommand_1.AbstractCommand {
77
77
  }
78
78
  catch (e) { }
79
79
  trm_commons_1.Logger.loading(`Reading system data...`);
80
- for (const oConnection of this.connections) {
80
+ for (const { connector: oConnection, alias: oAlias } of this.connections) {
81
+ yield oConnection.connect(false);
82
+ if (oAlias) {
83
+ try {
84
+ oAlias.saveChanges();
85
+ }
86
+ catch (e) {
87
+ trm_commons_1.Logger.error(e, true);
88
+ }
89
+ }
81
90
  trm_core_1.SystemConnector.systemConnector = oConnection;
82
91
  const system = trm_core_1.SystemConnector.getDest() || '';
83
92
  var installed;
84
93
  var version;
85
94
  var devclass;
86
95
  var importTransport;
87
- const aSystemPackages = yield trm_core_1.SystemConnector.getInstalledPackages(true);
96
+ var aSystemPackages;
97
+ try {
98
+ aSystemPackages = yield trm_core_1.SystemConnector.getInstalledPackages(true);
99
+ }
100
+ finally {
101
+ yield oConnection.closeConnection();
102
+ trm_core_1.SystemConnector.systemConnector = undefined;
103
+ }
88
104
  const oSystemView = aSystemPackages.find(o => o.compareName(packageName) && o.compareRegistry(registry));
89
105
  if (oSystemView && oSystemView.manifest) {
90
106
  installed = 'Yes';
@@ -13,8 +13,9 @@ export type ConnectArguments = {
13
13
  noSystemAlias?: boolean;
14
14
  force?: boolean;
15
15
  endpoint?: string;
16
- forwardRfcDest?: string;
16
+ forwardRfcDest?: string | boolean;
17
17
  connection?: ISystemConnector;
18
+ connectionArgs?: Record<string, any>;
18
19
  };
19
20
  export declare function connect(commandArgs: ConnectArguments, createAliasIfNotExist?: boolean, addNoConnection?: boolean): Promise<{
20
21
  connect: IConnect;
@@ -14,6 +14,20 @@ const systemAlias_1 = require("../../systemAlias");
14
14
  const utils_1 = require("../../utils");
15
15
  const trm_commons_1 = require("trm-commons");
16
16
  const lodash_1 = require("lodash");
17
+ function applyConnectionArgs(connection, commandArgs) {
18
+ const connectionArgs = commandArgs.connectionArgs;
19
+ if (!connectionArgs) {
20
+ return commandArgs;
21
+ }
22
+ const declared = connection.connectionArgs;
23
+ if (Array.isArray(declared)) {
24
+ const unknown = Object.keys(connectionArgs).filter(k => !declared.find(o => o.name === k));
25
+ if (unknown.length > 0) {
26
+ trm_commons_1.Logger.warning(`Connection "${connection.name}" doesn't support argument(s) ${unknown.join(', ')}. Supported arguments: ${declared.map(o => o.name).join(', ') || 'none'}.`);
27
+ }
28
+ }
29
+ return Object.assign(Object.assign({}, commandArgs), connectionArgs);
30
+ }
17
31
  const languageList = [
18
32
  { value: 'AR', name: 'AR (Arabic)' },
19
33
  { value: 'BG', name: 'BG (Bulgarian)' },
@@ -128,7 +142,7 @@ function connect(commandArgs_1) {
128
142
  }
129
143
  connection.setData(inq2.data);
130
144
  if (connection.onAfterLoginData) {
131
- yield connection.onAfterLoginData(force, commandArgs);
145
+ yield connection.onAfterLoginData(force, applyConnectionArgs(connection, commandArgs));
132
146
  }
133
147
  if (!(0, lodash_1.isEqual)(inq2.data, connection.getData())) {
134
148
  systemAlias_1.SystemAlias.delete(inq2.alias);
@@ -170,8 +184,9 @@ function connect(commandArgs_1) {
170
184
  }
171
185
  const connectionType = utils_1.GlobalContext.getInstance().getConnections().find(o => o.name === type);
172
186
  if (!connectionType) {
173
- throw new Error(`Invalid connection type "${type}"`);
187
+ throw new Error(`Invalid connection type "${type}". Possible values are ${utils_1.GlobalContext.getInstance().getConnections().map(o => o.name).join(', ')}.`);
174
188
  }
189
+ commandArgs = applyConnectionArgs(connectionType, commandArgs);
175
190
  if (connectionType.onConnectionData) {
176
191
  yield connectionType.onConnectionData(force, commandArgs);
177
192
  }
@@ -4,13 +4,17 @@ import { IConnect } from "trm-commons";
4
4
  export declare class SystemAlias {
5
5
  type: string;
6
6
  private _data;
7
- constructor(type: string, _data: any);
7
+ private _name?;
8
+ private _connection;
9
+ constructor(type: string, _data: any, _name?: string);
8
10
  getConnection(): ISystemConnector;
11
+ saveChanges(): void;
9
12
  private static generateFile;
10
13
  private static getSystemAliasFilePath;
11
14
  static getAll(): SystemAliasData[];
12
15
  static get(name: string): SystemAlias;
13
16
  static create(name: string, type: string, data: any): SystemAlias;
17
+ static update(name: string, data: any): void;
14
18
  static delete(name: string): void;
15
19
  private static deepEqual;
16
20
  static compare(a: SystemAlias, b: SystemAlias): boolean;
@@ -53,9 +53,10 @@ const ini = __importStar(require("ini"));
53
53
  const trm_commons_1 = require("trm-commons");
54
54
  const SYSTEM_FILE_NAME = "systems.ini";
55
55
  class SystemAlias {
56
- constructor(type, _data) {
56
+ constructor(type, _data, _name) {
57
57
  this.type = type;
58
58
  this._data = _data;
59
+ this._name = _name;
59
60
  }
60
61
  getConnection() {
61
62
  const connection = utils_1.GlobalContext.getInstance().getConnections().find(o => o.name === this.type);
@@ -63,8 +64,28 @@ class SystemAlias {
63
64
  throw new Error(`Unknown connection type "${this.type}". Possible values are ${utils_1.GlobalContext.getInstance().getConnections().map(k => k.name).join(', ')}.`);
64
65
  }
65
66
  connection.setData(this._data.data || this._data);
67
+ this._connection = connection;
66
68
  return connection.getSystemConnector();
67
69
  }
70
+ saveChanges() {
71
+ if (!this._name || !this._connection) {
72
+ return;
73
+ }
74
+ const normalize = (data) => {
75
+ const normalized = {};
76
+ Object.keys(data || {}).sort().forEach(key => {
77
+ if (key !== 'type' && data[key] !== undefined && data[key] !== null) {
78
+ normalized[key] = `${data[key]}`;
79
+ }
80
+ });
81
+ return normalized;
82
+ };
83
+ const newData = this._connection.getData();
84
+ if (!SystemAlias.deepEqual(normalize(this._data.data || this._data), normalize(newData))) {
85
+ SystemAlias.update(this._name, newData);
86
+ this._data = newData;
87
+ }
88
+ }
68
89
  static generateFile(content, filePath) {
69
90
  if (!filePath) {
70
91
  filePath = this.getSystemAliasFilePath();
@@ -110,7 +131,7 @@ class SystemAlias {
110
131
  const aAlias = this.getAll();
111
132
  const alias = aAlias.find(o => o.alias.trim().toUpperCase() === name.trim().toUpperCase());
112
133
  if (alias) {
113
- return new SystemAlias(alias.type, alias);
134
+ return new SystemAlias(alias.type, alias, alias.alias);
114
135
  }
115
136
  else {
116
137
  throw new Error(`System alias "${name}" not found.`);
@@ -135,6 +156,15 @@ class SystemAlias {
135
156
  }
136
157
  return new SystemAlias(type, data);
137
158
  }
159
+ static update(name, data) {
160
+ const aAlias = this.getAll();
161
+ const alias = aAlias.find(o => o.alias.trim().toUpperCase() === name.trim().toUpperCase());
162
+ if (!alias) {
163
+ throw new Error(`System alias "${name}" not found.`);
164
+ }
165
+ alias.data = data;
166
+ this.generateFile(aAlias);
167
+ }
138
168
  static delete(name) {
139
169
  var aAlias = this.getAll();
140
170
  aAlias = aAlias.filter(o => o.alias.trim().toUpperCase() !== name.trim().toUpperCase());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trm-client",
3
- "version": "11.1.2",
3
+ "version": "11.3.0",
4
4
  "description": "TRM (Transport Request Manager) Client",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -46,13 +46,13 @@
46
46
  "lodash": "^4.17.21",
47
47
  "sanitize-filename": "^1.6.3",
48
48
  "semver": "^7.7.4",
49
- "trm-commons": "^5.0.1",
50
- "trm-core": "^9.10.5",
49
+ "trm-commons": "^5.1.0",
50
+ "trm-core": "^9.10.6",
51
51
  "trm-registry-types": "^2.4.0",
52
52
  "xml2js": "^0.6.2"
53
53
  },
54
54
  "peerDependencies": {
55
- "trm-commons": "^5.0.1"
55
+ "trm-commons": "^5.1.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/ini": "^1.3.31",