From 526d52791b27c22a20992b8d870f5ce4f6d454b3 Mon Sep 17 00:00:00 2001 From: zgjimhaziri Date: Wed, 19 Aug 2026 10:37:05 +0200 Subject: [PATCH 1/2] SP-2314: List staging package nodes from config nodes list Includes-AI-Code: true Co-authored-by: Cursor --- docs/command-graph.html | 4 +- docs/user-guide/config-commands.md | 26 ++++-- .../configuration-management/api/node-api.ts | 18 ++++ .../configuration-management/module.ts | 6 +- .../configuration-management/node.service.ts | 6 +- .../config-node-list.spec.ts | 86 +++++++++++++++++++ 6 files changed, 132 insertions(+), 14 deletions(-) diff --git a/docs/command-graph.html b/docs/command-graph.html index 68fd253f..c245db19 100644 --- a/docs/command-graph.html +++ b/docs/command-graph.html @@ -389,8 +389,8 @@ description: "Archive a staging node in a package", options: ["-p, --profile ", "--packageKey ", "--nodeKey ", "--force (default: false)", "-h, --help"] }, { id: "config_nodes_list", label: "list", group: "command", path: "config nodes list", - description: "List nodes in a specific package version", - options: ["-p, --profile ", "--packageKey ", "--packageVersion ", "--limit ", "--offset ", "--withConfiguration (default: false)", "--json", "-h, --help"] }, + description: "List nodes in a package. Lists staging nodes by default.", + options: ["-p, --profile ", "--packageKey ", "--packageVersion (if omitted, staging state is used)", "--limit ", "--offset ", "--withConfiguration (default: false)", "--json", "-h, --help"] }, { id: "config_nodes_diff", label: "diff", group: "command", path: "config nodes diff", description: "Diff two versions of a specific node in a package", options: ["-p, --profile ", "--packageKey ", "--nodeKey ", "--baseVersion ", "--compareVersion (mutually exclusive with --file; exactly one required)", "-f, --file (mutually exclusive with --compareVersion; exactly one required)", "--json", "-h, --help"] }, diff --git a/docs/user-guide/config-commands.md b/docs/user-guide/config-commands.md index 1d2bb6be..524de15b 100644 --- a/docs/user-guide/config-commands.md +++ b/docs/user-guide/config-commands.md @@ -735,14 +735,16 @@ Use `--force` with care: dependants are not archived for you, and the package ma ## Listing Nodes -The **config nodes list** command allows you to retrieve all nodes within a specific package version. +The **config nodes list** command retrieves all nodes in a package. By default it lists nodes in the **staging (draft) version**. Pass `--packageVersion` to list a published package version instead. -### List Nodes in a Package Version +This command requires **edit permission** on the target package (see [Permissions](#permissions)). + +### List Staging Nodes -To list all nodes in a specific package version, use the following command: +To list all nodes in the staging version of a package, omit `--packageVersion`: ```bash -content-cli config nodes list --packageKey --packageVersion +content-cli config nodes list --packageKey ``` The command will display information for each node in the console as a JSON object: @@ -753,13 +755,22 @@ info: {"id":"node-id-456","key":"node-key-2","name":"My Second Node","type":"KNO ... ``` +### List Nodes in a Package Version + +To list all nodes in a specific package version, use the `--packageVersion` option: + +```bash +content-cli config nodes list --packageKey --packageVersion +``` + ### Pagination The response is paginated, and the page size can be controlled with the `--limit` and `--offset` options (defaults to 100 and 0 respectively). ```bash +content-cli config nodes list --packageKey my-package --limit 10 +content-cli config nodes list --packageKey my-package --limit 10 --offset 10 content-cli config nodes list --packageKey my-package --packageVersion 1.2.3 --limit 10 -content-cli config nodes list --packageKey my-package --packageVersion 1.2.3 --limit 10 --offset 10 ``` ### List Nodes with Configuration @@ -767,6 +778,7 @@ content-cli config nodes list --packageKey my-package --packageVersion 1.2.3 --l By default, the node configuration is not included in the response. To include each node's configuration, use the `--withConfiguration` flag: ```bash +content-cli config nodes list --packageKey --withConfiguration content-cli config nodes list --packageKey --packageVersion --withConfiguration ``` @@ -775,13 +787,13 @@ content-cli config nodes list --packageKey --packageVersion --packageVersion --json +content-cli config nodes list --packageKey --json ``` You can combine options: ```bash -content-cli config nodes list --packageKey --packageVersion --withConfiguration --json +content-cli config nodes list --packageKey --withConfiguration --json content-cli config nodes list --packageKey my-package --packageVersion 1.2.3 --limit 50 --offset 100 --json ``` diff --git a/src/commands/configuration-management/api/node-api.ts b/src/commands/configuration-management/api/node-api.ts index f6c9482b..ce47e7d1 100644 --- a/src/commands/configuration-management/api/node-api.ts +++ b/src/commands/configuration-management/api/node-api.ts @@ -64,6 +64,24 @@ export class NodeApi { }); } + public async findStagingNodesByPackage(packageKey: string, withConfiguration: boolean, limit: number, offset: number): Promise { + const queryParams = new URLSearchParams(); + queryParams.set("withConfiguration", withConfiguration.toString()); + + if (limit) { + queryParams.set("limit", limit.toString()); + } + if (offset) { + queryParams.set("offset", offset.toString()); + } + + return this.httpClient() + .get(`/pacman/api/core/staging/packages/${packageKey}/nodes?${queryParams.toString()}`) + .catch(e => { + throw new FatalError(`Problem fetching nodes from package ${packageKey}: ${e}`); + }); + } + public async findVersionedNodesByPackage(packageKey: string, version: string, withConfiguration: boolean, limit: number, offset: number): Promise { const queryParams = new URLSearchParams(); queryParams.set("version", version); diff --git a/src/commands/configuration-management/module.ts b/src/commands/configuration-management/module.ts index f332f463..e85e04e7 100644 --- a/src/commands/configuration-management/module.ts +++ b/src/commands/configuration-management/module.ts @@ -282,9 +282,9 @@ class Module extends IModule { .action(this.archiveNode); nodesCommand.command("list") - .description("List nodes in a specific package version") + .description("List nodes in a package. Lists staging nodes by default.") .requiredOption("--packageKey ", "Identifier of the package") - .requiredOption("--packageVersion ", "Version of the package") + .option("--packageVersion ", "Version of the package. If not sent, the staging state of the package will be used.") .option("--limit ", "Limit the number of results returned") .option("--offset ", "Offset for pagination") .option("--withConfiguration", "Include node configuration in the response", false) @@ -548,7 +548,7 @@ class Module extends IModule { } private async listNodes(context: Context, command: Command, options: OptionValues): Promise { - await new NodeService(context).listNodes(options.packageKey, options.packageVersion, options.limit, options.offset, options.withConfiguration, options.json); + await new NodeService(context).listNodes(options.packageKey, options.packageVersion ?? null, options.limit, options.offset, options.withConfiguration, options.json); } private async diffNode(context: Context, command: Command, options: OptionValues): Promise { diff --git a/src/commands/configuration-management/node.service.ts b/src/commands/configuration-management/node.service.ts index 5abbfcf9..32ab9a85 100644 --- a/src/commands/configuration-management/node.service.ts +++ b/src/commands/configuration-management/node.service.ts @@ -29,8 +29,10 @@ export class NodeService { } } - public async listNodes(packageKey: string, packageVersion: string, limit: number, offset: number, withConfiguration: boolean, jsonResponse: boolean): Promise { - const nodes: NodeTransport[] = await this.nodeApi.findVersionedNodesByPackage(packageKey, packageVersion, withConfiguration, limit, offset); + public async listNodes(packageKey: string, packageVersion: string | null, limit: number, offset: number, withConfiguration: boolean, jsonResponse: boolean): Promise { + const nodes: NodeTransport[] = packageVersion + ? await this.nodeApi.findVersionedNodesByPackage(packageKey, packageVersion, withConfiguration, limit, offset) + : await this.nodeApi.findStagingNodesByPackage(packageKey, withConfiguration, limit, offset); if (jsonResponse) { const filename = uuidv4() + ".json"; diff --git a/tests/commands/configuration-management/config-node-list.spec.ts b/tests/commands/configuration-management/config-node-list.spec.ts index 2b4501ef..a80338b8 100644 --- a/tests/commands/configuration-management/config-node-list.spec.ts +++ b/tests/commands/configuration-management/config-node-list.spec.ts @@ -290,4 +290,90 @@ describe("Node list", () => { const parentKeyMessages = loggingTestTransport.logMessages.filter(log => log.message.includes("Parent Node Key")); expect(parentKeyMessages.length).toBe(0); }); + + it("Should list staging nodes when package version is omitted", async () => { + const packageKey = "package-key"; + const limit = 10; + const offset = 0; + + const node1 = createNode("node-id-1", "node-key-1", "Node 1", "parent-key"); + const node2 = createNode("node-id-2", "node-key-2", "Node 2"); + const response: NodeTransport[] = [node1, node2]; + + mockAxiosGet( + `https://myTeam.celonis.cloud/pacman/api/core/staging/packages/${packageKey}/nodes?withConfiguration=false&limit=${limit}`, + response + ); + + await new NodeService(testContext).listNodes(packageKey, null, limit, offset, false, false); + + expect(loggingTestTransport.logMessages.length).toBe(2); + expect(loggingTestTransport.logMessages[0].message).toContain(JSON.stringify(node1)); + expect(loggingTestTransport.logMessages[1].message).toContain(JSON.stringify(node2)); + }); + + it("Should list staging nodes with configuration", async () => { + const packageKey = "package-key"; + const limit = 5; + const offset = 0; + + const node1: NodeTransport = { + ...createNode("node-id-1", "node-key-1", "Node 1"), + configuration: { + setting1: "value1", + } + }; + const response: NodeTransport[] = [node1]; + + mockAxiosGet( + `https://myTeam.celonis.cloud/pacman/api/core/staging/packages/${packageKey}/nodes?withConfiguration=true&limit=${limit}`, + response + ); + + await new NodeService(testContext).listNodes(packageKey, null, limit, offset, true, false); + + expect(loggingTestTransport.logMessages.length).toBe(1); + expect(loggingTestTransport.logMessages[0].message).toContain(`${JSON.stringify(node1.configuration)}`); + }); + + it("Should list staging nodes with pagination", async () => { + const packageKey = "package-key"; + const limit = 50; + const offset = 100; + + const node1 = createNode("node-id-101", "node-key-101", "Node 101"); + const response: NodeTransport[] = [node1]; + + mockAxiosGet( + `https://myTeam.celonis.cloud/pacman/api/core/staging/packages/${packageKey}/nodes?withConfiguration=false&limit=${limit}&offset=${offset}`, + response + ); + + await new NodeService(testContext).listNodes(packageKey, null, limit, offset, false, false); + + expect(loggingTestTransport.logMessages.length).toBe(1); + expect(loggingTestTransport.logMessages[0].message).toContain(JSON.stringify(node1)); + }); + + it("Should list staging nodes and return as JSON", async () => { + const packageKey = "package-key"; + const limit = 10; + const offset = 0; + + const node1 = createNode("node-id-1", "node-key-1", "Node 1"); + const node2 = createNode("node-id-2", "node-key-2", "Node 2"); + const response: NodeTransport[] = [node1, node2]; + + mockAxiosGet( + `https://myTeam.celonis.cloud/pacman/api/core/staging/packages/${packageKey}/nodes?withConfiguration=false&limit=${limit}`, + response + ); + + await new NodeService(testContext).listNodes(packageKey, null, limit, offset, false, true); + + const nodes = getJsonFromDownloadedFile() as NodeTransport[]; + + expect(nodes).toEqual([node1, node2]); + expect(nodes.length).toBe(2); + }); }); From fb13d3164a76665dfface84830c9c7027ec07772 Mon Sep 17 00:00:00 2001 From: zgjimhaziri Date: Wed, 19 Aug 2026 14:56:05 +0200 Subject: [PATCH 2/2] SP-2314: Use toHaveLength in staging node list tests Includes-AI-Code: true Co-authored-by: Cursor --- .../configuration-management/config-node-list.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/commands/configuration-management/config-node-list.spec.ts b/tests/commands/configuration-management/config-node-list.spec.ts index a80338b8..4e2668be 100644 --- a/tests/commands/configuration-management/config-node-list.spec.ts +++ b/tests/commands/configuration-management/config-node-list.spec.ts @@ -307,7 +307,7 @@ describe("Node list", () => { await new NodeService(testContext).listNodes(packageKey, null, limit, offset, false, false); - expect(loggingTestTransport.logMessages.length).toBe(2); + expect(loggingTestTransport.logMessages).toHaveLength(2); expect(loggingTestTransport.logMessages[0].message).toContain(JSON.stringify(node1)); expect(loggingTestTransport.logMessages[1].message).toContain(JSON.stringify(node2)); }); @@ -332,7 +332,7 @@ describe("Node list", () => { await new NodeService(testContext).listNodes(packageKey, null, limit, offset, true, false); - expect(loggingTestTransport.logMessages.length).toBe(1); + expect(loggingTestTransport.logMessages).toHaveLength(1); expect(loggingTestTransport.logMessages[0].message).toContain(`${JSON.stringify(node1.configuration)}`); }); @@ -351,7 +351,7 @@ describe("Node list", () => { await new NodeService(testContext).listNodes(packageKey, null, limit, offset, false, false); - expect(loggingTestTransport.logMessages.length).toBe(1); + expect(loggingTestTransport.logMessages).toHaveLength(1); expect(loggingTestTransport.logMessages[0].message).toContain(JSON.stringify(node1)); }); @@ -374,6 +374,6 @@ describe("Node list", () => { const nodes = getJsonFromDownloadedFile() as NodeTransport[]; expect(nodes).toEqual([node1, node2]); - expect(nodes.length).toBe(2); + expect(nodes).toHaveLength(2); }); });