@intuned/browser-dev 0.1.8-dev.0 → 0.1.9-dev.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.
@@ -10,11 +10,11 @@ import { Download } from "playwright";
10
10
  export interface SanitizeHtmlOptions {
11
11
  /** The HTML content to sanitize */
12
12
  html: string;
13
- /** Remove all <script> elements. Defaults to true. */
13
+ /** Remove all \<script\> elements. Defaults to true. */
14
14
  removeScripts?: boolean;
15
- /** Remove all <style> elements. Defaults to true. */
15
+ /** Remove all \<style\> elements. Defaults to true. */
16
16
  removeStyles?: boolean;
17
- /** Remove all <svg> elements. Defaults to true. */
17
+ /** Remove all \<svg\> elements. Defaults to true. */
18
18
  removeSvgs?: boolean;
19
19
  /** Remove HTML comments. Defaults to true. */
20
20
  removeComments?: boolean;
@@ -52,108 +52,101 @@ export interface SanitizeHtmlOptions {
52
52
  *
53
53
  * @example
54
54
  * ```typescript Basic Sanitization
55
+ * import { BrowserContext, Page } from "playwright";
55
56
  * import { sanitizeHtml } from "@intuned/browser";
56
- * export default async function handler(params, page, context){
57
- * const dirtyHtml = `
58
- * <div>
59
- * <script>alert('xss')</script>
60
- * <p style="color: red;">Hello World</p>
61
- * <span></span>
62
- * </div>
63
- * `;
64
- * const sanitizedHtml = sanitizeHtml({ html: dirtyHtml });
65
- * // Returns: '<div><p>Hello World</p></div>'
66
- * }
67
- * ```
68
57
  *
69
- * @example
70
- * ```typescript Sanitization Options
71
- * import { sanitizeHtml } from "@intuned/browser";
72
- * export default async function handler(params, page, context){
73
- * const html = `
74
- * <div data-long-attr="${'x'.repeat(600)}">
75
- * <style>.test { color: red; }</style>
76
- * <script>alert('test')</script>
77
- * <p style="color: blue;">Content</p>
78
- * <!-- Comment -->
79
- * </div>
80
- * `;
81
- * // Keep styles but remove scripts and comments
82
- * const result = sanitizeHtml({ html,
83
- * removeScripts: true,
84
- * removeStyles: false,
85
- * removeComments: true,
86
- * maxAttributeLength: 100,
87
- * preserveAttributes: ["class", "src", "style"]
88
- * });
89
- * }
58
+ * interface Params {}
59
+ *
60
+ * export default async function handler(
61
+ * params: Params,
62
+ * page: Page,
63
+ * context: BrowserContext
64
+ * ) {
65
+ * await page.goto("https://books.toscrape.com");
66
+ * const firstRow = page.locator("ol.row").locator("li").first();
67
+ * // Get the HTML of the first row.
68
+ * const html = await firstRow.innerHTML();
69
+ * // Sanitize the HTML.
70
+ * const sanitizedHtml = sanitizeHtml({ html });
71
+ * // Log the sanitized HTML.
72
+ * console.log(sanitizedHtml);
73
+ * // Return the sanitized HTML.
74
+ * return sanitizedHtml;
75
+ }
90
76
  * ```
91
77
  */
92
78
 
93
79
  export declare function sanitizeHtml(options: SanitizeHtmlOptions): string;
94
80
 
95
81
  /**
96
- * Downloads a file from a web page using various trigger methods.
97
- *
98
- * This function provides three flexible ways to initiate file downloads:
99
- * 1. **URL Navigation**: Directly navigate to a URL that triggers a download
100
- * 2. **Element Interaction**: Click on a Playwright locator (e.g., download button or link)
101
- * 3. **Custom Callback**: Execute a custom function to trigger the download programmatically
82
+ * Downloads a file from a web page using various trigger methods. This function provides three flexible ways to initiate file downloads:
83
+ *
84
+ * - **URL**: Creates a new page, navigates to the URL, waits for download, then automatically closes the page. Ideal for direct download links.
85
+ * - **Locator**: Uses the current page to click the element and capture the resulting download. Perfect for download buttons or interactive elements.
86
+ * - **Callback**: Executes the provided function with the page object and captures the first triggered download. Offers maximum flexibility for complex download scenarios.
102
87
  *
103
88
  * @param {Object} input - Configuration object for the download operation
104
89
  * @param {Page} input.page - The Playwright Page object to use for the download
105
- * @param {Trigger} input.trigger - The [Trigger](../type-aliases/Trigger) method to initiate the download
106
- * @param {number} [input.timeoutInMs=5000] - Maximum time in milliseconds to wait for download completion. Defaults to 5000.
107
- * @returns {Promise<Download>} Promise that resolves to a Playwright Download object
90
+ * @param {Trigger} input.trigger - The [Trigger](../type-references/Trigger) method to initiate the download
91
+ * @param {number} [input.timeoutInMs=5000] - Maximum time in milliseconds to wait for the download to trigger. Defaults to 5000.
92
+ * @returns {Promise<Download>} Promise that resolves to a [Playwright Download object](https://playwright.dev/docs/api/class-download)
108
93
  *
109
94
  * @example
110
- * ```typescript URL trigger
95
+ * ```typescript Download from direct URL
111
96
  * import { downloadFile } from "@intuned/browser";
112
- * export default async function handler(params, page, context){
113
- * // Download by navigating directly to a URL
114
- * const download = await downloadFile({
115
- * page,
116
- * trigger: "https://intuned-docs-public-images.s3.amazonaws.com/32UP83A_ENG_US.pdf"
117
- * });
118
- * console.log(`Downloaded to: ${await download.path()}`);
97
+ * import { BrowserContext, Page } from "playwright";
98
+
99
+ * interface Params {}
100
+
101
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
102
+ * // Download from a direct URL, this will open the url and automatically download the content in it.
103
+ * const download = await downloadFile({
104
+ * page,
105
+ * trigger: "https://intuned-docs-public-images.s3.amazonaws.com/32UP83A_ENG_US.pdf"
106
+ * });
107
+ * file_name = download.suggestedFilename();
108
+ * return file_name;
109
+ *
119
110
  * }
120
111
  * ```
121
112
  *
122
113
  * @example
123
- * ```typescript Locator trigger
114
+ * ```typescript Locator Trigger
124
115
  * import { downloadFile } from "@intuned/browser";
125
- * export default async function handler(params, page, context){
126
- * // Download by clicking a link or button
127
- * await page.goto("https://sandbox.intuned.dev/pdfs")
128
- * const download = await downloadFile({
129
- * page,
130
- * trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']")
131
- * });
132
- * console.log(`File saved at: ${await download.path()}`);
116
+ * import { BrowserContext, Page } from "playwright";
117
+ *
118
+ * interface Params {}
119
+
120
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
121
+ * await page.goto("https://sandbox.intuned.dev/pdfs");
122
+ * const download = await downloadFile({
123
+ * page,
124
+ * trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']")
125
+ * });
126
+ * file_name = download.suggestedFilename();
127
+ * return file_name;
133
128
  * }
134
129
  * ```
135
130
  *
136
131
  * @example
137
- * ```typescript Callback trigger
132
+ * ```typescript Callback Trigger
138
133
  * import { downloadFile } from "@intuned/browser";
139
- * export default async function handler(params, page, context){
140
- * // Download using a custom interaction sequence
141
- * await page.goto("https://sandbox.intuned.dev/pdfs")
142
- * const download = await downloadFile({
143
- * page,
144
- * trigger: async (page) => {
145
- * await page.locator("xpath=//tbody/tr[1]//*[name()='svg']").click();
146
- * }
147
- * });
148
- * console.log(`Download completed: ${await download.path()}`);
134
+ * import { BrowserContext, Page } from "playwright";
135
+ *
136
+ * interface Params {}
137
+ *
138
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
139
+ * await page.goto("https://sandbox.intuned.dev/pdfs");
140
+ * const download = await downloadFile({
141
+ * page,
142
+ * trigger: async (page) => {
143
+ * await page.locator("xpath=//tbody/tr[1]//*[name()='svg']").click();
144
+ * }
145
+ * });
146
+ * file_name = download.suggestedFilename();
147
+ * return file_name;
149
148
  * }
150
149
  * ```
151
- *
152
- * @note
153
- * **Trigger Behavior:**
154
- * - **URL**: Creates a new page, navigates to the URL, waits for download, then closes the page
155
- * - **Locator**: Uses the current page to click the element and capture the resulting download
156
- * - **Callback**: Executes the provided function with the page object and captures the first triggered downloads
157
150
  */
158
151
  export declare function downloadFile(input: {
159
152
  page: Page;
@@ -178,10 +171,26 @@ export declare function downloadFile(input: {
178
171
  * @example
179
172
  * ```typescript Basic Usage
180
173
  * import { filterEmptyValues } from "@intuned/browser";
181
- * export default async function handler(params, page, context){
182
- * filterEmptyValues({ data: { a: "", b: "hello", c: null } }) // Returns { b: "hello" }
183
- * filterEmptyValues({ data: [1, "", null, [2, ""]] }) // Returns [1, [2]]
184
- * filterEmptyValues({ data: { users: [{ name: "" }, { name: "John" }] } }) // Returns { users: [{ name: "John" }] }
174
+ * import { BrowserContext, Page } from "playwright";
175
+ *
176
+ * interface Params {}
177
+ *
178
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
179
+ * // Filter empty values from dictionary
180
+ * const result1 = filterEmptyValues({ data: { a: "", b: "hello", c: null } });
181
+ * // Output: { b: "hello" }
182
+ * console.log(result1);
183
+ *
184
+ * // Filter empty values from list
185
+ * const result2 = filterEmptyValues({ data: [1, "", null, [2, ""]] });
186
+ * // Output: [1, [2]]
187
+ * console.log(result2);
188
+ *
189
+ * // Filter nested structures
190
+ * const result3 = filterEmptyValues({ data: { users: [{ name: "" }, { name: "John" }] } });
191
+ * // Output: { users: [{ name: "John" }] }
192
+ * console.log(result3);
193
+ * return "All data filtered successfully";
185
194
  * }
186
195
  * ```
187
196
  */
@@ -189,66 +198,78 @@ export declare function filterEmptyValues<T>(input: { data: T }): T;
189
198
 
190
199
  /**
191
200
  * Navigates to a specified URL with enhanced reliability features including automatic retries with exponential backoff,
192
- * intelligent timeout detection, and optional AI-powered loading verification.
193
- *
194
- * This function handles common navigation challenges by automatically retrying failed requests, detecting navigation hangs, and ensuring the page reaches a truly idle state. For dynamic applications,
195
- * it can optionally verify page loading completion using AI vision to detect loading spinners, blank content, or incomplete states.
196
- * The function can be configured to either throw errors or gracefully continue execution when navigation issues occur.
197
- *
198
- * @param {Object} input - The input object containing the page and url
199
- * @param {Page} input.page - The Playwright page object to navigate
200
- * @param {string} input.url - The URL to navigate to
201
- * @param {number} [input.retries=3] - Number of retry attempts with exponential backoff (factor: 2, minTimeout: 1000ms). Defaults to 3
202
- * @param {number} [input.timeoutInMs=30000] - Maximum time in milliseconds to wait for navigation. Defaults to 30000
203
- * @param {string} [input.waitForLoadState="load"] - When to consider navigation succeeded. Options: "load", "domcontentloaded", "networkidle", "commit". Defaults to "load"
204
- * @param {boolean} [input.throwOnTimeout=true] - Whether to throw an error if navigation times out. When false, the function returns without throwing, allowing continued execution. Defaults to true.
205
- * @param {boolean} [input.waitForLoadingStateUsingAi=false] - When true, uses AI vision to verify the page is fully loaded by checking for loading spinners, blank content, or incomplete states. Retries up to 4 times with 5-second delays. Defaults to false
206
- * @param {string} [input.model="gpt-5-mini-2025-08-07"] - AI model to use for loading verification. Defaults to "gpt-5-mini-2025-08-07"
207
- * @param {string} [input.apiKey] - Optional API key for the AI service (if provided, will not be billed to your account)
208
- * @returns {Promise<void>} Promise that resolves when navigation completes successfully. If the operation fails and `throwOnTimeout` is false, resolves without error
201
+ * intelligent timeout handling, and optional AI-powered loading verification.
202
+ *
203
+ * This function handles common navigation challenges by automatically retrying failed requests, detecting navigation hangs, and ensuring the page reaches a truly idle state.
204
+ *
205
+ * This method can also use AI vision to verify the page is fully loaded by checking for loading spinners, blank content, or incomplete states.
206
+ *
207
+ * @param {Object} input - The input object containing the page and url.
208
+ * @param {Page} input.page - The Playwright page object to navigate.
209
+ * @param {string} input.url - The URL to navigate to.
210
+ * @param {number} [input.timeoutInMs=30000] - Maximum time in milliseconds to wait for navigation. Defaults to 30000.
211
+ * @param {number} [input.retries=3] - Number of retry attempts with exponential backoff (factor: 2). Defaults to 3.
212
+ * @param {("load"|"domcontentloaded"|"networkidle"|"commit")} [input.waitForLoadState="load"] - When to consider navigation succeeded. Defaults to `"load"`
213
+ * @param {boolean} [input.throwOnTimeout=false] - Whether to throw an error if navigation times out. When true, the function throws an error on navigation timeout. Defaults to false.
214
+ * @param {boolean} [input.waitForLoadingStateUsingAi=false] - When true, uses AI vision to verify the page is fully loaded by checking for loading spinners, blank content, or incomplete states. Retries up to 3 times with 5-second delays. Defaults to false
215
+ * Check [isPageLoaded](../../ai/functions/isPageLoaded) for more details on the AI loading verification.
216
+ * @param {string} [input.model="gpt-5-mini-2025-08-07"] - AI model to use for loading verification. Defaults to `"gpt-5-mini-2025-08-07"`
217
+ * @param {string} [input.apiKey] - Optional API key for the AI check.
218
+ * @returns {Promise<void>} Promise that resolves when navigation completes. If the operation fails and `throwOnTimeout` is false, resolves without error
209
219
  *
210
220
  * @example
211
- * ```typescript Basic Navigation
221
+ * ```typescript Without options
212
222
  * import { goToUrl } from "@intuned/browser";
213
- * export default async function handler(params, page, context){
214
- * // Navigate with automatic retries on failure
215
- * await goToUrl({
216
- * page,
217
- * url: 'https://example.com'
218
- * });
219
- * // Automatically retries up to 3 times with exponential backoff
223
+ * import { BrowserContext, Page } from "playwright";
224
+ *
225
+ * interface Params {}
226
+ *
227
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
228
+ * await goToUrl({
229
+ * page,
230
+ * url: 'https://sandbox.intuned.dev/'
231
+ * });
232
+ * // At this point, goToUrl has waited for the page to be loaded and the network requests to be settled.
220
233
  * }
221
234
  * ```
222
235
  *
223
236
  * @example
224
- * ```typescript Navigation with options
237
+ * ```typescript With options
225
238
  * import { goToUrl } from "@intuned/browser";
226
- * export default async function handler(params, page, context){
227
- * // Navigate to an unreliable site without throwing on timeout
228
- * await goToUrl({
229
- * page,
230
- * url: 'https://www.google.com',
231
- * throwOnTimeout: false, // Continue even if navigation fails
232
- * retries: 5, // Try more times for unreliable sites
233
- * timeoutInMs: 60000 // Give it more time
234
- * });
235
- * // If navigation fails after all retries, execution continues
239
+ * import { BrowserContext, Page } from "playwright";
240
+ *
241
+ * interface Params {}
242
+ *
243
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
244
+ * await goToUrl({
245
+ * page,
246
+ * url: 'https://intunedhq.com',
247
+ * waitForLoadState: "domcontentloaded", // Faster than "load" state. The function automatically waits for the page to settle.
248
+ * throwOnTimeout: true,
249
+ * timeoutInMs: 10000,
250
+ * retries: 3
251
+ * });
252
+ * // At this point, DOM content is loaded and goToUrl has waited for network requests to settle.
236
253
  * }
237
254
  * ```
238
255
  *
239
256
  * @example
240
- * ```typescript AI-Verified Loading for Dynamic Sites
257
+ * ```typescript With AI Loading Detection
241
258
  * import { goToUrl } from "@intuned/browser";
242
- * export default async function handler(params, page, context){
243
- * await goToUrl({
244
- * page,
245
- * url: 'https://sandbox.intuned.dev/',
246
- * waitForLoadState: "load",
247
- * waitForLoadingStateUsingAi: true, // AI checks for spinners/loading states
248
- * model: "gpt-4o",
249
- * retries: 3
250
- * });
251
- * // AI verifies no loading spinners or blank content before proceeding
259
+ * import { BrowserContext, Page } from "playwright";
260
+ *
261
+ * interface Params {}
262
+ *
263
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
264
+ * await goToUrl({
265
+ * page,
266
+ * url: 'https://intunedhq.com',
267
+ * waitForLoadingStateUsingAi: true,
268
+ * model: "gpt-4o"
269
+ * });
270
+ * // The page is loaded and ready to use.
271
+ * // If the AI check fails, the method won't throw even if throwOnTimeout is true.
272
+ * // It only throws if the page times out reaching the default load state and throwOnTimeout is true.
252
273
  * }
253
274
  * ```
254
275
  */
@@ -258,7 +279,7 @@ export declare function goToUrl(input: {
258
279
  timeoutInMs?: number;
259
280
  retries?: number;
260
281
  throwOnTimeout?: boolean;
261
- waitForLoadState?: "load" | "domcontentloaded" | "networkidle";
282
+ waitForLoadState?: "load" | "domcontentloaded" | "networkidle" | "commit";
262
283
  waitForLoadingStateUsingAi?: boolean;
263
284
  model?: string;
264
285
  apiKey?: string;
@@ -268,38 +289,49 @@ export declare function goToUrl(input: {
268
289
  * Automatically scrolls through infinite scroll content by repeatedly scrolling to the bottom
269
290
  * until no new content loads or maximum scroll limit is reached.
270
291
  *
271
- * @param {Object} input - The input object containing the data to scroll to load content
272
- * @param {Page | Locator} input.source - The Playwright Page or Locator to scroll
273
- * @param {Function} [input.onScrollProgress] - Optional callback function to call during each scroll iteration
274
- * @param {number} [input.maxScrolls=50] - Maximum number of scroll attempts before stopping. Defaults to 50
275
- * @param {number} [input.delayInMs=100] - Delay in milliseconds between scroll attempts. Defaults to 100
276
- * @param {number} [input.minHeightChange=100] - Minimum height change in pixels required to continue scrolling. Defaults to 100
277
- * @returns {Promise<void>} Promise that resolves when scrolling is complete
292
+ * @param {Object} input - The input object containing the data to scroll to load content.
293
+ * @param {Page | Locator} input.source - The Playwright Page or Locator to scroll.
294
+ * @param {Function} [input.onScrollProgress] - Optional callback function to call during each scroll iteration.
295
+ * @param {number} [input.maxScrolls=50] - Maximum number of scroll attempts before stopping. Defaults to 50.
296
+ * @param {number} [input.delayInMs=100] - Delay in milliseconds between scroll attempts. Defaults to 100.
297
+ * @param {number} [input.minHeightChange=100] - Minimum height change in pixels required to continue scrolling. Defaults to 100.
298
+ * If the page has loaded all content and we still haven't reached the maxScrolls, the minHeightChange will detect that no new content is loaded and stop the scrolling.
299
+ * @returns {Promise<void>} Promise that resolves when scrolling is complete.
278
300
  *
279
301
  * @example
280
- * ```typescript Basic Infinite Scroll
302
+ * ```typescript Basic Infinite Scroll handling
281
303
  * import { scrollToLoadContent } from "@intuned/browser";
282
- * export default async function handler(params, page, context){
304
+ * import { BrowserContext, Page } from "playwright";
305
+ *
306
+ * interface Params {}
307
+ *
308
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
283
309
  * // Scroll through entire page content
284
- * await page.goto("https://docs.intunedhq.com/docs-old/getting-started/introduction")
310
+ * await page.goto("https://sandbox.intuned.dev/infinite-scroll")
285
311
  * await scrollToLoadContent({
286
312
  * source: page,
287
313
  * });
288
- * // Now all content is loaded and visible
314
+ * // Will keep scrolling until the page has loaded all content or the maxScrolls is reached.
289
315
  * }
290
316
  * ```
291
317
  *
292
318
  * @example
293
319
  * ```typescript Scroll Specific Container
294
320
  * import { scrollToLoadContent } from "@intuned/browser";
295
- * export default async function handler(params, page, context){
321
+ * import { BrowserContext, Page } from "playwright";
322
+ *
323
+ * interface Params {}
324
+ *
325
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
296
326
  * // Scroll through a specific scrollable div
297
- * await page.goto("https://docs.intunedhq.com/docs-old/getting-started/introduction")
327
+ * await page.goto("https://docs.intunedhq.com/docs/00-getting-started/introduction")
328
+ * // This will scroll the sidebar content only and watch its height to change.
298
329
  * const container = page.locator("xpath=//div[@id='sidebar-content']");
299
330
  * await scrollToLoadContent({
300
331
  * source: container,
301
332
  * maxScrolls: 20
302
333
  * });
334
+ * // Will keep scrolling until the sidebar content has loaded all content or the maxScrolls is reached.
303
335
  * }
304
336
  * ```
305
337
  */
@@ -312,32 +344,6 @@ export declare function scrollToLoadContent(input: {
312
344
  minHeightChange?: number;
313
345
  }): Promise<void>;
314
346
 
315
- /**
316
- * Click a button and wait briefly for content to load.
317
- *
318
- * This function clicks a button element and waits for a specified delay, allowing time for
319
- * any triggered content to load. It automatically waits for network activity to settle.
320
- *
321
- * @param {Object} input - Configuration options
322
- * @param {Page} input.page - Playwright Page object
323
- * @param {Locator} input.buttonLocator - Locator for the button element to click
324
- * @param {number} [input.clickDelay=0.5] - Delay after clicking the button (in seconds)
325
- * @returns {Promise<void>} Promise that resolves when the click and wait is complete
326
- *
327
- * @example
328
- * ```typescript Basic Button Click
329
- * import { clickButtonAndWait } from "@intuned/browser";
330
- * export default async function handler(params, page, context){
331
- * await page.goto("https://example.com/products");
332
- * const loadMoreButton = page.locator("#load-more-button");
333
- * await clickButtonAndWait({
334
- * page,
335
- * buttonLocator: loadMoreButton,
336
- * clickDelay: 1.0
337
- * });
338
- * }
339
- * ```
340
- */
341
347
  export declare function clickButtonAndWait(input: {
342
348
  page: Page;
343
349
  buttonLocator: Locator;
@@ -349,8 +355,7 @@ export declare function clickButtonAndWait(input: {
349
355
  *
350
356
  * This function is useful for "Load More" buttons or paginated content where you need to
351
357
  * keep clicking until all content is loaded. It provides several stopping conditions:
352
- * - Button becomes invisible
353
- * - Button becomes disabled
358
+ * - Button becomes invisible/disabled
354
359
  * - Maximum number of clicks reached
355
360
  * - No change detected in container content (when containerLocator is provided)
356
361
  *
@@ -359,17 +364,21 @@ export declare function clickButtonAndWait(input: {
359
364
  * @param {Locator} input.buttonLocator - Locator for the button to click repeatedly
360
365
  * @param {CallableFunction} [input.heartbeat] - Optional callback invoked after each click
361
366
  * @param {Locator} [input.containerLocator] - Optional content container to detect changes
362
- * @param {number} [input.maxClicks=50] - Maximum number of times to click the button
363
- * @param {number} [input.clickDelay=0.5] - Delay after each click (in seconds)
364
- * @param {number} [input.noChangeThreshold=0] - Minimum change in content size to continue clicking
367
+ * @param {number} [input.maxClicks=50] - Maximum number of times to click the button. Defaults to 50.
368
+ * @param {number} [input.clickDelay=0.5] - Delay after each click (in seconds). Defaults to 0.5.
369
+ * @param {number} [input.noChangeThreshold=0] - Minimum change in content size to continue clicking. Defaults to 0.
365
370
  * @returns {Promise<void>} Promise that resolves when clicking is exhausted
366
371
  *
367
372
  * @example
368
373
  * ```typescript Load All Items
369
374
  * import { clickUntilExhausted } from "@intuned/browser";
370
- * export default async function handler(params, page, context){
371
- * await page.goto("https://example.com/products");
372
- * const loadMoreButton = page.locator("button:has-text('Load More')");
375
+ * import { BrowserContext, Page } from "playwright";
376
+ *
377
+ * interface Params {}
378
+ *
379
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
380
+ * await page.goto("https://sandbox.intuned.dev/load-more");
381
+ * const loadMoreButton = page.locator("main main button"); // Select the main button in the main content area.
373
382
  *
374
383
  * // Click until button disappears or is disabled
375
384
  * await clickUntilExhausted({
@@ -377,22 +386,27 @@ export declare function clickButtonAndWait(input: {
377
386
  * buttonLocator: loadMoreButton,
378
387
  * maxClicks: 20
379
388
  * });
389
+ * // Will keep clicking the button until the button disappears or is disabled or the maxClicks is reached.
380
390
  * }
381
391
  * ```
382
392
  *
383
393
  * @example
384
394
  * ```typescript Track Container Changes
385
395
  * import { clickUntilExhausted } from "@intuned/browser";
386
- * export default async function handler(params, page, context){
387
- * await page.goto("https://example.com/products");
388
- * const loadMoreButton = page.locator("#load-more");
389
- * const productsContainer = page.locator("#products-list");
396
+ * import { BrowserContext, Page } from "playwright";
390
397
  *
398
+ * interface Params {}
399
+ *
400
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
401
+ * await page.goto("https://sandbox.intuned.dev/load-more");
402
+ * const loadMoreButton = page.locator("aside button"); // Select the button in the sidebar.
403
+ * const container = page.locator('xpath=//*[@id="root"]/div[1]/main/slot/div/aside/div/div/slot/slot'); // Watch the sidebar container to detect changes.
404
+ * // This will count the elements under the container given before each click and after, if the count is the same, the function will stop.
391
405
  * let clickCount = 0;
392
406
  * await clickUntilExhausted({
393
407
  * page,
394
408
  * buttonLocator: loadMoreButton,
395
- * containerLocator: productsContainer,
409
+ * containerLocator: container,
396
410
  * heartbeat: () => {
397
411
  * clickCount++;
398
412
  * console.log(`Clicked ${clickCount} times`);
@@ -401,6 +415,7 @@ export declare function clickButtonAndWait(input: {
401
415
  * clickDelay: 0.5,
402
416
  * noChangeThreshold: 0
403
417
  * });
418
+ * // Will keep clicking the button until the button disappears or is disabled or the maxClicks is reached or no more content is loaded.
404
419
  * }
405
420
  * ```
406
421
  */
@@ -415,30 +430,76 @@ export declare function clickUntilExhausted(input: {
415
430
  }): Promise<void>;
416
431
 
417
432
  /**
418
- * Parses various date string formats into Date objects.
419
- * Returns only the date part (year, month, day) with time set to 00:00:00.
420
- *
421
- * Supports a wide variety of date formats including:
422
- * - DD/MM/YYYY with optional time (e.g., "22/11/2024 21:19:05", "13/12/2024")
423
- * - MM/DD/YYYY with optional time and timezone (e.g., "01/17/2025 3:00:00 PM CT", "10/25/2024")
424
- * - MM/DD/YYYY with time and timezone abbreviations (e.g., "10/23/2024 12:06 PM CST")
425
- * - MM/DD/YYYY with AM/PM time format (e.g., "11/28/2024 1:59:59 AM", "12/09/2024 9:00 AM")
426
- * - MM/DD/YYYY with dash separator and time (e.g., "12/19/2024 - 2:00 PM")
427
- * - M/DD/YYYY and MM/D/YYYY formats (e.g., "8/16/2019", "9/28/2024")
428
- * - DD MMM YYYY with optional time and timezone (e.g., "5 Dec 2024 8:00 AM PST", "11 Sep 2024")
429
- * - Full month name formats (e.g., "November 14, 2024", "January 31, 2025, 5:00 pm")
430
- * - 24-hour time format (e.g., "22/11/2024 19:45:00", "09/01/2025 15:00:00")
433
+ * Parses various date string formats into Date objects, returning only the date part with time set to midnight.
434
+ * This utility function provides robust date parsing capabilities for a wide range of common formats.
435
+ *
436
+ * ## Key features
437
+ *
438
+ * - Returns only the date part (year, month, day)
439
+ * - Time is always set to 00:00:00
440
+ * - Supports multiple international formats
441
+ * - Handles timezones and AM/PM formats
442
+ *
443
+ * ## Supported formats
444
+ *
445
+ * The function handles these date format categories:
446
+ *
447
+ * ### Standard date formats
448
+ * - `DD/MM/YYYY`: "22/11/2024", "13/12/2024"
449
+ * - `MM/DD/YYYY`: "01/17/2025", "10/25/2024"
450
+ * - Single-digit variants: "8/16/2019", "9/28/2024"
451
+ *
452
+ * ### Date-time combinations
453
+ * - With 24-hour time: "22/11/2024 21:19:05"
454
+ * - With AM/PM: "12/09/2024 9:00 AM"
455
+ * - With dash separator: "12/19/2024 - 2:00 PM"
456
+ *
457
+ * ### Timezone support
458
+ * - With timezone abbreviations: "10/23/2024 12:06 PM CST"
459
+ * - With timezone offset: "01/17/2025 3:00:00 PM CT"
460
+ *
461
+ * ### Text month formats
462
+ * - Short month: "5 Dec 2024", "11 Sep 2024"
463
+ * - With time: "5 Dec 2024 8:00 AM PST"
464
+ * - Full month: "November 14, 2024", "January 31, 2025, 5:00 pm"
431
465
  *
432
466
  * @param {Object} input - The input object containing the date to process
433
467
  * @param {string} input.date - A string containing a date in various possible formats
434
- * @returns {Date | null} Date object with only date components (time set to 00:00:00) if parsing successful, null if parsing fails
468
+ * @returns {Date | null} Returns a `Date` object with only date components preserved (year, month, day), time always set to 00:00:00, or `null` if parsing fails
435
469
  *
436
470
  * @example
437
- * ```typescript Basic Date Processing
471
+ * ```typescript Basic Usage
438
472
  * import { processDate } from "@intuned/browser";
439
- * export default async function handler(params, page, context){
440
- * processDate("22/11/2024 21:19:05") // Returns Date with 2024-11-22 00:00:00
441
- * processDate("5 Dec 2024 8:00 AM PST") // Returns Date with 2024-12-05 00:00:00
473
+ * import { BrowserContext, Page } from "playwright";
474
+ *
475
+ * interface Params {}
476
+ *
477
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
478
+ * // Basic date string
479
+ * const date1 = processDate({ date: "22/11/2024" });
480
+ * console.log(date1); // 2024-11-22 00:00:00
481
+ *
482
+ * // Date with time (time is ignored)
483
+ * const date2 = processDate({ date: "5 Dec 2024 8:00 AM PST" });
484
+ * console.log(date2); // 2024-12-05 00:00:00
485
+ * }
486
+ * ```
487
+ *
488
+ * @example
489
+ * ```typescript Invalid Date
490
+ * import { processDate } from "@intuned/browser";
491
+ * import { BrowserContext, Page } from "playwright";
492
+ *
493
+ * interface Params {}
494
+ *
495
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
496
+ * // Invalid date returns null
497
+ * const invalidDate = processDate({ date: "invalid date" });
498
+ * console.log(invalidDate); // will return null.
499
+ * if (invalidDate === null) {
500
+ * throw new Error("Invalid date");
501
+ * }
502
+ * return "should not reach here";
442
503
  * }
443
504
  * ```
444
505
  */
@@ -448,81 +509,83 @@ export declare function processDate(input: { date: string }): Date | null;
448
509
  * Uploads files to AWS S3 storage with flexible configuration options.
449
510
  *
450
511
  * This function accepts various file types including Playwright Download objects, binary data,
451
- * and file streams, making it versatile for different upload scenarios. It automatically
512
+ * making it versatile for different upload scenarios. It automatically
452
513
  * handles file metadata and provides comprehensive S3 configuration options.
453
514
  *
515
+ * ## S3 configuration fallback
516
+ *
517
+ * The function uses a fallback system to determine S3 settings:
518
+ *
519
+ * 1. **S3Configs Parameter** - If provided, uses the explicit `configs` object with your custom settings.
520
+ * 2. **Environment Variables** - If no configs provided, automatically reads from environment variables:
521
+ * - `AWS_ACCESS_KEY_ID` - Your AWS access key
522
+ * - `AWS_SECRET_ACCESS_KEY` - Your AWS secret key
523
+ * - `AWS_REGION` - AWS region (e.g., "us-west-1")
524
+ * - `AWS_BUCKET` - S3 bucket name
525
+ * - `AWS_ENDPOINT_URL` - Optional custom S3 endpoint
526
+ * - Check [Environment Variables & Secrets](https://docs.intunedhq.com/docs/02-features/environment-variables-secrets) to learn more about setting environment variables.
527
+ * 3. **Intuned Defaults** - If environment variables aren't set, falls back to Intuned's managed S3 storage. See [S3 Attachment Storage](https://docs.intunedhq.com/docs/04-integrations/s3/s3-attachment-storage) for more details.
528
+ *
454
529
  * @param {Object} input - Configuration object for the upload operation
455
- * @param {FileType} input.file - The file to upload. Accepts [FileType](../type-aliases/FileType) types including:
456
- * - Playwright Download objects (from `downloadFile`)
457
- * - Uint8Array or Buffer (binary data)
458
- * - ReadStream (file streams)
459
- * @param {S3Configs} [input.configs] - Optional [S3Configs](../interfaces/S3Configs) for customizing the S3 upload. If not provided, uses environment variables or default configuration
460
- * @param {string} [input.fileNameOverride] - Optional custom filename for the uploaded file. If not provided, uses the original filename
530
+ * @param {FileType} input.file - The file to upload. Accepts [FileType](../type-references/FileType) types including Playwright Download objects, Uint8Array, Buffer, or ReadStream
531
+ * @param {S3Configs} [input.configs] - Optional [S3Configs](../type-references/S3Configs) for customizing the S3 upload. If not provided, uses environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, `AWS_ENDPOINT_URL`, `AWS_BUCKET`). If environment variables aren't set, uses default Intuned S3 settings.
532
+ * @param {string} [input.fileNameOverride] - Optional custom filename for the uploaded file. If not provided, uses the original filename or generates a unique name.
461
533
  * @param {string} [input.contentType] - Optional MIME type for the uploaded file (e.g., "application/pdf", "image/png")
462
- * @returns {Promise<Attachment>} Promise that resolves to an [Attachment](../interfaces/Attachment) object with file metadata and utility methods
534
+ * @returns {Promise<Attachment>} Promise that resolves to an [Attachment](../type-references/Attachment) object with file metadata and utility methods
463
535
  *
464
536
  * @example
465
537
  * ```typescript Upload Downloaded File
466
538
  * import { downloadFile, uploadFileToS3 } from "@intuned/browser";
467
- * export default async function handler(params, page, context){
468
- * // Download and upload a file with custom S3 configuration
469
- * await page.goto("https://sandbox.intuned.dev/pdfs")
470
- * const download = await downloadFile({
471
- * page,
472
- * trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']")
473
- * });
539
+ * import { BrowserContext, Page } from "playwright";
474
540
  *
475
- * const uploadedFile = await uploadFileToS3({
476
- * file: download,
477
- * configs: {
478
- * bucket: 'my-documents',
479
- * region: 'us-west-2',
480
- * accessKeyId: 'accessKeyId',
481
- * secretAccessKey: 'SecretAccessKeyId'
541
+ * interface Params {}
542
+ *
543
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
544
+ * await page.goto("https://sandbox.intuned.dev/pdfs");
545
+ * const download = await downloadFile({
546
+ * page,
547
+ * trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']")
548
+ * });
549
+ * // Set your environment variables for the AWS credentials.
550
+ * // Check https://docs.intunedhq.com/docs/02-features/environment-variables-secrets to learn more about setting environment variables.
551
+ * const uploadedFile = await uploadFileToS3({
552
+ * file: download,
553
+ * configs: {
554
+ * bucket: process.env.AWS_BUCKET,
555
+ * region: process.env.AWS_REGION,
556
+ * accessKeyId: process.env.AWS_ACCESS_KEY_ID,
557
+ * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
482
558
  * },
483
559
  * fileNameOverride: 'reports/monthly-report.pdf'
484
- * }
485
- * });
560
+ * });
486
561
  *
487
- * console.log(`File uploaded: ${uploadedFile.suggestedFileName}`);
488
- * console.log(`S3 URL: ${uploadedFile.getS3Key()}`);
562
+ * console.log(`File uploaded: ${uploadedFile.suggestedFileName}`);
489
563
  * }
490
564
  * ```
491
565
  *
492
566
  * @example
493
567
  * ```typescript Upload Binary Data
494
568
  * import { uploadFileToS3 } from "@intuned/browser";
495
- * export default async function handler(params, page, context){
496
- * // Upload binary data with minimal configuration
497
- * const fileBuffer = Buffer.from('Hello World', 'utf8');
498
- * const uploadedFile = await uploadFileToS3({
499
- * file: fileBuffer,
500
- * configs: {
501
- * bucket: 'my-documents',
502
- * region: 'us-west-2',
503
- * accessKeyId: 'accessKeyId',
504
- * secretAccessKey: 'SecretAccessKeyId'
505
- * },
506
- * fileNameOverride: 'data/text-file.txt',
507
- * contentType: 'text/plain'
508
- * }
509
- * });
510
- *
511
- * // Generate a temporary download URL
512
- * const downloadUrl = await uploadedFile.getSignedUrl(3600); // 1 hour
569
+ * import { BrowserContext, Page } from "playwright";
570
+ *
571
+ * interface Params {}
572
+ *
573
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
574
+ * const fileBuffer = Buffer.from('Hello World', 'utf8');
575
+ * const uploadedFile = await uploadFileToS3({
576
+ * file: fileBuffer,
577
+ * fileNameOverride: 'data/text-file.txt',
578
+ * contentType: 'text/plain'
579
+ * });
580
+ *
581
+ * // Generate a temporary download URL
582
+ * const downloadUrl = await uploadedFile.getSignedUrl();
583
+ * console.log(`Download URL: ${downloadUrl}`);
584
+ * return {
585
+ * downloadUrl: downloadUrl
586
+ * };
513
587
  * }
514
588
  * ```
515
- *
516
- * @note
517
- * **S3 Configuration Priority:**
518
- * 1. **Explicit configs**: Values provided in `input.configs.s3Configs`
519
- * 2. **Environment variables**: Standard AWS environment variables:
520
- * - `AWS_BUCKET`
521
- * - `AWS_REGION`
522
- * - `AWS_ACCESS_KEY_ID`
523
- * - `AWS_SECRET_ACCESS_KEY`
524
- * - `AWS_ENDPOINT_URL`
525
- * 3. **Default fallback**: Intuned's default S3 configuration
526
589
  */
527
590
 
528
591
  export declare function uploadFileToS3(input: {
@@ -534,41 +597,58 @@ export declare function uploadFileToS3(input: {
534
597
 
535
598
  /**
536
599
  * Validates data against a JSON schema using the AJV validator.
537
- * This function can validate any given data against a given schema. It supports validating custom data types such as the [Attachment](../interfaces/Attachment) type.
600
+ * This function can validate any given data against a given schema. It supports validating custom data types such as the [Attachment](../type-references/Attachment) type.
538
601
  *
539
602
  * @param {Object} input - The input object containing data and schema
540
603
  * @param {Record<string, any> | Record<string, any>[]} input.data - The data to validate. Can be a single data object or an array of data objects
541
604
  * @param {Record<string, any>} input.schema - JSON schema object defining validation rules
542
605
  * @returns {void} Returns nothing if validation passes, throws ValidationError if it fails
606
+ * @throws {ValidationError} If validation fails
543
607
  *
544
608
  * @example
545
- * ```typescript Basic User Data Validation
609
+ * ```typescript Basic Validation
546
610
  * import { validateDataUsingSchema } from "@intuned/browser";
547
- * export default async function handler(params, page, context){
548
- * const userData = {
549
- * name: "John Doe",
550
- * email: "john@example.com",
551
- * age: 30
611
+ * import { BrowserContext, Page } from "playwright";
612
+ *
613
+ * interface Params {}
614
+ *
615
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
616
+ * const uploadData = {
617
+ * file: {
618
+ * fileName: "documents/report.pdf",
619
+ * bucket: "my-bucket",
620
+ * region: "us-east-1",
621
+ * key: "documents/report.pdf",
622
+ * endpoint: null,
623
+ * suggestedFileName: "Monthly Report.pdf",
624
+ * fileType: "document"
625
+ * },
626
+ * name: "Test File Upload"
552
627
  * };
553
628
  *
554
- * const userSchema = {
629
+ * const uploadSchema = {
555
630
  * type: "object",
556
- * required: ["name", "email", "age"],
631
+ * required: ["file", "name"],
557
632
  * properties: {
558
- * name: { type: "string", minLength: 1 },
559
- * email: { type: "string", format: "email" },
560
- * age: { type: "number", minimum: 0 }
633
+ * file: { type: "attachment" },
634
+ * name: { type: "string" }
561
635
  * }
562
636
  * };
563
637
  *
564
- * validateDataUsingSchema({ data: userData, schema: userSchema });
565
- * // Validation passes, no error thrown
638
+ * validateDataUsingSchema({ data: uploadData, schema: uploadSchema });
639
+ * // Validation passes with Attachment type
640
+ * console.log("Validation passed");
641
+ * return "Validation passed";
566
642
  * }
567
643
  * ```
568
644
  * @example
569
645
  * ```typescript Invalid Data Validation
570
646
  * import { validateDataUsingSchema } from "@intuned/browser";
571
- * export default async function handler(params, page, context){
647
+ * import { BrowserContext, Page } from "playwright";
648
+ *
649
+ * interface Params {}
650
+ *
651
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
572
652
  * const userData = {
573
653
  * name: "John Doe",
574
654
  * email: "john@example.com",
@@ -584,8 +664,10 @@ export declare function uploadFileToS3(input: {
584
664
  * }
585
665
  * };
586
666
  *
587
- * validateDataUsingSchema({ data: userData, schema: userSchema });
667
+ * validateDataUsingSchema({ data: userData, schema: userSchema }); // this will throw
588
668
  * // Validation fails, throws ValidationError
669
+ * console.log("Never reached");
670
+ * return "Never reached";
589
671
  * }
590
672
  * ```
591
673
  */
@@ -595,11 +677,11 @@ export declare function validateDataUsingSchema(input: {
595
677
  }): void;
596
678
 
597
679
  /**
598
- * Executes a callback function and waits for network requests to settle before returning.
680
+ * Executes a callback function and waits for network activity to settle before returning.
599
681
  *
600
- * This function monitors network activity and waits for all pending requests to complete
601
- * (or reach the specified maximum) before resolving. Useful for ensuring dynamic content
602
- * has fully loaded after performing actions that trigger network requests.
682
+ * ## `withNetworkSettledWait` vs `waitForDomSettled`
683
+ * - Use `withNetworkSettledWait` when watching **network requests** (API calls, form submissions, resource loading)
684
+ * - Use [waitForDomSettled](../functions/waitForDomSettled) when watching **DOM mutations** (elements added/removed/modified, loading spinners, dynamic content injection)
603
685
  *
604
686
  * @param {Function} callback - The callback function to execute. Receives the page object as parameter
605
687
  * @param {Object} [options] - Configuration options for network monitoring
@@ -608,21 +690,59 @@ export declare function validateDataUsingSchema(input: {
608
690
  * @param {number} [options.maxInflightRequests=0] - Maximum number of pending requests to consider as "settled". Defaults to 0 (waits for all requests to complete)
609
691
  * @returns {Promise<T>} Promise that resolves to the callback's return value after network settles
610
692
  * @example
611
- * ```typescript Navigation with Network Settlement
693
+ * ```typescript Wrapper with Inline Function
612
694
  * import { withNetworkSettledWait } from "@intuned/browser";
613
- * export default async function handler(params, page, context){
614
- * // Navigate and ensure all resources are loaded
615
- * await withNetworkSettledWait(
616
- * async (page) => {
617
- * await page.goto('https://spa-app.com/dashboard');
618
- * // Return when navigation is complete and network is idle
619
- * },
620
- * {
621
- * page,
622
- * timeoutInMs: 20000,
623
- * maxInflightRequests: 0 // Wait for complete network silence
624
- * }
625
- * );
695
+ * import { BrowserContext, Page } from "playwright";
696
+ *
697
+ * interface Params {}
698
+ *
699
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
700
+ * await page.goto('https://sandbox.intuned.dev/infinite-scroll');
701
+ *
702
+ * // Execute action and wait for network to settle
703
+ * const result = await withNetworkSettledWait(
704
+ * async (page) => {
705
+ * // scroll to load more content
706
+ * await page.evaluate(() => {
707
+ * window.scrollTo(0, document.body.scrollHeight);
708
+ * });
709
+ * return "scrolled";
710
+ * },
711
+ * {
712
+ * page,
713
+ * timeoutInMs: 15000,
714
+ * maxInflightRequests: 0
715
+ * }
716
+ * );
717
+ * console.log(result); // "scrolled"
718
+ * return result;
719
+ * }
720
+ * ```
721
+ *
722
+ * @example
723
+ * ```typescript Click Link with Network Wait
724
+ * import { withNetworkSettledWait } from "@intuned/browser";
725
+ * import { BrowserContext, Page } from "playwright";
726
+ *
727
+ * interface Params {}
728
+ *
729
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
730
+ * await page.goto('https://sandbox.intuned.dev/');
731
+ *
732
+ * // Click Object Extractors link and wait for page to load
733
+ * await withNetworkSettledWait(
734
+ * async (page) => {
735
+ * await page.getByText('Object Extractors').click();
736
+ * },
737
+ * {
738
+ * page,
739
+ * timeoutInMs: 10000,
740
+ * maxInflightRequests: 0
741
+ * }
742
+ * );
743
+ * // Object Extractors page loaded
744
+ * const title = await page.locator('div h2').innerText();
745
+ * return title;
626
746
  * }
627
747
  * ```
628
748
  */
@@ -636,57 +756,70 @@ export declare function withNetworkSettledWait<T>(
636
756
  ): Promise<T>;
637
757
 
638
758
  /**
639
- * Waits for the DOM to stop changing before proceeding. Useful for dynamic content
640
- * that loads progressively or elements that appear/update after initial page load.
759
+ * Waits for DOM mutations to settle without executing any function first. This helper uses a MutationObserver to monitor DOM changes and waits until the DOM has been stable (no mutations) for the specified settle duration.
641
760
  *
642
- * This function monitors DOM mutations and waits for a specified duration of stability
643
- * before considering the DOM "settled". It can monitor either the entire page or a
644
- * specific element within the page.
761
+ * ## `waitForDomSettled` vs `withNetworkSettledWait`
762
+ *
763
+ * - Use `waitForDomSettled` when watching **DOM mutations** (elements added/removed/modified, loading spinners, dynamic content injection)
764
+ * - Use [withNetworkSettledWait](../functions/withNetworkSettledWait) when watching **network requests** (API calls, form submissions, resource loading)
645
765
  *
646
766
  * @param {Object} options - Configuration object for DOM settlement monitoring
647
- * @param {Page | Locator} options.source - The Playwright Page or Locator to monitor for DOM changes. When a Page is provided, monitors the entire document for changes. When a Locator is provided, only monitors changes within that specific element
767
+ * @param {Page | Locator} options.source - The Playwright Page or Locator to monitor for DOM changes. When a Page is provided, monitors the entire document. When a Locator is provided, monitors only that specific element.
648
768
  * @param {number} [options.settleDurationMs=500] - Milliseconds the DOM must remain unchanged to be considered settled. Defaults to 500
649
769
  * @param {number} [options.timeoutInMs=30000] - Maximum milliseconds to wait before giving up. Defaults to 30000
650
770
  * @returns {Promise<boolean>} Promise that resolves to true if DOM settled within timeout, false if timeout or error occurred
651
771
  *
652
772
  * @example
653
- * ```typescript Wait for Page Content to Stabilize
773
+ * ```typescript Wait After Navigation
654
774
  * import { waitForDomSettled } from '@intuned/browser';
655
- * export default async function handler(params, page, context){
656
- * // Navigate to a dynamic page
657
- * await page.goto('https://docs.intunedhq.com/docs-old/getting-started/introduction');
775
+ * import { BrowserContext, Page } from "playwright";
658
776
  *
659
- * // Wait for entire page content to stabilize
660
- * const settled = await waitForDomSettled({
661
- * source: page,
662
- * settleDurationMs: 1000
663
- * });
777
+ * interface Params {}
664
778
  *
665
- * if (settled) {
666
- * // Safe to scrape or interact with content
667
- * console.log(`Found stable items`);
668
- * } else {
669
- * console.log("DOM never fully settled, proceeding anyway");
670
- * }
779
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
780
+ * // Navigate to page with dynamic content
781
+ * await page.goto('https://sandbox.intuned.dev/lists/table');
782
+ *
783
+ * // Wait for all DOM mutations to complete
784
+ * const settled = await waitForDomSettled({
785
+ * source: page,
786
+ * settleDurationMs: 1000,
787
+ * timeoutInMs: 20000
788
+ * });
789
+ *
790
+ * if (settled) {
791
+ * // DOM is stable, safe to extract data
792
+ * const rows = await page.locator('table tr').all();
793
+ * return rows.length;
794
+ * }
795
+ * return 0;
671
796
  * }
672
797
  * ```
673
798
  *
674
799
  * @example
675
- * ```typescript Monitor Specific Container
800
+ * ```typescript Watch Specific Container
676
801
  * import { waitForDomSettled } from '@intuned/browser';
677
- * export default async function handler(params, page, context){
678
- * await page.goto("https://docs.intunedhq.com/")
679
- * // Wait for a specific feed container to stop updating
680
- * const settled = await waitForDomSettled({
681
- * source: page.locator("xpath=//div[@id='sidebar-content']"),
682
- * settleDurationMs: 2000,
683
- * timeoutInMs: 15000,
684
- * });
802
+ * import { BrowserContext, Page } from "playwright";
685
803
  *
686
- * if (settled) {
687
- * // Now the feed is stable, safe to extract articles
688
- * console.log(`Feed stabilized`);
689
- * }
804
+ * interface Params {}
805
+ *
806
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
807
+ * await page.goto("https://sandbox.intuned.dev/lists/table");
808
+ *
809
+ * // Only watch table container (ignore header/footer changes)
810
+ * const table = page.locator("table");
811
+ * const settled = await waitForDomSettled({
812
+ * source: table,
813
+ * settleDurationMs: 800,
814
+ * timeoutInMs: 15000,
815
+ * });
816
+ *
817
+ * if (settled) {
818
+ * // Table has finished loading
819
+ * const rows = await table.locator('tr').count();
820
+ * return rows;
821
+ * }
822
+ * return 0;
690
823
  * }
691
824
  * ```
692
825
  */
@@ -700,53 +833,71 @@ export declare function waitForDomSettled(options: {
700
833
  * Converts HTML content from a Playwright Page or Locator to semantic markdown format.
701
834
  *
702
835
  * @param {Object} input - The input object containing the source of the HTML content
703
- * @param {Page | Locator} input.source - The source of the HTML content. Can be a Playwright Page or a Playwright Locator. If a Playwright Page is provided, the HTML content will be extracted from the entire page. If a Playwright Locator is provided, the HTML content will be extracted from the specific element
836
+ * @param {Page | Locator} input.source - The source of the HTML content. When a Page is provided, extracts from the entire page. When a Locator is provided, extracts from that specific element.
704
837
  * @returns {Promise<string>} Promise that resolves to the markdown representation of the HTML content
838
+ *
705
839
  * @example
706
- * ```typescript locator source
840
+ * ```typescript Extract Markdown from Locator
707
841
  * import { extractMarkdown } from "@intuned/browser";
708
- * export default async function handler(params, page, context){
709
- * await page.goto("https://example.com");
710
- * const headerLocator = page.locator('h1')
711
- * const markdown = await extractMarkdown({ source: headerLocator })
712
- * console.log(markdown); // Outputs the markdown representation of the header
842
+ * import { BrowserContext, Page } from "playwright";
843
+ *
844
+ * interface Params {}
845
+ *
846
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
847
+ * await page.goto("https://books.toscrape.com/");
848
+ * const headerLocator = page.locator('h1').first(); // First title on the page
849
+ * const markdown = await extractMarkdown({ source: headerLocator }); // Extract markdown from the first title
850
+ * console.log(markdown);
851
+ * return markdown;
713
852
  * }
714
853
  * ```
854
+ *
715
855
  * @example
716
- * ```typescript string source
856
+ * ```typescript Extract Markdown from Page
717
857
  * import { extractMarkdown } from "@intuned/browser";
718
- * export default async function handler(params, page, context){
719
- * await page.goto("https://example.com");
720
- * const markdown = await extractMarkdown({ source: page });
721
- * console.log(markdown); // Outputs the markdown representation of the page
858
+ * import { BrowserContext, Page } from "playwright";
859
+ *
860
+ * interface Params {}
861
+ *
862
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
863
+ * await page.goto("https://sandbox.intuned.dev/pdfs");
864
+ * const markdown = await extractMarkdown({ source: page });
865
+ * console.log(markdown);
866
+ * return markdown;
722
867
  * }
723
868
  * ```
724
- *
725
869
  */
726
870
  export declare function extractMarkdown(input: {
727
871
  source: Page | Locator;
728
872
  }): Promise<string>;
729
873
 
730
874
  /**
731
- * Converts any URL source to an absolute, properly encoded URL by combining a relative URL with a base URL string.
875
+ * Converts any URL source to an absolute, properly encoded URL.
876
+ *
877
+ * @overload Base URL String
878
+ *
879
+ * Combines a relative URL with a base URL string. Use when you have an explicit base URL string to resolve relative paths against.
732
880
  *
733
- * @overload From Base URL String
734
881
  * @param {Object} input - Configuration object with different properties based on the overload
735
882
  * @param {string} input.url - The relative or absolute URL to resolve
736
883
  * @param {string} input.baseUrl - Base URL string to resolve relative URLs against
737
884
  * @returns {Promise<string>} Promise that resolves to the absolute, properly encoded URL string
738
885
  * @example
739
- * ```typescript String source
886
+ * ```typescript Resolve from Base URL String
740
887
  * import { resolveUrl } from '@intuned/browser';
741
- * export default async function handler(params, page, context){
742
- * await page.goto("https://example.com");
888
+ * import { BrowserContext, Page } from "playwright";
889
+ *
890
+ * interface Params {}
743
891
  *
744
- * // Using explicit base URL
892
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
893
+ * // Resolve from base URL string
745
894
  * const absoluteUrl = await resolveUrl({
746
- * url: "/api/users",
747
- * baseUrl: "https://example.com"
895
+ * url: "/lists/table",
896
+ * baseUrl: "https://sandbox.intuned.dev"
748
897
  * });
749
- * // Returns: "https://example.com/api/users"
898
+ * // Returns: "https://sandbox.intuned.dev/lists/table"
899
+ * console.log(absoluteUrl);
900
+ * return absoluteUrl;
750
901
  * }
751
902
  * ```
752
903
  */
@@ -756,24 +907,33 @@ export declare function resolveUrl(input: {
756
907
  }): Promise<string>;
757
908
 
758
909
  /**
759
- * Converts any URL source to an absolute, properly encoded URL by using the current page's URL as the base URL.
910
+ * Converts any URL source to an absolute, properly encoded URL.
911
+ *
912
+ * @overload Current Page's URL
913
+ *
914
+ * Uses the current page's URL as the base URL. Use when resolving URLs relative to the current page.
760
915
  *
761
- * @overload From The Current Page's URL
762
916
  * @param {Object} input - Configuration object with different properties based on the overload
763
917
  * @param {string} input.url - The relative or absolute URL to resolve
764
918
  * @param {Page} input.page - Playwright Page object to extract base URL from. The current page URL will be used as the base URL
765
919
  * @returns {Promise<string>} Promise that resolves to the absolute, properly encoded URL string
766
920
  * @example
767
- * ```typescript Page source
921
+ * ```typescript Resolve from the Current Page's URL
768
922
  * import { resolveUrl } from '@intuned/browser';
769
- * export default async function handler(params, page, context){
770
- * await page.goto("https://example.com");
771
- * // Using current page as base URL
923
+ * import { BrowserContext, Page } from "playwright";
924
+ *
925
+ * interface Params {}
926
+ *
927
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
928
+ * await page.goto("https://sandbox.intuned.dev/");
929
+ * // Resolve from the current page's URL
772
930
  * const absoluteUrl = await resolveUrl({
773
- * url: "/api/users",
931
+ * url: "/lists/table",
774
932
  * page: page
775
933
  * });
776
- * // Returns: "https://example.com/api/users"
934
+ * // Returns: "https://sandbox.intuned.dev/lists/table"
935
+ * console.log(absoluteUrl);
936
+ * return absoluteUrl;
777
937
  * }
778
938
  * ```
779
939
  */
@@ -783,21 +943,31 @@ export declare function resolveUrl(input: {
783
943
  }): Promise<string>;
784
944
 
785
945
  /**
786
- * Converts any URL source to an absolute, properly encoded URL by extracting the href attribute from a Playwright Locator pointing to an anchor element.
946
+ * Converts any URL source to an absolute, properly encoded URL.
947
+ *
948
+ * @overload Anchor Elements
949
+ *
950
+ * Extracts the href attribute from a Playwright Locator pointing to an anchor element. Use when extracting and resolving URLs from anchor (`<a>`) elements.
787
951
  *
788
- * @overload From Anchor Element
789
952
  * @param {Object} input - Configuration object with different properties based on the overload
790
- * @param {Locator} input.url - Playwright Locator pointing to an anchor element. The href attribute will be extracted and resolved
953
+ * @param {Locator} input.url - Playwright Locator pointing to an anchor element. The href attribute will be extracted and resolved relative to the current page.
791
954
  * @returns {Promise<string>} Promise that resolves to the absolute, properly encoded URL string
792
955
  * @example
793
- * ```typescript Locator source
956
+ * ```typescript Resolve from Anchor Element
794
957
  * import { resolveUrl } from '@intuned/browser';
795
- * export default async function handler(params, page, context){
796
- * await page.goto("https://sandbox.intuned.dev/");
797
- * const absoluteUrl = await resolveUrl({
798
- * url: page.locator("xpath=//a[normalize-space()='Steps Form']"),
799
- * });
800
- * // Returns: "https://sandbox.intuned.dev/steps-form"
958
+ * import { BrowserContext, Page } from "playwright";
959
+ *
960
+ * interface Params {}
961
+ *
962
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
963
+ * await page.goto("https://sandbox.intuned.dev/");
964
+ * // Resolve from Anchor Element
965
+ * const absoluteUrl = await resolveUrl({
966
+ * url: page.locator("xpath=//a[normalize-space()='Steps Form']"),
967
+ * });
968
+ * // Returns: "https://sandbox.intuned.dev/steps-form"
969
+ * console.log(absoluteUrl);
970
+ * return absoluteUrl;
801
971
  * }
802
972
  * ```
803
973
  */
@@ -806,31 +976,64 @@ export declare function resolveUrl(input: { url: Locator }): Promise<string>;
806
976
  /**
807
977
  * Represents an uploaded file stored in AWS S3 with metadata and utility methods.
808
978
  *
809
- * This interface provides a structured way to handle file information for files stored
810
- * in S3, including methods for generating presigned URLs, serialization, and accessing
811
- * file metadata.
979
+ * Provides a structured way to handle file information for files stored in S3, including methods for generating presigned URLs, serialization, and accessing file metadata.
812
980
  *
813
981
  * @interface Attachment
982
+ *
814
983
  * @example
815
- * ```typescript Attachment Usage
816
- * import { uploadFileToS3 } from "@intuned/browser";
817
- * export default async function handler(params, page, context){
818
- * // Typically returned from uploadFileToS3 or saveFileToS3
984
+ * ```typescript Basic Usage
985
+ * import { uploadFileToS3, Attachment } from "@intuned/browser";
986
+ * import { BrowserContext, Page } from "playwright";
819
987
  *
820
- * const uploadedFile: Attachment = await uploadFileToS3({
821
- * file: myFile,
822
- * configs: s3Config
823
- * });
988
+ * interface Params {}
989
+ *
990
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
991
+ * const uploadedFile: Attachment = await uploadFileToS3({
992
+ * file: myFile,
993
+ * configs: s3Config
994
+ * });
995
+ *
996
+ * // Access file properties
997
+ * console.log(uploadedFile.fileName);
998
+ * console.log(uploadedFile.suggestedFileName);
999
+ * }
1000
+ * ```
1001
+ *
1002
+ * @example
1003
+ * ```typescript Working with Presigned URLs
1004
+ * import { uploadFileToS3, Attachment } from "@intuned/browser";
1005
+ * import { BrowserContext, Page } from "playwright";
1006
+ *
1007
+ * interface Params {}
824
1008
  *
825
- * // Access file properties
826
- * console.log(uploadedFile.fileName); // "documents/report.pdf"
827
- * console.log(uploadedFile.suggestedFileName); // "Monthly Report.pdf"
1009
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1010
+ * const uploadedFile: Attachment = await uploadFileToS3({
1011
+ * file: myFile
1012
+ * });
828
1013
  *
829
- * // Get a presigned URL for download
830
- * const downloadUrl = await uploadedFile.getSignedUrl(3600); // 1 hour
1014
+ * // Generate a presigned URL for temporary access
1015
+ * const downloadUrl = await uploadedFile.getSignedUrl(3600); // 1 hour expiration
831
1016
  *
832
- * // Convert to dictionary for storage or API responses
833
- * const fileDict = uploadedFile.toDict();
1017
+ * // Get the permanent S3 URL
1018
+ * const s3Url = uploadedFile.getS3Key();
1019
+ * }
1020
+ * ```
1021
+ *
1022
+ * @example
1023
+ * ```typescript Serialization
1024
+ * import { uploadFileToS3, Attachment } from "@intuned/browser";
1025
+ * import { BrowserContext, Page } from "playwright";
1026
+ *
1027
+ * interface Params {}
1028
+ *
1029
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1030
+ * const uploadedFile: Attachment = await uploadFileToS3({
1031
+ * file: myFile
1032
+ * });
1033
+ *
1034
+ * // Convert to dictionary for storage or API responses
1035
+ * const fileDict = uploadedFile.toDict();
1036
+ * const fileJson = uploadedFile.toJSON();
834
1037
  * }
835
1038
  * ```
836
1039
  */
@@ -859,96 +1062,36 @@ export interface Attachment {
859
1062
  /**
860
1063
  * Returns a JSON-serializable record representation of the file.
861
1064
  *
862
- * @method Attachment.toJSON
863
- * @returns {Record<string, string>} Complete model data including all fields
864
- *
865
- * @example
866
- * ```typescript
867
- * import { uploadFileToS3 } from "@intuned/browser";
868
- * export default async function handler(params, page, context){
869
- * file.toJSON()
870
- * // {
871
- * // 'fileName': 'docs/report.pdf',
872
- * // 'bucket': 'uploads',
873
- * // 'region': 'us-east-1',
874
- * // 'endpoint': undefined,
875
- * // 'suggestedFileName': 'Report.pdf'
876
- * // }
877
- * }
878
- * ```
1065
+ * @returns `Record<string, string>` - Complete model data including all fields
879
1066
  */
880
1067
  toJSON(): Record<string, string>;
881
1068
 
882
1069
  /**
883
- * Converts the file metadata to a record, excluding the endpoint field.
884
- *
885
- * @method Attachment.toDict
886
- * @returns {Record<string, string>} Record with fileName, bucket, region, and suggestedFileName
1070
+ * Converts the file metadata to a record.
887
1071
  *
888
- * @example
889
- * ```typescript
890
- * import { uploadFileToS3 } from "@intuned/browser";
891
- * export default async function handler(params, page, context){
892
- * file.toDict()
893
- * // {
894
- * // 'fileName': 'docs/report.pdf',
895
- * // 'bucket': 'uploads',
896
- * // 'region': 'us-east-1',
897
- * // 'suggestedFileName': 'Report.pdf'
898
- * // }
899
- * }
900
- * ```
1072
+ * @returns `Record<string, string>` - Record with fileName, key, bucket, region, endpoint, suggestedFileName, and fileType
901
1073
  */
902
1074
  toDict(): Record<string, string>;
903
1075
 
904
1076
  /**
905
1077
  * Returns the full S3 URL for the file.
906
1078
  *
907
- * @method Attachment.getS3Key
908
- * @returns {string} Complete S3 URL
909
- *
910
- * @example
911
- * ```typescript
912
- * import { uploadFileToS3 } from "@intuned/browser";
913
- * export default async function handler(params, page, context){
914
- * file.getS3Key()
915
- * // "https://uploads.s3.us-east-1.amazonaws.com/docs/report.pdf"
916
- * }
917
- * ```
1079
+ * @returns `string` - Complete S3 URL in format: https://bucket.s3.region.amazonaws.com/filename
918
1080
  */
919
1081
  getS3Key(): string;
920
1082
 
921
1083
  /**
922
1084
  * Returns the file path/key within the S3 bucket.
923
1085
  *
924
- * @method Attachment.getFilePath
925
- * @returns {string} The fileName property (S3 object key)
926
- *
927
- * @example
928
- * ```typescript
929
- * import { uploadFileToS3 } from "@intuned/browser";
930
- * export default async function handler(params, page, context){
931
- * file.getFilePath()
932
- * // "docs/report.pdf"
933
- * }
934
- * ```
1086
+ * @returns `string` - The fileName property (S3 object key)
935
1087
  */
936
1088
  getFilePath(): string;
937
1089
 
938
1090
  /**
939
1091
  * Generates a presigned URL for secure, temporary access to the file.
940
1092
  *
941
- * @method Attachment.getSignedUrl
942
- * @param {number} [expiration=432000] - URL expiration time in seconds. Defaults to 432000 (5 days)
943
- * @returns {Promise<string>} Promise that resolves to presigned URL for downloading the file
944
- *
945
- * @example
946
- * ```typescript
947
- * import { uploadFileToS3 } from "@intuned/browser";
948
- * export default async function handler(params, page, context){
949
- * const url = await file.getSignedUrl(3600); // 1 hour expiration
950
- * }
951
- * ```
1093
+ * @param expiration - URL expiration time in seconds. Defaults to 432000 (5 days)
1094
+ * @returns `Promise<string>` - Presigned URL for downloading the file
952
1095
  */
953
1096
  getSignedUrl(expiration?: number): Promise<string>;
954
1097
  }
@@ -956,124 +1099,129 @@ export interface Attachment {
956
1099
  /**
957
1100
  * A union type representing different methods to trigger file downloads in web automation.
958
1101
  *
959
- * This type alias standardizes how download operations can be initiated, providing
960
- * multiple approaches to suit different automation scenarios.
961
- *
962
- * @type Trigger
1102
+ * This type standardizes how download operations can be initiated, providing multiple approaches for different automation scenarios.
963
1103
  *
964
- * **Type Information:**
1104
+ * **Type variants:**
965
1105
  * - `string`: Direct URL string to download from
966
1106
  * - `Locator`: Playwright Locator object pointing to a clickable download element
967
- * - `(page: Page) => Promise<void>`: Custom function that takes a Page and triggers the download
1107
+ * - `(page: Page) => Promise<void>`: Custom async function that takes a Page and triggers the download
968
1108
  *
969
1109
  * @example
970
1110
  * ```typescript URL String Trigger
971
1111
  * import { downloadFile } from "@intuned/browser";
972
- * export default async function handler(params, page, context){
973
- * // Direct download from URL
974
- * const download = await downloadFile({
975
- * page,
976
- * trigger: "https://example.com/report.pdf"
977
- * });
1112
+ * import { BrowserContext, Page } from "playwright";
1113
+ *
1114
+ * interface Params {}
1115
+ *
1116
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1117
+ * // Direct download from URL
1118
+ * const download = await downloadFile({
1119
+ * page,
1120
+ * trigger: "https://example.com/report.pdf"
1121
+ * });
978
1122
  * }
979
1123
  * ```
980
1124
  *
981
1125
  * @example
982
1126
  * ```typescript Locator Trigger
983
1127
  * import { downloadFile } from "@intuned/browser";
984
- * export default async function handler(params, page, context){
985
- * // Click a download button/link
986
- * const downloadButton = page.locator("#download-btn");
987
- * const download = await downloadFile({
988
- * page,
989
- * trigger: downloadButton
990
- * });
1128
+ * import { BrowserContext, Page } from "playwright";
1129
+ *
1130
+ * interface Params {}
1131
+ *
1132
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1133
+ * // Click a download button
1134
+ * const download = await downloadFile({
1135
+ * page,
1136
+ * trigger: page.locator("#download-btn")
1137
+ * });
991
1138
  * }
992
1139
  * ```
993
1140
  *
994
1141
  * @example
995
- * ```typescript Custom Function Trigger
1142
+ * ```typescript Callback Trigger
996
1143
  * import { downloadFile } from "@intuned/browser";
997
- * export default async function handler(params, page, context){
998
- * // Complex download logic
999
- * const download = await downloadFile({
1000
- * page,
1001
- * trigger: async (page) => {
1002
- * await page.click(".menu-trigger");
1003
- * await page.waitForSelector(".download-option");
1004
- * await page.click(".download-option");
1005
- * }
1006
- * });
1144
+ * import { BrowserContext, Page } from "playwright";
1145
+ *
1146
+ * interface Params {}
1147
+ *
1148
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1149
+ * // Custom download logic
1150
+ * const download = await downloadFile({
1151
+ * page,
1152
+ * trigger: async (p) => {
1153
+ * await p.locator("button.prepare").click();
1154
+ * await p.waitForSelector(".ready");
1155
+ * await p.locator("a.download-link").click();
1156
+ * }
1157
+ * });
1007
1158
  * }
1008
1159
  * ```
1009
- *
1010
- * @note
1011
- * All download functions in the helpers module accept Trigger for consistency.
1012
- * The trigger method determines how the download operation is initiated.
1013
1160
  */
1014
1161
  export type Trigger = string | Locator | ((page: Page) => Promise<void>);
1015
1162
 
1016
1163
  /**
1017
- * Configuration options for AWS S3 storage operations.
1164
+ * Configuration for AWS S3 storage operations.
1018
1165
  *
1019
- * This interface defines the authentication and configuration properties
1020
- * for connecting to and performing operations with AWS S3 storage. All properties
1021
- * are optional and will fall back to environment variables or default configuration.
1166
+ * Defines the parameters needed to connect to and interact with AWS S3 storage services. Supports both standard AWS S3 and S3-compatible storage services through custom endpoints.
1022
1167
  *
1023
1168
  * @interface S3Configs
1024
- * @example
1025
- * ```typescript S3 Configuration
1026
- * import { uploadFileToS3 } from "@intuned/browser";
1027
- * export default async function handler(params, page, context){
1028
- * // Basic S3 configuration
1029
- * const s3Config: S3Configs = {
1030
- * bucket: "my-app-uploads",
1031
- * region: "us-east-1",
1032
- * accessKeyId: "accessKeyId",
1033
- * secretAccessKey: "SecretAccessKeyId"
1034
- * };
1035
1169
  *
1036
- * // Use with file upload
1037
- * const attachment = await uploadFileToS3({
1038
- * file: myFile,
1039
- * configs: s3Config
1040
- * });
1170
+ * @example
1171
+ * ```typescript Basic Configuration
1172
+ * import { uploadFileToS3, S3Configs } from "@intuned/browser";
1173
+ * import { BrowserContext, Page } from "playwright";
1174
+ *
1175
+ * interface Params {}
1176
+ *
1177
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1178
+ * // Using explicit credentials
1179
+ * const s3Config: S3Configs = {
1180
+ * accessKeyId: "accessKeyId",
1181
+ * secretAccessKey: "SecretAccessKeyId",
1182
+ * bucket: "my-app-uploads",
1183
+ * region: "us-east-1"
1184
+ * };
1185
+ * }
1186
+ * ```
1041
1187
  *
1042
- * // Use with download and upload operations
1043
- * const uploadedFile = await saveFileToS3({
1044
- * page,
1045
- * trigger: downloadUrl,
1046
- * configs: s3Config
1047
- * });
1188
+ * @example
1189
+ * ```typescript Environment Variables Configuration
1190
+ * import { uploadFileToS3, S3Configs } from "@intuned/browser";
1191
+ * export default async function handler(params, page, context){
1192
+ * // Credentials will be picked up from environment or IAM roles
1193
+ * const s3Config: S3Configs = {
1194
+ * bucket: "my-app-uploads",
1195
+ * region: "us-west-2"
1196
+ * };
1048
1197
  * }
1049
1198
  * ```
1050
1199
  */
1051
1200
  export interface S3Configs {
1052
- /** The name of the S3 bucket where files will be stored or retrieved */
1201
+ /** Name of the S3 bucket to store files in. Must be a valid S3 bucket name following AWS naming conventions. */
1053
1202
  bucket?: string;
1054
1203
 
1055
- /** The AWS region where the S3 bucket is located (e.g., "us-east-1", "eu-west-1") */
1204
+ /** AWS region where the S3 bucket is located. Examples: "us-east-1", "eu-west-1", "ap-southeast-1" */
1056
1205
  region?: string;
1057
1206
 
1058
- /** AWS access key ID for authentication and authorization */
1207
+ /** AWS access key ID for authentication. If undefined, will attempt to use default AWS credentials or environment variables. */
1059
1208
  accessKeyId?: string;
1060
1209
 
1061
- /** AWS secret access key for authentication and authorization */
1210
+ /** AWS secret access key for authentication. If undefined, will attempt to use default AWS credentials or environment variables. */
1062
1211
  secretAccessKey?: string;
1063
1212
 
1064
- /** Custom S3 endpoint URL for S3-compatible storage services */
1213
+ /** Custom endpoint URL for S3-compatible storage services. Use this for services like MinIO, DigitalOcean Spaces, or other S3-compatible APIs. For standard AWS S3, leave this undefined. */
1065
1214
  endpoint?: string;
1066
1215
  }
1067
1216
 
1068
1217
  /**
1069
1218
  * A union type representing different file formats that can be processed by the SDK.
1070
1219
  *
1071
- * This type alias provides flexibility in how files can be passed to various functions,
1072
- * supporting multiple input formats for maximum convenience.
1220
+ * Provides flexibility in how files can be passed to various functions, supporting multiple input formats.
1073
1221
  *
1074
1222
  * @type FileType
1075
1223
  *
1076
- * **Type Information:**
1224
+ * **Type variants:**
1077
1225
  * - `Download`: Playwright Download object from browser download operations
1078
1226
  * - `Uint8Array`: Binary data as Uint8Array
1079
1227
  * - `Buffer`: Node.js Buffer containing binary data
@@ -1129,79 +1277,59 @@ export type FileType = Download | Uint8Array | Buffer | ReadStream;
1129
1277
  /**
1130
1278
  * Downloads a file from a web page and automatically uploads it to AWS S3 storage in a single operation.
1131
1279
  *
1132
- * This convenience function combines the functionality of `downloadFile` and `uploadFileToS3`,
1133
- * providing a streamlined workflow for capturing files from web pages and storing them in S3.
1134
- * It supports the same flexible trigger methods as `downloadFile` with additional S3 upload configuration.
1280
+ * Combines [downloadFile](./downloadFile) (for trigger methods) and [uploadFileToS3](./uploadFileToS3)
1281
+ * (for S3 configuration), providing a streamlined workflow for capturing and storing files.
1135
1282
  *
1136
1283
  * @param {Object} input - Configuration object for the download and upload operation
1137
1284
  * @param {Page} input.page - The Playwright Page object to use for downloading
1138
- * @param {Trigger} input.trigger - The [Trigger](../type-aliases/Trigger) method to initiate the download:
1139
- * - **URL string**: Navigate directly to a download URL
1140
- * - **Locator**: Click on an element to trigger download
1141
- * - **Callback function**: Execute custom logic to initiate download
1142
- * @param {number} [input.timeoutInMs=5000] - Maximum time in milliseconds to wait for download completion. Defaults to 5000.
1143
- * @param {S3Configs} [input.configs] - Optional [S3Configs](../interfaces/S3Configs) to customize the S3 upload
1144
- * @param {string} [input.fileNameOverride] - Optional filename override for the uploaded file
1145
- * @param {string} [input.contentType] - Optional content type for the uploaded file
1146
- * @returns {Promise<Attachment>} Promise that resolves to an [Attachment](../interfaces/Attachment) object with file metadata and S3 utilities
1285
+ * @param {Trigger} input.trigger - The [Trigger](../type-references/Trigger) method to initiate the download
1286
+ * @param {number} [input.timeoutInMs=5000] - Maximum time in milliseconds to wait for download to start. Defaults to 5000.
1287
+ * @param {S3Configs} [input.configs] - Optional [S3Configs](../type-references/S3Configs) to customize the S3 upload. If not provided, uses environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_ENDPOINT_URL, AWS_BUCKET). If environment variables aren't set, uses default Intuned S3 settings.
1288
+ * @param {string} [input.fileNameOverride] - Optional custom filename for the uploaded file. If not provided, uses the original filename or generates a unique name.
1289
+ * @param {string} [input.contentType] - Optional MIME type for the uploaded file (e.g., “application/pdf”, “image/png”).
1290
+ * @returns {Promise<Attachment>} Promise that resolves to an [Attachment](../type-references/Attachment) object with file metadata and S3 utilities
1147
1291
  *
1148
1292
  * @example
1149
- * ```typescript URL trigger
1150
- * import { saveFileToS3 } from "@intuned/browser";
1151
- * export default async function handler(params, page, context){
1152
- * // Download from URL and upload to S3 with custom configuration
1153
- * const uploadedFile = await saveFileToS3({
1154
- * page,
1155
- * trigger: "https://sandbox.intuned.dev/pdfs/report.pdf",
1156
- * configs: {
1157
- * bucket: 'document-storage',
1293
+ * ```typescript URL Trigger
1294
+ * import { saveFileToS3 } from "@intuned/browser"
1295
+ * import { BrowserContext, Page } from "playwright";
1296
+ *
1297
+ * interface Params {}
1298
+ *
1299
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1300
+ * const uploadedFile = await saveFileToS3({
1301
+ * page,
1302
+ * trigger: "https://sandbox.intuned.dev/pdfs/report.pdf",
1303
+ * configs: {
1304
+ * bucket: 'document-storage',
1158
1305
  * region: 'us-east-1',
1159
1306
  * accessKeyId: 'accessKeyId',
1160
1307
  * secretAccessKey: 'SecretAccessKeyId'
1161
- * },
1162
- * fileNameOverride: 'reports/monthly-report.pdf',
1163
- * contentType: 'application/pdf'
1164
- * });
1165
- *
1166
- * console.log(`File uploaded to: ${uploadedFile.getS3Key()}`);
1308
+ * },
1309
+ * fileNameOverride: 'reports/monthly-report.pdf'
1310
+ * });
1311
+ * console.log(`File uploaded to: ${uploadedFile.getS3Key()}`);
1167
1312
  * }
1168
1313
  * ```
1169
1314
  *
1170
1315
  * @example
1171
- * ```typescript Locator trigger
1316
+ * ```typescript Locator Trigger
1172
1317
  * import { saveFileToS3 } from "@intuned/browser";
1173
- * export default async function handler(params, page, context){
1174
- * // Click download link and save to S3
1175
- * await page.goto("https://sandbox.intuned.dev/pdfs")
1176
- * const uploadedFile = await saveFileToS3({
1177
- * page,
1178
- * trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']"),
1179
- * timeoutInMs: 10000,
1180
- * configs: {
1181
- * bucket: 'invoice-archive',
1182
- * region: 'us-west-2',
1183
- * accessKeyId: 'accessKeyId',
1184
- * secretAccessKey: 'SecretAccessKeyId'
1185
- * },
1186
- * fileNameOverride: 'invoices/invoice.pdf',
1187
- * contentType: 'application/pdf'
1188
- * });
1318
+ * import { BrowserContext, Page } from "playwright";
1189
1319
  *
1190
- * // Generate temporary access URL
1191
- * const downloadUrl = await uploadedFile.getSignedUrl(7200); // 2 hours
1192
- * console.log(`Temporary access: ${downloadUrl}`);
1320
+ * interface Params {}
1321
+ *
1322
+ * export default async function handler(params: Params, page: Page, context: BrowserContext){
1323
+ * await page.goto("https://sandbox.intuned.dev/pdfs");
1324
+ * const uploadedFile = await saveFileToS3({
1325
+ * page,
1326
+ * trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']"),
1327
+ * timeoutInMs: 10000
1328
+ * });
1329
+ * const downloadUrl = await uploadedFile.getSignedUrl(7200); // 2 hours
1330
+ * console.log(`Temporary access: ${downloadUrl}`);
1193
1331
  * }
1194
1332
  * ```
1195
- * @note
1196
- * **S3 Configuration hierarchy:** (same as `uploadFileToS3`):
1197
- * 1. Explicit `configs` values from the input
1198
- * 2. Standard AWS environment variables (`AWS_BUCKET`, `AWS_REGION`, etc.)
1199
- * 3. Intuned's default S3 configuration as fallback
1200
- *
1201
- * **Trigger Behavior** (same as `downloadFile`):
1202
- * - **URL**: Creates temporary page, navigates to URL, captures download, closes page
1203
- * - **Locator**: Uses current page to click element and capture download
1204
- * - **Callback**: Executes custom function and captures any resulting downloads
1205
1333
  */
1206
1334
  export declare function saveFileToS3(input: {
1207
1335
  page: Page;
@@ -1215,7 +1343,6 @@ export declare function saveFileToS3(input: {
1215
1343
  /**
1216
1344
  * Union type representing the supported attachment file types.
1217
1345
  *
1218
- * @type AttachmentType
1219
1346
  * Currently supported types:
1220
1347
  * - `"document"`: Document files (PDFs, Word docs, etc.)
1221
1348
  */