@uipath/data-fabric-tool 1.1.0 → 1.196.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.
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
3
3
 
4
4
  vi.mock("../utils/sdk-client", () => ({
5
5
  createDataFabricClient: vi.fn(),
6
+ connectOrFail: vi.fn(),
6
7
  }));
7
8
 
8
9
  vi.mock("@uipath/common", async (importOriginal) => {
@@ -23,7 +24,7 @@ vi.mock("@uipath/filesystem", () => ({
23
24
  }));
24
25
 
25
26
  import { OutputFormatter } from "@uipath/common";
26
- import { createDataFabricClient } from "../utils/sdk-client";
27
+ import { connectOrFail } from "../utils/sdk-client";
27
28
  import { registerRecordsCommand } from "./records";
28
29
 
29
30
  function buildProgram(): Command {
@@ -66,7 +67,7 @@ function mockSdk(overrides: Record<string, unknown> = {}) {
66
67
  ...overrides,
67
68
  },
68
69
  };
69
- vi.mocked(createDataFabricClient).mockResolvedValue(sdk as never);
70
+ vi.mocked(connectOrFail).mockResolvedValue(sdk as never);
70
71
  return sdk;
71
72
  }
72
73
 
@@ -83,13 +84,14 @@ describe("records list", () => {
83
84
  expect(cmd?.commands.map((c) => c.name())).toContain("list");
84
85
  });
85
86
 
86
- it("should list records successfully", async () => {
87
+ it("should list records successfully (raw SDK shape)", async () => {
87
88
  const sdk = mockSdk();
88
- vi.mocked(sdk.entities.getAllRecords).mockResolvedValue({
89
+ const rawResult = {
89
90
  items: [{ Id: "rec-1", name: "test" }],
90
91
  totalCount: 1,
91
92
  hasNextPage: false,
92
- });
93
+ };
94
+ vi.mocked(sdk.entities.getAllRecords).mockResolvedValue(rawResult);
93
95
 
94
96
  const program = buildProgram();
95
97
  await program.parseAsync([
@@ -107,22 +109,20 @@ describe("records list", () => {
107
109
  expect.objectContaining({
108
110
  Result: "Success",
109
111
  Code: "RecordList",
110
- Data: expect.objectContaining({
111
- TotalCount: 1,
112
- HasNextPage: false,
113
- }),
112
+ Data: rawResult,
114
113
  }),
115
114
  );
116
115
  });
117
116
 
118
- it("should pass cursor to SDK and include NextCursor in output", async () => {
117
+ it("should pass cursor to SDK and return the raw paginated response", async () => {
119
118
  const sdk = mockSdk();
120
- vi.mocked(sdk.entities.getAllRecords).mockResolvedValue({
119
+ const rawResult = {
121
120
  items: [{ Id: "rec-2" }],
122
121
  totalCount: 100,
123
122
  hasNextPage: true,
124
- nextCursor: "cursor-abc",
125
- });
123
+ nextCursor: { value: "cursor-abc" },
124
+ };
125
+ vi.mocked(sdk.entities.getAllRecords).mockResolvedValue(rawResult);
126
126
 
127
127
  const program = buildProgram();
128
128
  await program.parseAsync([
@@ -141,16 +141,15 @@ describe("records list", () => {
141
141
  });
142
142
  expect(OutputFormatter.success).toHaveBeenCalledWith(
143
143
  expect.objectContaining({
144
- Data: expect.objectContaining({
145
- HasNextPage: true,
146
- NextCursor: "cursor-abc",
147
- }),
144
+ Data: rawResult,
148
145
  }),
149
146
  );
150
147
  });
151
148
 
152
- it("should return empty list when no records exist", async () => {
153
- mockSdk();
149
+ it("should return empty list when no records exist (raw SDK shape)", async () => {
150
+ const sdk = mockSdk();
151
+ const rawResult = { items: [], totalCount: 0 };
152
+ vi.mocked(sdk.entities.getAllRecords).mockResolvedValue(rawResult);
154
153
 
155
154
  const program = buildProgram();
156
155
  await program.parseAsync([
@@ -165,7 +164,7 @@ describe("records list", () => {
165
164
  expect.objectContaining({
166
165
  Result: "Success",
167
166
  Code: "RecordList",
168
- Data: expect.objectContaining({ TotalCount: 0, Records: [] }),
167
+ Data: rawResult,
169
168
  }),
170
169
  );
171
170
  expect(process.exitCode).not.toBe(1);
@@ -361,10 +360,9 @@ describe("records list client error", () => {
361
360
  process.exitCode = undefined;
362
361
  });
363
362
 
364
- it("should error when SDK connection fails on list", async () => {
365
- vi.mocked(createDataFabricClient).mockRejectedValue(
366
- new Error("Not logged in"),
367
- );
363
+ it("should bail when SDK connection fails on list", async () => {
364
+ const sdk = mockSdk();
365
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
368
366
  const program = buildProgram();
369
367
  await program.parseAsync([
370
368
  "node",
@@ -373,20 +371,14 @@ describe("records list client error", () => {
373
371
  "list",
374
372
  "entity-id",
375
373
  ]);
376
- expect(OutputFormatter.error).toHaveBeenCalledWith(
377
- expect.objectContaining({
378
- Result: "Failure",
379
- Message: "Error connecting to Data Fabric",
380
- }),
381
- );
382
- expect(process.exitCode).toBe(1);
374
+ expect(sdk.entities.getAllRecords).not.toHaveBeenCalled();
375
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
383
376
  });
384
377
 
385
- it("should handle list result without items/totalCount (uses defaults)", async () => {
378
+ it("should pass through the raw list result verbatim", async () => {
379
+ const rawResult = { items: [], hasNextPage: false };
386
380
  const sdk = mockSdk({
387
- getAllRecords: vi
388
- .fn()
389
- .mockResolvedValue({ items: [], hasNextPage: false }),
381
+ getAllRecords: vi.fn().mockResolvedValue(rawResult),
390
382
  });
391
383
  const program = buildProgram();
392
384
  await program.parseAsync([
@@ -399,11 +391,7 @@ describe("records list client error", () => {
399
391
  expect(sdk.entities.getAllRecords).toHaveBeenCalled();
400
392
  expect(OutputFormatter.success).toHaveBeenCalledWith(
401
393
  expect.objectContaining({
402
- Data: expect.objectContaining({
403
- TotalCount: 0,
404
- Records: [],
405
- HasNextPage: false,
406
- }),
394
+ Data: rawResult,
407
395
  }),
408
396
  );
409
397
  });
@@ -496,10 +484,9 @@ describe("records get client error", () => {
496
484
  process.exitCode = undefined;
497
485
  });
498
486
 
499
- it("should error when SDK connection fails on get", async () => {
500
- vi.mocked(createDataFabricClient).mockRejectedValue(
501
- new Error("Not logged in"),
502
- );
487
+ it("should bail when SDK connection fails on get", async () => {
488
+ const sdk = mockSdk();
489
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
503
490
  const program = buildProgram();
504
491
  await program.parseAsync([
505
492
  "node",
@@ -509,13 +496,8 @@ describe("records get client error", () => {
509
496
  "entity-id",
510
497
  "rec-1",
511
498
  ]);
512
- expect(OutputFormatter.error).toHaveBeenCalledWith(
513
- expect.objectContaining({
514
- Result: "Failure",
515
- Message: "Error connecting to Data Fabric",
516
- }),
517
- );
518
- expect(process.exitCode).toBe(1);
499
+ expect(sdk.entities.getRecordById).not.toHaveBeenCalled();
500
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
519
501
  });
520
502
  });
521
503
 
@@ -630,10 +612,9 @@ describe("records insert", () => {
630
612
  expect(process.exitCode).toBe(1);
631
613
  });
632
614
 
633
- it("should error when SDK connection fails on insert", async () => {
634
- vi.mocked(createDataFabricClient).mockRejectedValue(
635
- new Error("Not logged in"),
636
- );
615
+ it("should bail when SDK connection fails on insert", async () => {
616
+ const sdk = mockSdk();
617
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
637
618
  const program = buildProgram();
638
619
  await program.parseAsync([
639
620
  "node",
@@ -644,13 +625,8 @@ describe("records insert", () => {
644
625
  "--body",
645
626
  '{"amount":100}',
646
627
  ]);
647
- expect(OutputFormatter.error).toHaveBeenCalledWith(
648
- expect.objectContaining({
649
- Result: "Failure",
650
- Message: "Error connecting to Data Fabric",
651
- }),
652
- );
653
- expect(process.exitCode).toBe(1);
628
+ expect(sdk.entities.insertRecordById).not.toHaveBeenCalled();
629
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
654
630
  });
655
631
 
656
632
  it("should handle batch insert result without successRecords/failureRecords", async () => {
@@ -977,10 +953,9 @@ describe("records update client/batch errors", () => {
977
953
  process.exitCode = undefined;
978
954
  });
979
955
 
980
- it("should error when SDK connection fails on update", async () => {
981
- vi.mocked(createDataFabricClient).mockRejectedValue(
982
- new Error("Not logged in"),
983
- );
956
+ it("should bail when SDK connection fails on update", async () => {
957
+ const sdk = mockSdk();
958
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
984
959
  const program = buildProgram();
985
960
  await program.parseAsync([
986
961
  "node",
@@ -991,13 +966,8 @@ describe("records update client/batch errors", () => {
991
966
  "--body",
992
967
  '{"Id":"rec-1"}',
993
968
  ]);
994
- expect(OutputFormatter.error).toHaveBeenCalledWith(
995
- expect.objectContaining({
996
- Result: "Failure",
997
- Message: "Error connecting to Data Fabric",
998
- }),
999
- );
1000
- expect(process.exitCode).toBe(1);
969
+ expect(sdk.entities.updateRecordById).not.toHaveBeenCalled();
970
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1001
971
  });
1002
972
 
1003
973
  it("should handle batch update result without successRecords/failureRecords", async () => {
@@ -1097,6 +1067,9 @@ describe("records delete", () => {
1097
1067
  "entity-id",
1098
1068
  "rec-1",
1099
1069
  "rec-2",
1070
+ "--yes",
1071
+ "--reason",
1072
+ "test cleanup",
1100
1073
  ]);
1101
1074
 
1102
1075
  expect(sdk.entities.deleteRecordsById).toHaveBeenCalledWith(
@@ -1123,6 +1096,9 @@ describe("records delete", () => {
1123
1096
  "delete",
1124
1097
  "entity-id",
1125
1098
  "rec-1",
1099
+ "--yes",
1100
+ "--reason",
1101
+ "test cleanup",
1126
1102
  ]);
1127
1103
  expect(sdk.entities.deleteRecordsById).toHaveBeenCalled();
1128
1104
  expect(OutputFormatter.success).toHaveBeenCalledWith(
@@ -1149,6 +1125,9 @@ describe("records delete", () => {
1149
1125
  "delete",
1150
1126
  "entity-id",
1151
1127
  "rec-1",
1128
+ "--yes",
1129
+ "--reason",
1130
+ "test cleanup",
1152
1131
  ]);
1153
1132
 
1154
1133
  expect(OutputFormatter.error).toHaveBeenCalledWith(
@@ -1172,6 +1151,9 @@ describe("records delete", () => {
1172
1151
  "entity-id",
1173
1152
  "rec-1",
1174
1153
  "rec-2",
1154
+ "--yes",
1155
+ "--reason",
1156
+ "test cleanup",
1175
1157
  ]);
1176
1158
  expect(OutputFormatter.success).toHaveBeenCalledWith(
1177
1159
  expect.objectContaining({
@@ -1185,18 +1167,38 @@ describe("records delete", () => {
1185
1167
  );
1186
1168
  expect(process.exitCode).toBe(1);
1187
1169
  });
1188
- });
1189
1170
 
1190
- describe("records delete client error", () => {
1191
- beforeEach(() => {
1192
- vi.resetAllMocks();
1193
- process.exitCode = undefined;
1194
- });
1171
+ it("should accept --confirm as a deprecated alias for --yes", async () => {
1172
+ const sdk = mockSdk();
1173
+
1174
+ const program = buildProgram();
1175
+ await program.parseAsync([
1176
+ "node",
1177
+ "test",
1178
+ "records",
1179
+ "delete",
1180
+ "entity-id",
1181
+ "rec-1",
1182
+ "--confirm",
1183
+ "--reason",
1184
+ "test cleanup",
1185
+ ]);
1195
1186
 
1196
- it("should error when SDK connection fails on delete", async () => {
1197
- vi.mocked(createDataFabricClient).mockRejectedValue(
1198
- new Error("Not logged in"),
1187
+ expect(sdk.entities.deleteRecordsById).toHaveBeenCalledWith(
1188
+ "entity-id",
1189
+ ["rec-1"],
1190
+ );
1191
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
1192
+ expect.objectContaining({
1193
+ Result: "Success",
1194
+ Code: "RecordsDeleted",
1195
+ }),
1199
1196
  );
1197
+ });
1198
+
1199
+ it("should require confirmation: without --yes, exit 1 and SDK not called", async () => {
1200
+ const sdk = mockSdk();
1201
+
1200
1202
  const program = buildProgram();
1201
1203
  await program.parseAsync([
1202
1204
  "node",
@@ -1205,17 +1207,63 @@ describe("records delete client error", () => {
1205
1207
  "delete",
1206
1208
  "entity-id",
1207
1209
  "rec-1",
1210
+ "--reason",
1211
+ "test cleanup",
1208
1212
  ]);
1213
+
1214
+ expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
1215
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1216
+ expect(process.exitCode).toBe(1);
1217
+ });
1218
+
1219
+ it("should require --reason when confirmation is present", async () => {
1220
+ const sdk = mockSdk();
1221
+
1222
+ const program = buildProgram();
1223
+ await program.parseAsync([
1224
+ "node",
1225
+ "test",
1226
+ "records",
1227
+ "delete",
1228
+ "entity-id",
1229
+ "rec-1",
1230
+ "--yes",
1231
+ ]);
1232
+
1233
+ expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
1209
1234
  expect(OutputFormatter.error).toHaveBeenCalledWith(
1210
1235
  expect.objectContaining({
1211
1236
  Result: "Failure",
1212
- Message: "Error connecting to Data Fabric",
1237
+ Message: "Reason required for destructive operation",
1213
1238
  }),
1214
1239
  );
1215
1240
  expect(process.exitCode).toBe(1);
1216
1241
  });
1217
1242
  });
1218
1243
 
1244
+ describe("records delete client error", () => {
1245
+ beforeEach(() => {
1246
+ vi.resetAllMocks();
1247
+ process.exitCode = undefined;
1248
+ });
1249
+
1250
+ it("should bail when SDK connection fails on delete", async () => {
1251
+ const sdk = mockSdk();
1252
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
1253
+ const program = buildProgram();
1254
+ await program.parseAsync([
1255
+ "node",
1256
+ "test",
1257
+ "records",
1258
+ "delete",
1259
+ "entity-id",
1260
+ "rec-1",
1261
+ ]);
1262
+ expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
1263
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1264
+ });
1265
+ });
1266
+
1219
1267
  describe("records insert via --file", () => {
1220
1268
  beforeEach(() => {
1221
1269
  vi.resetAllMocks();
@@ -1305,13 +1353,14 @@ describe("records query", () => {
1305
1353
  process.exitCode = undefined;
1306
1354
  });
1307
1355
 
1308
- it("should query records without filters (no --body)", async () => {
1356
+ it("should query records without filters (no --body) and return raw shape", async () => {
1309
1357
  const sdk = mockSdk();
1310
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
1358
+ const rawResult = {
1311
1359
  items: [{ Id: "rec-1", title: "test" }],
1312
1360
  totalCount: 1,
1313
1361
  hasNextPage: false,
1314
- });
1362
+ };
1363
+ vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
1315
1364
 
1316
1365
  const program = buildProgram();
1317
1366
  await program.parseAsync([
@@ -1330,10 +1379,7 @@ describe("records query", () => {
1330
1379
  expect.objectContaining({
1331
1380
  Result: "Success",
1332
1381
  Code: "RecordQuery",
1333
- Data: expect.objectContaining({
1334
- TotalCount: 1,
1335
- HasNextPage: false,
1336
- }),
1382
+ Data: rawResult,
1337
1383
  }),
1338
1384
  );
1339
1385
  });
@@ -1421,7 +1467,7 @@ describe("records query", () => {
1421
1467
  expect.objectContaining({
1422
1468
  Result: "Success",
1423
1469
  Code: "RecordQuery",
1424
- Data: expect.objectContaining({ TotalCount: 2 }),
1470
+ Data: expect.objectContaining({ totalCount: 2 }),
1425
1471
  }),
1426
1472
  );
1427
1473
  });
@@ -1470,8 +1516,8 @@ describe("records query", () => {
1470
1516
  Result: "Success",
1471
1517
  Code: "RecordQuery",
1472
1518
  Data: expect.objectContaining({
1473
- TotalCount: 2,
1474
- Records: [
1519
+ totalCount: 2,
1520
+ items: [
1475
1521
  { status: "Open", total: 12 },
1476
1522
  { status: "Closed", total: 5 },
1477
1523
  ],
@@ -1527,12 +1573,13 @@ describe("records query", () => {
1527
1573
 
1528
1574
  it("should pass custom --limit and --cursor to queryRecordsById", async () => {
1529
1575
  const sdk = mockSdk();
1530
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
1576
+ const rawResult = {
1531
1577
  items: [{ Id: "rec-3" }],
1532
1578
  totalCount: 100,
1533
1579
  hasNextPage: true,
1534
- nextCursor: "next-cursor-xyz",
1535
- });
1580
+ nextCursor: { value: "next-cursor-xyz" },
1581
+ };
1582
+ vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
1536
1583
 
1537
1584
  const program = buildProgram();
1538
1585
  await program.parseAsync([
@@ -1556,10 +1603,7 @@ describe("records query", () => {
1556
1603
  );
1557
1604
  expect(OutputFormatter.success).toHaveBeenCalledWith(
1558
1605
  expect.objectContaining({
1559
- Data: expect.objectContaining({
1560
- HasNextPage: true,
1561
- NextCursor: "next-cursor-xyz",
1562
- }),
1606
+ Data: rawResult,
1563
1607
  }),
1564
1608
  );
1565
1609
  });
@@ -1627,10 +1671,9 @@ describe("records query", () => {
1627
1671
  expect(process.exitCode).toBe(1);
1628
1672
  });
1629
1673
 
1630
- it("should error when SDK connection fails on query", async () => {
1631
- vi.mocked(createDataFabricClient).mockRejectedValue(
1632
- new Error("Not logged in"),
1633
- );
1674
+ it("should bail when SDK connection fails on query", async () => {
1675
+ const sdk = mockSdk();
1676
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
1634
1677
  const program = buildProgram();
1635
1678
  await program.parseAsync([
1636
1679
  "node",
@@ -1639,13 +1682,8 @@ describe("records query", () => {
1639
1682
  "query",
1640
1683
  "entity-id",
1641
1684
  ]);
1642
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1643
- expect.objectContaining({
1644
- Result: "Failure",
1645
- Message: "Error connecting to Data Fabric",
1646
- }),
1647
- );
1648
- expect(process.exitCode).toBe(1);
1685
+ expect(sdk.entities.queryRecordsById).not.toHaveBeenCalled();
1686
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1649
1687
  });
1650
1688
 
1651
1689
  it("should error when query API fails", async () => {
@@ -1877,10 +1915,9 @@ describe("records import", () => {
1877
1915
  expect(process.exitCode).toBe(1);
1878
1916
  });
1879
1917
 
1880
- it("should error when SDK connection fails on import", async () => {
1881
- vi.mocked(createDataFabricClient).mockRejectedValue(
1882
- new Error("Not logged in"),
1883
- );
1918
+ it("should bail when SDK connection fails on import", async () => {
1919
+ const sdk = mockSdk();
1920
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
1884
1921
 
1885
1922
  const { getFileSystem } = await import("@uipath/filesystem");
1886
1923
  vi.mocked(getFileSystem).mockReturnValue({
@@ -1900,13 +1937,8 @@ describe("records import", () => {
1900
1937
  "data.csv",
1901
1938
  ]);
1902
1939
 
1903
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1904
- expect.objectContaining({
1905
- Result: "Failure",
1906
- Message: "Error connecting to Data Fabric",
1907
- }),
1908
- );
1909
- expect(process.exitCode).toBe(1);
1940
+ expect(sdk.entities.importRecordsById).not.toHaveBeenCalled();
1941
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1910
1942
  });
1911
1943
  });
1912
1944
 
@@ -1940,14 +1972,14 @@ describe("records query — pagination", () => {
1940
1972
  const call = vi.mocked(OutputFormatter.success).mock
1941
1973
  .calls[0][0] as unknown as {
1942
1974
  Data: {
1943
- TotalCount: number;
1944
- Records: unknown[];
1945
- HasNextPage: boolean;
1975
+ totalCount: number;
1976
+ items: unknown[];
1977
+ hasNextPage: boolean;
1946
1978
  };
1947
1979
  };
1948
- expect(call.Data.TotalCount).toBe(3);
1949
- expect(call.Data.Records).toHaveLength(3);
1950
- expect(call.Data.HasNextPage).toBe(false);
1980
+ expect(call.Data.totalCount).toBe(3);
1981
+ expect(call.Data.items).toHaveLength(3);
1982
+ expect(call.Data.hasNextPage).toBe(false);
1951
1983
  });
1952
1984
 
1953
1985
  it("should return first page with cursor when paginated", async () => {
@@ -1956,7 +1988,7 @@ describe("records query — pagination", () => {
1956
1988
  items: [{ Id: "r1" }, { Id: "r2" }],
1957
1989
  totalCount: 5,
1958
1990
  hasNextPage: true,
1959
- nextCursor: "cursor-page2",
1991
+ nextCursor: { value: "cursor-page2" },
1960
1992
  });
1961
1993
 
1962
1994
  const program = buildProgram();
@@ -1977,16 +2009,16 @@ describe("records query — pagination", () => {
1977
2009
  const call = vi.mocked(OutputFormatter.success).mock
1978
2010
  .calls[0][0] as unknown as {
1979
2011
  Data: {
1980
- TotalCount: number;
1981
- Records: unknown[];
1982
- HasNextPage: boolean;
1983
- NextCursor: string;
2012
+ totalCount: number;
2013
+ items: unknown[];
2014
+ hasNextPage: boolean;
2015
+ nextCursor: { value: string };
1984
2016
  };
1985
2017
  };
1986
- expect(call.Data.TotalCount).toBe(5);
1987
- expect(call.Data.Records).toHaveLength(2);
1988
- expect(call.Data.HasNextPage).toBe(true);
1989
- expect(call.Data.NextCursor).toBe("cursor-page2");
2018
+ expect(call.Data.totalCount).toBe(5);
2019
+ expect(call.Data.items).toHaveLength(2);
2020
+ expect(call.Data.hasNextPage).toBe(true);
2021
+ expect(call.Data.nextCursor).toEqual({ value: "cursor-page2" });
1990
2022
  });
1991
2023
 
1992
2024
  it("should pass cursor to second page request", async () => {
@@ -1995,7 +2027,7 @@ describe("records query — pagination", () => {
1995
2027
  items: [{ Id: "r3" }, { Id: "r4" }],
1996
2028
  totalCount: 5,
1997
2029
  hasNextPage: true,
1998
- nextCursor: "cursor-page3",
2030
+ nextCursor: { value: "cursor-page3" },
1999
2031
  });
2000
2032
 
2001
2033
  const program = buildProgram();
@@ -2021,8 +2053,8 @@ describe("records query — pagination", () => {
2021
2053
  expect(OutputFormatter.success).toHaveBeenCalledWith(
2022
2054
  expect.objectContaining({
2023
2055
  Data: expect.objectContaining({
2024
- HasNextPage: true,
2025
- NextCursor: "cursor-page3",
2056
+ hasNextPage: true,
2057
+ nextCursor: { value: "cursor-page3" },
2026
2058
  }),
2027
2059
  }),
2028
2060
  );
@@ -2034,7 +2066,7 @@ describe("records query — pagination", () => {
2034
2066
  items: [{ Id: "r1", status: "active" }],
2035
2067
  totalCount: 10,
2036
2068
  hasNextPage: true,
2037
- nextCursor: "cur-next",
2069
+ nextCursor: { value: "cur-next" },
2038
2070
  });
2039
2071
 
2040
2072
  const body = JSON.stringify({
@@ -2074,67 +2106,14 @@ describe("records query — pagination", () => {
2074
2106
  expect(OutputFormatter.success).toHaveBeenCalledWith(
2075
2107
  expect.objectContaining({
2076
2108
  Data: expect.objectContaining({
2077
- TotalCount: 10,
2078
- HasNextPage: true,
2079
- NextCursor: "cur-next",
2109
+ totalCount: 10,
2110
+ hasNextPage: true,
2111
+ nextCursor: { value: "cur-next" },
2080
2112
  }),
2081
2113
  }),
2082
2114
  );
2083
2115
  });
2084
2116
 
2085
- it("should omit NextCursor when hasNextPage is false", async () => {
2086
- const sdk = mockSdk();
2087
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
2088
- items: [{ Id: "r1" }],
2089
- totalCount: 1,
2090
- hasNextPage: false,
2091
- });
2092
-
2093
- const program = buildProgram();
2094
- await program.parseAsync([
2095
- "node",
2096
- "test",
2097
- "records",
2098
- "query",
2099
- "entity-id",
2100
- ]);
2101
-
2102
- const call = vi.mocked(OutputFormatter.success).mock.calls[0][0] as {
2103
- Data: Record<string, unknown>;
2104
- };
2105
- expect(call.Data).not.toHaveProperty("NextCursor");
2106
- });
2107
-
2108
- it("should normalise cursor object {value} returned by SDK to a plain string", async () => {
2109
- const sdk = mockSdk();
2110
- // SDK may return PaginationCursor = { value: string } instead of a raw string
2111
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
2112
- items: [{ Id: "r1" }, { Id: "r2" }],
2113
- totalCount: 4,
2114
- hasNextPage: true,
2115
- nextCursor: { value: "cursor-as-object" } as unknown as string,
2116
- });
2117
-
2118
- const program = buildProgram();
2119
- await program.parseAsync([
2120
- "node",
2121
- "test",
2122
- "records",
2123
- "query",
2124
- "entity-id",
2125
- "--limit",
2126
- "2",
2127
- ]);
2128
-
2129
- const call = vi.mocked(OutputFormatter.success).mock
2130
- .calls[0][0] as unknown as {
2131
- Data: { NextCursor: unknown };
2132
- };
2133
- // Must be a plain string, not the object
2134
- expect(typeof call.Data.NextCursor).toBe("string");
2135
- expect(call.Data.NextCursor).toBe("cursor-as-object");
2136
- });
2137
-
2138
2117
  it("should use default limit 50 when --cursor is given without --limit", async () => {
2139
2118
  const sdk = mockSdk();
2140
2119
  vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
@@ -2240,14 +2219,14 @@ describe("records query — pagination", () => {
2240
2219
  expect(process.exitCode).toBe(1);
2241
2220
  });
2242
2221
 
2243
- it("should handle last page correctly no NextCursor even if SDK emits undefined", async () => {
2222
+ it("should pass cursor through on the last page and return the raw result", async () => {
2244
2223
  const sdk = mockSdk();
2245
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
2224
+ const rawResult = {
2246
2225
  items: [{ Id: "r5" }],
2247
2226
  totalCount: 5,
2248
2227
  hasNextPage: false,
2249
- nextCursor: undefined,
2250
- });
2228
+ };
2229
+ vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
2251
2230
 
2252
2231
  const program = buildProgram();
2253
2232
  await program.parseAsync([
@@ -2269,11 +2248,11 @@ describe("records query — pagination", () => {
2269
2248
  cursor: { value: "cursor-page2" },
2270
2249
  }),
2271
2250
  );
2272
- const call = vi.mocked(OutputFormatter.success).mock.calls[0][0] as {
2273
- Data: Record<string, unknown>;
2274
- };
2275
- expect(call.Data.HasNextPage).toBe(false);
2276
- expect(call.Data).not.toHaveProperty("NextCursor");
2251
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
2252
+ expect.objectContaining({
2253
+ Data: rawResult,
2254
+ }),
2255
+ );
2277
2256
  });
2278
2257
  });
2279
2258
 
@@ -2347,6 +2326,9 @@ describe("records — negative scenarios", () => {
2347
2326
  "delete",
2348
2327
  "entity-id",
2349
2328
  "nonexistent-record-id",
2329
+ "--yes",
2330
+ "--reason",
2331
+ "test cleanup",
2350
2332
  ]);
2351
2333
 
2352
2334
  expect(OutputFormatter.error).toHaveBeenCalledWith(