@uipath/insights-sdk 1.204.0 → 1.205.0-preview.258

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.
@@ -287,6 +287,19 @@ var KNOWN_ERROR_LABELS = new Set([
287
287
  DASHBOARD_NOT_FOUND_LABEL,
288
288
  MODEL_NOT_FOUND_LABEL
289
289
  ]);
290
+ var PORTAL_ERROR_CODE = {
291
+ InvalidUserInput: 6,
292
+ LookerUnavailableError: 8,
293
+ PermissionsUserUnauthorized: 10,
294
+ UnableToGetEmbedLink: 23,
295
+ UnableToRetrieveDashboards: 26
296
+ };
297
+ var LOOKER_USER_UNAVAILABLE_MESSAGE = "Unable to get Looker userInfo";
298
+ var LOOKER_NO_DASHBOARDS_MESSAGE = "Unable to retrieve dashboards";
299
+ var KNOWN_PORTAL_ERROR_MESSAGES = new Set([
300
+ LOOKER_USER_UNAVAILABLE_MESSAGE,
301
+ LOOKER_NO_DASHBOARDS_MESSAGE
302
+ ]);
290
303
 
291
304
  class InsightsHttpError extends Error {
292
305
  status;
@@ -385,7 +398,9 @@ var ErrorDimensions = {
385
398
  Result: "Result",
386
399
  ErrorCode: "ErrorCode",
387
400
  Retry: "Retry",
388
- ErrorMessage: "ErrorMessage"
401
+ ErrorMessage: "ErrorMessage",
402
+ HttpStatus: "HttpStatus",
403
+ UpstreamErrorCode: "UpstreamErrorCode"
389
404
  };
390
405
  var AuthDimensions = {
391
406
  AuthenticationMethod: "AuthenticationMethod",
@@ -489,7 +504,7 @@ var package_default = {
489
504
  name: "@uipath/insights-sdk",
490
505
  author: "UiPath",
491
506
  license: "SEE LICENSE IN LICENSE.txt",
492
- version: "1.204.0",
507
+ version: "1.205.0-preview.258",
493
508
  description: "SDK for the UiPath Insights API — jobs, failures, and performance metrics.",
494
509
  repository: {
495
510
  type: "git",
@@ -694,6 +709,16 @@ var INSIGHTS_ROUTES = {
694
709
  method: "POST",
695
710
  template: "Authorization/tenant/insights"
696
711
  },
712
+ lookerDashboardsList: {
713
+ service: "portal",
714
+ method: "GET",
715
+ template: "AllDashboards/folders"
716
+ },
717
+ lookerDashboardEmbedUrl: {
718
+ service: "portal",
719
+ method: "POST",
720
+ template: "DashboardUrl"
721
+ },
697
722
  exportConfigurationsList: {
698
723
  service: "portal",
699
724
  method: "GET",
@@ -795,9 +820,43 @@ function buildServiceHeaders(config, route, hasBody) {
795
820
  return headers;
796
821
  }
797
822
  var MODEL_PATH_PATTERN = /^[A-Za-z0-9_.[\]]{1,200}$/;
823
+ var MAX_PORTAL_ERROR_CODE = 999;
824
+ function isJsonObject(value) {
825
+ return typeof value === "object" && value !== null && !Array.isArray(value);
826
+ }
827
+ function readPortalErrorCode(error) {
828
+ if (!isJsonObject(error)) {
829
+ return;
830
+ }
831
+ const code = error.errorCode;
832
+ if (typeof code !== "number" || !Number.isInteger(code) || code < 0 || code > MAX_PORTAL_ERROR_CODE) {
833
+ return;
834
+ }
835
+ return code;
836
+ }
837
+ function readPortalErrorMessage(error) {
838
+ if (!isJsonObject(error)) {
839
+ return;
840
+ }
841
+ const message = error.message;
842
+ if (typeof message !== "string" || !KNOWN_PORTAL_ERROR_MESSAGES.has(message)) {
843
+ return;
844
+ }
845
+ return message;
846
+ }
847
+ function liftPortalError(hint, error) {
848
+ const portalErrorCode = readPortalErrorCode(error);
849
+ if (portalErrorCode !== undefined) {
850
+ hint.portalErrorCode = portalErrorCode;
851
+ }
852
+ const portalErrorMessage = readPortalErrorMessage(error);
853
+ if (portalErrorMessage !== undefined) {
854
+ hint.portalErrorMessage = portalErrorMessage;
855
+ }
856
+ }
798
857
  function describeJsonErrorBody(parsed) {
799
858
  if (typeof parsed === "string") {
800
- return { shape: "string" };
859
+ return describeStringErrorBody(parsed);
801
860
  }
802
861
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
803
862
  return { shape: "other" };
@@ -817,6 +876,19 @@ function describeJsonErrorBody(parsed) {
817
876
  hint.firstInvalidField = firstKey;
818
877
  }
819
878
  }
879
+ liftPortalError(hint, record.error);
880
+ return hint;
881
+ }
882
+ function describeStringErrorBody(parsed) {
883
+ const hint = { shape: "string" };
884
+ const [parseError, inner] = catchError(() => JSON.parse(parsed));
885
+ if (parseError) {
886
+ return hint;
887
+ }
888
+ if (!isJsonObject(inner)) {
889
+ return hint;
890
+ }
891
+ liftPortalError(hint, inner.error);
820
892
  return hint;
821
893
  }
822
894
  function describeErrorBody(text) {
@@ -1410,6 +1482,151 @@ async function listQueueFilters(config) {
1410
1482
  async function listMachineFilters(config) {
1411
1483
  return listFilters(config, "filtersAllMachines", isMachineFiltersResponse, "machine filters");
1412
1484
  }
1485
+ // src/looker-dashboards.ts
1486
+ var TEMPLATE_ID_DELIMITER = "::";
1487
+ var INTEGER_ID_PATTERN = /^\d+$/;
1488
+ var LOOKER_FOLDERS = [
1489
+ "personal",
1490
+ "tenant",
1491
+ "templates",
1492
+ "organization"
1493
+ ];
1494
+ var LOOKER_THEMES = ["light", "dark"];
1495
+ async function listLookerDashboards(config) {
1496
+ return requestInsightsRoute(config, "lookerDashboardsList");
1497
+ }
1498
+ async function getLookerDashboardEmbedUrl(config, options) {
1499
+ const dashboardId = options.dashboardId.trim();
1500
+ if (dashboardId === "") {
1501
+ throw new Error("Insights Looker dashboard id must not be empty.");
1502
+ }
1503
+ if (!isDashboardId(dashboardId)) {
1504
+ throw new Error("Insights Looker dashboard id must be all digits or contain '::'; resolve a title with resolveLookerDashboard first.");
1505
+ }
1506
+ if (!LOOKER_THEMES.includes(options.theme)) {
1507
+ throw new Error(`Insights Looker theme must be one of ${LOOKER_THEMES.join(", ")}.`);
1508
+ }
1509
+ const locale = options.localization?.trim();
1510
+ if (locale === "") {
1511
+ throw new Error("Insights Looker localization must not be empty.");
1512
+ }
1513
+ return requestInsightsRoute(config, "lookerDashboardEmbedUrl", {
1514
+ body: {
1515
+ dashboardId,
1516
+ theme: options.theme,
1517
+ ...locale === undefined ? {} : { locale }
1518
+ }
1519
+ });
1520
+ }
1521
+ function parseLookerEnvelope(raw, routeKey) {
1522
+ const endpoint = insightsRouteTemplate(routeKey);
1523
+ if (typeof raw !== "string") {
1524
+ throw new InsightsProtocolError(endpoint, "the body is not the JSON string literal this root answers with");
1525
+ }
1526
+ const [parseError, envelope] = catchError(() => JSON.parse(raw));
1527
+ if (parseError) {
1528
+ throw new InsightsProtocolError(endpoint, "the body string does not hold JSON");
1529
+ }
1530
+ if (!isJsonObject(envelope)) {
1531
+ throw new InsightsProtocolError(endpoint, "the body string does not hold an object");
1532
+ }
1533
+ if (typeof envelope.isSuccess !== "boolean") {
1534
+ throw new InsightsProtocolError(endpoint, "the body carries no boolean isSuccess");
1535
+ }
1536
+ if (envelope.isSuccess !== true) {
1537
+ throw new InsightsProtocolError(endpoint, "the body reports isSuccess false inside a success status");
1538
+ }
1539
+ if (envelope.result === undefined || envelope.result === null) {
1540
+ throw new InsightsProtocolError(endpoint, "the body carries no result");
1541
+ }
1542
+ return envelope.result;
1543
+ }
1544
+
1545
+ class LookerResolveError extends Error {
1546
+ kind;
1547
+ candidates;
1548
+ constructor(kind, message, candidates = []) {
1549
+ super(message);
1550
+ this.name = "LookerResolveError";
1551
+ this.kind = kind;
1552
+ this.candidates = candidates;
1553
+ }
1554
+ }
1555
+ function isDashboardId(value) {
1556
+ return INTEGER_ID_PATTERN.test(value) || value.includes(TEMPLATE_ID_DELIMITER);
1557
+ }
1558
+ function isLookerTemplateDashboardId(id) {
1559
+ return !INTEGER_ID_PATTERN.test(id);
1560
+ }
1561
+ function readLookerListing(raw) {
1562
+ const endpoint = insightsRouteTemplate("lookerDashboardsList");
1563
+ const folders = parseLookerEnvelope(raw, "lookerDashboardsList");
1564
+ if (!isJsonObject(folders)) {
1565
+ throw new InsightsProtocolError(endpoint, "the result is not an object");
1566
+ }
1567
+ const listing = { rows: [], omittedFolders: [] };
1568
+ for (const folder of LOOKER_FOLDERS) {
1569
+ const group = readFolderGroup(folders[folder], folder, endpoint);
1570
+ if (group === null) {
1571
+ listing.omittedFolders.push(folder);
1572
+ continue;
1573
+ }
1574
+ for (const element of group) {
1575
+ listing.rows.push(readListingRow(element, folder, endpoint));
1576
+ }
1577
+ }
1578
+ return listing;
1579
+ }
1580
+ function readFolderGroup(group, folder, endpoint) {
1581
+ if (group === undefined) {
1582
+ throw new InsightsProtocolError(endpoint, `the result carries no ${folder} key`);
1583
+ }
1584
+ if (group === null) {
1585
+ return null;
1586
+ }
1587
+ if (!Array.isArray(group)) {
1588
+ throw new InsightsProtocolError(endpoint, `the result's ${folder} is neither an array nor null`);
1589
+ }
1590
+ return group;
1591
+ }
1592
+ function readListingRow(record, folder, endpoint) {
1593
+ if (!isJsonObject(record)) {
1594
+ throw new InsightsProtocolError(endpoint, `a row in the ${folder} folder is not an object`);
1595
+ }
1596
+ if (typeof record.id !== "string") {
1597
+ throw new InsightsProtocolError(endpoint, `a row in the ${folder} folder has no string id`);
1598
+ }
1599
+ if (record.title !== null && typeof record.title !== "string") {
1600
+ throw new InsightsProtocolError(endpoint, `a row in the ${folder} folder has a title that is neither a string nor null`);
1601
+ }
1602
+ return { folder, id: record.id, title: record.title, record };
1603
+ }
1604
+ async function resolveLookerDashboard(config, value) {
1605
+ const trimmed = value.trim();
1606
+ if (trimmed === "") {
1607
+ throw new Error("Insights Looker dashboard must not be empty.");
1608
+ }
1609
+ if (isDashboardId(trimmed)) {
1610
+ return { id: trimmed, resolvedFrom: "id" };
1611
+ }
1612
+ const { rows } = readLookerListing(await listLookerDashboards(config));
1613
+ const matches = rows.filter((row) => row.title?.trim() === trimmed);
1614
+ if (matches.length === 0) {
1615
+ throw new LookerResolveError("notFound", "No Looker dashboard with that title is listed for this session.");
1616
+ }
1617
+ for (const match of matches) {
1618
+ requireEmbeddableId(match);
1619
+ }
1620
+ if (matches.length > 1) {
1621
+ throw new LookerResolveError("ambiguous", `${matches.length} Looker dashboards share that title.`, matches.map((row) => ({ folder: row.folder, id: row.id })));
1622
+ }
1623
+ return { id: matches[0].id, resolvedFrom: "title" };
1624
+ }
1625
+ function requireEmbeddableId(row) {
1626
+ if (!isDashboardId(row.id)) {
1627
+ throw new InsightsProtocolError(insightsRouteTemplate("lookerDashboardsList"), `a row in the ${row.folder} folder has an id that is neither all digits nor contains '::'`);
1628
+ }
1629
+ }
1413
1630
  // src/machines.ts
1414
1631
  function isNullish(value) {
1415
1632
  return value === undefined || value === null;
@@ -1667,10 +1884,16 @@ export {
1667
1884
  InsightsHttpError,
1668
1885
  InsightsNetworkError,
1669
1886
  InsightsProtocolError,
1887
+ LOOKER_FOLDERS,
1888
+ LOOKER_NO_DASHBOARDS_MESSAGE,
1889
+ LOOKER_THEMES,
1890
+ LOOKER_USER_UNAVAILABLE_MESSAGE,
1891
+ LookerResolveError,
1670
1892
  MAESTRO_CASE_DASHBOARD_PREFIX,
1671
1893
  MAESTRO_DASHBOARD_SOURCE_TYPE,
1672
1894
  MAESTRO_PROCESS_DASHBOARD_PREFIX,
1673
1895
  MODEL_NOT_FOUND_LABEL,
1896
+ PORTAL_ERROR_CODE,
1674
1897
  UPDATE_BACKEND_FAILURE_LABEL,
1675
1898
  VALIDATION_FAILED_LABEL,
1676
1899
  checkAlertEntitlement,
@@ -1686,6 +1909,7 @@ export {
1686
1909
  getDashboardTemplate,
1687
1910
  getDefaultDelivery,
1688
1911
  getGroup,
1912
+ getLookerDashboardEmbedUrl,
1689
1913
  getMachineAvailabilityTimeline,
1690
1914
  getMachineDetails,
1691
1915
  getMachineRuntimeMix,
@@ -1704,6 +1928,7 @@ export {
1704
1928
  getRole,
1705
1929
  getUser,
1706
1930
  insightsPost,
1931
+ isLookerTemplateDashboardId,
1707
1932
  isTemplateKeyedDashboardId,
1708
1933
  listAgenticAlertDefinitions,
1709
1934
  listAlertDefinitions,
@@ -1712,15 +1937,19 @@ export {
1712
1937
  listExportConfigurations,
1713
1938
  listFolderFilters,
1714
1939
  listGroups,
1940
+ listLookerDashboards,
1715
1941
  listMachineFilters,
1716
1942
  listProcessFilters,
1717
1943
  listQueueFilters,
1718
1944
  listRoles,
1719
1945
  listUsers,
1720
1946
  parseDashboardSlotId,
1947
+ parseLookerEnvelope,
1948
+ readLookerListing,
1949
+ resolveLookerDashboard,
1721
1950
  updateDashboard,
1722
1951
  verifyAllExportDestinations,
1723
1952
  verifyExportDestination
1724
1953
  };
1725
1954
 
1726
- //# debugId=C5DF46655A2261CE64756E2164756E21
1955
+ //# debugId=54A108C36D39344C64756E2164756E21
package/dist/index.js CHANGED
@@ -883,6 +883,16 @@ class NodeFileSystem {
883
883
  async rename(oldPath, newPath) {
884
884
  await fs6.rename(oldPath, newPath);
885
885
  }
886
+ async isSymbolicLink(filePath) {
887
+ try {
888
+ return (await fs6.lstat(filePath)).isSymbolicLink();
889
+ } catch (error) {
890
+ if (this.isEnoent(error) || this.hasErrnoCode(error, "ENOTDIR")) {
891
+ return false;
892
+ }
893
+ throw error;
894
+ }
895
+ }
886
896
  async realpath(filePath) {
887
897
  try {
888
898
  return await fs6.realpath(filePath);
@@ -1227,6 +1237,19 @@ var KNOWN_ERROR_LABELS = new Set([
1227
1237
  DASHBOARD_NOT_FOUND_LABEL,
1228
1238
  MODEL_NOT_FOUND_LABEL
1229
1239
  ]);
1240
+ var PORTAL_ERROR_CODE = {
1241
+ InvalidUserInput: 6,
1242
+ LookerUnavailableError: 8,
1243
+ PermissionsUserUnauthorized: 10,
1244
+ UnableToGetEmbedLink: 23,
1245
+ UnableToRetrieveDashboards: 26
1246
+ };
1247
+ var LOOKER_USER_UNAVAILABLE_MESSAGE = "Unable to get Looker userInfo";
1248
+ var LOOKER_NO_DASHBOARDS_MESSAGE = "Unable to retrieve dashboards";
1249
+ var KNOWN_PORTAL_ERROR_MESSAGES = new Set([
1250
+ LOOKER_USER_UNAVAILABLE_MESSAGE,
1251
+ LOOKER_NO_DASHBOARDS_MESSAGE
1252
+ ]);
1230
1253
 
1231
1254
  class InsightsHttpError extends Error {
1232
1255
  status;
@@ -1325,7 +1348,9 @@ var ErrorDimensions = {
1325
1348
  Result: "Result",
1326
1349
  ErrorCode: "ErrorCode",
1327
1350
  Retry: "Retry",
1328
- ErrorMessage: "ErrorMessage"
1351
+ ErrorMessage: "ErrorMessage",
1352
+ HttpStatus: "HttpStatus",
1353
+ UpstreamErrorCode: "UpstreamErrorCode"
1329
1354
  };
1330
1355
  var AuthDimensions = {
1331
1356
  AuthenticationMethod: "AuthenticationMethod",
@@ -1429,7 +1454,7 @@ var package_default = {
1429
1454
  name: "@uipath/insights-sdk",
1430
1455
  author: "UiPath",
1431
1456
  license: "SEE LICENSE IN LICENSE.txt",
1432
- version: "1.204.0",
1457
+ version: "1.205.0-preview.258",
1433
1458
  description: "SDK for the UiPath Insights API — jobs, failures, and performance metrics.",
1434
1459
  repository: {
1435
1460
  type: "git",
@@ -1634,6 +1659,16 @@ var INSIGHTS_ROUTES = {
1634
1659
  method: "POST",
1635
1660
  template: "Authorization/tenant/insights"
1636
1661
  },
1662
+ lookerDashboardsList: {
1663
+ service: "portal",
1664
+ method: "GET",
1665
+ template: "AllDashboards/folders"
1666
+ },
1667
+ lookerDashboardEmbedUrl: {
1668
+ service: "portal",
1669
+ method: "POST",
1670
+ template: "DashboardUrl"
1671
+ },
1637
1672
  exportConfigurationsList: {
1638
1673
  service: "portal",
1639
1674
  method: "GET",
@@ -1735,9 +1770,43 @@ function buildServiceHeaders(config, route, hasBody) {
1735
1770
  return headers;
1736
1771
  }
1737
1772
  var MODEL_PATH_PATTERN = /^[A-Za-z0-9_.[\]]{1,200}$/;
1773
+ var MAX_PORTAL_ERROR_CODE = 999;
1774
+ function isJsonObject(value) {
1775
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1776
+ }
1777
+ function readPortalErrorCode(error) {
1778
+ if (!isJsonObject(error)) {
1779
+ return;
1780
+ }
1781
+ const code = error.errorCode;
1782
+ if (typeof code !== "number" || !Number.isInteger(code) || code < 0 || code > MAX_PORTAL_ERROR_CODE) {
1783
+ return;
1784
+ }
1785
+ return code;
1786
+ }
1787
+ function readPortalErrorMessage(error) {
1788
+ if (!isJsonObject(error)) {
1789
+ return;
1790
+ }
1791
+ const message = error.message;
1792
+ if (typeof message !== "string" || !KNOWN_PORTAL_ERROR_MESSAGES.has(message)) {
1793
+ return;
1794
+ }
1795
+ return message;
1796
+ }
1797
+ function liftPortalError(hint, error) {
1798
+ const portalErrorCode = readPortalErrorCode(error);
1799
+ if (portalErrorCode !== undefined) {
1800
+ hint.portalErrorCode = portalErrorCode;
1801
+ }
1802
+ const portalErrorMessage = readPortalErrorMessage(error);
1803
+ if (portalErrorMessage !== undefined) {
1804
+ hint.portalErrorMessage = portalErrorMessage;
1805
+ }
1806
+ }
1738
1807
  function describeJsonErrorBody(parsed) {
1739
1808
  if (typeof parsed === "string") {
1740
- return { shape: "string" };
1809
+ return describeStringErrorBody(parsed);
1741
1810
  }
1742
1811
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1743
1812
  return { shape: "other" };
@@ -1757,6 +1826,19 @@ function describeJsonErrorBody(parsed) {
1757
1826
  hint.firstInvalidField = firstKey;
1758
1827
  }
1759
1828
  }
1829
+ liftPortalError(hint, record.error);
1830
+ return hint;
1831
+ }
1832
+ function describeStringErrorBody(parsed) {
1833
+ const hint = { shape: "string" };
1834
+ const [parseError, inner] = catchError(() => JSON.parse(parsed));
1835
+ if (parseError) {
1836
+ return hint;
1837
+ }
1838
+ if (!isJsonObject(inner)) {
1839
+ return hint;
1840
+ }
1841
+ liftPortalError(hint, inner.error);
1760
1842
  return hint;
1761
1843
  }
1762
1844
  function describeErrorBody(text) {
@@ -2014,22 +2096,12 @@ var resolveConfigAsync = async ({
2014
2096
  baseUrl = DEFAULT_BASE_URL;
2015
2097
  }
2016
2098
  baseUrl = normalizeAndValidateBaseUrl(baseUrl);
2017
- let clientId = customClientId;
2018
- if (!clientId && fileAuth.clientId) {
2019
- clientId = fileAuth.clientId;
2020
- }
2021
- if (!clientId) {
2022
- clientId = DEFAULT_CLIENT_ID;
2023
- }
2024
- let clientSecret = customClientSecret;
2025
- if (!clientSecret && fileAuth.clientSecret) {
2026
- clientSecret = fileAuth.clientSecret;
2027
- }
2028
- const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(clientSecret) || Boolean(customClientAssertion));
2099
+ const clientId = customClientId || DEFAULT_CLIENT_ID;
2100
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(customClientSecret) || Boolean(customClientAssertion));
2029
2101
  const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
2030
2102
  return {
2031
2103
  clientId,
2032
- clientSecret,
2104
+ clientSecret: customClientSecret,
2033
2105
  scopes,
2034
2106
  baseUrl,
2035
2107
  authorizationEndpoint: `${baseUrl}/identity_/connect/authorize`,
@@ -2204,6 +2276,16 @@ var resolveIdentityType = (claims, authFlow, email) => {
2204
2276
  }
2205
2277
  return;
2206
2278
  };
2279
+ var resolveApplicationSubtype = (claims, authFlow) => {
2280
+ switch (asString(claims?.sub_type)) {
2281
+ case "service.external":
2282
+ return "External";
2283
+ case "service.internal":
2284
+ return "Internal";
2285
+ default:
2286
+ return authFlow === "client_credentials" || authFlow === "federated_credentials" ? "External" : undefined;
2287
+ }
2288
+ };
2207
2289
  var looksLikeEmail = (value) => value?.includes("@") ?? false;
2208
2290
  var pickEmail = (claims) => {
2209
2291
  for (const candidate of [claims?.email, claims?.preferred_username]) {
@@ -2245,6 +2327,12 @@ var resolveSessionIdentity = (accessToken, authFlow) => {
2245
2327
  const clientId = asString(claims?.client_id);
2246
2328
  if (clientId)
2247
2329
  identity.clientId = clientId;
2330
+ const subType = asString(claims?.sub_type);
2331
+ if (subType)
2332
+ identity.subType = subType;
2333
+ const applicationSubtype = resolveApplicationSubtype(claims, authFlow);
2334
+ if (applicationSubtype)
2335
+ identity.applicationSubtype = applicationSubtype;
2248
2336
  return identity;
2249
2337
  };
2250
2338
  var readTokenScopes = (accessToken) => accessToken ? pickScopes(decodeClaims(accessToken)) : undefined;
@@ -2539,6 +2627,40 @@ var tryRobotClientFallback = async (options = {}) => {
2539
2627
  }
2540
2628
  };
2541
2629
 
2630
+ // ../auth/src/tenantSelection.ts
2631
+ var LOGIN_STATUS_HINT = "Run 'uip login status' to see the organization the CLI is signed in to.";
2632
+ var organizationHint = (organizationId) => `The request used '${organizationId}' as the organization. ${LOGIN_STATUS_HINT}`;
2633
+ var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
2634
+ var describeNonJsonResponse = (organizationId, response, parseError) => {
2635
+ if (response.redirected) {
2636
+ return `Could not find organization '${organizationId}': the request was ` + `redirected to a sign-in page instead of the organization's tenant ` + `list. ${LOGIN_STATUS_HINT}`;
2637
+ }
2638
+ const contentType = response.headers.get("content-type") ?? "unknown";
2639
+ return `The organization service returned a '${contentType}' response instead ` + `of JSON: ${parseError.message}. ${organizationHint(organizationId)}`;
2640
+ };
2641
+ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId, signal) => {
2642
+ const url = `${baseUrl}/${organizationId}/portal_/api/filtering/leftnav/tenantsAndOrganizationInfo`;
2643
+ const response = await fetch(url, {
2644
+ headers: {
2645
+ Authorization: `Bearer ${accessToken}`
2646
+ },
2647
+ ...signal ? { signal } : {}
2648
+ });
2649
+ if (!response.ok) {
2650
+ if (response.status === 401) {
2651
+ throw new Error(`Unauthorized: the access token was rejected, it was not ` + `issued for organization '${organizationId}', or ` + `'${organizationId}' was not accepted as an organization ` + `URL segment in this environment. ` + LOGIN_STATUS_HINT);
2652
+ }
2653
+ const errorText = await response.text();
2654
+ const message = `Failed to get tenants and organizations: ${response.status} ${errorText}`;
2655
+ throw new Error(IDENTIFIER_STATUSES.has(response.status) ? `${message}. ${organizationHint(organizationId)}` : message);
2656
+ }
2657
+ const [parseError, data] = await catchError2(response.json());
2658
+ if (parseError) {
2659
+ throw new Error(describeNonJsonResponse(organizationId, response, parseError));
2660
+ }
2661
+ return data;
2662
+ };
2663
+
2542
2664
  // ../auth/src/tokenRefresh.ts
2543
2665
  var TOKEN_REFRESH_REAUTHENTICATE_MESSAGE = "Token refresh failed. Run 'uip login' to re-authenticate.";
2544
2666
 
@@ -2753,6 +2875,8 @@ var saveEnvFileAsync = async ({
2753
2875
  };
2754
2876
 
2755
2877
  // ../auth/src/loginStatus.ts
2878
+ var defaultRobotTenantIdCache = new Map;
2879
+ var ROBOT_TENANT_LOOKUP_TIMEOUT_MS = 5000;
2756
2880
  var getLoginStatusAsync = async (options = {}) => {
2757
2881
  return getLoginStatusWithDeps(options);
2758
2882
  };
@@ -2765,12 +2889,20 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
2765
2889
  refreshToken: refreshTokenFn = refreshAccessToken,
2766
2890
  resolveConfig = resolveConfigAsync,
2767
2891
  robotFallback = tryRobotClientFallback,
2892
+ fetchTenantsAndOrgs = fetchTenantsAndOrganizations,
2893
+ robotTenantIdCache = defaultRobotTenantIdCache,
2894
+ robotTenantLookupTimeoutMs = ROBOT_TENANT_LOOKUP_TIMEOUT_MS,
2768
2895
  loadBreaker = loadRefreshBreaker,
2769
2896
  saveBreaker = saveRefreshBreaker,
2770
2897
  clearBreaker = clearRefreshBreaker
2771
2898
  } = deps;
2899
+ const robotDeps = {
2900
+ fetchTenantsAndOrgs,
2901
+ cache: robotTenantIdCache,
2902
+ lookupTimeoutMs: robotTenantLookupTimeoutMs
2903
+ };
2772
2904
  if (isRobotAuthEnforced()) {
2773
- return resolveRobotEnforcedStatus(robotFallback);
2905
+ return resolveRobotEnforcedStatus(robotFallback, robotDeps);
2774
2906
  }
2775
2907
  if (isEnvAuthEnabled()) {
2776
2908
  return readAuthFromEnv();
@@ -2788,7 +2920,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
2788
2920
  hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
2789
2921
  };
2790
2922
  }
2791
- return resolveBorrowedRobotStatus(robotFallback);
2923
+ return resolveBorrowedRobotStatus(robotFallback, robotDeps);
2792
2924
  }
2793
2925
  const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
2794
2926
  if ("status" in loaded) {
@@ -2830,7 +2962,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
2830
2962
  }
2831
2963
  return buildFileStatus(tokens, credentials, globalHint);
2832
2964
  };
2833
- async function resolveRobotEnforcedStatus(robotFallback) {
2965
+ async function resolveRobotEnforcedStatus(robotFallback, deps) {
2834
2966
  if (isEnvAuthEnabled()) {
2835
2967
  throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
2836
2968
  }
@@ -2841,11 +2973,11 @@ async function resolveRobotEnforcedStatus(robotFallback) {
2841
2973
  hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
2842
2974
  };
2843
2975
  }
2844
- return buildRobotStatus(robotCreds);
2976
+ return buildRobotStatus(robotCreds, deps);
2845
2977
  }
2846
- async function resolveBorrowedRobotStatus(robotFallback) {
2978
+ async function resolveBorrowedRobotStatus(robotFallback, deps) {
2847
2979
  const robotCreds = await robotFallback();
2848
- return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
2980
+ return robotCreds ? buildRobotStatus(robotCreds, deps) : { loginStatus: "Not logged in" };
2849
2981
  }
2850
2982
  async function loadFileCredentials(loadEnvFile, absolutePath) {
2851
2983
  let credentials;
@@ -2980,9 +3112,10 @@ function identityFields(accessToken, credentials) {
2980
3112
  ...scopes ? { scopes } : {}
2981
3113
  };
2982
3114
  }
2983
- function buildRobotStatus(robotCreds) {
3115
+ async function buildRobotStatus(robotCreds, deps) {
2984
3116
  const identity = resolveSessionIdentity(robotCreds.accessToken);
2985
3117
  const scopes = readTokenScopes(robotCreds.accessToken);
3118
+ const tenant = robotCreds.tenantId ? { tenantId: robotCreds.tenantId } : await resolveRobotTenantId(robotCreds, deps);
2986
3119
  return {
2987
3120
  loginStatus: "Logged in",
2988
3121
  accessToken: robotCreds.accessToken,
@@ -2990,14 +3123,62 @@ function buildRobotStatus(robotCreds) {
2990
3123
  organizationName: robotCreds.organizationName,
2991
3124
  organizationId: robotCreds.organizationId,
2992
3125
  tenantName: robotCreds.tenantName,
2993
- tenantId: robotCreds.tenantId,
3126
+ tenantId: tenant.tenantId,
2994
3127
  issuer: robotCreds.issuer,
2995
3128
  expiration: getTokenExpiration(robotCreds.accessToken),
2996
3129
  source: "robot" /* Robot */,
3130
+ ...tenant.hint ? { hint: tenant.hint } : {},
2997
3131
  ...identity ? { identity } : {},
2998
3132
  ...scopes ? { scopes } : {}
2999
3133
  };
3000
3134
  }
3135
+ async function resolveRobotTenantId(robotCreds, deps) {
3136
+ const { baseUrl, accessToken, tenantName } = robotCreds;
3137
+ const organization = robotCreds.organizationName ?? robotCreds.organizationId;
3138
+ if (!tenantName || !organization) {
3139
+ return {};
3140
+ }
3141
+ const key = `${baseUrl}|${organization}|${tenantName}|${accessToken}`;
3142
+ let pending = deps.cache.get(key);
3143
+ if (!pending) {
3144
+ pending = catchError2(lookupRobotTenantId({ baseUrl, accessToken, organization, tenantName }, deps)).then(([error, resolution]) => {
3145
+ const settled = error ? { hint: tenantLookupFailureHint(tenantName, error.message) } : resolution;
3146
+ if (!settled.tenantId) {
3147
+ deps.cache.delete(key);
3148
+ }
3149
+ return settled;
3150
+ });
3151
+ deps.cache.set(key, pending);
3152
+ }
3153
+ return pending;
3154
+ }
3155
+ async function lookupRobotTenantId(target, deps) {
3156
+ const { baseUrl, accessToken, organization, tenantName } = target;
3157
+ const [error, data] = await catchError2(deps.fetchTenantsAndOrgs(baseUrl, accessToken, organization, AbortSignal.timeout(deps.lookupTimeoutMs)));
3158
+ if (error) {
3159
+ const reason = error.name === "TimeoutError" ? `the tenant list did not answer within ${deps.lookupTimeoutMs} ms.` : error.message;
3160
+ return { hint: tenantLookupFailureHint(tenantName, reason) };
3161
+ }
3162
+ const rows = data?.tenants;
3163
+ const tenants = Array.isArray(rows) ? rows.filter((tenant) => typeof tenant?.id === "string" && typeof tenant?.name === "string") : [];
3164
+ const wantedName = decodePathSegment(tenantName);
3165
+ const wanted = wantedName.toLowerCase();
3166
+ const match = tenants.find((tenant) => tenant.name === wantedName) ?? tenants.find((tenant) => tenant.name.toLowerCase() === wanted);
3167
+ if (!match) {
3168
+ const names = tenants.map((tenant) => tenant.name).join(", ");
3169
+ return {
3170
+ hint: `The Robot session targets tenant '${tenantName}', but ` + `organization '${organization}' lists no tenant of that name` + `${names ? ` (available: ${names})` : ""}. Commands that need ` + `the tenant id will fail until it can be resolved.`
3171
+ };
3172
+ }
3173
+ return { tenantId: match.id };
3174
+ }
3175
+ function tenantLookupFailureHint(tenantName, reason) {
3176
+ return `Could not resolve the id of tenant '${tenantName}' from the ` + `Robot session: ${reason} Commands that need the tenant id will ` + `fail until it can be resolved.`;
3177
+ }
3178
+ function decodePathSegment(segment) {
3179
+ const [error, decoded] = catchError2(() => decodeURIComponent(segment));
3180
+ return error ? segment : decoded;
3181
+ }
3001
3182
  var isFileNotFoundError = (error) => {
3002
3183
  if (!(error instanceof Object))
3003
3184
  return false;
@@ -3274,8 +3455,6 @@ init_constants();
3274
3455
  // ../auth/src/interactive.ts
3275
3456
  init_src();
3276
3457
  init_constants();
3277
- // ../auth/src/tenantSelection.ts
3278
- var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
3279
3458
 
3280
3459
  // ../auth/src/selectTenant.ts
3281
3460
  var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
@@ -3697,6 +3876,151 @@ async function listQueueFilters(config) {
3697
3876
  async function listMachineFilters(config) {
3698
3877
  return listFilters(config, "filtersAllMachines", isMachineFiltersResponse, "machine filters");
3699
3878
  }
3879
+ // src/looker-dashboards.ts
3880
+ var TEMPLATE_ID_DELIMITER = "::";
3881
+ var INTEGER_ID_PATTERN = /^\d+$/;
3882
+ var LOOKER_FOLDERS = [
3883
+ "personal",
3884
+ "tenant",
3885
+ "templates",
3886
+ "organization"
3887
+ ];
3888
+ var LOOKER_THEMES = ["light", "dark"];
3889
+ async function listLookerDashboards(config) {
3890
+ return requestInsightsRoute(config, "lookerDashboardsList");
3891
+ }
3892
+ async function getLookerDashboardEmbedUrl(config, options) {
3893
+ const dashboardId = options.dashboardId.trim();
3894
+ if (dashboardId === "") {
3895
+ throw new Error("Insights Looker dashboard id must not be empty.");
3896
+ }
3897
+ if (!isDashboardId(dashboardId)) {
3898
+ throw new Error("Insights Looker dashboard id must be all digits or contain '::'; resolve a title with resolveLookerDashboard first.");
3899
+ }
3900
+ if (!LOOKER_THEMES.includes(options.theme)) {
3901
+ throw new Error(`Insights Looker theme must be one of ${LOOKER_THEMES.join(", ")}.`);
3902
+ }
3903
+ const locale = options.localization?.trim();
3904
+ if (locale === "") {
3905
+ throw new Error("Insights Looker localization must not be empty.");
3906
+ }
3907
+ return requestInsightsRoute(config, "lookerDashboardEmbedUrl", {
3908
+ body: {
3909
+ dashboardId,
3910
+ theme: options.theme,
3911
+ ...locale === undefined ? {} : { locale }
3912
+ }
3913
+ });
3914
+ }
3915
+ function parseLookerEnvelope(raw, routeKey) {
3916
+ const endpoint = insightsRouteTemplate(routeKey);
3917
+ if (typeof raw !== "string") {
3918
+ throw new InsightsProtocolError(endpoint, "the body is not the JSON string literal this root answers with");
3919
+ }
3920
+ const [parseError, envelope] = catchError(() => JSON.parse(raw));
3921
+ if (parseError) {
3922
+ throw new InsightsProtocolError(endpoint, "the body string does not hold JSON");
3923
+ }
3924
+ if (!isJsonObject(envelope)) {
3925
+ throw new InsightsProtocolError(endpoint, "the body string does not hold an object");
3926
+ }
3927
+ if (typeof envelope.isSuccess !== "boolean") {
3928
+ throw new InsightsProtocolError(endpoint, "the body carries no boolean isSuccess");
3929
+ }
3930
+ if (envelope.isSuccess !== true) {
3931
+ throw new InsightsProtocolError(endpoint, "the body reports isSuccess false inside a success status");
3932
+ }
3933
+ if (envelope.result === undefined || envelope.result === null) {
3934
+ throw new InsightsProtocolError(endpoint, "the body carries no result");
3935
+ }
3936
+ return envelope.result;
3937
+ }
3938
+
3939
+ class LookerResolveError extends Error {
3940
+ kind;
3941
+ candidates;
3942
+ constructor(kind, message, candidates = []) {
3943
+ super(message);
3944
+ this.name = "LookerResolveError";
3945
+ this.kind = kind;
3946
+ this.candidates = candidates;
3947
+ }
3948
+ }
3949
+ function isDashboardId(value) {
3950
+ return INTEGER_ID_PATTERN.test(value) || value.includes(TEMPLATE_ID_DELIMITER);
3951
+ }
3952
+ function isLookerTemplateDashboardId(id) {
3953
+ return !INTEGER_ID_PATTERN.test(id);
3954
+ }
3955
+ function readLookerListing(raw) {
3956
+ const endpoint = insightsRouteTemplate("lookerDashboardsList");
3957
+ const folders = parseLookerEnvelope(raw, "lookerDashboardsList");
3958
+ if (!isJsonObject(folders)) {
3959
+ throw new InsightsProtocolError(endpoint, "the result is not an object");
3960
+ }
3961
+ const listing = { rows: [], omittedFolders: [] };
3962
+ for (const folder of LOOKER_FOLDERS) {
3963
+ const group = readFolderGroup(folders[folder], folder, endpoint);
3964
+ if (group === null) {
3965
+ listing.omittedFolders.push(folder);
3966
+ continue;
3967
+ }
3968
+ for (const element of group) {
3969
+ listing.rows.push(readListingRow(element, folder, endpoint));
3970
+ }
3971
+ }
3972
+ return listing;
3973
+ }
3974
+ function readFolderGroup(group, folder, endpoint) {
3975
+ if (group === undefined) {
3976
+ throw new InsightsProtocolError(endpoint, `the result carries no ${folder} key`);
3977
+ }
3978
+ if (group === null) {
3979
+ return null;
3980
+ }
3981
+ if (!Array.isArray(group)) {
3982
+ throw new InsightsProtocolError(endpoint, `the result's ${folder} is neither an array nor null`);
3983
+ }
3984
+ return group;
3985
+ }
3986
+ function readListingRow(record, folder, endpoint) {
3987
+ if (!isJsonObject(record)) {
3988
+ throw new InsightsProtocolError(endpoint, `a row in the ${folder} folder is not an object`);
3989
+ }
3990
+ if (typeof record.id !== "string") {
3991
+ throw new InsightsProtocolError(endpoint, `a row in the ${folder} folder has no string id`);
3992
+ }
3993
+ if (record.title !== null && typeof record.title !== "string") {
3994
+ throw new InsightsProtocolError(endpoint, `a row in the ${folder} folder has a title that is neither a string nor null`);
3995
+ }
3996
+ return { folder, id: record.id, title: record.title, record };
3997
+ }
3998
+ async function resolveLookerDashboard(config, value) {
3999
+ const trimmed = value.trim();
4000
+ if (trimmed === "") {
4001
+ throw new Error("Insights Looker dashboard must not be empty.");
4002
+ }
4003
+ if (isDashboardId(trimmed)) {
4004
+ return { id: trimmed, resolvedFrom: "id" };
4005
+ }
4006
+ const { rows } = readLookerListing(await listLookerDashboards(config));
4007
+ const matches = rows.filter((row) => row.title?.trim() === trimmed);
4008
+ if (matches.length === 0) {
4009
+ throw new LookerResolveError("notFound", "No Looker dashboard with that title is listed for this session.");
4010
+ }
4011
+ for (const match of matches) {
4012
+ requireEmbeddableId(match);
4013
+ }
4014
+ if (matches.length > 1) {
4015
+ throw new LookerResolveError("ambiguous", `${matches.length} Looker dashboards share that title.`, matches.map((row) => ({ folder: row.folder, id: row.id })));
4016
+ }
4017
+ return { id: matches[0].id, resolvedFrom: "title" };
4018
+ }
4019
+ function requireEmbeddableId(row) {
4020
+ if (!isDashboardId(row.id)) {
4021
+ throw new InsightsProtocolError(insightsRouteTemplate("lookerDashboardsList"), `a row in the ${row.folder} folder has an id that is neither all digits nor contains '::'`);
4022
+ }
4023
+ }
3700
4024
  // src/machines.ts
3701
4025
  function isNullish(value) {
3702
4026
  return value === undefined || value === null;
@@ -3954,10 +4278,16 @@ export {
3954
4278
  InsightsHttpError,
3955
4279
  InsightsNetworkError,
3956
4280
  InsightsProtocolError,
4281
+ LOOKER_FOLDERS,
4282
+ LOOKER_NO_DASHBOARDS_MESSAGE,
4283
+ LOOKER_THEMES,
4284
+ LOOKER_USER_UNAVAILABLE_MESSAGE,
4285
+ LookerResolveError,
3957
4286
  MAESTRO_CASE_DASHBOARD_PREFIX,
3958
4287
  MAESTRO_DASHBOARD_SOURCE_TYPE,
3959
4288
  MAESTRO_PROCESS_DASHBOARD_PREFIX,
3960
4289
  MODEL_NOT_FOUND_LABEL,
4290
+ PORTAL_ERROR_CODE,
3961
4291
  UPDATE_BACKEND_FAILURE_LABEL,
3962
4292
  VALIDATION_FAILED_LABEL,
3963
4293
  checkAlertEntitlement,
@@ -3973,6 +4303,7 @@ export {
3973
4303
  getDashboardTemplate,
3974
4304
  getDefaultDelivery,
3975
4305
  getGroup,
4306
+ getLookerDashboardEmbedUrl,
3976
4307
  getMachineAvailabilityTimeline,
3977
4308
  getMachineDetails,
3978
4309
  getMachineRuntimeMix,
@@ -3991,6 +4322,7 @@ export {
3991
4322
  getRole,
3992
4323
  getUser,
3993
4324
  insightsPost,
4325
+ isLookerTemplateDashboardId,
3994
4326
  isTemplateKeyedDashboardId,
3995
4327
  listAgenticAlertDefinitions,
3996
4328
  listAlertDefinitions,
@@ -3999,15 +4331,19 @@ export {
3999
4331
  listExportConfigurations,
4000
4332
  listFolderFilters,
4001
4333
  listGroups,
4334
+ listLookerDashboards,
4002
4335
  listMachineFilters,
4003
4336
  listProcessFilters,
4004
4337
  listQueueFilters,
4005
4338
  listRoles,
4006
4339
  listUsers,
4007
4340
  parseDashboardSlotId,
4341
+ parseLookerEnvelope,
4342
+ readLookerListing,
4343
+ resolveLookerDashboard,
4008
4344
  updateDashboard,
4009
4345
  verifyAllExportDestinations,
4010
4346
  verifyExportDestination
4011
4347
  };
4012
4348
 
4013
- //# debugId=BFA94E9FB55DE0F464756E2164756E21
4349
+ //# debugId=29164392C65E2CD564756E2164756E21
@@ -69,6 +69,8 @@ export interface InsightsErrorBodyHint {
69
69
  * numbers are at origin/develop 2c5860474, as above.
70
70
  */
71
71
  problemDetails?: true;
72
+ portalErrorCode?: number;
73
+ portalErrorMessage?: string;
72
74
  }
73
75
  /**
74
76
  * The only `error` values `describeJsonErrorBody` lifts into `errorLabel`.
@@ -109,6 +111,16 @@ export declare const VALIDATION_FAILED_LABEL = "Validation failed";
109
111
  export declare const CREATE_BACKEND_FAILURE_LABEL = "Failed to create dashboard";
110
112
  export declare const UPDATE_BACKEND_FAILURE_LABEL = "Failed to update dashboard";
111
113
  export declare const KNOWN_ERROR_LABELS: Set<string>;
114
+ export declare const PORTAL_ERROR_CODE: {
115
+ readonly InvalidUserInput: 6;
116
+ readonly LookerUnavailableError: 8;
117
+ readonly PermissionsUserUnauthorized: 10;
118
+ readonly UnableToGetEmbedLink: 23;
119
+ readonly UnableToRetrieveDashboards: 26;
120
+ };
121
+ export declare const LOOKER_USER_UNAVAILABLE_MESSAGE = "Unable to get Looker userInfo";
122
+ export declare const LOOKER_NO_DASHBOARDS_MESSAGE = "Unable to retrieve dashboards";
123
+ export declare const KNOWN_PORTAL_ERROR_MESSAGES: Set<string>;
112
124
  interface InsightsHttpErrorInit {
113
125
  status: number;
114
126
  method: InsightsHttpMethod;
@@ -4,10 +4,12 @@ export { createInsightsConfig } from "./client-factory";
4
4
  export type { CreateDashboardOptions, DashboardChart, DashboardChartAction, DashboardChartFilter, DashboardChartFilterRange, DashboardCustomLayout, DashboardDefinition, DashboardField, DashboardFieldFormat, DashboardLayout, DashboardLayoutContainer, DashboardMetric, DashboardMetricExpression, DashboardMetricFilter, DashboardSlot, DashboardSlotKind, DashboardTable, DeleteDashboardOptions, GetDashboardOptions, GetDashboardTemplateOptions, ListDashboardFiltersOptions, UpdateDashboardOptions, } from "./dashboards";
5
5
  export { composeDashboardSlotId, createDashboard, DASHBOARD_SLOT_DELIMITER, DASHBOARD_TEMPLATE_ID_PREFIX, DashboardRequestError, deleteDashboard, getDashboard, getDashboardTemplate, isTemplateKeyedDashboardId, listDashboardFilters, MAESTRO_CASE_DASHBOARD_PREFIX, MAESTRO_DASHBOARD_SOURCE_TYPE, MAESTRO_PROCESS_DASHBOARD_PREFIX, parseDashboardSlotId, updateDashboard, } from "./dashboards";
6
6
  export type { InsightsBodyKind, InsightsErrorBodyHint, InsightsHttpMethod, } from "./errors";
7
- export { CREATE_BACKEND_FAILURE_LABEL, DASHBOARD_NOT_FOUND_LABEL, InsightsHttpError, InsightsNetworkError, InsightsProtocolError, MODEL_NOT_FOUND_LABEL, UPDATE_BACKEND_FAILURE_LABEL, VALIDATION_FAILED_LABEL, } from "./errors";
7
+ export { CREATE_BACKEND_FAILURE_LABEL, DASHBOARD_NOT_FOUND_LABEL, InsightsHttpError, InsightsNetworkError, InsightsProtocolError, LOOKER_NO_DASHBOARDS_MESSAGE, LOOKER_USER_UNAVAILABLE_MESSAGE, MODEL_NOT_FOUND_LABEL, PORTAL_ERROR_CODE, UPDATE_BACKEND_FAILURE_LABEL, VALIDATION_FAILED_LABEL, } from "./errors";
8
8
  export type { ExportDestinationKey, ExportVerifyBody, } from "./export-configurations";
9
9
  export { listExportConfigurations, verifyAllExportDestinations, verifyExportDestination, } from "./export-configurations";
10
10
  export { listFolderFilters, listMachineFilters, listProcessFilters, listQueueFilters, } from "./filters";
11
+ export type { LookerDashboardRef, LookerEmbedUrlOptions, LookerFolder, LookerListing, LookerListingRow, LookerTheme, } from "./looker-dashboards";
12
+ export { getLookerDashboardEmbedUrl, isLookerTemplateDashboardId, LOOKER_FOLDERS, LOOKER_THEMES, LookerResolveError, listLookerDashboards, parseLookerEnvelope, readLookerListing, resolveLookerDashboard, } from "./looker-dashboards";
11
13
  export type { MachineQueryInput, MachinesResponse } from "./machines";
12
14
  export { getMachineAvailabilityTimeline, getMachineDetails, getMachineRuntimeMix, getMachineTopFailures, getMachineUtilization, } from "./machines";
13
15
  export type { QueueQueryInput, QueuesResponse, QueueWfMetricsRow, } from "./queues";
@@ -0,0 +1,42 @@
1
+ import { type InsightsRouteKey } from "./transport";
2
+ import type { InsightsApiConfig } from "./types";
3
+ export declare const LOOKER_FOLDERS: readonly ["personal", "tenant", "templates", "organization"];
4
+ export type LookerFolder = (typeof LOOKER_FOLDERS)[number];
5
+ export declare const LOOKER_THEMES: readonly ["light", "dark"];
6
+ export type LookerTheme = (typeof LOOKER_THEMES)[number];
7
+ export declare function listLookerDashboards(config: InsightsApiConfig): Promise<unknown>;
8
+ export interface LookerEmbedUrlOptions {
9
+ dashboardId: string;
10
+ theme: LookerTheme;
11
+ localization?: string;
12
+ }
13
+ export declare function getLookerDashboardEmbedUrl(config: InsightsApiConfig, options: LookerEmbedUrlOptions): Promise<unknown>;
14
+ export declare function parseLookerEnvelope(raw: unknown, routeKey: InsightsRouteKey): unknown;
15
+ export interface LookerDashboardRef {
16
+ id: string;
17
+ resolvedFrom: "id" | "title";
18
+ }
19
+ export declare class LookerResolveError extends Error {
20
+ readonly kind: "notFound" | "ambiguous";
21
+ readonly candidates: ReadonlyArray<{
22
+ folder: LookerFolder;
23
+ id: string;
24
+ }>;
25
+ constructor(kind: "notFound" | "ambiguous", message: string, candidates?: ReadonlyArray<{
26
+ folder: LookerFolder;
27
+ id: string;
28
+ }>);
29
+ }
30
+ export declare function isLookerTemplateDashboardId(id: string): boolean;
31
+ export interface LookerListingRow {
32
+ folder: LookerFolder;
33
+ id: string;
34
+ title: string | null;
35
+ record: Record<string, unknown>;
36
+ }
37
+ export interface LookerListing {
38
+ rows: LookerListingRow[];
39
+ omittedFolders: LookerFolder[];
40
+ }
41
+ export declare function readLookerListing(raw: unknown): LookerListing;
42
+ export declare function resolveLookerDashboard(config: InsightsApiConfig, value: string): Promise<LookerDashboardRef>;
@@ -160,6 +160,16 @@ export declare const INSIGHTS_ROUTES: {
160
160
  readonly method: "POST";
161
161
  readonly template: "Authorization/tenant/insights";
162
162
  };
163
+ readonly lookerDashboardsList: {
164
+ readonly service: "portal";
165
+ readonly method: "GET";
166
+ readonly template: "AllDashboards/folders";
167
+ };
168
+ readonly lookerDashboardEmbedUrl: {
169
+ readonly service: "portal";
170
+ readonly method: "POST";
171
+ readonly template: "DashboardUrl";
172
+ };
163
173
  readonly exportConfigurationsList: {
164
174
  readonly service: "portal";
165
175
  readonly method: "GET";
@@ -179,6 +189,7 @@ export declare const INSIGHTS_ROUTES: {
179
189
  export type InsightsRouteKey = keyof typeof INSIGHTS_ROUTES;
180
190
  /** Safe endpoint template for a route, for protocol-error reporting. */
181
191
  export declare function insightsRouteTemplate(routeKey: InsightsRouteKey): string;
192
+ export declare function isJsonObject(value: unknown): value is Record<string, unknown>;
182
193
  /** Query values a wrapper may set. `undefined` omits the parameter. */
183
194
  export type InsightsRouteQuery = Record<string, string | number | boolean | undefined>;
184
195
  export interface InsightsRouteRequest {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@uipath/insights-sdk",
3
3
  "author": "UiPath",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
- "version": "1.204.0",
5
+ "version": "1.205.0-preview.258",
6
6
  "description": "SDK for the UiPath Insights API — jobs, failures, and performance metrics.",
7
7
  "repository": {
8
8
  "type": "git",
@@ -35,5 +35,5 @@
35
35
  "files": [
36
36
  "dist"
37
37
  ],
38
- "gitHead": "699c58dabb59414557755a8933bcbe40aa420df3"
38
+ "gitHead": "8f629ee9fa89abf94f197436a60cb3b9620f8b27"
39
39
  }