featurebase-node 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +31 -0
  3. package/client.d.mts +12 -6
  4. package/client.d.mts.map +1 -1
  5. package/client.d.ts +12 -6
  6. package/client.d.ts.map +1 -1
  7. package/client.js +10 -0
  8. package/client.js.map +1 -1
  9. package/client.mjs +10 -0
  10. package/client.mjs.map +1 -1
  11. package/core/pagination.d.mts +54 -0
  12. package/core/pagination.d.mts.map +1 -0
  13. package/core/pagination.d.ts +54 -0
  14. package/core/pagination.d.ts.map +1 -0
  15. package/core/pagination.js +101 -0
  16. package/core/pagination.js.map +1 -0
  17. package/core/pagination.mjs +95 -0
  18. package/core/pagination.mjs.map +1 -0
  19. package/index.d.mts +1 -0
  20. package/index.d.mts.map +1 -1
  21. package/index.d.ts +1 -0
  22. package/index.d.ts.map +1 -1
  23. package/index.js +3 -1
  24. package/index.js.map +1 -1
  25. package/index.mjs +1 -0
  26. package/index.mjs.map +1 -1
  27. package/package.json +11 -1
  28. package/pagination.d.mts +2 -0
  29. package/pagination.d.mts.map +1 -0
  30. package/pagination.d.ts +2 -0
  31. package/pagination.d.ts.map +1 -0
  32. package/pagination.js +6 -0
  33. package/pagination.js.map +1 -0
  34. package/pagination.mjs +2 -0
  35. package/pagination.mjs.map +1 -0
  36. package/resources/changelogs/changelogs.d.mts +9 -53
  37. package/resources/changelogs/changelogs.d.mts.map +1 -1
  38. package/resources/changelogs/changelogs.d.ts +9 -53
  39. package/resources/changelogs/changelogs.d.ts.map +1 -1
  40. package/resources/changelogs/changelogs.js +6 -2
  41. package/resources/changelogs/changelogs.js.map +1 -1
  42. package/resources/changelogs/changelogs.mjs +6 -2
  43. package/resources/changelogs/changelogs.mjs.map +1 -1
  44. package/resources/changelogs/index.d.mts +1 -1
  45. package/resources/changelogs/index.d.mts.map +1 -1
  46. package/resources/changelogs/index.d.ts +1 -1
  47. package/resources/changelogs/index.d.ts.map +1 -1
  48. package/resources/feedback/comments.d.mts +9 -53
  49. package/resources/feedback/comments.d.mts.map +1 -1
  50. package/resources/feedback/comments.d.ts +9 -53
  51. package/resources/feedback/comments.d.ts.map +1 -1
  52. package/resources/feedback/comments.js +6 -2
  53. package/resources/feedback/comments.js.map +1 -1
  54. package/resources/feedback/comments.mjs +6 -2
  55. package/resources/feedback/comments.mjs.map +1 -1
  56. package/resources/feedback/feedback.d.mts +4 -4
  57. package/resources/feedback/feedback.d.mts.map +1 -1
  58. package/resources/feedback/feedback.d.ts +4 -4
  59. package/resources/feedback/feedback.d.ts.map +1 -1
  60. package/resources/feedback/feedback.mjs.map +1 -1
  61. package/resources/feedback/index.d.mts +2 -2
  62. package/resources/feedback/index.d.mts.map +1 -1
  63. package/resources/feedback/index.d.ts +2 -2
  64. package/resources/feedback/index.d.ts.map +1 -1
  65. package/resources/feedback/posts/index.d.mts +2 -2
  66. package/resources/feedback/posts/index.d.mts.map +1 -1
  67. package/resources/feedback/posts/index.d.ts +2 -2
  68. package/resources/feedback/posts/index.d.ts.map +1 -1
  69. package/resources/feedback/posts/index.js.map +1 -1
  70. package/resources/feedback/posts/index.mjs.map +1 -1
  71. package/resources/feedback/posts/posts.d.mts +11 -56
  72. package/resources/feedback/posts/posts.d.mts.map +1 -1
  73. package/resources/feedback/posts/posts.d.ts +11 -56
  74. package/resources/feedback/posts/posts.d.ts.map +1 -1
  75. package/resources/feedback/posts/posts.js +6 -2
  76. package/resources/feedback/posts/posts.js.map +1 -1
  77. package/resources/feedback/posts/posts.mjs +6 -2
  78. package/resources/feedback/posts/posts.mjs.map +1 -1
  79. package/resources/feedback/posts/voters.d.mts +79 -124
  80. package/resources/feedback/posts/voters.d.mts.map +1 -1
  81. package/resources/feedback/posts/voters.d.ts +79 -124
  82. package/resources/feedback/posts/voters.d.ts.map +1 -1
  83. package/resources/feedback/posts/voters.js +7 -3
  84. package/resources/feedback/posts/voters.js.map +1 -1
  85. package/resources/feedback/posts/voters.mjs +7 -3
  86. package/resources/feedback/posts/voters.mjs.map +1 -1
  87. package/resources/help-center/articles.d.mts +9 -27
  88. package/resources/help-center/articles.d.mts.map +1 -1
  89. package/resources/help-center/articles.d.ts +9 -27
  90. package/resources/help-center/articles.d.ts.map +1 -1
  91. package/resources/help-center/articles.js +6 -2
  92. package/resources/help-center/articles.js.map +1 -1
  93. package/resources/help-center/articles.mjs +6 -2
  94. package/resources/help-center/articles.mjs.map +1 -1
  95. package/resources/help-center/collections.d.mts +9 -28
  96. package/resources/help-center/collections.d.mts.map +1 -1
  97. package/resources/help-center/collections.d.ts +9 -28
  98. package/resources/help-center/collections.d.ts.map +1 -1
  99. package/resources/help-center/collections.js +6 -3
  100. package/resources/help-center/collections.js.map +1 -1
  101. package/resources/help-center/collections.mjs +6 -3
  102. package/resources/help-center/collections.mjs.map +1 -1
  103. package/resources/help-center/help-center.d.mts +8 -8
  104. package/resources/help-center/help-center.d.mts.map +1 -1
  105. package/resources/help-center/help-center.d.ts +8 -8
  106. package/resources/help-center/help-center.d.ts.map +1 -1
  107. package/resources/help-center/help-center.mjs.map +1 -1
  108. package/resources/help-center/help-centers.d.mts +9 -28
  109. package/resources/help-center/help-centers.d.mts.map +1 -1
  110. package/resources/help-center/help-centers.d.ts +9 -28
  111. package/resources/help-center/help-centers.d.ts.map +1 -1
  112. package/resources/help-center/help-centers.js +6 -3
  113. package/resources/help-center/help-centers.js.map +1 -1
  114. package/resources/help-center/help-centers.mjs +6 -3
  115. package/resources/help-center/help-centers.mjs.map +1 -1
  116. package/resources/help-center/index.d.mts +4 -4
  117. package/resources/help-center/index.d.mts.map +1 -1
  118. package/resources/help-center/index.d.ts +4 -4
  119. package/resources/help-center/index.d.ts.map +1 -1
  120. package/resources/help-center/redirect-rules.d.mts +9 -28
  121. package/resources/help-center/redirect-rules.d.mts.map +1 -1
  122. package/resources/help-center/redirect-rules.d.ts +9 -28
  123. package/resources/help-center/redirect-rules.d.ts.map +1 -1
  124. package/resources/help-center/redirect-rules.js +6 -3
  125. package/resources/help-center/redirect-rules.js.map +1 -1
  126. package/resources/help-center/redirect-rules.mjs +6 -3
  127. package/resources/help-center/redirect-rules.mjs.map +1 -1
  128. package/resources/index.d.mts +3 -3
  129. package/resources/index.d.mts.map +1 -1
  130. package/resources/index.d.ts +3 -3
  131. package/resources/index.d.ts.map +1 -1
  132. package/resources/index.js.map +1 -1
  133. package/resources/index.mjs.map +1 -1
  134. package/resources/organization/brands.d.mts +5 -26
  135. package/resources/organization/brands.d.mts.map +1 -1
  136. package/resources/organization/brands.d.ts +5 -26
  137. package/resources/organization/brands.d.ts.map +1 -1
  138. package/resources/organization/brands.js +2 -1
  139. package/resources/organization/brands.js.map +1 -1
  140. package/resources/organization/brands.mjs +2 -1
  141. package/resources/organization/brands.mjs.map +1 -1
  142. package/resources/organization/index.d.mts +1 -1
  143. package/resources/organization/index.d.mts.map +1 -1
  144. package/resources/organization/index.d.ts +1 -1
  145. package/resources/organization/index.d.ts.map +1 -1
  146. package/resources/organization/organization.d.mts +2 -2
  147. package/resources/organization/organization.d.mts.map +1 -1
  148. package/resources/organization/organization.d.ts +2 -2
  149. package/resources/organization/organization.d.ts.map +1 -1
  150. package/resources/organization/organization.js.map +1 -1
  151. package/resources/organization/organization.mjs.map +1 -1
  152. package/resources/support/conversations/conversations.d.mts +9 -28
  153. package/resources/support/conversations/conversations.d.mts.map +1 -1
  154. package/resources/support/conversations/conversations.d.ts +9 -28
  155. package/resources/support/conversations/conversations.d.ts.map +1 -1
  156. package/resources/support/conversations/conversations.js +6 -3
  157. package/resources/support/conversations/conversations.js.map +1 -1
  158. package/resources/support/conversations/conversations.mjs +6 -3
  159. package/resources/support/conversations/conversations.mjs.map +1 -1
  160. package/resources/support/conversations/index.d.mts +1 -1
  161. package/resources/support/conversations/index.d.mts.map +1 -1
  162. package/resources/support/conversations/index.d.ts +1 -1
  163. package/resources/support/conversations/index.d.ts.map +1 -1
  164. package/resources/support/index.d.mts +2 -2
  165. package/resources/support/index.d.mts.map +1 -1
  166. package/resources/support/index.d.ts +2 -2
  167. package/resources/support/index.d.ts.map +1 -1
  168. package/resources/support/support.d.mts +4 -4
  169. package/resources/support/support.d.mts.map +1 -1
  170. package/resources/support/support.d.ts +4 -4
  171. package/resources/support/support.d.ts.map +1 -1
  172. package/resources/support/support.mjs.map +1 -1
  173. package/resources/support/tickets/index.d.mts +1 -1
  174. package/resources/support/tickets/index.d.mts.map +1 -1
  175. package/resources/support/tickets/index.d.ts +1 -1
  176. package/resources/support/tickets/index.d.ts.map +1 -1
  177. package/resources/support/tickets/tickets.d.mts +9 -27
  178. package/resources/support/tickets/tickets.d.mts.map +1 -1
  179. package/resources/support/tickets/tickets.d.ts +9 -27
  180. package/resources/support/tickets/tickets.d.ts.map +1 -1
  181. package/resources/support/tickets/tickets.js +6 -2
  182. package/resources/support/tickets/tickets.js.map +1 -1
  183. package/resources/support/tickets/tickets.mjs +6 -2
  184. package/resources/support/tickets/tickets.mjs.map +1 -1
  185. package/resources/surveys.d.mts +34 -79
  186. package/resources/surveys.d.mts.map +1 -1
  187. package/resources/surveys.d.ts +34 -79
  188. package/resources/surveys.d.ts.map +1 -1
  189. package/resources/surveys.js +4 -3
  190. package/resources/surveys.js.map +1 -1
  191. package/resources/surveys.mjs +4 -3
  192. package/resources/surveys.mjs.map +1 -1
  193. package/resources/users/companies/companies.d.mts +9 -28
  194. package/resources/users/companies/companies.d.mts.map +1 -1
  195. package/resources/users/companies/companies.d.ts +9 -28
  196. package/resources/users/companies/companies.d.ts.map +1 -1
  197. package/resources/users/companies/companies.js +6 -2
  198. package/resources/users/companies/companies.js.map +1 -1
  199. package/resources/users/companies/companies.mjs +6 -2
  200. package/resources/users/companies/companies.mjs.map +1 -1
  201. package/resources/users/companies/contacts.d.mts +11 -16
  202. package/resources/users/companies/contacts.d.mts.map +1 -1
  203. package/resources/users/companies/contacts.d.ts +11 -16
  204. package/resources/users/companies/contacts.d.ts.map +1 -1
  205. package/resources/users/companies/contacts.js +8 -5
  206. package/resources/users/companies/contacts.js.map +1 -1
  207. package/resources/users/companies/contacts.mjs +8 -5
  208. package/resources/users/companies/contacts.mjs.map +1 -1
  209. package/resources/users/companies/index.d.mts +1 -1
  210. package/resources/users/companies/index.d.mts.map +1 -1
  211. package/resources/users/companies/index.d.ts +1 -1
  212. package/resources/users/companies/index.d.ts.map +1 -1
  213. package/resources/users/contacts/contacts.d.mts +9 -13
  214. package/resources/users/contacts/contacts.d.mts.map +1 -1
  215. package/resources/users/contacts/contacts.d.ts +9 -13
  216. package/resources/users/contacts/contacts.d.ts.map +1 -1
  217. package/resources/users/contacts/contacts.js +6 -2
  218. package/resources/users/contacts/contacts.js.map +1 -1
  219. package/resources/users/contacts/contacts.mjs +6 -2
  220. package/resources/users/contacts/contacts.mjs.map +1 -1
  221. package/resources/users/contacts/index.d.mts +1 -1
  222. package/resources/users/contacts/index.d.mts.map +1 -1
  223. package/resources/users/contacts/index.d.ts +1 -1
  224. package/resources/users/contacts/index.d.ts.map +1 -1
  225. package/resources/users/contacts/index.js.map +1 -1
  226. package/resources/users/contacts/index.mjs.map +1 -1
  227. package/resources/users/index.d.mts +2 -2
  228. package/resources/users/index.d.mts.map +1 -1
  229. package/resources/users/index.d.ts +2 -2
  230. package/resources/users/index.d.ts.map +1 -1
  231. package/resources/users/index.js.map +1 -1
  232. package/resources/users/index.mjs.map +1 -1
  233. package/resources/users/users.d.mts +4 -4
  234. package/resources/users/users.d.mts.map +1 -1
  235. package/resources/users/users.d.ts +4 -4
  236. package/resources/users/users.d.ts.map +1 -1
  237. package/resources/users/users.js.map +1 -1
  238. package/resources/users/users.mjs.map +1 -1
  239. package/resources/webhooks.d.mts +9 -27
  240. package/resources/webhooks.d.mts.map +1 -1
  241. package/resources/webhooks.d.ts +9 -27
  242. package/resources/webhooks.d.ts.map +1 -1
  243. package/resources/webhooks.js +6 -2
  244. package/resources/webhooks.js.map +1 -1
  245. package/resources/webhooks.mjs +6 -2
  246. package/resources/webhooks.mjs.map +1 -1
  247. package/src/client.ts +41 -10
  248. package/src/core/pagination.ts +157 -0
  249. package/src/index.ts +1 -0
  250. package/src/pagination.ts +2 -0
  251. package/src/resources/changelogs/changelogs.ts +11 -64
  252. package/src/resources/changelogs/index.ts +1 -1
  253. package/src/resources/feedback/comments.ts +11 -64
  254. package/src/resources/feedback/feedback.ts +4 -4
  255. package/src/resources/feedback/index.ts +2 -2
  256. package/src/resources/feedback/posts/index.ts +2 -1
  257. package/src/resources/feedback/posts/posts.ts +13 -65
  258. package/src/resources/feedback/posts/voters.ts +87 -140
  259. package/src/resources/help-center/articles.ts +11 -33
  260. package/src/resources/help-center/collections.ts +11 -34
  261. package/src/resources/help-center/help-center.ts +8 -8
  262. package/src/resources/help-center/help-centers.ts +11 -34
  263. package/src/resources/help-center/index.ts +4 -4
  264. package/src/resources/help-center/redirect-rules.ts +11 -34
  265. package/src/resources/index.ts +6 -5
  266. package/src/resources/organization/brands.ts +7 -32
  267. package/src/resources/organization/index.ts +1 -1
  268. package/src/resources/organization/organization.ts +2 -2
  269. package/src/resources/support/conversations/conversations.ts +11 -34
  270. package/src/resources/support/conversations/index.ts +1 -1
  271. package/src/resources/support/index.ts +2 -2
  272. package/src/resources/support/support.ts +4 -4
  273. package/src/resources/support/tickets/index.ts +1 -1
  274. package/src/resources/support/tickets/tickets.ts +11 -33
  275. package/src/resources/surveys.ts +54 -102
  276. package/src/resources/users/companies/companies.ts +11 -34
  277. package/src/resources/users/companies/contacts.ts +24 -26
  278. package/src/resources/users/companies/index.ts +1 -1
  279. package/src/resources/users/contacts/contacts.ts +14 -15
  280. package/src/resources/users/contacts/index.ts +1 -0
  281. package/src/resources/users/index.ts +2 -1
  282. package/src/resources/users/users.ts +4 -2
  283. package/src/resources/webhooks.ts +11 -33
  284. package/src/version.ts +1 -1
  285. package/version.d.mts +1 -1
  286. package/version.d.ts +1 -1
  287. package/version.js +1 -1
  288. package/version.mjs +1 -1
