quickbase-js 0.1.0-beta.7 → 0.1.0-beta.9

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 (82) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +46 -130
  3. package/dist/esm/quickbase.d.ts +1292 -125
  4. package/dist/esm/quickbase.js +666 -190
  5. package/dist/esm/quickbase.js.map +1 -1
  6. package/dist/esm/quickbase.min.js +1 -1
  7. package/dist/esm/quickbase.min.js.map +1 -1
  8. package/dist/umd/quickbase.umd.js +674 -189
  9. package/dist/umd/quickbase.umd.js.map +1 -1
  10. package/dist/umd/quickbase.umd.min.js +1 -1
  11. package/dist/umd/quickbase.umd.min.js.map +1 -1
  12. package/open-api/fix-spec-main.ts +69 -68
  13. package/open-api/generate-override-report.ts +214 -0
  14. package/open-api/generate-unified-interface.ts +162 -103
  15. package/open-api/output/override-report.html +11 -0
  16. package/open-api/output/override-report.json +14395 -58
  17. package/open-api/output/quickbase-fixed.json +583 -2
  18. package/open-api/schema/tags/fields.ts +331 -16
  19. package/open-api/schema/tags/index.ts +2 -4
  20. package/open-api/types/spec.ts +2 -1
  21. package/open-api/utils/generateJsDoc.ts +96 -0
  22. package/package.json +33 -33
  23. package/src/RateLimitError.ts +12 -0
  24. package/src/ThrottleBucket.ts +41 -0
  25. package/src/authorizationStrategy.ts +246 -0
  26. package/src/generated-unified/QuickbaseClient.ts +809 -119
  27. package/src/invokeMethod.ts +242 -0
  28. package/src/quickbaseClient.ts +117 -248
  29. package/src/rateLimiter.ts +25 -0
  30. package/src/tokenCache.ts +10 -26
  31. package/tests/setup.ts +2 -0
  32. package/tests/vitest/qb/apps/getApp.test.ts +6 -2
  33. package/tests/vitest/qb/apps/getAppEvents.test.ts +67 -0
  34. package/tests/vitest/qb/apps/updateApp.test.ts +58 -0
  35. package/tests/vitest/qb/auth/mockQuickbaseServer.ts +60 -0
  36. package/tests/vitest/qb/auth/retryUserToken401.test.ts +73 -0
  37. package/tests/vitest/qb/auth/ssoTokenIntegrationWithServer.test.ts +65 -0
  38. package/tests/vitest/qb/fields/createField.test.ts +1 -2
  39. package/tests/vitest/qb/fields/deleteFields.test.ts +10 -16
  40. package/tests/vitest/qb/fields/getFieldUsage.test.ts +58 -150
  41. package/tests/vitest/qb/fields/updateField.test.ts +93 -0
  42. package/tests/vitest/qb/formulas/runFormula.test.ts +96 -0
  43. package/tests/vitest/qb/index.ts +1 -0
  44. package/tests/vitest/qb/tables/createRelationship.test.ts +102 -0
  45. package/tests/vitest/qb/tables/deleteRelationship.test.ts +143 -0
  46. package/tests/vitest/qb/tables/updateRelationship.test.ts +250 -0
  47. package/tests/vitest/unit/ThrottleBucket.test.ts +95 -0
  48. package/tests/vitest/unit/apps/copyApp.test.ts +133 -40
  49. package/tests/vitest/unit/apps/getAppEvents.test.ts +193 -0
  50. package/tests/vitest/unit/apps/updateApp.test.ts +412 -0
  51. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +7 -26
  52. package/tests/vitest/unit/auth/getTempToken.test.ts +42 -18
  53. package/tests/vitest/unit/auth/retryTempToken401.test.ts +95 -0
  54. package/tests/vitest/unit/auth/retryTempTokenMaxRetries.test.ts +235 -0
  55. package/tests/vitest/unit/auth/retryUserToken401.test.ts +69 -0
  56. package/tests/vitest/unit/auth/ssoTokenRefresh.test.ts +325 -0
  57. package/tests/vitest/unit/fields/createField.test.ts +180 -120
  58. package/tests/vitest/unit/fields/getFieldUsage.test.ts +47 -14
  59. package/tests/vitest/unit/fields/updateField.test.ts +285 -0
  60. package/tests/vitest/unit/formulas/runFormula.test.ts +205 -0
  61. package/tests/vitest/unit/index.ts +2 -1
  62. package/tests/vitest/unit/inferHttpMethod.test.ts +131 -0
  63. package/tests/vitest/unit/rateLimit.test.ts +191 -0
  64. package/tests/vitest/unit/tables/createRelationship.test.ts +212 -0
  65. package/tests/vitest/unit/tables/deleteRelationship.test.ts +97 -0
  66. package/tests/vitest/unit/tables/updateRelationship.test.ts +307 -0
  67. package/tests/vitest/unit/tokenLifespan.test.ts +204 -0
  68. package/tools/log-gen.ts +20 -7
  69. package/tools/log-gen.yaml +3446 -1848
  70. package/tsconfig.json +5 -2
  71. package/vitest.config.ts +2 -2
  72. package/notes.txt +0 -158
  73. package/tests/vitest/unit/auth/retryOn401.test.ts +0 -116
  74. package/tests/vitest/unit/auth/two401s.test.ts +0 -86
  75. package/tools/generate-types.ts +0 -29
  76. package/tools/openapi-schema-validator.ts +0 -38
  77. package/tools/spec-analyzer.ts +0 -163
  78. package/tools/split-spec.ts +0 -148
  79. package/tools/test-import.ts +0 -3
  80. package/tools/validate-spec.ts +0 -40
  81. /package/tests/playwright/qb/auth/{tokenPrefetch.test.ts → tempTokenPrefetch.test.ts} +0 -0
  82. /package/tests/playwright/qb/auth/{tokenRenewal.test.ts → tempTokenRenewal.test.ts} +0 -0
@@ -1673,6 +1673,209 @@
1673
1673
  };
1674
1674
  }
1675
1675
 
