@zapier/zapier-sdk-cli 0.0.1

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.
@@ -0,0 +1,202 @@
1
+ import inquirer from "inquirer";
2
+ import chalk from "chalk";
3
+
4
+ export interface PagerOptions {
5
+ pageSize?: number;
6
+ showPrompt?: boolean;
7
+ itemName?: string;
8
+ }
9
+
10
+ export interface PaginatedResult<T> {
11
+ items: T[];
12
+ hasMore: boolean;
13
+ totalShown: number;
14
+ }
15
+
16
+ /**
17
+ * Generic pager that handles pagination for any data source
18
+ * Supports interactive "load more" functionality
19
+ */
20
+ export class Pager<T> {
21
+ private pageSize: number;
22
+ private showPrompt: boolean;
23
+ private itemName: string;
24
+ private allItems: T[] = [];
25
+ private currentOffset = 0;
26
+
27
+ constructor(options: PagerOptions = {}) {
28
+ this.pageSize = options.pageSize || 20;
29
+ this.showPrompt = options.showPrompt !== false;
30
+ this.itemName = options.itemName || "items";
31
+ }
32
+
33
+ /**
34
+ * Fetch and display paginated results with interactive loading
35
+ */
36
+ async paginate<TParams>(
37
+ fetchFunction: (
38
+ params: TParams & { limit: number; offset?: number },
39
+ ) => Promise<T[]>,
40
+ baseParams: TParams,
41
+ displayFunction: (
42
+ items: T[],
43
+ totalShown: number,
44
+ totalAvailable?: number,
45
+ ) => void,
46
+ ): Promise<PaginatedResult<T>> {
47
+ let hasMore = true;
48
+ let totalAvailable: number | undefined;
49
+
50
+ while (hasMore) {
51
+ // Fetch next page
52
+ const params = {
53
+ ...baseParams,
54
+ limit: this.pageSize,
55
+ offset: this.currentOffset,
56
+ };
57
+
58
+ try {
59
+ const items = await fetchFunction(params);
60
+
61
+ if (items.length === 0) {
62
+ // Still call display function to show "No items found" message
63
+ displayFunction(this.allItems, this.allItems.length, totalAvailable);
64
+ hasMore = false;
65
+ break;
66
+ }
67
+
68
+ // Check for pagination metadata to get total count
69
+ const pagination = (items as any).__pagination;
70
+ if (pagination && pagination.count) {
71
+ totalAvailable = pagination.count;
72
+ hasMore = pagination.hasNext;
73
+ } else {
74
+ // Fallback: check if we got fewer items than requested
75
+ hasMore = items.length >= this.pageSize;
76
+ }
77
+
78
+ // Add to our collection
79
+ this.allItems.push(...items);
80
+ this.currentOffset += items.length;
81
+
82
+ // Display current batch
83
+ displayFunction(this.allItems, this.allItems.length, totalAvailable);
84
+
85
+ // If prompting is disabled, continue automatically
86
+ if (!this.showPrompt) {
87
+ continue;
88
+ }
89
+
90
+ // If we have total count info, show more detailed prompt
91
+ const totalInfo = totalAvailable
92
+ ? ` of ${totalAvailable.toLocaleString()}`
93
+ : "";
94
+ const message = `Load more ${this.itemName}? (${this.allItems.length}${totalInfo} shown so far)`;
95
+
96
+ // Ask user if they want to load more
97
+ const { loadMore } = await inquirer.prompt([
98
+ {
99
+ type: "confirm",
100
+ name: "loadMore",
101
+ message,
102
+ default: true,
103
+ },
104
+ ]);
105
+
106
+ if (!loadMore) {
107
+ hasMore = false;
108
+ }
109
+ } catch (error) {
110
+ // Re-throw the error to be handled by the caller
111
+ throw error;
112
+ }
113
+ }
114
+
115
+ return {
116
+ items: this.allItems,
117
+ hasMore: this.currentOffset > 0 && hasMore,
118
+ totalShown: this.allItems.length,
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Reset the pager state
124
+ */
125
+ reset(): void {
126
+ this.allItems = [];
127
+ this.currentOffset = 0;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Convenience function to create a pager for a specific use case
133
+ */
134
+ export function createPager<T>(options: PagerOptions = {}): Pager<T> {
135
+ return new Pager<T>(options);
136
+ }
137
+
138
+ /**
139
+ * Simple pagination without interactivity - just fetches all results up to a limit
140
+ */
141
+ export async function fetchAllPages<T, TParams>(
142
+ fetchFunction: (
143
+ params: TParams & { limit: number; offset?: number },
144
+ ) => Promise<T[]>,
145
+ baseParams: TParams,
146
+ maxResults: number = 100,
147
+ ): Promise<T[]> {
148
+ const pageSize = Math.min(maxResults, 50); // Reasonable page size
149
+ const allItems: T[] = [];
150
+ let offset = 0;
151
+
152
+ while (allItems.length < maxResults) {
153
+ const remainingItems = maxResults - allItems.length;
154
+ const currentPageSize = Math.min(pageSize, remainingItems);
155
+
156
+ const params = {
157
+ ...baseParams,
158
+ limit: currentPageSize,
159
+ offset,
160
+ };
161
+
162
+ const items = await fetchFunction(params);
163
+
164
+ if (items.length === 0) {
165
+ break; // No more data
166
+ }
167
+
168
+ allItems.push(...items);
169
+ offset += items.length;
170
+
171
+ // If we got fewer items than requested, we've reached the end
172
+ if (items.length < currentPageSize) {
173
+ break;
174
+ }
175
+ }
176
+
177
+ return allItems;
178
+ }
179
+
180
+ /**
181
+ * Display helper for showing pagination status
182
+ */
183
+ export function showPaginationStatus(
184
+ currentCount: number,
185
+ requestedLimit: number,
186
+ itemName: string = "items",
187
+ ): void {
188
+ if (currentCount >= requestedLimit) {
189
+ console.log(
190
+ chalk.yellow(
191
+ `\nšŸ“„ Showing first ${currentCount} ${itemName} (limit: ${requestedLimit})`,
192
+ ),
193
+ );
194
+ console.log(
195
+ chalk.gray(
196
+ `Use --limit to increase the limit, or add paging with --page`,
197
+ ),
198
+ );
199
+ } else {
200
+ console.log(chalk.gray(`\nšŸ“„ Showing all ${currentCount} ${itemName}`));
201
+ }
202
+ }