@uipath/data-fabric-tool 1.0.4 → 1.195.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 () => {
@@ -701,6 +677,75 @@ describe("records insert", () => {
701
677
  expect(process.exitCode).toBe(1);
702
678
  });
703
679
 
680
+ it("should pass choice-set NumberId integers and a relationship UUID through to the SDK on single insert", async () => {
681
+ const sdk = mockSdk();
682
+ vi.mocked(sdk.entities.insertRecordById).mockResolvedValue({
683
+ Id: "new-rec",
684
+ });
685
+
686
+ const program = buildProgram();
687
+ await program.parseAsync([
688
+ "node",
689
+ "test",
690
+ "records",
691
+ "insert",
692
+ "entity-id",
693
+ "--body",
694
+ '{"title":"Flight to NYC","amount":420.5,"opType":0,"multiOpType":[0,1],"assignee":"AEDE69C3-EFD1-4897-B216-019E1A7E9269","rel1":"B065E2A8-F33B-4721-8228-019DE0C593AF"}',
695
+ ]);
696
+
697
+ expect(sdk.entities.insertRecordById).toHaveBeenCalledWith(
698
+ "entity-id",
699
+ expect.objectContaining({
700
+ opType: 0,
701
+ multiOpType: [0, 1],
702
+ assignee: "AEDE69C3-EFD1-4897-B216-019E1A7E9269",
703
+ rel1: "B065E2A8-F33B-4721-8228-019DE0C593AF",
704
+ }),
705
+ );
706
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
707
+ expect.objectContaining({ Code: "RecordInserted" }),
708
+ );
709
+ });
710
+
711
+ it("should pass choice-set and relationship values through unchanged on batch insert", async () => {
712
+ const sdk = mockSdk();
713
+ vi.mocked(sdk.entities.insertRecordsById).mockResolvedValue({
714
+ successRecords: [{ Id: "rec-a" }, { Id: "rec-b" }],
715
+ failureRecords: [],
716
+ });
717
+
718
+ const program = buildProgram();
719
+ await program.parseAsync([
720
+ "node",
721
+ "test",
722
+ "records",
723
+ "insert",
724
+ "entity-id",
725
+ "--body",
726
+ '[{"opType":0,"multiOpType":[0],"assignee":"AEDE69C3-EFD1-4897-B216-019E1A7E9269"},{"opType":1,"multiOpType":[0,1],"assignee":"2481A9F6-E0F7-4996-8446-019E1A7E926A"}]',
727
+ ]);
728
+
729
+ expect(sdk.entities.insertRecordsById).toHaveBeenCalledWith(
730
+ "entity-id",
731
+ expect.arrayContaining([
732
+ expect.objectContaining({
733
+ opType: 0,
734
+ multiOpType: [0],
735
+ assignee: "AEDE69C3-EFD1-4897-B216-019E1A7E9269",
736
+ }),
737
+ expect.objectContaining({
738
+ opType: 1,
739
+ multiOpType: [0, 1],
740
+ assignee: "2481A9F6-E0F7-4996-8446-019E1A7E926A",
741
+ }),
742
+ ]),
743
+ );
744
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
745
+ expect.objectContaining({ Code: "RecordsBatchInserted" }),
746
+ );
747
+ });
748
+
704
749
  it("should error on partial batch insert failure (FailureCount > 0)", async () => {
705
750
  const sdk = mockSdk();
706
751
  vi.mocked(sdk.entities.insertRecordsById).mockResolvedValue({
@@ -908,10 +953,9 @@ describe("records update client/batch errors", () => {
908
953
  process.exitCode = undefined;
909
954
  });
910
955
 
911
- it("should error when SDK connection fails on update", async () => {
912
- vi.mocked(createDataFabricClient).mockRejectedValue(
913
- new Error("Not logged in"),
914
- );
956
+ it("should bail when SDK connection fails on update", async () => {
957
+ const sdk = mockSdk();
958
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
915
959
  const program = buildProgram();
916
960
  await program.parseAsync([
917
961
  "node",
@@ -922,13 +966,8 @@ describe("records update client/batch errors", () => {
922
966
  "--body",
923
967
  '{"Id":"rec-1"}',
924
968
  ]);
925
- expect(OutputFormatter.error).toHaveBeenCalledWith(
926
- expect.objectContaining({
927
- Result: "Failure",
928
- Message: "Error connecting to Data Fabric",
929
- }),
930
- );
931
- expect(process.exitCode).toBe(1);
969
+ expect(sdk.entities.updateRecordById).not.toHaveBeenCalled();
970
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
932
971
  });
933
972
 
934
973
  it("should handle batch update result without successRecords/failureRecords", async () => {
@@ -1124,10 +1163,9 @@ describe("records delete client error", () => {
1124
1163
  process.exitCode = undefined;
1125
1164
  });
1126
1165
 
1127
- it("should error when SDK connection fails on delete", async () => {
1128
- vi.mocked(createDataFabricClient).mockRejectedValue(
1129
- new Error("Not logged in"),
1130
- );
1166
+ it("should bail when SDK connection fails on delete", async () => {
1167
+ const sdk = mockSdk();
1168
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
1131
1169
  const program = buildProgram();
1132
1170
  await program.parseAsync([
1133
1171
  "node",
@@ -1137,13 +1175,8 @@ describe("records delete client error", () => {
1137
1175
  "entity-id",
1138
1176
  "rec-1",
1139
1177
  ]);
1140
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1141
- expect.objectContaining({
1142
- Result: "Failure",
1143
- Message: "Error connecting to Data Fabric",
1144
- }),
1145
- );
1146
- expect(process.exitCode).toBe(1);
1178
+ expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
1179
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1147
1180
  });
1148
1181
  });
1149
1182
 
@@ -1236,13 +1269,14 @@ describe("records query", () => {
1236
1269
  process.exitCode = undefined;
1237
1270
  });
1238
1271
 
1239
- it("should query records without filters (no --body)", async () => {
1272
+ it("should query records without filters (no --body) and return raw shape", async () => {
1240
1273
  const sdk = mockSdk();
1241
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
1274
+ const rawResult = {
1242
1275
  items: [{ Id: "rec-1", title: "test" }],
1243
1276
  totalCount: 1,
1244
1277
  hasNextPage: false,
1245
- });
1278
+ };
1279
+ vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
1246
1280
 
1247
1281
  const program = buildProgram();
1248
1282
  await program.parseAsync([
@@ -1261,10 +1295,7 @@ describe("records query", () => {
1261
1295
  expect.objectContaining({
1262
1296
  Result: "Success",
1263
1297
  Code: "RecordQuery",
1264
- Data: expect.objectContaining({
1265
- TotalCount: 1,
1266
- HasNextPage: false,
1267
- }),
1298
+ Data: rawResult,
1268
1299
  }),
1269
1300
  );
1270
1301
  });
@@ -1352,7 +1383,7 @@ describe("records query", () => {
1352
1383
  expect.objectContaining({
1353
1384
  Result: "Success",
1354
1385
  Code: "RecordQuery",
1355
- Data: expect.objectContaining({ TotalCount: 2 }),
1386
+ Data: expect.objectContaining({ totalCount: 2 }),
1356
1387
  }),
1357
1388
  );
1358
1389
  });
@@ -1401,8 +1432,8 @@ describe("records query", () => {
1401
1432
  Result: "Success",
1402
1433
  Code: "RecordQuery",
1403
1434
  Data: expect.objectContaining({
1404
- TotalCount: 2,
1405
- Records: [
1435
+ totalCount: 2,
1436
+ items: [
1406
1437
  { status: "Open", total: 12 },
1407
1438
  { status: "Closed", total: 5 },
1408
1439
  ],
@@ -1458,12 +1489,13 @@ describe("records query", () => {
1458
1489
 
1459
1490
  it("should pass custom --limit and --cursor to queryRecordsById", async () => {
1460
1491
  const sdk = mockSdk();
1461
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
1492
+ const rawResult = {
1462
1493
  items: [{ Id: "rec-3" }],
1463
1494
  totalCount: 100,
1464
1495
  hasNextPage: true,
1465
- nextCursor: "next-cursor-xyz",
1466
- });
1496
+ nextCursor: { value: "next-cursor-xyz" },
1497
+ };
1498
+ vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
1467
1499
 
1468
1500
  const program = buildProgram();
1469
1501
  await program.parseAsync([
@@ -1487,10 +1519,7 @@ describe("records query", () => {
1487
1519
  );
1488
1520
  expect(OutputFormatter.success).toHaveBeenCalledWith(
1489
1521
  expect.objectContaining({
1490
- Data: expect.objectContaining({
1491
- HasNextPage: true,
1492
- NextCursor: "next-cursor-xyz",
1493
- }),
1522
+ Data: rawResult,
1494
1523
  }),
1495
1524
  );
1496
1525
  });
@@ -1558,10 +1587,9 @@ describe("records query", () => {
1558
1587
  expect(process.exitCode).toBe(1);
1559
1588
  });
1560
1589
 
1561
- it("should error when SDK connection fails on query", async () => {
1562
- vi.mocked(createDataFabricClient).mockRejectedValue(
1563
- new Error("Not logged in"),
1564
- );
1590
+ it("should bail when SDK connection fails on query", async () => {
1591
+ const sdk = mockSdk();
1592
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
1565
1593
  const program = buildProgram();
1566
1594
  await program.parseAsync([
1567
1595
  "node",
@@ -1570,13 +1598,8 @@ describe("records query", () => {
1570
1598
  "query",
1571
1599
  "entity-id",
1572
1600
  ]);
1573
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1574
- expect.objectContaining({
1575
- Result: "Failure",
1576
- Message: "Error connecting to Data Fabric",
1577
- }),
1578
- );
1579
- expect(process.exitCode).toBe(1);
1601
+ expect(sdk.entities.queryRecordsById).not.toHaveBeenCalled();
1602
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1580
1603
  });
1581
1604
 
1582
1605
  it("should error when query API fails", async () => {
@@ -1808,10 +1831,9 @@ describe("records import", () => {
1808
1831
  expect(process.exitCode).toBe(1);
1809
1832
  });
1810
1833
 
1811
- it("should error when SDK connection fails on import", async () => {
1812
- vi.mocked(createDataFabricClient).mockRejectedValue(
1813
- new Error("Not logged in"),
1814
- );
1834
+ it("should bail when SDK connection fails on import", async () => {
1835
+ const sdk = mockSdk();
1836
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
1815
1837
 
1816
1838
  const { getFileSystem } = await import("@uipath/filesystem");
1817
1839
  vi.mocked(getFileSystem).mockReturnValue({
@@ -1831,13 +1853,8 @@ describe("records import", () => {
1831
1853
  "data.csv",
1832
1854
  ]);
1833
1855
 
1834
- expect(OutputFormatter.error).toHaveBeenCalledWith(
1835
- expect.objectContaining({
1836
- Result: "Failure",
1837
- Message: "Error connecting to Data Fabric",
1838
- }),
1839
- );
1840
- expect(process.exitCode).toBe(1);
1856
+ expect(sdk.entities.importRecordsById).not.toHaveBeenCalled();
1857
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
1841
1858
  });
1842
1859
  });
1843
1860
 
@@ -1871,14 +1888,14 @@ describe("records query — pagination", () => {
1871
1888
  const call = vi.mocked(OutputFormatter.success).mock
1872
1889
  .calls[0][0] as unknown as {
1873
1890
  Data: {
1874
- TotalCount: number;
1875
- Records: unknown[];
1876
- HasNextPage: boolean;
1891
+ totalCount: number;
1892
+ items: unknown[];
1893
+ hasNextPage: boolean;
1877
1894
  };
1878
1895
  };
1879
- expect(call.Data.TotalCount).toBe(3);
1880
- expect(call.Data.Records).toHaveLength(3);
1881
- expect(call.Data.HasNextPage).toBe(false);
1896
+ expect(call.Data.totalCount).toBe(3);
1897
+ expect(call.Data.items).toHaveLength(3);
1898
+ expect(call.Data.hasNextPage).toBe(false);
1882
1899
  });
1883
1900
 
1884
1901
  it("should return first page with cursor when paginated", async () => {
@@ -1887,7 +1904,7 @@ describe("records query — pagination", () => {
1887
1904
  items: [{ Id: "r1" }, { Id: "r2" }],
1888
1905
  totalCount: 5,
1889
1906
  hasNextPage: true,
1890
- nextCursor: "cursor-page2",
1907
+ nextCursor: { value: "cursor-page2" },
1891
1908
  });
1892
1909
 
1893
1910
  const program = buildProgram();
@@ -1908,16 +1925,16 @@ describe("records query — pagination", () => {
1908
1925
  const call = vi.mocked(OutputFormatter.success).mock
1909
1926
  .calls[0][0] as unknown as {
1910
1927
  Data: {
1911
- TotalCount: number;
1912
- Records: unknown[];
1913
- HasNextPage: boolean;
1914
- NextCursor: string;
1928
+ totalCount: number;
1929
+ items: unknown[];
1930
+ hasNextPage: boolean;
1931
+ nextCursor: { value: string };
1915
1932
  };
1916
1933
  };
1917
- expect(call.Data.TotalCount).toBe(5);
1918
- expect(call.Data.Records).toHaveLength(2);
1919
- expect(call.Data.HasNextPage).toBe(true);
1920
- expect(call.Data.NextCursor).toBe("cursor-page2");
1934
+ expect(call.Data.totalCount).toBe(5);
1935
+ expect(call.Data.items).toHaveLength(2);
1936
+ expect(call.Data.hasNextPage).toBe(true);
1937
+ expect(call.Data.nextCursor).toEqual({ value: "cursor-page2" });
1921
1938
  });
1922
1939
 
1923
1940
  it("should pass cursor to second page request", async () => {
@@ -1926,7 +1943,7 @@ describe("records query — pagination", () => {
1926
1943
  items: [{ Id: "r3" }, { Id: "r4" }],
1927
1944
  totalCount: 5,
1928
1945
  hasNextPage: true,
1929
- nextCursor: "cursor-page3",
1946
+ nextCursor: { value: "cursor-page3" },
1930
1947
  });
1931
1948
 
1932
1949
  const program = buildProgram();
@@ -1952,8 +1969,8 @@ describe("records query — pagination", () => {
1952
1969
  expect(OutputFormatter.success).toHaveBeenCalledWith(
1953
1970
  expect.objectContaining({
1954
1971
  Data: expect.objectContaining({
1955
- HasNextPage: true,
1956
- NextCursor: "cursor-page3",
1972
+ hasNextPage: true,
1973
+ nextCursor: { value: "cursor-page3" },
1957
1974
  }),
1958
1975
  }),
1959
1976
  );
@@ -1965,7 +1982,7 @@ describe("records query — pagination", () => {
1965
1982
  items: [{ Id: "r1", status: "active" }],
1966
1983
  totalCount: 10,
1967
1984
  hasNextPage: true,
1968
- nextCursor: "cur-next",
1985
+ nextCursor: { value: "cur-next" },
1969
1986
  });
1970
1987
 
1971
1988
  const body = JSON.stringify({
@@ -2005,67 +2022,14 @@ describe("records query — pagination", () => {
2005
2022
  expect(OutputFormatter.success).toHaveBeenCalledWith(
2006
2023
  expect.objectContaining({
2007
2024
  Data: expect.objectContaining({
2008
- TotalCount: 10,
2009
- HasNextPage: true,
2010
- NextCursor: "cur-next",
2025
+ totalCount: 10,
2026
+ hasNextPage: true,
2027
+ nextCursor: { value: "cur-next" },
2011
2028
  }),
2012
2029
  }),
2013
2030
  );
2014
2031
  });
2015
2032
 
2016
- it("should omit NextCursor when hasNextPage is false", async () => {
2017
- const sdk = mockSdk();
2018
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
2019
- items: [{ Id: "r1" }],
2020
- totalCount: 1,
2021
- hasNextPage: false,
2022
- });
2023
-
2024
- const program = buildProgram();
2025
- await program.parseAsync([
2026
- "node",
2027
- "test",
2028
- "records",
2029
- "query",
2030
- "entity-id",
2031
- ]);
2032
-
2033
- const call = vi.mocked(OutputFormatter.success).mock.calls[0][0] as {
2034
- Data: Record<string, unknown>;
2035
- };
2036
- expect(call.Data).not.toHaveProperty("NextCursor");
2037
- });
2038
-
2039
- it("should normalise cursor object {value} returned by SDK to a plain string", async () => {
2040
- const sdk = mockSdk();
2041
- // SDK may return PaginationCursor = { value: string } instead of a raw string
2042
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
2043
- items: [{ Id: "r1" }, { Id: "r2" }],
2044
- totalCount: 4,
2045
- hasNextPage: true,
2046
- nextCursor: { value: "cursor-as-object" } as unknown as string,
2047
- });
2048
-
2049
- const program = buildProgram();
2050
- await program.parseAsync([
2051
- "node",
2052
- "test",
2053
- "records",
2054
- "query",
2055
- "entity-id",
2056
- "--limit",
2057
- "2",
2058
- ]);
2059
-
2060
- const call = vi.mocked(OutputFormatter.success).mock
2061
- .calls[0][0] as unknown as {
2062
- Data: { NextCursor: unknown };
2063
- };
2064
- // Must be a plain string, not the object
2065
- expect(typeof call.Data.NextCursor).toBe("string");
2066
- expect(call.Data.NextCursor).toBe("cursor-as-object");
2067
- });
2068
-
2069
2033
  it("should use default limit 50 when --cursor is given without --limit", async () => {
2070
2034
  const sdk = mockSdk();
2071
2035
  vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
@@ -2171,14 +2135,14 @@ describe("records query — pagination", () => {
2171
2135
  expect(process.exitCode).toBe(1);
2172
2136
  });
2173
2137
 
2174
- it("should handle last page correctly no NextCursor even if SDK emits undefined", async () => {
2138
+ it("should pass cursor through on the last page and return the raw result", async () => {
2175
2139
  const sdk = mockSdk();
2176
- vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
2140
+ const rawResult = {
2177
2141
  items: [{ Id: "r5" }],
2178
2142
  totalCount: 5,
2179
2143
  hasNextPage: false,
2180
- nextCursor: undefined,
2181
- });
2144
+ };
2145
+ vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
2182
2146
 
2183
2147
  const program = buildProgram();
2184
2148
  await program.parseAsync([
@@ -2200,11 +2164,11 @@ describe("records query — pagination", () => {
2200
2164
  cursor: { value: "cursor-page2" },
2201
2165
  }),
2202
2166
  );
2203
- const call = vi.mocked(OutputFormatter.success).mock.calls[0][0] as {
2204
- Data: Record<string, unknown>;
2205
- };
2206
- expect(call.Data.HasNextPage).toBe(false);
2207
- expect(call.Data).not.toHaveProperty("NextCursor");
2167
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
2168
+ expect.objectContaining({
2169
+ Data: rawResult,
2170
+ }),
2171
+ );
2208
2172
  });
2209
2173
  });
2210
2174