1676
+ /* tslint:disable */
1677
+ /* eslint-disable */
1678
+ /**
1679
+ * Quick Base API
1680
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
1681
+ *
1682
+ * The version of the OpenAPI document: 1.0.0
1683
+ *
1684
+ *
1685
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
1686
+ * https://openapi-generator.tech
1687
+ * Do not edit the class manually.
1688
+ */
1689
+ /**
1690
+ * @export
1691
+ */
1692
+ const CreateFieldRequestPropertiesOpenTargetInEnum = {
1693
+ SameWindow: 'sameWindow',
1694
+ NewWindow: 'newWindow',
1695
+ Popup: 'popup'
1696
+ };
1697
+ /**
1698
+ * @export
1699
+ */
1700
+ const CreateFieldRequestPropertiesSummaryFunctionEnum = {
1701
+ Avg: 'AVG',
1702
+ Sum: 'SUM',
1703
+ Max: 'MAX',
1704
+ Min: 'MIN',
1705
+ StdDev: 'STD-DEV',
1706
+ Count: 'COUNT',
1707
+ CombinedText: 'COMBINED-TEXT',
1708
+ CombinedUser: 'COMBINED-USER',
1709
+ DistinctCount: 'DISTINCT-COUNT'
1710
+ };
1711
+ /**
1712
+ * @export
1713
+ */
1714
+ const CreateFieldRequestPropertiesCurrencyFormatEnum = {
1715
+ Left: 'left',
1716
+ Right: 'right',
1717
+ Middle: 'middle'
1718
+ };
1719
+ /**
1720
+ * @export
1721
+ */
1722
+ const CreateFieldRequestPropertiesVersionModeEnum = {
1723
+ Keepallversions: 'keepallversions',
1724
+ Keeplastversions: 'keeplastversions'
1725
+ };
1726
+ /**
1727
+ * Check if a given object implements the CreateFieldRequestProperties interface.
1728
+ */
1729
+ function instanceOfCreateFieldRequestProperties(value) {
1730
+ return true;
1731
+ }
1732
+ function CreateFieldRequestPropertiesFromJSON(json) {
1733
+ return CreateFieldRequestPropertiesFromJSONTyped(json);
1734
+ }
1735
+ function CreateFieldRequestPropertiesFromJSONTyped(json, ignoreDiscriminator) {
1736
+ if (json == null) {
1737
+ return json;
1738
+ }
1739
+ return {
1740
+ 'numLines': json['numLines'] == null ? undefined : json['numLines'],
1741
+ 'maxLength': json['maxLength'] == null ? undefined : json['maxLength'],
1742
+ 'appendOnly': json['appendOnly'] == null ? undefined : json['appendOnly'],
1743
+ 'sortAsGiven': json['sortAsGiven'] == null ? undefined : json['sortAsGiven'],
1744
+ 'allowMentions': json['allowMentions'] == null ? undefined : json['allowMentions'],
1745
+ 'comments': json['comments'] == null ? undefined : json['comments'],
1746
+ 'doesTotal': json['doesTotal'] == null ? undefined : json['doesTotal'],
1747
+ 'autoSave': json['autoSave'] == null ? undefined : json['autoSave'],
1748
+ 'defaultValueLuid': json['defaultValueLuid'] == null ? undefined : json['defaultValueLuid'],
1749
+ 'useI18NFormat': json['useI18NFormat'] == null ? undefined : json['useI18NFormat'],
1750
+ 'maxVersions': json['maxVersions'] == null ? undefined : json['maxVersions'],
1751
+ 'format': json['format'] == null ? undefined : json['format'],
1752
+ 'carryChoices': json['carryChoices'] == null ? undefined : json['carryChoices'],
1753
+ 'linkText': json['linkText'] == null ? undefined : json['linkText'],
1754
+ 'parentFieldId': json['parentFieldId'] == null ? undefined : json['parentFieldId'],
1755
+ 'displayTimezone': json['displayTimezone'] == null ? undefined : json['displayTimezone'],
1756
+ 'summaryTargetFieldId': json['summaryTargetFieldId'] == null ? undefined : json['summaryTargetFieldId'],
1757
+ 'allowNewChoices': json['allowNewChoices'] == null ? undefined : json['allowNewChoices'],
1758
+ 'defaultToday': json['defaultToday'] == null ? undefined : json['defaultToday'],
1759
+ 'units': json['units'] == null ? undefined : json['units'],
1760
+ 'openTargetIn': json['openTargetIn'] == null ? undefined : json['openTargetIn'],
1761
+ 'lookupTargetFieldId': json['lookupTargetFieldId'] == null ? undefined : json['lookupTargetFieldId'],
1762
+ 'summaryFunction': json['summaryFunction'] == null ? undefined : json['summaryFunction'],
1763
+ 'sourceFieldId': json['sourceFieldId'] == null ? undefined : json['sourceFieldId'],
1764
+ 'doesAverage': json['doesAverage'] == null ? undefined : json['doesAverage'],
1765
+ 'formula': json['formula'] == null ? undefined : json['formula'],
1766
+ 'decimalPlaces': json['decimalPlaces'] == null ? undefined : json['decimalPlaces'],
1767
+ 'defaultCountryCode': json['defaultCountryCode'] == null ? undefined : json['defaultCountryCode'],
1768
+ 'displayMonth': json['displayMonth'] == null ? undefined : json['displayMonth'],
1769
+ 'seeVersions': json['seeVersions'] == null ? undefined : json['seeVersions'],
1770
+ 'defaultKind': json['defaultKind'] == null ? undefined : json['defaultKind'],
1771
+ 'displayEmail': json['displayEmail'] == null ? undefined : json['displayEmail'],
1772
+ 'coverText': json['coverText'] == null ? undefined : json['coverText'],
1773
+ 'currencySymbol': json['currencySymbol'] == null ? undefined : json['currencySymbol'],
1774
+ 'summaryQuery': json['summaryQuery'] == null ? undefined : json['summaryQuery'],
1775
+ 'targetFieldId': json['targetFieldId'] == null ? undefined : json['targetFieldId'],
1776
+ 'displayUser': json['displayUser'] == null ? undefined : json['displayUser'],
1777
+ 'blankIsZero': json['blankIsZero'] == null ? undefined : json['blankIsZero'],
1778
+ 'exact': json['exact'] == null ? undefined : json['exact'],
1779
+ 'defaultDomain': json['defaultDomain'] == null ? undefined : json['defaultDomain'],
1780
+ 'defaultValue': json['defaultValue'] == null ? undefined : json['defaultValue'],
1781
+ 'abbreviate': json['abbreviate'] == null ? undefined : json['abbreviate'],
1782
+ 'numberFormat': json['numberFormat'] == null ? undefined : json['numberFormat'],
1783
+ 'targetTableName': json['targetTableName'] == null ? undefined : json['targetTableName'],
1784
+ 'appearsAs': json['appearsAs'] == null ? undefined : json['appearsAs'],
1785
+ 'width': json['width'] == null ? undefined : json['width'],
1786
+ 'currencyFormat': json['currencyFormat'] == null ? undefined : json['currencyFormat'],
1787
+ 'displayDayOfWeek': json['displayDayOfWeek'] == null ? undefined : json['displayDayOfWeek'],
1788
+ 'summaryReferenceFieldId': json['summaryReferenceFieldId'] == null ? undefined : json['summaryReferenceFieldId'],
1789
+ 'commaStart': json['commaStart'] == null ? undefined : json['commaStart'],
1790
+ 'choices': json['choices'] == null ? undefined : json['choices'],
1791
+ 'targetTableId': json['targetTableId'] == null ? undefined : json['targetTableId'],
1792
+ 'displayRelative': json['displayRelative'] == null ? undefined : json['displayRelative'],
1793
+ 'compositeFields': json['compositeFields'] == null ? undefined : json['compositeFields'],
1794
+ 'displayCheckboxAsText': json['displayCheckboxAsText'] == null ? undefined : json['displayCheckboxAsText'],
1795
+ 'versionMode': json['versionMode'] == null ? undefined : json['versionMode'],
1796
+ 'snapFieldId': json['snapFieldId'] == null ? undefined : json['snapFieldId'],
1797
+ 'hours24': json['hours24'] == null ? undefined : json['hours24'],
1798
+ 'sortAlpha': json['sortAlpha'] == null ? undefined : json['sortAlpha'],
1799
+ 'hasExtension': json['hasExtension'] == null ? undefined : json['hasExtension'],
1800
+ 'useNewWindow': json['useNewWindow'] == null ? undefined : json['useNewWindow'],
1801
+ 'displayAsLink': json['displayAsLink'] == null ? undefined : json['displayAsLink'],
1802
+ 'lookupReferenceFieldId': json['lookupReferenceFieldId'] == null ? undefined : json['lookupReferenceFieldId'],
1803
+ };
1804
+ }
1805
+ function CreateFieldRequestPropertiesToJSON(json) {
1806
+ return CreateFieldRequestPropertiesToJSONTyped(json, false);
1807
+ }
1808
+ function CreateFieldRequestPropertiesToJSONTyped(value, ignoreDiscriminator = false) {
1809
+ if (value == null) {
1810
+ return value;
1811
+ }
1812
+ return {
1813
+ 'numLines': value['numLines'],
1814
+ 'maxLength': value['maxLength'],
1815
+ 'appendOnly': value['appendOnly'],
1816
+ 'sortAsGiven': value['sortAsGiven'],
1817
+ 'allowMentions': value['allowMentions'],
1818
+ 'comments': value['comments'],
1819
+ 'doesTotal': value['doesTotal'],
1820
+ 'autoSave': value['autoSave'],
1821
+ 'defaultValueLuid': value['defaultValueLuid'],
1822
+ 'useI18NFormat': value['useI18NFormat'],
1823
+ 'maxVersions': value['maxVersions'],
1824
+ 'format': value['format'],
1825
+ 'carryChoices': value['carryChoices'],
1826
+ 'linkText': value['linkText'],
1827
+ 'parentFieldId': value['parentFieldId'],
1828
+ 'displayTimezone': value['displayTimezone'],
1829
+ 'summaryTargetFieldId': value['summaryTargetFieldId'],
1830
+ 'allowNewChoices': value['allowNewChoices'],
1831
+ 'defaultToday': value['defaultToday'],
1832
+ 'units': value['units'],
1833
+ 'openTargetIn': value['openTargetIn'],
1834
+ 'lookupTargetFieldId': value['lookupTargetFieldId'],
1835
+ 'summaryFunction': value['summaryFunction'],
1836
+ 'sourceFieldId': value['sourceFieldId'],
1837
+ 'doesAverage': value['doesAverage'],
1838
+ 'formula': value['formula'],
1839
+ 'decimalPlaces': value['decimalPlaces'],
1840
+ 'defaultCountryCode': value['defaultCountryCode'],
1841
+ 'displayMonth': value['displayMonth'],
1842
+ 'seeVersions': value['seeVersions'],
1843
+ 'defaultKind': value['defaultKind'],
1844
+ 'displayEmail': value['displayEmail'],
1845
+ 'coverText': value['coverText'],
1846
+ 'currencySymbol': value['currencySymbol'],
1847
+ 'summaryQuery': value['summaryQuery'],
1848
+ 'targetFieldId': value['targetFieldId'],
1849
+ 'displayUser': value['displayUser'],
1850
+ 'blankIsZero': value['blankIsZero'],
1851
+ 'exact': value['exact'],
1852
+ 'defaultDomain': value['defaultDomain'],
1853
+ 'defaultValue': value['defaultValue'],
1854
+ 'abbreviate': value['abbreviate'],
1855
+ 'numberFormat': value['numberFormat'],
1856
+ 'targetTableName': value['targetTableName'],
1857
+ 'appearsAs': value['appearsAs'],
1858
+ 'width': value['width'],
1859
+ 'currencyFormat': value['currencyFormat'],
1860
+ 'displayDayOfWeek': value['displayDayOfWeek'],
1861
+ 'summaryReferenceFieldId': value['summaryReferenceFieldId'],
1862
+ 'commaStart': value['commaStart'],
1863
+ 'choices': value['choices'],
1864
+ 'targetTableId': value['targetTableId'],
1865
+ 'displayRelative': value['displayRelative'],
1866
+ 'compositeFields': value['compositeFields'],
1867
+ 'displayCheckboxAsText': value['displayCheckboxAsText'],
1868
+ 'versionMode': value['versionMode'],
1869
+ 'snapFieldId': value['snapFieldId'],
1870
+ 'hours24': value['hours24'],
1871
+ 'sortAlpha': value['sortAlpha'],
1872
+ 'hasExtension': value['hasExtension'],
1873
+ 'useNewWindow': value['useNewWindow'],
1874
+ 'displayAsLink': value['displayAsLink'],
1875
+ 'lookupReferenceFieldId': value['lookupReferenceFieldId'],
1876
+ };
1877
+ }
1878
+
1676
1879
  /* tslint:disable */
