trm-client 7.5.1 → 7.7.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/README.md CHANGED
@@ -12,22 +12,195 @@
12
12
 
13
13
  [trm-client](https://www.npmjs.com/package/trm-client) is the CLI implementation of the core functionalities of TRM.
14
14
 
15
- **TRM (Transport Request Manager)** is a package manager inspired solution built leveraging CTS that simplifies SAP ABAP transports.
15
+ 🚚 **TRM (Transport Request Manager)** is a package manager inspired solution built leveraging CTS that simplifies SAP ABAP transports.
16
+
17
+ <p align="center">
18
+ <img src="https://docs.trmregistry.com/logo.png" alt="TRM Logo" />
19
+ </p>
20
+
21
+ TRM introduces **package-based software delivery** to the SAP ecosystem, bringing with it semantic versioning, dependency management, and automated deployment activities.
22
+
23
+ ---
24
+
25
+ # What is TRM?
26
+
27
+ TRM is a software that transforms how custom ABAP developments are published, installed, and maintained across SAP landscapes.
28
+ Inspired by modern package managers, TRM introduces a declarative, version-controlled, and automated way to manage your SAP transports.
29
+
30
+ With TRM, you can:
31
+
32
+ - **Define a manifest** for each ABAP package (similar to `package.json` with Node.js or `pom.xml` with Maven)
33
+ - **Version your products** ([SemVer](https://semver.org/) compliance)
34
+ - **Declare dependencies** (to other TRM packages, SAP standard objects, or customizing data)
35
+ - **Automate post-install activities**, such as client dependant customizing, cache invalidation etc.
36
+ - **Validate system requirements** prior to installation
37
+ - **Compare versions** of the same product across multiple SAP systems (in or outside the same landscape)
38
+ - **Distribute** your product release to the public or to a restricted number of users:
39
+ - Registry (e.g., [trmregistry.com](https://trmregistry.com) or private registry)
40
+ - Local `.trm` files for offline installations
41
+
42
+ ## Modern approach for ABAP
43
+
44
+ - Publish ABAP packages from a **central development system**
45
+ - Deliver packages to target systems (outside of the original landscape e.g. customers development system) using a single CLI command (or in a pipeline)
46
+ - Full support for **workbench objects**, **customizing**, and **translations**
47
+
48
+ ## Structured Manifest
49
+
50
+ Each package includes a `manifest.json` that declares:
51
+
52
+ - Version and metadata
53
+ - System requirements
54
+ - Dependencies
55
+ - Post-install scripts
16
56
 
17
57
  # Documentation
18
58
 
19
- You can find the full documentation at [docs.trmregistry.com](https://docs.trmregistry.com).
59
+ Full documentation can be seen at [https://docs.trmregistry.com/](https://docs.trmregistry.com).
60
+
61
+ ---
62
+
63
+ <!-- START OF SETUP.MD -->
64
+
65
+ # Dockerized version (Recommended)
66
+
67
+ If you are using [Docker](https://www.docker.com/), the recommended approach is to use [trm-docker](https://github.com/RegestaItalia/trm-docker).
68
+
69
+ ## Download Docker Run Script
70
+
71
+ This script is a small utility used to run TRM inside Docker. After installing the required SAP proprietary tools, the script can be moved into a directory included in your `PATH` so that it can be executed from anywhere.
72
+
73
+ 1. Go to the [trm-docker repository](https://github.com/RegestaItalia/trm-docker)
74
+ 2. Download the script corresponding to your operating system:
75
+ - **Windows**: download [win.cmd](https://raw.githubusercontent.com/RegestaItalia/trm-docker/refs/heads/main/win.cmd) and rename it to `trm.cmd`
76
+ - **macOS / Linux**: download [macos](https://raw.githubusercontent.com/RegestaItalia/trm-docker/refs/heads/main/macos), rename it to `trm`, and make it executable:
77
+ ```bash
78
+ chmod +x trm
79
+ ```
80
+ 3. In the same directory where you placed the script, create a folder named `init`.
81
+
82
+ This `init` folder will later contain the SAP proprietary files required by TRM.
83
+
84
+ ## Download SAPCAR and SAPEXE and Extract Required Files
85
+
86
+ SAPCAR is used to extract `.SAR` archives downloaded from SAP Software Center.
87
+
88
+ ### Download SAPCAR
89
+
90
+ 1. Log in to the [SAP Software Center](https://me.sap.com/softwarecenter)
91
+ 2. Click **SUPPORT PACKAGES & PATCHES**
92
+ 3. Expand **By Alphabetical Index (A–Z)** and select **S**
93
+ 4. Click **SAPCAR**
94
+ 5. Choose the **latest version**
95
+ 6. On the download page select your operating system:
96
+ - **WINDOWS ON X64 64BIT**
97
+ - **MACOS ON ARM64BIT**
98
+ - **MACOS X 64-BIT**
99
+ 7. Download:
100
+ - **Windows** → latest `.EXE`
101
+ - **macOS** → latest `.ZIP`
102
+ 8. If using macOS, extract the archive and make the binary executable:
103
+ ```bash
104
+ chmod +x SAPCAR
105
+ ```
106
+
107
+ ### Download SAP Kernel Files
108
+
109
+ 1. Go back to **SUPPORT PACKAGES & PATCHES**
110
+ 2. Expand **By Alphabetical Index (A–Z)** and select **K**
111
+ 3. Click **SAP KERNEL 64-BIT**
112
+ 4. Choose the **latest version**
113
+ 5. On the download page select **LINUX ON X86_64 64BIT**
114
+ 6. Download the latest **SAPEXE** archive
115
+ (file name similar to `SAPEXE_###-########.SAR`)
116
+
117
+ ### Extract the Required Files
118
+
119
+ 1. Place the downloaded `SAPEXE_*.SAR` file in the same directory as `SAPCAR`.
120
+ 2. Extract it:
121
+
122
+ **Windows**
123
+ ```bash
124
+ SAPCAR -xvf SAPEXE_###-########.SAR
125
+ ```
126
+
127
+ **macOS / Linux**
128
+ ```bash
129
+ ./SAPCAR -xvf SAPEXE_###-########.SAR
130
+ ```
131
+
132
+ 3. After extraction, move the following files into the previously created `init` folder:
133
+
134
+ ```
135
+ R3trans
136
+ libicudata##.so
137
+ libicui18n##.so
138
+ libicuuc##.so
139
+ ```
140
+
141
+ 4. *(Optional)* If you want RFC functionality available in TRM, also move the following files into the `init` folder:
142
+
143
+ ```
144
+ startrfc
145
+ rfcexec
146
+ libsapnwrfc.so
147
+ libsapucum.so
148
+ ```
149
+
150
+ ## Pull docker image
151
+
152
+ Execute this command to pull the latest docker image
153
+
154
+ ```bash
155
+ docker pull --platform=linux/amd64 abaptrm/docker
156
+ ```
157
+
158
+ ## Initial Installation via Script
159
+
160
+ Once the `init` folder is populated and the `trm` script is ready, run the script from the directory where it is located.
161
+
162
+ **Windows**
163
+ ```bash
164
+ trm
165
+ ```
166
+
167
+ **macOS / Linux**
168
+ ```bash
169
+ ./trm
170
+ ```
171
+
172
+ The first execution performs the initial setup of the Docker environment.\
173
+ After the installation completes, you may move the script to a directory included in your system `PATH` so it can be executed from anywhere.
174
+
175
+ **Windows**
176
+ ```
177
+ C:\Windows\System32
178
+ ```
179
+
180
+ **macOS / Linux**
181
+ ```
182
+ /usr/local/bin
183
+ ```
184
+
185
+ After this step, you can simply run:
186
+
187
+ ```bash
188
+ trm
189
+ ```
190
+
191
+ from any directory.
192
+
193
+ ---
20
194
 
21
- - [Setup](/docs/setup.md)
22
- - [Publish and install](https://docs.trmregistry.com/#/examples/1_publish_and_install)
195
+ # Install via Npm
23
196
 
24
- ## Install
197
+ With [Node.js and npm](https://nodejs.org/en/download) installed, you can install [trm-client](https://www.npmjs.com/package/trm-client) via npm, as it is distributed as a Node.js package.
25
198
 
26
- First, make sure you have all the [requirements installed](/docs/setup.md).
199
+ ## TODO
27
200
 
28
- You can then install the CLI via npm:
201
+ <!-- END OF SETUP.MD -->
29
202
 
30
- `npm install trm-client -g`
203
+ ---
31
204
 
32
205
  # Contributing
33
206
 
package/changelog.txt CHANGED
@@ -8,6 +8,19 @@ Legend
8
8
  + : added
9
9
  - : removed
10
10
 
11
+ 2026-03-23 v7.7.0
12
+ -------------------
13
+ * pack command usage
14
+
15
+ 2026-03-11 v7.6.0
16
+ -------------------
17
+ * show subcommands in --help
18
+ + command cg3y
19
+ + command cg3z
20
+ * trm-core ^8.5.3
21
+ + TRM_DOCKERIZED env variable (for docker usage)
22
+ + clear-cache command
23
+
11
24
  2026-03-10 v7.5.1
12
25
  -------------------
13
26
  * dependency tree package objects counter
@@ -31,6 +31,8 @@ export declare abstract class AbstractCommand {
31
31
  private getLogger;
32
32
  private getInquirer;
33
33
  private parseCommandArgs;
34
+ validateOutputFileArg(argValue: string): void;
35
+ validateInputFileArg(argValue: string): void;
34
36
  protected onArgs(): void;
35
37
  protected onTrmDepMissing(dependency: string): boolean;
36
38
  protected onTrmDepVersionNotSatisfied(trmPackage: Core.TrmPackage): boolean;
@@ -56,6 +56,9 @@ const systemAlias_1 = require("../systemAlias");
56
56
  const chalk_1 = __importDefault(require("chalk"));
57
57
  const prompts_1 = require("./prompts");
58
58
  const fs_1 = require("fs");
59
+ const path_1 = require("path");
60
+ const constants_1 = __importDefault(require("constants"));
61
+ const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
59
62
  class AbstractCommand {
60
63
  constructor(program, name, aliases, subcommand) {
61
64
  this.name = name;
@@ -241,6 +244,62 @@ class AbstractCommand {
241
244
  }, {});
242
245
  return args;
243
246
  }
247
+ validateOutputFileArg(argValue) {
248
+ const resolvedPath = (0, path_1.resolve)(argValue);
249
+ if ((0, fs_1.existsSync)(resolvedPath)) {
250
+ const stats = (0, fs_1.statSync)(resolvedPath);
251
+ if (stats.isDirectory()) {
252
+ try {
253
+ (0, fs_1.accessSync)(resolvedPath, constants_1.default.W_OK);
254
+ }
255
+ catch (_a) {
256
+ throw new Error(`No write access to directory "${resolvedPath}"`);
257
+ }
258
+ return;
259
+ }
260
+ if (stats.isFile()) {
261
+ const dir = (0, path_1.dirname)(resolvedPath);
262
+ try {
263
+ (0, fs_1.accessSync)(dir, constants_1.default.W_OK);
264
+ }
265
+ catch (_b) {
266
+ throw new Error(`No write access to directory "${dir}"`);
267
+ }
268
+ const fileName = (0, path_1.basename)(resolvedPath);
269
+ const sanitizedFileName = (0, sanitize_filename_1.default)(fileName);
270
+ if (fileName !== sanitizedFileName) {
271
+ throw new Error(`Invalid filename "${fileName}"`);
272
+ }
273
+ return;
274
+ }
275
+ throw new Error(`Output path "${resolvedPath}" is neither a file nor a directory`);
276
+ }
277
+ const dir = (0, path_1.dirname)(resolvedPath);
278
+ const fileName = (0, path_1.basename)(resolvedPath);
279
+ const sanitizedFileName = (0, sanitize_filename_1.default)(fileName);
280
+ if (!(0, fs_1.existsSync)(dir)) {
281
+ throw new Error(`Parent directory does not exist "${dir}"`);
282
+ }
283
+ try {
284
+ (0, fs_1.accessSync)(dir, constants_1.default.W_OK);
285
+ }
286
+ catch (_c) {
287
+ throw new Error(`No write access to directory "${dir}"`);
288
+ }
289
+ if (fileName !== sanitizedFileName) {
290
+ throw new Error(`Invalid filename "${fileName}"`);
291
+ }
292
+ }
293
+ validateInputFileArg(argValue) {
294
+ const resolvedPath = (0, path_1.resolve)(argValue);
295
+ if (!(0, fs_1.existsSync)(resolvedPath)) {
296
+ throw new Error(`"${resolvedPath}" does not exist`);
297
+ }
298
+ const stats = (0, fs_1.statSync)(resolvedPath);
299
+ if (!stats.isFile()) {
300
+ throw new Error(`"${resolvedPath}" is not a file`);
301
+ }
302
+ }
244
303
  onArgs() {
245
304
  }
246
305
  onTrmDepMissing(dependency) {
@@ -318,18 +377,19 @@ class AbstractCommand {
318
377
  yield Commons.Plugin.call("client", "loadCommons", { commons: Commons });
319
378
  Commons.Inquirer.inquirer = this.getInquirer(InquirerType_1.InquirerType.CLI);
320
379
  Commons.Logger.logger = this.getLogger(this.args.logger, this.args.debug, this.args.loggerOutDir);
321
- if (this.registerOpts.requiresR3trans && process.platform === 'darwin') {
322
- Commons.Logger.info(`This command needs R3trans program dockerized in your OS.`);
380
+ const useDocker = utils_1.GlobalContext.getInstance().getSettings().r3transDocker;
381
+ if (this.registerOpts.requiresR3trans && useDocker) {
382
+ Commons.Logger.info(`This command needs R3trans program dockerized.`);
323
383
  Commons.Logger.loading(`Checking if docker is running...`);
324
384
  if (yield (0, utils_1.isDockerRunning)()) {
325
385
  const dockerName = utils_1.GlobalContext.getInstance().getSettings().r3transDockerName;
326
386
  Commons.Logger.info(`Docker "${dockerName || 'local/r3trans'}" will be used.`);
327
387
  }
328
388
  else {
329
- throw new Error(`Command needs R3trans dockerized, docker is not currently running.`);
389
+ throw new Error(`Command needs R3trans dockerized, docker engine is not currently running.`);
330
390
  }
331
391
  }
332
- if (process.platform !== 'win32' && process.platform !== 'darwin') {
392
+ if (process.platform !== 'win32' && process.platform !== 'darwin' && process.platform !== 'linux') {
333
393
  Commons.Logger.warning(`Running on untested OS "${process.platform}"! Some features aren't tested yet.`);
334
394
  }
335
395
  if (!this.registerOpts.noClientVersionCheck) {
@@ -0,0 +1,5 @@
1
+ import { AbstractCommand } from "../AbstractCommand";
2
+ export declare class Cg3y extends AbstractCommand {
3
+ protected init(): void;
4
+ protected handler(): Promise<void>;
5
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.Cg3y = void 0;
16
+ const path_1 = require("path");
17
+ const AbstractCommand_1 = require("../AbstractCommand");
18
+ const trm_core_1 = require("trm-core");
19
+ const trm_commons_1 = require("trm-commons");
20
+ const promises_1 = require("fs/promises");
21
+ const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
22
+ class Cg3y extends AbstractCommand_1.AbstractCommand {
23
+ init() {
24
+ this.registerOpts.requiresConnection = true;
25
+ this.registerOpts.requiresTrmDependencies = true;
26
+ this.command.description(`Download any released transport.`);
27
+ this.command.argument(`<transport>`, `Transport number.`);
28
+ this.command.argument(`[filename]`, `Name (or path) of the output file.`);
29
+ }
30
+ handler() {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ if (!this.args.filename) {
33
+ this.args.filename = (0, path_1.join)(process.cwd(), `${(0, sanitize_filename_1.default)(this.args.transport.toUpperCase())}.zip`);
34
+ }
35
+ const extension = (0, path_1.extname)(this.args.filename);
36
+ if (extension !== '.zip') {
37
+ this.args.filename = this.args.filename + '.zip';
38
+ }
39
+ this.validateOutputFileArg(this.args.filename);
40
+ const result = yield (0, trm_core_1.cg3y)({
41
+ trkorr: this.args.transport.toUpperCase()
42
+ });
43
+ trm_commons_1.Logger.loading(`Transport downloaded, writing data to disk...`);
44
+ yield (0, promises_1.writeFile)(this.args.filename, result.binaries);
45
+ trm_commons_1.Logger.success(`Transport available at "${this.args.filename}"`);
46
+ });
47
+ }
48
+ }
49
+ exports.Cg3y = Cg3y;
@@ -0,0 +1,5 @@
1
+ import { AbstractCommand } from "../AbstractCommand";
2
+ export declare class Cg3z extends AbstractCommand {
3
+ protected init(): void;
4
+ protected handler(): Promise<void>;
5
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Cg3z = void 0;
13
+ const trm_commons_1 = require("trm-commons");
14
+ const AbstractCommand_1 = require("../AbstractCommand");
15
+ const trm_core_1 = require("trm-core");
16
+ const utils_1 = require("../../utils");
17
+ const promises_1 = require("fs/promises");
18
+ const path_1 = require("path");
19
+ class Cg3z extends AbstractCommand_1.AbstractCommand {
20
+ init() {
21
+ this.registerOpts.requiresConnection = true;
22
+ this.registerOpts.requiresTrmDependencies = true;
23
+ this.registerOpts.requiresR3trans = true;
24
+ this.command.description(`Upload any released transport.`);
25
+ this.command.argument(`<filename>`, `Name (or path) of the file.`);
26
+ }
27
+ handler() {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ const extension = (0, path_1.extname)(this.args.filename);
30
+ var transportLayer;
31
+ try {
32
+ transportLayer = yield trm_core_1.SystemConnector.getDefaultTransportLayer();
33
+ }
34
+ catch (_a) { }
35
+ if (extension !== '.zip') {
36
+ this.args.filename = this.args.filename + '.zip';
37
+ }
38
+ this.validateInputFileArg(this.args.filename);
39
+ trm_commons_1.Logger.loading(`Reading file "${this.args.filename}"...`);
40
+ const binaries = yield (0, promises_1.readFile)(this.args.filename);
41
+ const result = yield (0, trm_core_1.cg3z)({
42
+ r3transOptions: {
43
+ tempDirPath: (0, utils_1.getTempFolder)(),
44
+ r3transDirPath: this.args.r3transPath,
45
+ useDocker: utils_1.GlobalContext.getInstance().getSettings().r3transDocker,
46
+ dockerOptions: {
47
+ name: utils_1.GlobalContext.getInstance().getSettings().r3transDockerName
48
+ }
49
+ },
50
+ binaries
51
+ });
52
+ trm_commons_1.Logger.success(`Uploaded ${trm_core_1.Transport.getTransportIcon()} ${result.trkorr}`);
53
+ trm_commons_1.Logger.info(`Transport is now available in transaction STMS, ${trm_core_1.SystemConnector.getDest()} queue`);
54
+ trm_commons_1.Logger.info(`-> Manually import into ${trm_core_1.SystemConnector.getDest()} via STMS in the appropriate client`);
55
+ trm_commons_1.Logger.info(`-> Manually change ${result.trkorr} workbench content origin system to ${trm_core_1.SystemConnector.getDest()} via SE03 if needed`);
56
+ trm_commons_1.Logger.info(`-> Manually change ${result.trkorr} SAP packages transport layer to ${transportLayer || 'default'} via SE80 if needed`);
57
+ });
58
+ }
59
+ }
60
+ exports.Cg3z = Cg3z;
@@ -0,0 +1,5 @@
1
+ import { AbstractCommand } from "../AbstractCommand";
2
+ export declare class ClearCache extends AbstractCommand {
3
+ protected init(): void;
4
+ protected handler(): Promise<void>;
5
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ClearCache = void 0;
13
+ const AbstractCommand_1 = require("../AbstractCommand");
14
+ const trm_commons_1 = require("trm-commons");
15
+ const utils_1 = require("../../utils");
16
+ class ClearCache extends AbstractCommand_1.AbstractCommand {
17
+ init() {
18
+ this.command.description(`Clear client cache.`);
19
+ }
20
+ handler() {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ utils_1.GlobalContext.getInstance().clearCache();
23
+ trm_commons_1.Logger.success(`Cache cleared`);
24
+ });
25
+ }
26
+ }
27
+ exports.ClearCache = ClearCache;
@@ -20,6 +20,7 @@ const utils_1 = require("../../utils");
20
20
  const execa_1 = require("execa");
21
21
  const node_os_1 = __importDefault(require("node:os"));
22
22
  const lockfile_1 = require("trm-core/dist/lockfile");
23
+ const node_path_1 = require("node:path");
23
24
  class Install extends AbstractCommand_1.AbstractCommand {
24
25
  init() {
25
26
  this.registerOpts.requiresConnection = true;
@@ -139,6 +140,11 @@ class Install extends AbstractCommand_1.AbstractCommand {
139
140
  }
140
141
  var registry;
141
142
  if (this.name === 'import') {
143
+ const extension = (0, node_path_1.extname)(this.args.filename);
144
+ if (extension !== '.trm') {
145
+ this.args.filename = this.args.filename + 'trm';
146
+ }
147
+ this.validateInputFileArg(this.args.filename);
142
148
  registry = new trm_core_1.FileSystem(this.args.filename);
143
149
  }
144
150
  else {
@@ -8,6 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.Publish = void 0;
13
16
  const trm_commons_1 = require("trm-commons");
@@ -15,15 +18,17 @@ const trm_core_1 = require("trm-core");
15
18
  const AbstractCommand_1 = require("../AbstractCommand");
16
19
  const utils_1 = require("../../utils");
17
20
  const semver_1 = require("semver");
21
+ const path_1 = require("path");
22
+ const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
18
23
  class Publish extends AbstractCommand_1.AbstractCommand {
19
24
  init() {
20
25
  this.registerOpts.requiresConnection = true;
21
26
  this.registerOpts.requiresTrmDependencies = true;
22
27
  if (this.name === 'pack') {
23
28
  this.command.description(`Export a package to local file.`);
24
- this.command.argument(`<filename>`, `Name (or path) of the file.`);
25
- this.command.option(`--package <package>`, `Name of the package`);
26
- this.command.option(`--version <version>`, `Version of the release`);
29
+ this.command.argument(`<package>`, `Name of the package`);
30
+ this.command.argument(`<version>`, `Version of the release`);
31
+ this.command.argument(`[filename]`, `Name (or path) of the output file.`);
27
32
  }
28
33
  else {
29
34
  this.registerOpts.requiresRegistry = true;
@@ -89,6 +94,14 @@ class Publish extends AbstractCommand_1.AbstractCommand {
89
94
  if (this.validateVersion(this.args.version) !== true) {
90
95
  throw new Error(this.validateVersion(this.args.version));
91
96
  }
97
+ if (!this.args.filename) {
98
+ this.args.filename = (0, path_1.join)(process.cwd(), `${(0, sanitize_filename_1.default)(this.args.package)}.trm`);
99
+ }
100
+ const extension = (0, path_1.extname)(this.args.filename);
101
+ if (extension !== '.trm') {
102
+ this.args.filename = this.args.filename + '.trm';
103
+ }
104
+ this.validateOutputFileArg(this.args.filename);
92
105
  registry = new trm_core_1.FileSystem(this.args.filename);
93
106
  }
94
107
  else {
@@ -16,4 +16,7 @@ export * from "./Content";
16
16
  export * from "./View";
17
17
  export * from "./Compare";
18
18
  export * from "./FindDependencies";
19
+ export * from "./Cg3y";
20
+ export * from "./Cg3z";
19
21
  export * from "./Settings";
22
+ export * from "./ClearCache";
@@ -32,4 +32,7 @@ __exportStar(require("./Content"), exports);
32
32
  __exportStar(require("./View"), exports);
33
33
  __exportStar(require("./Compare"), exports);
34
34
  __exportStar(require("./FindDependencies"), exports);
35
+ __exportStar(require("./Cg3y"), exports);
36
+ __exportStar(require("./Cg3z"), exports);
35
37
  __exportStar(require("./Settings"), exports);
38
+ __exportStar(require("./ClearCache"), exports);
package/dist/index.js CHANGED
@@ -20,8 +20,30 @@ program
20
20
  Full documentation available at https://docs.trmregistry.com/
21
21
  Public registry at https://trmregistry.com/
22
22
 
23
- © 2025 RegestaItalia https://regestaitalia.eu/`)
23
+ © 2023 RegestaItalia https://regestaitalia.eu/`)
24
24
  .version((0, utils_1.getClientVersion)());
25
+ program.configureHelp({
26
+ sortSubcommands: true,
27
+ visibleCommands: (cmd) => {
28
+ var commands = [];
29
+ cmd.commands.forEach(c => {
30
+ if (c.description()) {
31
+ commands.push(c);
32
+ }
33
+ c.commands.forEach(s => {
34
+ commands.push(s);
35
+ });
36
+ });
37
+ return commands;
38
+ },
39
+ subcommandTerm: (cmd) => {
40
+ var term = `${cmd.name()} ${cmd.usage()}`;
41
+ if (cmd.parent.name() !== program.name()) {
42
+ term = `${cmd.parent.name()} ${cmd.name()} ${cmd.usage()}`;
43
+ }
44
+ return term;
45
+ }
46
+ });
25
47
  new implementations_1.Ping(program, 'ping').register();
26
48
  new implementations_1.Info(program, 'info').register();
27
49
  new implementations_1.Registry(program, 'registry', null, 'add').register();
@@ -48,5 +70,8 @@ new implementations_1.Content(program, 'content', ['contents']).register();
48
70
  new implementations_1.View(program, 'view').register();
49
71
  new implementations_1.Compare(program, 'compare').register();
50
72
  new implementations_1.FindDependencies(program, 'find-dependencies').register();
73
+ new implementations_1.Cg3y(program, 'cg3y').register();
74
+ new implementations_1.Cg3z(program, 'cg3z').register();
51
75
  new implementations_1.Settings(program, 'settings').register();
76
+ new implementations_1.ClearCache(program, 'clear-cache').register();
52
77
  program.parse(process.argv);
@@ -7,6 +7,7 @@ export declare class GlobalContext {
7
7
  private _cache;
8
8
  private _connections;
9
9
  private _plugins;
10
+ private _dockerized;
10
11
  constructor();
11
12
  getSettings(): SettingsData;
12
13
  getGlobalNodeModules(): string;
@@ -23,6 +24,7 @@ export declare class GlobalContext {
23
24
  private getDefaultSettings;
24
25
  private setGlobalNpmPathInternal;
25
26
  private getSettingsInternal;
27
+ clearCache(): void;
26
28
  private getCacheInternal;
27
29
  private generateSettingsFile;
28
30
  private generateCacheFile;
@@ -71,6 +71,7 @@ class GlobalContext {
71
71
  this._pluginsLoaded = false;
72
72
  this._connections = [];
73
73
  this._plugins = [];
74
+ this._dockerized = process.env.TRM_DOCKERIZED === 'true';
74
75
  this._settings = this.getSettingsInternal();
75
76
  this._cache = this.getCacheInternal();
76
77
  if (typeof (this._settings.r3transDocker) !== 'boolean') {
@@ -172,13 +173,24 @@ class GlobalContext {
172
173
  };
173
174
  }
174
175
  setGlobalNpmPathInternal() {
176
+ var path;
177
+ if (this._dockerized) {
178
+ trm_commons_1.Logger.log(`TRM running in docker environment, ignoring cache and recalculating NPM global path`, true);
179
+ path = (0, trm_commons_1.getGlobalNodeModules)();
180
+ this._cache['globalNpmPath'] = {
181
+ ts: -1,
182
+ data: path
183
+ };
184
+ trm_commons_1.Logger.log(`Npm global modules path set to ${path}`, true);
185
+ return;
186
+ }
175
187
  const globalNpmPathCache = this._cache.globalNpmPath;
176
188
  const isValid = !!globalNpmPathCache && !!globalNpmPathCache.ts && (Date.now() - globalNpmPathCache.ts) < this.getSettings().npmGlobalPathCheckCache * 1000;
177
189
  if (isValid) {
178
190
  return globalNpmPathCache.data;
179
191
  }
180
192
  trm_commons_1.Logger.loading(`Cache expired, setting npm global modules path...`, true);
181
- const path = (0, trm_commons_1.getGlobalNodeModules)();
193
+ path = (0, trm_commons_1.getGlobalNodeModules)();
182
194
  trm_commons_1.Logger.log(`Npm global modules path set to ${path}`, true);
183
195
  this.setCache('globalNpmPath', path);
184
196
  }
@@ -210,11 +222,19 @@ class GlobalContext {
210
222
  this.generateSettingsFile(defaultSettings, filePath);
211
223
  return defaultSettings;
212
224
  }
225
+ clearCache() {
226
+ const filePath = this.getCacheFilePath();
227
+ this.generateCacheFile({}, filePath);
228
+ }
213
229
  getCacheInternal() {
214
230
  const filePath = this.getCacheFilePath();
215
231
  if (fs.existsSync(filePath)) {
216
232
  try {
217
- return JSON.parse(fs.readFileSync(filePath).toString());
233
+ var data = JSON.parse(fs.readFileSync(filePath).toString());
234
+ if (this._dockerized) {
235
+ delete data.globalNpmPath;
236
+ }
237
+ return data;
218
238
  }
219
239
  catch (e) { }
220
240
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trm-client",
3
- "version": "7.5.1",
3
+ "version": "7.7.0",
4
4
  "description": "TRM (Transport Request Manager) Client",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -45,9 +45,10 @@
45
45
  "i": "^0.3.7",
46
46
  "ini": "^4.1.1",
47
47
  "lodash": "^4.17.21",
48
+ "sanitize-filename": "^1.6.3",
48
49
  "semver": "^7.7.4",
49
50
  "trm-commons": "^3.5.1",
50
- "trm-core": "^8.5.1",
51
+ "trm-core": "^8.5.3",
51
52
  "trm-registry-types": "^2.1.0",
52
53
  "xml2js": "^0.6.2"
53
54
  },