@wokuapp/sdk 0.4.0 → 0.5.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.
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ var FollowUps = class {
36
36
  };
37
37
 
38
38
  // package.json
39
- var version = "0.4.0";
39
+ var version = "0.5.0";
40
40
 
41
41
  // src/core/errors.ts
42
42
  var WokuError = class extends Error {
@@ -383,7 +383,8 @@ var WokuClient = class {
383
383
  headers,
384
384
  bodyText,
385
385
  timeout,
386
- args.signal
386
+ args.signal,
387
+ args.binary
387
388
  );
388
389
  if (status >= 200 && status < 300) {
389
390
  return body;
@@ -500,7 +501,7 @@ var WokuClient = class {
500
501
  }
501
502
  return headers;
502
503
  }
503
- async send(url, method, headers, body, timeout, signal) {
504
+ async send(url, method, headers, body, timeout, signal, binary) {
504
505
  if (signal?.aborted)
505
506
  throw new WokuConnectionError("Request aborted", { code: "aborted" });
506
507
  const controller = new AbortController();
@@ -521,6 +522,20 @@ var WokuClient = class {
521
522
  body,
522
523
  signal: controller.signal
523
524
  });
525
+ if (binary && response.status >= 200 && response.status < 300) {
526
+ if (!response.arrayBuffer) {
527
+ throw new WokuError(
528
+ "The fetch implementation cannot read binary responses.",
529
+ { code: "config_error" }
530
+ );
531
+ }
532
+ return {
533
+ status: response.status,
534
+ body: new Uint8Array(await response.arrayBuffer()),
535
+ requestId: requestIdFrom(response.headers),
536
+ retryAfterSeconds: retryAfterFromHeaders(response.headers)
537
+ };
538
+ }
524
539
  const text = await response.text();
525
540
  return {
526
541
  status: response.status,
@@ -719,6 +734,14 @@ var NpsTools = class {
719
734
  }
720
735
  );
721
736
  }
737
+ /** Move the tool into a folder, or to the root with `folderId: null`. */
738
+ move(id, body, opts) {
739
+ return this.client.request(
740
+ "patch",
741
+ `/v1/nps-tools/${encodeURIComponent(id)}/move`,
742
+ { ...opts, body }
743
+ );
744
+ }
722
745
  delete(id, opts) {
723
746
  return this.client.request(
724
747
  "delete",
@@ -758,6 +781,14 @@ var CsatTools = class {
758
781
  }
759
782
  );
760
783
  }
784
+ /** Move the tool into a folder, or to the root with `folderId: null`. */
785
+ move(id, body, opts) {
786
+ return this.client.request(
787
+ "patch",
788
+ `/v1/csat-tools/${encodeURIComponent(id)}/move`,
789
+ { ...opts, body }
790
+ );
791
+ }
761
792
  delete(id, opts) {
762
793
  return this.client.request(
763
794
  "delete",
@@ -797,6 +828,14 @@ var CesTools = class {
797
828
  }
798
829
  );
799
830
  }
831
+ /** Move the tool into a folder, or to the root with `folderId: null`. */
832
+ move(id, body, opts) {
833
+ return this.client.request(
834
+ "patch",
835
+ `/v1/ces-tools/${encodeURIComponent(id)}/move`,
836
+ { ...opts, body }
837
+ );
838
+ }
800
839
  delete(id, opts) {
801
840
  return this.client.request(
802
841
  "delete",
@@ -1014,9 +1053,11 @@ var Flows = class {
1014
1053
  constructor(client) {
1015
1054
  this.client = client;
1016
1055
  }
1056
+ /** List the flows of the company, with their ordered `steps`. */
1017
1057
  list(params, opts) {
1018
1058
  return this.client.getPage("/v1/flows", params, opts);
1019
1059
  }
1060
+ /** The data of a flow: ordered steps with their tools, wokus and branding. */
1020
1061
  get(id, opts) {
1021
1062
  return this.client.request(
1022
1063
  "get",
@@ -1024,6 +1065,33 @@ var Flows = class {
1024
1065
  opts
1025
1066
  );
1026
1067
  }
1068
+ /**
1069
+ * Create a flow from 1 to 20 ordered steps (each tool once, all of your
1070
+ * company). Flows live outside folders.
1071
+ */
1072
+ create(body, opts) {
1073
+ return this.client.request("post", "/v1/flows", {
1074
+ ...opts,
1075
+ body,
1076
+ idempotent: true
1077
+ });
1078
+ }
1079
+ /** Rename a flow or replace its full ordered list of steps. */
1080
+ update(id, body, opts) {
1081
+ return this.client.request(
1082
+ "patch",
1083
+ `/v1/flows/${encodeURIComponent(id)}`,
1084
+ { ...opts, body }
1085
+ );
1086
+ }
1087
+ /** Delete a flow. Its tools and their responses stay. */
1088
+ delete(id, opts) {
1089
+ return this.client.request(
1090
+ "delete",
1091
+ `/v1/flows/${encodeURIComponent(id)}`,
1092
+ opts
1093
+ );
1094
+ }
1027
1095
  };
1028
1096
 
1029
1097
  // src/resources/action-plans.ts
@@ -1521,6 +1589,240 @@ var Quarantines = class {
1521
1589
  }
1522
1590
  };
1523
1591
 
1592
+ // src/resources/folders.ts
1593
+ var Folders = class {
1594
+ constructor(client) {
1595
+ this.client = client;
1596
+ }
1597
+ /** Every folder of the company, or the direct subfolders of `parentFolderId`. */
1598
+ list(params, opts) {
1599
+ return this.client.request("get", "/v1/folders", {
1600
+ ...opts,
1601
+ query: { ...params, ...opts?.query }
1602
+ });
1603
+ }
1604
+ get(id, opts) {
1605
+ return this.client.request(
1606
+ "get",
1607
+ `/v1/folders/${encodeURIComponent(id)}`,
1608
+ opts
1609
+ );
1610
+ }
1611
+ create(body, opts) {
1612
+ return this.client.request("post", "/v1/folders", {
1613
+ ...opts,
1614
+ body,
1615
+ idempotent: true
1616
+ });
1617
+ }
1618
+ /**
1619
+ * Rename or recolor a folder (`color: null` clears the color) and/or replace
1620
+ * its WhatsApp alert recipients (`whatsappAlertRecipients`, `[]` clears them).
1621
+ */
1622
+ update(id, body, opts) {
1623
+ return this.client.request(
1624
+ "patch",
1625
+ `/v1/folders/${encodeURIComponent(id)}`,
1626
+ { ...opts, body }
1627
+ );
1628
+ }
1629
+ /**
1630
+ * Move a folder under another folder, or to the root with
1631
+ * `parentFolderId: null`. A folder cannot move into its own subtree.
1632
+ */
1633
+ move(id, body, opts) {
1634
+ return this.client.request(
1635
+ "patch",
1636
+ `/v1/folders/${encodeURIComponent(id)}/move`,
1637
+ { ...opts, body }
1638
+ );
1639
+ }
1640
+ /**
1641
+ * Delete a folder. Nothing inside is deleted: subfolders, wokus and tools
1642
+ * move up to the parent folder (or the root).
1643
+ */
1644
+ delete(id, opts) {
1645
+ return this.client.request(
1646
+ "delete",
1647
+ `/v1/folders/${encodeURIComponent(id)}`,
1648
+ opts
1649
+ );
1650
+ }
1651
+ /**
1652
+ * AI report over every woku, NPS, CSAT and CES tool of the folder and its
1653
+ * subfolders. Scales differ per type, so there is no rating distribution.
1654
+ */
1655
+ report(id, params, opts) {
1656
+ return this.client.request(
1657
+ "get",
1658
+ `/v1/folders/${encodeURIComponent(id)}/report`,
1659
+ { ...opts, query: { ...params, ...opts?.query } }
1660
+ );
1661
+ }
1662
+ /**
1663
+ * Per-tool figures of the woku, NPS, CSAT and CES tools of the folder and its
1664
+ * subfolders for a period against the one before it, with the daily sums and
1665
+ * the histogram of scores. `days` is 7, 30 (default) or 90, or 0 for the whole
1666
+ * history (every `previous` window is then empty). The period is the last
1667
+ * `days` calendar days in UTC, today included. Scales are never mixed across
1668
+ * types.
1669
+ */
1670
+ metrics(id, params, opts) {
1671
+ return this.client.request(
1672
+ "get",
1673
+ `/v1/folders/${encodeURIComponent(id)}/metrics`,
1674
+ { ...opts, query: { ...params, ...opts?.query } }
1675
+ );
1676
+ }
1677
+ /** CSV text with one row per response of every tool of the folder subtree. */
1678
+ csv(id, opts) {
1679
+ return this.client.request(
1680
+ "get",
1681
+ `/v1/folders/${encodeURIComponent(id)}/csv`,
1682
+ opts
1683
+ );
1684
+ }
1685
+ /**
1686
+ * PDF of the folder report (every woku, NPS, CSAT and CES tool of the folder
1687
+ * and its subfolders) with a breakdown per type on each native scale.
1688
+ * Returns the file bytes: write them to disk or send them as is.
1689
+ */
1690
+ pdf(id, params, opts) {
1691
+ return this.client.request(
1692
+ "get",
1693
+ `/v1/folders/${encodeURIComponent(id)}/pdf`,
1694
+ {
1695
+ ...opts,
1696
+ headers: { Accept: "application/pdf", ...opts?.headers },
1697
+ query: { ...params, ...opts?.query },
1698
+ binary: true
1699
+ }
1700
+ );
1701
+ }
1702
+ };
1703
+
1704
+ // src/resources/tools.ts
1705
+ var ToolsPage = class {
1706
+ constructor(response, fetchNext, fetchMoreFolders = () => Promise.reject(new RangeError("No more folders"))) {
1707
+ this.fetchNext = fetchNext;
1708
+ this.fetchMoreFolders = fetchMoreFolders;
1709
+ this.folders = response.folders;
1710
+ this.tools = response.tools;
1711
+ this.nextCursor = response.nextCursor;
1712
+ this.foldersNextCursor = response.foldersNextCursor ?? null;
1713
+ this.facets = response.facets;
1714
+ }
1715
+ hasMoreFolders() {
1716
+ return this.foldersNextCursor !== null;
1717
+ }
1718
+ /** The next page of folders ("see more"): a page with those folders and no tools. */
1719
+ getMoreFolders() {
1720
+ if (this.foldersNextCursor === null)
1721
+ throw new RangeError("No more folders");
1722
+ return this.fetchMoreFolders(this.foldersNextCursor);
1723
+ }
1724
+ hasNextPage() {
1725
+ return this.nextCursor !== null;
1726
+ }
1727
+ getNextPage() {
1728
+ if (this.nextCursor === null) throw new RangeError("No next page");
1729
+ return this.fetchNext(this.nextCursor);
1730
+ }
1731
+ async *iterPages() {
1732
+ yield this;
1733
+ if (this.hasNextPage()) yield* (await this.getNextPage()).iterPages();
1734
+ }
1735
+ async *[Symbol.asyncIterator]() {
1736
+ for await (const page of this.iterPages()) {
1737
+ for (const tool of page.tools) yield tool;
1738
+ }
1739
+ }
1740
+ };
1741
+ var Tools = class {
1742
+ constructor(client) {
1743
+ this.client = client;
1744
+ }
1745
+ /**
1746
+ * List one folder level (or search the company). Folders and tools of every
1747
+ * type come together; the first page also carries the folders and facets.
1748
+ */
1749
+ async list(params, opts) {
1750
+ const fetchPage = async (cursor, foldersCursor) => {
1751
+ const response = await this.client.request(
1752
+ "get",
1753
+ "/v1/tools",
1754
+ {
1755
+ ...opts,
1756
+ query: {
1757
+ ...params,
1758
+ types: params?.types?.join(","),
1759
+ ...cursor ? { cursor } : {},
1760
+ ...foldersCursor ? { foldersCursor } : {},
1761
+ ...opts?.query
1762
+ }
1763
+ }
1764
+ );
1765
+ return new ToolsPage(
1766
+ response,
1767
+ fetchPage,
1768
+ (next) => fetchPage(void 0, next)
1769
+ );
1770
+ };
1771
+ return fetchPage();
1772
+ }
1773
+ /**
1774
+ * Headline figures per type (woku stars, NPS score, CSAT satisfied %, CES
1775
+ * mean) for the company or one folder and its subfolders, in a period.
1776
+ * A type that fails reports `{ error: true }`; the others stay valid.
1777
+ */
1778
+ stats(params, opts) {
1779
+ return this.client.request("get", "/v1/tools/stats", {
1780
+ ...opts,
1781
+ query: { ...params, ...opts?.query }
1782
+ });
1783
+ }
1784
+ /**
1785
+ * Move up to 200 items of mixed types (`woku`, `nps`, `csat`, `ces`,
1786
+ * `folder`) into a folder, or to the root with `folderId: null`. Idempotent;
1787
+ * nothing moves if one item or the destination is not found.
1788
+ */
1789
+ move(body, opts) {
1790
+ return this.client.request("post", "/v1/tools/move", {
1791
+ ...opts,
1792
+ body
1793
+ });
1794
+ }
1795
+ };
1796
+
1797
+ // src/resources/journey-folders.ts
1798
+ var JourneyFolders = class {
1799
+ constructor(client) {
1800
+ this.client = client;
1801
+ }
1802
+ /** Whether the organization is on, running, and how much is still without a folder. */
1803
+ status(opts) {
1804
+ return this.client.request(
1805
+ "get",
1806
+ "/v1/journey-folders",
1807
+ opts
1808
+ );
1809
+ }
1810
+ /**
1811
+ * Switch the organization on and run the one-off pass in the background: tools
1812
+ * of existing journeys without a folder move into their moment folder, and
1813
+ * tools journeys create from now on are placed there. Tools that already have
1814
+ * a folder are never touched. Rejects with a conflict (409) while a pass is
1815
+ * already running; poll {@link status} for progress.
1816
+ */
1817
+ organize(opts) {
1818
+ return this.client.request(
1819
+ "post",
1820
+ "/v1/journey-folders/organize",
1821
+ opts
1822
+ );
1823
+ }
1824
+ };
1825
+
1524
1826
  // src/woku.ts
1525
1827
  var Woku = class {
1526
1828
  constructor(options) {
@@ -1546,10 +1848,13 @@ var Woku = class {
1546
1848
  this.reports = new Reports(this.client);
1547
1849
  this.company = new Company(this.client);
1548
1850
  this.journeys = new Journeys(this.client);
1851
+ this.folders = new Folders(this.client);
1852
+ this.tools = new Tools(this.client);
1853
+ this.journeyFolders = new JourneyFolders(this.client);
1549
1854
  this.quarantines = new Quarantines(this.client);
1550
1855
  }
1551
1856
  };
1552
1857
 
1553
- export { AuthenticationError, BadRequestError, ConflictError, FollowUps, InternalServerError, Journeys, Media, NotFoundError, Page, PayloadTooLargeError, PermissionDeniedError, RateLimitError, UnprocessableEntityError, Woku, WokuAPIError, WokuClient, WokuConnectionError, WokuError, WokuTimeoutError };
1858
+ export { AuthenticationError, BadRequestError, ConflictError, Folders, FollowUps, InternalServerError, JourneyFolders, Journeys, Media, NotFoundError, Page, PayloadTooLargeError, PermissionDeniedError, RateLimitError, Tools, ToolsPage, UnprocessableEntityError, Woku, WokuAPIError, WokuClient, WokuConnectionError, WokuError, WokuTimeoutError };
1554
1859
  //# sourceMappingURL=index.js.map
1555
1860
  //# sourceMappingURL=index.js.map