1677
1880
  /* eslint-disable */
1678
1881
  /**
@@ -1743,6 +1946,7 @@
1743
1946
  'findEnabled': json['findEnabled'] == null ? undefined : json['findEnabled'],
1744
1947
  'doesDataCopy': json['doesDataCopy'] == null ? undefined : json['doesDataCopy'],
1745
1948
  'audited': json['audited'] == null ? undefined : json['audited'],
1949
+ 'properties': json['properties'] == null ? undefined : CreateFieldRequestPropertiesFromJSON(json['properties']),
1746
1950
  };
1747
1951
  }
1748
1952
  function CreateFieldRequestToJSON(json) {
@@ -1766,6 +1970,7 @@
1766
1970
  'findEnabled': value['findEnabled'],
1767
1971
  'doesDataCopy': value['doesDataCopy'],
1768
1972
  'audited': value['audited'],
1973
+ 'properties': CreateFieldRequestPropertiesToJSON(value['properties']),
1769
1974
  };
1770
1975
  }
1771
1976
 
@@ -6361,8 +6566,6 @@
6361
6566
  function instanceOfUpdateFieldRequest(value) {
6362
6567
  if (!('label' in value) || value['label'] === undefined)
6363
6568
  return false;
6364
- if (!('fieldType' in value) || value['fieldType'] === undefined)
6365
- return false;
6366
6569
  return true;
6367
6570
  }
6368
6571
  function UpdateFieldRequestFromJSON(json) {
@@ -6374,7 +6577,7 @@
6374
6577
  }
6375
6578
  return {
6376
6579
  'label': json['label'],
6377
- 'fieldType': json['fieldType'],
6580
+ 'fieldType': json['fieldType'] == null ? undefined : json['fieldType'],
6378
6581
  'fieldHelp': json['fieldHelp'] == null ? undefined : json['fieldHelp'],
6379
6582
  'addToForms': json['addToForms'] == null ? undefined : json['addToForms'],
6380
6583
  'permissions': json['permissions'] == null ? undefined : json['permissions'],
@@ -6386,6 +6589,7 @@
6386
6589
  'findEnabled': json['findEnabled'] == null ? undefined : json['findEnabled'],
6387
6590
  'doesDataCopy': json['doesDataCopy'] == null ? undefined : json['doesDataCopy'],
6388
6591
  'audited': json['audited'] == null ? undefined : json['audited'],
6592
+ 'properties': json['properties'] == null ? undefined : CreateFieldRequestPropertiesFromJSON(json['properties']),
6389
6593
  };
6390
6594
  }
6391
6595
  function UpdateFieldRequestToJSON(json) {
@@ -6409,6 +6613,7 @@
6409
6613
  'findEnabled': value['findEnabled'],
6410
6614
  'doesDataCopy': value['doesDataCopy'],
6411
6615
  'audited': value['audited'],
6616
+ 'properties': CreateFieldRequestPropertiesToJSON(value['properties']),
6412
6617
  };
6413
6618
  }
6414
6619
 
@@ -9446,40 +9651,27 @@
9446
9651
 
9447
9652
  class TokenCache {
9448
9653
  cache;
9449
- lifespan; // Token lifespan in milliseconds
9450
- constructor(lifespan = 4 * 60 * 1000 + 50 * 1000) {
9451
- // Default 4:50
9654
+ tempTokenLifespan;
9655
+ constructor(tempTokenLifespan = 4 * 60 * 1000 + 50 * 1000) {
9452
9656
  this.cache = new Map();
9453
- this.lifespan = lifespan;
9657
+ this.tempTokenLifespan = tempTokenLifespan;
9454
9658
  }
9455
9659
  get(dbid) {
9456
9660
  const entry = this.cache.get(dbid);
9457
9661
  const now = Date.now();
9458
- if (entry && entry.expiresAt > now) {
9662
+ if (entry && entry.expiresAt > now)
9459
9663
  return entry.token;
9460
- }
9461
- return undefined; // Expired or not found
9462
- }
9463
- // New method to get full entry
9464
- getEntry(dbid) {
9465
- const entry = this.cache.get(dbid);
9466
- const now = Date.now();
9467
- if (entry && entry.expiresAt > now) {
9468
- return entry;
9469
- }
9470
- return undefined; // Expired or not found
9664
+ if (entry)
9665
+ this.cache.delete(dbid); // Clean up expired temp tokens
9666
+ return undefined;
9471
9667
  }
9472
- set(dbid, token) {
9668
+ set(dbid, token, lifespan) {
9473
9669
  const now = Date.now();
9474
9670
  this.cache.set(dbid, {
9475
9671
  token,
9476
- expiresAt: now + this.lifespan,
9672
+ expiresAt: now + (lifespan || this.tempTokenLifespan),
9477
9673
  });
9478
9674
  }
9479
- dump() {
9480
- return Array.from(this.cache.entries());
9481
- }
9482
- // New method to clear the cache
9483
9675
  clear() {
9484
9676
  this.cache.clear();
9485
9677
  }
@@ -9493,20 +9685,405 @@
9493
9685
  .replace(/^(\w)/, (_, c) => c.toLowerCase());
9494
9686
  }
9495
9687
 
9688
+ // src/authorizationStrategy.ts
9689
+ class TempTokenStrategy {
9690
+ tokenCache;
9691
+ initialTempToken;
9692
+ constructor(tokenCache, initialTempToken) {
9693
+ this.tokenCache = tokenCache;
9694
+ this.initialTempToken = initialTempToken;
9695
+ }
9696
+ async getToken(dbid) {
9697
+ return this.tokenCache.get(dbid) || this.initialTempToken;
9698
+ }
9699
+ applyHeaders(headers, token) {
9700
+ headers["Authorization"] = `QB-TEMP-TOKEN ${token}`;
9701
+ }
9702
+ async handleError(status, params, fetchTempToken, attempt, maxAttempts, debug, methodName) {
9703
+ if (status !== 401 || attempt >= maxAttempts - 1)
9704
+ return null;
9705
+ if (debug)
9706
+ console.log(`Authorization error for ${methodName || "method"} (temp token), refreshing token:`);
9707
+ const dbid = extractDbid(params);
9708
+ if (!dbid) {
9709
+ if (debug)
9710
+ console.log(`No dbid available for ${methodName || "method"}, skipping token refresh`);
9711
+ return null;
9712
+ }
9713
+ if (debug)
9714
+ console.log(`Refreshing temp token for dbid: ${dbid}`);
9715
+ const newToken = await fetchTempToken(dbid);
9716
+ this.tokenCache.set(dbid, newToken);
9717
+ return newToken;
9718
+ }
9719
+ }
9720
+ class UserTokenStrategy {
9721
+ userToken;
9722
+ constructor(userToken) {
9723
+ this.userToken = userToken;
9724
+ }
9725
+ async getToken(_dbid) {
9726
+ return this.userToken;
9727
+ }
9728
+ applyHeaders(headers, token) {
9729
+ headers["Authorization"] = `QB-USER-TOKEN ${token}`;
9730
+ }
9731
+ async handleError(status, _params, _fetchTempToken, attempt, maxAttempts, debug, methodName) {
9732
+ if (status !== 401 || attempt >= maxAttempts - 1)
9733
+ return null;
9734
+ if (debug)
9735
+ console.log(`Retrying ${methodName || "method"} with existing user token: ${this.userToken.substring(0, 10)}...`);
9736
+ return this.userToken;
9737
+ }
9738
+ }
9739
+ class SsoTokenStrategy {
9740
+ samlToken;
9741
+ realm;
9742
+ fetchApi;
9743
+ debug;
9744
+ currentToken;
9745
+ constructor(samlToken, realm, fetchApi, debug = false) {
9746
+ this.samlToken = samlToken;
9747
+ this.realm = realm;
9748
+ this.fetchApi = fetchApi;
9749
+ this.debug = debug;
9750
+ }
9751
+ async getToken(_dbid) {
9752
+ if (!this.currentToken) {
9753
+ this.currentToken = await this.fetchSsoToken({
9754
+ grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
9755
+ requested_token_type: "urn:quickbase:params:oauth:token-type:temp_token",
9756
+ subject_token: this.samlToken,
9757
+ subject_token_type: "urn:ietf:params:oauth:token-type:saml2",
9758
+ });
9759
+ }
9760
+ return this.currentToken;
9761
+ }
9762
+ applyHeaders(headers, token) {
9763
+ headers["Authorization"] = `QB-TEMP-TOKEN ${token}`;
9764
+ }
9765
+ async handleError(status, _params, _fetchTempToken, attempt, maxAttempts, debug, methodName) {
9766
+ if (status !== 401 || attempt >= maxAttempts - 1)
9767
+ return null;
9768
+ if (debug || this.debug) {
9769
+ console.log(`Authorization error for ${methodName || "method"} (SSO), refreshing token`);
9770
+ }
9771
+ const newToken = await this.refreshSsoToken(debug || this.debug);
9772
+ if (newToken) {
9773
+ this.currentToken = newToken;
9774
+ return newToken;
9775
+ }
9776
+ return null;
9777
+ }
9778
+ async refreshSsoToken(debug = false) {
9779
+ const payload = {
9780
+ grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
9781
+ requested_token_type: "urn:quickbase:params:oauth:token-type:temp_token",
9782
+ subject_token: this.samlToken,
9783
+ subject_token_type: "urn:ietf:params:oauth:token-type:saml2",
9784
+ };
9785
+ const response = await this.fetchApi(`https://api.quickbase.com/v1/auth/oauth/token`, {
9786
+ method: "POST",
9787
+ headers: {
9788
+ "QB-Realm-Hostname": `${this.realm}.quickbase.com`,
9789
+ "Content-Type": "application/json",
9790
+ },
9791
+ body: JSON.stringify(payload),
9792
+ credentials: "omit",
9793
+ });
9794
+ if (!response.ok) {
9795
+ const errorBody = await response.json().catch(() => ({}));
9796
+ if (debug) {
9797
+ console.log(`[SSO Refresh] Failed: ${response.status}`, errorBody);
9798
+ }
9799
+ throw new Error(`SSO token refresh failed: ${errorBody.message || "Unknown error"}`);
9800
+ }
9801
+ const result = await response.json();
9802
+ const newToken = result.access_token;
9803
+ if (!newToken) {
9804
+ throw new Error("No access token returned from SSO token exchange");
9805
+ }
9806
+ if (debug) {
9807
+ console.log(`[SSO Refresh] New token: ${newToken.substring(0, 10)}...`);
9808
+ }
9809
+ return newToken;
9810
+ }
9811
+ async fetchSsoToken(params) {
9812
+ const response = await this.fetchApi(`https://api.quickbase.com/v1/auth/oauth/token`, {
9813
+ method: "POST",
9814
+ headers: {
9815
+ "QB-Realm-Hostname": `${this.realm}.quickbase.com`,
9816
+ "Content-Type": "application/json",
9817
+ },
9818
+ body: JSON.stringify(params),
9819
+ credentials: "omit",
9820
+ });
9821
+ if (!response.ok) {
9822
+ const errorBody = await response.json().catch(() => ({}));
9823
+ if (this.debug) {
9824
+ console.log(`[fetchSsoToken] Failed: ${response.status}`, errorBody);
9825
+ }
9826
+ throw new Error(`SSO token fetch failed: ${errorBody.message || "Unknown error"}`);
9827
+ }
9828
+ const result = await response.json();
9829
+ const newToken = result.access_token;
9830
+ if (!newToken) {
9831
+ throw new Error("No access token returned from SSO token exchange");
9832
+ }
9833
+ if (this.debug) {
9834
+ console.log(`[fetchSsoToken] Fetched token: ${newToken.substring(0, 10)}...`);
9835
+ }
9836
+ return newToken;
9837
+ }
9838
+ }
9839
+ function extractDbid(params) {
9840
+ return (params.dbid ||
9841
+ params.tableId ||
9842
+ params.appId ||
9843
+ params.body?.from ||
9844
+ params.body?.to);
9845
+ }
9846
+
9847
+ // src/RateLimitError.ts
9848
+ class RateLimitError extends Error {
9849
+ status;
9850
+ retryAfter;
9851
+ constructor(message, status, retryAfter) {
9852
+ super(message);
9853
+ this.name = "RateLimitError";
9854
+ this.status = status;
9855
+ this.retryAfter = retryAfter; // Seconds from Retry-After header, if present
9856
+ }
9857
+ }
9858
+
9859
+ // src/invokeMethod.ts
9860
+ async function invokeMethod(methodName, params, methodMap, baseHeaders, authStrategy, rateLimiter, fetchTempToken, transformDates, debug, convertDates) {
9861
+ console.log("[invokeMethod] Starting for method:", methodName);
9862
+ const methodInfo = methodMap[methodName];
9863
+ if (!methodInfo)
9864
+ throw new Error(`Method ${methodName} not found`);
9865
+ const hasBody = "body" in params && params.body !== undefined;
9866
+ const body = hasBody ? params.body : undefined;
9867
+ const restParams = hasBody
9868
+ ? Object.fromEntries(Object.entries(params).filter(([key]) => key !== "body"))
9869
+ : { ...params };
9870
+ const requestParameters = {
9871
+ ...restParams,
9872
+ ...(hasBody ? { generated: body } : {}),
9873
+ };
9874
+ const requestOptions = {
9875
+ credentials: methodName === "getTempTokenDBID" ? "include" : "omit",
9876
+ method: methodInfo.httpMethod,
9877
+ };
9878
+ let dbid = extractDbid(params);
9879
+ console.log("[invokeMethod] Extracted dbid:", dbid);
9880
+ let token = dbid
9881
+ ? await authStrategy.getToken(dbid)
9882
+ : await authStrategy.getToken("");
9883
+ console.log("[invokeMethod] Initial token:", token);
9884
+ if (!token && dbid) {
9885
+ token = await fetchTempToken(dbid);
9886
+ authStrategy.applyHeaders(baseHeaders, token);
9887
+ requestOptions.headers = { ...baseHeaders };
9888
+ console.log("[invokeMethod] Fetched new token:", token);
9889
+ }
9890
+ if (token) {
9891
+ authStrategy.applyHeaders(baseHeaders, token);
9892
+ requestOptions.headers = { ...baseHeaders };
9893
+ console.log("[invokeMethod] Token found, headers set:", requestOptions.headers);
9894
+ if (methodName === "getTempTokenDBID") {
9895
+ console.log("[invokeMethod] Using cached token:", token);
9896
+ return { temporaryAuthorization: token };
9897
+ }
9898
+ }
9899
+ if (debug) {
9900
+ console.log(`[${methodName}] requestParameters:`, requestParameters);
9901
+ console.log(`[${methodName}] requestOptions:`, requestOptions);
9902
+ }
9903
+ async function processResponse(rawResponse) {
9904
+ if (debug)
9905
+ console.log(`[${methodName}] rawResponse:`, rawResponse);
9906
+ if (rawResponse instanceof Response) {
9907
+ const contentType = rawResponse.headers
9908
+ .get("Content-Type")
9909
+ ?.toLowerCase();
9910
+ if (debug)
9911
+ console.log(`[${methodName}] contentType:`, contentType);
9912
+ if (contentType?.includes("application/json")) {
9913
+ const jsonResponse = await rawResponse.json();
9914
+ return transformDates(jsonResponse, convertDates);
9915
+ }
9916
+ return rawResponse;
9917
+ }
9918
+ if (rawResponse && typeof rawResponse.value === "function") {
9919
+ const response = await rawResponse.value();
9920
+ if (debug)
9921
+ console.log(`[${methodName}] Resolved JSONApiResponse:`, response);
9922
+ return transformDates(response, convertDates);
9923
+ }
9924
+ return transformDates(rawResponse, convertDates);
9925
+ }
9926
+ async function parseErrorResponse(response) {
9927
+ let message = "Unknown error";
9928
+ let status = response.status || 500;
9929
+ try {
9930
+ const contentType = response.headers?.get("Content-Type")?.toLowerCase() ||
9931
+ "application/json";
9932
+ if (contentType.includes("application/json") &&
9933
+ typeof response.json === "function") {
9934
+ const errorBody = await response.json();
9935
+ if (errorBody &&
9936
+ typeof errorBody === "object" &&
9937
+ "message" in errorBody) {
9938
+ message = errorBody.message;
9939
+ }
9940
+ else {
9941
+ message = "Invalid error response format";
9942
+ }
9943
+ }
9944
+ else if (typeof response.text === "function") {
9945
+ message = (await response.text()) || message;
9946
+ }
9947
+ }
9948
+ catch (e) {
9949
+ if (debug)
9950
+ console.log(`[${methodName}] Error parsing response body:`, e);
9951
+ message = "Failed to parse error response";
9952
+ }
9953
+ console.log("[invokeMethod] Parsed error - status:", status, "message:", message);
9954
+ return { message, status };
9955
+ }
9956
+ let attempt = 0;
9957
+ const maxAttempts = rateLimiter.maxRetries + 1;
9958
+ while (attempt < maxAttempts) {
9959
+ console.log("[invokeMethod] Attempt:", attempt + 1, "of", maxAttempts);
9960
+ try {
9961
+ await rateLimiter.throttle();
9962
+ console.log("[invokeMethod] About to call API for method:", methodName);
9963
+ const response = await methodInfo.method(requestParameters, requestOptions);
9964
+ console.log("[invokeMethod] API call completed for method:", methodName);
9965
+ return await processResponse(response);
9966
+ }
9967
+ catch (error) {
9968
+ let status;
9969
+ let message;
9970
+ let response;
9971
+ console.log("[invokeMethod] Caught error:", error);
9972
+ if (error instanceof ResponseError && error.response) {
9973
+ response = error.response;
9974
+ ({ message, status } = await parseErrorResponse(response));
9975
+ }
9976
+ else if (error instanceof Response) {
9977
+ response = error;
9978
+ ({ message, status } = await parseErrorResponse(response));
9979
+ }
9980
+ else {
9981
+ if (debug)
9982
+ console.log(`[${methodName}] Unexpected error:`, error);
9983
+ throw error; // Rethrow non-response errors
9984
+ }
9985
+ console.log("[invokeMethod] Handling error with status:", status);
9986
+ if (status === 429) {
9987
+ if (!(error instanceof ResponseError)) {
9988
+ throw new Error("Expected ResponseError for 429 handling"); // Shouldn't happen
9989
+ }
9990
+ const delay = await rateLimiter.handle429(error, attempt + 1);
9991
+ if (debug)
9992
+ console.log(`[${methodName}] 429 delay: ${delay}ms`);
9993
+ if (attempt + 1 === maxAttempts) {
9994
+ throw new RateLimitError(`API Error: ${message} (Status: ${status})`, status, response.headers.get("Retry-After")
9995
+ ? parseInt(response.headers.get("Retry-After"), 10)
9996
+ : undefined);
9997
+ }
9998
+ await new Promise((resolve) => setTimeout(resolve, delay));
9999
+ attempt++;
10000
+ continue;
10001
+ }
10002
+ const newToken = await authStrategy.handleError(status, params, fetchTempToken, attempt, maxAttempts, debug, methodName);
10003
+ if (newToken) {
10004
+ token = newToken;
10005
+ authStrategy.applyHeaders(baseHeaders, token);
10006
+ requestOptions.headers = { ...baseHeaders };
10007
+ attempt++;
10008
+ if (debug)
10009
+ console.log(`[${methodName}] Retrying with token: ${token.substring(0, 10)}...`);
10010
+ continue;
10011
+ }
10012
+ throw new Error(`API Error: ${message} (Status: ${status})`);
10013
+ }
10014
+ }
10015
+ throw new Error(`API Error: Exhausted retries after ${maxAttempts} attempts`);
10016
+ }
10017
+
10018
+ // src/ThrottleBucket.ts
10019
+ class ThrottleBucket {
10020
+ tokens;
10021
+ maxTokens;
10022
+ refillRate; // Tokens per second
10023
+ lastRefill;
10024
+ pending = Promise.resolve(); // Queue for sequential execution
10025
+ constructor(rate, burst) {
10026
+ this.tokens = burst;
10027
+ this.maxTokens = burst;
10028
+ this.refillRate = rate;
10029
+ this.lastRefill = Date.now();
10030
+ }
10031
+ refill() {
10032
+ const now = Date.now();
10033
+ const elapsed = (now - this.lastRefill) / 1000; // Seconds elapsed
10034
+ const newTokens = elapsed * this.refillRate;
10035
+ this.tokens = Math.min(this.maxTokens, this.tokens + newTokens);
10036
+ this.lastRefill = now;
10037
+ }
10038
+ async acquire() {
10039
+ // Chain the new acquisition onto the pending queue
10040
+ const previous = this.pending;
10041
+ this.pending = (async () => {
10042
+ await previous; // Wait for prior calls to complete
10043
+ this.refill();
10044
+ if (this.tokens >= 1) {
10045
+ this.tokens -= 1;
10046
+ return;
10047
+ }
10048
+ const waitTime = ((1 - this.tokens) / this.refillRate) * 1000; // ms until next token
10049
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
10050
+ this.refill();
10051
+ this.tokens -= 1;
10052
+ })();
10053
+ await this.pending;
10054
+ }
10055
+ }
10056
+
10057
+ class RateLimiter {
10058
+ throttleBucket;
10059
+ maxRetries;
10060
+ retryDelay;
10061
+ constructor(throttleBucket, maxRetries = 3, retryDelay = 1000) {
10062
+ this.throttleBucket = throttleBucket;
10063
+ this.maxRetries = maxRetries;
10064
+ this.retryDelay = retryDelay;
10065
+ }
10066
+ async throttle() {
10067
+ if (this.throttleBucket) {
10068
+ await this.throttleBucket.acquire();
10069
+ }
10070
+ }
10071
+ async handle429(error, attempt) {
10072
+ // Remove the throw here; let invokeMethod handle exhaustion
10073
+ const retryAfter = error.response.headers.get("Retry-After");
10074
+ return retryAfter
10075
+ ? parseInt(retryAfter, 10) * 1000
10076
+ : this.retryDelay * Math.pow(2, attempt - 1);
10077
+ }
10078
+ }
10079
+
10080
+ // src/quickbaseClient.ts
9496
10081
  const getParamNames = (fn) => fn
9497
10082
  .toString()
9498
10083
  .slice(fn.toString().indexOf("(") + 1, fn.toString().indexOf(")"))
9499
10084
  .split(",")
9500
10085
  .map((p) => p.trim().split("=")[0]?.trim())
9501
10086
  .filter((p) => p && !p.match(/^\{/) && p !== "options");
9502
- const extractDbid = (params, errorMessage) => {
9503
- const dbid = params.dbid || params.tableId || params.appId;
9504
- if (!dbid) {
9505
- throw new Error(errorMessage);
9506
- }
9507
- return dbid;
9508
- };
9509
- // Utility to convert ISO date strings to Date objects recursively, with optional conversion
9510
10087
  function transformDates(obj, convertStringsToDates = true) {
9511
10088
  if (obj === null || obj === undefined)
9512
10089
  return obj;
@@ -9528,40 +10105,59 @@
9528
10105
  }
9529
10106
  return obj;
9530
10107
  }
10108
+ function inferHttpMethod(methodSource, debug) {
10109
+ const methodMatches = [
10110
+ ...methodSource.matchAll(/method:\s*['"]?(\w+)['"]?/gi),
10111
+ ];
10112
+ const method = methodMatches.length > 0
10113
+ ? methodMatches[methodMatches.length - 1][1].toUpperCase()
10114
+ : "GET";
10115
+ if (debug) {
10116
+ console.log(`[inferHttpMethod] Source:`, methodSource);
10117
+ console.log(`[inferHttpMethod] All matches:`, methodMatches.map((m) => m[0]));
10118
+ console.log(`[inferHttpMethod] Extracted method:`, method);
10119
+ }
10120
+ return method;
10121
+ }
9531
10122
  function quickbase(config) {
9532
- const { realm, userToken, tempToken: initialTempToken, useTempTokens, fetchApi, debug, convertDates = true, // Default to true for backward compatibility
9533
- } = config;
9534
- const baseUrl = `https://api.quickbase.com/v1`;
9535
- const tokenCache = new TokenCache();
10123
+ const { realm, userToken, tempToken, useTempTokens, useSso, samlToken, fetchApi, debug, convertDates = true, tempTokenLifespan = 290000, throttle = { rate: 10, burst: 10 }, maxRetries = 3, retryDelay = 1000, tokenCache: providedTokenCache, baseUrl = "https://api.quickbase.com/v1", } = config;
10124
+ const tokenCache = providedTokenCache || new TokenCache(tempTokenLifespan);
10125
+ const throttleBucket = throttle
10126
+ ? new ThrottleBucket(throttle.rate, throttle.burst)
10127
+ : null;
10128
+ const rateLimiter = new RateLimiter(throttleBucket, maxRetries, retryDelay);
10129
+ const defaultFetch = typeof globalThis.window !== "undefined"
10130
+ ? globalThis.window.fetch.bind(globalThis.window)
10131
+ : undefined;
10132
+ const effectiveFetch = fetchApi || defaultFetch;
10133
+ if (!effectiveFetch) {
10134
+ throw new Error("No fetch implementation available");
10135
+ }
10136
+ const authStrategy = useSso
10137
+ ? new SsoTokenStrategy(samlToken || "", realm, effectiveFetch, debug)
10138
+ : useTempTokens
10139
+ ? new TempTokenStrategy(tokenCache, tempToken)
10140
+ : new UserTokenStrategy(userToken || "");
9536
10141
  const baseHeaders = {
9537
10142
  "QB-Realm-Hostname": `${realm}.quickbase.com`,
9538
10143
  "Content-Type": "application/json",
9539
10144
  };
9540
- if (initialTempToken) {
9541
- baseHeaders["Authorization"] = `QB-TEMP-TOKEN ${initialTempToken}`;
9542
- }
9543
- else if (userToken && !useTempTokens) {
9544
- baseHeaders["Authorization"] = `QB-USER-TOKEN ${userToken}`;
9545
- }
9546
- const defaultFetch = typeof globalThis.window !== "undefined"
9547
- ? globalThis.window.fetch.bind(globalThis.window)
9548
- : undefined;
9549
10145
  const configuration = new Configuration({
9550
10146
  basePath: baseUrl,
9551
10147
  headers: { ...baseHeaders },
9552
- fetchApi: fetchApi || defaultFetch,
10148
+ fetchApi: effectiveFetch,
9553
10149
  credentials: "omit",
9554
10150
  });
9555
- if (!configuration.fetchApi && typeof globalThis.window === "undefined") {
9556
- throw new Error("fetchApi must be provided in non-browser environments (e.g., Node.js)");
9557
- }
10151
+ // Removed redundant check:
10152
+ // if (!configuration.fetchApi && typeof globalThis.window === "undefined") {
10153
+ // throw new Error("fetchApi must be provided in non-browser environments (e.g., Node.js)");
10154
+ // }
9558
10155
  const apiInstances = Object.fromEntries(Object.entries(apis)
9559
10156
  .filter(([name]) => name.endsWith("Api"))
9560
10157
  .map(([name, ApiClass]) => [
9561
10158
  name.replace("Api", "").toLowerCase(),
9562
10159
  new ApiClass(configuration),
9563
10160
  ]));
9564
- const methodMap = buildMethodMap();
9565
10161
  function buildMethodMap() {
9566
10162
  const methodMap = {};
9567
10163
  const isValidMethod = (name) => !name.startsWith("_") &&
@@ -9573,25 +10169,28 @@
9573
10169
  typeof api[name] === "function")
9574
10170
  .forEach((rawMethodName) => {
9575
10171
  const simplifiedName = simplifyName(rawMethodName);
9576
- const method = api[rawMethodName];
10172
+ const rawMethodKey = `${rawMethodName}Raw`;
10173
+ const method = api[rawMethodKey] || api[rawMethodName];
9577
10174
  const boundMethod = method.bind(api);
9578
10175
  if (typeof boundMethod === "function" && boundMethod.length <= 2) {
10176
+ const methodSource = method.toString();
9579
10177
  methodMap[simplifiedName] = {
9580
10178
  api,
9581
10179
  method: boundMethod,
9582
10180
  paramMap: getParamNames(method),
10181
+ httpMethod: inferHttpMethod(methodSource, debug),
9583
10182
  };
9584
10183
  }
9585
10184
  });
9586
10185
  }
10186
+ if (debug) {
10187
+ console.log("[buildMethodMap] Methods:", Object.keys(methodMap));
10188
+ }
9587
10189
  return methodMap;
9588
10190
  }
10191
+ const methodMap = buildMethodMap();
9589
10192
  const fetchTempToken = async (dbid) => {
9590
- const effectiveFetch = fetchApi || defaultFetch;
9591
- if (!effectiveFetch) {
9592
- throw new Error("No fetch implementation available for fetching temp token");
9593
- }
9594
- const response = await effectiveFetch(`https://api.quickbase.com/v1/auth/temporary/${dbid}`, {
10193
+ const response = await effectiveFetch(`${baseUrl}/auth/temporary/${dbid}`, {
9595
10194
  method: "GET",
9596
10195
  headers: { ...baseHeaders },
9597
10196
  credentials: "include",
@@ -9601,155 +10200,32 @@
9601
10200
  throw new Error(`API Error: ${errorBody.message || "Unknown error"} (Status: ${response.status})`);
9602
10201
  }
9603
10202
  const tokenResult = await response.json();
10203
+ console.log(`[fetchTempToken] Response:`, tokenResult);
9604
10204
  const token = tokenResult.temporaryAuthorization;
9605
10205
  if (!token) {
9606
10206
  throw new Error("No temporary token returned from API");
9607
10207
  }
9608
- tokenCache.set(dbid, token);
10208
+ tokenCache.set(dbid, token, tempTokenLifespan);
9609
10209
  if (debug) {
9610
10210
  console.log(`Fetched and cached new token for dbid: ${dbid}`, token);
9611
10211
  }
9612
10212
  return token;
9613
10213
  };
9614
- async function invokeMethod(methodName, params, retryCount = 0) {
9615
- const methodInfo = methodMap[methodName];
9616
- if (!methodInfo) {
9617
- throw new Error(`Method ${methodName} not found`);
9618
- }
9619
- // Safely handle body extraction
9620
- const hasBody = "body" in params && params.body !== undefined;
9621
- const body = hasBody ? params.body : undefined;
9622
- const restParams = hasBody
9623
- ? Object.fromEntries(Object.entries(params).filter(([key]) => key !== "body"))
9624
- : { ...params };
9625
- // Construct requestParameters with 'generated' for body
9626
- const requestParameters = {
9627
- ...restParams,
9628
- ...(body ? { generated: { ...body } } : {}),
9629
- };
9630
- let requestOptions = {
9631
- credentials: "omit",
9632
- };
9633
- const selectedToken = initialTempToken || (userToken && !useTempTokens ? userToken : undefined);
9634
- if (methodName === "getTempTokenDBID" && useTempTokens) {
9635
- const dbid = extractDbid(params, "No dbid provided for getTempTokenDBID");
9636
- const cachedToken = tokenCache.get(dbid);
9637
- if (cachedToken) {
9638
- return { temporaryAuthorization: cachedToken };
9639
- }
9640
- }
9641
- let authorizationToken = selectedToken;
9642
- if (useTempTokens && !authorizationToken) {
9643
- const dbid = extractDbid(params, `No dbid found in params for ${methodName} to fetch temp token`);
9644
- const cachedToken = tokenCache.get(dbid);
9645
- authorizationToken = cachedToken || (await fetchTempToken(dbid));
9646
- if (methodName === "getTempTokenDBID") {
9647
- return { temporaryAuthorization: authorizationToken };
9648
- }
9649
- requestOptions.headers = {
9650
- ...baseHeaders,
9651
- Authorization: `QB-TEMP-TOKEN ${authorizationToken}`,
9652
- };
9653
- }
9654
- else if (authorizationToken) {
9655
- requestOptions.headers = {
9656
- ...baseHeaders,
9657
- Authorization: `QB-USER-TOKEN ${authorizationToken}`,
9658
- };
9659
- }
9660
- if (debug) {
9661
- console.log(`[${methodName}] requestParameters:`, requestParameters);
9662
- console.log(`[${methodName}] requestOptions:`, requestOptions);
9663
- }
9664
- try {
9665
- const response = await methodInfo.method(requestParameters, requestOptions);
9666
- if (debug) {
9667
- console.log(`[${methodName}] rawResponse:`, response);
9668
- }
9669
- if (response instanceof Response) {
9670
- const contentType = response.headers.get("Content-Type")?.toLowerCase();
9671
- if (debug) {
9672
- console.log(`[${methodName}] contentType:`, contentType);
9673
- }
9674
- if (contentType?.includes("application/octet-stream")) {
9675
- return (await response.arrayBuffer());
9676
- }
9677
- else if (contentType?.includes("application/x-yaml") ||
9678
- contentType?.includes("text/yaml")) {
9679
- return (await response.text());
9680
- }
9681
- else if (contentType?.includes("application/json")) {
9682
- const jsonResponse = await response.json();
9683
- if (debug) {
9684
- console.log(`[${methodName}] jsonResponse:`, jsonResponse);
9685
- }
9686
- const transformedResponse = transformDates(jsonResponse, convertDates);
9687
- if (debug) {
9688
- console.log(`[${methodName}] transformedResponse:`, transformedResponse);
9689
- }
9690
- return transformedResponse;
9691
- }
9692
- return response;
9693
- }
9694
- else {
9695
- if (debug) {
9696
- console.log(`[${methodName}] non-Response return, applying transform:`, response);
9697
- }
9698
- const transformedResponse = transformDates(response, convertDates);
9699
- if (debug) {
9700
- console.log(`[${methodName}] transformedNonResponse:`, transformedResponse);
9701
- }
9702
- return transformedResponse;
9703
- }
9704
- }
9705
- catch (error) {
9706
- if (error instanceof ResponseError &&
9707
- error.response.status === 401 &&
9708
- retryCount < 1 &&
9709
- useTempTokens) {
9710
- if (debug) {
9711
- console.log(`Authorization error for ${methodName}, refreshing token:`, error.message);
9712
- }
9713
- const dbid = extractDbid(params, `No dbid to refresh token after authorization error`);
9714
- authorizationToken = await fetchTempToken(dbid);
9715
- requestOptions.headers = {
9716
- ...baseHeaders,
9717
- Authorization: `QB-TEMP-TOKEN ${authorizationToken}`,
9718
- };
9719
- if (debug) {
9720
- console.log(`Retrying ${methodName} with new token`);
9721
- }
9722
- return invokeMethod(methodName, params, retryCount + 1);
9723
- }
9724
- if (error instanceof ResponseError) {
9725
- let errorMessage = error.message;
9726
- try {
9727
- const errorBody = await error.response.json();
9728
- if (debug) {
9729
- console.log(`Error response body for ${methodName}:`, errorBody);
9730
- }
9731
- errorMessage = errorBody.message || errorMessage;
9732
- }
9733
- catch (e) {
9734
- // Silent fail on parse error
9735
- }
9736
- throw new Error(`API Error: ${errorMessage} (Status: ${error.response.status})`);
9737
- }
9738
- throw error;
9739
- }
9740
- }
9741
- const proxy = new Proxy({}, {
10214
+ const proxyHandler = {
9742
10215
  get: (_, prop) => {
10216
+ console.log("[proxy] Accessing:", prop, "in methodMap:", prop in methodMap);
9743
10217
  if (prop in methodMap) {
9744
10218
  const methodName = prop;
9745
- return (params) => invokeMethod(methodName, params);
10219
+ return (params) => invokeMethod(methodName, params, methodMap, baseHeaders, authStrategy, rateLimiter, fetchTempToken, transformDates, debug, convertDates);
9746
10220
  }
10221
+ console.log("[proxy] Method not found:", prop);
9747
10222
  return undefined;
9748
10223
  },
9749
- });
10224
+ };
10225
+ const proxy = new Proxy({}, proxyHandler);
9750
10226
  if (debug) {
9751
10227
  console.log("[createClient] Config:", config);
9752
- console.log("[createClient] Returning:", proxy);
10228
+ console.log("[createClient] Proxy created:", proxy);
9753
10229
  }
9754
10230
  return proxy;
9755
10231
  }
@@ -9873,6 +10349,14 @@
9873
10349
  exports.CreateFieldRequestFieldTypeEnum = CreateFieldRequestFieldTypeEnum;
9874
10350
  exports.CreateFieldRequestFromJSON = CreateFieldRequestFromJSON;
9875
10351
  exports.CreateFieldRequestFromJSONTyped = CreateFieldRequestFromJSONTyped;
10352
+ exports.CreateFieldRequestPropertiesCurrencyFormatEnum = CreateFieldRequestPropertiesCurrencyFormatEnum;
10353
+ exports.CreateFieldRequestPropertiesFromJSON = CreateFieldRequestPropertiesFromJSON;
10354
+ exports.CreateFieldRequestPropertiesFromJSONTyped = CreateFieldRequestPropertiesFromJSONTyped;
10355
+ exports.CreateFieldRequestPropertiesOpenTargetInEnum = CreateFieldRequestPropertiesOpenTargetInEnum;
10356
+ exports.CreateFieldRequestPropertiesSummaryFunctionEnum = CreateFieldRequestPropertiesSummaryFunctionEnum;
10357
+ exports.CreateFieldRequestPropertiesToJSON = CreateFieldRequestPropertiesToJSON;
10358
+ exports.CreateFieldRequestPropertiesToJSONTyped = CreateFieldRequestPropertiesToJSONTyped;
10359
+ exports.CreateFieldRequestPropertiesVersionModeEnum = CreateFieldRequestPropertiesVersionModeEnum;
9876
10360
  exports.CreateFieldRequestToJSON = CreateFieldRequestToJSON;
9877
10361
  exports.CreateFieldRequestToJSONTyped = CreateFieldRequestToJSONTyped;
9878
10362
  exports.CreateRelationship200ResponseFromJSON = CreateRelationship200ResponseFromJSON;
@@ -10381,6 +10865,7 @@
10381
10865
  exports.instanceOfCreateAppRequest = instanceOfCreateAppRequest;
10382
10866
  exports.instanceOfCreateField200Response = instanceOfCreateField200Response;
10383
10867
  exports.instanceOfCreateFieldRequest = instanceOfCreateFieldRequest;
10868
+ exports.instanceOfCreateFieldRequestProperties = instanceOfCreateFieldRequestProperties;
10384
10869
  exports.instanceOfCreateRelationship200Response = instanceOfCreateRelationship200Response;
10385
10870
  exports.instanceOfCreateRelationshipRequest = instanceOfCreateRelationshipRequest;
10386
10871
  exports.instanceOfCreateSolution200Response = instanceOfCreateSolution200Response;