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