@uipath/data-fabric-tool 1.195.0 → 1.197.0-preview.59

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.
@@ -518,6 +518,48 @@ describe("entities create", () => {
518
518
  );
519
519
  });
520
520
 
521
+ it("should preserve per-field referenceFolderKey on a cross-folder RELATIONSHIP", async () => {
522
+ const sdk = mockSdk();
523
+ vi.mocked(sdk.entities.create).mockResolvedValue("entity-xfolder-rel");
524
+ const fields = [
525
+ {
526
+ fieldName: "order",
527
+ type: "RELATIONSHIP",
528
+ referenceEntityId: "a1b2c3d4-0000-0000-0000-000000000010",
529
+ referenceFieldId: "f1000000-0000-0000-0000-000000000100",
530
+ referenceFolderKey: "f1000000-0000-0000-0000-000000000060",
531
+ },
532
+ ];
533
+ vi.mocked(readJsonInput).mockResolvedValue({ fields });
534
+
535
+ const program = buildProgram();
536
+ await program.parseAsync([
537
+ "node",
538
+ "test",
539
+ "entities",
540
+ "create",
541
+ "OrderLine",
542
+ "--body",
543
+ JSON.stringify({ fields }),
544
+ "--folder-key",
545
+ "f1000000-0000-0000-0000-000000000050",
546
+ ]);
547
+
548
+ expect(sdk.entities.create).toHaveBeenCalledWith(
549
+ "OrderLine",
550
+ expect.arrayContaining([
551
+ expect.objectContaining({
552
+ fieldName: "order",
553
+ type: "RELATIONSHIP",
554
+ referenceFolderKey: "f1000000-0000-0000-0000-000000000060",
555
+ }),
556
+ ]),
557
+ expect.objectContaining({
558
+ folderKey: "f1000000-0000-0000-0000-000000000050",
559
+ }),
560
+ );
561
+ });
562
+
521
563
  it("should error when no --body or --file provided", async () => {
522
564
  vi.mocked(readJsonInput).mockRejectedValue(
523
565
  new Error("Provide entity definition via --file or --body."),
@@ -763,6 +805,43 @@ describe("entities update", () => {
763
805
  );
764
806
  });
765
807
 
808
+ it("should preserve per-field referenceFolderKey when addFields includes a cross-folder RELATIONSHIP", async () => {
809
+ const sdk = mockSdk();
810
+ const addFields = [
811
+ {
812
+ fieldName: "order",
813
+ type: "RELATIONSHIP",
814
+ referenceEntityId: "a1b2c3d4-0000-0000-0000-000000000010",
815
+ referenceFieldId: "f1000000-0000-0000-0000-000000000100",
816
+ referenceFolderKey: "f1000000-0000-0000-0000-000000000060",
817
+ },
818
+ ];
819
+ vi.mocked(readJsonInput).mockResolvedValue({ addFields });
820
+
821
+ const program = buildProgram();
822
+ await program.parseAsync([
823
+ "node",
824
+ "test",
825
+ "entities",
826
+ "update",
827
+ "entity-id",
828
+ "--body",
829
+ JSON.stringify({ addFields }),
830
+ ]);
831
+
832
+ expect(sdk.entities.updateById).toHaveBeenCalledWith(
833
+ "entity-id",
834
+ expect.objectContaining({
835
+ addFields: expect.arrayContaining([
836
+ expect.objectContaining({
837
+ referenceFolderKey:
838
+ "f1000000-0000-0000-0000-000000000060",
839
+ }),
840
+ ]),
841
+ }),
842
+ );
843
+ });
844
+
766
845
  it("should update entity by adding a CHOICE_SET_MULTIPLE field with choiceSetId", async () => {
767
846
  const sdk = mockSdk();
768
847
  const addFields = [
@@ -1217,7 +1296,7 @@ describe("entities update", () => {
1217
1296
  expect(process.exitCode).toBe(1);
1218
1297
  });
1219
1298
 
1220
- it("should reject removeFields without --confirm", async () => {
1299
+ it("should reject removeFields without confirmation: exit 1, SDK not called", async () => {
1221
1300
  const sdk = mockSdk();
1222
1301
  vi.mocked(readJsonInput).mockResolvedValue({
1223
1302
  removeFields: [{ fieldName: "oldField" }],
@@ -1237,15 +1316,36 @@ describe("entities update", () => {
1237
1316
  ]);
1238
1317
 
1239
1318
  expect(sdk.entities.updateById).not.toHaveBeenCalled();
1240
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1241
- expect.objectContaining({
1242
- Result: "Failure",
1243
- Message: "Confirmation required for destructive operation",
1244
- }),
1245
- );
1319
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1246
1320
  expect(process.exitCode).toBe(1);
1247
1321
  });
1248
1322
 
1323
+ it("should accept removeFields with --yes (canonical flag)", async () => {
1324
+ const sdk = mockSdk();
1325
+ vi.mocked(readJsonInput).mockResolvedValue({
1326
+ removeFields: [{ fieldName: "oldField" }],
1327
+ });
1328
+
1329
+ const program = buildProgram();
1330
+ await program.parseAsync([
1331
+ "node",
1332
+ "test",
1333
+ "entities",
1334
+ "update",
1335
+ "entity-id",
1336
+ "--body",
1337
+ '{"removeFields":[{"fieldName":"oldField"}]}',
1338
+ "--yes",
1339
+ "--reason",
1340
+ "drop legacy",
1341
+ ]);
1342
+
1343
+ expect(sdk.entities.updateById).toHaveBeenCalled();
1344
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
1345
+ expect.objectContaining({ Result: "Success" }),
1346
+ );
1347
+ });
1348
+
1249
1349
  it("should reject removeFields without --reason", async () => {
1250
1350
  const sdk = mockSdk();
1251
1351
  vi.mocked(readJsonInput).mockResolvedValue({
@@ -1751,6 +1851,7 @@ describe("entities delete", () => {
1751
1851
 
1752
1852
  expect(sdk.entities.deleteById).toHaveBeenCalledWith(
1753
1853
  "entity-to-delete",
1854
+ undefined,
1754
1855
  );
1755
1856
  expect(OutputFormatter.success).toHaveBeenCalledWith(
1756
1857
  expect.objectContaining({
@@ -1764,7 +1865,7 @@ describe("entities delete", () => {
1764
1865
  );
1765
1866
  });
1766
1867
 
1767
- it("should error when --confirm is missing", async () => {
1868
+ it("should error when confirmation is missing: exit 1, SDK not called", async () => {
1768
1869
  const sdk = mockSdk();
1769
1870
 
1770
1871
  const program = buildProgram();
@@ -1779,15 +1880,34 @@ describe("entities delete", () => {
1779
1880
  ]);
1780
1881
 
1781
1882
  expect(sdk.entities.deleteById).not.toHaveBeenCalled();
1782
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1783
- expect.objectContaining({
1784
- Result: "Failure",
1785
- Message: "Confirmation required for destructive operation",
1786
- }),
1787
- );
1883
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1788
1884
  expect(process.exitCode).toBe(1);
1789
1885
  });
1790
1886
 
1887
+ it("should delete with --yes (canonical confirmation flag)", async () => {
1888
+ const sdk = mockSdk();
1889
+
1890
+ const program = buildProgram();
1891
+ await program.parseAsync([
1892
+ "node",
1893
+ "test",
1894
+ "entities",
1895
+ "delete",
1896
+ "entity-id",
1897
+ "--yes",
1898
+ "--reason",
1899
+ "cleanup",
1900
+ ]);
1901
+
1902
+ expect(sdk.entities.deleteById).toHaveBeenCalledWith(
1903
+ "entity-id",
1904
+ undefined,
1905
+ );
1906
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
1907
+ expect.objectContaining({ Result: "Success" }),
1908
+ );
1909
+ });
1910
+
1791
1911
  it("should error when --reason is missing", async () => {
1792
1912
  const sdk = mockSdk();
1793
1913
 
@@ -1883,3 +2003,171 @@ describe("entities delete", () => {
1883
2003
  expect(process.exitCode).toBe(1);
1884
2004
  });
1885
2005
  });
2006
+
2007
+ describe("entities --folder-key forwarding", () => {
2008
+ beforeEach(() => {
2009
+ vi.resetAllMocks();
2010
+ process.exitCode = undefined;
2011
+ });
2012
+
2013
+ it("should forward --folder-key to getById", async () => {
2014
+ const sdk = mockSdk();
2015
+ vi.mocked(sdk.entities.getById).mockResolvedValue({
2016
+ id: "ent-1",
2017
+ fields: [],
2018
+ } as never);
2019
+
2020
+ const program = buildProgram();
2021
+ await program.parseAsync([
2022
+ "node",
2023
+ "test",
2024
+ "entities",
2025
+ "get",
2026
+ "ent-1",
2027
+ "--folder-key",
2028
+ "folder-guid-1",
2029
+ ]);
2030
+
2031
+ expect(sdk.entities.getById).toHaveBeenCalledWith("ent-1", {
2032
+ folderKey: "folder-guid-1",
2033
+ });
2034
+ });
2035
+
2036
+ it("should forward --folder-key into create options", async () => {
2037
+ const sdk = mockSdk();
2038
+ vi.mocked(sdk.entities.create).mockResolvedValue("new-entity-id");
2039
+ vi.mocked(readJsonInput).mockResolvedValue({
2040
+ fields: [{ fieldName: "title", type: "STRING" }],
2041
+ });
2042
+
2043
+ const program = buildProgram();
2044
+ await program.parseAsync([
2045
+ "node",
2046
+ "test",
2047
+ "entities",
2048
+ "create",
2049
+ "MyEntity",
2050
+ "--body",
2051
+ '{"fields":[{"fieldName":"title","type":"STRING"}]}',
2052
+ "--folder-key",
2053
+ "folder-guid-2",
2054
+ ]);
2055
+
2056
+ expect(sdk.entities.create).toHaveBeenCalledWith(
2057
+ "MyEntity",
2058
+ [{ fieldName: "title", type: "STRING" }],
2059
+ expect.objectContaining({ folderKey: "folder-guid-2" }),
2060
+ );
2061
+ });
2062
+
2063
+ it("should forward --folder-key into updateById options", async () => {
2064
+ const sdk = mockSdk();
2065
+ vi.mocked(readJsonInput).mockResolvedValue({
2066
+ displayName: "Renamed",
2067
+ });
2068
+
2069
+ const program = buildProgram();
2070
+ await program.parseAsync([
2071
+ "node",
2072
+ "test",
2073
+ "entities",
2074
+ "update",
2075
+ "ent-1",
2076
+ "--body",
2077
+ '{"displayName":"Renamed"}',
2078
+ "--folder-key",
2079
+ "folder-guid-3",
2080
+ ]);
2081
+
2082
+ expect(sdk.entities.updateById).toHaveBeenCalledWith(
2083
+ "ent-1",
2084
+ expect.objectContaining({
2085
+ displayName: "Renamed",
2086
+ folderKey: "folder-guid-3",
2087
+ }),
2088
+ );
2089
+ });
2090
+
2091
+ it("should forward --folder-key to deleteById", async () => {
2092
+ const sdk = mockSdk();
2093
+
2094
+ const program = buildProgram();
2095
+ await program.parseAsync([
2096
+ "node",
2097
+ "test",
2098
+ "entities",
2099
+ "delete",
2100
+ "ent-1",
2101
+ "--confirm",
2102
+ "--reason",
2103
+ "cleanup",
2104
+ "--folder-key",
2105
+ "folder-guid-4",
2106
+ ]);
2107
+
2108
+ expect(sdk.entities.deleteById).toHaveBeenCalledWith("ent-1", {
2109
+ folderKey: "folder-guid-4",
2110
+ });
2111
+ });
2112
+ });
2113
+
2114
+ describe("entities list --include-folders", () => {
2115
+ beforeEach(() => {
2116
+ vi.resetAllMocks();
2117
+ process.exitCode = undefined;
2118
+ });
2119
+
2120
+ it("should call getAll with no options when neither --folder-key nor --include-folders is passed", async () => {
2121
+ const sdk = mockSdk();
2122
+ const program = buildProgram();
2123
+ await program.parseAsync(["node", "test", "entities", "list"]);
2124
+ expect(sdk.entities.getAll).toHaveBeenCalledWith(undefined);
2125
+ });
2126
+
2127
+ it("should forward --include-folders as includeFolderEntities: true", async () => {
2128
+ const sdk = mockSdk();
2129
+ const program = buildProgram();
2130
+ await program.parseAsync([
2131
+ "node",
2132
+ "test",
2133
+ "entities",
2134
+ "list",
2135
+ "--include-folders",
2136
+ ]);
2137
+ expect(sdk.entities.getAll).toHaveBeenCalledWith({
2138
+ includeFolderEntities: true,
2139
+ });
2140
+ });
2141
+
2142
+ it("should forward --folder-key as folderKey to getAll", async () => {
2143
+ const sdk = mockSdk();
2144
+ const program = buildProgram();
2145
+ await program.parseAsync([
2146
+ "node",
2147
+ "test",
2148
+ "entities",
2149
+ "list",
2150
+ "--folder-key",
2151
+ "folder-guid-1",
2152
+ ]);
2153
+ expect(sdk.entities.getAll).toHaveBeenCalledWith({
2154
+ folderKey: "folder-guid-1",
2155
+ });
2156
+ });
2157
+
2158
+ it("should reject --folder-key combined with --include-folders", async () => {
2159
+ const sdk = mockSdk();
2160
+ const program = buildProgram();
2161
+ await program.parseAsync([
2162
+ "node",
2163
+ "test",
2164
+ "entities",
2165
+ "list",
2166
+ "--folder-key",
2167
+ "folder-guid-1",
2168
+ "--include-folders",
2169
+ ]);
2170
+ expect(sdk.entities.getAll).not.toHaveBeenCalled();
2171
+ expect(process.exitCode).toBe(1);
2172
+ });
2173
+ });
@@ -9,13 +9,14 @@ import {
9
9
  } from "@uipath/common";
10
10
  import type {
11
11
  EntityCreateFieldOptions,
12
+ EntityGetAllOptions,
12
13
  EntityServiceModel,
13
14
  EntityUpdateByIdOptions,
14
15
  ExternalSourceFields,
15
16
  RawEntityGetResponse,
16
17
  } from "@uipath/uipath-typescript";
17
18
  import { EntityFieldDataType } from "@uipath/uipath-typescript";
18
- import type { Command } from "commander";
19
+ import { type Command, Option } from "commander";
19
20
  import { readJsonInput } from "../utils/input";
20
21
  import { fail, requireDestructiveConfirmation } from "../utils/output";
21
22
  import { connectOrFail } from "../utils/sdk-client";
@@ -23,35 +24,45 @@ import { connectOrFail } from "../utils/sdk-client";
23
24
  interface ListOptions {
24
25
  tenant?: string;
25
26
  nativeOnly?: boolean;
27
+ folderKey?: string;
28
+ includeFolders?: boolean;
26
29
  }
27
30
 
28
31
  interface GetOptions {
29
32
  tenant?: string;
33
+ folderKey?: string;
30
34
  }
31
35
 
32
36
  interface CreateOptions {
33
37
  tenant?: string;
34
38
  file?: string;
35
39
  body?: string;
40
+ folderKey?: string;
36
41
  }
37
42
 
38
43
  interface UpdateEntityOptions {
39
44
  tenant?: string;
40
45
  file?: string;
41
46
  body?: string;
47
+ yes?: boolean;
42
48
  confirm?: boolean;
43
49
  reason?: string;
50
+ folderKey?: string;
44
51
  }
45
52
 
46
53
  interface DeleteOptions {
47
54
  tenant?: string;
55
+ yes?: boolean;
48
56
  confirm?: boolean;
49
57
  reason?: string;
58
+ folderKey?: string;
50
59
  }
51
60
 
52
61
  const ENTITIES_LIST_EXAMPLES: CommandExample[] = [
53
62
  {
54
- Description: "List Data Fabric entities.",
63
+ Description:
64
+ "List Data Fabric entities. Each entity includes the 'folderId' it lives in — pass that as '--folder-key' on follow-up commands targeting folder-scoped entities. " +
65
+ "Scope modes: omit both flags to see only tenant-level entities (the default); pass '--folder-key <uuid>' to see only that folder's entities; pass '--include-folders' to see tenant + folder entities together. '--folder-key' and '--include-folders' are mutually exclusive.",
55
66
  Command: "uip df entities list --native-only",
56
67
  Output: {
57
68
  Code: "EntityList",
@@ -62,6 +73,7 @@ const ENTITIES_LIST_EXAMPLES: CommandExample[] = [
62
73
  displayName: "Invoice",
63
74
  entityType: "Standard",
64
75
  description: "Invoice records",
76
+ folderId: "f1000000-0000-0000-0000-000000000001",
65
77
  isRbacEnabled: false,
66
78
  fields: [
67
79
  {
@@ -144,6 +156,19 @@ const ENTITIES_CREATE_EXAMPLES: CommandExample[] = [
144
156
  Data: { ID: "a1b2c3d4-0000-0000-0000-000000000004" },
145
157
  },
146
158
  },
159
+ {
160
+ Description:
161
+ "Create a folder-scoped entity with cross-folder references. " +
162
+ "Pass '--folder-key' to place the new entity in a folder. " +
163
+ "Per-field 'referenceFolderKey' points a RELATIONSHIP, FILE, or CHOICE_SET_* field at a target that lives in a different folder (or at the tenant level when omitted). " +
164
+ "Get target entity/field IDs from 'df entities list --folder-key <key>' and 'df entities get <id> --folder-key <key>'; get choice-set IDs from 'df choice-sets list --folder-key <key>' (omit '--folder-key' for tenant-level choice sets).",
165
+ Command:
166
+ 'uip df entities create OrderLine --folder-key f1000000-0000-0000-0000-000000000050 --body \'{"displayName":"Order Line","fields":[{"fieldName":"order","type":"RELATIONSHIP","referenceEntityId":"a1b2c3d4-0000-0000-0000-000000000010","referenceFieldId":"f1000000-0000-0000-0000-000000000100","referenceFolderKey":"f1000000-0000-0000-0000-000000000060","isRequired":true},{"fieldName":"userType","type":"CHOICE_SET_SINGLE","choiceSetId":"c1d2e3f4-0000-0000-0000-000000000077"}]}\'',
167
+ Output: {
168
+ Code: "EntityCreated",
169
+ Data: { ID: "a1b2c3d4-0000-0000-0000-000000000005" },
170
+ },
171
+ },
147
172
  ];
148
173
 
149
174
  const VALID_FIELD_TYPES = new Set(Object.values(EntityFieldDataType));
@@ -193,12 +218,43 @@ export const registerEntitiesCommand = (program: Command) => {
193
218
  "--native-only",
194
219
  "Show only native entities (exclude federated entities with external connections)",
195
220
  )
221
+ .option(
222
+ "--folder-key <key>",
223
+ "Folder key (GUID) to scope the listing to a specific folder",
224
+ )
225
+ .option(
226
+ "--include-folders",
227
+ "List tenant-level entities together with entities from every folder you can see. Mutually exclusive with --folder-key.",
228
+ )
196
229
  .examples(ENTITIES_LIST_EXAMPLES)
197
230
  .trackedAction(processContext, async (options: ListOptions) => {
231
+ if (
232
+ options.folderKey !== undefined &&
233
+ options.includeFolders === true
234
+ ) {
235
+ return fail(
236
+ "--folder-key and --include-folders are mutually exclusive",
237
+ "Use --folder-key to list a single folder, or --include-folders to list tenant + folder entities together.",
238
+ );
239
+ }
240
+
198
241
  const sdk = await connectOrFail(options.tenant);
199
242
  if (!sdk) return;
200
243
 
201
- const [listError, result] = await catchError(sdk.entities.getAll());
244
+ const listOpts: EntityGetAllOptions = {
245
+ ...(options.folderKey !== undefined && {
246
+ folderKey: options.folderKey,
247
+ }),
248
+ ...(options.includeFolders === true && {
249
+ includeFolderEntities: true,
250
+ }),
251
+ };
252
+
253
+ const [listError, result] = await catchError(
254
+ sdk.entities.getAll(
255
+ Object.keys(listOpts).length > 0 ? listOpts : undefined,
256
+ ),
257
+ );
202
258
 
203
259
  if (listError) {
204
260
  return fail(
@@ -229,6 +285,10 @@ export const registerEntitiesCommand = (program: Command) => {
229
285
  .addOption(
230
286
  createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>"),
231
287
  )
288
+ .option(
289
+ "--folder-key <key>",
290
+ "Folder key (GUID) of the folder containing the entity (for folder-scoped entities)",
291
+ )
232
292
  .examples(ENTITIES_GET_EXAMPLES)
233
293
  .trackedAction(
234
294
  processContext,
@@ -237,7 +297,12 @@ export const registerEntitiesCommand = (program: Command) => {
237
297
  if (!sdk) return;
238
298
 
239
299
  const [getError, entity] = await catchError(
240
- sdk.entities.getById(id),
300
+ sdk.entities.getById(
301
+ id,
302
+ options.folderKey !== undefined
303
+ ? { folderKey: options.folderKey }
304
+ : undefined,
305
+ ),
241
306
  );
242
307
 
243
308
  if (getError) {
@@ -279,6 +344,10 @@ export const registerEntitiesCommand = (program: Command) => {
279
344
  "Path to JSON file with entity definition (fields array required; displayName, description, isRbacEnabled optional)",
280
345
  )
281
346
  .option("--body <json>", "Inline JSON entity definition")
347
+ .option(
348
+ "--folder-key <key>",
349
+ "Folder key (GUID) of the target folder (for folder-scoped entities)",
350
+ )
282
351
  .examples(ENTITIES_CREATE_EXAMPLES)
283
352
  .trackedAction(
284
353
  processContext,
@@ -351,6 +420,9 @@ export const registerEntitiesCommand = (program: Command) => {
351
420
  ...(definition.isRbacEnabled !== undefined && {
352
421
  isRbacEnabled: definition.isRbacEnabled as boolean,
353
422
  }),
423
+ ...(options.folderKey !== undefined && {
424
+ folderKey: options.folderKey,
425
+ }),
354
426
  };
355
427
 
356
428
  const entityService: EntityServiceModel = sdk.entities;
@@ -390,15 +462,25 @@ export const registerEntitiesCommand = (program: Command) => {
390
462
  "-f, --file <path>",
391
463
  "Path to JSON file with update options (addFields, updateFields, removeFields, displayName, description, isRbacEnabled)",
392
464
  )
393
- .option("--body <json>", "Inline JSON update options")
394
465
  .option(
395
- "--confirm",
466
+ "--body <json>",
467
+ "Inline JSON update options (use `-` to read from stdin)",
468
+ )
469
+ .option(
470
+ "-y, --yes",
396
471
  "Required when 'removeFields' is non-empty — acknowledges the field deletion is irreversible",
397
472
  )
473
+ .addOption(
474
+ new Option("--confirm", "Deprecated alias for --yes").hideHelp(),
475
+ )
398
476
  .option(
399
477
  "--reason <reason>",
400
478
  "Required when 'removeFields' is non-empty — echoed back in the response so the caller can log it",
401
479
  )
480
+ .option(
481
+ "--folder-key <key>",
482
+ "Folder key (GUID) of the folder containing the entity (for folder-scoped entities)",
483
+ )
402
484
  .trackedAction(
403
485
  processContext,
404
486
  async (id: string, options: UpdateEntityOptions) => {
@@ -482,6 +564,7 @@ export const registerEntitiesCommand = (program: Command) => {
482
564
 
483
565
  const reason = requireDestructiveConfirmation(
484
566
  options,
567
+ `remove fields from entity '${id}'`,
485
568
  'Pass --reason "<text>" to record why fields are being removed.',
486
569
  );
487
570
  if (reason === null) return;
@@ -561,8 +644,14 @@ export const registerEntitiesCommand = (program: Command) => {
561
644
  if (!sdk) return;
562
645
 
563
646
  const entityService: EntityServiceModel = sdk.entities;
647
+ const updatePayload: EntityUpdateByIdOptions = {
648
+ ...pickKnownUpdateKeys(input),
649
+ ...(options.folderKey !== undefined && {
650
+ folderKey: options.folderKey,
651
+ }),
652
+ };
564
653
  const [updateError] = await catchError(
565
- entityService.updateById(id, pickKnownUpdateKeys(input)),
654
+ entityService.updateById(id, updatePayload),
566
655
  );
567
656
 
568
657
  if (updateError) {
@@ -593,17 +682,25 @@ export const registerEntitiesCommand = (program: Command) => {
593
682
  .addOption(
594
683
  createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>"),
595
684
  )
596
- .option("--confirm", "Acknowledge this is an irreversible operation")
685
+ .option("-y, --yes", "Acknowledge this is an irreversible operation")
686
+ .addOption(
687
+ new Option("--confirm", "Deprecated alias for --yes").hideHelp(),
688
+ )
597
689
  .option(
598
690
  "--reason <reason>",
599
691
  "Reason for the deletion — echoed back in the response so the caller can log it",
600
692
  )
693
+ .option(
694
+ "--folder-key <key>",
695
+ "Folder key (GUID) of the folder containing the entity (for folder-scoped entities)",
696
+ )
601
697
  .examples(ENTITIES_DELETE_EXAMPLES)
602
698
  .trackedAction(
603
699
  processContext,
604
700
  async (id: string, options: DeleteOptions) => {
605
701
  const reason = requireDestructiveConfirmation(
606
702
  options,
703
+ `delete entity '${id}'`,
607
704
  'Pass --reason "<text>" to record why the entity is being deleted.',
608
705
  );
609
706
  if (reason === null) return;
@@ -613,7 +710,12 @@ export const registerEntitiesCommand = (program: Command) => {
613
710
 
614
711
  const entityService: EntityServiceModel = sdk.entities;
615
712
  const [deleteError] = await catchError(
616
- entityService.deleteById(id),
713
+ entityService.deleteById(
714
+ id,
715
+ options.folderKey !== undefined
716
+ ? { folderKey: options.folderKey }
717
+ : undefined,
718
+ ),
617
719
  );
618
720
 
619
721
  if (deleteError) {