microsoft-graph 1.0.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.
Files changed (151) hide show
  1. package/.editorconfig +18 -0
  2. package/.gitattributes +46 -0
  3. package/.vscode/extensions.json +3 -0
  4. package/.vscode/launch.json +15 -0
  5. package/.vscode/settings.json +15 -0
  6. package/CONTRIBUTING.md +2 -0
  7. package/LICENCE.md +360 -0
  8. package/README.md +52 -0
  9. package/biome.jsonc +83 -0
  10. package/dist/errors/BadTemplateError.js +6 -0
  11. package/dist/errors/EnvironmentVariableMissingError.js +6 -0
  12. package/dist/errors/InvalidArgumentError.js +21 -0
  13. package/dist/errors/ProtocolError.js +11 -0
  14. package/dist/errors/RequestFailedError.js +21 -0
  15. package/dist/graphApi.js +116 -0
  16. package/dist/index.js +2 -0
  17. package/dist/models/AccessToken.js +1 -0
  18. package/dist/models/DriveId.js +1 -0
  19. package/dist/models/DriveItemId.js +1 -0
  20. package/dist/models/DriveItemPath.js +1 -0
  21. package/dist/models/DriveItemRef.js +1 -0
  22. package/dist/models/DriveRef.js +1 -0
  23. package/dist/models/GraphOperation.js +1 -0
  24. package/dist/models/GraphOperationDefinition.js +1 -0
  25. package/dist/models/HostName.js +1 -0
  26. package/dist/models/Scope.js +1 -0
  27. package/dist/models/SiteId.js +1 -0
  28. package/dist/models/SiteName.js +1 -0
  29. package/dist/models/SiteRef.js +1 -0
  30. package/dist/models/WorkbookNamedRangeRef.js +1 -0
  31. package/dist/models/WorkbookRangeAddress.js +1 -0
  32. package/dist/models/WorkbookRangeName.js +1 -0
  33. package/dist/models/WorkbookRangeRef.js +1 -0
  34. package/dist/models/WorkbookRef.js +1 -0
  35. package/dist/models/WorkbookSessionId.js +1 -0
  36. package/dist/models/WorkbookTableId.js +1 -0
  37. package/dist/models/WorkbookTableRef.js +1 -0
  38. package/dist/models/WorkbookWorksheetId.js +1 -0
  39. package/dist/models/WorkbookWorksheetName.js +1 -0
  40. package/dist/models/WorkbookWorksheetRef.js +1 -0
  41. package/dist/operations/drive/createFolder.js +27 -0
  42. package/dist/operations/drive/createFolder.test.js +31 -0
  43. package/dist/operations/drive/listDrives.js +23 -0
  44. package/dist/operations/drive/listDrives.test.js +9 -0
  45. package/dist/operations/driveItem/copyDriveItem.js +21 -0
  46. package/dist/operations/driveItem/copyDriveItem.test.js +28 -0
  47. package/dist/operations/driveItem/deleteDriveItem.js +12 -0
  48. package/dist/operations/driveItem/deleteDriveItem.test.js +22 -0
  49. package/dist/operations/driveItem/getDriveItem.js +18 -0
  50. package/dist/operations/driveItem/getDriveItem.test.js +24 -0
  51. package/dist/operations/driveItem/getDriveItemByPath.js +20 -0
  52. package/dist/operations/driveItem/getDriveItemByPath.test.js +22 -0
  53. package/dist/operations/driveItem/getDriveItemContent.js +22 -0
  54. package/dist/operations/driveItem/getDriveItemContent.test.js +37 -0
  55. package/dist/operations/driveItem/listDriveItems.js +25 -0
  56. package/dist/operations/driveItem/listDriveItems.test.js +24 -0
  57. package/dist/operations/site/getSite.js +18 -0
  58. package/dist/operations/site/getSite.test.js +15 -0
  59. package/dist/operations/site/getSiteByName.js +20 -0
  60. package/dist/operations/site/getSiteByName.test.js +20 -0
  61. package/dist/operations/site/listSites.js +23 -0
  62. package/dist/operations/site/listSites.test.js +10 -0
  63. package/dist/operations/site/searchSites.js +23 -0
  64. package/dist/operations/site/searchSites.test.js +21 -0
  65. package/dist/operations/workbook/calculateWorkbook.js +20 -0
  66. package/dist/operations/workbook/calculateWorkbook.test.js +46 -0
  67. package/dist/operations/workbook/createWorkbook.js +26 -0
  68. package/dist/operations/workbook/createWorkbook.test.js +15 -0
  69. package/dist/operations/workbook/deleteWorkbook.js +5 -0
  70. package/dist/operations/workbookRange/clearWorkbookRange.js +17 -0
  71. package/dist/operations/workbookRange/clearWorkbookRange.test.js +56 -0
  72. package/dist/operations/workbookRange/deleteWorkbookRange.js +17 -0
  73. package/dist/operations/workbookRange/deleteWorkbookRange.test.js +56 -0
  74. package/dist/operations/workbookRange/getWorkbookNamedRange.js +20 -0
  75. package/dist/operations/workbookRange/getWorkbookUsedRange.js +22 -0
  76. package/dist/operations/workbookRange/getWorkbookUsedRange.test.js +54 -0
  77. package/dist/operations/workbookRange/getWorkbookVisibleRange.js +20 -0
  78. package/dist/operations/workbookRange/getWorkbookVisibleRange.test.js +109 -0
  79. package/dist/operations/workbookRange/insertWorkbookCells.js +25 -0
  80. package/dist/operations/workbookRange/insertWorkbookCells.test.js +41 -0
  81. package/dist/operations/workbookRange/updateWorkbookNamedRange.js +15 -0
  82. package/dist/operations/workbookRange/updateWorkbookRange.js +21 -0
  83. package/dist/operations/workbookRange/updateWorkbookRange.test.js +54 -0
  84. package/dist/operations/workbookSession/closeWorkbookSession.js +18 -0
  85. package/dist/operations/workbookSession/createWorkbookSession.js +22 -0
  86. package/dist/operations/workbookSession/refreshWorkbookSession.js +19 -0
  87. package/dist/operations/workbookTable/createWorkbookTable.js +26 -0
  88. package/dist/operations/workbookTable/createWorkbookTable.test.js +25 -0
  89. package/dist/operations/workbookTable/getWorkbookTable.js +20 -0
  90. package/dist/operations/workbookTable/getWorkbookTable.test.js +30 -0
  91. package/dist/operations/workbookTable/getWorkbookTableBodyRange.js +22 -0
  92. package/dist/operations/workbookTable/getWorkbookTableBodyRange.test.js +45 -0
  93. package/dist/operations/workbookTable/getWorkbookTableHeaderRange.js +22 -0
  94. package/dist/operations/workbookTable/getWorkbookTableHeaderRange.test.js +41 -0
  95. package/dist/operations/workbookTable/listWorkbookTableColumns.js +17 -0
  96. package/dist/operations/workbookTable/listWorkbookTableColumns.test.js +29 -0
  97. package/dist/operations/workbookTable/listWorkbookTableRows.js +17 -0
  98. package/dist/operations/workbookTable/listWorkbookTableRows.test.js +29 -0
  99. package/dist/operations/workbookTable/listWorkbookTables.js +25 -0
  100. package/dist/operations/workbookTable/listWorkbookTables.test.js +30 -0
  101. package/dist/operations/workbookWorksheet/createWorkbookWorksheet.js +25 -0
  102. package/dist/operations/workbookWorksheet/createWorkbookWorksheet.test.js +36 -0
  103. package/dist/operations/workbookWorksheet/deleteWorkbookWorksheet.js +14 -0
  104. package/dist/operations/workbookWorksheet/deleteWorkbookWorksheet.test.js +28 -0
  105. package/dist/operations/workbookWorksheet/getWorkbookWorksheetRange.js +20 -0
  106. package/dist/operations/workbookWorksheet/getWorkbookWorksheetRange.test.js +30 -0
  107. package/dist/operations/workbookWorksheet/listWorkbookWorksheets.js +28 -0
  108. package/dist/operations/workbookWorksheet/listWorkbookWorksheets.test.js +45 -0
  109. package/dist/operations/workbookWorksheet/updateWorkbookWorksheet.js +21 -0
  110. package/dist/operations/workbookWorksheet/updateWorkbookWorksheet.test.js +37 -0
  111. package/dist/services/accessToken.js +15 -0
  112. package/dist/services/address.js +3 -0
  113. package/dist/services/configuration.js +20 -0
  114. package/dist/services/drive.js +17 -0
  115. package/dist/services/driveItem.js +48 -0
  116. package/dist/services/driveItem.test.js +17 -0
  117. package/dist/services/httpAgent.js +9 -0
  118. package/dist/services/httpStatus.js +3 -0
  119. package/dist/services/operationId.js +6 -0
  120. package/dist/services/sharepointUrl.js +24 -0
  121. package/dist/services/sharepointUrl.test.js +32 -0
  122. package/dist/services/site.js +15 -0
  123. package/dist/services/sleep.js +3 -0
  124. package/dist/services/stringCaseConversion.js +5 -0
  125. package/dist/services/stringCaseConversion.test.js +16 -0
  126. package/dist/services/templatedPaths.js +20 -0
  127. package/dist/services/templatedPaths.test.js +49 -0
  128. package/dist/services/temporaryFiles.js +11 -0
  129. package/dist/services/workbookRange.js +10 -0
  130. package/dist/services/workbookRangeAddress.js +8 -0
  131. package/dist/services/workbookTable.js +13 -0
  132. package/dist/services/workbookWorksheet.js +13 -0
  133. package/dist/tasks/createWorkbookAndStartSession.js +10 -0
  134. package/dist/tasks/deleteDriveItemWithRetry.js +16 -0
  135. package/dist/tasks/downloadDriveItemContent.js +7 -0
  136. package/dist/tasks/endSessionAndDeleteWorkbook.js +6 -0
  137. package/dist/tasks/getRangeLastUsedCell.js +38 -0
  138. package/dist/tasks/getRangeLastUsedCell.test.js +89 -0
  139. package/dist/tasks/getWorkbookTableVisibleBody.js +24 -0
  140. package/dist/tasks/getWorkbookTableVisibleBody.test.js +104 -0
  141. package/dist/tasks/getWorkbookWorksheetRefByName.js +10 -0
  142. package/dist/tasks/setColumnHidden.js +7 -0
  143. package/dist/tasks/setColumnHidden.test.js +43 -0
  144. package/dist/tasks/setRowHidden.js +7 -0
  145. package/dist/tasks/setRowHidden.test.js +42 -0
  146. package/docs/approach.md +7 -0
  147. package/docs/calculateWorkbook.md +20 -0
  148. package/docs/concepts.md +4 -0
  149. package/docs/envs.md +11 -0
  150. package/docs/performance.md +24 -0
  151. package/package.json +426 -0
