@intuned/browser-dev 0.1.4-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.
- package/.babelrc +21 -0
- package/.eslintignore +10 -0
- package/.eslintrc.js +39 -0
- package/BROWSER_SCRIPTS_SETUP.md +84 -0
- package/LICENSE +43 -0
- package/README.md +160 -0
- package/RELEASE.md +60 -0
- package/dist/ai/export.d.js +5 -0
- package/dist/ai/export.d.ts +641 -0
- package/dist/ai/extractStructuredData.js +320 -0
- package/dist/ai/extractStructuredDataUsingAi.js +142 -0
- package/dist/ai/extractionHelpers/screenshotHelpers.js +56 -0
- package/dist/ai/extractionHelpers/validateSchema.js +148 -0
- package/dist/ai/index.d.ts +641 -0
- package/dist/ai/index.js +19 -0
- package/dist/ai/isPageLoaded.js +80 -0
- package/dist/ai/prompt.js +39 -0
- package/dist/ai/tests/testCheckAllTypesAreStrings.spec.js +137 -0
- package/dist/ai/tests/testExtractFromContent.spec.js +372 -0
- package/dist/ai/tests/testExtractStructuredData.spec.js +646 -0
- package/dist/ai/tests/testIsPageLoaded.spec.js +277 -0
- package/dist/ai/tools/index.js +48 -0
- package/dist/ai/types/errors.js +67 -0
- package/dist/ai/types/models.js +45 -0
- package/dist/ai/types/types.js +48 -0
- package/dist/ai/validators.js +167 -0
- package/dist/common/Logger/index.js +60 -0
- package/dist/common/Logger/types.js +5 -0
- package/dist/common/SdkError.js +50 -0
- package/dist/common/aiModelsValidations.js +32 -0
- package/dist/common/ensureBrowserScripts.js +14 -0
- package/dist/common/extendedTest.js +157 -0
- package/dist/common/extractionHelpers.js +19 -0
- package/dist/common/formatZodError.js +18 -0
- package/dist/common/fuzzySearch/fuzzySearch.test.js +250 -0
- package/dist/common/fuzzySearch/levenshtein-search.js +298 -0
- package/dist/common/fuzzySearch/utils.js +23 -0
- package/dist/common/getModelProvider.js +18 -0
- package/dist/common/getSimplifiedHtml.js +122 -0
- package/dist/common/hashObject.js +32 -0
- package/dist/common/html2markdown/convertElementToMarkdown.js +469 -0
- package/dist/common/html2markdown/index.js +19 -0
- package/dist/common/jwtTokenManager.js +57 -0
- package/dist/common/loadRuntime.js +16 -0
- package/dist/common/locatorHelpers.js +41 -0
- package/dist/common/matching/collectStrings.js +32 -0
- package/dist/common/matching/levenshtein.js +40 -0
- package/dist/common/matching/matching.js +317 -0
- package/dist/common/matching/types.js +1 -0
- package/dist/common/noEmpty.js +9 -0
- package/dist/common/saveSnapshotWithExamples.js +60 -0
- package/dist/common/script.js +2602 -0
- package/dist/common/tests/testEnsureBrowserScript.spec.js +31 -0
- package/dist/common/xpathMapping.js +107 -0
- package/dist/helpers/clickUntilExhausted.js +85 -0
- package/dist/helpers/downloadFile.js +125 -0
- package/dist/helpers/export.d.js +5 -0
- package/dist/helpers/export.d.ts +1220 -0
- package/dist/helpers/extractMarkdown.js +35 -0
- package/dist/helpers/filterEmptyValues.js +54 -0
- package/dist/helpers/gotoUrl.js +98 -0
- package/dist/helpers/index.d.ts +1220 -0
- package/dist/helpers/index.js +122 -0
- package/dist/helpers/processDate.js +25 -0
- package/dist/helpers/resolveUrl.js +64 -0
- package/dist/helpers/sanitizeHtml.js +74 -0
- package/dist/helpers/saveFileToS3.js +50 -0
- package/dist/helpers/scrollToLoadContent.js +57 -0
- package/dist/helpers/tests/testClickUntilExhausted.spec.js +372 -0
- package/dist/helpers/tests/testDownloadFile.spec.js +206 -0
- package/dist/helpers/tests/testExtractMarkdown.spec.js +290 -0
- package/dist/helpers/tests/testFilterEmptyValues.spec.js +151 -0
- package/dist/helpers/tests/testGoToUrl.spec.js +37 -0
- package/dist/helpers/tests/testProcessDate.spec.js +13 -0
- package/dist/helpers/tests/testResolveUrl.spec.js +341 -0
- package/dist/helpers/tests/testSanitizeHtml.spec.js +330 -0
- package/dist/helpers/tests/testScrollToLoadContent.spec.js +163 -0
- package/dist/helpers/tests/testValidateDataUsingSchema.spec.js +342 -0
- package/dist/helpers/tests/testWithDomSettledWait.spec.js +164 -0
- package/dist/helpers/tests/testWithNetworkIdleWait.spec.js +114 -0
- package/dist/helpers/types/Attachment.js +115 -0
- package/dist/helpers/types/CustomTypeRegistry.js +48 -0
- package/dist/helpers/types/RunEnvironment.js +18 -0
- package/dist/helpers/types/ValidationError.js +17 -0
- package/dist/helpers/types/index.js +51 -0
- package/dist/helpers/uploadFileToS3.js +154 -0
- package/dist/helpers/utils/getS3Client.js +22 -0
- package/dist/helpers/utils/index.js +73 -0
- package/dist/helpers/utils/isDownload.js +10 -0
- package/dist/helpers/utils/isGenerateCodeMode.js +9 -0
- package/dist/helpers/utils/isLocator.js +9 -0
- package/dist/helpers/utils/jwtTokenManager.js +18 -0
- package/dist/helpers/validateDataUsingSchema.js +103 -0
- package/dist/helpers/waitForDomSettled.js +90 -0
- package/dist/helpers/withNetworkSettledWait.js +91 -0
- package/dist/index.d.js +16 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +16 -0
- package/dist/intunedServices/ApiGateway/aiApiGateway.js +143 -0
- package/dist/intunedServices/ApiGateway/factory.js +16 -0
- package/dist/intunedServices/ApiGateway/providers/Anthropic.js +26 -0
- package/dist/intunedServices/ApiGateway/providers/Gemini.js +29 -0
- package/dist/intunedServices/ApiGateway/providers/OpenAI.js +29 -0
- package/dist/intunedServices/ApiGateway/tests/testApiGateway.spec.js +355 -0
- package/dist/intunedServices/ApiGateway/types.js +11 -0
- package/dist/intunedServices/cache/cache.js +61 -0
- package/dist/intunedServices/cache/index.js +12 -0
- package/dist/intunedServices/cache/tests/testCache.spec.js +117 -0
- package/dist/optimized-extractors/common/buildExamplesPrompt.js +12 -0
- package/dist/optimized-extractors/common/buildImagesFromPage.js +55 -0
- package/dist/optimized-extractors/common/extractStructuredDataUsingClaude.js +135 -0
- package/dist/optimized-extractors/common/extractStructuredDataUsingGoogle.js +37 -0
- package/dist/optimized-extractors/common/extractStructuredDataUsingOpenAi.js +132 -0
- package/dist/optimized-extractors/common/extractStrucutredDataUsingAiInstance.js +122 -0
- package/dist/optimized-extractors/common/findTableHeaders.js +162 -0
- package/dist/optimized-extractors/common/index.js +55 -0
- package/dist/optimized-extractors/common/isTableHeaderOrFooter.js +84 -0
- package/dist/optimized-extractors/common/matching/matching.js +212 -0
- package/dist/optimized-extractors/common/matching/matching.test.js +655 -0
- package/dist/optimized-extractors/common/matching/types.js +18 -0
- package/dist/optimized-extractors/common/matching/utils.js +184 -0
- package/dist/optimized-extractors/common/utils.js +58 -0
- package/dist/optimized-extractors/export.d.js +5 -0
- package/dist/optimized-extractors/export.d.ts +397 -0
- package/dist/optimized-extractors/extractArray.js +120 -0
- package/dist/optimized-extractors/extractObject.js +104 -0
- package/dist/optimized-extractors/index.d.ts +397 -0
- package/dist/optimized-extractors/index.js +31 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/dynamicListExtractor.spec.js +269 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/findSetOfXpathsToCreateAnArrayExtractor.test.js +22 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/getContainerElement.test.js +21 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/partOfSameArrayXpath.test.js +42 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/testArrayExtractorFromLocator.spec.js +146 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/testArrayExtractorFromPage.spec.js +130 -0
- package/dist/optimized-extractors/listExtractionHelpers/__tests__/verifyThatAllXpathsArePartOfSameArray.test.js +9 -0
- package/dist/optimized-extractors/listExtractionHelpers/dynamicListExtractor.js +160 -0
- package/dist/optimized-extractors/listExtractionHelpers/errors.js +46 -0
- package/dist/optimized-extractors/listExtractionHelpers/getListMatches.js +14 -0
- package/dist/optimized-extractors/listExtractionHelpers/runAiExtraction.js +243 -0
- package/dist/optimized-extractors/listExtractionHelpers/typesAndSchema.js +5 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/extractPropertiesUsingGPTFromArray.js +277 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/extractStructuredListUsingAi.js +44 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/getListContainerXpath.js +94 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/getRelativeContainerXpathSelector.js +20 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/getSimplifiedHtmlPerListItem.js +21 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/tablesUtils.js +48 -0
- package/dist/optimized-extractors/listExtractionHelpers/utils/validateOptions.js +52 -0
- package/dist/optimized-extractors/models/anthropicModel.js +23 -0
- package/dist/optimized-extractors/models/openaiModel.js +23 -0
- package/dist/optimized-extractors/objectExtractionHelpers/AIExtractors.js +73 -0
- package/dist/optimized-extractors/objectExtractionHelpers/__tests__/checksumUtils.test.js +103 -0
- package/dist/optimized-extractors/objectExtractionHelpers/__tests__/testObjectExtractorFromLocator.spec.js +107 -0
- package/dist/optimized-extractors/objectExtractionHelpers/__tests__/testObjectExtractorFromPage.spec.js +107 -0
- package/dist/optimized-extractors/objectExtractionHelpers/calculateObjectExampleHash.js +28 -0
- package/dist/optimized-extractors/objectExtractionHelpers/captureSnapshot.js +26 -0
- package/dist/optimized-extractors/objectExtractionHelpers/checksumUtils.js +32 -0
- package/dist/optimized-extractors/objectExtractionHelpers/constants.js +7 -0
- package/dist/optimized-extractors/objectExtractionHelpers/dynamicObjectExtractor.js +106 -0
- package/dist/optimized-extractors/objectExtractionHelpers/errors.js +42 -0
- package/dist/optimized-extractors/objectExtractionHelpers/findDomMatches.js +54 -0
- package/dist/optimized-extractors/objectExtractionHelpers/getSimplifiedHtml.js +122 -0
- package/dist/optimized-extractors/objectExtractionHelpers/typesAndSchemas.js +5 -0
- package/dist/optimized-extractors/objectExtractionHelpers/validateDynamicObjectExtractorOptions.js +52 -0
- package/dist/optimized-extractors/types/aiModelsValidation.js +45 -0
- package/dist/optimized-extractors/types/errors.js +42 -0
- package/dist/optimized-extractors/types/jsonSchema.d.js +5 -0
- package/dist/optimized-extractors/types/jsonSchema.d.ts +50 -0
- package/dist/optimized-extractors/types/types.js +5 -0
- package/dist/optimized-extractors/validators.js +152 -0
- package/dist/types/intuned-runtime.d.js +1 -0
- package/dist/types/intuned-runtime.d.ts +64 -0
- package/dist/vite-env.d.js +1 -0
- package/dist/vite-env.d.ts +9 -0
- package/generated-docs/ai/functions/extractStructuredData.mdx +255 -0
- package/generated-docs/ai/functions/isPageLoaded.mdx +88 -0
- package/generated-docs/ai/interfaces/ArraySchema.mdx +36 -0
- package/generated-docs/ai/interfaces/BasicSchema.mdx +14 -0
- package/generated-docs/ai/interfaces/BooleanSchema.mdx +28 -0
- package/generated-docs/ai/interfaces/ImageBufferContentItem.mdx +16 -0
- package/generated-docs/ai/interfaces/ImageUrlContentItem.mdx +16 -0
- package/generated-docs/ai/interfaces/NumberSchema.mdx +35 -0
- package/generated-docs/ai/interfaces/ObjectSchema.mdx +39 -0
- package/generated-docs/ai/interfaces/StringSchema.mdx +35 -0
- package/generated-docs/ai/interfaces/TextContentItem.mdx +14 -0
- package/generated-docs/ai/type-aliases/ContentItem.mdx +12 -0
- package/generated-docs/ai/type-aliases/JsonSchema.mdx +47 -0
- package/generated-docs/ai/type-aliases/SUPPORTED_MODELS.mdx +85 -0
- package/generated-docs/helpers/functions/downloadFile.mdx +99 -0
- package/generated-docs/helpers/functions/extractMarkdown.mdx +56 -0
- package/generated-docs/helpers/functions/filterEmptyValues.mdx +51 -0
- package/generated-docs/helpers/functions/goToUrl.mdx +124 -0
- package/generated-docs/helpers/functions/processDate.mdx +55 -0
- package/generated-docs/helpers/functions/resolveUrl.mdx +165 -0
- package/generated-docs/helpers/functions/sanitizeHtml.mdx +113 -0
- package/generated-docs/helpers/functions/saveFileToS3.mdx +127 -0
- package/generated-docs/helpers/functions/scrollToLoadContent.mdx +89 -0
- package/generated-docs/helpers/functions/uploadFileToS3.mdx +121 -0
- package/generated-docs/helpers/functions/validateDataUsingSchema.mdx +90 -0
- package/generated-docs/helpers/functions/waitForDomSettled.mdx +91 -0
- package/generated-docs/helpers/functions/withNetworkSettledWait.mdx +76 -0
- package/generated-docs/helpers/interfaces/Attachment.mdx +56 -0
- package/generated-docs/helpers/interfaces/S3Configs.mdx +52 -0
- package/generated-docs/helpers/interfaces/SanitizeHtmlOptions.mdx +22 -0
- package/generated-docs/helpers/type-aliases/AttachmentType.mdx +10 -0
- package/generated-docs/helpers/type-aliases/FileType.mdx +61 -0
- package/generated-docs/helpers/type-aliases/Trigger.mdx +62 -0
- package/how-to-generate-docs.md +61 -0
- package/how-to-run-tests.md +42 -0
- package/intuned-runtime-setup.md +13 -0
- package/package.json +124 -0
- package/tsconfig.eslint.json +5 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,1220 @@
|
|
|
1
|
+
/* eslint-disable prettier/prettier */
|
|
2
|
+
// prettier-ignore-file
|
|
3
|
+
import type { Locator, Page, ElementHandle } from "playwright-core";
|
|
4
|
+
import type { ReadStream } from "fs";
|
|
5
|
+
import { Download } from "playwright-core";
|
|
6
|
+
import { SUPPORTED_MODELS } from "../ai/export";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configuration options for sanitizing HTML content.
|
|
10
|
+
*/
|
|
11
|
+
export interface SanitizeHtmlOptions {
|
|
12
|
+
/** The HTML content to sanitize */
|
|
13
|
+
html: string;
|
|
14
|
+
/** Remove all <script> elements. Defaults to true. */
|
|
15
|
+
removeScripts?: boolean;
|
|
16
|
+
/** Remove all <style> elements. Defaults to true. */
|
|
17
|
+
removeStyles?: boolean;
|
|
18
|
+
/** Remove all <svg> elements. Defaults to true. */
|
|
19
|
+
removeSvgs?: boolean;
|
|
20
|
+
/** Remove HTML comments. Defaults to true. */
|
|
21
|
+
removeComments?: boolean;
|
|
22
|
+
/** Remove attributes longer than maxAttributeLength. Defaults to true. */
|
|
23
|
+
removeLongAttributes?: boolean;
|
|
24
|
+
/** Maximum length for attributes before removal. Defaults to 500. */
|
|
25
|
+
maxAttributeLength?: number;
|
|
26
|
+
/** List of attribute names to always preserve. Defaults to ["class", "src"]. */
|
|
27
|
+
preserveAttributes?: string[];
|
|
28
|
+
/** Remove empty tags (except preserved ones). Defaults to true. */
|
|
29
|
+
removeEmptyTags?: boolean;
|
|
30
|
+
/** List of tag names to preserve even when empty. Defaults to ["img"]. */
|
|
31
|
+
preserveEmptyTags?: string[];
|
|
32
|
+
/** Remove extra whitespace between tags and empty lines. Defaults to true. */
|
|
33
|
+
minifyWhitespace?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Sanitizes and cleans HTML content by removing unwanted elements, attributes, and whitespace.
|
|
38
|
+
* Provides fine-grained control over each cleaning operation through configurable options.
|
|
39
|
+
*
|
|
40
|
+
* @param {SanitizeHtmlOptions} options - Configuration options for sanitization
|
|
41
|
+
* @param {string} options.html - The HTML content to sanitize
|
|
42
|
+
* @param {boolean} [options.removeScripts=true] - Remove all `<script>` elements. Defaults to true.
|
|
43
|
+
* @param {boolean} [options.removeStyles=true] - Remove all `<style>` elements. Defaults to true.
|
|
44
|
+
* @param {boolean} [options.removeSvgs=true] - Remove all `<svg>` elements. Defaults to true.
|
|
45
|
+
* @param {boolean} [options.removeComments=true] - Remove HTML comments. Defaults to true.
|
|
46
|
+
* @param {boolean} [options.removeLongAttributes=true] - Remove attributes longer than maxAttributeLength. Defaults to true.
|
|
47
|
+
* @param {number} [options.maxAttributeLength=500] - Maximum length for attributes before removal. Defaults to 500.
|
|
48
|
+
* @param {string[]} [options.preserveAttributes=["class", "src"]] - List of attribute names to always preserve. Defaults to ["class", "src"].
|
|
49
|
+
* @param {boolean} [options.removeEmptyTags=true] - Remove empty tags (except preserved ones). Defaults to true.
|
|
50
|
+
* @param {string[]} [options.preserveEmptyTags=["img"]] - List of tag names to preserve even when empty. Defaults to ["img"].
|
|
51
|
+
* @param {boolean} [options.minifyWhitespace=true] - Remove extra whitespace between tags and empty lines. Defaults to true.
|
|
52
|
+
* @returns {string} The sanitized HTML string
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript Basic Sanitization
|
|
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
|
+
*
|
|
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
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
export declare function sanitizeHtml(options: SanitizeHtmlOptions): string;
|
|
95
|
+
|
|
96
|
+
/**
|
|
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
|
|
103
|
+
*
|
|
104
|
+
* @param {Object} input - Configuration object for the download operation
|
|
105
|
+
* @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
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript URL trigger
|
|
112
|
+
* 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()}`);
|
|
120
|
+
* }
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript Locator trigger
|
|
125
|
+
* 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()}`);
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript Callback trigger
|
|
139
|
+
* 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()}`);
|
|
150
|
+
* }
|
|
151
|
+
* ```
|
|
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
|
+
*/
|
|
159
|
+
export declare function downloadFile(input: {
|
|
160
|
+
page: Page;
|
|
161
|
+
trigger: Trigger;
|
|
162
|
+
timeoutInMs?: number;
|
|
163
|
+
}): Promise<Download>;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Recursively filters out empty values from nested objects and arrays.
|
|
167
|
+
*
|
|
168
|
+
* This function removes the following empty values:
|
|
169
|
+
* - `null` and `undefined` values
|
|
170
|
+
* - Empty strings (after trimming whitespace)
|
|
171
|
+
* - Empty arrays
|
|
172
|
+
* - Empty objects
|
|
173
|
+
* - Arrays and objects that become empty after filtering their contents
|
|
174
|
+
*
|
|
175
|
+
* @param {Object} input - The input object containing the data to filter
|
|
176
|
+
* @param {T} input.data - The data structure to filter (object, array, or any other type)
|
|
177
|
+
* @returns {T} Filtered data structure with empty values removed
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript Basic Usage
|
|
181
|
+
* 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" }] }
|
|
186
|
+
* }
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
export declare function filterEmptyValues<T>(input: { data: T }): T;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 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-4o-2024-08-06"] - AI model to use for loading verification. See [SUPPORTED_MODELS](../type-aliases/SUPPORTED_MODELS) for all supported models. Defaults to "gpt-4o-2024-08-06"
|
|
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
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript Basic Navigation
|
|
213
|
+
* 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
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```typescript Navigation with options
|
|
226
|
+
* 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
|
|
237
|
+
* }
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript AI-Verified Loading for Dynamic Sites
|
|
242
|
+
* 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
|
|
253
|
+
* }
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export declare function goToUrl(input: {
|
|
257
|
+
page: Page;
|
|
258
|
+
url: string;
|
|
259
|
+
timeoutInMs?: number;
|
|
260
|
+
retries?: number;
|
|
261
|
+
throwOnTimeout?: boolean;
|
|
262
|
+
waitForLoadState?: "load" | "domcontentloaded" | "networkidle";
|
|
263
|
+
waitForLoadingStateUsingAi?: boolean;
|
|
264
|
+
model?: SUPPORTED_MODELS;
|
|
265
|
+
apiKey?: string;
|
|
266
|
+
}): Promise<void>;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Automatically scrolls through infinite scroll content by repeatedly scrolling to the bottom
|
|
270
|
+
* until no new content loads or maximum scroll limit is reached.
|
|
271
|
+
*
|
|
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
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript Basic Infinite Scroll
|
|
282
|
+
* import { scrollToLoadContent } from "@intuned/browser";
|
|
283
|
+
* export default async function handler(params, page, context){
|
|
284
|
+
* // Scroll through entire page content
|
|
285
|
+
* await page.goto("https://docs.intunedhq.com/docs-old/getting-started/introduction")
|
|
286
|
+
* await scrollToLoadContent({
|
|
287
|
+
* source: page,
|
|
288
|
+
* });
|
|
289
|
+
* // Now all content is loaded and visible
|
|
290
|
+
* }
|
|
291
|
+
* ```
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript Scroll Specific Container
|
|
295
|
+
* import { scrollToLoadContent } from "@intuned/browser";
|
|
296
|
+
* export default async function handler(params, page, context){
|
|
297
|
+
* // Scroll through a specific scrollable div
|
|
298
|
+
* await page.goto("https://docs.intunedhq.com/docs-old/getting-started/introduction")
|
|
299
|
+
* const container = page.locator("xpath=//div[@id='sidebar-content']");
|
|
300
|
+
* await scrollToLoadContent({
|
|
301
|
+
* source: container,
|
|
302
|
+
* maxScrolls: 20
|
|
303
|
+
* });
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
export declare function scrollToLoadContent(input: {
|
|
309
|
+
source: Page | Locator;
|
|
310
|
+
onScrollProgress?: CallableFunction;
|
|
311
|
+
maxScrolls?: number;
|
|
312
|
+
delayInMs?: number;
|
|
313
|
+
minHeightChange?: number;
|
|
314
|
+
}): Promise<void>;
|
|
315
|
+
|
|
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
|
+
export declare function clickButtonAndWait(input: {
|
|
343
|
+
page: Page;
|
|
344
|
+
buttonLocator: Locator;
|
|
345
|
+
clickDelay?: number;
|
|
346
|
+
}): Promise<void>;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Repeatedly click a button until no new content appears or max clicks reached.
|
|
350
|
+
*
|
|
351
|
+
* This function is useful for "Load More" buttons or paginated content where you need to
|
|
352
|
+
* keep clicking until all content is loaded. It provides several stopping conditions:
|
|
353
|
+
* - Button becomes invisible
|
|
354
|
+
* - Button becomes disabled
|
|
355
|
+
* - Maximum number of clicks reached
|
|
356
|
+
* - No change detected in container content (when containerLocator is provided)
|
|
357
|
+
*
|
|
358
|
+
* @param {Object} input - Configuration options
|
|
359
|
+
* @param {Page} input.page - Playwright Page object
|
|
360
|
+
* @param {Locator} input.buttonLocator - Locator for the button to click repeatedly
|
|
361
|
+
* @param {CallableFunction} [input.heartbeat] - Optional callback invoked after each click
|
|
362
|
+
* @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
|
|
366
|
+
* @returns {Promise<void>} Promise that resolves when clicking is exhausted
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript Load All Items
|
|
370
|
+
* 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')");
|
|
374
|
+
*
|
|
375
|
+
* // Click until button disappears or is disabled
|
|
376
|
+
* await clickUntilExhausted({
|
|
377
|
+
* page,
|
|
378
|
+
* buttonLocator: loadMoreButton,
|
|
379
|
+
* maxClicks: 20
|
|
380
|
+
* });
|
|
381
|
+
* }
|
|
382
|
+
* ```
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* ```typescript Track Container Changes
|
|
386
|
+
* 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");
|
|
391
|
+
*
|
|
392
|
+
* let clickCount = 0;
|
|
393
|
+
* await clickUntilExhausted({
|
|
394
|
+
* page,
|
|
395
|
+
* buttonLocator: loadMoreButton,
|
|
396
|
+
* containerLocator: productsContainer,
|
|
397
|
+
* heartbeat: () => {
|
|
398
|
+
* clickCount++;
|
|
399
|
+
* console.log(`Clicked ${clickCount} times`);
|
|
400
|
+
* },
|
|
401
|
+
* maxClicks: 30,
|
|
402
|
+
* clickDelay: 0.5,
|
|
403
|
+
* noChangeThreshold: 0
|
|
404
|
+
* });
|
|
405
|
+
* }
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
export declare function clickUntilExhausted(input: {
|
|
409
|
+
page: Page;
|
|
410
|
+
buttonLocator: Locator;
|
|
411
|
+
heartbeat?: CallableFunction;
|
|
412
|
+
containerLocator?: Locator;
|
|
413
|
+
maxClicks?: number;
|
|
414
|
+
clickDelay?: number;
|
|
415
|
+
noChangeThreshold?: number;
|
|
416
|
+
}): Promise<void>;
|
|
417
|
+
|
|
418
|
+
/**
|
|
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")
|
|
432
|
+
*
|
|
433
|
+
* @param {Object} input - The input object containing the date to process
|
|
434
|
+
* @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
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```typescript Basic Date Processing
|
|
439
|
+
* 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
|
|
443
|
+
* }
|
|
444
|
+
* ```
|
|
445
|
+
*/
|
|
446
|
+
export declare function processDate(input: { date: string }): Date | null;
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Uploads files to AWS S3 storage with flexible configuration options.
|
|
450
|
+
*
|
|
451
|
+
* 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
|
|
453
|
+
* handles file metadata and provides comprehensive S3 configuration options.
|
|
454
|
+
*
|
|
455
|
+
* @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
|
|
462
|
+
* @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
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```typescript Upload Downloaded File
|
|
467
|
+
* 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
|
+
* });
|
|
475
|
+
*
|
|
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'
|
|
483
|
+
* },
|
|
484
|
+
* fileNameOverride: 'reports/monthly-report.pdf'
|
|
485
|
+
* }
|
|
486
|
+
* });
|
|
487
|
+
*
|
|
488
|
+
* console.log(`File uploaded: ${uploadedFile.suggestedFileName}`);
|
|
489
|
+
* console.log(`S3 URL: ${uploadedFile.getS3Key()}`);
|
|
490
|
+
* }
|
|
491
|
+
* ```
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```typescript Upload Binary Data
|
|
495
|
+
* 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
|
|
514
|
+
* }
|
|
515
|
+
* ```
|
|
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
|
+
*/
|
|
528
|
+
|
|
529
|
+
export declare function uploadFileToS3(input: {
|
|
530
|
+
file: FileType;
|
|
531
|
+
configs?: S3Configs;
|
|
532
|
+
fileNameOverride?: string;
|
|
533
|
+
contentType?: string;
|
|
534
|
+
}): Promise<Attachment>;
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* 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.
|
|
539
|
+
*
|
|
540
|
+
* @param {Object} input - The input object containing data and schema
|
|
541
|
+
* @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
|
+
* @param {Record<string, any>} input.schema - JSON schema object defining validation rules
|
|
543
|
+
* @returns {Promise<void>} Promise that resolves if validation passes, throws ValidationError if it fails
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* ```typescript Basic User Data Validation
|
|
547
|
+
* 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
|
|
553
|
+
* };
|
|
554
|
+
*
|
|
555
|
+
* const userSchema = {
|
|
556
|
+
* type: "object",
|
|
557
|
+
* required: ["name", "email", "age"],
|
|
558
|
+
* properties: {
|
|
559
|
+
* name: { type: "string", minLength: 1 },
|
|
560
|
+
* email: { type: "string", format: "email" },
|
|
561
|
+
* age: { type: "number", minimum: 0 }
|
|
562
|
+
* }
|
|
563
|
+
* };
|
|
564
|
+
*
|
|
565
|
+
* await validateDataUsingSchema({ data: userData, schema: userSchema });
|
|
566
|
+
* // Validation passes, no error thrown
|
|
567
|
+
* }
|
|
568
|
+
* ```
|
|
569
|
+
* @example
|
|
570
|
+
* ```typescript Invalid Data Validation
|
|
571
|
+
* import { validateDataUsingSchema } from "@intuned/browser";
|
|
572
|
+
* export default async function handler(params, page, context){
|
|
573
|
+
* const userData = {
|
|
574
|
+
* name: "John Doe",
|
|
575
|
+
* email: "john@example.com",
|
|
576
|
+
* };
|
|
577
|
+
*
|
|
578
|
+
* const userSchema = {
|
|
579
|
+
* type: "object",
|
|
580
|
+
* required: ["name", "email", "age"],
|
|
581
|
+
* properties: {
|
|
582
|
+
* name: { type: "string", minLength: 1 },
|
|
583
|
+
* email: { type: "string", format: "email" },
|
|
584
|
+
* age: { type: "number", minimum: 0 }
|
|
585
|
+
* }
|
|
586
|
+
* };
|
|
587
|
+
*
|
|
588
|
+
* await validateDataUsingSchema({ data: userData, schema: userSchema });
|
|
589
|
+
* // Validation fails, throws ValidationError
|
|
590
|
+
* }
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
export declare function validateDataUsingSchema(input: {
|
|
594
|
+
data: Record<string, any>[] | Record<string, any>;
|
|
595
|
+
schema: Record<string, any>;
|
|
596
|
+
}): Promise<void>;
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Executes a callback function and waits for network requests to settle before returning.
|
|
600
|
+
*
|
|
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.
|
|
604
|
+
*
|
|
605
|
+
* @param {Function} callback - The callback function to execute. Receives the page object as parameter
|
|
606
|
+
* @param {Object} [options] - Configuration options for network monitoring
|
|
607
|
+
* @param {Page} options.page - The Playwright page object to monitor for network activity
|
|
608
|
+
* @param {number} [options.timeoutInMs=30000] - Maximum time to wait in milliseconds before timing out. Defaults to 30000
|
|
609
|
+
* @param {number} [options.maxInflightRequests=0] - Maximum number of pending requests to consider as "settled". Defaults to 0 (waits for all requests to complete)
|
|
610
|
+
* @returns {Promise<T>} Promise that resolves to the callback's return value after network settles
|
|
611
|
+
* @example
|
|
612
|
+
* ```typescript Navigation with Network Settlement
|
|
613
|
+
* 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
|
+
* );
|
|
627
|
+
* }
|
|
628
|
+
* ```
|
|
629
|
+
*/
|
|
630
|
+
export declare function withNetworkSettledWait<T>(
|
|
631
|
+
callback: (page: Page) => Promise<T>,
|
|
632
|
+
options?: {
|
|
633
|
+
page: Page;
|
|
634
|
+
timeoutInMs?: number;
|
|
635
|
+
maxInflightRequests?: number;
|
|
636
|
+
}
|
|
637
|
+
): Promise<T>;
|
|
638
|
+
|
|
639
|
+
/**
|
|
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.
|
|
642
|
+
*
|
|
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.
|
|
646
|
+
*
|
|
647
|
+
* @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
|
|
649
|
+
* @param {number} [options.settleDurationMs=500] - Milliseconds the DOM must remain unchanged to be considered settled. Defaults to 500
|
|
650
|
+
* @param {number} [options.timeoutInMs=30000] - Maximum milliseconds to wait before giving up. Defaults to 30000
|
|
651
|
+
* @returns {Promise<boolean>} Promise that resolves to true if DOM settled within timeout, false if timeout or error occurred
|
|
652
|
+
*
|
|
653
|
+
* @example
|
|
654
|
+
* ```typescript Wait for Page Content to Stabilize
|
|
655
|
+
* 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');
|
|
659
|
+
*
|
|
660
|
+
* // Wait for entire page content to stabilize
|
|
661
|
+
* const settled = await waitForDomSettled({
|
|
662
|
+
* source: page,
|
|
663
|
+
* settleDurationMs: 1000
|
|
664
|
+
* });
|
|
665
|
+
*
|
|
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
|
+
* }
|
|
672
|
+
* }
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* @example
|
|
676
|
+
* ```typescript Monitor Specific Container
|
|
677
|
+
* 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
|
+
* });
|
|
686
|
+
*
|
|
687
|
+
* if (settled) {
|
|
688
|
+
* // Now the feed is stable, safe to extract articles
|
|
689
|
+
* console.log(`Feed stabilized`);
|
|
690
|
+
* }
|
|
691
|
+
* }
|
|
692
|
+
* ```
|
|
693
|
+
*/
|
|
694
|
+
|
|
695
|
+
export declare function waitForDomSettled(options: {
|
|
696
|
+
source: Page | Locator;
|
|
697
|
+
settleDurationMs?: number;
|
|
698
|
+
timeoutInMs?: number;
|
|
699
|
+
}): Promise<boolean>;
|
|
700
|
+
/**
|
|
701
|
+
* Converts HTML content from a Playwright Page or Locator to semantic markdown format.
|
|
702
|
+
*
|
|
703
|
+
* @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
|
|
705
|
+
* @returns {Promise<string>} Promise that resolves to the markdown representation of the HTML content
|
|
706
|
+
* @example
|
|
707
|
+
* ```typescript locator source
|
|
708
|
+
* 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
|
|
714
|
+
* }
|
|
715
|
+
* ```
|
|
716
|
+
* @example
|
|
717
|
+
* ```typescript string source
|
|
718
|
+
* 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
|
|
723
|
+
* }
|
|
724
|
+
* ```
|
|
725
|
+
*
|
|
726
|
+
*/
|
|
727
|
+
export declare function extractMarkdown(input: {
|
|
728
|
+
source: Page | Locator;
|
|
729
|
+
}): Promise<string>;
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Converts any URL source to an absolute, properly encoded URL by combining a relative URL with a base URL string.
|
|
733
|
+
*
|
|
734
|
+
* @overload From Base URL String
|
|
735
|
+
* @param {Object} input - Configuration object with different properties based on the overload
|
|
736
|
+
* @param {string} input.url - The relative or absolute URL to resolve
|
|
737
|
+
* @param {string} input.baseUrl - Base URL string to resolve relative URLs against
|
|
738
|
+
* @returns {Promise<string>} Promise that resolves to the absolute, properly encoded URL string
|
|
739
|
+
* @example
|
|
740
|
+
* ```typescript String source
|
|
741
|
+
* import { resolveUrl } from '@intuned/browser';
|
|
742
|
+
* export default async function handler(params, page, context){
|
|
743
|
+
* await page.goto("https://example.com");
|
|
744
|
+
*
|
|
745
|
+
* // Using explicit base URL
|
|
746
|
+
* const absoluteUrl = await resolveUrl({
|
|
747
|
+
* url: "/api/users",
|
|
748
|
+
* baseUrl: "https://example.com"
|
|
749
|
+
* });
|
|
750
|
+
* // Returns: "https://example.com/api/users"
|
|
751
|
+
* }
|
|
752
|
+
* ```
|
|
753
|
+
*/
|
|
754
|
+
export declare function resolveUrl(input: {
|
|
755
|
+
url: string;
|
|
756
|
+
baseUrl: string;
|
|
757
|
+
}): Promise<string>;
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Converts any URL source to an absolute, properly encoded URL by using the current page's URL as the base URL.
|
|
761
|
+
*
|
|
762
|
+
* @overload From The Current Page's URL
|
|
763
|
+
* @param {Object} input - Configuration object with different properties based on the overload
|
|
764
|
+
* @param {string} input.url - The relative or absolute URL to resolve
|
|
765
|
+
* @param {Page} input.page - Playwright Page object to extract base URL from. The current page URL will be used as the base URL
|
|
766
|
+
* @returns {Promise<string>} Promise that resolves to the absolute, properly encoded URL string
|
|
767
|
+
* @example
|
|
768
|
+
* ```typescript Page source
|
|
769
|
+
* 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
|
|
773
|
+
* const absoluteUrl = await resolveUrl({
|
|
774
|
+
* url: "/api/users",
|
|
775
|
+
* page: page
|
|
776
|
+
* });
|
|
777
|
+
* // Returns: "https://example.com/api/users"
|
|
778
|
+
* }
|
|
779
|
+
* ```
|
|
780
|
+
*/
|
|
781
|
+
export declare function resolveUrl(input: {
|
|
782
|
+
url: string;
|
|
783
|
+
page: Page;
|
|
784
|
+
}): Promise<string>;
|
|
785
|
+
|
|
786
|
+
/**
|
|
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.
|
|
788
|
+
*
|
|
789
|
+
* @overload From Anchor Element
|
|
790
|
+
* @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
|
|
792
|
+
* @returns {Promise<string>} Promise that resolves to the absolute, properly encoded URL string
|
|
793
|
+
* @example
|
|
794
|
+
* ```typescript Locator source
|
|
795
|
+
* 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"
|
|
802
|
+
* }
|
|
803
|
+
* ```
|
|
804
|
+
*/
|
|
805
|
+
export declare function resolveUrl(input: { url: Locator }): Promise<string>;
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Represents an uploaded file stored in AWS S3 with metadata and utility methods.
|
|
809
|
+
*
|
|
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.
|
|
813
|
+
*
|
|
814
|
+
* @interface Attachment
|
|
815
|
+
* @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
|
|
820
|
+
*
|
|
821
|
+
* const uploadedFile: Attachment = await uploadFileToS3({
|
|
822
|
+
* file: myFile,
|
|
823
|
+
* configs: s3Config
|
|
824
|
+
* });
|
|
825
|
+
*
|
|
826
|
+
* // Access file properties
|
|
827
|
+
* console.log(uploadedFile.fileName); // "documents/report.pdf"
|
|
828
|
+
* console.log(uploadedFile.suggestedFileName); // "Monthly Report.pdf"
|
|
829
|
+
*
|
|
830
|
+
* // Get a presigned URL for download
|
|
831
|
+
* const downloadUrl = await uploadedFile.getSignedUrl(3600); // 1 hour
|
|
832
|
+
*
|
|
833
|
+
* // Convert to dictionary for storage or API responses
|
|
834
|
+
* const fileDict = uploadedFile.toDict();
|
|
835
|
+
* }
|
|
836
|
+
* ```
|
|
837
|
+
*/
|
|
838
|
+
export interface Attachment {
|
|
839
|
+
/** The name/key of the file in the S3 bucket */
|
|
840
|
+
fileName: string;
|
|
841
|
+
|
|
842
|
+
/** The S3 bucket name where the file is stored */
|
|
843
|
+
bucket: string;
|
|
844
|
+
|
|
845
|
+
/** The AWS region where the S3 bucket is located */
|
|
846
|
+
region: string;
|
|
847
|
+
|
|
848
|
+
/** Optional custom S3 endpoint URL. Defaults to undefined for standard AWS S3 */
|
|
849
|
+
endpoint?: string;
|
|
850
|
+
|
|
851
|
+
/** A human-readable filename suggestion for downloads or display */
|
|
852
|
+
suggestedFileName: string;
|
|
853
|
+
|
|
854
|
+
/** The file type of the file */
|
|
855
|
+
fileType?: AttachmentType;
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Returns a JSON-serializable record representation of the file.
|
|
859
|
+
*
|
|
860
|
+
* @method Attachment.toJSON
|
|
861
|
+
* @returns {Record<string, string>} Complete model data including all fields
|
|
862
|
+
*
|
|
863
|
+
* @example
|
|
864
|
+
* ```typescript
|
|
865
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
866
|
+
* export default async function handler(params, page, context){
|
|
867
|
+
* file.toJSON()
|
|
868
|
+
* // {
|
|
869
|
+
* // 'fileName': 'docs/report.pdf',
|
|
870
|
+
* // 'bucket': 'uploads',
|
|
871
|
+
* // 'region': 'us-east-1',
|
|
872
|
+
* // 'endpoint': undefined,
|
|
873
|
+
* // 'suggestedFileName': 'Report.pdf'
|
|
874
|
+
* // }
|
|
875
|
+
* }
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
toJSON(): Record<string, string>;
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Converts the file metadata to a record, excluding the endpoint field.
|
|
882
|
+
*
|
|
883
|
+
* @method Attachment.toDict
|
|
884
|
+
* @returns {Record<string, string>} Record with fileName, bucket, region, and suggestedFileName
|
|
885
|
+
*
|
|
886
|
+
* @example
|
|
887
|
+
* ```typescript
|
|
888
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
889
|
+
* export default async function handler(params, page, context){
|
|
890
|
+
* file.toDict()
|
|
891
|
+
* // {
|
|
892
|
+
* // 'fileName': 'docs/report.pdf',
|
|
893
|
+
* // 'bucket': 'uploads',
|
|
894
|
+
* // 'region': 'us-east-1',
|
|
895
|
+
* // 'suggestedFileName': 'Report.pdf'
|
|
896
|
+
* // }
|
|
897
|
+
* }
|
|
898
|
+
* ```
|
|
899
|
+
*/
|
|
900
|
+
toDict(): Record<string, string>;
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Returns the full S3 URL for the file.
|
|
904
|
+
*
|
|
905
|
+
* @method Attachment.getS3Key
|
|
906
|
+
* @returns {string} Complete S3 URL
|
|
907
|
+
*
|
|
908
|
+
* @example
|
|
909
|
+
* ```typescript
|
|
910
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
911
|
+
* export default async function handler(params, page, context){
|
|
912
|
+
* file.getS3Key()
|
|
913
|
+
* // "https://uploads.s3.us-east-1.amazonaws.com/docs/report.pdf"
|
|
914
|
+
* }
|
|
915
|
+
* ```
|
|
916
|
+
*/
|
|
917
|
+
getS3Key(): string;
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Returns the file path/key within the S3 bucket.
|
|
921
|
+
*
|
|
922
|
+
* @method Attachment.getFilePath
|
|
923
|
+
* @returns {string} The fileName property (S3 object key)
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* ```typescript
|
|
927
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
928
|
+
* export default async function handler(params, page, context){
|
|
929
|
+
* file.getFilePath()
|
|
930
|
+
* // "docs/report.pdf"
|
|
931
|
+
* }
|
|
932
|
+
* ```
|
|
933
|
+
*/
|
|
934
|
+
getFilePath(): string;
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* Generates a presigned URL for secure, temporary access to the file.
|
|
938
|
+
*
|
|
939
|
+
* @method Attachment.getSignedUrl
|
|
940
|
+
* @param {number} [expiration=432000] - URL expiration time in seconds. Defaults to 432000 (5 days)
|
|
941
|
+
* @returns {Promise<string>} Promise that resolves to presigned URL for downloading the file
|
|
942
|
+
*
|
|
943
|
+
* @example
|
|
944
|
+
* ```typescript
|
|
945
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
946
|
+
* export default async function handler(params, page, context){
|
|
947
|
+
* const url = await file.getSignedUrl(3600); // 1 hour expiration
|
|
948
|
+
* }
|
|
949
|
+
* ```
|
|
950
|
+
*/
|
|
951
|
+
getSignedUrl(expiration?: number): Promise<string>;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* A union type representing different methods to trigger file downloads in web automation.
|
|
956
|
+
*
|
|
957
|
+
* This type alias standardizes how download operations can be initiated, providing
|
|
958
|
+
* multiple approaches to suit different automation scenarios.
|
|
959
|
+
*
|
|
960
|
+
* @type Trigger
|
|
961
|
+
*
|
|
962
|
+
* **Type Information:**
|
|
963
|
+
* - `string`: Direct URL string to download from
|
|
964
|
+
* - `Locator`: Playwright Locator object pointing to a clickable download element
|
|
965
|
+
* - `(page: Page) => Promise<void>`: Custom function that takes a Page and triggers the download
|
|
966
|
+
*
|
|
967
|
+
* @example
|
|
968
|
+
* ```typescript URL String Trigger
|
|
969
|
+
* import { downloadFile } from "@intuned/browser";
|
|
970
|
+
* export default async function handler(params, page, context){
|
|
971
|
+
* // Direct download from URL
|
|
972
|
+
* const download = await downloadFile({
|
|
973
|
+
* page,
|
|
974
|
+
* trigger: "https://example.com/report.pdf"
|
|
975
|
+
* });
|
|
976
|
+
* }
|
|
977
|
+
* ```
|
|
978
|
+
*
|
|
979
|
+
* @example
|
|
980
|
+
* ```typescript Locator Trigger
|
|
981
|
+
* import { downloadFile } from "@intuned/browser";
|
|
982
|
+
* export default async function handler(params, page, context){
|
|
983
|
+
* // Click a download button/link
|
|
984
|
+
* const downloadButton = page.locator("#download-btn");
|
|
985
|
+
* const download = await downloadFile({
|
|
986
|
+
* page,
|
|
987
|
+
* trigger: downloadButton
|
|
988
|
+
* });
|
|
989
|
+
* }
|
|
990
|
+
* ```
|
|
991
|
+
*
|
|
992
|
+
* @example
|
|
993
|
+
* ```typescript Custom Function Trigger
|
|
994
|
+
* import { downloadFile } from "@intuned/browser";
|
|
995
|
+
* export default async function handler(params, page, context){
|
|
996
|
+
* // Complex download logic
|
|
997
|
+
* const download = await downloadFile({
|
|
998
|
+
* page,
|
|
999
|
+
* trigger: async (page) => {
|
|
1000
|
+
* await page.click(".menu-trigger");
|
|
1001
|
+
* await page.waitForSelector(".download-option");
|
|
1002
|
+
* await page.click(".download-option");
|
|
1003
|
+
* }
|
|
1004
|
+
* });
|
|
1005
|
+
* }
|
|
1006
|
+
* ```
|
|
1007
|
+
*
|
|
1008
|
+
* @note
|
|
1009
|
+
* All download functions in the helpers module accept Trigger for consistency.
|
|
1010
|
+
* The trigger method determines how the download operation is initiated.
|
|
1011
|
+
*/
|
|
1012
|
+
export type Trigger = string | Locator | ((page: Page) => Promise<void>);
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Configuration options for AWS S3 storage operations.
|
|
1016
|
+
*
|
|
1017
|
+
* This interface defines the authentication and configuration properties
|
|
1018
|
+
* for connecting to and performing operations with AWS S3 storage. All properties
|
|
1019
|
+
* are optional and will fall back to environment variables or default configuration.
|
|
1020
|
+
*
|
|
1021
|
+
* @interface S3Configs
|
|
1022
|
+
* @example
|
|
1023
|
+
* ```typescript S3 Configuration
|
|
1024
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
1025
|
+
* export default async function handler(params, page, context){
|
|
1026
|
+
* // Basic S3 configuration
|
|
1027
|
+
* const s3Config: S3Configs = {
|
|
1028
|
+
* bucket: "my-app-uploads",
|
|
1029
|
+
* region: "us-east-1",
|
|
1030
|
+
* accessKeyId: "accessKeyId",
|
|
1031
|
+
* secretAccessKey: "SecretAccessKeyId"
|
|
1032
|
+
* };
|
|
1033
|
+
*
|
|
1034
|
+
* // Use with file upload
|
|
1035
|
+
* const attachment = await uploadFileToS3({
|
|
1036
|
+
* file: myFile,
|
|
1037
|
+
* configs: s3Config
|
|
1038
|
+
* });
|
|
1039
|
+
*
|
|
1040
|
+
* // Use with download and upload operations
|
|
1041
|
+
* const uploadedFile = await saveFileToS3({
|
|
1042
|
+
* page,
|
|
1043
|
+
* trigger: downloadUrl,
|
|
1044
|
+
* configs: s3Config
|
|
1045
|
+
* });
|
|
1046
|
+
* }
|
|
1047
|
+
* ```
|
|
1048
|
+
*/
|
|
1049
|
+
export interface S3Configs {
|
|
1050
|
+
/** The name of the S3 bucket where files will be stored or retrieved */
|
|
1051
|
+
bucket?: string;
|
|
1052
|
+
|
|
1053
|
+
/** The AWS region where the S3 bucket is located (e.g., "us-east-1", "eu-west-1") */
|
|
1054
|
+
region?: string;
|
|
1055
|
+
|
|
1056
|
+
/** AWS access key ID for authentication and authorization */
|
|
1057
|
+
accessKeyId?: string;
|
|
1058
|
+
|
|
1059
|
+
/** AWS secret access key for authentication and authorization */
|
|
1060
|
+
secretAccessKey?: string;
|
|
1061
|
+
|
|
1062
|
+
/** Custom S3 endpoint URL for S3-compatible storage services */
|
|
1063
|
+
endpoint?: string;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* A union type representing different file formats that can be processed by the SDK.
|
|
1068
|
+
*
|
|
1069
|
+
* This type alias provides flexibility in how files can be passed to various functions,
|
|
1070
|
+
* supporting multiple input formats for maximum convenience.
|
|
1071
|
+
*
|
|
1072
|
+
* @type FileType
|
|
1073
|
+
*
|
|
1074
|
+
* **Type Information:**
|
|
1075
|
+
* - `Download`: Playwright Download object from browser download operations
|
|
1076
|
+
* - `Uint8Array`: Binary data as Uint8Array
|
|
1077
|
+
* - `Buffer`: Node.js Buffer containing binary data
|
|
1078
|
+
* - `ReadStream`: Node.js file stream for reading files
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* ```typescript Using Download Object
|
|
1082
|
+
* import { downloadFile, uploadFileToS3 } from "@intuned/browser";
|
|
1083
|
+
* export default async function handler(params, page, context){
|
|
1084
|
+
* // From a browser download
|
|
1085
|
+
* const download = await downloadFile({
|
|
1086
|
+
* page,
|
|
1087
|
+
* trigger: "https://example.com/file.pdf"
|
|
1088
|
+
* });
|
|
1089
|
+
* const uploaded = await uploadFileToS3({
|
|
1090
|
+
* file: download,
|
|
1091
|
+
* configs: s3Config
|
|
1092
|
+
* });
|
|
1093
|
+
* }
|
|
1094
|
+
* ```
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* ```typescript Using Buffer
|
|
1098
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
1099
|
+
* export default async function handler(params, page, context){
|
|
1100
|
+
* // From raw buffer
|
|
1101
|
+
* const fileBuffer = Buffer.from("PDF content here...", "utf8");
|
|
1102
|
+
* const uploaded = await uploadFileToS3({
|
|
1103
|
+
* file: fileBuffer,
|
|
1104
|
+
* fileNameOverride: "generated.pdf",
|
|
1105
|
+
* configs: s3Config
|
|
1106
|
+
* });
|
|
1107
|
+
* }
|
|
1108
|
+
* ```
|
|
1109
|
+
*
|
|
1110
|
+
* @example
|
|
1111
|
+
* ```typescript Using ReadStream
|
|
1112
|
+
* import { uploadFileToS3 } from "@intuned/browser";
|
|
1113
|
+
* import { createReadStream } from "fs";
|
|
1114
|
+
* export default async function handler(params, page, context){
|
|
1115
|
+
* // From a file stream
|
|
1116
|
+
* const fileStream = createReadStream("/path/to/document.pdf");
|
|
1117
|
+
* const uploaded = await uploadFileToS3({
|
|
1118
|
+
* file: fileStream,
|
|
1119
|
+
* fileNameOverride: "renamed.pdf",
|
|
1120
|
+
* configs: s3Config
|
|
1121
|
+
* });
|
|
1122
|
+
* }
|
|
1123
|
+
* ```
|
|
1124
|
+
*/
|
|
1125
|
+
export type FileType = Download | Uint8Array | Buffer | ReadStream;
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Downloads a file from a web page and automatically uploads it to AWS S3 storage in a single operation.
|
|
1129
|
+
*
|
|
1130
|
+
* This convenience function combines the functionality of `downloadFile` and `uploadFileToS3`,
|
|
1131
|
+
* providing a streamlined workflow for capturing files from web pages and storing them in S3.
|
|
1132
|
+
* It supports the same flexible trigger methods as `downloadFile` with additional S3 upload configuration.
|
|
1133
|
+
*
|
|
1134
|
+
* @param {Object} input - Configuration object for the download and upload operation
|
|
1135
|
+
* @param {Page} input.page - The Playwright Page object to use for downloading
|
|
1136
|
+
* @param {Trigger} input.trigger - The [Trigger](../type-aliases/Trigger) method to initiate the download:
|
|
1137
|
+
* - **URL string**: Navigate directly to a download URL
|
|
1138
|
+
* - **Locator**: Click on an element to trigger download
|
|
1139
|
+
* - **Callback function**: Execute custom logic to initiate download
|
|
1140
|
+
* @param {number} [input.timeoutInMs=5000] - Maximum time in milliseconds to wait for download completion. Defaults to 5000.
|
|
1141
|
+
* @param {S3Configs} [input.configs] - Optional [S3Configs](../interfaces/S3Configs) to customize the S3 upload
|
|
1142
|
+
* @param {string} [input.fileNameOverride] - Optional filename override for the uploaded file
|
|
1143
|
+
* @param {string} [input.contentType] - Optional content type for the uploaded file
|
|
1144
|
+
* @returns {Promise<Attachment>} Promise that resolves to an [Attachment](../interfaces/Attachment) object with file metadata and S3 utilities
|
|
1145
|
+
*
|
|
1146
|
+
* @example
|
|
1147
|
+
* ```typescript URL trigger
|
|
1148
|
+
* import { saveFileToS3 } from "@intuned/browser";
|
|
1149
|
+
* export default async function handler(params, page, context){
|
|
1150
|
+
* // Download from URL and upload to S3 with custom configuration
|
|
1151
|
+
* const uploadedFile = await saveFileToS3({
|
|
1152
|
+
* page,
|
|
1153
|
+
* trigger: "https://sandbox.intuned.dev/pdfs/report.pdf",
|
|
1154
|
+
* configs: {
|
|
1155
|
+
* bucket: 'document-storage',
|
|
1156
|
+
* region: 'us-east-1',
|
|
1157
|
+
* accessKeyId: 'accessKeyId',
|
|
1158
|
+
* secretAccessKey: 'SecretAccessKeyId'
|
|
1159
|
+
* },
|
|
1160
|
+
* fileNameOverride: 'reports/monthly-report.pdf',
|
|
1161
|
+
* contentType: 'application/pdf'
|
|
1162
|
+
* });
|
|
1163
|
+
*
|
|
1164
|
+
* console.log(`File uploaded to: ${uploadedFile.getS3Key()}`);
|
|
1165
|
+
* }
|
|
1166
|
+
* ```
|
|
1167
|
+
*
|
|
1168
|
+
* @example
|
|
1169
|
+
* ```typescript Locator trigger
|
|
1170
|
+
* import { saveFileToS3 } from "@intuned/browser";
|
|
1171
|
+
* export default async function handler(params, page, context){
|
|
1172
|
+
* // Click download link and save to S3
|
|
1173
|
+
* await page.goto("https://sandbox.intuned.dev/pdfs")
|
|
1174
|
+
* const uploadedFile = await saveFileToS3({
|
|
1175
|
+
* page,
|
|
1176
|
+
* trigger: page.locator("xpath=//tbody/tr[1]//*[name()='svg']"),
|
|
1177
|
+
* timeoutInMs: 10000,
|
|
1178
|
+
* configs: {
|
|
1179
|
+
* bucket: 'invoice-archive',
|
|
1180
|
+
* region: 'us-west-2',
|
|
1181
|
+
* accessKeyId: 'accessKeyId',
|
|
1182
|
+
* secretAccessKey: 'SecretAccessKeyId'
|
|
1183
|
+
* },
|
|
1184
|
+
* fileNameOverride: 'invoices/invoice.pdf',
|
|
1185
|
+
* contentType: 'application/pdf'
|
|
1186
|
+
* });
|
|
1187
|
+
*
|
|
1188
|
+
* // Generate temporary access URL
|
|
1189
|
+
* const downloadUrl = await uploadedFile.getSignedUrl(7200); // 2 hours
|
|
1190
|
+
* console.log(`Temporary access: ${downloadUrl}`);
|
|
1191
|
+
* }
|
|
1192
|
+
* ```
|
|
1193
|
+
* @note
|
|
1194
|
+
* **S3 Configuration hierarchy:** (same as `uploadFileToS3`):
|
|
1195
|
+
* 1. Explicit `configs` values from the input
|
|
1196
|
+
* 2. Standard AWS environment variables (`AWS_BUCKET`, `AWS_REGION`, etc.)
|
|
1197
|
+
* 3. Intuned's default S3 configuration as fallback
|
|
1198
|
+
*
|
|
1199
|
+
* **Trigger Behavior** (same as `downloadFile`):
|
|
1200
|
+
* - **URL**: Creates temporary page, navigates to URL, captures download, closes page
|
|
1201
|
+
* - **Locator**: Uses current page to click element and capture download
|
|
1202
|
+
* - **Callback**: Executes custom function and captures any resulting downloads
|
|
1203
|
+
*/
|
|
1204
|
+
export declare function saveFileToS3(input: {
|
|
1205
|
+
page: Page;
|
|
1206
|
+
trigger: Trigger;
|
|
1207
|
+
timeoutInMs?: number;
|
|
1208
|
+
configs?: S3Configs;
|
|
1209
|
+
fileNameOverride?: string;
|
|
1210
|
+
contentType?: string;
|
|
1211
|
+
}): Promise<Attachment>;
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Union type representing the supported attachment file types.
|
|
1215
|
+
*
|
|
1216
|
+
* @type AttachmentType
|
|
1217
|
+
* Currently supported types:
|
|
1218
|
+
* - `"document"`: Document files (PDFs, Word docs, etc.)
|
|
1219
|
+
*/
|
|
1220
|
+
export type AttachmentType = "document";
|