diff --git a/.stats.yml b/.stats.yml index 6e991c2..ff3783d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 6 +configured_endpoints: 9 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-73f12c3021fc56466b869b17a82fec982131d51e383151c897908d874bc188da.yml diff --git a/api.md b/api.md index ab2d301..328188a 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,17 @@ +# Steel + +Types: + +- PdfResponse +- ScrapeResponse +- ScreenshotResponse + +Methods: + +- client.pdf({ ...params }) -> PdfResponse +- client.scrape({ ...params }) -> ScrapeResponse +- client.screenshot({ ...params }) -> ScreenshotResponse + # Sessions Types: diff --git a/src/index.ts b/src/index.ts index 9e7645c..b02f68a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,15 @@ import * as Pagination from './pagination'; import { type SessionsCursorParams, SessionsCursorResponse } from './pagination'; import * as Uploads from './uploads'; import * as API from './resources/index'; +import * as TopLevelAPI from './resources/top-level'; +import { + PdfParams, + PdfResponse, + ScrapeParams, + ScrapeResponse, + ScreenshotParams, + ScreenshotResponse, +} from './resources/top-level'; import { Session, SessionContext, @@ -137,6 +146,33 @@ export class Steel extends Core.APIClient { sessions: API.Sessions = new API.Sessions(this); + /** + * Generates a PDF from a specified webpage. + */ + pdf(body: TopLevelAPI.PdfParams, options?: Core.RequestOptions): Core.APIPromise { + return this.post('/v1/pdf', { body, ...options }); + } + + /** + * Extracts content from a specified URL. + */ + scrape( + body: TopLevelAPI.ScrapeParams, + options?: Core.RequestOptions, + ): Core.APIPromise { + return this.post('/v1/scrape', { body, ...options }); + } + + /** + * Captures a screenshot of a specified webpage. + */ + screenshot( + body: TopLevelAPI.ScreenshotParams, + options?: Core.RequestOptions, + ): Core.APIPromise { + return this.post('/v1/screenshot', { body, ...options }); + } + protected override defaultQuery(): Core.DefaultQuery | undefined { return this._options.defaultQuery; } @@ -184,6 +220,15 @@ export declare namespace Steel { type SessionsCursorResponse as SessionsCursorResponse, }; + export { + type PdfResponse as PdfResponse, + type ScrapeResponse as ScrapeResponse, + type ScreenshotResponse as ScreenshotResponse, + type PdfParams as PdfParams, + type ScrapeParams as ScrapeParams, + type ScreenshotParams as ScreenshotParams, + }; + export { Sessions as Sessions, type Session as Session, diff --git a/src/resources/index.ts b/src/resources/index.ts index 5c4c83f..0586b0d 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -14,3 +14,11 @@ export { type SessionReleaseParams, type SessionReleaseAllParams, } from './sessions'; +export { + type PdfResponse, + type ScrapeResponse, + type ScreenshotResponse, + type PdfParams, + type ScrapeParams, + type ScreenshotParams, +} from './top-level'; diff --git a/src/resources/top-level.ts b/src/resources/top-level.ts new file mode 100644 index 0000000..469536c --- /dev/null +++ b/src/resources/top-level.ts @@ -0,0 +1,214 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export interface PdfResponse { + /** + * URL where the PDF is hosted + */ + url: string; +} + +/** + * Response from a successful scrape request + */ +export interface ScrapeResponse { + content: ScrapeResponse.Content; + + links: Array; + + metadata: ScrapeResponse.Metadata; + + pdf?: ScrapeResponse.Pdf; + + screenshot?: ScrapeResponse.Screenshot; +} + +export namespace ScrapeResponse { + export interface Content { + /** + * Cleaned HTML content of the webpage + */ + cleaned_html?: string; + + /** + * Raw HTML content of the webpage + */ + html?: string; + + /** + * Webpage content converted to Markdown + */ + markdown?: string; + + /** + * Webpage content in Readability format + */ + readability?: Record; + } + + export interface Link { + /** + * Text content of the link + */ + text: string; + + /** + * URL of the link + */ + url: string; + } + + export interface Metadata { + /** + * HTTP status code of the response + */ + statusCode: number; + + /** + * Description of the webpage + */ + description?: string; + + /** + * Detected language of the webpage + */ + language?: string; + + /** + * Open Graph description + */ + ogDescription?: string; + + /** + * Open Graph image URL + */ + ogImage?: string; + + /** + * Open Graph title + */ + ogTitle?: string; + + /** + * Publication timestamp of the content (if available) + */ + published_timestamp?: string; + + /** + * Timestamp when the scrape was performed + */ + timestamp?: string; + + /** + * Title of the webpage + */ + title?: string; + + /** + * Source URL of the scraped page + */ + urlSource?: string; + } + + export interface Pdf { + /** + * URL of the generated PDF + */ + url: string; + } + + export interface Screenshot { + /** + * URL of the screenshot image + */ + url: string; + } +} + +export interface ScreenshotResponse { + /** + * URL where the screenshot is hosted + */ + url: string; +} + +export interface PdfParams { + /** + * URL of the webpage to convert to PDF + */ + url: string; + + /** + * Delay before generating the PDF (in milliseconds) + */ + delay?: number; + + /** + * Use a Steel-provided residential proxy for generating the PDF + */ + useProxy?: boolean; +} + +export interface ScrapeParams { + /** + * URL of the webpage to scrape + */ + url: string; + + /** + * Delay before scraping (in milliseconds) + */ + delay?: number; + + /** + * Desired format(s) for the scraped content. Default is `html`. + */ + format?: Array<'html' | 'readability' | 'cleaned_html' | 'markdown'>; + + /** + * Include a PDF in the response + */ + pdf?: boolean; + + /** + * Include a screenshot in the response + */ + screenshot?: boolean; + + /** + * Use a Steel-provided residential proxy for the scrape + */ + useProxy?: boolean; +} + +export interface ScreenshotParams { + /** + * URL of the webpage to capture + */ + url: string; + + /** + * Delay before capturing the screenshot (in milliseconds) + */ + delay?: number; + + /** + * Capture the full page screenshot. Default is `false`. + */ + fullPage?: boolean; + + /** + * Use a Steel-provided residential proxy for capturing the screenshot + */ + useProxy?: boolean; +} + +export declare namespace TopLevel { + export { + type PdfResponse as PdfResponse, + type ScrapeResponse as ScrapeResponse, + type ScreenshotResponse as ScreenshotResponse, + type PdfParams as PdfParams, + type ScrapeParams as ScrapeParams, + type ScreenshotParams as ScreenshotParams, + }; +} diff --git a/tests/api-resources/top-level.test.ts b/tests/api-resources/top-level.test.ts new file mode 100644 index 0000000..fa65ff7 --- /dev/null +++ b/tests/api-resources/top-level.test.ts @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Steel from 'steel-sdk'; +import { Response } from 'node-fetch'; + +const client = new Steel({ + steelAPIKey: 'My Steel API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('top level methods', () => { + test('pdf: only required params', async () => { + const responsePromise = client.pdf({ url: 'https://example.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('pdf: required and optional params', async () => { + const response = await client.pdf({ url: 'https://example.com', delay: 0, useProxy: true }); + }); + + test('scrape: only required params', async () => { + const responsePromise = client.scrape({ url: 'https://example.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('scrape: required and optional params', async () => { + const response = await client.scrape({ + url: 'https://example.com', + delay: 0, + format: ['html'], + pdf: true, + screenshot: true, + useProxy: true, + }); + }); + + test('screenshot: only required params', async () => { + const responsePromise = client.screenshot({ url: 'https://example.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('screenshot: required and optional params', async () => { + const response = await client.screenshot({ + url: 'https://example.com', + delay: 0, + fullPage: true, + useProxy: true, + }); + }); +});