package/src/client.ts CHANGED
@@ -14,18 +14,21 @@ import * as Opts from './internal/request-options';
14
14
  import { stringifyQuery } from './internal/utils/query';
15
15
  import { VERSION } from './version';
16
16
  import * as Errors from './core/error';
17
+ import * as Pagination from './core/pagination';
18
+ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/pagination';
17
19
  import * as Uploads from './core/uploads';
18
20
  import * as API from './resources/index';
19
21
  import { APIPromise } from './core/api-promise';
20
22
  import {
21
23
  Survey,
22
24
  SurveyListParams,
23
- SurveyListResponse,
25
+ SurveyListResponsesParams,
26
+ SurveyListResponsesResponse,
27
+ SurveyListResponsesResponsesCursorPage,
24
28
  SurveyNextAction,
25
29
  SurveyRetrieveParams,
26
- SurveyRetrieveResponsesParams,
27
- SurveyRetrieveResponsesResponse,
28
30
  Surveys,
31
+ SurveysCursorPage,
29
32
  } from './resources/surveys';
30
33
  import {
31
34
  Webhook,
@@ -33,12 +36,12 @@ import {
33
36
  WebhookDeleteParams,
34
37
  WebhookDeleteResponse,
35
38
  WebhookListParams,
36
- WebhookListResponse,
37
39
  WebhookRefreshSecretParams,
38
40
  WebhookRequestConfigInput,
39
41
  WebhookRetrieveParams,
40
42
  WebhookUpdateParams,
41
43
  Webhooks,
44
+ WebhooksCursorPage,
42
45
  } from './resources/webhooks';
43
46
  import {
44
47
  Changelog,
@@ -46,12 +49,12 @@ import {
46
49
  ChangelogDeleteParams,
47
50
  ChangelogDeleteResponse,
48
51
  ChangelogListParams,
49
- ChangelogListResponse,
50
52
  ChangelogPublishParams,
51
53
  ChangelogRetrieveParams,
52
54
  ChangelogUnpublishParams,
53
55
  ChangelogUpdateParams,
54
56
  Changelogs,
57
+ ChangelogsCursorPage,
55
58
  PublishUnpublishSuccess,
56
59
  } from './resources/changelogs/changelogs';
57
60
  import { Feedback } from './resources/feedback/feedback';
@@ -521,6 +524,30 @@ export class Featurebase {
521
524
  return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
522
525
  }
523
526
 
527
+ getAPIList<Item, PageClass extends Pagination.AbstractPage<Item> = Pagination.AbstractPage<Item>>(
528
+ path: string,
529
+ Page: new (...args: any[]) => PageClass,
530
+ opts?: PromiseOrValue<RequestOptions>,
531
+ ): Pagination.PagePromise<PageClass, Item> {
532
+ return this.requestAPIList(
533
+ Page,
534
+ opts && 'then' in opts ?
535
+ opts.then((opts) => ({ method: 'get', path, ...opts }))
536
+ : { method: 'get', path, ...opts },
537
+ );
538
+ }
539
+
540
+ requestAPIList<
541
+ Item = unknown,
542
+ PageClass extends Pagination.AbstractPage<Item> = Pagination.AbstractPage<Item>,
543
+ >(
544
+ Page: new (...args: ConstructorParameters<typeof Pagination.AbstractPage>) => PageClass,
545
+ options: PromiseOrValue<FinalRequestOptions>,
546
+ ): Pagination.PagePromise<PageClass, Item> {
547
+ const request = this.makeRequest(options, null, undefined);
548
+ return new Pagination.PagePromise<PageClass, Item>(this as any as Featurebase, request, Page);
549
+ }
550
+
524
551
  async fetchWithTimeout(
525
552
  url: RequestInfo,
526
553
  init: RequestInit | undefined,
@@ -799,6 +826,9 @@ Featurebase.Webhooks = Webhooks;
799
826
  export declare namespace Featurebase {
800
827
  export type RequestOptions = Opts.RequestOptions;
801
828
 
829
+ export import CursorPage = Pagination.CursorPage;
830
+ export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse };
831
+
802
832
  export { Support as Support };
803
833
 
804
834
  export { Feedback as Feedback };
@@ -807,8 +837,8 @@ export declare namespace Featurebase {
807
837
  Changelogs as Changelogs,
808
838
  type Changelog as Changelog,
809
839
  type PublishUnpublishSuccess as PublishUnpublishSuccess,
810
- type ChangelogListResponse as ChangelogListResponse,
811
840
  type ChangelogDeleteResponse as ChangelogDeleteResponse,
841
+ type ChangelogsCursorPage as ChangelogsCursorPage,
812
842
  type ChangelogCreateParams as ChangelogCreateParams,
813
843
  type ChangelogRetrieveParams as ChangelogRetrieveParams,
814
844
  type ChangelogUpdateParams as ChangelogUpdateParams,
@@ -828,19 +858,20 @@ export declare namespace Featurebase {
828
858
  Surveys as Surveys,
829
859
  type Survey as Survey,
830
860
  type SurveyNextAction as SurveyNextAction,
831
- type SurveyListResponse as SurveyListResponse,
832
- type SurveyRetrieveResponsesResponse as SurveyRetrieveResponsesResponse,
861
+ type SurveyListResponsesResponse as SurveyListResponsesResponse,
862
+ type SurveysCursorPage as SurveysCursorPage,
863
+ type SurveyListResponsesResponsesCursorPage as SurveyListResponsesResponsesCursorPage,
833
864
  type SurveyRetrieveParams as SurveyRetrieveParams,
834
865
  type SurveyListParams as SurveyListParams,
835
- type SurveyRetrieveResponsesParams as SurveyRetrieveResponsesParams,
866
+ type SurveyListResponsesParams as SurveyListResponsesParams,
836
867
  };
837
868
 
838
869
  export {
839
870
  Webhooks as Webhooks,
840
871
  type Webhook as Webhook,
841
872
  type WebhookRequestConfigInput as WebhookRequestConfigInput,
842
- type WebhookListResponse as WebhookListResponse,
843
873
  type WebhookDeleteResponse as WebhookDeleteResponse,
874
+ type WebhooksCursorPage as WebhooksCursorPage,
844
875
  type WebhookCreateParams as WebhookCreateParams,
845
876
  type WebhookRetrieveParams as WebhookRetrieveParams,
846
877
  type WebhookUpdateParams as WebhookUpdateParams,
@@ -0,0 +1,157 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import { FeaturebaseError } from './error';
4
+ import { FinalRequestOptions } from '../internal/request-options';
5
+ import { defaultParseResponse } from '../internal/parse';
6
+ import { type Featurebase } from '../client';
7
+ import { APIPromise } from './api-promise';
8
+ import { type APIResponseProps } from '../internal/parse';
9
+ import { maybeObj } from '../internal/utils/values';
10
+
11
+ export type PageRequestOptions = Pick<FinalRequestOptions, 'query' | 'headers' | 'body' | 'path' | 'method'>;
12
+
13
+ export abstract class AbstractPage<Item> implements AsyncIterable<Item> {
14
+ #client: Featurebase;
15
+ protected options: FinalRequestOptions;
16
+
17
+ protected response: Response;
18
+ protected body: unknown;
19
+
20
+ constructor(client: Featurebase, response: Response, body: unknown, options: FinalRequestOptions) {
21
+ this.#client = client;
22
+ this.options = options;
23
+ this.response = response;
24
+ this.body = body;
25
+ }
26
+
27
+ abstract nextPageRequestOptions(): PageRequestOptions | null;
28
+
29
+ abstract getPaginatedItems(): Item[];
30
+
31
+ hasNextPage(): boolean {
32
+ const items = this.getPaginatedItems();
33
+ if (!items.length) return false;
34
+ return this.nextPageRequestOptions() != null;
35
+ }
36
+
37
+ async getNextPage(): Promise<this> {
38
+ const nextOptions = this.nextPageRequestOptions();
39
+ if (!nextOptions) {
40
+ throw new FeaturebaseError(
41
+ 'No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.',
42
+ );
43
+ }
44
+
45
+ return await this.#client.requestAPIList(this.constructor as any, nextOptions);
46
+ }
47
+
48
+ async *iterPages(): AsyncGenerator<this> {
49
+ let page: this = this;
50
+ yield page;
51
+ while (page.hasNextPage()) {
52
+ page = await page.getNextPage();
53
+ yield page;
54
+ }
55
+ }
56
+
57
+ async *[Symbol.asyncIterator](): AsyncGenerator<Item> {
58
+ for await (const page of this.iterPages()) {
59
+ for (const item of page.getPaginatedItems()) {
60
+ yield item;
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * This subclass of Promise will resolve to an instantiated Page once the request completes.
68
+ *
69
+ * It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg:
70
+ *
71
+ * for await (const item of client.items.list()) {
72
+ * console.log(item)
73
+ * }
74
+ */
75
+ export class PagePromise<
76
+ PageClass extends AbstractPage<Item>,
77
+ Item = ReturnType<PageClass['getPaginatedItems']>[number],
78
+ >
79
+ extends APIPromise<PageClass>
80
+ implements AsyncIterable<Item>
81
+ {
82
+ constructor(
83
+ client: Featurebase,
84
+ request: Promise<APIResponseProps>,
85
+ Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass,
86
+ ) {
87
+ super(
88
+ client,
89
+ request,
90
+ async (client, props) =>
91
+ new Page(client, props.response, await defaultParseResponse(client, props), props.options),
92
+ );
93
+ }
94
+
95
+ /**
96
+ * Allow auto-paginating iteration on an unawaited list call, eg:
97
+ *
98
+ * for await (const item of client.items.list()) {
99
+ * console.log(item)
100
+ * }
101
+ */
102
+ async *[Symbol.asyncIterator](): AsyncGenerator<Item> {
103
+ const page = await this;
104
+ for await (const item of page) {
105
+ yield item;
106
+ }
107
+ }
108
+ }
109
+
110
+ export interface CursorPageResponse<Item> {
111
+ data: Array<Item>;
112
+
113
+ nextCursor: string | null;
114
+ }
115
+
116
+ export interface CursorPageParams {
117
+ cursor?: string;
118
+
119
+ limit?: number;
120
+ }
121
+
122
+ export class CursorPage<Item> extends AbstractPage<Item> implements CursorPageResponse<Item> {
123
+ data: Array<Item>;
124
+
125
+ nextCursor: string | null;
126
+
127
+ constructor(
128
+ client: Featurebase,
129
+ response: Response,
130
+ body: CursorPageResponse<Item>,
131
+ options: FinalRequestOptions,
132
+ ) {
133
+ super(client, response, body, options);
134
+
135
+ this.data = body.data || [];
136
+ this.nextCursor = body.nextCursor || null;
137
+ }
138
+
139
+ getPaginatedItems(): Item[] {
140
+ return this.data ?? [];
141
+ }
142
+
143
+ nextPageRequestOptions(): PageRequestOptions | null {
144
+ const cursor = this.nextCursor;
145
+ if (!cursor) {
146
+ return null;
147
+ }
148
+
149
+ return {
150
+ ...this.options,
151
+ query: {
152
+ ...maybeObj(this.options.query),
153
+ cursor,
154
+ },
155
+ };
156
+ }
157
+ }
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export { Featurebase as default } from './client';
5
5
  export { type Uploadable, toFile } from './core/uploads';
6
6
  export { APIPromise } from './core/api-promise';
7
7
  export { Featurebase, type ClientOptions } from './client';
8
+ export { PagePromise } from './core/pagination';
8
9
  export {
9
10
  FeaturebaseError,
10
11
  APIError,
@@ -0,0 +1,2 @@
1
+ /** @deprecated Import from ./core/pagination instead */
2
+ export * from './core/pagination';
@@ -10,6 +10,7 @@ import {
10
10
  Subscribers,
11
11
  } from './subscribers';
12
12
  import { APIPromise } from '../../core/api-promise';
13
+ import { CursorPage, type CursorPageParams, PagePromise } from '../../core/pagination';
13
14
  import { buildHeaders } from '../../internal/headers';
14
15
  import { RequestOptions } from '../../internal/request-options';
15
16
  import { path } from '../../internal/utils/path';
@@ -231,15 +232,18 @@ export class Changelogs extends APIResource {
231
232
  *
232
233
  * @example
233
234
  * ```ts
234
- * const changelogs = await client.changelogs.list();
235
+ * // Automatically fetches more pages as needed.
236
+ * for await (const changelog of client.changelogs.list()) {
237
+ * // ...
238
+ * }
235
239
  * ```
236
240
  */
237
241
  list(
238
242
  params: ChangelogListParams | null | undefined = {},
239
243
  options?: RequestOptions,
240
- ): APIPromise<ChangelogListResponse> {
244
+ ): PagePromise<ChangelogsCursorPage, Changelog> {
241
245
  const { 'Featurebase-Version': featurebaseVersion, ...query } = params ?? {};
242
- return this._client.get('/v2/changelogs', {
246
+ return this._client.getAPIList('/v2/changelogs', CursorPage<Changelog>, {
243
247
  query,
244
248
  ...options,
245
249
  headers: buildHeaders([
@@ -431,6 +435,8 @@ export class Changelogs extends APIResource {
431
435
  }
432
436
  }
433
437
 
438
+ export type ChangelogsCursorPage = CursorPage<Changelog>;
439
+
434
440
  export interface Changelog {
435
441
  /**
436
442
  * Unique identifier
@@ -648,55 +654,6 @@ export interface PublishUnpublishSuccess {
648
654
  state?: 'published' | 'scheduled' | 'unpublished';
649
655
  }
650
656
 
651
- export interface ChangelogListResponse {
652
- /**
653
- * Array of changelogs
654
- */
655
- data: Array<Changelog>;
656
-
657
- /**
658
- * Cursor for fetching the next page (cursor-based pagination)
659
- */
660
- nextCursor: string | null;
661
-
662
- /**
663
- * Object type identifier
664
- */
665
- object: 'list';
666
-
667
- /**
668
- * Pagination metadata for page-based requests
669
- */
670
- pagination?: ChangelogListResponse.Pagination;
671
- }
672
-
673
- export namespace ChangelogListResponse {
674
- /**
675
- * Pagination metadata for page-based requests
676
- */
677
- export interface Pagination {
678
- /**
679
- * Items per page
680
- */
681
- limit: number;
682
-
683
- /**
684
- * Current page number
685
- */
686
- page: number;
687
-
688
- /**
689
- * Total number of items
690
- */
691
- total: number;
692
-
693
- /**
694
- * Total number of pages
695
- */
696
- totalPages: number;
697
- }
698
- }
699
-
700
657
  export interface ChangelogDeleteResponse {
701
658
  /**
702
659
  * Unique identifier of the deleted changelog
@@ -871,7 +828,7 @@ export interface ChangelogUpdateParams {
871
828
  'Featurebase-Version'?: string;
872
829
  }
873
830
 
874
- export interface ChangelogListParams {
831
+ export interface ChangelogListParams extends CursorPageParams {
875
832
  /**
876
833
  * Query param: Find changelog by its id (also accepts slug)
877
834
  */
@@ -882,21 +839,11 @@ export interface ChangelogListParams {
882
839
  */
883
840
  categories?: string | Array<string>;
884
841
 
885
- /**
886
- * Query param: Cursor for pagination. Use nextCursor from previous response.
887
- */
888
- cursor?: string;
889
-
890
842
  /**
891
843
  * Query param: Include Changelogs dated on or before the specified end date
892
844
  */
893
845
  endDate?: string | null;
894
846
 
895
- /**
896
- * Query param: Maximum number of changelogs to return
897
- */
898
- limit?: number;
899
-
900
847
  /**
901
848
  * Query param: The locale of the changelogs. Defaults to the organization default
902
849
  * locale.
@@ -1118,8 +1065,8 @@ export declare namespace Changelogs {
1118
1065
  export {
1119
1066
  type Changelog as Changelog,
1120
1067
  type PublishUnpublishSuccess as PublishUnpublishSuccess,
1121
- type ChangelogListResponse as ChangelogListResponse,
1122
1068
  type ChangelogDeleteResponse as ChangelogDeleteResponse,
1069
+ type ChangelogsCursorPage as ChangelogsCursorPage,
1123
1070
  type ChangelogCreateParams as ChangelogCreateParams,
1124
1071
  type ChangelogRetrieveParams as ChangelogRetrieveParams,
1125
1072
  type ChangelogUpdateParams as ChangelogUpdateParams,
@@ -4,7 +4,6 @@ export {
4
4
  Changelogs,
5
5
  type Changelog,
6
6
  type PublishUnpublishSuccess,
7
- type ChangelogListResponse,
8
7
  type ChangelogDeleteResponse,
9
8
  type ChangelogCreateParams,
10
9
  type ChangelogRetrieveParams,
@@ -13,6 +12,7 @@ export {
13
12
  type ChangelogDeleteParams,
14
13
  type ChangelogPublishParams,
15
14
  type ChangelogUnpublishParams,
15
+ type ChangelogsCursorPage,
16
16
  } from './changelogs';
17
17
  export {
18
18
  Subscribers,
@@ -3,6 +3,7 @@
3
3
  import { APIResource } from '../../core/resource';
4
4
  import * as TicketsAPI from '../support/tickets/tickets';
5
5
  import { APIPromise } from '../../core/api-promise';
6
+ import { CursorPage, type CursorPageParams, PagePromise } from '../../core/pagination';
6
7
  import { buildHeaders } from '../../internal/headers';
7
8
  import { RequestOptions } from '../../internal/request-options';
8
9
  import { path } from '../../internal/utils/path';
@@ -258,15 +259,18 @@ export class Comments extends APIResource {
258
259
  *
259
260
  * @example
260
261
  * ```ts
261
- * const comments = await client.feedback.comments.list();
262
+ * // Automatically fetches more pages as needed.
263
+ * for await (const comment of client.feedback.comments.list()) {
264
+ * // ...
265
+ * }
262
266
  * ```
263
267
  */
264
268
  list(
265
269
  params: CommentListParams | null | undefined = {},
266
270
  options?: RequestOptions,
267
- ): APIPromise<CommentListResponse> {
271
+ ): PagePromise<CommentsCursorPage, Comment> {
268
272
  const { 'Featurebase-Version': featurebaseVersion, ...query } = params ?? {};
269
- return this._client.get('/v2/comments', {
273
+ return this._client.getAPIList('/v2/comments', CursorPage<Comment>, {
270
274
  query,
271
275
  ...options,
272
276
  headers: buildHeaders([
@@ -412,6 +416,8 @@ export class Comments extends APIResource {
412
416
  }
413
417
  }
414
418
 
419
+ export type CommentsCursorPage = CursorPage<Comment>;
420
+
415
421
  export interface Comment {
416
422
  /**
417
423
  * Unique identifier
@@ -520,55 +526,6 @@ export namespace Comment {
520
526
  }
521
527
  }
522
528
 
523
- export interface CommentListResponse {
524
- /**
525
- * Array of comments
526
- */
527
- data: Array<Comment>;
528
-
529
- /**
530
- * Cursor for fetching the next page (cursor-based pagination)
531
- */
532
- nextCursor: string | null;
533
-
534
- /**
535
- * Object type identifier
536
- */
537
- object: 'list';
538
-
539
- /**
540
- * Pagination metadata for page-based requests
541
- */
542
- pagination?: CommentListResponse.Pagination;
543
- }
544
-
545
- export namespace CommentListResponse {
546
- /**
547
- * Pagination metadata for page-based requests
548
- */
549
- export interface Pagination {
550
- /**
551
- * Items per page
552
- */
553
- limit: number;
554
-
555
- /**
556
- * Current page number
557
- */
558
- page: number;
559
-
560
- /**
561
- * Total number of items
562
- */
563
- total: number;
564
-
565
- /**
566
- * Total number of pages
567
- */
568
- totalPages: number;
569
- }
570
- }
571
-
572
529
  export interface CommentDelete0Response {
573
530
  /**
574
531
  * Unique identifier of the deleted comment
@@ -706,27 +663,17 @@ export interface CommentUpdateParams {
706
663
  'Featurebase-Version'?: string;
707
664
  }
708
665
 
709
- export interface CommentListParams {
666
+ export interface CommentListParams extends CursorPageParams {
710
667
  /**
711
668
  * Query param: Filter comments by changelog ID
712
669
  */
713
670
  changelogId?: string;
714
671
 
715
- /**
716
- * Query param: Cursor for pagination. Use nextCursor from previous response.
717
- */
718
- cursor?: string;
719
-
720
672
  /**
721
673
  * Query param: Filter by review status
722
674
  */
723
675
  inReview?: boolean | null;
724
676
 
725
- /**
726
- * Query param: Maximum number of comments to return
727
- */
728
- limit?: number;
729
-
730
677
  /**
731
678
  * Query param: Filter comments by post ID
732
679
  */
@@ -773,9 +720,9 @@ export interface CommentDelete1Params {
773
720
  export declare namespace Comments {
774
721
  export {
775
722
  type Comment as Comment,
776
- type CommentListResponse as CommentListResponse,
777
723
  type CommentDelete0Response as CommentDelete0Response,
778
724
  type CommentDelete1Response as CommentDelete1Response,
725
+ type CommentsCursorPage as CommentsCursorPage,
779
726
  type CommentCreateParams as CommentCreateParams,
780
727
  type CommentRetrieveParams as CommentRetrieveParams,
781
728
  type CommentUpdateParams as CommentUpdateParams,
@@ -12,10 +12,10 @@ import {
12
12
  CommentDelete1Params,
13
13
  CommentDelete1Response,
14
14
  CommentListParams,
15
- CommentListResponse,
16
15
  CommentRetrieveParams,
17
16
  CommentUpdateParams,
18
17
  Comments,
18
+ CommentsCursorPage,
19
19
  } from './comments';
20
20
  import * as CustomFieldsAPI from './custom-fields';
21
21
  import {
@@ -40,10 +40,10 @@ import {
40
40
  PostDeleteParams,
41
41
  PostDeleteResponse,
42
42
  PostListParams,
43
- PostListResponse,
44
43
  PostRetrieveParams,
45
44
  PostUpdateParams,
46
45
  Posts,
46
+ PostsCursorPage,
47
47
  } from './posts/posts';
48
48
 
49
49
  export class Feedback extends APIResource {
@@ -72,8 +72,8 @@ export declare namespace Feedback {
72
72
  export {
73
73
  Posts as Posts,
74
74
  type Post as Post,
75
- type PostListResponse as PostListResponse,
76
75
  type PostDeleteResponse as PostDeleteResponse,
76
+ type PostsCursorPage as PostsCursorPage,
77
77
  type PostCreateParams as PostCreateParams,
78
78
  type PostRetrieveParams as PostRetrieveParams,
79
79
  type PostUpdateParams as PostUpdateParams,
@@ -92,9 +92,9 @@ export declare namespace Feedback {
92
92
  export {
93
93
  Comments as Comments,
94
94
  type Comment as Comment,
95
- type CommentListResponse as CommentListResponse,
96
95
  type CommentDelete0Response as CommentDelete0Response,
97
96
  type CommentDelete1Response as CommentDelete1Response,
97
+ type CommentsCursorPage as CommentsCursorPage,
98
98
  type CommentCreateParams as CommentCreateParams,
99
99
  type CommentRetrieveParams as CommentRetrieveParams,
100
100
  type CommentUpdateParams as CommentUpdateParams,
@@ -10,7 +10,6 @@ export {
10
10
  export {
11
11
  Comments,
12
12
  type Comment,
13
- type CommentListResponse,
14
13
  type CommentDelete0Response,
15
14
  type CommentDelete1Response,
16
15
  type CommentCreateParams,
@@ -19,6 +18,7 @@ export {
19
18
  type CommentListParams,
20
19
  type CommentDelete0Params,
21
20
  type CommentDelete1Params,
21
+ type CommentsCursorPage,
22
22
  } from './comments';
23
23
  export {
24
24
  CustomFields,
@@ -38,11 +38,11 @@ export {
38
38
  export {
39
39
  Posts,
40
40
  type Post,
41
- type PostListResponse,
42
41
  type PostDeleteResponse,
43
42
  type PostCreateParams,
44
43
  type PostRetrieveParams,
45
44
  type PostUpdateParams,
46
45
  type PostListParams,
47
46
  type PostDeleteParams,
47
+ type PostsCursorPage,
48
48
  } from './posts/index';
@@ -3,13 +3,13 @@
3
3
  export {
4
4
  Posts,
5
5
  type Post,
6
- type PostListResponse,
7
6
  type PostDeleteResponse,
8
7
  type PostCreateParams,
9
8
  type PostRetrieveParams,
10
9
  type PostUpdateParams,
11
10
  type PostListParams,
12
11
  type PostDeleteParams,
12
+ type PostsCursorPage,
13
13
  } from './posts';
14
14
  export {
15
15
  Voters,
@@ -19,4 +19,5 @@ export {
19
19
  type VoterListParams,
20
20
  type VoterAddParams,
21
21
  type VoterRemoveParams,
22
+ type VoterListResponsesCursorPage,
22
23
  } from './voters';