@@ -0,0 +1,20 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { siteRef } from "../../services/site.js";
3
+ import { generatePath } from "../../services/templatedPaths.js";
4
+ /** Get site by name. @see https://learn.microsoft.com/en-us/graph/api/site-getbypath */
5
+ export default function getSiteByName(hostName, siteName) {
6
+ return operation({
7
+ method: "GET",
8
+ path: generatePath("/sites/{host-name}:/sites/{site-name}", { hostName, siteName }),
9
+ headers: {},
10
+ body: null,
11
+ responseTransform: (response) => {
12
+ const site = response;
13
+ const ref = siteRef(site.id);
14
+ return {
15
+ ...site,
16
+ ...ref
17
+ };
18
+ }
19
+ });
20
+ }
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getDefaultSiteRef } from "../../services/site.js";
3
+ import getSite from "./getSite.js";
4
+ import getSiteByName from "./getSiteByName.js";
5
+ describe("getSiteByName", () => {
6
+ it("can retrieve an existing site by name", async () => {
7
+ const defaultSiteRef = getDefaultSiteRef();
8
+ const defaultSite = await getSite(defaultSiteRef);
9
+ const hostName = new URL(defaultSite.webUrl ?? "").hostname; // Yeah, a little hacky, but in the context of this test it's fine
10
+ const siteName = defaultSite.name;
11
+ const site = await getSiteByName(hostName, siteName);
12
+ expect(site.id).toBe(defaultSite.id);
13
+ expect(site.name).toBe(siteName);
14
+ });
15
+ it("throws an error when trying to retrieve a non-existent site by name", async () => {
16
+ const nonExistentHostName = "non-existent-host-name";
17
+ const nonExistentSiteName = "non-existent-site-name";
18
+ await expect(getSiteByName(nonExistentHostName, nonExistentSiteName)).rejects.toThrow();
19
+ });
20
+ });
@@ -0,0 +1,23 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { siteRef } from "../../services/site.js";
3
+ import { generatePath } from "../../services/templatedPaths.js";
4
+ /** List sites that are available. @see https://learn.microsoft.com/en-us/graph/api/site-list */
5
+ export default function listSites() {
6
+ return operation({
7
+ method: "GET",
8
+ path: generatePath("/sites", {}),
9
+ headers: {},
10
+ body: null,
11
+ responseTransform: response => {
12
+ const list = response;
13
+ const sites = list.value.map(site => {
14
+ const ref = siteRef(site.id);
15
+ return {
16
+ ...site,
17
+ ...ref,
18
+ };
19
+ });
20
+ return sites;
21
+ }
22
+ });
23
+ }
@@ -0,0 +1,10 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import listSites from "./listSites.js";
3
+ describe("listSites", () => {
4
+ it("can list all sites", async () => {
5
+ const sites = await listSites();
6
+ console.debug("Sites:", sites.map(site => [site.id, site.name]));
7
+ expect(sites).toBeInstanceOf(Array);
8
+ expect(sites.length).toBeGreaterThan(0);
9
+ });
10
+ });
@@ -0,0 +1,23 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { siteRef } from "../../services/site.js";
3
+ import { generatePath } from "../../services/templatedPaths.js";
4
+ /** Find accessible sites that match keywords provided. @see https://learn.microsoft.com/en-us/graph/api/site-search */
5
+ export default function searchSites(search) {
6
+ return operation({
7
+ method: "GET",
8
+ path: generatePath("/sites?search={search}", { search }),
9
+ headers: {},
10
+ body: null,
11
+ responseTransform: response => {
12
+ const list = response;
13
+ const sites = list.value.map(site => {
14
+ const ref = siteRef(site.id);
15
+ return {
16
+ ...site,
17
+ ...ref,
18
+ };
19
+ });
20
+ return sites;
21
+ }
22
+ });
23
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import searchSites from "./searchSites.js";
3
+ describe("searchSites", () => {
4
+ it("can find sites matching the search keyword", async () => {
5
+ const searchKeyword = "a";
6
+ const result = await searchSites(searchKeyword);
7
+ expect(result).toBeInstanceOf(Array);
8
+ expect(result.length).toBeGreaterThan(0);
9
+ });
10
+ it("returns an empty array when no sites match the search keyword", async () => {
11
+ const searchKeyword = "non-existent-keyword";
12
+ const result = await searchSites(searchKeyword);
13
+ expect(result).toBeInstanceOf(Array);
14
+ expect(result.length).toBe(0);
15
+ });
16
+ it("handles search with '/' character", async () => {
17
+ const searchKeyword = "/";
18
+ const result = await searchSites(searchKeyword);
19
+ expect(result).toBeInstanceOf(Array);
20
+ });
21
+ });
@@ -0,0 +1,20 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ /** Recalculate a workbook. @see https://learn.microsoft.com/en-us/graph/api/workbookapplication-calculate */
4
+ export default function calculateWorkbook(workbookRef, calculationType = "Recalculate") {
5
+ return operation({
6
+ method: "POST",
7
+ path: generatePath("/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/application/calculate", workbookRef),
8
+ headers: {
9
+ "content-type": "application/json",
10
+ },
11
+ body: {
12
+ calculationType
13
+ },
14
+ responseTransform: () => undefined
15
+ });
16
+ }
17
+ /** @deprecated Use calculateWorkbook instead. */
18
+ export function recalculateWorkbook(workbookRef) {
19
+ return calculateWorkbook(workbookRef, "Recalculate");
20
+ }
@@ -0,0 +1,46 @@
1
+ import { describe, it } from "vitest";
2
+ import { getDefaultDriveRef } from "../../services/drive.js";
3
+ import { driveItemPath, } from "../../services/driveItem.js";
4
+ import { generateTempFileName } from "../../services/temporaryFiles.js";
5
+ import deleteDriveItemWithRetry from "../../tasks/deleteDriveItemWithRetry.js";
6
+ import calculateWorkbook from "./calculateWorkbook.js";
7
+ import createWorkbook from "./createWorkbook.js";
8
+ describe("calculateWorkbook", () => {
9
+ // All we're really doing is check that there's no errors
10
+ it(`can calculate workbook with calculation type: 'Recalculate'`, { timeout: 10000 }, async () => {
11
+ const workbookName = generateTempFileName("xlsx");
12
+ const workbookPath = driveItemPath(workbookName);
13
+ const driveRef = getDefaultDriveRef();
14
+ const workbook = await createWorkbook(driveRef, workbookPath);
15
+ try {
16
+ await calculateWorkbook(workbook, "Recalculate");
17
+ }
18
+ finally {
19
+ await deleteDriveItemWithRetry(workbook);
20
+ }
21
+ });
22
+ it(`can calculate workbook with calculation type: 'Full'`, async () => {
23
+ const driveRef = getDefaultDriveRef();
24
+ const workbookName = generateTempFileName("xlsx");
25
+ const workbookPath = driveItemPath(workbookName);
26
+ const workbook = await createWorkbook(driveRef, workbookPath);
27
+ try {
28
+ await calculateWorkbook(workbook, "Full");
29
+ }
30
+ finally {
31
+ await deleteDriveItemWithRetry(workbook);
32
+ }
33
+ });
34
+ it(`can calculate workbook with calculation type: 'FullRebuild'`, { timeout: 10000 }, async () => {
35
+ const driveRef = getDefaultDriveRef();
36
+ const workbookName = generateTempFileName("xlsx");
37
+ const workbookPath = driveItemPath(workbookName);
38
+ const workbook = await createWorkbook(driveRef, workbookPath);
39
+ try {
40
+ await calculateWorkbook(workbook, "FullRebuild");
41
+ }
42
+ finally {
43
+ await deleteDriveItemWithRetry(workbook);
44
+ }
45
+ });
46
+ });
@@ -0,0 +1,26 @@
1
+ import InvalidArgumentError from "../../errors/InvalidArgumentError.js";
2
+ import { operation } from "../../graphApi.js";
3
+ import { driveItemRef, workbookFileExtension } from "../../services/driveItem.js";
4
+ import { generatePath } from "../../services/templatedPaths.js";
5
+ /** Create a new blank workbook. */
6
+ export default function createWorkbook(driveRef, itemPath) {
7
+ if (!itemPath.endsWith(`.${workbookFileExtension}`)) {
8
+ throw new InvalidArgumentError(`Item path must end with '.${workbookFileExtension}'`);
9
+ }
10
+ return operation({
11
+ method: "PUT",
12
+ path: generatePath(`/sites/{site-id}/drives/{drive-id}/root:${itemPath}:/content`, driveRef),
13
+ headers: {
14
+ "content-type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
15
+ },
16
+ body: null, // This is correct, Sharepoint interprets a 0-byte files as a new workbook.
17
+ responseTransform: response => {
18
+ const driveItem = response;
19
+ const itemRef = driveItemRef(driveRef, driveItem.id);
20
+ return {
21
+ ...driveItem,
22
+ ...itemRef
23
+ };
24
+ }
25
+ });
26
+ }
@@ -0,0 +1,15 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getDefaultDriveRef } from "../../services/drive.js";
3
+ import { driveItemPath } from "../../services/driveItem.js";
4
+ import { generateTempFileName } from "../../services/temporaryFiles.js";
5
+ import deleteDriveItemWithRetry from "../../tasks/deleteDriveItemWithRetry.js";
6
+ import createWorkbook from "./createWorkbook.js";
7
+ describe("createWorkbook", () => {
8
+ it("can create a new workbook", async () => {
9
+ const workbookName = generateTempFileName("xlsx");
10
+ const workbookPath = driveItemPath(workbookName);
11
+ const workbook = await createWorkbook(getDefaultDriveRef(), workbookPath);
12
+ expect(workbook.name).toBe(workbookName);
13
+ await deleteDriveItemWithRetry(workbook);
14
+ });
15
+ });
@@ -0,0 +1,5 @@
1
+ import deleteDriveItem from "../driveItem/deleteDriveItem.js";
2
+ /** Delete a workbook. @see https://learn.microsoft.com/en-us/graph/api/driveitem-delete */
3
+ export default function deleteWorkbook(workbookRef) {
4
+ return deleteDriveItem(workbookRef);
5
+ }
@@ -0,0 +1,17 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ /** Clear a range - content, formatting or both. @see https://learn.microsoft.com/en-us/graph/api/range-delete */
4
+ export default function clearWorkbookRange(rangeRef, applyTo = "All") {
5
+ return operation({
6
+ method: "POST",
7
+ path: generatePath("/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/worksheets/{worksheet-id}/range(address='{address}')/clear", rangeRef),
8
+ headers: {
9
+ "workbook-session-id": rangeRef.sessionId,
10
+ "content-type": "application/json",
11
+ },
12
+ body: {
13
+ applyTo
14
+ },
15
+ responseTransform: () => undefined
16
+ });
17
+ }
@@ -0,0 +1,56 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { sequential } from "../../graphApi.js";
3
+ import { getDefaultDriveRef } from "../../services/drive.js";
4
+ import { driveItemPath, } from "../../services/driveItem.js";
5
+ import { generateTempFileName } from "../../services/temporaryFiles.js";
6
+ import { workbookRangeRef } from "../../services/workbookRange.js";
7
+ import { defaultWorkbookWorksheetId, workbookWorksheetRef } from "../../services/workbookWorksheet.js";
8
+ import deleteDriveItemWithRetry from "../../tasks/deleteDriveItemWithRetry.js";
9
+ import calculateWorkbook from "../workbook/calculateWorkbook.js";
10
+ import createWorkbook from "../workbook/createWorkbook.js";
11
+ import getWorkbookWorksheetRange from "../workbookWorksheet/getWorkbookWorksheetRange.js";
12
+ import clearWorkbookRange from "./clearWorkbookRange.js";
13
+ import updateWorkbookRange from "./updateWorkbookRange.js";
14
+ describe("clearWorkbookRange", () => {
15
+ it("can clear a range in an existing workbook", { timeout: 10000 }, async () => {
16
+ const address = "A1:B2";
17
+ const values = [[1, 2], [3, 4]];
18
+ const workbookName = generateTempFileName("xlsx");
19
+ const workbookPath = driveItemPath(workbookName);
20
+ const driveRef = getDefaultDriveRef();
21
+ const workbook = await createWorkbook(driveRef, workbookPath);
22
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
23
+ const rangeRef = workbookRangeRef(worksheetRef, address);
24
+ try {
25
+ await updateWorkbookRange(rangeRef, {
26
+ values: values
27
+ });
28
+ await clearWorkbookRange(rangeRef);
29
+ await calculateWorkbook(workbook);
30
+ const clearedRange = await getWorkbookWorksheetRange(rangeRef);
31
+ expect(clearedRange.values).toEqual([["", ""], ["", ""]]);
32
+ }
33
+ finally {
34
+ await deleteDriveItemWithRetry(workbook);
35
+ }
36
+ });
37
+ it("can clear a range in an existing workbook sequential", { timeout: 10000 }, async () => {
38
+ const address = "A1:B2";
39
+ const values = [[1, 2], [3, 4]];
40
+ const workbookName = generateTempFileName("xlsx");
41
+ const workbookPath = driveItemPath(workbookName);
42
+ const driveRef = getDefaultDriveRef();
43
+ const workbook = await createWorkbook(driveRef, workbookPath);
44
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
45
+ const rangeRef = workbookRangeRef(worksheetRef, address);
46
+ try {
47
+ const [_, __, ___, clearedRange] = await sequential(updateWorkbookRange(rangeRef, {
48
+ values: values
49
+ }), clearWorkbookRange(rangeRef), calculateWorkbook(workbook), getWorkbookWorksheetRange(rangeRef));
50
+ expect(clearedRange.values).toEqual([["", ""], ["", ""]]);
51
+ }
52
+ finally {
53
+ await deleteDriveItemWithRetry(workbook);
54
+ }
55
+ });
56
+ });
@@ -0,0 +1,17 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ /** Delete a range. @see https://learn.microsoft.com/en-us/graph/api/range-clear */
4
+ export default function deleteWorkbookRange(rangeRef, shift) {
5
+ return operation({
6
+ method: "POST",
7
+ path: generatePath("/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/worksheets/{worksheet-id}/range(address='{address}')/delete", rangeRef),
8
+ headers: {
9
+ "workbook-session-id": rangeRef.sessionId,
10
+ "content-type": "application/json",
11
+ },
12
+ body: {
13
+ shift
14
+ },
15
+ responseTransform: () => undefined
16
+ });
17
+ }
@@ -0,0 +1,56 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { sequential } from "../../graphApi.js";
3
+ import { getDefaultDriveRef } from "../../services/drive.js";
4
+ import { driveItemPath, } from "../../services/driveItem.js";
5
+ import { generateTempFileName } from "../../services/temporaryFiles.js";
6
+ import { workbookRangeRef } from "../../services/workbookRange.js";
7
+ import { defaultWorkbookWorksheetId, workbookWorksheetRef } from "../../services/workbookWorksheet.js";
8
+ import deleteDriveItemWithRetry from "../../tasks/deleteDriveItemWithRetry.js";
9
+ import calculateWorkbook from "../workbook/calculateWorkbook.js";
10
+ import createWorkbook from "../workbook/createWorkbook.js";
11
+ import getWorkbookWorksheetRange from "../workbookWorksheet/getWorkbookWorksheetRange.js";
12
+ import deleteWorkbookRange from "./deleteWorkbookRange.js";
13
+ import updateWorkbookRange from "./updateWorkbookRange.js";
14
+ describe("deleteWorkbookRange", () => {
15
+ it("can delete a range in an existing workbook", { timeout: 10000 }, async () => {
16
+ const address = "A1:B2";
17
+ const values = [[1, 2], [3, 4]];
18
+ const workbookName = generateTempFileName("xlsx");
19
+ const workbookPath = driveItemPath(workbookName);
20
+ const driveRef = getDefaultDriveRef();
21
+ const workbook = await createWorkbook(driveRef, workbookPath);
22
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
23
+ const rangeRef = workbookRangeRef(worksheetRef, address);
24
+ try {
25
+ await updateWorkbookRange(rangeRef, {
26
+ values: values
27
+ });
28
+ await deleteWorkbookRange(rangeRef, "Up");
29
+ await calculateWorkbook(workbook);
30
+ const deletedRange = await getWorkbookWorksheetRange(rangeRef);
31
+ expect(deletedRange.values).toEqual([["", ""], ["", ""]]);
32
+ }
33
+ finally {
34
+ await deleteDriveItemWithRetry(workbook);
35
+ }
36
+ });
37
+ it("can delete a range in an existing workbook sequential", { timeout: 10000 }, async () => {
38
+ const address = "A1:B2";
39
+ const values = [[1, 2], [3, 4]];
40
+ const workbookName = generateTempFileName("xlsx");
41
+ const workbookPath = driveItemPath(workbookName);
42
+ const driveRef = getDefaultDriveRef();
43
+ const workbook = await createWorkbook(driveRef, workbookPath);
44
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
45
+ const rangeRef = workbookRangeRef(worksheetRef, address);
46
+ try {
47
+ const [_, __, ___, deletedRange] = await sequential(updateWorkbookRange(rangeRef, {
48
+ values: values
49
+ }), deleteWorkbookRange(rangeRef, "Up"), calculateWorkbook(workbook), getWorkbookWorksheetRange(rangeRef));
50
+ expect(deletedRange.values).toEqual([["", ""], ["", ""]]);
51
+ }
52
+ finally {
53
+ await deleteDriveItemWithRetry(workbook);
54
+ }
55
+ });
56
+ });
@@ -0,0 +1,20 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ /** Retrieve range that has been defined using the "named range" functionality. @see https://learn.microsoft.com/en-us/graph/api/range-get */
4
+ export default function getWorkbookNamedRange(rangeRef) {
5
+ return operation({
6
+ method: "GET",
7
+ path: generatePath("/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/names/{range-name}/range", rangeRef),
8
+ headers: {
9
+ "workbook-session-id": rangeRef.sessionId,
10
+ },
11
+ body: null,
12
+ responseTransform: response => {
13
+ const range = response;
14
+ return {
15
+ ...range,
16
+ ...rangeRef
17
+ };
18
+ }
19
+ });
20
+ }
@@ -0,0 +1,22 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ import { workbookRangeRef } from "../../services/workbookRange.js";
4
+ /** Retrieve the used range in a worksheet, ignoring trailing rows and columns that are blank. @see https://learn.microsoft.com/en-us/graph/api/range-usedrange */
5
+ export default function getWorkbookUsedRange(worksheetRef) {
6
+ return operation({
7
+ method: "GET",
8
+ path: generatePath("/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/worksheets/{worksheet-id}/range/usedRange", worksheetRef),
9
+ headers: {
10
+ "workbook-session-id": worksheetRef.sessionId,
11
+ },
12
+ body: null,
13
+ responseTransform: response => {
14
+ const range = response;
15
+ const rangeRef = workbookRangeRef(worksheetRef, range.address);
16
+ return {
17
+ ...range,
18
+ ...rangeRef
19
+ };
20
+ }
21
+ });
22
+ }
@@ -0,0 +1,54 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { sequential } from "../../graphApi.js";
3
+ import { getDefaultDriveRef } from "../../services/drive.js";
4
+ import { driveItemPath, } from "../../services/driveItem.js";
5
+ import { generateTempFileName } from "../../services/temporaryFiles.js";
6
+ import { workbookRangeRef } from "../../services/workbookRange.js";
7
+ import { defaultWorkbookWorksheetId, workbookWorksheetRef } from "../../services/workbookWorksheet.js";
8
+ import deleteDriveItemWithRetry from "../../tasks/deleteDriveItemWithRetry.js";
9
+ import calculateWorkbook from "../workbook/calculateWorkbook.js";
10
+ import createWorkbook from "../workbook/createWorkbook.js";
11
+ import getWorkbookUsedRange from "./getWorkbookUsedRange.js";
12
+ import updateWorkbookRange from "./updateWorkbookRange.js";
13
+ describe("getWorkbookUsedRange", { timeout: 10000 }, () => {
14
+ it("can retrieve the used range from an existing workbook", { timeout: 10000 }, async () => {
15
+ const address = "A1:B2";
16
+ const values = [[1, 2], [3, 4]];
17
+ const workbookName = generateTempFileName("xlsx");
18
+ const workbookPath = driveItemPath(workbookName);
19
+ const driveRef = getDefaultDriveRef();
20
+ const workbook = await createWorkbook(driveRef, workbookPath);
21
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
22
+ const rangeRef = workbookRangeRef(worksheetRef, address);
23
+ try {
24
+ await updateWorkbookRange(rangeRef, {
25
+ values: values
26
+ });
27
+ await calculateWorkbook(workbook);
28
+ const usedRange = await getWorkbookUsedRange(worksheetRef);
29
+ expect(usedRange.values).toEqual(values);
30
+ }
31
+ finally {
32
+ await deleteDriveItemWithRetry(workbook);
33
+ }
34
+ });
35
+ it("can retrieve the used range from an existing workbook sequential", { timeout: 10000 }, async () => {
36
+ const address = "A1:B2";
37
+ const values = [[1, 2], [3, 4]];
38
+ const workbookName = generateTempFileName("xlsx");
39
+ const workbookPath = driveItemPath(workbookName);
40
+ const driveRef = getDefaultDriveRef();
41
+ const workbook = await createWorkbook(driveRef, workbookPath);
42
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
43
+ const rangeRef = workbookRangeRef(worksheetRef, address);
44
+ try {
45
+ const [_, __, usedRange] = await sequential(updateWorkbookRange(rangeRef, {
46
+ values: values
47
+ }), calculateWorkbook(workbook), getWorkbookUsedRange(worksheetRef));
48
+ expect(usedRange.values).toEqual(values);
49
+ }
50
+ finally {
51
+ await deleteDriveItemWithRetry(workbook);
52
+ }
53
+ });
54
+ });
@@ -0,0 +1,20 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ /** Retrieve the visible view of a range. @see https://learn.microsoft.com/en-us/graph/api/workbookrange-visibleview */
4
+ export default function getWorkbookVisibleRange(rangeRef) {
5
+ return operation({
6
+ method: "GET",
7
+ path: generatePath(`/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/worksheets/{worksheet-id}/range(address='${rangeRef.address}')/visibleView`, rangeRef),
8
+ headers: {
9
+ "workbook-session-id": rangeRef.sessionId,
10
+ },
11
+ body: null,
12
+ responseTransform: response => {
13
+ const range = response;
14
+ return {
15
+ ...range,
16
+ ...rangeRef
17
+ };
18
+ }
19
+ });
20
+ }
@@ -0,0 +1,109 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { sequential } from "../../graphApi.js";
3
+ import { getDefaultDriveRef } from "../../services/drive.js";
4
+ import { driveItemPath, } from "../../services/driveItem.js";
5
+ import { generateTempFileName } from "../../services/temporaryFiles.js";
6
+ import { workbookRangeRef } from "../../services/workbookRange.js";
7
+ import { defaultWorkbookWorksheetId, workbookWorksheetRef } from "../../services/workbookWorksheet.js";
8
+ import deleteDriveItemWithRetry from "../../tasks/deleteDriveItemWithRetry.js";
9
+ import calculateWorkbook from "../workbook/calculateWorkbook.js";
10
+ import createWorkbook from "../workbook/createWorkbook.js";
11
+ import getWorkbookVisibleRange from "./getWorkbookVisibleRange.js";
12
+ import updateWorkbookRange from "./updateWorkbookRange.js";
13
+ describe("getWorkbookRangeVisible", () => {
14
+ it("can retrieve the visible view of a range in an existing workbook", { timeout: 10000 }, async () => {
15
+ const address = "A1:B2";
16
+ const values = [[1, 2], [3, 4]];
17
+ const workbookName = generateTempFileName("xlsx");
18
+ const workbookPath = driveItemPath(workbookName);
19
+ const driveRef = getDefaultDriveRef();
20
+ const workbook = await createWorkbook(driveRef, workbookPath);
21
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
22
+ const rangeRef = workbookRangeRef(worksheetRef, address);
23
+ try {
24
+ await updateWorkbookRange(rangeRef, { values: values });
25
+ await calculateWorkbook(workbook);
26
+ const visibleView = await getWorkbookVisibleRange(rangeRef);
27
+ expect(visibleView).toBeDefined();
28
+ }
29
+ finally {
30
+ await deleteDriveItemWithRetry(workbook);
31
+ }
32
+ });
33
+ it("can retrieve the visible view of a range in an existing workbook sequential", { timeout: 10000 }, async () => {
34
+ const address = "A1:B2";
35
+ const values = [[1, 2], [3, 4]];
36
+ const workbookName = generateTempFileName("xlsx");
37
+ const workbookPath = driveItemPath(workbookName);
38
+ const driveRef = getDefaultDriveRef();
39
+ const workbook = await createWorkbook(driveRef, workbookPath);
40
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
41
+ const rangeRef = workbookRangeRef(worksheetRef, address);
42
+ try {
43
+ const [_, __, visibleView] = await sequential(updateWorkbookRange(rangeRef, { values: values }), calculateWorkbook(workbook), getWorkbookVisibleRange(rangeRef));
44
+ expect(visibleView).toBeDefined();
45
+ }
46
+ finally {
47
+ await deleteDriveItemWithRetry(workbook);
48
+ }
49
+ });
50
+ it("omits hidden row from the visible view of a range", { timeout: 10000 }, async () => {
51
+ const workbookName = generateTempFileName("xlsx");
52
+ const workbookPath = driveItemPath(workbookName);
53
+ const driveRef = getDefaultDriveRef();
54
+ const workbook = await createWorkbook(driveRef, workbookPath);
55
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
56
+ try {
57
+ const rangeRef = workbookRangeRef(worksheetRef, "A1:C3");
58
+ await updateWorkbookRange(rangeRef, {
59
+ values: [
60
+ [1, 2, 3],
61
+ [4, 5, 6],
62
+ [7, 8, 9]
63
+ ]
64
+ });
65
+ const hiddenRange = workbookRangeRef(worksheetRef, "B:B");
66
+ await updateWorkbookRange(hiddenRange, {
67
+ columnHidden: true
68
+ });
69
+ await calculateWorkbook(workbook);
70
+ const visibleView = await getWorkbookVisibleRange(rangeRef);
71
+ expect(visibleView.values).toEqual([
72
+ [1, 3],
73
+ [4, 6],
74
+ [7, 9]
75
+ ]);
76
+ }
77
+ finally {
78
+ await deleteDriveItemWithRetry(workbook);
79
+ }
80
+ });
81
+ it("omits hidden column from the visible view of a range", { timeout: 10000 }, async () => {
82
+ const workbookName = generateTempFileName("xlsx");
83
+ const workbookPath = driveItemPath(workbookName);
84
+ const driveRef = getDefaultDriveRef();
85
+ const workbook = await createWorkbook(driveRef, workbookPath);
86
+ const worksheetRef = workbookWorksheetRef(workbook, defaultWorkbookWorksheetId);
87
+ try {
88
+ const rangeRef = workbookRangeRef(worksheetRef, "A1:C3");
89
+ await updateWorkbookRange(rangeRef, {
90
+ values: [
91
+ [1, 2, 3],
92
+ [4, 5, 6],
93
+ [7, 8, 9]
94
+ ]
95
+ });
96
+ const hiddenRange = workbookRangeRef(worksheetRef, "2:2");
97
+ const [_, __, visibleView] = await sequential(updateWorkbookRange(hiddenRange, {
98
+ rowHidden: true
99
+ }), calculateWorkbook(workbook), getWorkbookVisibleRange(rangeRef));
100
+ expect(visibleView.values).toEqual([
101
+ [1, 2, 3],
102
+ [7, 8, 9]
103
+ ]);
104
+ }
105
+ finally {
106
+ await deleteDriveItemWithRetry(workbook);
107
+ }
108
+ });
109
+ });
@@ -0,0 +1,25 @@
1
+ import { operation } from "../../graphApi.js";
2
+ import { generatePath } from "../../services/templatedPaths.js";
3
+ import { workbookRangeRef } from "../../services/workbookRange.js";
4
+ /** Insert a new blank range at a specified address, shifting existing cells. Use `updateRange` after to set content. @see https://learn.microsoft.com/en-us/graph/api/range-insert */
5
+ export default function insertWorkbookCells(worksheetRef, address, shift) {
6
+ return operation({
7
+ method: "POST",
8
+ path: generatePath(`/sites/{site-id}/drives/{drive-id}/items/{item-id}/workbook/worksheets/{worksheet-id}/range(address='${address}')/insert`, worksheetRef),
9
+ headers: {
10
+ "workbook-session-id": worksheetRef.sessionId,
11
+ "content-type": "application/json",
12
+ },
13
+ body: {
14
+ shift
15
+ },
16
+ responseTransform: response => {
17
+ const workbook = response;
18
+ const rangeRef = workbookRangeRef(worksheetRef, workbook.address);
19
+ return {
20
+ ...workbook,
21
+ ...rangeRef
22
+ };
23
+ }
24
+ });
25
+ }